Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Store only the SHA1 and SHA256 of the public key internally
This will allow switching to other representation formats for output
or input of public key PIN. For example to the RFC7469 key PIN.

Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
  • Loading branch information
nmav authored and dwmw2 committed May 15, 2017
1 parent af03217 commit b3e5f00
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 42 deletions.
3 changes: 2 additions & 1 deletion dtls.c
Expand Up @@ -72,7 +72,8 @@ char *openconnect_bin2hex(const char *prefix, const uint8_t *data, unsigned len)
char *p = NULL;

buf = buf_alloc();
buf_append(buf, "%s", prefix);
if (prefix)
buf_append(buf, "%s", prefix);
buf_append_hex(buf, data, len);

if (!buf_error(buf)) {
Expand Down
20 changes: 7 additions & 13 deletions gnutls.c
Expand Up @@ -1927,7 +1927,6 @@ int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,

static int set_peer_cert_hash(struct openconnect_info *vpninfo)
{
unsigned char hash[SHA256_SIZE];
size_t shalen;
gnutls_pubkey_t pkey;
gnutls_datum_t d;
Expand Down Expand Up @@ -1969,27 +1968,23 @@ static int set_peer_cert_hash(struct openconnect_info *vpninfo)
}
#endif
gnutls_pubkey_deinit(pkey);
shalen = SHA256_SIZE;

err = gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, hash, &shalen);
shalen = sizeof(vpninfo->peer_cert_sha256_raw);
err = gnutls_fingerprint(GNUTLS_DIG_SHA256, &d, vpninfo->peer_cert_sha256_raw, &shalen);
if (err) {
gnutls_free(d.data);
return err;
}

vpninfo->peer_cert_sha256 = openconnect_bin2hex("sha256:", hash, shalen);

shalen = SHA1_SIZE;
err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, hash, &shalen);
shalen = sizeof(vpninfo->peer_cert_sha1_raw);
err = gnutls_fingerprint(GNUTLS_DIG_SHA1, &d, vpninfo->peer_cert_sha1_raw, &shalen);
if (err) {
gnutls_free(d.data);
return err;
}

gnutls_free(d.data);

vpninfo->peer_cert_sha1 = openconnect_bin2hex("sha1:", hash, shalen);

return 0;
}

Expand Down Expand Up @@ -2221,10 +2216,9 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
gnutls_x509_crt_deinit(vpninfo->peer_cert);
vpninfo->peer_cert = NULL;
}
free(vpninfo->peer_cert_sha1);
vpninfo->peer_cert_sha1 = NULL;
free(vpninfo->peer_cert_sha256);
vpninfo->peer_cert_sha256 = NULL;

free(vpninfo->peer_cert_hash);
vpninfo->peer_cert_hash = NULL;
gnutls_free(vpninfo->cstp_cipher);
vpninfo->cstp_cipher = NULL;

Expand Down
26 changes: 11 additions & 15 deletions library.c
Expand Up @@ -368,8 +368,6 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
free(cache);
}

