mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-07 09:30:48 +02:00
Reject duplicate certificatePolicies extension in WOLFSSL_CERT_EXT builds
DecodeExtensionType() guarded the certificatePolicies duplicate check (VERIFY_AND_SET_OID) under WOLFSSL_SEP only, because the extCertPolicySet tracking bit was SEP-only. In a WOLFSSL_CERT_EXT-without-WOLFSSL_SEP build a cert with two certificatePolicies extensions was accepted and the second silently overwrote the first (RFC 5280 4.2 forbids repeats). Make the bit and the guard available under WOLFSSL_CERT_EXT too, matching every other non-repeatable extension. Add test_DecodeCertExtensions_dup_certpol (DecodeExtensionType now WOLFSSL_TEST_VIS).
This commit is contained in:
@@ -1495,6 +1495,46 @@ int test_DecodeAltNames_length_underflow(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* A certificate must not carry two certificatePolicies extensions
|
||||
* (non-repeatable per RFC 5280 4.2). DecodeCertExtensions calls
|
||||
* DecodeExtensionType once per extension; with strict ASN.1 (the default) a
|
||||
* second certificatePolicies extension must be rejected (ASN_OBJECT_ID_E)
|
||||
* rather than silently overwriting the first - which happened in
|
||||
* WOLFSSL_CERT_EXT builds without WOLFSSL_SEP before the duplicate guard was
|
||||
* extended to cover them. */
|
||||
int test_DecodeCertExtensions_dup_certpol(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)) && \
|
||||
!defined(WOLFSSL_NO_ASN_STRICT) && !defined(NO_CERTS) && !defined(NO_ASN)
|
||||
/* Minimal certificatePolicies extnValue: SEQUENCE OF PolicyInformation
|
||||
* with one policyIdentifier OID 1.2.3.4 (encoded 2A 03 04). */
|
||||
static const byte policy[] = {
|
||||
0x30, 0x07, /* certificatePolicies SEQUENCE */
|
||||
0x30, 0x05, /* PolicyInformation SEQUENCE */
|
||||
0x06, 0x03, 0x2A, 0x03, 0x04 /* policyIdentifier OID 1.2.3.4 */
|
||||
};
|
||||
DecodedCert cert;
|
||||
int isUnknown = 0;
|
||||
|
||||
/* DecodeExtensionType only needs an initialized DecodedCert for its
|
||||
* bit-fields and policy storage; the source buffer is never parsed here,
|
||||
* so any non-NULL pointer/size suffices. */
|
||||
wc_InitDecodedCert(&cert, policy, (word32)sizeof(policy), NULL);
|
||||
|
||||
/* First certificatePolicies extension: accepted. */
|
||||
ExpectIntEQ(DecodeExtensionType(policy, (word32)sizeof(policy),
|
||||
CERT_POLICY_OID, 0, &cert, &isUnknown), 0);
|
||||
/* Duplicate certificatePolicies extension: rejected as non-repeatable. */
|
||||
ExpectIntEQ(DecodeExtensionType(policy, (word32)sizeof(policy),
|
||||
CERT_POLICY_OID, 0, &cert, &isUnknown),
|
||||
WC_NO_ERR_TRACE(ASN_OBJECT_ID_E));
|
||||
|
||||
wc_FreeDecodedCert(&cert);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
int test_ParseCert_SM3wSM2_short_pubkey(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
|
||||
@@ -35,6 +35,7 @@ int test_wolfssl_local_MatchUriNameConstraint(void);
|
||||
int test_wc_DecodeRsaPssParams(void);
|
||||
int test_SerialNumber0_RootCA(void);
|
||||
int test_DecodeAltNames_length_underflow(void);
|
||||
int test_DecodeCertExtensions_dup_certpol(void);
|
||||
int test_ParseCert_SM3wSM2_short_pubkey(void);
|
||||
int test_wc_DecodeObjectId(void);
|
||||
int test_ToTraditional_ex_handcrafted(void);
|
||||
@@ -54,6 +55,7 @@ int test_ToTraditional_ex_mldsa_bad_params(void);
|
||||
TEST_DECL_GROUP("asn", test_wc_DecodeRsaPssParams), \
|
||||
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_ParseCert_SM3wSM2_short_pubkey), \
|
||||
TEST_DECL_GROUP("asn", test_wc_DecodeObjectId), \
|
||||
TEST_DECL_GROUP("asn", test_ToTraditional_ex_handcrafted), \
|
||||
|
||||
+11
-4
@@ -21036,8 +21036,9 @@ static int DecodeAltSigVal(const byte* input, int sz, DecodedCert* cert)
|
||||
* @return MEMORY_E on dynamic memory allocation failure.
|
||||
* @return Other negative values on error.
|
||||
*/
|
||||
int DecodeExtensionType(const byte* input, word32 length, word32 oid,
|
||||
byte critical, DecodedCert* cert, int *isUnknownExt)
|
||||
WOLFSSL_TEST_VIS int DecodeExtensionType(const byte* input, word32 length,
|
||||
word32 oid, byte critical,
|
||||
DecodedCert* cert, int *isUnknownExt)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 idx = 0;
|
||||
@@ -21137,11 +21138,17 @@ int DecodeExtensionType(const byte* input, word32 length, word32 oid,
|
||||
|
||||
/* Certificate policies. */
|
||||
case CERT_POLICY_OID:
|
||||
#ifdef WOLFSSL_SEP
|
||||
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
|
||||
/* certificatePolicies is non-repeatable (RFC 5280 4.2). In strict
|
||||
* mode (the default; VERIFY_AND_SET_OID is a no-op under
|
||||
* WOLFSSL_NO_ASN_STRICT, like every other extension) reject a
|
||||
* duplicate regardless of WOLFSSL_SEP - otherwise the second one
|
||||
* silently overwrites the first (DecodeCertPolicy resets
|
||||
* extCertPoliciesNb), a policy-authorization confusion. */
|
||||
VERIFY_AND_SET_OID(cert->extCertPolicySet);
|
||||
#ifdef WOLFSSL_SEP
|
||||
cert->extCertPolicyCrit = critical ? 1 : 0;
|
||||
#endif
|
||||
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
|
||||
if (DecodeCertPolicy(input, length, cert) < 0) {
|
||||
ret = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
@@ -2089,7 +2089,7 @@ struct DecodedCert {
|
||||
WC_BITFIELD extSubjAltNameSet:1;
|
||||
WC_BITFIELD inhibitAnyOidSet:1;
|
||||
WC_BITFIELD selfSigned:1; /* Indicates subject and issuer are same */
|
||||
#ifdef WOLFSSL_SEP
|
||||
#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT)
|
||||
WC_BITFIELD extCertPolicySet:1;
|
||||
#endif
|
||||
WC_BITFIELD extCRLdistCrit:1;
|
||||
@@ -2369,6 +2369,7 @@ typedef enum MimeStatus
|
||||
#define FreeSigner wc_FreeSigner
|
||||
#define AllocDer wc_AllocDer
|
||||
#define FreeDer wc_FreeDer
|
||||
#define DecodeExtensionType wc_DecodeExtensionType
|
||||
#endif /* WOLFSSL_API_PREFIX_MAP */
|
||||
|
||||
WOLFSSL_LOCAL int HashIdAlg(word32 oidSum);
|
||||
@@ -2412,9 +2413,9 @@ WOLFSSL_LOCAL int DecodePolicyOID(char *out, word32 outSz, const byte *in,
|
||||
word32 inSz);
|
||||
WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz,
|
||||
const char *in, void* heap);
|
||||
WOLFSSL_LOCAL int DecodeExtensionType(const byte* input, word32 length,
|
||||
word32 oid, byte critical,
|
||||
DecodedCert* cert, int *isUnknownExt);
|
||||
WOLFSSL_TEST_VIS int DecodeExtensionType(const byte* input, word32 length,
|
||||
word32 oid, byte critical,
|
||||
DecodedCert* cert, int *isUnknownExt);
|
||||
WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
|
||||
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
|
||||
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SMALL_CERT_VERIFY)
|
||||
|
||||
Reference in New Issue
Block a user