Require non-NULL store in X509_STORE_CTX_init.
X509_STORE_CTX_init is documented upstream to allow a NULL store and has
logic to account for it. However, attempting to use such an
X509_STORE_CTX crashes in X509_verify_cert due to the
additional_untrusted logic we added.
Moreover, before that change, it still crashes because
X509_STORE_CTX_get1_issuer (the default get_issuer hook) assumes
ctx->ctx (the store) is non-null. This was also true in upstream but
later fixed in https://github.com/openssl/openssl/pull/6001. However,
without a store, there is no trust anchor, so this is not very useful.
Reject NULL stores in X509_STORE_CTX_init and remove the logic allowing
for a NULL one.
Thanks to Danny Halawi for catching this.
Update-Note: X509_STORE_CTX_init will now fail when the store is NULL,
rather than report success, only to crash later in X509_verify_cert.
Breakage should thus be limited to code which was passing in a NULL
store but never used the resulting X509_STORE_CTX.
Change-Id: I9db0289612cc245a8d62d6fa647d6b56b2daabda
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/42728
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index d71dee9..426e181 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -2445,3 +2445,13 @@
EXPECT_FALSE(CertFromPEM(kV1WithIssuerUniqueIDPEM));
EXPECT_FALSE(CertFromPEM(kV1WithSubjectUniqueIDPEM));
}
+
+// Unlike upstream OpenSSL, we require a non-null store in
+// |X509_STORE_CTX_init|.
+TEST(X509Test, NullStore) {
+ bssl::UniquePtr<X509> leaf(CertFromPEM(kLeafPEM));
+ ASSERT_TRUE(leaf);
+ bssl::UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
+ ASSERT_TRUE(ctx);
+ EXPECT_FALSE(X509_STORE_CTX_init(ctx.get(), nullptr, leaf.get(), nullptr));
+}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 9839b95..a997202 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -2307,8 +2307,6 @@
int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
STACK_OF(X509) *chain)
{
- int ret = 1;
-
X509_STORE_CTX_zero(ctx);
ctx->ctx = store;
ctx->cert = x509;
@@ -2316,78 +2314,74 @@
CRYPTO_new_ex_data(&ctx->ex_data);
+ if (store == NULL) {
+ OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+ goto err;
+ }
+
ctx->param = X509_VERIFY_PARAM_new();
if (!ctx->param)
goto err;
/*
- * Inherit callbacks and flags from X509_STORE if not set use defaults.
+ * Inherit callbacks and flags from X509_STORE.
*/
- if (store)
- ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
- else
- ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
+ ctx->verify_cb = store->verify_cb;
+ ctx->cleanup = store->cleanup;
- if (store) {
- ctx->verify_cb = store->verify_cb;
- ctx->cleanup = store->cleanup;
- } else
- ctx->cleanup = 0;
-
- if (ret)
- ret = X509_VERIFY_PARAM_inherit(ctx->param,
- X509_VERIFY_PARAM_lookup("default"));
-
- if (ret == 0)
+ if (!X509_VERIFY_PARAM_inherit(ctx->param, store->param) ||
+ !X509_VERIFY_PARAM_inherit(ctx->param,
+ X509_VERIFY_PARAM_lookup("default"))) {
goto err;
+ }
- if (store && store->check_issued)
+ if (store->check_issued)
ctx->check_issued = store->check_issued;
else
ctx->check_issued = check_issued;
- if (store && store->get_issuer)
+ if (store->get_issuer)
ctx->get_issuer = store->get_issuer;
else
ctx->get_issuer = X509_STORE_CTX_get1_issuer;
- if (store && store->verify_cb)
+ if (store->verify_cb)
ctx->verify_cb = store->verify_cb;
else
ctx->verify_cb = null_callback;
- if (store && store->verify)
+ if (store->verify)
ctx->verify = store->verify;
else
ctx->verify = internal_verify;
- if (store && store->check_revocation)
+ if (store->check_revocation)
ctx->check_revocation = store->check_revocation;
else
ctx->check_revocation = check_revocation;
- if (store && store->get_crl)
+ if (store->get_crl)
ctx->get_crl = store->get_crl;
else
ctx->get_crl = NULL;
- if (store && store->check_crl)
+ if (store->check_crl)
ctx->check_crl = store->check_crl;
else
ctx->check_crl = check_crl;
- if (store && store->cert_crl)
+ if (store->cert_crl)
ctx->cert_crl = store->cert_crl;
else
ctx->cert_crl = cert_crl;
- if (store && store->lookup_certs)
+ if (store->lookup_certs)
ctx->lookup_certs = store->lookup_certs;
else
ctx->lookup_certs = X509_STORE_get1_certs;
- if (store && store->lookup_crls)
+ if (store->lookup_crls)
ctx->lookup_crls = store->lookup_crls;
else
ctx->lookup_crls = X509_STORE_get1_crls;