aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/x509
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-06-25 09:47:15 +0100
committerMatt Caswell <matt@openssl.org>2015-07-07 21:57:11 +0100
commitaae41f8c54257d9fa6904d3a9aa09c5db6cefd0d (patch)
treedfdf107f25fc6355b6427091b8a178854c091d3b /crypto/x509
parent593e9c638c58e1a510c519db0d024527113330f3 (diff)
downloadopenssl-aae41f8c54257d9fa6904d3a9aa09c5db6cefd0d.tar.gz
Reject calls to X509_verify_cert that have not been reinitialised
The function X509_verify_cert checks the value of |ctx->chain| at the beginning, and if it is NULL then it initialises it, along with the value of ctx->untrusted. The normal way to use X509_verify_cert() is to first call X509_STORE_CTX_init(); then set up various parameters etc; then call X509_verify_cert(); then check the results; and finally call X509_STORE_CTX_cleanup(). The initial call to X509_STORE_CTX_init() sets |ctx->chain| to NULL. The only place in the OpenSSL codebase where |ctx->chain| is set to anything other than a non NULL value is in X509_verify_cert itself. Therefore the only ways that |ctx->chain| could be non NULL on entry to X509_verify_cert is if one of the following occurs: 1) An application calls X509_verify_cert() twice without re-initialising in between. 2) An application reaches inside the X509_STORE_CTX structure and changes the value of |ctx->chain| directly. With regards to the second of these, we should discount this - it should not be supported to allow this. With regards to the first of these, the documentation is not exactly crystal clear, but the implication is that you must call X509_STORE_CTX_init() before each call to X509_verify_cert(). If you fail to do this then, at best, the results would be undefined. Calling X509_verify_cert() with |ctx->chain| set to a non NULL value is likely to have unexpected results, and could be dangerous. This commit changes the behaviour of X509_verify_cert() so that it causes an error if |ctx->chain| is anything other than NULL (because this indicates that we have not been initialised properly). It also clarifies the associated documentation. This is a follow up commit to CVE-2015-1793. Reviewed-by: Stephen Henson <steve@openssl.org>
Diffstat (limited to 'crypto/x509')
-rw-r--r--crypto/x509/x509_vfy.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 7a7fc59e77..7222113c68 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -193,6 +193,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
return -1;
}
+ if (ctx->chain != NULL) {
+ /*
+ * This X509_STORE_CTX has already been used to verify a cert. We
+ * cannot do another one.
+ */
+ X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return -1;
+ }
cb = ctx->verify_cb;
@@ -200,15 +208,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* first we make sure the chain we are going to build is present and that
* the first entry is in place
*/
- if (ctx->chain == NULL) {
- if (((ctx->chain = sk_X509_new_null()) == NULL) ||
- (!sk_X509_push(ctx->chain, ctx->cert))) {
- X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
- goto end;
- }
- CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509);
- ctx->last_untrusted = 1;
+ if (((ctx->chain = sk_X509_new_null()) == NULL) ||
+ (!sk_X509_push(ctx->chain, ctx->cert))) {
+ X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ goto end;
}
+ CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509);
+ ctx->last_untrusted = 1;
/* We use a temporary STACK so we can chop and hack at it */
if (ctx->untrusted != NULL