[openssl-commits] [openssl] master update

Rich Salz rsalz at openssl.org
Fri Apr 15 17:21:52 UTC 2016


The branch master has been updated
       via  f0e0fd51fd8307f6eae64862ad9aaea113f1177a (commit)
      from  34da11b39d2421f546ec568f355875eec353844c (commit)


- Log -----------------------------------------------------------------
commit f0e0fd51fd8307f6eae64862ad9aaea113f1177a
Author: Rich Salz <rsalz at openssl.org>
Date:   Thu Apr 14 23:59:26 2016 -0400

    Make many X509_xxx types opaque.
    
    Make X509_OBJECT, X509_STORE_CTX, X509_STORE, X509_LOOKUP,
    and X509_LOOKUP_METHOD opaque.
    Remove unused X509_CERT_FILE_CTX
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Dr. Stephen Henson <steve at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 CHANGES                                     |   5 +
 NEWS                                        |   4 +-
 apps/crl.c                                  |  24 ++--
 apps/pkcs12.c                               |  23 ++--
 apps/s_server.c                             |  28 +++--
 apps/verify.c                               |   2 +-
 apps/x509.c                                 |  13 +-
 crypto/cms/cms_smime.c                      |  19 +--
 crypto/include/internal/x509_int.h          |  82 +++++++++++++
 crypto/ocsp/ocsp_vfy.c                      |  82 ++++++++-----
 crypto/pkcs7/pk7_smime.c                    |  19 +--
 crypto/ts/ts_rsp_verify.c                   |  31 +++--
 crypto/x509/by_file.c                       |   1 +
 crypto/x509/x509_err.c                      |   2 +
 crypto/x509/x509_lcl.h                      |  65 ++++++++++
 crypto/x509/x509_lu.c                       |  33 ++++-
 crypto/x509/x509_vfy.c                      |  44 +++++--
 doc/crypto/X509_STORE_CTX_get_error.pod     |   8 +-
 doc/crypto/X509_STORE_CTX_new.pod           |  69 +++++++----
 doc/crypto/X509_STORE_CTX_set_verify_cb.pod |  12 +-
 include/openssl/ossl_typ.h                  |   6 +
 include/openssl/x509.h                      |   1 +
 include/openssl/x509_vfy.h                  | 181 +++-------------------------
 ssl/ssl_cert.c                              |  95 +++++++++------
 test/ssltest_old.c                          |  28 +++--
 util/libcrypto.num                          |  18 ++-
 26 files changed, 542 insertions(+), 353 deletions(-)

diff --git a/CHANGES b/CHANGES
index d6cfc0e..477d185 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 1.0.2g and 1.1.0  [xx XXX xxxx]
 
+  *) The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX,
+     X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD.  The unused type
+     X509_CERT_FILE_CTX was removed.
+     [Rich Salz]
+
   *) "shared" builds are now the default. To create only static libraries use
      the "no-shared" Configure option.
      [Matt Caswell]
diff --git a/NEWS b/NEWS
index 72f7579..90336bc 100644
--- a/NEWS
+++ b/NEWS
@@ -15,8 +15,8 @@
       o Support for extended master secret
       o CCM ciphersuites
       o Reworked test suite, now based on perl, Test::Harness and Test::More
-      o Various libcrypto structures made opaque including: BIGNUM, EVP_MD,
-        EVP_MD_CTX, HMAC_CTX, EVP_CIPHER and EVP_CIPHER_CTX.
+      o *Most* libcrypto and libssl structures were made opaque including:
+        <TBA>
       o libssl internal structures made opaque
       o SSLv2 support removed
       o Kerberos ciphersuite support removed
diff --git a/apps/crl.c b/apps/crl.c
index c6fc9e6..915c9ac 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -112,9 +112,9 @@ int crl_main(int argc, char **argv)
     X509_CRL *x = NULL;
     BIO *out = NULL;
     X509_STORE *store = NULL;
-    X509_STORE_CTX ctx;
+    X509_STORE_CTX *ctx = NULL;
     X509_LOOKUP *lookup = NULL;
-    X509_OBJECT xobj;
+    X509_OBJECT *xobj = NULL;
     EVP_PKEY *pkey;
     const EVP_MD *digest = EVP_sha1();
     unsigned long nmflag = 0;
@@ -243,24 +243,26 @@ int crl_main(int argc, char **argv)
         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
         if (lookup == NULL)
             goto end;
-        if (!X509_STORE_CTX_init(&ctx, store, NULL, NULL)) {
+        ctx = X509_STORE_CTX_new();
+        if (!X509_STORE_CTX_init(ctx, store, NULL, NULL)) {
             BIO_printf(bio_err, "Error initialising X509 store\n");
             goto end;
         }
 
-        i = X509_STORE_get_by_subject(&ctx, X509_LU_X509,
-                                      X509_CRL_get_issuer(x), &xobj);
-        if (i <= 0) {
+        xobj = X509_STORE_get_X509_by_subject(ctx, X509_LU_X509,
+                                              X509_CRL_get_issuer(x));
+        if (xobj == NULL) {
             BIO_printf(bio_err, "Error getting CRL issuer certificate\n");
             goto end;
         }
-        pkey = X509_get0_pubkey(xobj.data.x509);
-        X509_OBJECT_free_contents(&xobj);
+        pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj));
+        X509_OBJECT_free(xobj);
         if (!pkey) {
             BIO_printf(bio_err, "Error getting CRL issuer public key\n");
             goto end;
         }
         i = X509_CRL_verify(x, pkey);
+        EVP_PKEY_free(pkey);
         if (i < 0)
             goto end;
         if (i == 0)
@@ -388,9 +390,7 @@ int crl_main(int argc, char **argv)
         ERR_print_errors(bio_err);
     BIO_free_all(out);
     X509_CRL_free(x);
-    if (store) {
-        X509_STORE_CTX_cleanup(&ctx);
-        X509_STORE_free(store);
-    }
+    X509_STORE_CTX_free(ctx);
+    X509_STORE_free(store);
     return (ret);
 }
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index ff3cb88..406b103 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -758,21 +758,28 @@ int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass,
 static int get_cert_chain(X509 *cert, X509_STORE *store,
                           STACK_OF(X509) **chain)
 {
-    X509_STORE_CTX store_ctx;
+    X509_STORE_CTX *store_ctx = NULL;
     STACK_OF(X509) *chn = NULL;
     int i = 0;
 
-    if (!X509_STORE_CTX_init(&store_ctx, store, cert, NULL)) {
-        *chain = NULL;
-        return X509_V_ERR_UNSPECIFIED;
+    store_ctx = X509_STORE_CTX_new();
+    if (store_ctx == NULL) {
+        i =  X509_V_ERR_UNSPECIFIED;
+        goto end;
+    }
+    if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
+        i =  X509_V_ERR_UNSPECIFIED;
+        goto end;
     }
 
-    if (X509_verify_cert(&store_ctx) > 0)
-        chn = X509_STORE_CTX_get1_chain(&store_ctx);
-    else if ((i = X509_STORE_CTX_get_error(&store_ctx)) == 0)
+
+    if (X509_verify_cert(store_ctx) > 0)
+        chn = X509_STORE_CTX_get1_chain(store_ctx);
+    else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
         i = X509_V_ERR_UNSPECIFIED;
 
-    X509_STORE_CTX_cleanup(&store_ctx);
+end:
+    X509_STORE_CTX_free(store_ctx);
     *chain = chn;
     return i;
 }
diff --git a/apps/s_server.c b/apps/s_server.c
index e0aa2ae..6c8541e 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -622,8 +622,8 @@ static int cert_status_cb(SSL *s, void *arg)
     int rspderlen;
     STACK_OF(OPENSSL_STRING) *aia = NULL;
     X509 *x = NULL;
-    X509_STORE_CTX inctx;
-    X509_OBJECT obj;
+    X509_STORE_CTX *inctx = NULL;
+    X509_OBJECT *obj;
     OCSP_REQUEST *req = NULL;
     OCSP_RESPONSE *resp = NULL;
     OCSP_CERTID *id = NULL;
@@ -657,22 +657,24 @@ static int cert_status_cb(SSL *s, void *arg)
         use_ssl = srctx->use_ssl;
     }
 
