Skip to content

Commit 018ee97

Browse files
authored
Merge pull request #8608 from anhu/2akid
Check for duplicate extensions in a CRL
2 parents d1c1bca + a0cd18d commit 018ee97

File tree

2 files changed

+98
-32
lines changed

2 files changed

+98
-32
lines changed

tests/api.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4257,6 +4257,44 @@ static int test_wolfSSL_CertManagerNameConstraint5(void)
42574257
return EXPECT_RESULT();
42584258
}
42594259

4260+
static int test_wolfSSL_CRL_duplicate_extensions(void)
4261+
{
4262+
EXPECT_DECLS;
4263+
#if defined(WOLFSSL_ASN_TEMPLATE) && !defined(NO_CERTS) && \
4264+
defined(HAVE_CRL) && !defined(NO_RSA) && !defined(WOLFSSL_NO_ASN_STRICT)
4265+
const unsigned char crl_duplicate_akd[] =
4266+
"-----BEGIN X509 CRL-----\n"
4267+
"MIICCDCB8QIBATANBgkqhkiG9w0BAQsFADB5MQswCQYDVQQGEwJVUzETMBEGA1UE\n"
4268+
"CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK\n"
4269+
"TXkgQ29tcGFueTETMBEGA1UEAwwKTXkgUm9vdCBDQTETMBEGA1UECwwKTXkgUm9v\n"
4270+
"dCBDQRcNMjQwOTAxMDAwMDAwWhcNMjUxMjAxMDAwMDAwWqBEMEIwHwYDVR0jBBgw\n"
4271+
"FoAU72ng99Ud5pns3G3Q9+K5XGRxgzUwHwYDVR0jBBgwFoAU72ng99Ud5pns3G3Q\n"
4272+
"9+K5XGRxgzUwDQYJKoZIhvcNAQELBQADggEBAIFVw4jrS4taSXR/9gPzqGrqFeHr\n"
4273+
"IXCnFtHJTLxqa8vUOAqSwqysvNpepVKioMVoGrLjFMjANjWQqTEiMROAnLfJ/+L8\n"
4274+
"FHZkV/mZwOKAXMhIC9MrJzifxBICwmvD028qnwQm09EP8z4ICZptD6wPdRTDzduc\n"
4275+
"KBuAX+zn8pNrJgyrheRKpPgno9KsbCzK4D/RIt1sTK2M3vVOtY+vpsN70QYUXvQ4\n"
4276+
"r2RZac3omlT43x5lddPxIlcouQpwWcVvr/K+Va770MRrjn88PBrJmvsEw/QYVBXp\n"
4277+
"Gxv2b78HFDacba80sMIm8ltRdqUCa5qIc6OATsz7izCQXEbkTEeESrcK1MA=\n"
4278+
"-----END X509 CRL-----\n";
4279+
4280+
WOLFSSL_CERT_MANAGER* cm = NULL;
4281+
int ret;
4282+
4283+
cm = wolfSSL_CertManagerNew();
4284+
ExpectNotNull(cm);
4285+
4286+
/* Test loading CRL with duplicate extensions */
4287+
WOLFSSL_MSG("Testing CRL with duplicate Authority Key Identifier extensions");
4288+
ret = wolfSSL_CertManagerLoadCRLBuffer(cm, crl_duplicate_akd,
4289+
sizeof(crl_duplicate_akd),
4290+
WOLFSSL_FILETYPE_PEM);
4291+
ExpectIntEQ(ret, ASN_PARSE_E);
4292+
4293+
wolfSSL_CertManagerFree(cm);
4294+
#endif
4295+
return EXPECT_RESULT();
4296+
}
4297+
42604298
static int test_wolfSSL_CertManagerCRL(void)
42614299
{
42624300
EXPECT_DECLS;
@@ -68150,6 +68188,7 @@ TEST_CASE testCases[] = {
6815068188
TEST_DECL(test_wolfSSL_CertManagerNameConstraint4),
6815168189
TEST_DECL(test_wolfSSL_CertManagerNameConstraint5),
6815268190
TEST_DECL(test_wolfSSL_CertManagerCRL),
68191+
TEST_DECL(test_wolfSSL_CRL_duplicate_extensions),
6815368192
TEST_DECL(test_wolfSSL_CertManagerCheckOCSPResponse),
6815468193
TEST_DECL(test_wolfSSL_CheckOCSPResponse),
6815568194
#ifdef HAVE_CERT_CHAIN_VALIDATION

wolfcrypt/src/asn.c

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40566,6 +40566,9 @@ static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, word32 idx,
4056640566
{
4056740567
DECL_ASNGETDATA(dataASN, certExtASN_Length);
4056840568
int ret = 0;
40569+
/* Track if we've seen these extensions already */
40570+
word32 seenAuthKey = 0;
40571+
word32 seenCrlNum = 0;
4056940572

4057040573
ALLOC_ASNGETDATA(dataASN, certExtASN_Length, ret, dcrl->heap);
4057140574

@@ -40588,47 +40591,71 @@ static int ParseCRL_Extensions(DecodedCRL* dcrl, const byte* buf, word32 idx,
4058840591
/* Length of extension data. */
4058940592
int length = (int)dataASN[CERTEXTASN_IDX_VAL].length;
4059040593

40591-
if (oid == AUTH_KEY_OID) {
40592-
#ifndef NO_SKID
40593-
/* Parse Authority Key Id extension.
40594-
* idx is at start of OCTET_STRING data. */
40595-
ret = ParseCRL_AuthKeyIdExt(buf + localIdx, length, dcrl);
40596-
if (ret != 0) {
40597-
WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension");
40598-
}
40599-
#endif
40594+
/* Check for duplicate extension. RFC 5280 Section 4.2 states that
40595+
* a certificate must not include more than one instance of a
40596+
* particular extension. Note that the same guidance does not appear
40597+
* for CRLs but the same reasoning should apply. */
40598+
if ((oid == AUTH_KEY_OID && seenAuthKey) ||
40599+
(oid == CRL_NUMBER_OID && seenCrlNum)) {
40600+
WOLFSSL_MSG("Duplicate CRL extension found");
40601+
/* Gating !WOLFSSL_NO_ASN_STRICT will allow wolfCLU to have same
40602+
* behaviour as OpenSSL */
40603+
#ifndef WOLFSSL_NO_ASN_STRICT
40604+
ret = ASN_PARSE_E;
40605+
#endif
4060040606
}
40601-
else if (oid == CRL_NUMBER_OID) {
40602-
DECL_MP_INT_SIZE_DYN(m, CRL_MAX_NUM_SZ * CHAR_BIT,
40603-
CRL_MAX_NUM_SZ * CHAR_BIT);
40604-
NEW_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT, NULL,
40605-
DYNAMIC_TYPE_TMP_BUFFER);
4060640607

40607-
#ifdef MP_INT_SIZE_CHECK_NULL
40608-
if (m == NULL) {
40609-
ret = MEMORY_E;
40608+
/* Track this extension if no duplicate found */
40609+
if (ret == 0) {
40610+
if (oid == AUTH_KEY_OID)
40611+
seenAuthKey = 1;
40612+
else if (oid == CRL_NUMBER_OID)
40613+
seenCrlNum = 1;
40614+
}
40615+
40616+
if (ret == 0) {
40617+
if (oid == AUTH_KEY_OID) {
40618+
#ifndef NO_SKID
40619+
/* Parse Authority Key Id extension.
40620+
* idx is at start of OCTET_STRING data. */
40621+
ret = ParseCRL_AuthKeyIdExt(buf + localIdx, length, dcrl);
40622+
if (ret != 0) {
40623+
WOLFSSL_MSG("\tcouldn't parse AuthKeyId extension");
40624+
}
40625+
#endif
4061040626
}
40611-
#endif
40627+
else if (oid == CRL_NUMBER_OID) {
40628+
DECL_MP_INT_SIZE_DYN(m, CRL_MAX_NUM_SZ * CHAR_BIT,
40629+
CRL_MAX_NUM_SZ * CHAR_BIT);
40630+
NEW_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT, NULL,
40631+
DYNAMIC_TYPE_TMP_BUFFER);
40632+
40633+
#ifdef MP_INT_SIZE_CHECK_NULL
40634+
if (m == NULL) {
40635+
ret = MEMORY_E;
40636+
}
40637+
#endif
4061240638

40613-
if (ret == 0 && (INIT_MP_INT_SIZE(m, CRL_MAX_NUM_SZ * CHAR_BIT)
40614-
!= MP_OKAY)) {
40639+
if (ret == 0 && (INIT_MP_INT_SIZE(m, CRL_MAX_NUM_SZ *
40640+
CHAR_BIT) != MP_OKAY)) {
4061540641
ret = MP_INIT_E;
40616-
}
40642+
}
4061740643

40618-
if (ret == 0) {
40619-
ret = GetInt(m, buf, &localIdx, maxIdx);
40620-
}
40644+
if (ret == 0) {
40645+
ret = GetInt(m, buf, &localIdx, maxIdx);
40646+
}
4062140647

40622-
if (ret == 0 && mp_toradix(m, (char*)dcrl->crlNumber,
40623-
MP_RADIX_HEX) != MP_OKAY)
40624-
ret = BUFFER_E;
40648+
if (ret == 0 && mp_toradix(m, (char*)dcrl->crlNumber,
40649+
MP_RADIX_HEX) != MP_OKAY)
40650+
ret = BUFFER_E;
4062540651

40626-
if (ret == 0) {
40627-
dcrl->crlNumberSet = 1;
40628-
}
40652+
if (ret == 0) {
40653+
dcrl->crlNumberSet = 1;
40654+
}
4062940655

40630-
mp_free(m);
40631-
FREE_MP_INT_SIZE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40656+
mp_free(m);
40657+
FREE_MP_INT_SIZE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40658+
}
4063240659
}
4063340660
/* TODO: check criticality */
4063440661
/* Move index on to next extension. */

0 commit comments

Comments
 (0)