Skip to content

Commit b573823

Browse files
Merge pull request #10187 from embhorn/zd21587
Fixes in TLS ECH, handle empty records, and ASN len check
2 parents bc4bec6 + 0c0c426 commit b573823

10 files changed

Lines changed: 665 additions & 12 deletions

File tree

src/internal.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21907,6 +21907,23 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
2190721907
}
2190821908
#endif
2190921909

21910+
/* Rate-limit empty application data records to prevent DoS */
21911+
if (dataSz == 0) {
21912+
if (++ssl->options.emptyRecordCount >= WOLFSSL_MAX_EMPTY_RECORDS) {
21913+
WOLFSSL_MSG("Too many empty records");
21914+
#ifdef WOLFSSL_EXTRA_ALERTS
21915+
if (sniff == NO_SNIFF) {
21916+
SendAlert(ssl, alert_fatal, unexpected_message);
21917+
}
21918+
#endif
21919+
WOLFSSL_ERROR_VERBOSE(EMPTY_RECORD_LIMIT_E);
21920+
return EMPTY_RECORD_LIMIT_E;
21921+
}
21922+
}
21923+
else {
21924+
ssl->options.emptyRecordCount = 0;
21925+
}
21926+
2191021927
/* read data */
2191121928
if (dataSz) {
2191221929
int rawSz = dataSz; /* keep raw size for idx adjustment */
@@ -27616,6 +27633,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
2761627633
case ALERT_COUNT_E:
2761727634
return "Alert Count exceeded error";
2761827635

27636+
case EMPTY_RECORD_LIMIT_E:
27637+
return "Too many empty records error";
27638+
2761927639
case EXT_MISSING:
2762027640
return "Required TLS extension missing";
2762127641

src/tls.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17211,6 +17211,9 @@ int TLSX_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType,
1721117211
#ifdef WOLFSSL_QUIC
1721217212
|| (type == TLSX_KEY_QUIC_TP_PARAMS_DRAFT)
1721317213
#endif
17214+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
17215+
|| (type == TLSX_ECH)
17216+
#endif
1721417217
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_DUAL_ALG_CERTS)
1721517218
|| (type == TLSX_CKS)
1721617219
#endif

src/tls13.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2638,7 +2638,8 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
26382638
#endif
26392639

26402640
#ifdef WOLFSSL_CIPHER_TEXT_CHECK
2641-
if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) {
2641+
if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null &&
2642+
dataSz > 0) {
26422643
XMEMCPY(ssl->encrypt.sanityCheck, input,
26432644
min(dataSz, sizeof(ssl->encrypt.sanityCheck)));
26442645
}
@@ -2824,6 +2825,7 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input,
28242825

28252826
#ifdef WOLFSSL_CIPHER_TEXT_CHECK
28262827
if (ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null &&
2828+
dataSz > 0 &&
28272829
XMEMCMP(output, ssl->encrypt.sanityCheck,
28282830
min(dataSz, sizeof(ssl->encrypt.sanityCheck))) == 0) {
28292831

tests/api.c

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21620,6 +21620,326 @@ static int test_MakeCertWithPathLen(void)
2162021620
return EXPECT_RESULT();
2162121621
}
2162221622

