@@ -24006,11 +24006,25 @@ static word32 build_otherName_san(byte* out, word32 outSz, const char* val7)
2400624006 return (word32)(sizeof(prefix) + 7);
2400724007}
2400824008
24009+ /* Build a SubjectAltName extension value with a single registeredID
24010+ * GeneralName for OID 1.2.3.4, to use as the leaf SAN in RID tests. */
24011+ static word32 build_registeredID_san(byte* out, word32 outSz)
24012+ {
24013+ static const byte ridSan[] = {
24014+ 0x30, 0x05, /* SEQUENCE, 5 */
24015+ 0x88, 0x03, /* [8] regId, 3 */
24016+ 0x2A, 0x03, 0x04 /* OID 1.2.3.4 */
24017+ };
24018+ if (outSz < sizeof(ridSan))
24019+ return 0;
24020+ XMEMCPY(out, ridSan, sizeof(ridSan));
24021+ return (word32)sizeof(ridSan);
24022+ }
24023+
2400924024/* Build a NameConstraints extension value with a single excludedSubtree
24010- * carrying a registeredID GeneralName for OID 1.2.3.4. registeredID is a
24011- * GeneralName form wolfSSL does not enforce, so DecodeSubtree() must
24012- * record it as 'unsupported' and ConfirmNameConstraints() must fail
24013- * closed when the extension is critical (RFC 5280 4.2.1.10). */
24025+ * carrying a registeredID GeneralName for OID 1.2.3.4. wolfSSL enforces
24026+ * registeredID name constraints by byte-comparing OID bodies, so a leaf
24027+ * whose registeredID SAN matches this exclusion must be rejected. */
2401424028static word32 build_registeredID_nameConstraints(byte* out, word32 outSz)
2401524029{
2401624030 static const byte ridNc[] = {
@@ -24187,10 +24201,12 @@ static int verify_with_otherName_chain(const byte* nameConstraintsDer,
2418724201 * (excluded is enforced regardless of criticality)
2418824202 * 4. Critical permitted subtree, leaf SAN matches -> accept
2418924203 * 5. Critical permitted subtree, leaf SAN does NOT match -> reject
24190- * 6. Critical nameConstraints carrying an unsupported form
24191- * (registeredID), leaf has no relevant SAN -> reject
24192- * (RFC 5280 4.2.1.10 fail-closed for unprocessed forms)
24193- * 7. Same as (6) but non-critical -> accept
24204+ * 6. Critical excluded registeredID subtree, leaf SAN matches -> reject
24205+ * (registeredID is enforced by byte-comparison of OID bodies)
24206+ * 7. Non-critical excluded registeredID subtree, leaf SAN matches -> reject
24207+ * (excluded subtrees are enforced regardless of criticality)
24208+ * 8. Critical excluded registeredID subtree, leaf has no RID SAN -> accept
24209+ * (no match in excluded list, constraint is satisfied)
2419424210 */
2419524211static int test_NameConstraints_OtherName(void)
2419624212{
@@ -24203,16 +24219,19 @@ static int test_NameConstraints_OtherName(void)
2420324219 defined(HAVE_OID_ENCODING) && !defined(IGNORE_NAME_CONSTRAINTS)
2420424220 byte sanBlocked[64];
2420524221 byte sanAllowed[64];
24222+ byte sanRegisteredID[16];
2420624223 byte ncExcludedBlocked[64];
2420724224 byte ncPermittedAllowed[64];
2420824225 byte ncRegisteredID[16];
24209- word32 sanBlockedSz, sanAllowedSz;
24226+ word32 sanBlockedSz, sanAllowedSz, sanRegisteredIDSz ;
2421024227 word32 ncExcludedBlockedSz, ncPermittedAllowedSz, ncRegisteredIDSz;
2421124228
2421224229 sanBlockedSz =
2421324230 build_otherName_san(sanBlocked, sizeof(sanBlocked), "blocked");
2421424231 sanAllowedSz =
2421524232 build_otherName_san(sanAllowed, sizeof(sanAllowed), "allowed");
24233+ sanRegisteredIDSz =
24234+ build_registeredID_san(sanRegisteredID, sizeof(sanRegisteredID));
2421624235 ncExcludedBlockedSz = build_otherName_nameConstraints(
2421724236 ncExcludedBlocked, sizeof(ncExcludedBlocked), 1, "blocked");
2421824237 ncPermittedAllowedSz = build_otherName_nameConstraints(
@@ -24221,6 +24240,7 @@ static int test_NameConstraints_OtherName(void)
2422124240 ncRegisteredID, sizeof(ncRegisteredID));
2422224241 ExpectIntGT((int)sanBlockedSz, 0);
2422324242 ExpectIntGT((int)sanAllowedSz, 0);
24243+ ExpectIntGT((int)sanRegisteredIDSz, 0);
2422424244 ExpectIntGT((int)ncExcludedBlockedSz, 0);
2422524245 ExpectIntGT((int)ncPermittedAllowedSz, 0);
2422624246 ExpectIntGT((int)ncRegisteredIDSz, 0);
@@ -24263,20 +24283,25 @@ static int test_NameConstraints_OtherName(void)
2426324283 sanBlocked, sanBlockedSz),
2426424284 WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
2426524285
24266- /* (6) Critical nameConstraints carrying a GeneralName form wolfSSL
24267- * does not enforce (registeredID). RFC 5280 4.2.1.10 requires the
24268- * verifier to either process the constraint or reject; we reject
24269- * fail-closed. The leaf needs no SAN to exercise this path. */
24286+ /* (6) Critical excluded registeredID subtree, leaf SAN matches:
24287+ * registeredID is now enforced by byte-comparing OID bodies, so a
24288+ * matching excluded entry must be rejected. */
2427024289 ExpectIntEQ(verify_with_otherName_chain(
24271- ncRegisteredID, ncRegisteredIDSz, 1, NULL, 0),
24290+ ncRegisteredID, ncRegisteredIDSz, 1,
24291+ sanRegisteredID, sanRegisteredIDSz),
24292+ WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
24293+
24294+ /* (7) Non-critical excluded registeredID subtree, leaf SAN matches:
24295+ * excluded subtrees are enforced regardless of criticality. */
24296+ ExpectIntEQ(verify_with_otherName_chain(
24297+ ncRegisteredID, ncRegisteredIDSz, 0,
24298+ sanRegisteredID, sanRegisteredIDSz),
2427224299 WC_NO_ERR_TRACE(ASN_NAME_INVALID_E));
2427324300
24274- /* (7) Same as (6) but non-critical: RFC 5280 only mandates the
24275- * fail-closed reject when the extension is critical, so a
24276- * non-critical unsupported constraint form is silently ignored
24277- * and verification succeeds. */
24301+ /* (8) Critical excluded registeredID subtree, leaf has no RID SAN:
24302+ * no excluded match, so verification succeeds. */
2427824303 ExpectIntEQ(verify_with_otherName_chain(
24279- ncRegisteredID, ncRegisteredIDSz, 0 , NULL, 0),
24304+ ncRegisteredID, ncRegisteredIDSz, 1 , NULL, 0),
2428024305 0);
2428124306#endif
2428224307 return EXPECT_RESULT();
@@ -26733,11 +26758,25 @@ static int test_wolfSSL_X509_print(void)
2673326758 /* Will print IP address subject alt name. */
2673426759 ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3350);
2673526760 #endif
26736- #elif defined(NO_ASN_TIME)
26737- /* With NO_ASN_TIME defined, X509_print skips printing Validity. */
26761+ #elif defined(IGNORE_NAME_CONSTRAINTS)
26762+ /* DecodeGeneralName skips iPAddress entries when name constraints
26763+ * are disabled, so the IP SAN never reaches the print path. */
26764+ #if defined(NO_ASN_TIME)
2673826765 ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3213);
26739- #else
26766+ #else
2674026767 ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3328);
26768+ #endif
26769+ #elif defined(NO_ASN_TIME)
26770+ /* With NO_ASN_TIME defined, X509_print skips printing Validity.
26771+ * iPAddress SAN now always parsed; prints as
26772+ * "IP Address:<unavailable>" (+26 bytes) without
26773+ * WOLFSSL_IP_ALT_NAME. */
26774+ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3239);
26775+ #else
26776+ /* iPAddress SAN now always parsed; prints as
26777+ * "IP Address:<unavailable>" (+26 bytes) without
26778+ * WOLFSSL_IP_ALT_NAME. */
26779+ ExpectIntEQ(BIO_get_mem_data(bio, NULL), 3354);
2674126780#endif
2674226781 BIO_free(bio);
2674326782 bio = NULL;
0 commit comments