diff --git a/tests/api/test_asn.c b/tests/api/test_asn.c index 1d6f1e571a..0f713ca8cc 100644 --- a/tests/api/test_asn.c +++ b/tests/api/test_asn.c @@ -1577,6 +1577,60 @@ int test_DecodeCertExtensions_dup_certpol(void) return EXPECT_RESULT(); } +/* RFC 5280 4.2.1.4 defines certificatePolicies as SEQUENCE SIZE (1..MAX) OF + * PolicyInformation, so an empty SEQUENCE must be rejected instead of being + * accepted as zero policies. */ +int test_DecodeCertExtensions_empty_certpol(void) +{ + EXPECT_DECLS; +#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_CERTS) && !defined(NO_ASN) + /* certificatePolicies extnValue carrying no PolicyInformation. */ + static const byte emptyPolicy[] = { + 0x30, 0x00 /* certificatePolicies SEQUENCE */ + }; + DecodedCert cert; + int isUnknown = 0; + + wc_InitDecodedCert(&cert, emptyPolicy, (word32)sizeof(emptyPolicy), NULL); + + ExpectIntEQ(DecodeExtensionType(emptyPolicy, (word32)sizeof(emptyPolicy), + CERT_POLICY_OID, 0, &cert, &isUnknown), + WC_NO_ERR_TRACE(ASN_PARSE_E)); + + wc_FreeDecodedCert(&cert); +#endif + return EXPECT_RESULT(); +} + +/* Trailing bytes after the last PolicyInformation must be rejected rather than + * skipped. */ +int test_DecodeCertExtensions_certpol_trailing_junk(void) +{ + EXPECT_DECLS; +#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)) && \ + !defined(NO_CERTS) && !defined(NO_ASN) + /* One valid PolicyInformation followed by two bytes that are not one. */ + static const byte trailingJunk[] = { + 0x30, 0x09, /* certificatePolicies SEQUENCE */ + 0x30, 0x05, /* PolicyInformation SEQUENCE */ + 0x06, 0x03, 0x2A, 0x03, 0x04,/* policyIdentifier OID 1.2.3.4 */ + 0x00, 0x00 /* trailing junk */ + }; + DecodedCert cert; + int isUnknown = 0; + + wc_InitDecodedCert(&cert, trailingJunk, (word32)sizeof(trailingJunk), NULL); + + ExpectIntEQ(DecodeExtensionType(trailingJunk, (word32)sizeof(trailingJunk), + CERT_POLICY_OID, 0, &cert, &isUnknown), + WC_NO_ERR_TRACE(ASN_PARSE_E)); + + wc_FreeDecodedCert(&cert); +#endif + return EXPECT_RESULT(); +} + int test_ParseCert_SM3wSM2_short_pubkey(void) { EXPECT_DECLS; diff --git a/tests/api/test_asn.h b/tests/api/test_asn.h index 4ac0cf3404..9dcc0d45fc 100644 --- a/tests/api/test_asn.h +++ b/tests/api/test_asn.h @@ -36,6 +36,8 @@ int test_wc_DecodeRsaPssParams(void); int test_SerialNumber0_RootCA(void); int test_DecodeAltNames_length_underflow(void); int test_DecodeCertExtensions_dup_certpol(void); +int test_DecodeCertExtensions_empty_certpol(void); +int test_DecodeCertExtensions_certpol_trailing_junk(void); int test_ParseCert_SM3wSM2_short_pubkey(void); int test_ParseCert_dnBufferBoundary(void); int test_wc_DecodeObjectId(void); @@ -61,6 +63,8 @@ int test_wc_AsnFeatureCoverage(void); TEST_DECL_GROUP("asn", test_SerialNumber0_RootCA), \ TEST_DECL_GROUP("asn", test_DecodeAltNames_length_underflow), \ TEST_DECL_GROUP("asn", test_DecodeCertExtensions_dup_certpol), \ + TEST_DECL_GROUP("asn", test_DecodeCertExtensions_empty_certpol), \ + TEST_DECL_GROUP("asn", test_DecodeCertExtensions_certpol_trailing_junk), \ TEST_DECL_GROUP("asn", test_ParseCert_SM3wSM2_short_pubkey), \ TEST_DECL_GROUP("asn", test_ParseCert_dnBufferBoundary), \ TEST_DECL_GROUP("asn", test_wc_DecodeObjectId), \ diff --git a/tests/unit-mcdc/test_asn_ext_whitebox.c b/tests/unit-mcdc/test_asn_ext_whitebox.c index 7755c6a61e..fa6f064a16 100644 --- a/tests/unit-mcdc/test_asn_ext_whitebox.c +++ b/tests/unit-mcdc/test_asn_ext_whitebox.c @@ -1288,7 +1288,8 @@ static void wb_decode_policy_oid(void) /* ------------------------------------------------------------------------- * * Section 17: DecodeCertPolicy() (static, called directly). * Gated on WOLFSSL_SEP || WOLFSSL_CERT_EXT, same as the source. - * :21346 while ((ret==0) && (idxdeviceType==NULL (WOLFSSL_SEP) * :21401 duplicate-OID scan loop (WOLFSSL_CERT_EXT, !WOLFSSL_DUP_CERTPOL) * MAX_CERTPOL_NB is 2, so three policies exercise the count limit. @@ -1338,10 +1339,11 @@ static void wb_decode_cert_policy(void) /* Zero policies. */ static const byte noPolicies[] = { 0x30, 0x00 }; - WB_NOTE("DecodeCertPolicy(): zero policies (loop false via idxextCertPoliciesNb < MAX_CERTPOL_NB) #endif diff --git a/wolfcrypt/src/asn_orig.c b/wolfcrypt/src/asn_orig.c index 655b9f0193..074bdeac0b 100644 --- a/wolfcrypt/src/asn_orig.c +++ b/wolfcrypt/src/asn_orig.c @@ -4254,7 +4254,8 @@ static int DecodeCertPolicy(const byte* input, word32 sz, DecodedCert* cert) #endif } idx += (word32)policy_length; - } while((int)idx < total_length + /* idx is an offset into input, so it is bound by sz. */ + } while(idx < sz #ifdef WOLFSSL_CERT_EXT && cert->extCertPoliciesNb < MAX_CERTPOL_NB #endif