@@ -1584,6 +1584,101 @@ int test_wolfSSL_CertManagerNameConstraint5(void)
15841584 return EXPECT_RESULT ();
15851585}
15861586
1587+ int test_wolfSSL_CertManagerNameConstraint_DNS_CN (void )
1588+ {
1589+ EXPECT_DECLS ;
1590+ #if !defined(NO_FILESYSTEM ) && !defined(NO_CERTS ) && \
1591+ !defined(NO_WOLFSSL_CM_VERIFY ) && !defined(NO_RSA ) && \
1592+ defined(OPENSSL_EXTRA ) && defined(WOLFSSL_CERT_GEN ) && \
1593+ defined(WOLFSSL_CERT_EXT ) && defined(WOLFSSL_ALT_NAMES ) && \
1594+ !defined(NO_SHA256 )
1595+ /* Test that DNS name constraints are enforced against the Subject CN
1596+ * when no SAN extension is present. The CA cert (cert-ext-ncdns.der)
1597+ * permits only DNS:wolfssl.com and DNS:example.com. A leaf cert with
1598+ * CN=evil.attacker.com and no SAN should be REJECTED. */
1599+ WOLFSSL_CERT_MANAGER * cm = NULL ;
1600+ WOLFSSL_EVP_PKEY * priv = NULL ;
1601+ WOLFSSL_X509_NAME * name = NULL ;
1602+ const char * ca_cert = "./certs/test/cert-ext-ncdns.der" ;
1603+ const char * server_cert = "./certs/test/server-goodcn.pem" ;
1604+
1605+ byte * der = NULL ;
1606+ int derSz ;
1607+ byte * pt ;
1608+ WOLFSSL_X509 * x509 = NULL ;
1609+ WOLFSSL_X509 * ca = NULL ;
1610+
1611+ pt = (byte * )server_key_der_2048 ;
1612+ ExpectNotNull (priv = wolfSSL_d2i_PrivateKey (EVP_PKEY_RSA , NULL ,
1613+ (const unsigned char * * )& pt , sizeof_server_key_der_2048 ));
1614+
1615+ ExpectNotNull (cm = wolfSSL_CertManagerNew ());
1616+ ExpectNotNull (ca = wolfSSL_X509_load_certificate_file (ca_cert ,
1617+ WOLFSSL_FILETYPE_ASN1 ));
1618+ ExpectNotNull ((der = (byte * )wolfSSL_X509_get_der (ca , & derSz )));
1619+ ExpectIntEQ (wolfSSL_CertManagerLoadCABuffer (cm , der , derSz ,
1620+ WOLFSSL_FILETYPE_ASN1 ), WOLFSSL_SUCCESS );
1621+
1622+ /* Sanity check: cert with SAN=evil.attacker.com is correctly rejected */
1623+ ExpectNotNull (x509 = wolfSSL_X509_load_certificate_file (server_cert ,
1624+ WOLFSSL_FILETYPE_PEM ));
1625+ ExpectNotNull (name = wolfSSL_X509_get_subject_name (ca ));
1626+ ExpectIntEQ (wolfSSL_X509_set_issuer_name (x509 , name ), WOLFSSL_SUCCESS );
1627+ name = NULL ;
1628+
1629+ ExpectNotNull (name = X509_NAME_new ());
1630+ ExpectIntEQ (X509_NAME_add_entry_by_txt (name , "countryName" , MBSTRING_UTF8 ,
1631+ (byte * )"US" , 2 , -1 , 0 ), SSL_SUCCESS );
1632+ ExpectIntEQ (X509_NAME_add_entry_by_txt (name , "commonName" , MBSTRING_UTF8 ,
1633+ (byte * )"evil.attacker.com" , 17 , -1 , 0 ),
1634+ SSL_SUCCESS );
1635+ ExpectIntEQ (wolfSSL_X509_set_subject_name (x509 , name ), WOLFSSL_SUCCESS );
1636+ X509_NAME_free (name );
1637+ name = NULL ;
1638+
1639+ ExpectIntEQ (wolfSSL_X509_add_altname (x509 , "evil.attacker.com" ,
1640+ ASN_DNS_TYPE ), WOLFSSL_SUCCESS );
1641+ ExpectIntGT (wolfSSL_X509_sign (x509 , priv , EVP_sha256 ()), 0 );
1642+ ExpectNotNull ((der = (byte * )wolfSSL_X509_get_der (x509 , & derSz )));
1643+ ExpectIntEQ (wolfSSL_CertManagerVerifyBuffer (cm , der , derSz ,
1644+ WOLFSSL_FILETYPE_ASN1 ), WC_NO_ERR_TRACE (ASN_NAME_INVALID_E ));
1645+ wolfSSL_X509_free (x509 );
1646+ x509 = NULL ;
1647+
1648+ /* NOW the actual vulnerability test: cert with CN=evil.attacker.com
1649+ * but NO SAN. The DNS name constraint should still reject this, since
1650+ * wolfSSL's hostname verification falls back to CN when no SAN exists. */
1651+ ExpectNotNull (x509 = wolfSSL_X509_load_certificate_file (server_cert ,
1652+ WOLFSSL_FILETYPE_PEM ));
1653+ ExpectNotNull (name = wolfSSL_X509_get_subject_name (ca ));
1654+ ExpectIntEQ (wolfSSL_X509_set_issuer_name (x509 , name ), WOLFSSL_SUCCESS );
1655+ name = NULL ;
1656+
1657+ ExpectNotNull (name = X509_NAME_new ());
1658+ ExpectIntEQ (X509_NAME_add_entry_by_txt (name , "countryName" , MBSTRING_UTF8 ,
1659+ (byte * )"US" , 2 , -1 , 0 ), SSL_SUCCESS );
1660+ ExpectIntEQ (X509_NAME_add_entry_by_txt (name , "commonName" , MBSTRING_UTF8 ,
1661+ (byte * )"evil.attacker.com" , 17 , -1 , 0 ),
1662+ SSL_SUCCESS );
1663+ ExpectIntEQ (wolfSSL_X509_set_subject_name (x509 , name ), WOLFSSL_SUCCESS );
1664+ X509_NAME_free (name );
1665+ name = NULL ;
1666+
1667+ /* Do NOT add any SAN — this is the bypass vector */
1668+ ExpectIntGT (wolfSSL_X509_sign (x509 , priv , EVP_sha256 ()), 0 );
1669+ ExpectNotNull ((der = (byte * )wolfSSL_X509_get_der (x509 , & derSz )));
1670+ /* Should be ASN_NAME_INVALID_E because CN violates the constraint */
1671+ ExpectIntEQ (wolfSSL_CertManagerVerifyBuffer (cm , der , derSz ,
1672+ WOLFSSL_FILETYPE_ASN1 ), WC_NO_ERR_TRACE (ASN_NAME_INVALID_E ));
1673+
1674+ wolfSSL_CertManagerFree (cm );
1675+ wolfSSL_X509_free (x509 );
1676+ wolfSSL_X509_free (ca );
1677+ wolfSSL_EVP_PKEY_free (priv );
1678+ #endif
1679+ return EXPECT_RESULT ();
1680+ }
1681+
15871682int test_wolfSSL_CertManagerCRL (void )
15881683{
15891684 EXPECT_DECLS ;
0 commit comments