Merge pull request #10222 from embhorn/zd21597

Report cert verify failure with MD5
This commit is contained in:
Sean Parkinson
2026-04-16 08:45:15 +10:00
committed by GitHub
4 changed files with 98 additions and 1 deletions
+1
View File
@@ -682,6 +682,7 @@ WOLFSSL_ALLOW_CRIT_AIA
WOLFSSL_ALLOW_CRIT_AKID
WOLFSSL_ALLOW_CRIT_SKID
WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST
WOLFSSL_ALLOW_MD5_CERT_SIGS
WOLFSSL_ALLOW_NO_CN_IN_SAN
WOLFSSL_ALLOW_NO_SUITES
WOLFSSL_ALLOW_SERVER_SC_EXT
+87
View File
@@ -2540,3 +2540,90 @@ int test_various_pathlen_chains(void)
#endif
return EXPECT_RESULT();
}
/* Verify that certificates signed with MD5 (md5WithRSAEncryption) are
* rejected during chain verification. MD5 must not be acceptable as a
* certificate signature hash, even when MD5 is compiled in (e.g. for TLS
* 1.0 PRF or HMAC uses). Trust anchors are exempt from this check because
* ParseCertRelative skips ConfirmSignature for CA_TYPE. */
int test_wolfSSL_CertManagerRejectMD5Cert(void)
{
EXPECT_DECLS;
#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_MD5) && \
!defined(WOLFSSL_ALLOW_MD5_CERT_SIGS) && defined(WOLFSSL_CERT_GEN) && \
!defined(NO_WOLFSSL_CM_VERIFY) && !defined(NO_ASN_CRYPT) && \
!defined(USE_CERT_BUFFERS_1024)
WOLFSSL_CERT_MANAGER* cm = NULL;
RsaKey caKey;
WC_RNG rng;
Cert leaf;
byte* der = NULL;
int derSz = 0;
word32 idx = 0;
int caKeyInit = 0;
int rngInit = 0;
XMEMSET(&caKey, 0, sizeof(caKey));
XMEMSET(&rng, 0, sizeof(rng));
ExpectIntEQ(wc_InitRng(&rng), 0);
if (EXPECT_SUCCESS()) rngInit = 1;
ExpectIntEQ(wc_InitRsaKey_ex(&caKey, HEAP_HINT, testDevId), 0);
if (EXPECT_SUCCESS()) caKeyInit = 1;
ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey,
sizeof_ca_key_der_2048), 0);
ExpectNotNull(der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT,
DYNAMIC_TYPE_TMP_BUFFER));
if (der == NULL) {
goto cleanup;
}
/* Build a leaf certificate whose issuer is the built-in 2048-bit
* wolfSSL test CA and sign it with MD5+RSA using the matching CA
* private key. */
ExpectIntEQ(wc_InitCert(&leaf), 0);
leaf.sigType = CTC_MD5wRSA;
leaf.isCA = 0;
XSTRNCPY(leaf.subject.country, "US", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.state, "MT", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.locality, "Bozeman", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.org, "wolfSSL", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.unit, "Test", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.commonName, "md5-leaf", CTC_NAME_SIZE);
XSTRNCPY(leaf.subject.email, "info@wolfssl.com", CTC_NAME_SIZE);
ExpectIntEQ(wc_SetIssuerBuffer(&leaf, ca_cert_der_2048,
sizeof_ca_cert_der_2048), 0);
/* wc_MakeCert needs an RSA public key for the subject; reuse caKey
* for simplicity (we only care about signature-side verification). */
ExpectIntGT((derSz = wc_MakeCert(&leaf, der, FOURK_BUF, &caKey, NULL,
&rng)), 0);
ExpectIntGT((derSz = wc_SignCert(leaf.bodySz, leaf.sigType, der,
FOURK_BUF, &caKey, NULL, &rng)), 0);
/* Load the SHA-256 signed CA cert as a trust anchor and attempt
* to verify the MD5-signed leaf: it must be rejected because
* HashForSignature() now returns HASH_TYPE_E for MD5 in verify mode,
* and wolfSSL_CertManagerVerifyBuffer() returns that error. */
ExpectNotNull(cm = wolfSSL_CertManagerNew());
if (cm != NULL) {
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, ca_cert_der_2048,
sizeof_ca_cert_der_2048, WOLFSSL_FILETYPE_ASN1),
WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
WOLFSSL_FILETYPE_ASN1),
WC_NO_ERR_TRACE(HASH_TYPE_E));
}
cleanup:
wolfSSL_CertManagerFree(cm);
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
if (caKeyInit) wc_FreeRsaKey(&caKey);
if (rngInit) wc_FreeRng(&rng);
#endif
return EXPECT_RESULT();
}
+3 -1
View File
@@ -41,6 +41,7 @@ int test_wolfSSL_CRL_static_revoked_list(void);
int test_wolfSSL_CRL_duplicate_extensions(void);
int test_wolfSSL_CertManagerCheckOCSPResponse(void);
int test_various_pathlen_chains(void);
int test_wolfSSL_CertManagerRejectMD5Cert(void);
#define TEST_CERTMAN_DECLS \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerAPI), \
@@ -59,7 +60,8 @@ int test_various_pathlen_chains(void);
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_static_revoked_list), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_duplicate_extensions), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCheckOCSPResponse), \
TEST_DECL_GROUP("certman", test_various_pathlen_chains)
TEST_DECL_GROUP("certman", test_various_pathlen_chains), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerRejectMD5Cert)
#endif /* WOLFCRYPT_TEST_CERTMAN_H */
+7
View File
@@ -15932,6 +15932,13 @@ static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID,
#endif
#ifndef NO_MD5
case CTC_MD5wRSA:
#ifndef WOLFSSL_ALLOW_MD5_CERT_SIGS
if (verify) {
ret = HASH_TYPE_E;
WOLFSSL_MSG("MD5 not supported for certificate verification");
break;
}
#endif
if ((ret = wc_Md5Hash_ex(buf, bufSz, digest, heap, devId)) == 0) {
*typeH = MD5h;
*digestSz = WC_MD5_DIGEST_SIZE;