@@ -2540,3 +2540,84 @@ int test_various_pathlen_chains(void)
25402540#endif
25412541 return EXPECT_RESULT ();
25422542}
2543+
2544+ /* Verify that certificates signed with MD5 (md5WithRSAEncryption) are
2545+ * rejected during chain verification. MD5 must not be acceptable as a
2546+ * certificate signature hash, even when MD5 is compiled in (e.g. for TLS
2547+ * 1.0 PRF or HMAC uses). Trust anchors are exempt from this check because
2548+ * ParseCertRelative skips ConfirmSignature for CA_TYPE. */
2549+ int test_wolfSSL_CertManagerRejectMD5Cert (void )
2550+ {
2551+ EXPECT_DECLS ;
2552+ #if !defined(NO_CERTS ) && !defined(NO_RSA ) && !defined(NO_MD5 ) && \
2553+ !defined(WOLFSSL_ALLOW_MD5_CERT_SIGS ) && defined(WOLFSSL_CERT_GEN ) && \
2554+ !defined(NO_WOLFSSL_CM_VERIFY ) && !defined(NO_ASN_CRYPT ) && \
2555+ !defined(USE_CERT_BUFFERS_1024 )
2556+ WOLFSSL_CERT_MANAGER * cm = NULL ;
2557+ RsaKey caKey ;
2558+ WC_RNG rng ;
2559+ Cert leaf ;
2560+ byte * der = NULL ;
2561+ int derSz = 0 ;
2562+ word32 idx = 0 ;
2563+ int caKeyInit = 0 ;
2564+ int rngInit = 0 ;
2565+
2566+ XMEMSET (& caKey , 0 , sizeof (caKey ));
2567+ XMEMSET (& rng , 0 , sizeof (rng ));
2568+
2569+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
2570+ if (EXPECT_SUCCESS ()) rngInit = 1 ;
2571+
2572+ ExpectIntEQ (wc_InitRsaKey_ex (& caKey , HEAP_HINT , testDevId ), 0 );
2573+ if (EXPECT_SUCCESS ()) caKeyInit = 1 ;
2574+ ExpectIntEQ (wc_RsaPrivateKeyDecode (ca_key_der_2048 , & idx , & caKey ,
2575+ sizeof_ca_key_der_2048 ), 0 );
2576+
2577+ ExpectNotNull (der = (byte * )XMALLOC (FOURK_BUF , HEAP_HINT ,
2578+ DYNAMIC_TYPE_TMP_BUFFER ));
2579+
2580+ /* Build a leaf certificate whose issuer is the built-in 2048-bit
2581+ * wolfSSL test CA and sign it with MD5+RSA using the matching CA
2582+ * private key. */
2583+ ExpectIntEQ (wc_InitCert (& leaf ), 0 );
2584+ leaf .sigType = CTC_MD5wRSA ;
2585+ leaf .isCA = 0 ;
2586+ XSTRNCPY (leaf .subject .country , "US" , CTC_NAME_SIZE );
2587+ XSTRNCPY (leaf .subject .state , "MT" , CTC_NAME_SIZE );
2588+ XSTRNCPY (leaf .subject .locality , "Bozeman" , CTC_NAME_SIZE );
2589+ XSTRNCPY (leaf .subject .org , "wolfSSL" , CTC_NAME_SIZE );
2590+ XSTRNCPY (leaf .subject .unit , "Test" , CTC_NAME_SIZE );
2591+ XSTRNCPY (leaf .subject .commonName , "md5-leaf" , CTC_NAME_SIZE );
2592+ XSTRNCPY (leaf .subject .email , "info@wolfssl.com" , CTC_NAME_SIZE );
2593+
2594+ ExpectIntEQ (wc_SetIssuerBuffer (& leaf , ca_cert_der_2048 ,
2595+ sizeof_ca_cert_der_2048 ), 0 );
2596+
2597+ /* wc_MakeCert needs an RSA public key for the subject; reuse caKey
2598+ * for simplicity (we only care about signature-side verification). */
2599+ ExpectIntGT ((derSz = wc_MakeCert (& leaf , der , FOURK_BUF , & caKey , NULL ,
2600+ & rng )), 0 );
2601+ ExpectIntGT ((derSz = wc_SignCert (leaf .bodySz , leaf .sigType , der ,
2602+ FOURK_BUF , & caKey , NULL , & rng )), 0 );
2603+
2604+ /* Load the SHA-256 signed CA cert as a trust anchor and attempt
2605+ * to verify the MD5-signed leaf: it must be rejected because
2606+ * HashForSignature() now returns HASH_TYPE_E for MD5 in verify mode,
2607+ * which surfaces as ASN_SIG_CONFIRM_E from ConfirmSignature(). */
2608+ ExpectNotNull (cm = wolfSSL_CertManagerNew ());
2609+ ExpectIntEQ (wolfSSL_CertManagerLoadCABuffer (cm , ca_cert_der_2048 ,
2610+ sizeof_ca_cert_der_2048 , WOLFSSL_FILETYPE_ASN1 ),
2611+ WOLFSSL_SUCCESS );
2612+
2613+ ExpectIntEQ (wolfSSL_CertManagerVerifyBuffer (cm , der , derSz ,
2614+ WOLFSSL_FILETYPE_ASN1 ),
2615+ WC_NO_ERR_TRACE (HASH_TYPE_E ));
2616+
2617+ wolfSSL_CertManagerFree (cm );
2618+ XFREE (der , HEAP_HINT , DYNAMIC_TYPE_TMP_BUFFER );
2619+ if (caKeyInit ) wc_FreeRsaKey (& caKey );
2620+ if (rngInit ) wc_FreeRng (& rng );
2621+ #endif
2622+ return EXPECT_RESULT ();
2623+ }
0 commit comments