free(vpninfo->peer_cert_sha1);
free(vpninfo->peer_cert_sha256);
free(vpninfo->localname);
free(vpninfo->useragent);
free(vpninfo->authgroup);
Expand Down Expand Up @@ -968,29 +966,25 @@ int openconnect_set_csd_environ(struct openconnect_info *vpninfo,
int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
const char *old_hash)
{
char sha1_text[41];
const char *fingerprint;
char *fingerprint = NULL;
unsigned min_match_len;
unsigned real_min_match_len = 4;
unsigned old_len, fingerprint_len;

if (strchr(old_hash, ':')) {
if (strncmp(old_hash, "sha1:", 5) == 0) {
fingerprint = vpninfo->peer_cert_sha1;
fingerprint = openconnect_bin2hex("sha1:", vpninfo->peer_cert_sha1_raw, sizeof(vpninfo->peer_cert_sha1_raw));
min_match_len = real_min_match_len + sizeof("sha1:")-1;
} else if (strncmp(old_hash, "sha256:", 7) == 0) {
fingerprint = vpninfo->peer_cert_sha256;
fingerprint = openconnect_bin2hex("sha256:", vpninfo->peer_cert_sha256_raw, sizeof(vpninfo->peer_cert_sha256_raw));
min_match_len = real_min_match_len + sizeof("sha256:")-1;
} else {
vpn_progress(vpninfo, PRG_ERR, _("Unknown certificate hash: %s.\n"), old_hash);
return -EIO;
}

if (!fingerprint)
return -EIO;
} else {
unsigned char *cert;
int len, i;
int len;
unsigned char sha1_bin[SHA1_SIZE];

len = openconnect_get_peer_cert_DER(vpninfo, &cert);
Expand All @@ -1000,13 +994,13 @@ int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
if (openconnect_sha1(sha1_bin, cert, len))
return -EIO;

for (i = 0; i < sizeof(sha1_bin); i++)
sprintf(&sha1_text[i*2], "%02x", sha1_bin[i]);

fingerprint = sha1_text;
fingerprint = openconnect_bin2hex(NULL, sha1_bin, sizeof(sha1_bin));
min_match_len = real_min_match_len;
}

if (!fingerprint)
return -EIO;

old_len = strlen(old_hash);
fingerprint_len = strlen(fingerprint);

Expand All @@ -1033,7 +1027,9 @@ const char *openconnect_get_cstp_cipher(struct openconnect_info *vpninfo)

const char *openconnect_get_peer_cert_hash(struct openconnect_info *vpninfo)
{
return vpninfo->peer_cert_sha256;
if (vpninfo->peer_cert_hash == NULL)
vpninfo->peer_cert_hash = openconnect_bin2hex("sha256:", vpninfo->peer_cert_sha256_raw, sizeof(vpninfo->peer_cert_sha256_raw));
return vpninfo->peer_cert_hash;
}

int openconnect_set_compression_mode(struct openconnect_info *vpninfo,
Expand Down
7 changes: 5 additions & 2 deletions openconnect-internal.h
Expand Up @@ -458,8 +458,11 @@ struct openconnect_info {
void *tok_cbdata;

void *peer_cert;
char *peer_cert_sha1;
char *peer_cert_sha256;
/* The SHA1 and SHA256 hashes of the peer's public key */
uint8_t peer_cert_sha1_raw[SHA1_SIZE];
uint8_t peer_cert_sha256_raw[SHA256_SIZE];
/* this value is cache for openconnect_get_peer_cert_hash */
char *peer_cert_hash;
void *cert_list_handle;
int cert_list_size;

Expand Down
15 changes: 4 additions & 11 deletions openssl.c
Expand Up @@ -1099,8 +1099,6 @@ int get_cert_md5_fingerprint(struct openconnect_info *vpninfo,

static int set_peer_cert_hash(struct openconnect_info *vpninfo)
{
unsigned char sha256_hash[SHA256_SIZE];
unsigned char sha1_hash[SHA1_SIZE];
EVP_PKEY *pkey;
BIO *bp = BIO_new(BIO_s_mem());
BUF_MEM *keyinfo;
Expand All @@ -1119,14 +1117,11 @@ static int set_peer_cert_hash(struct openconnect_info *vpninfo)

BIO_get_mem_ptr(bp, &keyinfo);

openconnect_sha256(sha256_hash, keyinfo->data, keyinfo->length);
openconnect_sha1(sha1_hash, keyinfo->data, keyinfo->length);
openconnect_sha256(vpninfo->peer_cert_sha256_raw, keyinfo->data, keyinfo->length);
openconnect_sha1(vpninfo->peer_cert_sha1_raw, keyinfo->data, keyinfo->length);

BIO_free(bp);

vpninfo->peer_cert_sha1 = openconnect_bin2hex("sha1:", sha1_hash, sizeof(sha1_hash));
vpninfo->peer_cert_sha256 = openconnect_bin2hex("sha256:", sha256_hash, sizeof(sha256_hash));

return 0;
}

Expand Down Expand Up @@ -1658,10 +1653,8 @@ int openconnect_open_https(struct openconnect_info *vpninfo)
X509_free(vpninfo->peer_cert);
vpninfo->peer_cert = NULL;
}
free (vpninfo->peer_cert_sha1);
vpninfo->peer_cert_sha1 = NULL;
free (vpninfo->peer_cert_sha256);
vpninfo->peer_cert_sha256 = NULL;
free(vpninfo->peer_cert_hash);
vpninfo->peer_cert_hash = NULL;
vpninfo->cstp_cipher = NULL;

ssl_sock = connect_https_socket(vpninfo);
Expand Down

0 comments on commit b3e5f00

Please sign in to comment.