diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 3858cad983..918a4686fc 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -772,8 +772,9 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, /* only do this if pinnedpubkey starts with "sha256//", length 8 */ if(!strncmp(pinnedpubkey, "sha256//", 8)) { CURLcode encode; - size_t encodedlen = 0; - char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos; + char *cert_hash = NULL; + const char *pinned_hash, *end_pos; + size_t cert_hash_len = 0, pinned_hash_len; unsigned char *sha256sumdigest; if(!Curl_ssl->sha256sum) { @@ -790,50 +791,37 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, if(!encode) encode = curlx_base64_encode((char *)sha256sumdigest, - CURL_SHA256_DIGEST_LENGTH, &encoded, - &encodedlen); + CURL_SHA256_DIGEST_LENGTH, + &cert_hash, &cert_hash_len); Curl_safefree(sha256sumdigest); if(encode) return encode; - infof(data, " public key hash: sha256//%s", encoded); + infof(data, " public key hash: sha256//%s", cert_hash); - /* it starts with sha256//, copy so we can modify it */ - pinkeycopy = strdup(pinnedpubkey); - if(!pinkeycopy) { - Curl_safefree(encoded); - return CURLE_OUT_OF_MEMORY; - } - /* point begin_pos to the copy, and start extracting keys */ - begin_pos = pinkeycopy; - do { - end_pos = strstr(begin_pos, ";sha256//"); - /* - * if there is an end_pos, null-terminate, otherwise it will go to the - * end of the original string - */ - if(end_pos) - end_pos[0] = '\0'; + pinned_hash = pinnedpubkey; + while(pinned_hash && + !strncmp(pinned_hash, "sha256//", (sizeof("sha256//")-1))) { + pinned_hash = pinned_hash + (sizeof("sha256//")-1); + end_pos = strchr(pinned_hash, ';'); + pinned_hash_len = end_pos ? + (size_t)(end_pos - pinned_hash) : strlen(pinned_hash); - /* compare base64 sha256 digests, 8 is the length of "sha256//" */ - if(encodedlen == strlen(begin_pos + 8) && - !memcmp(encoded, begin_pos + 8, encodedlen)) { + /* compare base64 sha256 digests" */ + if(cert_hash_len == pinned_hash_len && + !memcmp(cert_hash, pinned_hash, cert_hash_len)) { + DEBUGF(infof(data, "public key hash matches pinned value")); result = CURLE_OK; break; } - /* - * change back the null-terminator we changed earlier, - * and look for next begin - */ - if(end_pos) { - end_pos[0] = ';'; - begin_pos = strstr(end_pos, "sha256//"); - } - } while(end_pos && begin_pos); - Curl_safefree(encoded); - Curl_safefree(pinkeycopy); + DEBUGF(infof(data, "public key hash does not match 'sha256//%.*s'", + (int)pinned_hash_len, pinned_hash)); + /* next one or we are at the end */ + pinned_hash = end_pos ? (end_pos + 1) : NULL; + } + Curl_safefree(cert_hash); } else { long filesize;