@@ -18588,9 +18588,10 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert)
1858818588 case ASN_DNS_TYPE:
1858918589 name = cert->altNames;
1859018590
18591- /* When no SAN is present, apply DNS name constraints to the
18592- * Subject CN. */
18593- if (cert->subjectCN != NULL && cert->altNames == NULL) {
18591+ /* Apply DNS constraints to leaf Subject CN when no SAN
18592+ * (legacy hostname-in-CN). Skipped for CAs. */
18593+ if (cert->subjectCN != NULL && cert->altNames == NULL &&
18594+ !cert->isCA) {
1859418595 subjectDnsName.next = NULL;
1859518596 subjectDnsName.type = ASN_DNS_TYPE;
1859618597 subjectDnsName.len = cert->subjectCNLen;
@@ -23149,6 +23150,71 @@ Signer* findSignerByName(Signer *list, byte *hash)
2314923150 return NULL;
2315023151}
2315123152
23153+ #ifndef IGNORE_NAME_CONSTRAINTS
23154+ /* Find a signer for cert in cm and extraCAList. Prefers AKID->SKID
23155+ * with name-hash validation. Fall back to name-only when AKID is
23156+ * absent. */
23157+ static Signer* FindSignerByAkidOrName(void* cm, Signer* extraCAList,
23158+ Signer* cert)
23159+ {
23160+ Signer* signer = NULL;
23161+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
23162+ #ifndef NO_SKID
23163+ Signer* exCaSigner;
23164+ #endif
23165+ #else
23166+ (void)extraCAList;
23167+ #endif
23168+
23169+ #ifndef NO_SKID
23170+ if (cert->authKeyIdSet) {
23171+ signer = GetCA(cm, cert->authKeyIdHash);
23172+ if (signer != NULL &&
23173+ XMEMCMP(signer->subjectNameHash, cert->issuerNameHash,
23174+ SIGNER_DIGEST_SIZE) != 0) {
23175+ signer = NULL;
23176+ }
23177+ /* AKID is authoritative; do not fall back to name when AKID
23178+ * is set (could substitute a same-DN sibling). */
23179+ }
23180+ else {
23181+ signer = GetCAByName(cm, cert->issuerNameHash);
23182+ }
23183+ #else
23184+ signer = GetCA(cm, cert->issuerNameHash);
23185+ #endif
23186+
23187+ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
23188+ if (signer == NULL && extraCAList != NULL) {
23189+ #ifndef NO_SKID
23190+ if (cert->authKeyIdSet) {
23191+ for (exCaSigner = extraCAList; exCaSigner != NULL;
23192+ exCaSigner = exCaSigner->next) {
23193+ if (XMEMCMP(exCaSigner->subjectKeyIdHash,
23194+ cert->authKeyIdHash,
23195+ SIGNER_DIGEST_SIZE) == 0 &&
23196+ XMEMCMP(exCaSigner->subjectNameHash,
23197+ cert->issuerNameHash,
23198+ SIGNER_DIGEST_SIZE) == 0) {
23199+ signer = exCaSigner;
23200+ break;
23201+ }
23202+ }
23203+ /* AKID is authoritative; do not fall back to name. */
23204+ }
23205+ else {
23206+ signer = findSignerByName(extraCAList, cert->issuerNameHash);
23207+ }
23208+ #else
23209+ signer = findSignerByName(extraCAList, cert->issuerNameHash);
23210+ #endif
23211+ }
23212+ #endif
23213+
23214+ return signer;
23215+ }
23216+ #endif /* !IGNORE_NAME_CONSTRAINTS */
23217+
2315223218int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm,
2315323219 Signer *extraCAList)
2315423220{
@@ -23163,6 +23229,12 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm,
2316323229 int idx = 0;
2316423230#endif
2316523231 byte* sce_tsip_encRsaKeyIdx;
23232+ #ifndef IGNORE_NAME_CONSTRAINTS
23233+ int ncDepth = 0;
23234+ Signer* ncSigner = NULL;
23235+ Signer* ncParent = NULL;
23236+ Signer* ncPrev = NULL;
23237+ #endif
2316623238 (void)extraCAList;
2316723239
2316823240 if (cert == NULL) {
@@ -23795,18 +23867,6 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm,
2379523867 }
2379623868 #endif /* WOLFSSL_DUAL_ALG_CERTS */
2379723869 }
23798- #ifndef IGNORE_NAME_CONSTRAINTS
23799- if (verify == VERIFY || verify == VERIFY_OCSP ||
23800- verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) {
23801- /* check that this cert's name is permitted by the signer's
23802- * name constraints */
23803- if (!ConfirmNameConstraints(cert->ca, cert)) {
23804- WOLFSSL_MSG("Confirm name constraint failed");
23805- WOLFSSL_ERROR_VERBOSE(ASN_NAME_INVALID_E);
23806- return ASN_NAME_INVALID_E;
23807- }
23808- }
23809- #endif /* IGNORE_NAME_CONSTRAINTS */
2381023870 } /* cert->ca */
2381123871#ifdef WOLFSSL_CERT_REQ
2381223872 else if (type == CERTREQ_TYPE) {
@@ -23888,6 +23948,38 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm,
2388823948 }
2388923949 } /* verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE */
2389023950
23951+ #ifndef IGNORE_NAME_CONSTRAINTS
23952+ /* Apply each ancestor CA's name constraints to this cert.
23953+ * Signer pointers between lookups are not lock-protected
23954+ * (see wolfssl_cm_get_certs_der). */
23955+ if ((verify == VERIFY || verify == VERIFY_OCSP ||
23956+ verify == VERIFY_NAME || verify == VERIFY_SKIP_DATE) &&
23957+ type != TRUSTED_PEER_TYPE && cert->ca != NULL) {
23958+ ncSigner = cert->ca;
23959+ while (ncSigner != NULL) {
23960+ if (!ConfirmNameConstraints(ncSigner, cert)) {
23961+ WOLFSSL_MSG("Confirm name constraint failed");
23962+ WOLFSSL_ERROR_VERBOSE(ASN_NAME_INVALID_E);
23963+ return ASN_NAME_INVALID_E;
23964+ }
23965+ /* Stop at trust anchor (self-issued). */
23966+ if (ncSigner->selfSigned)
23967+ break;
23968+ ncParent = FindSignerByAkidOrName(cm, extraCAList, ncSigner);
23969+ /* Stop on missing parent, self-loop, or A->B->A cycle. */
23970+ if (ncParent == NULL || ncParent == ncSigner ||
23971+ ncParent == ncPrev)
23972+ break;
23973+ if (++ncDepth >= WOLFSSL_MAX_CHAIN_DEPTH) {
23974+ WOLFSSL_MSG("NC ancestor walk exceeded WOLFSSL_MAX_CHAIN_DEPTH");
23975+ WOLFSSL_ERROR_VERBOSE(ASN_PATHLEN_SIZE_E);
23976+ return ASN_PATHLEN_SIZE_E;
23977+ }
23978+ ncPrev = ncSigner;
23979+ ncSigner = ncParent;
23980+ }
23981+ }
23982+ #endif /* IGNORE_NAME_CONSTRAINTS */
2389123983#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID)
2389223984exit_pcr:
2389323985#endif
@@ -23966,10 +24058,18 @@ int FillSigner(Signer* signer, DecodedCert* cert, int type, DerBuffer *der)
2396624058 #ifndef NO_SKID
2396724059 XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId,
2396824060 SIGNER_DIGEST_SIZE);
24061+ #ifndef IGNORE_NAME_CONSTRAINTS
24062+ if (cert->extAuthKeyIdSet) {
24063+ XMEMCPY(signer->authKeyIdHash, cert->extAuthKeyId,
24064+ SIGNER_DIGEST_SIZE);
24065+ signer->authKeyIdSet = 1;
24066+ }
24067+ #endif
2396924068 #endif
2397024069 XMEMCPY(signer->subjectNameHash, cert->subjectHash,
2397124070 SIGNER_DIGEST_SIZE);
23972- #if defined(HAVE_OCSP) || defined(HAVE_CRL) || defined(WOLFSSL_AKID_NAME)
24071+ #if defined(HAVE_OCSP) || defined(HAVE_CRL) || \
24072+ defined(WOLFSSL_AKID_NAME) || !defined(IGNORE_NAME_CONSTRAINTS)
2397324073 XMEMCPY(signer->issuerNameHash, cert->issuerHash,
2397424074 SIGNER_DIGEST_SIZE);
2397524075 #endif
0 commit comments