vtls: pinned key check

Cleanup the vtls pinned key matching somewhat. Add a DEBUGF
for pinned key hashes that do not match, so we can see in
traces what was going on.

Ref #19489
Closes #19529
This commit is contained in:
Stefan Eissing 2025-11-14 15:25:04 +01:00 committed by Daniel Stenberg
parent 0abb72210e
commit 9f979ea683
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2

View file

@ -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;