Skip to content

Commit 2a40b7b

Browse files
t8mmattcaswell
authored andcommitted
check_chain_extensions: Do not override error return value by check_curve
The X509_V_FLAG_X509_STRICT flag enables additional security checks of the certificates present in a certificate chain. It is not set by default. Starting from OpenSSL version 1.1.1h a check to disallow certificates with explicitly encoded elliptic curve parameters in the chain was added to the strict checks. An error in the implementation of this check meant that the result of a previous check to confirm that certificates in the chain are valid CA certificates was overwritten. This effectively bypasses the check that non-CA certificates must not be able to issue other certificates. If a "purpose" has been configured then a subsequent check that the certificate is consistent with that purpose also checks that it is a valid CA. Therefore where a purpose is set the certificate chain will still be rejected even when the strict flag has been used. A purpose is set by default in libssl client and server certificate verification routines, but it can be overriden by an application. Affected applications explicitly set the X509_V_FLAG_X509_STRICT verification flag and either do not set a purpose for the certificate verification or, in the case of TLS client or server applications, override the default purpose to make it not set. CVE-2021-3450 Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org>
1 parent cfd7438 commit 2a40b7b

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

crypto/x509/x509_vfy.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -524,15 +524,19 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
524524
ret = 1;
525525
break;
526526
}
527-
if ((ctx->param->flags & X509_V_FLAG_X509_STRICT) && num > 1) {
527+
if (ret > 0
528+
&& (ctx->param->flags & X509_V_FLAG_X509_STRICT) && num > 1) {
528529
/* Check for presence of explicit elliptic curve parameters */
529530
ret = check_curve(x);
530-
if (ret < 0)
531+
if (ret < 0) {
531532
ctx->error = X509_V_ERR_UNSPECIFIED;
532-
else if (ret == 0)
533+
ret = 0;
534+
} else if (ret == 0) {
533535
ctx->error = X509_V_ERR_EC_KEY_EXPLICIT_PARAMS;
536+
}
534537
}
535-
if ((x->ex_flags & EXFLAG_CA) == 0
538+
if (ret > 0
539+
&& (x->ex_flags & EXFLAG_CA) == 0
536540
&& x->ex_pathlen != -1
537541
&& (ctx->param->flags & X509_V_FLAG_X509_STRICT)) {
538542
ctx->error = X509_V_ERR_INVALID_EXTENSION;

test/verify_extra_test.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,22 @@ static int test_alt_chains_cert_forgery(void)
140140

141141
i = X509_verify_cert(sctx);
142142

143-
if (i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA) {
143+
if (i != 0 || X509_STORE_CTX_get_error(sctx) != X509_V_ERR_INVALID_CA)
144+
goto err;
145+
146+
/* repeat with X509_V_FLAG_X509_STRICT */
147+
X509_STORE_CTX_cleanup(sctx);
148+
X509_STORE_set_flags(store, X509_V_FLAG_X509_STRICT);
149+
150+
if (!X509_STORE_CTX_init(sctx, store, x, untrusted))
151+
goto err;
152+
153+
i = X509_verify_cert(sctx);
154+
155+
if (i == 0 && X509_STORE_CTX_get_error(sctx) == X509_V_ERR_INVALID_CA)
144156
/* This is the result we were expecting: Test passed */
145157
ret = 1;
146-
}
158+
147159
err:
148160
X509_STORE_CTX_free(sctx);
149161
X509_free(x);

0 commit comments

Comments
 (0)