wolfssl: patch CVE-2026-6731

Details:
https://nvd.nist.gov/vuln/detail/cve-2026-6731

Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Ankur Tyagi
2026-09-15 10:13:42 +05:30
committed by Anuj Mittal
parent 983b006bac
commit e99f95d5b5
3 changed files with 212 additions and 0 deletions
@@ -0,0 +1,39 @@
From df2df57a027066708b498f41ce0b591704b579cc Mon Sep 17 00:00:00 2001
From: Ruby Martin <ruby@wolfssl.com>
Date: Tue, 14 Apr 2026 12:39:34 -0600
Subject: [PATCH] Apply DNS constraints to subject CN when SAN is not
available.
(cherry picked from commit e7b7fddacb4cc794e5dfc7693586d87a539f5aad)
CVE: CVE-2026-6731
Upstream-Status: Backport [https://github.com/wolfSSL/wolfssl/commit/e7b7fddacb4cc794e5dfc7693586d87a539f5aad]
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
wolfcrypt/src/asn.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c
index f8db5c457..d12a78850 100644
--- a/wolfcrypt/src/asn.c
+++ b/wolfcrypt/src/asn.c
@@ -17665,9 +17665,16 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
XMEMSET(&subjectDnsName, 0, sizeof(DNS_entry));
switch (nameType) {
case ASN_DNS_TYPE:
- /* Should it also consider CN in subject? It could use
- * subjectDnsName too */
name = cert->altNames;
+
+ /* When no SAN is present, apply DNS name constraints to the
+ * Subject CN. */
+ if (cert->subjectCN != NULL && cert->altNames == NULL) {
+ subjectDnsName.next = NULL;
+ subjectDnsName.type = ASN_DNS_TYPE;
+ subjectDnsName.len = cert->subjectCNLen;
+ subjectDnsName.name = cert->subjectCN;
+ }
break;
case ASN_IP_TYPE:
/* IP addresses are stored in altNames with type ASN_IP_TYPE */
@@ -0,0 +1,171 @@
From 9d1ee979f67c8e31a04b73fadac61f4697bcb7c6 Mon Sep 17 00:00:00 2001
From: Ruby Martin <ruby@wolfssl.com>
Date: Tue, 14 Apr 2026 12:44:21 -0600
Subject: [PATCH] test DNS name constraints on CA are applied against Subject
CN name when SAN name is unavailable
test correct CN with no SAN available is accepted
(cherry picked from commit 797ba3f03b1a8dc05c7b91a86c2e6698d76bfc8a)
CVE: CVE-2026-6731
Upstream-Status: Backport [https://github.com/wolfSSL/wolfssl/commit/797ba3f03b1a8dc05c7b91a86c2e6698d76bfc8a]
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
---
tests/api/test_certman.c | 121 +++++++++++++++++++++++++++++++++++++++
tests/api/test_certman.h | 2 +
2 files changed, 123 insertions(+)
diff --git a/tests/api/test_certman.c b/tests/api/test_certman.c
index 7405f4bff..c76902af2 100644
--- a/tests/api/test_certman.c
+++ b/tests/api/test_certman.c
@@ -1584,6 +1584,127 @@ int test_wolfSSL_CertManagerNameConstraint5(void)
return EXPECT_RESULT();
}
+int test_wolfSSL_CertManagerNameConstraint_DNS_CN(void)
+{
+ EXPECT_DECLS;
+#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
+ !defined(NO_WOLFSSL_CM_VERIFY) && !defined(NO_RSA) && \
+ defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_GEN) && \
+ defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_ALT_NAMES) && \
+ !defined(NO_SHA256)
+ /* Test that DNS name constraints are enforced against the Subject CN
+ * when no SAN extension is present. The CA cert (cert-ext-ncdns.der)
+ * permits only DNS:wolfssl.com and DNS:example.com. A leaf cert with
+ * CN=evil.attacker.com and no SAN should be REJECTED. */
+ WOLFSSL_CERT_MANAGER* cm = NULL;
+ WOLFSSL_EVP_PKEY *priv = NULL;
+ WOLFSSL_X509_NAME* name = NULL;
+ const char* ca_cert = "./certs/test/cert-ext-ncdns.der";
+ const char* server_cert = "./certs/test/server-goodcn.pem";
+
+ byte *der = NULL;
+ int derSz;
+ byte *pt;
+ WOLFSSL_X509 *x509 = NULL;
+ WOLFSSL_X509 *ca = NULL;
+
+ pt = (byte*)server_key_der_2048;
+ ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL,
+ (const unsigned char**)&pt, sizeof_server_key_der_2048));
+
+ ExpectNotNull(cm = wolfSSL_CertManagerNew());
+ ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(ca_cert,
+ WOLFSSL_FILETYPE_ASN1));
+ ExpectNotNull((der = (byte*)wolfSSL_X509_get_der(ca, &derSz)));
+ ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, der, derSz,
+ WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
+
+ /* Sanity check: cert with SAN=evil.attacker.com is correctly rejected */
+ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(server_cert,
+ WOLFSSL_FILETYPE_PEM));
+ ExpectNotNull(name = wolfSSL_X509_get_subject_name(ca));
+ ExpectIntEQ(wolfSSL_X509_set_issuer_name(x509, name), WOLFSSL_SUCCESS);
+ name = NULL;
+
+ ExpectNotNull(name = X509_NAME_new());
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "countryName", MBSTRING_UTF8,
+ (byte*)"US", 2, -1, 0), SSL_SUCCESS);
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8,
+ (byte*)"evil.attacker.com", 17, -1, 0),
+ SSL_SUCCESS);
+ ExpectIntEQ(wolfSSL_X509_set_subject_name(x509, name), WOLFSSL_SUCCESS);
+ X509_NAME_free(name);
+ name = NULL;
+
+ ExpectIntEQ(wolfSSL_X509_add_altname(x509, "evil.attacker.com",
+ ASN_DNS_TYPE), WOLFSSL_SUCCESS);
+ ExpectIntGT(wolfSSL_X509_sign(x509, priv, EVP_sha256()), 0);
+ ExpectNotNull((der = (byte*)wolfSSL_X509_get_der(x509, &derSz)));
+ ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
+ WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
+ wolfSSL_X509_free(x509);
+ x509 = NULL;
+
+ /* NOW the actual vulnerability test: cert with CN=evil.attacker.com
+ * but NO SAN. The DNS name constraint should still reject this, since
+ * wolfSSL's hostname verification falls back to CN when no SAN exists. */
+ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(server_cert,
+ WOLFSSL_FILETYPE_PEM));
+ ExpectNotNull(name = wolfSSL_X509_get_subject_name(ca));
+ ExpectIntEQ(wolfSSL_X509_set_issuer_name(x509, name), WOLFSSL_SUCCESS);
+ name = NULL;
+
+ ExpectNotNull(name = X509_NAME_new());
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "countryName", MBSTRING_UTF8,
+ (byte*)"US", 2, -1, 0), SSL_SUCCESS);
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8,
+ (byte*)"evil.attacker.com", 17, -1, 0),
+ SSL_SUCCESS);
+ ExpectIntEQ(wolfSSL_X509_set_subject_name(x509, name), WOLFSSL_SUCCESS);
+ X509_NAME_free(name);
+ name = NULL;
+
+ /* Do NOT add any SAN this is the bypass vector */
+ ExpectIntGT(wolfSSL_X509_sign(x509, priv, EVP_sha256()), 0);
+ ExpectNotNull((der = (byte*)wolfSSL_X509_get_der(x509, &derSz)));
+ /* Should be ASN_NAME_INVALID_E because CN violates the constraint */
+ ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
+ WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
+ wolfSSL_X509_free(x509);
+ x509 = NULL;
+
+ /* Positive test: CN matches a permitted name (wolfssl.com) and no SAN is
+ * present. The CN fallback should accept this cert. */
+ ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(server_cert,
+ WOLFSSL_FILETYPE_PEM));
+ ExpectNotNull(name = wolfSSL_X509_get_subject_name(ca));
+ ExpectIntEQ(wolfSSL_X509_set_issuer_name(x509, name), WOLFSSL_SUCCESS);
+ name = NULL;
+
+ ExpectNotNull(name = X509_NAME_new());
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "countryName", MBSTRING_UTF8,
+ (byte*)"US", 2, -1, 0), SSL_SUCCESS);
+ ExpectIntEQ(X509_NAME_add_entry_by_txt(name, "commonName", MBSTRING_UTF8,
+ (byte*)"wolfssl.com", 11, -1, 0),
+ SSL_SUCCESS);
+ ExpectIntEQ(wolfSSL_X509_set_subject_name(x509, name), WOLFSSL_SUCCESS);
+ X509_NAME_free(name);
+ name = NULL;
+
+ /* No SAN added; CN=wolfssl.com matches the permitted DNS constraint. */
+ ExpectIntGT(wolfSSL_X509_sign(x509, priv, EVP_sha256()), 0);
+ ExpectNotNull((der = (byte*)wolfSSL_X509_get_der(x509, &derSz)));
+ ExpectIntEQ(wolfSSL_CertManagerVerifyBuffer(cm, der, derSz,
+ WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
+
+ wolfSSL_CertManagerFree(cm);
+ wolfSSL_X509_free(x509);
+ wolfSSL_X509_free(ca);
+ wolfSSL_EVP_PKEY_free(priv);
+#endif
+ return EXPECT_RESULT();
+}
+
int test_wolfSSL_CertManagerCRL(void)
{
EXPECT_DECLS;
diff --git a/tests/api/test_certman.h b/tests/api/test_certman.h
index 3b6afd0fc..60047cfa3 100644
--- a/tests/api/test_certman.h
+++ b/tests/api/test_certman.h
@@ -35,6 +35,7 @@ int test_wolfSSL_CertManagerNameConstraint2(void);
int test_wolfSSL_CertManagerNameConstraint3(void);
int test_wolfSSL_CertManagerNameConstraint4(void);
int test_wolfSSL_CertManagerNameConstraint5(void);
+int test_wolfSSL_CertManagerNameConstraint_DNS_CN(void);
int test_wolfSSL_CertManagerCRL(void);
int test_wolfSSL_CRL_reason_extensions_cleanup(void);
int test_wolfSSL_CRL_static_revoked_list(void);
@@ -57,6 +58,7 @@ int test_wolfSSL_CertManagerRejectMD5Cert(void);
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint3), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint4), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint5), \
+ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint_DNS_CN), \
TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCRL), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_reason_extensions_cleanup), \
TEST_DECL_GROUP("certman", test_wolfSSL_CRL_static_revoked_list), \
@@ -34,6 +34,8 @@ SRC_URI = " \
file://CVE-2026-6412-2.patch \
file://CVE-2026-6450-1.patch \
file://CVE-2026-6450-2.patch \
file://CVE-2026-6731-1.patch \
file://CVE-2026-6731-2.patch \
"
SRCREV = "1d363f3adceba9d1478230ede476a37b0dcdef24"