-    if (!X509_STORE_CTX_init(&inctx,
+    inctx = X509_STORE_CTX_new();
+    if (inctx == NULL)
+        goto err;
+    if (!X509_STORE_CTX_init(inctx,
                              SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
                              NULL, NULL))
         goto err;
-    if (X509_STORE_get_by_subject(&inctx, X509_LU_X509,
-                                  X509_get_issuer_name(x), &obj) <= 0) {
+    obj = X509_STORE_get_X509_by_subject(inctx, X509_LU_X509,
+                                         X509_get_issuer_name(x));
+    if (obj == NULL) {
         BIO_puts(bio_err, "cert_status: Can't retrieve issuer certificate.\n");
-        X509_STORE_CTX_cleanup(&inctx);
         goto done;
     }
     req = OCSP_REQUEST_new();
     if (req == NULL)
         goto err;
-    id = OCSP_cert_to_id(NULL, x, obj.data.x509);
-    X509_free(obj.data.x509);
-    X509_STORE_CTX_cleanup(&inctx);
+    id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
+    X509_OBJECT_free(obj);
     if (!id)
         goto err;
     if (!OCSP_request_add0_id(req, id))
@@ -700,6 +702,10 @@ static int cert_status_cb(SSL *s, void *arg)
         OCSP_RESPONSE_print(bio_err, resp, 2);
     }
     ret = SSL_TLSEXT_ERR_OK;
+    goto done;
+
+ err:
+    ret = SSL_TLSEXT_ERR_ALERT_FATAL;
  done:
     if (ret != SSL_TLSEXT_ERR_OK)
         ERR_print_errors(bio_err);
@@ -712,10 +718,8 @@ static int cert_status_cb(SSL *s, void *arg)
     OCSP_CERTID_free(id);
     OCSP_REQUEST_free(req);
     OCSP_RESPONSE_free(resp);
+    X509_STORE_CTX_free(inctx);
     return ret;
- err:
-    ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-    goto done;
 }
 #endif
 
diff --git a/apps/verify.c b/apps/verify.c
index 58a48c7..fa51783 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -269,7 +269,7 @@ static int check(X509_STORE *ctx, char *file,
         goto end;
     }
     if (tchain)
-        X509_STORE_CTX_trusted_stack(csc, tchain);
+        X509_STORE_CTX_set0_trusted_stack(csc, tchain);
     if (crls)
         X509_STORE_CTX_set0_crls(csc, crls);
     i = X509_verify_cert(csc);
diff --git a/apps/x509.c b/apps/x509.c
index d8be179..6e6ee08 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -987,13 +987,14 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
 {
     int ret = 0;
     ASN1_INTEGER *bs = NULL;
-    X509_STORE_CTX xsc;
+    X509_STORE_CTX *xsc = NULL;
     EVP_PKEY *upkey;
 
     upkey = X509_get0_pubkey(xca);
     EVP_PKEY_copy_parameters(upkey, pkey);
 
-    if (!X509_STORE_CTX_init(&xsc, ctx, x, NULL)) {
+    xsc = X509_STORE_CTX_new();
+    if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
         BIO_printf(bio_err, "Error initialising X509 store\n");
         goto end;
     }
@@ -1006,9 +1007,9 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
      * NOTE: this certificate can/should be self signed, unless it was a
      * certificate request in which case it is not.
      */
-    X509_STORE_CTX_set_cert(&xsc, x);
-    X509_STORE_CTX_set_flags(&xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
-    if (!reqfile && X509_verify_cert(&xsc) <= 0)
+    X509_STORE_CTX_set_cert(xsc, x);
+    X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+    if (!reqfile && X509_verify_cert(xsc) <= 0)
         goto end;
 
     if (!X509_check_private_key(xca, pkey)) {
@@ -1047,7 +1048,7 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
         goto end;
     ret = 1;
  end:
-    X509_STORE_CTX_cleanup(&xsc);
+    X509_STORE_CTX_free(xsc);
     if (!ret)
         ERR_print_errors(bio_err);
     if (!sno)
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index e84b7e7..98054b3 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -273,21 +273,26 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
                                       STACK_OF(X509) *certs,
                                       STACK_OF(X509_CRL) *crls)
 {
-    X509_STORE_CTX ctx;
+    X509_STORE_CTX *ctx = X509_STORE_CTX_new();
     X509 *signer;
     int i, j, r = 0;
+
+    if (ctx == NULL) {
+        CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
     CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
-    if (!X509_STORE_CTX_init(&ctx, store, signer, certs)) {
+    if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, CMS_R_STORE_INIT_ERROR);
         goto err;
     }
-    X509_STORE_CTX_set_default(&ctx, "smime_sign");
+    X509_STORE_CTX_set_default(ctx, "smime_sign");
     if (crls)
-        X509_STORE_CTX_set0_crls(&ctx, crls);
+        X509_STORE_CTX_set0_crls(ctx, crls);
 
-    i = X509_verify_cert(&ctx);
+    i = X509_verify_cert(ctx);
     if (i <= 0) {
-        j = X509_STORE_CTX_get_error(&ctx);
+        j = X509_STORE_CTX_get_error(ctx);
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT,
                CMS_R_CERTIFICATE_VERIFY_ERROR);
         ERR_add_error_data(2, "Verify error:",
@@ -296,7 +301,7 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
     }
     r = 1;
  err:
-    X509_STORE_CTX_cleanup(&ctx);
+    X509_STORE_CTX_free(ctx);
     return r;
 
 }
diff --git a/crypto/include/internal/x509_int.h b/crypto/include/internal/x509_int.h
index fc032ae..ee49f2a 100644
--- a/crypto/include/internal/x509_int.h
+++ b/crypto/include/internal/x509_int.h
@@ -217,6 +217,77 @@ struct x509_st {
     CRYPTO_RWLOCK *lock;
 } /* X509 */ ;
 
+/*
+ * This is a used when verifying cert chains.  Since the gathering of the
+ * cert chain can take some time (and have to be 'retried', this needs to be
+ * kept and passed around.
+ */
+struct x509_store_ctx_st {      /* X509_STORE_CTX */
+    X509_STORE *ctx;
+    /* used when looking up certs */
+    int current_method;
+    /* The following are set by the caller */
+    /* The cert to check */
+    X509 *cert;
+    /* chain of X509s - untrusted - passed in */
+    STACK_OF(X509) *untrusted;
+    /* set of CRLs passed in */
+    STACK_OF(X509_CRL) *crls;
+    X509_VERIFY_PARAM *param;
+    /* Other info for use with get_issuer() */
+    void *other_ctx;
+    /* Callbacks for various operations */
+    /* called to verify a certificate */
+    int (*verify) (X509_STORE_CTX *ctx);
+    /* error callback */
+    int (*verify_cb) (int ok, X509_STORE_CTX *ctx);
+    /* get issuers cert from ctx */
+    int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+    /* check issued */
+    int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
+    /* Check revocation status of chain */
+    int (*check_revocation) (X509_STORE_CTX *ctx);
+    /* retrieve CRL */
+    int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
+    /* Check CRL validity */
+    int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl);
+    /* Check certificate against CRL */
+    int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
+    int (*check_policy) (X509_STORE_CTX *ctx);
+    STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
+    STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
+    int (*cleanup) (X509_STORE_CTX *ctx);
+    /* The following is built up */
+    /* if 0, rebuild chain */
+    int valid;
+    /* number of untrusted certs */
+    int num_untrusted;
+    /* chain of X509s - built up and trusted */
+    STACK_OF(X509) *chain;
+    /* Valid policy tree */
+    X509_POLICY_TREE *tree;
+    /* Require explicit policy value */
+    int explicit_policy;
+    /* When something goes wrong, this is why */
+    int error_depth;
+    int error;
+    X509 *current_cert;
+    /* cert currently being tested as valid issuer */
+    X509 *current_issuer;
+    /* current CRL */
+    X509_CRL *current_crl;
+    /* score of current CRL */
+    int current_crl_score;
+    /* Reason mask */
+    unsigned int current_reasons;
+    /* For CRL path validation: parent context */
+    X509_STORE_CTX *parent;
+    CRYPTO_EX_DATA ex_data;
+    SSL_DANE *dane;
+    /* signed via bare TA public key, rather than CA certificate */
+    int bare_ta_signed;
+};
+
 /* PKCS#8 private key info structure */
 
 struct pkcs8_priv_key_info_st {
@@ -230,3 +301,14 @@ struct X509_sig_st {
     X509_ALGOR *algor;
     ASN1_OCTET_STRING *digest;
 };
+
+struct x509_object_st {
+    /* one of the above types */
+    X509_LOOKUP_TYPE type;
+    union {
+        char *ptr;
+        X509 *x509;
+        X509_CRL *crl;
+        EVP_PKEY *pkey;
+    } data;
+};
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
index 356c797..aba623c 100644
--- a/crypto/ocsp/ocsp_vfy.c
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -82,13 +82,18 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
     X509 *signer, *x;
     STACK_OF(X509) *chain = NULL;
     STACK_OF(X509) *untrusted = NULL;
-    X509_STORE_CTX ctx;
+    X509_STORE_CTX *ctx = NULL;
     int i, ret = ocsp_find_signer(&signer, bs, certs, flags);
 
     if (!ret) {
         OCSPerr(OCSP_F_OCSP_BASIC_VERIFY,
                 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
-        goto end;
+        goto err;
+    }
+    ctx = X509_STORE_CTX_new();
+    if (ctx == NULL) {
+        OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
     }
     if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
         flags |= OCSP_NOVERIFY;
@@ -99,7 +104,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
             ret = OCSP_BASICRESP_verify(bs, skey, 0);
         if (!skey || ret <= 0) {
             OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE);
-            goto end;
+            goto err;
         }
     }
     if (!(flags & OCSP_NOVERIFY)) {
@@ -111,30 +116,28 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
             for (i = 0; i < sk_X509_num(certs); i++) {
                 if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) {
                     OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE);
-                    goto end;
+                    goto err;
                 }
             }
         } else {
             untrusted = bs->certs;
         }
