@@ -23916,11 +23916,25 @@ static word32 build_otherName_san(byte* out, word32 outSz, const char* val7)
2391623916 return (word32)(sizeof(prefix) + 7);
2391723917}
2391823918
23919+ /* Build a SubjectAltName extension value with a single registeredID
23920+ * GeneralName for OID 1.2.3.4, to use as the leaf SAN in RID tests. */
23921+ static word32 build_registeredID_san(byte* out, word32 outSz)
23922+ {
23923+ static const byte ridSan[] = {
23924+ 0x30, 0x05, /* SEQUENCE, 5 */
23925+ 0x88, 0x03, /* [8] regId, 3 */
23926+ 0x2A, 0x03, 0x04 /* OID 1.2.3.4 */
23927+ };
23928+ if (outSz < sizeof(ridSan))
23929+ return 0;
23930+ XMEMCPY(out, ridSan, sizeof(ridSan));
23931+ return (word32)sizeof(ridSan);
23932+ }
23933+
2391923934/* Build a NameConstraints extension value with a single excludedSubtree
23920- * carrying a registeredID GeneralName for OID 1.2.3.4. registeredID is a
23921- * GeneralName form wolfSSL does not enforce, so DecodeSubtree() must
23922- * record it as 'unsupported' and ConfirmNameConstraints() must fail
23923- * closed when the extension is critical (RFC 5280 4.2.1.10). */
23935+ * carrying a registeredID GeneralName for OID 1.2.3.4. wolfSSL enforces
23936+ * registeredID name constraints by byte-comparing OID bodies, so a leaf
23937+ * whose registeredID SAN matches this exclusion must be rejected. */
2392423938static word32 build_registeredID_nameConstraints(byte* out, word32 outSz)
2392523939{
2392623940 static const byte ridNc[] = {
@@ -24097,10 +24111,12 @@ static int verify_with_otherName_chain(const byte* nameConstraintsDer,
2409724111 * (excluded is enforced regardless of criticality)
2409824112 * 4. Critical permitted subtree, leaf SAN matches -> accept
2409924113 * 5. Critical permitted subtree, leaf SAN does NOT match -> reject
24100- * 6. Critical nameConstraints carrying an unsupported form
24101- * (registeredID), leaf has no relevant SAN -> reject
24102- * (RFC 5280 4.2.1.10 fail-closed for unprocessed forms)
24103- * 7. Same as (6) but non-critical -> accept
24114+ * 6. Critical excluded registeredID subtree, leaf SAN matches -> reject
24115+ * (registeredID is enforced by byte-comparison of OID bodies)
24116+ * 7. Non-critical excluded registeredID subtree, leaf SAN matches -> reject
24117+ * (excluded subtrees are enforced regardless of criticality)
24118+ * 8. Critical excluded registeredID subtree, leaf has no RID SAN -> accept
24119+ * (no match in excluded list, constraint is satisfied)
2410424120 */
2410524121static int test_NameConstraints_OtherName(void)
2410624122{
@@ -24113,16 +24129,19 @@ static int test_NameConstraints_OtherName(void)
2411324129 defined(HAVE_OID_ENCODING) && !defined(IGNORE_NAME_CONSTRAINTS)
2411424130 byte sanBlocked[64];
2411524131 byte sanAllowed[64];
24132+ byte sanRegisteredID[16];
2411624133 byte ncExcludedBlocked[64];
2411724134 byte ncPermittedAllowed[64];
2411824135 byte ncRegisteredID[16];
24119- word32 sanBlockedSz, sanAllowedSz;
24136+ word32 sanBlockedSz, sanAllowedSz, sanRegisteredIDSz ;
2412024137 word32 ncExcludedBlockedSz, ncPermittedAllowedSz, ncRegisteredIDSz;
2412124138
2412224139 sanBlockedSz =
2412324140 build_otherName_san(sanBlocked, sizeof(sanBlocked), "blocked");
2412424141 sanAllowedSz =
2412524142 build_otherName_san(sanAllowed, sizeof(sanAllowed), "allowed");
24143+ sanRegisteredIDSz =
24144+ build_registeredID_san(sanRegisteredID, sizeof(sanRegisteredID));
2412624145 ncExcludedBlockedSz = build_otherName_nameConstraints(
2412724146 ncExcludedBlocked, sizeof(ncExcludedBlocked), 1, "blocked");
2412824147 ncPermittedAllowedSz = build_otherName_nameConstraints(
@@ -24131,6 +24150,7 @@ static int test_NameConstraints_OtherName(void)
2413124150 ncRegisteredID, sizeof(ncRegisteredID));
2413224151 ExpectIntGT((int)sanBlockedSz, 0);
2413324152 ExpectIntGT((int)sanAllowedSz, 0);
24153+ ExpectIntGT((int)sanRegisteredIDSz, 0);
2413424154 ExpectIntGT((int)ncExcludedBlockedSz, 0);
2413524155 ExpectIntGT((int)ncPermittedAllowedSz, 0);
2413624156 ExpectIntGT((int)ncRegisteredIDSz, 0);
@@ -24173,20 +24193,25 @@ static int test_NameConstraints_OtherName(void)
2417324193 sanBlocked, sanBlockedSz),
2417424194 WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
2417524195
24176- /* (6) Critical nameConstraints carrying a GeneralName form wolfSSL
24177- * does not enforce (registeredID). RFC 5280 4.2.1.10 requires the
24178- * verifier to either process the constraint or reject; we reject
24179- * fail-closed. The leaf needs no SAN to exercise this path. */
24196+ /* (6) Critical excluded registeredID subtree, leaf SAN matches:
24197+ * registeredID is now enforced by byte-comparing OID bodies, so a
24198+ * matching excluded entry must be rejected. */
2418024199 ExpectIntEQ(verify_with_otherName_chain(
24181- ncRegisteredID, ncRegisteredIDSz, 1, NULL, 0),
24200+ ncRegisteredID, ncRegisteredIDSz, 1,
24201+ sanRegisteredID, sanRegisteredIDSz),
24202+ WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
24203+
24204+ /* (7) Non-critical excluded registeredID subtree, leaf SAN matches:
24205+ * excluded subtrees are enforced regardless of criticality. */
24206+ ExpectIntEQ(verify_with_otherName_chain(
24207+ ncRegisteredID, ncRegisteredIDSz, 0,
24208+ sanRegisteredID, sanRegisteredIDSz),
2418224209 WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
2418324210
24184- /* (7) Same as (6) but non-critical: RFC 5280 only mandates the
24185- * fail-closed reject when the extension is critical, so a
24186- * non-critical unsupported constraint form is silently ignored
24187- * and verification succeeds. */
24211+ /* (8) Critical excluded registeredID subtree, leaf has no RID SAN:
24212+ * no excluded match, so verification succeeds. */
2418824213 ExpectIntEQ(verify_with_otherName_chain(
24189- ncRegisteredID, ncRegisteredIDSz, 0 , NULL, 0),
24214+ ncRegisteredID, ncRegisteredIDSz, 1 , NULL, 0),
2419024215 0);
2419124216#endif
2419224217 return EXPECT_RESULT();
0 commit comments