From 2b5e5c3d08dcdd474591ac8b4fa8ecaff0a83dfb Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 26 Dec 2012 14:12:09 +0000 Subject: [PATCH] Revert incompatible OCSP_basic_verify changes. Make partial chain chekcing work with EE certificates only. Remove unneeded -trust_other option from tocsp. (Backport from HEAD) --- crypto/ocsp/ocsp_vfy.c | 72 ++++-------------------------------------- crypto/x509/x509_vfy.c | 41 ++++++++++++++++++++++++ test/tocsp | 2 +- 3 files changed, 49 insertions(+), 66 deletions(-) diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index f7cd36beb7..8a5e788d96 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -77,10 +77,8 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, { X509 *signer, *x; STACK_OF(X509) *chain = NULL; - STACK_OF(X509) *tmpchain = NULL; - X509_STORE *tmpstore = NULL; X509_STORE_CTX ctx; - int i, ret; + int i, ret = 0; ret = ocsp_find_signer(&signer, bs, certs, st, flags); if (!ret) { @@ -88,7 +86,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, goto end; } if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) - chain = certs; + flags |= OCSP_NOVERIFY; if (!(flags & OCSP_NOSIGS)) { EVP_PKEY *skey; @@ -104,59 +102,6 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, if (!(flags & OCSP_NOVERIFY)) { int init_res; - - /* If we trust the signer, we don't need to build a chain. - * (If the signer is a root certificate, X509_verify_cert() - * would fail anyway!) - */ - if (chain && chain == certs) goto verified_chain; - - /* If we trust some "other" certificates, allow partial - * chains (because some of them might be - * Intermediate CA Certificates), put them in a store and - * attempt to build a trusted chain. - */ - if ((flags & OCSP_TRUSTOTHER) && (certs != NULL)) - { - tmpstore = X509_STORE_new(); - if (!tmpstore) - { - ret = -1; - OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE); - goto end; - } - for (i = 0; i < sk_X509_num(certs); i++) - { - X509 *xother = sk_X509_value(certs, i); - if (!X509_STORE_add_cert(tmpstore, xother)) - { - ret = -1; - goto end; - } - } - - init_res = X509_STORE_CTX_init(&ctx, tmpstore, signer, NULL); - if (!init_res) - { - ret = -1; - OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,ERR_R_X509_LIB); - goto end; - } - X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); - X509_STORE_CTX_set_flags(&ctx, X509_V_FLAG_PARTIAL_CHAIN); - ret = X509_verify_cert(&ctx); - if (ret == 1) - { - chain = tmpchain = X509_STORE_CTX_get1_chain(&ctx); - X509_STORE_CTX_cleanup(&ctx); - goto verified_chain; - } - X509_STORE_CTX_cleanup(&ctx); - } - - /* Attempt to build a chain up to a Root Certificate in the - * trust store provided by the caller. - */ if(flags & OCSP_NOCHAIN) init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL); else @@ -170,18 +115,16 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); ret = X509_verify_cert(&ctx); - chain = tmpchain = X509_STORE_CTX_get1_chain(&ctx); + chain = X509_STORE_CTX_get1_chain(&ctx); X509_STORE_CTX_cleanup(&ctx); - if (ret <= 0) + if (ret <= 0) { i = X509_STORE_CTX_get_error(&ctx); OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,OCSP_R_CERTIFICATE_VERIFY_ERROR); ERR_add_error_data(2, "Verify error:", X509_verify_cert_error_string(i)); - goto end; - } - - verified_chain: + goto end; + } if(flags & OCSP_NOCHECKS) { ret = 1; @@ -212,8 +155,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, end: - if(tmpchain) sk_X509_pop_free(tmpchain, X509_free); - if(tmpstore) X509_STORE_free(tmpstore); + if(chain) sk_X509_pop_free(chain, X509_free); return ret; } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index de075267bc..1b3c62ef7d 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -151,6 +151,32 @@ static int x509_subject_cmp(X509 **a, X509 **b) } #endif +/* Given a certificate try and find an exact match in the store */ + +static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) + { + STACK_OF(X509) *certs; + X509 *xtmp; + int i; + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) + return NULL; + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) + { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) + break; + } + if (i < sk_X509_num(certs)) + CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509); + else + xtmp = NULL; + sk_X509_pop_free(certs, X509_free); + return xtmp; + } + int X509_verify_cert(X509_STORE_CTX *ctx) { X509 *x,*xtmp,*chain_ss=NULL; @@ -724,6 +750,19 @@ static int check_trust(X509_STORE_CTX *ctx) { if (ctx->last_untrusted < sk_X509_num(ctx->chain)) return X509_TRUST_TRUSTED; + if (sk_X509_num(ctx->chain) == 1) + { + X509 *mx; + x = sk_X509_value(ctx->chain, 0); + mx = lookup_cert_match(ctx, x); + if (mx) + { + (void)sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->last_untrusted = 0; + return X509_TRUST_TRUSTED; + } + } } /* If no trusted certs in chain at all return untrusted and @@ -1657,6 +1696,8 @@ static int internal_verify(X509_STORE_CTX *ctx) xs=xi; else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN && n == 0) + return check_cert_time(ctx, xi); if (n <= 0) { ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; diff --git a/test/tocsp b/test/tocsp index 143453cf05..5fc291ca6e 100644 --- a/test/tocsp +++ b/test/tocsp @@ -8,7 +8,7 @@ check_time="-attime 1355875200" test_ocsp () { $cmd base64 -d -in $ocspdir/$1 | \ - $cmd ocsp -respin - -partial_chain -trust_other $check_time \ + $cmd ocsp -respin - -partial_chain $check_time \ -CAfile $ocspdir/$2 -verify_other $ocspdir/$2 -CApath /dev/null [ $? != $3 ] && exit 1 } -- 2.25.1