-        init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted);
+        init_res = X509_STORE_CTX_init(ctx, st, signer, untrusted);
         if (!init_res) {
-            ret = -1;
             OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB);
-            goto end;
+            goto err;
         }
 
-        X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
-        ret = X509_verify_cert(&ctx);
-        chain = X509_STORE_CTX_get1_chain(&ctx);
-        X509_STORE_CTX_cleanup(&ctx);
+        X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
+        ret = X509_verify_cert(ctx);
+        chain = X509_STORE_CTX_get1_chain(ctx);
         if (ret <= 0) {
-            i = X509_STORE_CTX_get_error(&ctx);
+            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;
+            goto err;
         }
         if (flags & OCSP_NOCHECKS) {
             ret = 1;
@@ -148,7 +151,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
 
         /* If fatal error or valid match then finish */
         if (ret != 0)
-            goto end;
+            goto err;
 
         /*
          * Easy case: explicitly trusted. Get root CA and check for explicit
@@ -160,12 +163,16 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
         x = sk_X509_value(chain, sk_X509_num(chain) - 1);
         if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) {
             OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED);
-            goto end;
+            goto err;
         }
         ret = 1;
+        goto end;
     }
 
+ err:
+    ret = 0;
  end:
+    X509_STORE_CTX_free(ctx);
     sk_X509_pop_free(chain, X509_free);
     if (bs->certs && certs)
         sk_X509_free(untrusted);
@@ -367,24 +374,30 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
     X509 *signer;
     X509_NAME *nm;
     GENERAL_NAME *gen;
-    int ret;
-    X509_STORE_CTX ctx;
+    int ret = 0;
+    X509_STORE_CTX *ctx = X509_STORE_CTX_new();
+
+    if (ctx == NULL) {
+        OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
     if (!req->optionalSignature) {
         OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED);
-        return 0;
+        goto err;
     }
     gen = req->tbsRequest.requestorName;
     if (!gen || gen->type != GEN_DIRNAME) {
         OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
                 OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
-        return 0;
+        goto err;
     }
     nm = gen->d.directoryName;
     ret = ocsp_req_find_signer(&signer, req, nm, certs, flags);
     if (ret <= 0) {
         OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
                 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
-        return 0;
+        goto err;
     }
     if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
         flags |= OCSP_NOVERIFY;
@@ -394,35 +407,42 @@ int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
         ret = OCSP_REQUEST_verify(req, skey);
         if (ret <= 0) {
             OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE);
-            return 0;
+            goto err;
         }
     }
     if (!(flags & OCSP_NOVERIFY)) {
         int init_res;
         if (flags & OCSP_NOCHAIN)
-            init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL);
+            init_res = X509_STORE_CTX_init(ctx, store, signer, NULL);
         else
-            init_res = X509_STORE_CTX_init(&ctx, store, signer,
+            init_res = X509_STORE_CTX_init(ctx, store, signer,
                                            req->optionalSignature->certs);
         if (!init_res) {
             OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB);
-            return 0;
+            goto err;
         }
 
-        X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER);
-        X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST);
-        ret = X509_verify_cert(&ctx);
-        X509_STORE_CTX_cleanup(&ctx);
+        X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
+        X509_STORE_CTX_set_trust(ctx, X509_TRUST_OCSP_REQUEST);
+        ret = X509_verify_cert(ctx);
         if (ret <= 0) {
-            ret = X509_STORE_CTX_get_error(&ctx);
+            ret = X509_STORE_CTX_get_error(ctx);
             OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY,
                     OCSP_R_CERTIFICATE_VERIFY_ERROR);
             ERR_add_error_data(2, "Verify error:",
                                X509_verify_cert_error_string(ret));
-            return 0;
+            goto err;
         }
     }
-    return 1;
+    ret = 1;
+    goto end;
+
+err:
+    ret = 0;
+end:
+    X509_STORE_CTX_free(ctx);
+    return ret;
+
 }
 
 static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index 8027640..b146f68 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -257,7 +257,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     X509 *signer;
     STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
     PKCS7_SIGNER_INFO *si;
-    X509_STORE_CTX cert_ctx;
+    X509_STORE_CTX *cert_ctx = NULL;
     char *buf = NULL;
     int i, j = 0, k, ret = 0;
     BIO *p7bio = NULL;
@@ -306,26 +306,28 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
 
     /* Now verify the certificates */
 
+    cert_ctx = X509_STORE_CTX_new();
+    if (cert_ctx == NULL)
+        goto err;
     if (!(flags & PKCS7_NOVERIFY))
         for (k = 0; k < sk_X509_num(signers); k++) {
             signer = sk_X509_value(signers, k);
             if (!(flags & PKCS7_NOCHAIN)) {
-                if (!X509_STORE_CTX_init(&cert_ctx, store, signer,
+                if (!X509_STORE_CTX_init(cert_ctx, store, signer,
                                          p7->d.sign->cert)) {
                     PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
                     goto err;
                 }
-                X509_STORE_CTX_set_default(&cert_ctx, "smime_sign");
-            } else if (!X509_STORE_CTX_init(&cert_ctx, store, signer, NULL)) {
+                X509_STORE_CTX_set_default(cert_ctx, "smime_sign");
+            } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) {
                 PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
                 goto err;
             }
             if (!(flags & PKCS7_NOCRL))
-                X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
-            i = X509_verify_cert(&cert_ctx);
+                X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl);
+            i = X509_verify_cert(cert_ctx);
             if (i <= 0)
-                j = X509_STORE_CTX_get_error(&cert_ctx);
-            X509_STORE_CTX_cleanup(&cert_ctx);
+                j = X509_STORE_CTX_get_error(cert_ctx);
             if (i <= 0) {
                 PKCS7err(PKCS7_F_PKCS7_VERIFY,
                          PKCS7_R_CERTIFICATE_VERIFY_ERROR);
@@ -404,6 +406,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     ret = 1;
 
  err:
+    X509_STORE_CTX_free(cert_ctx);
     OPENSSL_free(buf);
     if (tmpin == indata) {
         if (indata)
diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c
index e6e213a..89b86e1 100644
--- a/crypto/ts/ts_rsp_verify.c
+++ b/crypto/ts/ts_rsp_verify.c
@@ -211,27 +211,36 @@ int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
 static int ts_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted,
                           X509 *signer, STACK_OF(X509) **chain)
 {
-    X509_STORE_CTX cert_ctx;
+    X509_STORE_CTX *cert_ctx = NULL;
     int i;
-    int ret = 1;
+    int ret = 0;
 
     *chain = NULL;
-    if (!X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted))
-        return 0;
-    X509_STORE_CTX_set_purpose(&cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN);
-    i = X509_verify_cert(&cert_ctx);
+    cert_ctx = X509_STORE_CTX_new();
+    if (cert_ctx == NULL) {
+        TSerr(TS_F_TS_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted))
+        goto end;
+    X509_STORE_CTX_set_purpose(cert_ctx, X509_PURPOSE_TIMESTAMP_SIGN);
+    i = X509_verify_cert(cert_ctx);
     if (i <= 0) {
-        int j = X509_STORE_CTX_get_error(&cert_ctx);
+        int j = X509_STORE_CTX_get_error(cert_ctx);
         TSerr(TS_F_TS_VERIFY_CERT, TS_R_CERTIFICATE_VERIFY_ERROR);
         ERR_add_error_data(2, "Verify error:",
                            X509_verify_cert_error_string(j));
-        ret = 0;
-    } else {
-        *chain = X509_STORE_CTX_get1_chain(&cert_ctx);
+        goto err;
     }
+    *chain = X509_STORE_CTX_get1_chain(cert_ctx);
+    ret = 1;
+    goto end;
 
-    X509_STORE_CTX_cleanup(&cert_ctx);
+err:
+    ret = 0;
 
+end:
+    X509_STORE_CTX_free(cert_ctx);
     return ret;
 }
 
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index 51d642d..eea7a7e 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -64,6 +64,7 @@
 #include <openssl/buffer.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
+#include "x509_lcl.h"
 
 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                         long argl, char **ret);
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index 90a22de..d140d52 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -126,6 +126,8 @@ static ERR_STRING_DATA X509_str_functs[] = {
     {ERR_FUNC(X509_F_X509_STORE_CTX_NEW), "X509_STORE_CTX_new"},
     {ERR_FUNC(X509_F_X509_STORE_CTX_PURPOSE_INHERIT),
      "X509_STORE_CTX_purpose_inherit"},
+    {ERR_FUNC(X509_F_X509_STORE_GET_X509_BY_SUBJECT),
+     "X509_STORE_get_X509_by_subject"},
     {ERR_FUNC(X509_F_X509_TO_X509_REQ), "X509_to_X509_REQ"},
     {ERR_FUNC(X509_F_X509_TRUST_ADD), "X509_TRUST_add"},
     {ERR_FUNC(X509_F_X509_TRUST_SET), "X509_TRUST_set"},
diff --git a/crypto/x509/x509_lcl.h b/crypto/x509/x509_lcl.h
index 603c177..db98a10 100644
--- a/crypto/x509/x509_lcl.h
+++ b/crypto/x509/x509_lcl.h
@@ -115,6 +115,71 @@ struct x509_crl_method_st {
     int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
 };
 
+struct x509_lookup_method_st {
+    const char *name;
+    int (*new_item) (X509_LOOKUP *ctx);
+    void (*free) (X509_LOOKUP *ctx);
+    int (*init) (X509_LOOKUP *ctx);
+    int (*shutdown) (X509_LOOKUP *ctx);
+    int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+                 char **ret);
+    int (*get_by_subject) (X509_LOOKUP *ctx, int type, X509_NAME *name,
+                           X509_OBJECT *ret);
+    int (*get_by_issuer_serial) (X509_LOOKUP *ctx, int type, X509_NAME *name,
+                                 ASN1_INTEGER *serial, X509_OBJECT *ret);
+    int (*get_by_fingerprint) (X509_LOOKUP *ctx, int type,
+                               unsigned char *bytes, int len,
+                               X509_OBJECT *ret);
+    int (*get_by_alias) (X509_LOOKUP *ctx, int type, char *str, int len,
+                         X509_OBJECT *ret);
+};
+
+/* This is the functions plus an instance of the local variables. */
+struct x509_lookup_st {
+    int init;                   /* have we been started */
+    int skip;                   /* don't use us. */
+    X509_LOOKUP_METHOD *method; /* the functions */
+    char *method_data;          /* method data */
+    X509_STORE *store_ctx;      /* who owns us */
+};
+
+/*
+ * This is used to hold everything.  It is used for all certificate
+ * validation.  Once we have a certificate chain, the 'verify' function is
+ * then called to actually check the cert chain.
+ */
+struct x509_store_st {
+    /* The following is a cache of trusted certs */
+    int cache;                  /* if true, stash any hits */
+    STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */
+    /* These are external lookup methods */
+    STACK_OF(X509_LOOKUP) *get_cert_methods;
+    X509_VERIFY_PARAM *param;
+    /* Callbacks for various operations */
+    /* called to verify a certificate */
+    int (*verify) (X509_STORE_CTX *ctx);
+    /* error callback */
+    int (*verify_cb) (int ok, X509_STORE_CTX *ctx);
+    /* get issuers cert from ctx */
+    int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
+    /* check issued */
+    int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
+    /* Check revocation status of chain */
+    int (*check_revocation) (X509_STORE_CTX *ctx);
+    /* retrieve CRL */
+    int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
+    /* Check CRL validity */
+    int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl);
+    /* Check certificate against CRL */
+    int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
+    STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
+    STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
+    int (*cleanup) (X509_STORE_CTX *ctx);
+    CRYPTO_EX_DATA ex_data;
+    int references;
+    CRYPTO_RWLOCK *lock;
+};
+
 typedef struct lookup_dir_hashes_st BY_DIR_HASH;
 typedef struct lookup_dir_entry_st BY_DIR_ENTRY;
 DEFINE_STACK_OF(BY_DIR_HASH)
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index f9802c5..b822966 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -294,6 +294,23 @@ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
     }
 }
 
