diff options
author | Viktor Dukhovni <openssl-users@dukhovni.org> | 2022-12-13 08:49:13 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2023-02-07 17:05:10 +0100 |
commit | 748f478f814bc8e418542c68599ec7dbcbac97b2 (patch) | |
tree | 03b84aeab075c441d56dcfcf7627f006d5b7d9b7 | |
parent | cded5d05253df6eb29e025ab25d763805493479a (diff) |
Fix type confusion in nc_match_single()
This function assumes that if the "gen" is an OtherName, then the "base"
is a rfc822Name constraint. This assumption is not true in all cases.
If the end-entity certificate contains an OtherName SAN of any type besides
SmtpUtf8Mailbox and the CA certificate contains a name constraint of
OtherName (of any type), then "nc_email_eai" will be invoked, with the
OTHERNAME "base" being incorrectly interpreted as a ASN1_IA5STRING.
Reported by Corey Bonnell from Digicert.
CVE-2022-4203
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
-rw-r--r-- | crypto/x509/v3_ncons.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/crypto/x509/v3_ncons.c b/crypto/x509/v3_ncons.c index 8c7aee32a2..ba8141b8c1 100644 --- a/crypto/x509/v3_ncons.c +++ b/crypto/x509/v3_ncons.c @@ -34,7 +34,8 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); -static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen); +static int nc_match_single(int effective_type, GENERAL_NAME *sub, + GENERAL_NAME *gen); static int nc_dn(const X509_NAME *sub, const X509_NAME *nm); static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); @@ -481,14 +482,17 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) { GENERAL_SUBTREE *sub; int i, r, match = 0; + int effective_type = gen->type; + /* * We need to compare not gen->type field but an "effective" type because * the otherName field may contain EAI email address treated specially * according to RFC 8398, section 6 */ - int effective_type = ((gen->type == GEN_OTHERNAME) && - (OBJ_obj2nid(gen->d.otherName->type_id) == - NID_id_on_SmtpUTF8Mailbox)) ? GEN_EMAIL : gen->type; + if (effective_type == GEN_OTHERNAME && + (OBJ_obj2nid(gen->d.otherName->type_id) == NID_id_on_SmtpUTF8Mailbox)) { + effective_type = GEN_EMAIL; + } /* * Permitted subtrees: if any subtrees exist of matching the type at @@ -497,7 +501,10 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); - if (effective_type != sub->base->type) + if (effective_type != sub->base->type + || (effective_type == GEN_OTHERNAME && + OBJ_cmp(gen->d.otherName->type_id, + sub->base->d.otherName->type_id) != 0)) continue; if (!nc_minmax_valid(sub)) return X509_V_ERR_SUBTREE_MINMAX; @@ -506,7 +513,7 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) continue; if (match == 0) match = 1; - r = nc_match_single(gen, sub->base); + r = nc_match_single(effective_type, gen, sub->base); if (r == X509_V_OK) match = 2; else if (r != X509_V_ERR_PERMITTED_VIOLATION) @@ -520,12 +527,15 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); - if (effective_type != sub->base->type) + if (effective_type != sub->base->type + || (effective_type == GEN_OTHERNAME && + OBJ_cmp(gen->d.otherName->type_id, + sub->base->d.otherName->type_id) != 0)) continue; if (!nc_minmax_valid(sub)) return X509_V_ERR_SUBTREE_MINMAX; - r = nc_match_single(gen, sub->base); + r = nc_match_single(effective_type, gen, sub->base); if (r == X509_V_OK) return X509_V_ERR_EXCLUDED_VIOLATION; else if (r != X509_V_ERR_PERMITTED_VIOLATION) @@ -537,15 +547,22 @@ static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) } -static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) +static int nc_match_single(int effective_type, GENERAL_NAME *gen, + GENERAL_NAME *base) { switch (gen->type) { case GEN_OTHERNAME: - /* - * We are here only when we have SmtpUTF8 name, - * so we match the value of othername with base->d.rfc822Name - */ - return nc_email_eai(gen->d.otherName->value, base->d.rfc822Name); + switch (effective_type) { + case GEN_EMAIL: + /* + * We are here only when we have SmtpUTF8 name, + * so we match the value of othername with base->d.rfc822Name + */ + return nc_email_eai(gen->d.otherName->value, base->d.rfc822Name); + + default: + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; + } case GEN_DIRNAME: return nc_dn(gen->d.directoryName, base->d.directoryName); |