@@ -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