+X509_OBJECT *X509_STORE_get_X509_by_subject(X509_STORE_CTX *vs, int type,
+                                                  X509_NAME *name)
+{
+    X509_OBJECT *ret;
+
+    ret = OPENSSL_malloc(sizeof (*ret));
+    if (ret == NULL) {
+        X509err(X509_F_X509_STORE_GET_X509_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    if (!X509_STORE_get_by_subject(vs, type, name, ret)) {
+        OPENSSL_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
                               X509_NAME *name, X509_OBJECT *ret)
 {
@@ -414,9 +431,22 @@ void X509_OBJECT_up_ref_count(X509_OBJECT *a)
     }
 }
 
+X509 *X509_OBJECT_get0_X509(X509_OBJECT *a)
+{
+    return a->data.x509;
+}
+
+void X509_OBJECT_free(X509_OBJECT *a)
+{
+    if (a == NULL)
+        return;
+    X509_OBJECT_free_contents(a);
+    OPENSSL_free(a);
+}
+
 void X509_OBJECT_free_contents(X509_OBJECT *a)
 {
-    if (!a)
+    if (a == NULL)
         return;
     switch (a->type) {
     default:
@@ -613,6 +643,7 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
     X509_NAME *xn;
     X509_OBJECT obj, *pobj;
     int i, ok, idx, ret;
+
     *issuer = NULL;
     xn = X509_get_issuer_name(x);
     ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 2c3efdd..312b112 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1994,7 +1994,7 @@ X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
     return ctx->current_cert;
 }
 
-STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
+STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx)
 {
     return ctx->chain;
 }
@@ -2026,11 +2026,6 @@ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
     ctx->cert = x;
 }
 
-void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
-{
-    ctx->untrusted = sk;
-}
-
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
 {
     ctx->crls = sk;
@@ -2278,8 +2273,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
  * Set alternative lookup method: just a STACK of trusted certificates. This
  * avoids X509_STORE nastiness where it isn't needed.
  */
-
-void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
+void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
     ctx->other_ctx = sk;
     ctx->get_issuer = get_issuer_sk;
@@ -2329,11 +2323,43 @@ void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
 }
 
 void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
-                                  int (*verify_cb) (int, X509_STORE_CTX *))
+                                  X509_STORE_CTX_verify_cb verify_cb)
 {
     ctx->verify_cb = verify_cb;
 }
 
+X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx)
+{
+    return ctx->verify_cb;
+}
+
+X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx)
+{
+    return ctx->cert;
+}
+
+STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
+{
+    return ctx->untrusted;
+}
+
+void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
+{
+    sk_X509_pop_free(ctx->chain, X509_free);
+    ctx->chain = sk;
+}
+
+void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
+                               X509_STORE_CTX_verify verify)
+{
+    ctx->verify = verify;
+}
+
+X509_STORE_CTX_verify X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx)
+{
+    return ctx->verify;
+}
+
 X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
 {
     return ctx->tree;
diff --git a/doc/crypto/X509_STORE_CTX_get_error.pod b/doc/crypto/X509_STORE_CTX_get_error.pod
index 75be453..1cc6bb5 100644
--- a/doc/crypto/X509_STORE_CTX_get_error.pod
+++ b/doc/crypto/X509_STORE_CTX_get_error.pod
@@ -2,7 +2,10 @@
 
 =head1 NAME
 
-X509_STORE_CTX_get_error, X509_STORE_CTX_set_error, X509_STORE_CTX_get_error_depth, X509_STORE_CTX_get_current_cert, X509_STORE_CTX_get1_chain, X509_verify_cert_error_string - get or set certificate verification status information
+X509_STORE_CTX_get_error, X509_STORE_CTX_set_error,
+X509_STORE_CTX_get_error_depth, X509_STORE_CTX_get_current_cert,
+X509_STORE_CTX_get0_cert,
+X509_STORE_CTX_get1_chain, X509_verify_cert_error_string - get or set certificate verification status information
 
 =head1 SYNOPSIS
 
@@ -13,6 +16,7 @@ X509_STORE_CTX_get_error, X509_STORE_CTX_set_error, X509_STORE_CTX_get_error_dep
  void	X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s);
  int	X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
  X509 *	X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+ X509 *	X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx);
 
  STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
 
