Improved fingerprint hash comparison

* Allow new hash format 11bbccdd along already supported 11:22:aa:BB
This commit is contained in:
Armin Novak 2021-08-26 08:58:39 +02:00 committed by akallabeth
parent 06c883a709
commit 13f54fc0dd
3 changed files with 58 additions and 20 deletions

View File

@ -56,6 +56,8 @@ extern "C"
FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length); FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length);
FREERDP_API BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length); FREERDP_API BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length);
FREERDP_API char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash); FREERDP_API char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash);
FREERDP_API char* crypto_cert_fingerprint_by_hash_ex(X509* xcert, const char* hash,
BOOL separator);
FREERDP_API char* crypto_cert_fingerprint(X509* xcert); FREERDP_API char* crypto_cert_fingerprint(X509* xcert);
FREERDP_API BYTE* crypto_cert_pem(X509* xcert, STACK_OF(X509) * chain, size_t* length); FREERDP_API BYTE* crypto_cert_pem(X509* xcert, STACK_OF(X509) * chain, size_t* length);
FREERDP_API X509* crypto_cert_from_pem(const char* data, size_t length, BOOL fromFile); FREERDP_API X509* crypto_cert_from_pem(const char* data, size_t length, BOOL fromFile);

View File

@ -275,11 +275,16 @@ BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length)
} }
char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash) char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash)
{
return crypto_cert_fingerprint_by_hash_ex(xcert, hash, 0);
}
char* crypto_cert_fingerprint_by_hash_ex(X509* xcert, const char* hash, BOOL separator)
{ {
UINT32 fp_len, i; UINT32 fp_len, i;
size_t pos, size;
BYTE* fp; BYTE* fp;
char* p; char* fp_buffer = NULL;
char* fp_buffer;
if (!xcert) if (!xcert)
{ {
WLog_ERR(TAG, "Invalid certificate %p", xcert); WLog_ERR(TAG, "Invalid certificate %p", xcert);
@ -294,23 +299,35 @@ char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash)
if (!fp) if (!fp)
return NULL; return NULL;
fp_buffer = calloc(fp_len * 3 + 1, sizeof(char)); size = fp_len * 3 + 1;
fp_buffer = calloc(size, sizeof(char));
if (!fp_buffer) if (!fp_buffer)
goto fail; goto fail;
p = fp_buffer; pos = 0;
for (i = 0; i < (fp_len - 1); i++) for (i = 0; i < (fp_len - 1); i++)
{ {
sprintf_s(p, (fp_len - i) * 3, "%02" PRIx8 ":", fp[i]); int rc;
p = &fp_buffer[(i + 1) * 3]; char* p = &fp_buffer[pos];
if (separator)
rc = sprintf_s(p, size - pos, "%02" PRIx8 ":", fp[i]);
else
rc = sprintf_s(p, size - pos, "%02" PRIx8, fp[i]);
if (rc <= 0)
goto fail;
pos += (size_t)rc;
} }
sprintf_s(p, (fp_len - i) * 3, "%02" PRIx8 "", fp[i]); sprintf_s(&fp_buffer[pos], size - pos, "%02" PRIx8 "", fp[i]);
fail:
free(fp); free(fp);
return fp_buffer; return fp_buffer;
fail:
free(fp);
free(fp_buffer);
return NULL;
} }
static char* crypto_print_name(X509_NAME* name) static char* crypto_print_name(X509_NAME* name)

View File

@ -1176,6 +1176,33 @@ static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
return FALSE; return FALSE;
} }
static BOOL compare_fingerprint(const char* fp, const char* hash, CryptoCert cert, BOOL separator)
{
BOOL equal;
char* strhash;
WINPR_ASSERT(fp);
WINPR_ASSERT(hash);
WINPR_ASSERT(cert);
strhash = crypto_cert_fingerprint_by_hash_ex(cert->px509, hash, separator);
if (!strhash)
return FALSE;
equal = (_stricmp(strhash, fp) == 0);
free(strhash);
return equal;
}
static BOOL compare_fingerprint_all(const char* fp, const char* hash, CryptoCert cert)
{
if (compare_fingerprint(fp, hash, cert, FALSE))
return TRUE;
if (compare_fingerprint(fp, hash, cert, TRUE))
return TRUE;
return FALSE;
}
static BOOL is_accepted_fingerprint(CryptoCert cert, const char* CertificateAcceptedFingerprints) static BOOL is_accepted_fingerprint(CryptoCert cert, const char* CertificateAcceptedFingerprints)
{ {
BOOL rc = FALSE; BOOL rc = FALSE;
@ -1187,30 +1214,22 @@ static BOOL is_accepted_fingerprint(CryptoCert cert, const char* CertificateAcce
while (cur) while (cur)
{ {
char* subcontext = NULL; char* subcontext = NULL;
BOOL equal;
char* strhash;
const char* h = strtok_s(cur, ":", &subcontext); const char* h = strtok_s(cur, ":", &subcontext);
const char* fp; const char* fp;
if (!h) if (!h)
continue; goto next;
fp = h + strlen(h) + 1; fp = h + strlen(h) + 1;
if (!fp) if (!fp)
continue; goto next;
strhash = crypto_cert_fingerprint_by_hash(cert->px509, h); if (compare_fingerprint_all(fp, h, cert))
if (!strhash)
continue;
equal = (_stricmp(strhash, fp) == 0);
free(strhash);
if (equal)
{ {
rc = TRUE; rc = TRUE;
break; break;
} }
next:
cur = strtok_s(NULL, ",", &context); cur = strtok_s(NULL, ",", &context);
} }
free(copy); free(copy);