21623+
static int test_PathLenSelfIssued(void)
21624+
{
21625+
EXPECT_DECLS;
21626+
#if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \
21627+
defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \
21628+
defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \
21629+
(!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
21630+
Cert cert;
21631+
DecodedCert decodedCert;
21632+
byte rootDer[FOURK_BUF];
21633+
byte icaDer[FOURK_BUF];
21634+
byte entityDer[FOURK_BUF];
21635+
int rootDerSz = 0;
21636+
int icaDerSz = 0;
21637+
int entityDerSz = 0;
21638+
WC_RNG rng;
21639+
ecc_key rootKey;
21640+
ecc_key icaKey;
21641+
ecc_key entityKey;
21642+
WOLFSSL_CERT_MANAGER* cm = NULL;
21643+
21644+
XMEMSET(&rng, 0, sizeof(WC_RNG));
21645+
XMEMSET(&rootKey, 0, sizeof(ecc_key));
21646+
XMEMSET(&icaKey, 0, sizeof(ecc_key));
21647+
XMEMSET(&entityKey, 0, sizeof(ecc_key));
21648+
21649+
ExpectIntEQ(wc_InitRng(&rng), 0);
21650+
ExpectIntEQ(wc_ecc_init(&rootKey), 0);
21651+
ExpectIntEQ(wc_ecc_init(&icaKey), 0);
21652+
ExpectIntEQ(wc_ecc_init(&entityKey), 0);
21653+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0);
21654+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0);
21655+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &entityKey), 0);
21656+
21657+
/* Step 1: Create root CA with pathLen=0 */
21658+
ExpectIntEQ(wc_InitCert(&cert), 0);
21659+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
21660+
(void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
21661+
(void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
21662+
(void)XSTRNCPY(cert.subject.org, "TestCA", CTC_NAME_SIZE);
21663+
(void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE);
21664+
(void)XSTRNCPY(cert.subject.commonName, "TestRootCA", CTC_NAME_SIZE);
21665+
(void)XSTRNCPY(cert.subject.email, "root@test.com", CTC_NAME_SIZE);
21666+
cert.selfSigned = 1;
21667+
cert.isCA = 1;
21668+
cert.pathLen = 0;
21669+
cert.pathLenSet = 1;
21670+
cert.sigType = CTC_SHA256wECDSA;
21671+
cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN;
21672+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey),
21673+
0);
21674+
21675+
ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng),
21676+
0);
21677+
ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer,
21678+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21679+
21680+
/* Step 2: Create self-issued intermediate (same subject DN as root,
21681+
* different key, signed by root) - this should be blocked by pathLen=0 */
21682+
ExpectIntEQ(wc_InitCert(&cert), 0);
21683+
cert.selfSigned = 0;
21684+
cert.isCA = 1;
21685+
cert.sigType = CTC_SHA256wECDSA;
21686+
cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN;
21687+
/* Set both subject and issuer from the root cert so they match */
21688+
ExpectIntEQ(wc_SetSubjectBuffer(&cert, rootDer, rootDerSz), 0);
21689+
ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0);
21690+
ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0);
21691+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey),
21692+
0);
21693+
21694+
ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0);
21695+
ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer,
21696+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21697+
21698+
/* Step 3: Create entity cert signed by the intermediate */
21699+
ExpectIntEQ(wc_InitCert(&cert), 0);
21700+
cert.selfSigned = 0;
21701+
cert.isCA = 0;
21702+
cert.sigType = CTC_SHA256wECDSA;
21703+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
21704+
(void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
21705+
(void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
21706+
(void)XSTRNCPY(cert.subject.org, "TestEntity", CTC_NAME_SIZE);
21707+
(void)XSTRNCPY(cert.subject.commonName, "entity.test", CTC_NAME_SIZE);
21708+
ExpectIntEQ(wc_SetIssuerBuffer(&cert, icaDer, icaDerSz), 0);
21709+
ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey), 0);
21710+
21711+
ExpectIntGE(wc_MakeCert(&cert, entityDer, FOURK_BUF, NULL, &entityKey,
21712+
&rng), 0);
21713+
ExpectIntGE(entityDerSz = wc_SignCert(cert.bodySz, cert.sigType, entityDer,
21714+
FOURK_BUF, NULL, &icaKey, &rng), 0);
21715+
21716+
/* Step 4: Load root CA into cert manager */
21717+
ExpectNotNull(cm = wolfSSL_CertManagerNew());
21718+
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz,
21719+
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
21720+
21721+
/* Step 5: Parse the self-issued intermediate as a chain cert.
21722+
* This simulates TLS chain verification where the intermediate is
21723+
* received as part of the certificate chain.
21724+
* Root CA has pathLen=0, so it should NOT be allowed to sign any
21725+
* intermediate CA (including self-issued ones).
21726+
* BUG: wolfSSL sets selfSigned=1 for this cert (issuer==subject DN),
21727+
* which causes the pathLen enforcement to be entirely skipped. */
21728+
wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL);
21729+
ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY,
21730+
cm), WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E));
21731+
wc_FreeDecodedCert(&decodedCert);
21732+
21733+
wolfSSL_CertManagerFree(cm);
21734+
wc_ecc_free(&entityKey);
21735+
wc_ecc_free(&icaKey);
21736+
wc_ecc_free(&rootKey);
21737+
wc_FreeRng(&rng);
21738+
#endif
21739+
return EXPECT_RESULT();
21740+
}
21741+
21742+
/* Verifies that a self-issued intermediate under a CA with pathLen > 0 is
21743+
* accepted AND that maxPathLen is propagated as min(ca->maxPathLen,
21744+
* cert->pathLength) without being decremented (RFC 5280 6.1.4(l)).
21745+
* Pins the `else` branch in asn.c so deletion or an accidental decrement
21746+
* (like the non-self-issued path) is detected. */
21747+
static int test_PathLenSelfIssuedAllowed(void)
21748+
{
21749+
EXPECT_DECLS;
21750+
#if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \
21751+
defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \
21752+
defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \
21753+
(!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
21754+
Cert cert;
21755+
DecodedCert decodedCert;
21756+
byte rootDer[FOURK_BUF];
21757+
byte icaDer[FOURK_BUF];
21758+
int rootDerSz = 0;
21759+
int icaDerSz = 0;
21760+
WC_RNG rng;
21761+
ecc_key rootKey;
21762+
ecc_key icaKey;
21763+
WOLFSSL_CERT_MANAGER* cm = NULL;
21764+
21765+
XMEMSET(&rng, 0, sizeof(WC_RNG));
21766+
XMEMSET(&rootKey, 0, sizeof(ecc_key));
21767+
XMEMSET(&icaKey, 0, sizeof(ecc_key));
21768+
21769+
ExpectIntEQ(wc_InitRng(&rng), 0);
21770+
ExpectIntEQ(wc_ecc_init(&rootKey), 0);
21771+
ExpectIntEQ(wc_ecc_init(&icaKey), 0);
21772+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0);
21773+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0);
21774+
21775+
/* Step 1: Create root CA with pathLen=1 */
21776+
ExpectIntEQ(wc_InitCert(&cert), 0);
21777+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
21778+
(void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
21779+
(void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
21780+
(void)XSTRNCPY(cert.subject.org, "TestCA3", CTC_NAME_SIZE);
21781+
(void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE);
21782+
(void)XSTRNCPY(cert.subject.commonName, "TestRootCA3", CTC_NAME_SIZE);
21783+
(void)XSTRNCPY(cert.subject.email, "root@test3.com", CTC_NAME_SIZE);
21784+
cert.selfSigned = 1;
21785+
cert.isCA = 1;
21786+
cert.pathLen = 1;
21787+
cert.pathLenSet = 1;
21788+
cert.sigType = CTC_SHA256wECDSA;
21789+
cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN;
21790+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey),
21791+
0);
21792+
21793+
ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng),
21794+
0);
21795+
ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer,
21796+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21797+
21798+
/* Step 2: Create a self-issued intermediate with its OWN pathLen=5.
21799+
* The intentionally-larger pathLen lets the test distinguish:
21800+
* - Correct self-issued path: maxPathLen = min(1, 5) = 1
21801+
* - Deleted else branch: maxPathLen stays at 5 (cert->pathLength)
21802+
* - Mutated to decrement: maxPathLen = min(0, 5) = 0 */
21803+
ExpectIntEQ(wc_InitCert(&cert), 0);
21804+
cert.selfSigned = 0;
21805+
cert.isCA = 1;
21806+
cert.pathLen = 5;
21807+
cert.pathLenSet = 1;
21808+
cert.sigType = CTC_SHA256wECDSA;
21809+
cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN;
21810+
/* Same subject/issuer DN as root -> self-issued */
21811+
ExpectIntEQ(wc_SetSubjectBuffer(&cert, rootDer, rootDerSz), 0);
21812+
ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0);
21813+
ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0);
21814+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey),
21815+
0);
21816+
21817+
ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0);
21818+
ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer,
21819+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21820+
21821+
/* Step 3: Load root CA into cert manager */
21822+
ExpectNotNull(cm = wolfSSL_CertManagerNew());
21823+
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz,
21824+
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
21825+
21826+
/* Step 4: Parse the self-issued intermediate. Must be accepted AND
21827+
* maxPathLen must be exactly 1 (honors root's constraint without
21828+
* decrementing). */
21829+
wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL);
21830+
ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY, cm), 0);
21831+
ExpectIntEQ(decodedCert.maxPathLen, 1);
21832+
wc_FreeDecodedCert(&decodedCert);
21833+
21834+
wolfSSL_CertManagerFree(cm);
21835+
wc_ecc_free(&icaKey);
21836+
wc_ecc_free(&rootKey);
21837+
wc_FreeRng(&rng);
21838+
#endif
21839+
return EXPECT_RESULT();
21840+
}
21841+
21842+
static int test_PathLenNoKeyUsage(void)
21843+
{
21844+
EXPECT_DECLS;
21845+
#if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \
21846+
defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) && \
21847+
defined(WOLFSSL_CERT_EXT) && !defined(NO_CERTS) && \
21848+
(!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
21849+
Cert cert;
21850+
DecodedCert decodedCert;
21851+
byte rootDer[FOURK_BUF];
21852+
byte icaDer[FOURK_BUF];
21853+
int rootDerSz = 0;
21854+
int icaDerSz = 0;
21855+
WC_RNG rng;
21856+
ecc_key rootKey;
21857+
ecc_key icaKey;
21858+
WOLFSSL_CERT_MANAGER* cm = NULL;
21859+
21860+
XMEMSET(&rng, 0, sizeof(WC_RNG));
21861+
XMEMSET(&rootKey, 0, sizeof(ecc_key));
21862+
XMEMSET(&icaKey, 0, sizeof(ecc_key));
21863+
21864+
ExpectIntEQ(wc_InitRng(&rng), 0);
21865+
ExpectIntEQ(wc_ecc_init(&rootKey), 0);
21866+
ExpectIntEQ(wc_ecc_init(&icaKey), 0);
21867+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &rootKey), 0);
21868+
ExpectIntEQ(wc_ecc_make_key(&rng, 32, &icaKey), 0);
21869+
21870+
/* Step 1: Create root CA with pathLen=0 and KeyUsage */
21871+
ExpectIntEQ(wc_InitCert(&cert), 0);
21872+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
21873+
(void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
21874+
(void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
21875+
(void)XSTRNCPY(cert.subject.org, "TestCA2", CTC_NAME_SIZE);
21876+
(void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE);
21877+
(void)XSTRNCPY(cert.subject.commonName, "TestRootCA2", CTC_NAME_SIZE);
21878+
(void)XSTRNCPY(cert.subject.email, "root@test2.com", CTC_NAME_SIZE);
21879+
cert.selfSigned = 1;
21880+
cert.isCA = 1;
21881+
cert.pathLen = 0;
21882+
cert.pathLenSet = 1;
21883+
cert.sigType = CTC_SHA256wECDSA;
21884+
cert.keyUsage = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN;
21885+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey),
21886+
0);
21887+
21888+
ExpectIntGE(wc_MakeCert(&cert, rootDer, FOURK_BUF, NULL, &rootKey, &rng),
21889+
0);
21890+
ExpectIntGE(rootDerSz = wc_SignCert(cert.bodySz, cert.sigType, rootDer,
21891+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21892+
21893+
/* Step 2: Create intermediate CA WITHOUT KeyUsage extension.
21894+
* Per RFC 5280, when KeyUsage is absent all uses are valid.
21895+
* The root's pathLen=0 should still block this intermediate CA.
21896+
* BUG: pathLen check requires extKeyUsageSet which is false when
21897+
* KeyUsage is absent, so the check is skipped entirely. */
21898+
ExpectIntEQ(wc_InitCert(&cert), 0);
21899+
cert.selfSigned = 0;
21900+
cert.isCA = 1;
21901+
cert.sigType = CTC_SHA256wECDSA;
21902+
/* Intentionally do NOT set keyUsage - test that pathLen is still enforced */
21903+
cert.keyUsage = 0;
21904+
(void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE);
21905+
(void)XSTRNCPY(cert.subject.state, "MT", CTC_NAME_SIZE);
21906+
(void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE);
21907+
(void)XSTRNCPY(cert.subject.org, "TestICA", CTC_NAME_SIZE);
21908+
(void)XSTRNCPY(cert.subject.unit, "Test", CTC_NAME_SIZE);
21909+
(void)XSTRNCPY(cert.subject.commonName, "TestICA-NoKU", CTC_NAME_SIZE);
21910+
(void)XSTRNCPY(cert.subject.email, "ica@test2.com", CTC_NAME_SIZE);
21911+
ExpectIntEQ(wc_SetIssuerBuffer(&cert, rootDer, rootDerSz), 0);
21912+
ExpectIntEQ(wc_SetAuthKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &rootKey), 0);
21913+
ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey_ex(&cert, ECC_TYPE, &icaKey),
21914+
0);
21915+
21916+
ExpectIntGE(wc_MakeCert(&cert, icaDer, FOURK_BUF, NULL, &icaKey, &rng), 0);
21917+
ExpectIntGE(icaDerSz = wc_SignCert(cert.bodySz, cert.sigType, icaDer,
21918+
FOURK_BUF, NULL, &rootKey, &rng), 0);
21919+
21920+
/* Step 3: Load root CA into cert manager */
21921+
ExpectNotNull(cm = wolfSSL_CertManagerNew());
21922+
ExpectIntEQ(wolfSSL_CertManagerLoadCABuffer(cm, rootDer, rootDerSz,
21923+
WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS);
21924+
21925+
/* Step 4: Parse the intermediate (no KeyUsage) as a chain cert.
21926+
* Root CA has pathLen=0, this intermediate CA should be rejected.
21927+
* The intermediate does NOT have the KeyUsage extension, but per
21928+
* RFC 5280 4.2.1.3 all key uses are valid when the extension is
21929+
* absent, so pathLen must still be enforced. */
21930+
wc_InitDecodedCert(&decodedCert, icaDer, (word32)icaDerSz, NULL);
21931+
ExpectIntEQ(wc_ParseCert(&decodedCert, CHAIN_CERT_TYPE, VERIFY,
21932+
cm), WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E));
21933+
wc_FreeDecodedCert(&decodedCert);
21934+
21935+
wolfSSL_CertManagerFree(cm);
21936+
wc_ecc_free(&icaKey);
21937+
wc_ecc_free(&rootKey);
21938+
wc_FreeRng(&rng);
21939+
#endif
21940+
return EXPECT_RESULT();
21941+
}
21942+
2162321943
static int test_MakeCertWith0Ser(void)
2162421944
{
2162521945
EXPECT_DECLS;
@@ -35807,6 +36127,9 @@ TEST_CASE testCases[] = {
3580736127
TEST_DECL(test_wc_ParseCert),
3580836128
TEST_DECL(test_wc_ParseCert_Error),
3580936129
TEST_DECL(test_MakeCertWithPathLen),
36130+
TEST_DECL(test_PathLenSelfIssued),
36131+
TEST_DECL(test_PathLenSelfIssuedAllowed),
36132+
TEST_DECL(test_PathLenNoKeyUsage),
3581036133
TEST_DECL(test_MakeCertWith0Ser),
3581136134
TEST_DECL(test_MakeCertWithCaFalse),
3581236135
#ifdef WOLFSSL_CERT_SIGN_CB

0 commit comments

Comments
 (0)