@@ -35,6 +39,8 @@ non-negative integer representing where in the certificate chain the error
 occurred. If it is zero it occurred in the end entity certificate, one if
 it is the certificate which signed the end entity certificate and so on.
 
+X509_STORE_CTX_get0_cert() returns the leaf certificate being verified.
+
 X509_STORE_CTX_get_current_cert() returns the certificate in B<ctx> which
 caused the error or B<NULL> if no certificate is relevant.
 
diff --git a/doc/crypto/X509_STORE_CTX_new.pod b/doc/crypto/X509_STORE_CTX_new.pod
index 1f3ded6..69ff7c4 100644
--- a/doc/crypto/X509_STORE_CTX_new.pod
+++ b/doc/crypto/X509_STORE_CTX_new.pod
@@ -2,7 +2,18 @@
 
 =head1 NAME
 
-X509_STORE_CTX_new, X509_STORE_CTX_cleanup, X509_STORE_CTX_free, X509_STORE_CTX_init, X509_STORE_CTX_trusted_stack, X509_STORE_CTX_set_cert, X509_STORE_CTX_set_chain, X509_STORE_CTX_set0_crls, X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param, X509_STORE_CTX_set_default - X509_STORE_CTX initialisation
+X509_STORE_CTX_new, X509_STORE_CTX_cleanup, X509_STORE_CTX_free,
+X509_STORE_CTX_init, X509_STORE_CTX_set0_trusted_stack, X509_STORE_CTX_set_cert,
+X509_STORE_CTX_set0_crls,
+X509_STORE_CTX_get0_chain, X509_STORE_CTX_set0_verified_chain,
+X509_STORE_CTX_get0_param, X509_STORE_CTX_set0_param,
+X509_STORE_CTX_get0_cert,
+X509_STORE_CTX_get0_untrusted,
+X509_STORE_CTX_get_num_untrusted,
+X509_STORE_CTX_set_default,
+X509_STORE_CTX_get_verify_cb,
+X509_STORE_CTX_set_verify,
+X509_STORE_CTX_get_verify - X509_STORE_CTX initialisation
 
 =head1 SYNOPSIS
 
@@ -15,18 +26,27 @@ X509_STORE_CTX_new, X509_STORE_CTX_cleanup, X509_STORE_CTX_free, X509_STORE_CTX_
  int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
 			 X509 *x509, STACK_OF(X509) *chain);
 
- void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+ void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
 
- void	X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx,X509 *x);
- void	X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx,STACK_OF(X509) *sk);
- void	X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
+ void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx,X509 *x);
+ STACK_OF(X509) *X509_STORE_CTX_get0_chain(X609_STORE_CTX *ctx);
+ void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *chain);
+ void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk);
 
  X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx);
  void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param);
  int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name);
 
+ X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx);
+ STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
+
  int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx);
 
+ typedef int (*X509_STORE_CTX_verify)(X509_STORE_CTX *);
+ X509_STORE_CTX_verify X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx);
+ void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, X509_STORE_CTX_verify verify);
+
+
 =head1 DESCRIPTION
 
 These functions initialise an B<X509_STORE_CTX> structure for subsequent use
@@ -52,15 +72,19 @@ certificates (which will be untrusted but may be used to build the chain) in
 B<chain>. Any or all of the B<store>, B<x509> and B<chain> parameters can be
 B<NULL>.
 
-X509_STORE_CTX_trusted_stack() sets the set of trusted certificates of B<ctx>
-to B<sk>. This is an alternative way of specifying trusted certificates 
+X509_STORE_CTX_set0_trusted_stack() sets the set of trusted certificates of
+B<ctx> to B<sk>. This is an alternative way of specifying trusted certificates
 instead of using an B<X509_STORE>.
 
 X509_STORE_CTX_set_cert() sets the certificate to be verified in B<ctx> to
 B<x>.
 
-X509_STORE_CTX_set_chain() sets the additional certificate chain used by B<ctx>
-to B<sk>.
+X509_STORE_CTX_set0_verified_chain() sets the validated chain used
+by B<ctx> to be B<chain>.
+Ownership of the chain is transferred to B<ctx> and should not be
+free'd by the caller.
+X509_STORE_CTX_get0_chain() returns a the internal pointer used by the
+B<ctx> that contains the validated chain.
 
 X509_STORE_CTX_set0_crls() sets a set of CRLs to use to aid certificate
 verification to B<sk>. These CRLs will only be used if CRL verification is
@@ -68,9 +92,15 @@ enabled in the associated B<X509_VERIFY_PARAM> structure. This might be
 used where additional "useful" CRLs are supplied as part of a protocol,
 for example in a PKCS#7 structure.
 
-X509_VERIFY_PARAM *X509_STORE_CTX_get0_param() retrieves an internal pointer
+X509_STORE_CTX_get0_param() retrieves an internal pointer
 to the verification parameters associated with B<ctx>.
 
+X509_STORE_CTX_get0_cert() retrieves an internal pointer to the
+certificate being verified by the B<ctx>.
+
+X509_STORE_CTX_get0_untrusted() retrieves an internal pointer to the
+stack of untrusted certifieds associated with B<ctx>.
+
 X509_STORE_CTX_set0_param() sets the internal verification parameter pointer
 to B<param>. After this call B<param> should not be used.
 
@@ -84,19 +114,7 @@ that were used in building the chain following a call to X509_verify_cert().
 =head1 NOTES
 
 The certificates and CRLs in a store are used internally and should B<not>
-be freed up until after the associated B<X509_STORE_CTX> is freed. Legacy
-applications might implicitly use an B<X509_STORE_CTX> like this:
-
-  X509_STORE_CTX ctx;
-  X509_STORE_CTX_init(&ctx, store, cert, chain);
-
-this is B<not> recommended in new applications they should instead do:
-
-  X509_STORE_CTX *ctx;
-  ctx = X509_STORE_CTX_new();
-  if (ctx == NULL)
-	/* Bad error */
-  X509_STORE_CTX_init(ctx, store, cert, chain);
+be freed up until after the associated B<X509_STORE_CTX> is freed.
 
 =head1 BUGS
 
@@ -114,8 +132,9 @@ X509_STORE_CTX_init() returns 1 for success or 0 if an error occurred.
 X509_STORE_CTX_get0_param() returns a pointer to an B<X509_VERIFY_PARAM>
 structure or B<NULL> if an error occurred.
 
-X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(), X509_STORE_CTX_trusted_stack(),
-X509_STORE_CTX_set_cert(), X509_STORE_CTX_set_chain(),
+X509_STORE_CTX_cleanup(), X509_STORE_CTX_free(),
+X509_STORE_CTX_set0_trusted_stack(),
+X509_STORE_CTX_set_cert(),
 X509_STORE_CTX_set0_crls() and X509_STORE_CTX_set0_param() do not return
 values.
 
diff --git a/doc/crypto/X509_STORE_CTX_set_verify_cb.pod b/doc/crypto/X509_STORE_CTX_set_verify_cb.pod
index ba35a38..e89b806 100644
--- a/doc/crypto/X509_STORE_CTX_set_verify_cb.pod
+++ b/doc/crypto/X509_STORE_CTX_set_verify_cb.pod
@@ -2,14 +2,19 @@
 
 =head1 NAME
 
-X509_STORE_CTX_set_verify_cb - set verification callback
+X509_STORE_CTX_get_verify_cb,
+X509_STORE_CTX_set_verify_cb - get and set verification callback
 
 =head1 SYNOPSIS
 
  #include <openssl/x509_vfy.h>
 
+ typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+
+ X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx);
+
  void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
-				int (*verify_cb)(int ok, X509_STORE_CTX *ctx));
+				   X509_STORE_CTX_verify_cb verify_cb);
 
 =head1 DESCRIPTION
 
@@ -35,6 +40,9 @@ structure and receive additional information about the error, for example
 by calling X509_STORE_CTX_get_current_cert(). Additional application data can
 be passed to the callback via the B<ex_data> mechanism.
 
+X509_STORE_CTX_get_verify_cb() returns the value of the current callback
+for the specific B<ctx>.
+
 =head1 WARNING
 
 In general a verification callback should B<NOT> unconditionally return 1 in
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index ee6ebcf..81da792 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -119,6 +119,7 @@ typedef struct asn1_sctx_st ASN1_SCTX;
 # ifdef BIGNUM
 #  undef BIGNUM
 # endif
+struct dane_st;
 typedef struct bio_st BIO;
 typedef struct bignum_st BIGNUM;
 typedef struct bignum_ctx BN_CTX;
@@ -169,6 +170,11 @@ typedef struct X509_pubkey_st X509_PUBKEY;
 typedef struct x509_store_st X509_STORE;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
 
+typedef struct x509_object_st X509_OBJECT;
+typedef struct x509_lookup_st X509_LOOKUP;
+typedef struct x509_lookup_method_st X509_LOOKUP_METHOD;
+typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
+
 typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
 
 typedef struct v3_ext_ctx X509V3_CTX;
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index b7123d0..a36500c 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -1096,6 +1096,7 @@ void ERR_load_X509_strings(void);
 # define X509_F_X509_STORE_CTX_INIT                       143
 # define X509_F_X509_STORE_CTX_NEW                        142
 # define X509_F_X509_STORE_CTX_PURPOSE_INHERIT            134
+# define X509_F_X509_STORE_GET_X509_BY_SUBJECT            149
 # define X509_F_X509_TO_X509_REQ                          126
 # define X509_F_X509_TRUST_ADD                            133
 # define X509_F_X509_TRUST_SET                            141
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 2d0cbc0..544f2ad 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -75,14 +75,6 @@
 extern "C" {
 #endif
 
-typedef struct x509_file_st {
-    int num_paths;              /* number of paths to files or directories */
-    int num_alloced;
-    char **paths;               /* the list of paths or directories */
-    int *path_type;
-} X509_CERT_FILE_CTX;
-
-/*******************************/
 /*-
 SSL_CTX -> X509_STORE
                 -> X509_LOOKUP
@@ -105,168 +97,16 @@ typedef enum {
     X509_LU_FAIL, X509_LU_X509, X509_LU_CRL
 } X509_LOOKUP_TYPE;
 
-typedef struct x509_object_st {
-    /* one of the above types */
-    X509_LOOKUP_TYPE type;
-    union {
-        char *ptr;
-        X509 *x509;
-        X509_CRL *crl;
-        EVP_PKEY *pkey;
-    } data;
-} X509_OBJECT;
-
-typedef struct x509_lookup_st X509_LOOKUP;
 
 DEFINE_STACK_OF(X509_LOOKUP)
 DEFINE_STACK_OF(X509_OBJECT)
-
-/* This is a static that defines the function interface */
-typedef struct x509_lookup_method_st {
-    const char *name;
-    int (*new_item) (X509_LOOKUP *ctx);
-    void (*free) (X509_LOOKUP *ctx);
-    int (*init) (X509_LOOKUP *ctx);
-    int (*shutdown) (X509_LOOKUP *ctx);
-    int (*ctrl) (X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
-                 char **ret);
-    int (*get_by_subject) (X509_LOOKUP *ctx, int type, X509_NAME *name,
-                           X509_OBJECT *ret);
-    int (*get_by_issuer_serial) (X509_LOOKUP *ctx, int type, X509_NAME *name,
-                                 ASN1_INTEGER *serial, X509_OBJECT *ret);
-    int (*get_by_fingerprint) (X509_LOOKUP *ctx, int type,
-                               unsigned char *bytes, int len,
-                               X509_OBJECT *ret);
-    int (*get_by_alias) (X509_LOOKUP *ctx, int type, char *str, int len,
-                         X509_OBJECT *ret);
-} X509_LOOKUP_METHOD;
-
-typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
-
 DEFINE_STACK_OF(X509_VERIFY_PARAM)
 
-/*
- * This is used to hold everything.  It is used for all certificate
- * validation.  Once we have a certificate chain, the 'verify' function is
- * then called to actually check the cert chain.
- */
-struct x509_store_st {
-    /* The following is a cache of trusted certs */
-    int cache;                  /* if true, stash any hits */
-    STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */
-    /* These are external lookup methods */
-    STACK_OF(X509_LOOKUP) *get_cert_methods;
-    X509_VERIFY_PARAM *param;
-    /* Callbacks for various operations */
-    /* called to verify a certificate */
-    int (*verify) (X509_STORE_CTX *ctx);
-    /* error callback */
-    int (*verify_cb) (int ok, X509_STORE_CTX *ctx);
-    /* get issuers cert from ctx */
-    int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
-    /* check issued */
-    int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
-    /* Check revocation status of chain */
-    int (*check_revocation) (X509_STORE_CTX *ctx);
-    /* retrieve CRL */
-    int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
-    /* Check CRL validity */
-    int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl);
-    /* Check certificate against CRL */
-    int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
-    STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
-    STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
-    int (*cleanup) (X509_STORE_CTX *ctx);
-    CRYPTO_EX_DATA ex_data;
-    int references;
-    CRYPTO_RWLOCK *lock;
-} /* X509_STORE */ ;
-
 int X509_STORE_set_depth(X509_STORE *store, int depth);
 
 # define X509_STORE_set_verify_cb_func(ctx,func) ((ctx)->verify_cb=(func))
 # define X509_STORE_set_verify_func(ctx,func)    ((ctx)->verify=(func))
 
-/* This is the functions plus an instance of the local variables. */
-struct x509_lookup_st {
-    int init;                   /* have we been started */
-    int skip;                   /* don't use us. */
-    X509_LOOKUP_METHOD *method; /* the functions */
-    char *method_data;          /* method data */
-    X509_STORE *store_ctx;      /* who owns us */
-} /* X509_LOOKUP */ ;
-
-/*
- * This is a used when verifying cert chains.  Since the gathering of the
- * cert chain can take some time (and have to be 'retried', this needs to be
- * kept and passed around.
- */
-struct x509_store_ctx_st {      /* X509_STORE_CTX */
-    X509_STORE *ctx;
-    /* used when looking up certs */
-    int current_method;
-    /* The following are set by the caller */
-    /* The cert to check */
-    X509 *cert;
-    /* chain of X509s - untrusted - passed in */
-    STACK_OF(X509) *untrusted;
-    /* set of CRLs passed in */
-    STACK_OF(X509_CRL) *crls;
-    X509_VERIFY_PARAM *param;
-    /* Other info for use with get_issuer() */
-    void *other_ctx;
-    /* Callbacks for various operations */
-    /* called to verify a certificate */
-    int (*verify) (X509_STORE_CTX *ctx);
-    /* error callback */
-    int (*verify_cb) (int ok, X509_STORE_CTX *ctx);
-    /* get issuers cert from ctx */
-    int (*get_issuer) (X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
-    /* check issued */
-    int (*check_issued) (X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
-    /* Check revocation status of chain */
-    int (*check_revocation) (X509_STORE_CTX *ctx);
-    /* retrieve CRL */
-    int (*get_crl) (X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x);
-    /* Check CRL validity */
-    int (*check_crl) (X509_STORE_CTX *ctx, X509_CRL *crl);
-    /* Check certificate against CRL */
-    int (*cert_crl) (X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
-    int (*check_policy) (X509_STORE_CTX *ctx);
-    STACK_OF(X509) *(*lookup_certs) (X509_STORE_CTX *ctx, X509_NAME *nm);
-    STACK_OF(X509_CRL) *(*lookup_crls) (X509_STORE_CTX *ctx, X509_NAME *nm);
-    int (*cleanup) (X509_STORE_CTX *ctx);
-    /* The following is built up */
-    /* if 0, rebuild chain */
-    int valid;
-    /* number of untrusted certs */
-    int num_untrusted;
-    /* chain of X509s - built up and trusted */
-    STACK_OF(X509) *chain;
-    /* Valid policy tree */
-    X509_POLICY_TREE *tree;
-    /* Require explicit policy value */
-    int explicit_policy;
-    /* When something goes wrong, this is why */
-    int error_depth;
-    int error;
-    X509 *current_cert;
-    /* cert currently being tested as valid issuer */
-    X509 *current_issuer;
-    /* current CRL */
-    X509_CRL *current_crl;
-    /* score of current CRL */
-    int current_crl_score;
-    /* Reason mask */
-    unsigned int current_reasons;
-    /* For CRL path validation: parent context */
-    X509_STORE_CTX *parent;
-    CRYPTO_EX_DATA ex_data;
-    SSL_DANE *dane;
-    /* signed via bare TA public key, rather than CA certificate */
-    int bare_ta_signed;
-} /* X509_STORE_CTX */ ;
-
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 
 # define X509_STORE_CTX_set_app_data(ctx,data) \
@@ -431,6 +271,8 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
 X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
                                         X509_OBJECT *x);
 void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+void X509_OBJECT_free(X509_OBJECT *a);
+X509 *X509_OBJECT_get0_X509(X509_OBJECT *a);
 void X509_OBJECT_free_contents(X509_OBJECT *a);
 X509_STORE *X509_STORE_new(void);
 void X509_STORE_free(X509_STORE *v);
@@ -458,10 +300,20 @@ int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x);
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx);
 int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store,
                         X509 *x509, STACK_OF(X509) *chain);
-void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
+void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk);
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx);
 
 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx);
+X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx);
+STACK_OF(X509)* X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
+typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
+typedef int (*X509_STORE_CTX_verify)(X509_STORE_CTX *);
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+                                  X509_STORE_CTX_verify_cb verify);
+X509_STORE_CTX_verify_cb X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx);
+void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx,
+                               X509_STORE_CTX_verify verify);
+X509_STORE_CTX_verify X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx);
 
 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m);
 X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void);
@@ -472,6 +324,8 @@ int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x);
 
 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
                               X509_OBJECT *ret);
+X509_OBJECT *X509_STORE_get_X509_by_subject(X509_STORE_CTX *vs, int type,
+                                            X509_NAME *name);
 
 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                      long argl, char **ret);
@@ -505,14 +359,15 @@ void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx);
 int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
 void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int s);
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+X509 *X509_STORE_CTX_get_cert(X509_STORE_CTX *ctx);
 X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
 X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx);
 X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx);
 X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx);
-STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
 STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
 void X509_STORE_CTX_set_cert(X509_STORE_CTX *c, X509 *x);
-void X509_STORE_CTX_set_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
+void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *c, STACK_OF(X509) *sk);
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c, STACK_OF(X509_CRL) *sk);
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index 24ac352..04a4a36 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -475,25 +475,31 @@ void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg)
 int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
 {
     X509 *x;
-    int i;
+    int i = 0;
     X509_STORE *verify_store;
-    X509_STORE_CTX ctx;
+    X509_STORE_CTX *ctx = NULL;
     X509_VERIFY_PARAM *param;
 
+    if ((sk == NULL) || (sk_X509_num(sk) == 0))
+        return 0;
+
     if (s->cert->verify_store)
         verify_store = s->cert->verify_store;
     else
         verify_store = s->ctx->cert_store;
 
-    if ((sk == NULL) || (sk_X509_num(sk) == 0))
-        return (0);
+    ctx = X509_STORE_CTX_new();
+    if (ctx == NULL) {
+        SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
 
     x = sk_X509_value(sk, 0);
-    if (!X509_STORE_CTX_init(&ctx, verify_store, x, sk)) {
+    if (!X509_STORE_CTX_init(ctx, verify_store, x, sk)) {
         SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_X509_LIB);
-        return (0);
+        goto end;
     }
-    param = X509_STORE_CTX_get0_param(&ctx);
+    param = X509_STORE_CTX_get0_param(ctx);
     /*
      * XXX: Separate @AUTHSECLEVEL and @TLSSECLEVEL would be useful at some
      * point, for now a single @SECLEVEL sets the same policy for TLS crypto
@@ -502,12 +508,12 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
     X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s));
 
     /* Set suite B flags if needed */
-    X509_STORE_CTX_set_flags(&ctx, tls1_suiteb(s));
-    X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
+    X509_STORE_CTX_set_flags(ctx, tls1_suiteb(s));
+    X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s);
 
     /* Verify via DANE if enabled */
     if (DANETLS_ENABLED(&s->dane))
-        X509_STORE_CTX_set0_dane(&ctx, &s->dane);
+        X509_STORE_CTX_set0_dane(ctx, &s->dane);
 
     /*
      * We need to inherit the verify parameters. These can be determined by
@@ -515,25 +521,25 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
      * vice versa.
      */
 
-    X509_STORE_CTX_set_default(&ctx, s->server ? "ssl_client" : "ssl_server");
+    X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server");
     /*
      * Anything non-default in "s->param" should overwrite anything in the ctx.
      */
     X509_VERIFY_PARAM_set1(param, s->param);
 
     if (s->verify_callback)
-        X509_STORE_CTX_set_verify_cb(&ctx, s->verify_callback);
+        X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback);
 
     if (s->ctx->app_verify_callback != NULL)
-        i = s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg);
+        i = s->ctx->app_verify_callback(ctx, s->ctx->app_verify_arg);
     else
-        i = X509_verify_cert(&ctx);
+        i = X509_verify_cert(ctx);
 
-    s->verify_result = ctx.error;
+    s->verify_result = X509_STORE_CTX_get_error(ctx);
     sk_X509_pop_free(s->verified_chain, X509_free);
     s->verified_chain = NULL;
-    if (X509_STORE_CTX_get_chain(&ctx) != NULL) {
-        s->verified_chain = X509_STORE_CTX_get1_chain(&ctx);
+    if (X509_STORE_CTX_get0_chain(ctx) != NULL) {
+        s->verified_chain = X509_STORE_CTX_get1_chain(ctx);
         if (s->verified_chain == NULL) {
             SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
             i = 0;
@@ -543,9 +549,9 @@ int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk)
     /* Move peername from the store context params to the SSL handle's */
     X509_VERIFY_PARAM_move_peername(s->param, param);
 
-    X509_STORE_CTX_cleanup(&ctx);
-
-    return (i);
+end:
+    X509_STORE_CTX_free(ctx);
+    return i;
 }
 
 static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
@@ -846,10 +852,10 @@ static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x)
 int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
 {
     BUF_MEM *buf = s->init_buf;
-    int i;
-
+    int i, chain_count;
     X509 *x;
     STACK_OF(X509) *extra_certs;
+    STACK_OF(X509) *chain = NULL;
     X509_STORE *chain_store;
 
     /* TLSv1 sends a chain with nothing in it, instead of an alert */
@@ -879,9 +885,14 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
         chain_store = s->ctx->cert_store;
 
     if (chain_store) {
-        X509_STORE_CTX xs_ctx;
+        X509_STORE_CTX* xs_ctx = X509_STORE_CTX_new();
 
-        if (!X509_STORE_CTX_init(&xs_ctx, chain_store, x, NULL)) {
+        if (xs_ctx == NULL) {
+            SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+            return (0);
+        }
+        if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
+            X509_STORE_CTX_free(xs_ctx);
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, ERR_R_X509_LIB);
             return (0);
         }
@@ -891,30 +902,32 @@ int ssl_add_cert_chain(SSL *s, CERT_PKEY *cpk, unsigned long *l)
          * ignore the error return from this call. We're not actually verifying
          * the cert - we're just building as much of the chain as we can
          */
-        (void) X509_verify_cert(&xs_ctx);
+        (void) X509_verify_cert(xs_ctx);
         /* Don't leave errors in the queue */
         ERR_clear_error();
-        i = ssl_security_cert_chain(s, xs_ctx.chain, NULL, 0);
+        chain =  X509_STORE_CTX_get0_chain(xs_ctx);
+        i = ssl_security_cert_chain(s, chain, NULL, 0);
         if (i != 1) {
-            X509_STORE_CTX_cleanup(&xs_ctx);
 #if 0
             /* Dummy error calls so mkerr generates them */
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
 #endif
+            X509_STORE_CTX_free(xs_ctx);
             SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, i);
             return 0;
         }
-        for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
-            x = sk_X509_value(xs_ctx.chain, i);
+        chain_count = sk_X509_num(chain);
+        for (i = 0; i < chain_count; i++) {
+            x = sk_X509_value(chain, i);
 
             if (!ssl_add_cert_to_buf(buf, l, x)) {
-                X509_STORE_CTX_cleanup(&xs_ctx);
+                X509_STORE_CTX_free(xs_ctx);
                 return 0;
             }
         }
-        X509_STORE_CTX_cleanup(&xs_ctx);
+        X509_STORE_CTX_free(xs_ctx);
     } else {
         i = ssl_security_cert_chain(s, extra_certs, x, 0);
         if (i != 1) {
@@ -938,7 +951,7 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
     CERT *c = s ? s->cert : ctx->cert;
     CERT_PKEY *cpk = c->key;
     X509_STORE *chain_store = NULL;
-    X509_STORE_CTX xs_ctx;
+    X509_STORE_CTX *xs_ctx = NULL;
     STACK_OF(X509) *chain = NULL, *untrusted = NULL;
     X509 *x;
     int i, rv = 0;
@@ -984,15 +997,20 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
             untrusted = cpk->chain;
     }
 
-    if (!X509_STORE_CTX_init(&xs_ctx, chain_store, cpk->x509, untrusted)) {
+    xs_ctx = X509_STORE_CTX_new();
+    if (xs_ctx == NULL) {
+        SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (!X509_STORE_CTX_init(xs_ctx, chain_store, cpk->x509, untrusted)) {
         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_X509_LIB);
         goto err;
     }
     /* Set suite B flags if needed */
-    X509_STORE_CTX_set_flags(&xs_ctx,
+    X509_STORE_CTX_set_flags(xs_ctx,
                              c->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS);
 
-    i = X509_verify_cert(&xs_ctx);
+    i = X509_verify_cert(xs_ctx);
     if (i <= 0 && flags & SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR) {
         if (flags & SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR)
             ERR_clear_error();
@@ -1000,17 +1018,15 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
         rv = 2;
     }
     if (i > 0)
-        chain = X509_STORE_CTX_get1_chain(&xs_ctx);
+        chain = X509_STORE_CTX_get1_chain(xs_ctx);
     if (i <= 0) {
         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, SSL_R_CERTIFICATE_VERIFY_FAILED);
-        i = X509_STORE_CTX_get_error(&xs_ctx);
+        i = X509_STORE_CTX_get_error(xs_ctx);
         ERR_add_error_data(2, "Verify error:",
                            X509_verify_cert_error_string(i));
 
-        X509_STORE_CTX_cleanup(&xs_ctx);
         goto err;
     }
-    X509_STORE_CTX_cleanup(&xs_ctx);
     /* Remove EE certificate from chain */
     x = sk_X509_shift(chain);
     X509_free(x);
@@ -1045,6 +1061,7 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
  err:
     if (flags & SSL_BUILD_CHAIN_FLAG_CHECK)
         X509_STORE_free(chain_store);
+    X509_STORE_CTX_free(xs_ctx);
 
     return rv;
 }
diff --git a/test/ssltest_old.c b/test/ssltest_old.c
index 0dae90f..2fd7da8 100644
--- a/test/ssltest_old.c
+++ b/test/ssltest_old.c
@@ -3072,32 +3072,36 @@ static int verify_callback(int ok, X509_STORE_CTX *ctx)
 {
     char *s, buf[256];
 
-    s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf,
-                          sizeof buf);
+    s = X509_NAME_oneline(X509_get_subject_name(X509_STORE_CTX_get_current_cert(ctx)),
+                          buf, sizeof buf);
     if (s != NULL) {
         if (ok)
-            printf("depth=%d %s\n", ctx->error_depth, buf);
+            printf("depth=%d %s\n", X509_STORE_CTX_get_error_depth(ctx), buf);
         else {
             fprintf(stderr, "depth=%d error=%d %s\n",
-                    ctx->error_depth, ctx->error, buf);
+                    X509_STORE_CTX_get_error_depth(ctx),
+                    X509_STORE_CTX_get_error(ctx), buf);
         }
     }
 
     if (ok == 0) {
-        switch (ctx->error) {
+        int i = X509_STORE_CTX_get_error(ctx);
+
+        switch (i) {
         default:
             fprintf(stderr, "Error string: %s\n",
-                    X509_verify_cert_error_string(ctx->error));
+                    X509_verify_cert_error_string(i));
             break;
         case X509_V_ERR_CERT_NOT_YET_VALID:
         case X509_V_ERR_CERT_HAS_EXPIRED:
         case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
             ok = 1;
+            break;
         }
     }
 
     if (ok == 1) {
-        X509 *xs = ctx->current_cert;
+        X509 *xs = X509_STORE_CTX_get_current_cert(ctx);
         if (X509_get_extension_flags(xs) & EXFLAG_PROXY) {
             unsigned int *letters = X509_STORE_CTX_get_ex_data(ctx,
                                                                get_proxy_auth_ex_data_idx
@@ -3434,15 +3438,17 @@ static int app_verify_callback(X509_STORE_CTX *ctx, void *arg)
 
     if (cb_arg->app_verify) {
         char *s = NULL, buf[256];
+        X509 *c = X509_STORE_CTX_get0_cert(ctx);
 
         printf("In app_verify_callback, allowing cert. ");
         printf("Arg is: %s\n", cb_arg->string);
         printf("Finished printing do we have a context? 0x%p a cert? 0x%p\n",
-                (void *)ctx, (void *)ctx->cert);
-        if (ctx->cert)
-            s = X509_NAME_oneline(X509_get_subject_name(ctx->cert), buf, 256);
+                (void *)ctx, (void *)c);
+        if (c)
+            s = X509_NAME_oneline(X509_get_subject_name(c), buf, 256);
         if (s != NULL) {
-            printf("cert depth=%d %s\n", ctx->error_depth, buf);
+            printf("cert depth=%d %s\n",
+                    X509_STORE_CTX_get_error_depth(ctx), buf);
         }
         return (1);
     }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 6a9311c..a92286c 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -1,7 +1,7 @@
 d2i_EC_PUBKEY                           1	1_1_0	EXIST::FUNCTION:EC
 b2i_PVK_bio                             2	1_1_0	EXIST::FUNCTION:RC4
 PEM_read_bio_NETSCAPE_CERT_SEQUENCE     3	1_1_0	EXIST::FUNCTION:
-X509_STORE_CTX_get_chain                4	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_get0_chain               4	1_1_0	EXIST::FUNCTION:
 COMP_expand_block                       5	1_1_0	EXIST::FUNCTION:COMP
 X509V3_get_string                       6	1_1_0	EXIST::FUNCTION:
 TS_MSG_IMPRINT_free                     7	1_1_0	EXIST::FUNCTION:TS
@@ -1755,7 +1755,6 @@ X509_REVOKED_new                        1703	1_1_0	EXIST::FUNCTION:
 NCONF_WIN32                             1704	1_1_0	EXIST::FUNCTION:
 RSA_padding_check_PKCS1_OAEP_mgf1       1705	1_1_0	EXIST::FUNCTION:RSA
 X509_policy_tree_get0_level             1706	1_1_0	EXIST::FUNCTION:
-X509_STORE_CTX_set_chain                1707	1_1_0	EXIST::FUNCTION:
 ASN1_parse_dump                         1708	1_1_0	EXIST::FUNCTION:
 BIO_vfree                               1709	1_1_0	EXIST::FUNCTION:
 CRYPTO_cbc128_decrypt                   1710	1_1_0	EXIST::FUNCTION:
@@ -1942,7 +1941,7 @@ X509_STORE_set_verify_cb                1882	1_1_0	EXIST::FUNCTION:
 OCSP_REQUEST_print                      1883	1_1_0	EXIST::FUNCTION:
 CMS_add1_crl                            1884	1_1_0	EXIST::FUNCTION:CMS
 d2i_EDIPARTYNAME                        1885	1_1_0	EXIST::FUNCTION:
-X509_STORE_CTX_trusted_stack            1886	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_set0_trusted_stack       1886	1_1_0	EXIST::FUNCTION:
 BIO_ADDR_service_string                 1887	1_1_0	EXIST::FUNCTION:
 ASN1_BOOLEAN_it                         1888	1_1_0	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:
 ASN1_BOOLEAN_it                         1888	1_1_0	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:
@@ -4166,7 +4165,6 @@ RSA_meth_get_priv_enc                   4032	1_1_0	EXIST::FUNCTION:RSA
 RSA_set0_crt_params                     4037	1_1_0	EXIST::FUNCTION:RSA
 RSA_get0_crt_params                     4038	1_1_0	EXIST::FUNCTION:RSA
 DH_set0_pqg                             4039	1_1_0	EXIST::FUNCTION:DH
-DH_set_flags                            4040	1_1_0	EXIST::FUNCTION:DH
 DH_clear_flags                          4041	1_1_0	EXIST::FUNCTION:DH
 DH_get0_key                             4042	1_1_0	EXIST::FUNCTION:DH
 DH_get0_engine                          4043	1_1_0	EXIST::FUNCTION:DH
@@ -4196,3 +4194,15 @@ DH_meth_set_bn_mod_exp                  4066	1_1_0	EXIST::FUNCTION:DH
 DH_meth_set_generate_key                4067	1_1_0	EXIST::FUNCTION:DH
 DH_meth_free                            4068	1_1_0	EXIST::FUNCTION:DH
 DH_meth_get_generate_key                4069	1_1_0	EXIST::FUNCTION:DH
+DH_set_flags                            4070	1_1_0	EXIST::FUNCTION:DH
+X509_STORE_get_X509_by_subject          4071	1_1_0	EXIST::FUNCTION:
+X509_OBJECT_free                        4072	1_1_0	EXIST::FUNCTION:
+X509_OBJECT_get0_X509                   4073	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_get0_untrusted           4074	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_set0_chain               4075	1_1_0	NOEXIST::FUNCTION:
+X509_STORE_CTX_get0_cert                4076	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_set_verify               4077	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_get_verify               4079	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_get_verify_cb            4080	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_get_cert                 4081	1_1_0	EXIST::FUNCTION:
+X509_STORE_CTX_set0_verified_chain      4082	1_1_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list