[openssl] master update

shane.lontis at oracle.com shane.lontis at oracle.com
Fri Jul 24 12:56:56 UTC 2020


The branch master has been updated
       via  6725682d77510bf6d499957897d7be124d603f40 (commit)
      from  ae89578be2930c726d6ef56451233757a89f224f (commit)


- Log -----------------------------------------------------------------
commit 6725682d77510bf6d499957897d7be124d603f40
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Fri Jul 24 22:53:27 2020 +1000

    Add X509 related libctx changes.
    
    - In order to not add many X509_XXXX_with_libctx() functions the libctx and propq may be stored in the X509 object via a call to X509_new_with_libctx().
    - Loading via PEM_read_bio_X509() or d2i_X509() should pass in a created cert using X509_new_with_libctx().
    - Renamed some XXXX_ex() to XXX_with_libctx() for X509 API's.
    - Removed the extra parameters in check_purpose..
    - X509_digest() has been modified so that it expects a const EVP_MD object() and then internally it does the fetch when it needs to (via ASN1_item_digest_with_libctx()).
    - Added API's that set the libctx when they load such as X509_STORE_new_with_libctx() so that the cert chains can be verified.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/12153)

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

Summary of changes:
 apps/ca.c                                       |   2 +-
 apps/include/apps.h                             |   3 +
 apps/lib/apps.c                                 |  33 +++++--
 apps/req.c                                      |   3 +-
 apps/storeutl.c                                 |  14 ++-
 apps/ts.c                                       |   8 +-
 apps/x509.c                                     |   5 +-
 crypto/asn1/a_digest.c                          |  40 ++++++--
 crypto/ess/ess_lib.c                            |   5 +-
 crypto/pem/pem_info.c                           |  40 ++++++--
 crypto/pem/pem_pkey.c                           |   9 +-
 crypto/store/loader_file.c                      |  98 +++++++++++--------
 crypto/store/store_lib.c                        |  32 +++---
 crypto/store/store_local.h                      |   1 +
 crypto/store/store_register.c                   |   1 +
 crypto/x509/by_dir.c                            |  56 +++++++----
 crypto/x509/by_file.c                           |  95 ++++++++++++------
 crypto/x509/by_store.c                          |  42 +++++---
 crypto/x509/v3_purp.c                           |  31 ++----
 crypto/x509/x509_d2.c                           |  48 +++++++--
 crypto/x509/x509_local.h                        |   9 +-
 crypto/x509/x509_lu.c                           |  53 +++++++---
 crypto/x509/x509_vfy.c                          |  30 ++----
 crypto/x509/x_all.c                             |  31 +++---
 crypto/x509/x_x509.c                            |  31 +++++-
 doc/man3/OSSL_STORE_LOADER.pod                  |  17 ++--
 doc/man3/OSSL_STORE_attach.pod                  |   4 +-
 doc/man3/OSSL_STORE_open.pod                    |  36 ++++---
 doc/man3/PEM_X509_INFO_read_bio_with_libctx.pod |  65 ++++++++++++
 doc/man3/PEM_read_bio_PrivateKey.pod            |  10 ++
 doc/man3/SSL_load_client_CA_file.pod            |  16 ++-
 doc/man3/X509_LOOKUP.pod                        | 106 ++++++++++++++------
 doc/man3/X509_LOOKUP_hash_dir.pod               |  16 ++-
 doc/man3/X509_STORE_add_cert.pod                |  72 ++++++++++----
 doc/man3/X509_STORE_new.pod                     |   7 +-
 doc/man3/X509_new.pod                           |  19 +++-
 doc/man3/X509_sign.pod                          |   4 +-
 doc/man3/X509_verify.pod                        |  30 +++---
 doc/man3/X509v3_cache_extensions.pod            |  44 ---------
 doc/man7/x509.pod                               |   3 +-
 include/crypto/store.h                          |  10 --
 include/crypto/x509.h                           |  11 ++-
 include/openssl/pem.h                           |   9 ++
 include/openssl/ssl.h                           |   3 +
 include/openssl/store.h                         |  35 ++++---
 include/openssl/x509.h                          |   6 +-
 include/openssl/x509_vfy.h                      |  46 ++++++++-
 include/openssl/x509v3.h                        |   2 -
 ssl/s3_lib.c                                    |   4 -
 ssl/ssl_cert.c                                  |  35 ++++---
 ssl/ssl_conf.c                                  |  22 ++++-
 ssl/ssl_lib.c                                   |  14 ++-
 ssl/ssl_mcnf.c                                  |   6 ++
 ssl/ssl_rsa.c                                   | 125 +++++++++++++++---------
 ssl/statem/statem_clnt.c                        |  10 +-
 ssl/statem/statem_srvr.c                        |   8 +-
 test/ssl_test.c                                 |   2 +-
 test/ssl_test_ctx.c                             |  20 ++--
 test/ssl_test_ctx.h                             |   7 +-
 test/ssl_test_ctx_test.c                        |   7 +-
 test/sslapitest.c                               |  51 +++++-----
 util/libcrypto.num                              |  19 +++-
 util/libssl.num                                 |   1 +
 util/other.syms                                 |   3 +
 64 files changed, 1081 insertions(+), 544 deletions(-)
 create mode 100644 doc/man3/PEM_X509_INFO_read_bio_with_libctx.pod
 delete mode 100644 doc/man3/X509v3_cache_extensions.pod

diff --git a/apps/ca.c b/apps/ca.c
index d0309ae15c..e001a34190 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1643,7 +1643,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
         BIO_printf(bio_err,
                    "Everything appears to be ok, creating and signing the certificate\n");
 
-    if ((ret = X509_new()) == NULL)
+    if ((ret = X509_new_with_libctx(app_get0_libctx(), app_get0_propq())) == NULL)
         goto end;
 
 #ifdef X509_V3
diff --git a/apps/include/apps.h b/apps/include/apps.h
index 9a76dcd339..e91cdcdb8f 100644
--- a/apps/include/apps.h
+++ b/apps/include/apps.h
@@ -299,4 +299,7 @@ void app_params_free(OSSL_PARAM *params);
 int app_provider_load(OPENSSL_CTX *libctx, const char *provider_name);
 void app_providers_cleanup(void);
 
+OPENSSL_CTX *app_get0_libctx(void);
+const char *app_get0_propq(void);
+
 #endif
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index ba40e9bc7e..cf99ca0ebf 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -342,6 +342,12 @@ OPENSSL_CTX *app_get0_libctx(void)
     return app_libctx;
 }
 
+/* TODO(3.0): Make this an environment variable if required */
+const char *app_get0_propq(void)
+{
+    return NULL;
+}
+
 OPENSSL_CTX *app_create_libctx(void)
 {
     /*
@@ -657,9 +663,11 @@ static int load_certs_crls(const char *file, int format,
     if (bio == NULL)
         return 0;
 
-    xis = PEM_X509_INFO_read_bio(bio, NULL,
-                                 (pem_password_cb *)password_callback,
-                                 &cb_data);
+    xis = PEM_X509_INFO_read_bio_with_libctx(bio, NULL,
+                                             (pem_password_cb *)password_callback,
+                                             &cb_data,
+                                             app_get0_libctx(),
+                                             app_get0_propq());
 
     BIO_free(bio);
 
@@ -765,6 +773,8 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
 {
     PW_CB_DATA uidata;
     OSSL_STORE_CTX *ctx = NULL;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
     int ret = 0;
     /* TODO make use of the engine reference 'eng' when loading pkeys */
 
@@ -791,11 +801,12 @@ int load_key_cert_crl(const char *uri, int maybe_stdin,
         unbuffer(stdin);
         bio = BIO_new_fp(stdin, 0);
         if (bio != NULL)
-            ctx = OSSL_STORE_attach(bio, NULL, "file", NULL,
+            ctx = OSSL_STORE_attach(bio, "file", libctx, propq,
                                     get_ui_method(), &uidata, NULL, NULL);
         uri = "<stdin>";
     } else {
-        ctx = OSSL_STORE_open(uri, get_ui_method(), &uidata, NULL, NULL);
+        ctx = OSSL_STORE_open_with_libctx(uri, libctx, propq, get_ui_method(),
+                                          &uidata, NULL, NULL);
     }
     if (ctx == NULL) {
         BIO_printf(bio_err, "Could not open file or uri %s for loading %s\n",
@@ -1099,6 +1110,8 @@ X509_STORE *setup_verify(const char *CAfile, int noCAfile,
 {
     X509_STORE *store = X509_STORE_new();
     X509_LOOKUP *lookup;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     if (store == NULL)
         goto end;
@@ -1108,12 +1121,16 @@ X509_STORE *setup_verify(const char *CAfile, int noCAfile,
         if (lookup == NULL)
             goto end;
         if (CAfile != NULL) {
-            if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
+            if (!X509_LOOKUP_load_file_with_libctx(lookup, CAfile,
+                                                   X509_FILETYPE_PEM,
+                                                   libctx, propq)) {
                 BIO_printf(bio_err, "Error loading file %s\n", CAfile);
                 goto end;
             }
         } else {
-            X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+            X509_LOOKUP_load_file_with_libctx(lookup, NULL,
+                                              X509_FILETYPE_DEFAULT,
+                                              libctx, propq);
         }
     }
 
@@ -1135,7 +1152,7 @@ X509_STORE *setup_verify(const char *CAfile, int noCAfile,
         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_store());
         if (lookup == NULL)
             goto end;
-        if (!X509_LOOKUP_add_store(lookup, CAstore)) {
+        if (!X509_LOOKUP_add_store_with_libctx(lookup, CAstore, libctx, propq)) {
             if (CAstore != NULL)
                 BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
             goto end;
diff --git a/apps/req.c b/apps/req.c
index 4ae828cd45..bee0329b24 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -742,7 +742,8 @@ int req_main(int argc, char **argv)
         if (x509) {
             EVP_PKEY *tmppkey;
             X509V3_CTX ext_ctx;
-            if ((x509ss = X509_new()) == NULL)
+            if ((x509ss = X509_new_with_libctx(app_get0_libctx(),
+                                               app_get0_propq())) == NULL)
                 goto end;
 
             /* Set version to V3 */
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 87e8fcc9e6..95af277260 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -19,7 +19,7 @@
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                    int expected, int criterion, OSSL_STORE_SEARCH *search,
                    int text, int noout, int recursive, int indent, BIO *out,
-                   const char *prog);
+                   const char *prog, OPENSSL_CTX *libctx, const char *propq);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_ENGINE, OPT_OUT, OPT_PASSIN,
@@ -84,6 +84,8 @@ int storeutl_main(int argc, char *argv[])
     char *alias = NULL;
     OSSL_STORE_SEARCH *search = NULL;
     const EVP_MD *digest = NULL;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     while ((o = opt_next()) != OPT_EOF) {
         switch (o) {
@@ -322,7 +324,7 @@ int storeutl_main(int argc, char *argv[])
 
     ret = process(argv[0], get_ui_method(), &pw_cb_data,
                   expected, criterion, search,
-                  text, noout, recursive, 0, out, prog);
+                  text, noout, recursive, 0, out, prog, libctx, propq);
 
  end:
     OPENSSL_free(fingerprint);
@@ -353,12 +355,13 @@ static int indent_printf(int indent, BIO *bio, const char *format, ...)
 static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                    int expected, int criterion, OSSL_STORE_SEARCH *search,
                    int text, int noout, int recursive, int indent, BIO *out,
-                   const char *prog)
+                   const char *prog, OPENSSL_CTX *libctx, const char *propq)
 {
     OSSL_STORE_CTX *store_ctx = NULL;
     int ret = 1, items = 0;
 
-    if ((store_ctx = OSSL_STORE_open(uri, uimeth, uidata, NULL, NULL))
+    if ((store_ctx = OSSL_STORE_open_with_libctx(uri, libctx, propq,
+                                                 uimeth, uidata, NULL, NULL))
         == NULL) {
         BIO_printf(bio_err, "Couldn't open file or uri %s\n", uri);
         ERR_print_errors(bio_err);
@@ -439,7 +442,8 @@ static int process(const char *uri, const UI_METHOD *uimeth, PW_CB_DATA *uidata,
                 const char *suburi = OSSL_STORE_INFO_get0_NAME(info);
                 ret += process(suburi, uimeth, uidata,
                                expected, criterion, search,
-                               text, noout, recursive, indent + 2, out, prog);
+                               text, noout, recursive, indent + 2, out, prog,
+                               libctx, propq);
             }
             break;
         case OSSL_STORE_INFO_PARAMS:
diff --git a/apps/ts.c b/apps/ts.c
index da4584ab53..09c586b44f 100644
--- a/apps/ts.c
+++ b/apps/ts.c
@@ -957,6 +957,8 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
 {
     X509_STORE *cert_ctx = NULL;
     X509_LOOKUP *lookup = NULL;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     cert_ctx = X509_STORE_new();
     X509_STORE_set_verify_cb(cert_ctx, verify_cb);
@@ -978,7 +980,9 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
             BIO_printf(bio_err, "memory allocation failure\n");
             goto err;
         }
-        if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) {
+        if (!X509_LOOKUP_load_file_with_libctx(lookup, CAfile,
+                                               X509_FILETYPE_PEM,
+                                               libctx, propq)) {
             BIO_printf(bio_err, "Error loading file %s\n", CAfile);
             goto err;
         }
@@ -990,7 +994,7 @@ static X509_STORE *create_cert_store(const char *CApath, const char *CAfile,
             BIO_printf(bio_err, "memory allocation failure\n");
             goto err;
         }
-        if (!X509_LOOKUP_load_store(lookup, CAstore)) {
+        if (!X509_LOOKUP_load_store_with_libctx(lookup, CAstore, libctx, propq)) {
             BIO_printf(bio_err, "Error loading store URI %s\n", CAstore);
             goto err;
         }
diff --git a/apps/x509.c b/apps/x509.c
index c09bca37bc..d8f69c08eb 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -510,7 +510,8 @@ int x509_main(int argc, char **argv)
         goto end;
     }
 
-    if (!X509_STORE_set_default_paths(ctx)) {
+    if (!X509_STORE_set_default_paths_with_libctx(ctx, app_get0_libctx(),
+                                                  app_get0_propq())) {
         ERR_print_errors(bio_err);
         goto end;
     }
@@ -607,7 +608,7 @@ int x509_main(int argc, char **argv)
                        "We need a private key to sign with, use -signkey or -CAkey or -CA <file> with private key\n");
             goto end;
         }
-        if ((x = X509_new()) == NULL)
+        if ((x = X509_new_with_libctx(app_get0_libctx(), app_get0_propq())) == NULL)
             goto end;
 
         if (sno == NULL) {
diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c
index caf2f6c34f..c0c1cda272 100644
--- a/crypto/asn1/a_digest.c
+++ b/crypto/asn1/a_digest.c
@@ -7,16 +7,21 @@
  * https://www.openssl.org/source/license.html
  */
 
+/* We need to use some engine deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include <time.h>
 #include <sys/types.h>
 
 #include "internal/cryptlib.h"
 
+#include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include <openssl/x509.h>
+#include "crypto/x509.h"
 
 #ifndef OPENSSL_NO_DEPRECATED_3_0
 
@@ -48,20 +53,39 @@ int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
 
 #endif
 
-int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
-                     unsigned char *md, unsigned int *len)
+int asn1_item_digest_with_libctx(const ASN1_ITEM *it, const EVP_MD *md,
+                                 void *asn, unsigned char *data,
+                                 unsigned int *len, OPENSSL_CTX *libctx,
+                                 const char *propq)
 {
-    int i;
+    int i, ret = 0;
     unsigned char *str = NULL;
+    EVP_MD *fetched_md = (EVP_MD *)md;
 
     i = ASN1_item_i2d(asn, &str, it);
-    if (!str)
+    if (str == NULL)
         return 0;
 
-    if (!EVP_Digest(str, i, md, len, type, NULL)) {
-        OPENSSL_free(str);
-        return 0;
+    if (EVP_MD_provider(md) == NULL) {
+#if !defined(OPENSSL_NO_ENGINE)
+        if (ENGINE_get_digest_engine(EVP_MD_type(md)) == NULL)
+#endif
+            fetched_md = EVP_MD_fetch(libctx, EVP_MD_name(md), propq);
     }
+     if (fetched_md == NULL)
+         goto err;
+
+    ret = EVP_Digest(str, i, data, len, fetched_md, NULL);
+err:
     OPENSSL_free(str);
-    return 1;
+    if (fetched_md != md)
+        EVP_MD_free(fetched_md);
+    return ret;
 }
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *md, void *asn,
+                     unsigned char *data, unsigned int *len)
+{
+    return asn1_item_digest_with_libctx(it, md, asn, data, len, NULL, NULL);
+}
+
diff --git a/crypto/ess/ess_lib.c b/crypto/ess/ess_lib.c
index 4a7a2632ba..ad0d6f332c 100644
--- a/crypto/ess/ess_lib.c
+++ b/crypto/ess/ess_lib.c
@@ -12,6 +12,7 @@
 #include <openssl/err.h>
 #include <openssl/ess.h>
 #include "crypto/ess.h"
+#include "crypto/x509.h"
 
 DEFINE_STACK_OF(ESS_CERT_ID)
 DEFINE_STACK_OF(ESS_CERT_ID_V2)
@@ -61,7 +62,7 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
     unsigned char cert_sha1[SHA_DIGEST_LENGTH];
 
     /* Call for side-effect of computing hash and caching extensions */
-    if (!X509v3_cache_extensions(cert, NULL, NULL))
+    if (!x509v3_cache_extensions(cert))
         return NULL;
 
     if ((cid = ESS_CERT_ID_new()) == NULL)
@@ -304,7 +305,7 @@ int ess_find_cert(const STACK_OF(ESS_CERT_ID) *cert_ids, X509 *cert)
         return -1;
 
     /* Recompute SHA1 hash of certificate if necessary (side effect). */
-    if (!X509v3_cache_extensions(cert, NULL, NULL))
+    if (!x509v3_cache_extensions(cert))
         return -1;
 
     /* TODO(3.0): fetch sha1 algorithm from providers */
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
index f6a5dedc48..a3981c9dda 100644
--- a/crypto/pem/pem_info.c
+++ b/crypto/pem/pem_info.c
@@ -26,25 +26,35 @@
 DEFINE_STACK_OF(X509_INFO)
 
 #ifndef OPENSSL_NO_STDIO
-STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
-                                        pem_password_cb *cb, void *u)
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_with_libctx(FILE *fp, STACK_OF(X509_INFO) *sk,
+                                pem_password_cb *cb, void *u,
+                                OPENSSL_CTX *libctx, const char *propq)
 {
     BIO *b;
     STACK_OF(X509_INFO) *ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        PEMerr(PEM_F_PEM_X509_INFO_READ, ERR_R_BUF_LIB);
+        PEMerr(0, ERR_R_BUF_LIB);
         return 0;
     }
     BIO_set_fp(b, fp, BIO_NOCLOSE);
-    ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+    ret = PEM_X509_INFO_read_bio_with_libctx(b, sk, cb, u, libctx, propq);
     BIO_free(b);
     return ret;
 }
+
+STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+                                        pem_password_cb *cb, void *u)
+{
+    return PEM_X509_INFO_read_with_libctx(fp, sk, cb, u, NULL, NULL);
+}
 #endif
 
-STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
-                                            pem_password_cb *cb, void *u)
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_bio_with_libctx(BIO *bp, STACK_OF(X509_INFO) *sk,
+                                    pem_password_cb *cb, void *u,
+                                    OPENSSL_CTX *libctx, const char *propq)
 {
     X509_INFO *xi = NULL;
     char *name = NULL, *header = NULL;
@@ -59,7 +69,7 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
 
     if (sk == NULL) {
         if ((ret = sk_X509_INFO_new_null()) == NULL) {
-            PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_MALLOC_FAILURE);
+            PEMerr(0, ERR_R_MALLOC_FAILURE);
             goto err;
         }
     } else
@@ -90,6 +100,9 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
                     goto err;
                 goto start;
             }
+            xi->x509 = X509_new_with_libctx(libctx, propq);
+            if (xi->x509 == NULL)
+                goto err;
             pp = &(xi->x509);
         } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
             d2i = (D2I_OF(void)) d2i_X509_AUX;
@@ -100,6 +113,9 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
                     goto err;
                 goto start;
             }
+            xi->x509 = X509_new_with_libctx(libctx, propq);
+            if (xi->x509 == NULL)
+                goto err;
             pp = &(xi->x509);
         } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
             d2i = (D2I_OF(void)) d2i_X509_CRL;
@@ -197,11 +213,11 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
                 p = data;
                 if (ptype) {
                     if (!d2i_PrivateKey(ptype, pp, &p, len)) {
-                        PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB);
+                        PEMerr(0, ERR_R_ASN1_LIB);
                         goto err;
                     }
                 } else if (d2i(pp, &p, len) == NULL) {
-                    PEMerr(PEM_F_PEM_X509_INFO_READ_BIO, ERR_R_ASN1_LIB);
+                    PEMerr(0, ERR_R_ASN1_LIB);
                     goto err;
                 }
             } else {            /* encrypted RSA data */
@@ -251,6 +267,12 @@ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
     return ret;
 }
 
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
+                                            pem_password_cb *cb, void *u)
+{
+    return PEM_X509_INFO_read_bio_with_libctx(bp, sk, cb, u, NULL, NULL);
+}
+
 /* A TJH addition */
 int PEM_X509_INFO_write_bio(BIO *bp, const X509_INFO *xi, EVP_CIPHER *enc,
                             const unsigned char *kstr, int klen,
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
index ee9b6764a6..c60eed97c0 100644
--- a/crypto/pem/pem_pkey.c
+++ b/crypto/pem/pem_pkey.c
@@ -39,7 +39,7 @@ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
     if ((ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0)) == NULL)
         return NULL;
 
-    if ((ctx = OSSL_STORE_attach(bp, libctx, "file", propq, ui_method, u,
+    if ((ctx = OSSL_STORE_attach(bp, "file", libctx, propq, ui_method, u,
                                  NULL, NULL)) == NULL)
         goto err;
 #ifndef OPENSSL_NO_SECURE_HEAP
@@ -50,7 +50,8 @@ EVP_PKEY *PEM_read_bio_PrivateKey_ex(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
     }
 #endif
 
-    while (!OSSL_STORE_eof(ctx) && (info = OSSL_STORE_load(ctx)) != NULL) {
+    while (!OSSL_STORE_eof(ctx)
+           && (info = OSSL_STORE_load(ctx)) != NULL) {
         if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
             ret = OSSL_STORE_INFO_get1_PKEY(info);
             break;
@@ -106,7 +107,7 @@ EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
     OSSL_STORE_CTX *ctx = NULL;
     OSSL_STORE_INFO *info = NULL;
 
-    if ((ctx = OSSL_STORE_attach(bp, NULL, "file", NULL, UI_null(), NULL,
+    if ((ctx = OSSL_STORE_attach(bp, "file", NULL, NULL, UI_null(), NULL,
                                  NULL, NULL)) == NULL)
         goto err;
 
@@ -201,7 +202,7 @@ DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
     if ((ui_method = UI_UTIL_wrap_read_pem_callback(cb, 0)) == NULL)
         return NULL;
 
-    if ((ctx = OSSL_STORE_attach(bp, NULL, "file", NULL, ui_method, u,
+    if ((ctx = OSSL_STORE_attach(bp, "file", NULL, NULL, ui_method, u,
                                  NULL, NULL)) == NULL)
         goto err;
 
diff --git a/crypto/store/loader_file.c b/crypto/store/loader_file.c
index 30f4e6ecaf..5ff93e33ab 100644
--- a/crypto/store/loader_file.c
+++ b/crypto/store/loader_file.c
@@ -693,8 +693,12 @@ static OSSL_STORE_INFO *try_decode_X509Certificate(const char *pem_name,
         *matchcount = 1;
     }
 
-    if ((cert = d2i_X509_AUX(NULL, &blob, len)) != NULL
-        || (ignore_trusted && (cert = d2i_X509(NULL, &blob, len)) != NULL)) {
+    cert = X509_new_with_libctx(libctx, propq);
+    if (cert == NULL)
+        return NULL;
+
+    if ((d2i_X509_AUX(&cert, &blob, len)) != NULL
+        || (ignore_trusted && (d2i_X509(&cert, &blob, len)) != NULL)) {
         *matchcount = 1;
         store_info = OSSL_STORE_INFO_new_CERT(cert);
     }
@@ -813,7 +817,6 @@ struct ossl_store_loader_ctx_st {
 
     /* Expected object type.  May be unspecified */
     int expected_type;
-
     OPENSSL_CTX *libctx;
     char *propq;
 };
@@ -823,6 +826,7 @@ static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
     if (ctx == NULL)
         return;
 
+    OPENSSL_free(ctx->propq);
     OPENSSL_free(ctx->uri);
     if (ctx->type != is_dir) {
         if (ctx->_.file.last_handler != NULL) {
@@ -831,7 +835,6 @@ static void OSSL_STORE_LOADER_CTX_free(OSSL_STORE_LOADER_CTX *ctx)
             ctx->_.file.last_handler = NULL;
         }
     }
-    OPENSSL_free(ctx->propq);
     OPENSSL_free(ctx);
 }
 
@@ -852,10 +855,10 @@ static int file_find_type(OSSL_STORE_LOADER_CTX *ctx)
     return 1;
 }
 
-static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
-                                        const char *uri,
-                                        const UI_METHOD *ui_method,
-                                        void *ui_data)
+static OSSL_STORE_LOADER_CTX *file_open_with_libctx
+    (const OSSL_STORE_LOADER *loader, const char *uri,
+     OPENSSL_CTX *libctx, const char *propq,
+     const UI_METHOD *ui_method, void *ui_data)
 {
     OSSL_STORE_LOADER_CTX *ctx = NULL;
     struct stat st;
@@ -888,8 +891,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
             } else if (uri[7] == '/') {
                 p = &uri[7];
             } else {
-                OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
-                              OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
+                OSSL_STOREerr(0, OSSL_STORE_R_URI_AUTHORITY_UNSUPPORTED);
                 return NULL;
             }
         }
@@ -917,8 +919,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
          * be absolute.  So says RFC 8089
          */
         if (path_data[i].check_absolute && path_data[i].path[0] != '/') {
-            OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN,
-                          OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
+            OSSL_STOREerr(0, OSSL_STORE_R_PATH_MUST_BE_ABSOLUTE);
             ERR_add_error_data(1, path_data[i].path);
             return NULL;
         }
@@ -940,12 +941,12 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
 
     ctx = OPENSSL_zalloc(sizeof(*ctx));
     if (ctx == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE);
+        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     ctx->uri = OPENSSL_strdup(uri);
     if (ctx->uri == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_MALLOC_FAILURE);
+        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -956,7 +957,7 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
         if (ctx->_.dir.last_entry == NULL) {
             if (ctx->_.dir.last_errno != 0) {
                 char errbuf[256];
-                OSSL_STOREerr(OSSL_STORE_F_FILE_OPEN, ERR_R_SYS_LIB);
+                OSSL_STOREerr(0, ERR_R_SYS_LIB);
                 errno = ctx->_.dir.last_errno;
                 if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
                     ERR_add_error_data(1, errbuf);
@@ -969,6 +970,14 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
         BIO_free_all(ctx->_.file.file);
         goto err;
     }
+    if (propq != NULL) {
+        ctx->propq = OPENSSL_strdup(propq);
+        if (ctx->propq == NULL) {
+            OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
+    ctx->libctx = libctx;
 
     return ctx;
  err:
@@ -976,32 +985,44 @@ static OSSL_STORE_LOADER_CTX *file_open(const OSSL_STORE_LOADER *loader,
     return NULL;
 }
 
-static OSSL_STORE_LOADER_CTX *file_attach(const OSSL_STORE_LOADER *loader,
-                                          BIO *bp, OPENSSL_CTX *libctx,
-                                          const char *propq,
-                                          const UI_METHOD *ui_method,
-                                          void *ui_data)
+static OSSL_STORE_LOADER_CTX *file_open
+    (const OSSL_STORE_LOADER *loader, const char *uri,
+     const UI_METHOD *ui_method, void *ui_data)
 {
-    OSSL_STORE_LOADER_CTX *ctx;
+    return file_open_with_libctx(loader, uri, NULL, NULL, ui_method, ui_data);
+}
 
-    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
-        || (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL)) {
-        OSSL_STOREerr(OSSL_STORE_F_FILE_ATTACH, ERR_R_MALLOC_FAILURE);
-        OSSL_STORE_LOADER_CTX_free(ctx);
-        return NULL;
+static OSSL_STORE_LOADER_CTX *file_attach
+    (const OSSL_STORE_LOADER *loader, BIO *bp,
+     OPENSSL_CTX *libctx, const char *propq,
+     const UI_METHOD *ui_method, void *ui_data)
+{
+    OSSL_STORE_LOADER_CTX *ctx = NULL;
+
+    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
+        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+        goto err;
     }
 
+    if (propq != NULL) {
+        ctx->propq = OPENSSL_strdup(propq);
+        if (ctx->propq == NULL) {
+            OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
     ctx->libctx = libctx;
     ctx->flags |= FILE_FLAG_ATTACHED;
     ctx->_.file.file = bp;
     if (!file_find_type(ctx)) {
         /* Safety measure */
         ctx->_.file.file = NULL;
-        OSSL_STORE_LOADER_CTX_free(ctx);
-        ctx = NULL;
+        goto err;
     }
-
     return ctx;
+err:
+    OSSL_STORE_LOADER_CTX_free(ctx);
+    return NULL;
 }
 
 static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
@@ -1021,8 +1042,7 @@ static int file_ctrl(OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args)
                 ctx->flags |= FILE_FLAG_SECMEM;
                 break;
             default:
-                OSSL_STOREerr(OSSL_STORE_F_FILE_CTRL,
-                              ERR_R_PASSED_INVALID_ARGUMENT);
+                OSSL_STOREerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
                 ret = 0;
                 break;
             }
@@ -1422,7 +1442,8 @@ static int file_name_check(OSSL_STORE_LOADER_CTX *ctx, const char *name)
 static int file_eof(OSSL_STORE_LOADER_CTX *ctx);
 static int file_error(OSSL_STORE_LOADER_CTX *ctx);
 static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
-                                  const UI_METHOD *ui_method, void *ui_data)
+                                  const UI_METHOD *ui_method,
+                                  void *ui_data)
 {
     OSSL_STORE_INFO *result = NULL;
 
@@ -1437,7 +1458,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
                 if (!ctx->_.dir.end_reached) {
                     char errbuf[256];
                     assert(ctx->_.dir.last_errno != 0);
-                    OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_SYS_LIB);
+                    OSSL_STOREerr(0, ERR_R_SYS_LIB);
                     errno = ctx->_.dir.last_errno;
                     ctx->errcnt++;
                     if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
@@ -1465,7 +1486,7 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
             if (newname != NULL
                 && (result = OSSL_STORE_INFO_new_NAME(newname)) == NULL) {
                 OPENSSL_free(newname);
-                OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD, ERR_R_OSSL_STORE_LIB);
+                OSSL_STOREerr(0, ERR_R_OSSL_STORE_LIB);
                 return NULL;
             }
         } while (result == NULL && !file_eof(ctx));
@@ -1524,16 +1545,14 @@ static OSSL_STORE_INFO *file_load(OSSL_STORE_LOADER_CTX *ctx,
             }
 
             if (matchcount > 1) {
-                OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
-                              OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE);
+                OSSL_STOREerr(0, OSSL_STORE_R_AMBIGUOUS_CONTENT_TYPE);
             } else if (matchcount == 1) {
                 /*
                  * If there are other errors on the stack, they already show
                  * what the problem is.
                  */
                 if (ERR_peek_error() == 0) {
-                    OSSL_STOREerr(OSSL_STORE_F_FILE_LOAD,
-                                  OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE);
+                    OSSL_STOREerr(0, OSSL_STORE_R_UNSUPPORTED_CONTENT_TYPE);
                     if (pem_name != NULL)
                         ERR_add_error_data(3, "PEM type is '", pem_name, "'");
                 }
@@ -1617,7 +1636,8 @@ static OSSL_STORE_LOADER file_loader =
         file_load,
         file_eof,
         file_error,
-        file_close
+        file_close,
+        file_open_with_libctx,
     };
 
 static void store_file_loader_deinit(void)
diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c
index e1fc591894..2878358245 100644
--- a/crypto/store/store_lib.c
+++ b/crypto/store/store_lib.c
@@ -11,9 +11,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-
-#include "e_os.h"
-
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/trace.h>
@@ -35,10 +32,10 @@ struct ossl_store_ctx_st {
     int loading;
 };
 
-OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
-                                void *ui_data,
-                                OSSL_STORE_post_process_info_fn post_process,
-                                void *post_process_data)
+OSSL_STORE_CTX *OSSL_STORE_open_with_libctx(
+    const char *uri, OPENSSL_CTX *libctx, const char *propq,
+    const UI_METHOD *ui_method, void *ui_data,
+    OSSL_STORE_post_process_info_fn post_process, void *post_process_data)
 {
     const OSSL_STORE_LOADER *loader = NULL;
     OSSL_STORE_LOADER_CTX *loader_ctx = NULL;
@@ -78,7 +75,11 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
         OSSL_TRACE1(STORE, "Looking up scheme %s\n", schemes[i]);
         if ((loader = ossl_store_get0_loader_int(schemes[i])) != NULL) {
             OSSL_TRACE1(STORE, "Found loader for scheme %s\n", schemes[i]);
-            loader_ctx = loader->open(loader, uri, ui_method, ui_data);
+            if (loader->open_with_libctx != NULL)
+                loader_ctx = loader->open_with_libctx(loader, uri, libctx, propq,
+                                                      ui_method, ui_data);
+            else
+                loader_ctx = loader->open(loader, uri, ui_method, ui_data);
             OSSL_TRACE2(STORE, "Opened %s => %p\n", uri, (void *)loader_ctx);
         }
     }
@@ -87,7 +88,7 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
         goto err;
 
     if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) {
-        OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_OPEN, ERR_R_MALLOC_FAILURE);
+        OSSL_STOREerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -120,6 +121,15 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
     return NULL;
 }
 
+OSSL_STORE_CTX *OSSL_STORE_open(const char *uri,
+                                const UI_METHOD *ui_method, void *ui_data,
+                                OSSL_STORE_post_process_info_fn post_process,
+                                void *post_process_data)
+{
+    return OSSL_STORE_open_with_libctx(uri, NULL, NULL, ui_method, ui_data,
+                                       post_process, post_process_data);
+}
+
 int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ...)
 {
     va_list args;
@@ -653,8 +663,8 @@ char *ossl_store_info_get0_EMBEDDED_pem_name(OSSL_STORE_INFO *info)
     return NULL;
 }
 
-OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, OPENSSL_CTX *libctx,
-                                  const char *scheme, const char *propq,
+OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bp, const char *scheme,
+                                  OPENSSL_CTX *libctx, const char *propq,
                                   const UI_METHOD *ui_method, void *ui_data,
                                   OSSL_STORE_post_process_info_fn post_process,
                                   void *post_process_data)
diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h
index 31e04d13ad..c9592c38ce 100644
--- a/crypto/store/store_local.h
+++ b/crypto/store/store_local.h
@@ -110,6 +110,7 @@ struct ossl_store_loader_st {
     OSSL_STORE_eof_fn eof;
     OSSL_STORE_error_fn error;
     OSSL_STORE_close_fn close;
+    OSSL_STORE_open_with_libctx_fn open_with_libctx;
 };
 DEFINE_LHASH_OF(OSSL_STORE_LOADER);
 
diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c
index 12efb3e89b..4fbf459afa 100644
--- a/crypto/store/store_register.c
+++ b/crypto/store/store_register.c
@@ -220,6 +220,7 @@ const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme)
     template.load = NULL;
     template.eof = NULL;
     template.close = NULL;
+    template.open_with_libctx = NULL;
 
     if (!ossl_store_init_once())
         return NULL;
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 43b175e2dc..ff6e4cf03c 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -42,23 +42,32 @@ typedef struct lookup_dir_st {
 } BY_DIR;
 
 static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
-                    char **ret);
+                    char **retp);
+
 static int new_dir(X509_LOOKUP *lu);
 static void free_dir(X509_LOOKUP *lu);
 static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
 static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
                                const X509_NAME *name, X509_OBJECT *ret);
+static int get_cert_by_subject_with_libctx(X509_LOOKUP *xl,
+                                           X509_LOOKUP_TYPE type,
+                                           const X509_NAME *name,
+                                           X509_OBJECT *ret,
+                                           OPENSSL_CTX *libctx,
+                                           const char *propq);
 static X509_LOOKUP_METHOD x509_dir_lookup = {
     "Load certs from files in a directory",
-    new_dir,                    /* new_item */
-    free_dir,                   /* free */
-    NULL,                       /* init */
-    NULL,                       /* shutdown */
-    dir_ctrl,                   /* ctrl */
-    get_cert_by_subject,        /* get_by_subject */
-    NULL,                       /* get_by_issuer_serial */
-    NULL,                       /* get_by_fingerprint */
-    NULL,                       /* get_by_alias */
+    new_dir,                         /* new_item */
+    free_dir,                        /* free */
+    NULL,                            /* init */
+    NULL,                            /* shutdown */
+    dir_ctrl,                        /* ctrl */
+    get_cert_by_subject,             /* get_by_subject */
+    NULL,                            /* get_by_issuer_serial */
+    NULL,                            /* get_by_fingerprint */
+    NULL,                            /* get_by_alias */
+    get_cert_by_subject_with_libctx, /* get_by_subject_with_libctx */
+    NULL,                            /* ctrl_with_libctx */
 };
 
 X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
@@ -210,8 +219,12 @@ static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
     return 1;
 }
 
-static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
-                               const X509_NAME *name, X509_OBJECT *ret)
+static int get_cert_by_subject_with_libctx(X509_LOOKUP *xl,
+                                           X509_LOOKUP_TYPE type,
+                                           const X509_NAME *name,
+                                           X509_OBJECT *ret,
+                                           OPENSSL_CTX *libctx,
+                                           const char *propq)
 {
     BY_DIR *ctx;
     union {
@@ -238,12 +251,12 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
         stmp.data.crl = &data.crl;
         postfix = "r";
     } else {
-        X509err(X509_F_GET_CERT_BY_SUBJECT, X509_R_WRONG_LOOKUP_TYPE);
+        X509err(0, X509_R_WRONG_LOOKUP_TYPE);
         goto finish;
     }
 
     if ((b = BUF_MEM_new()) == NULL) {
-        X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_BUF_LIB);
+        X509err(0, ERR_R_BUF_LIB);
         goto finish;
     }
 
@@ -258,7 +271,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
         ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
         j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
         if (!BUF_MEM_grow(b, j)) {
-            X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+            X509err(0, ERR_R_MALLOC_FAILURE);
             goto finish;
         }
         if (type == X509_LU_CRL && ent->hashes) {
@@ -316,7 +329,8 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
 #endif
             /* found one. */
             if (type == X509_LU_X509) {
-                if ((X509_load_cert_file(xl, b->data, ent->dir_type)) == 0)
+                if ((X509_load_cert_file_with_libctx(xl, b->data, ent->dir_type,
+                                                     libctx, propq)) == 0)
                     break;
             } else if (type == X509_LU_CRL) {
                 if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
@@ -351,7 +365,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
                 hent = OPENSSL_malloc(sizeof(*hent));
                 if (hent == NULL) {
                     CRYPTO_THREAD_unlock(ctx->lock);
-                    X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+                    X509err(0, ERR_R_MALLOC_FAILURE);
                     ok = 0;
                     goto finish;
                 }
@@ -360,7 +374,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
                 if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
                     CRYPTO_THREAD_unlock(ctx->lock);
                     OPENSSL_free(hent);
-                    X509err(X509_F_GET_CERT_BY_SUBJECT, ERR_R_MALLOC_FAILURE);
+                    X509err(0, ERR_R_MALLOC_FAILURE);
                     ok = 0;
                     goto finish;
                 }
@@ -390,3 +404,9 @@ static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
     BUF_MEM_free(b);
     return ok;
 }
+
+static int get_cert_by_subject(X509_LOOKUP *xl, X509_LOOKUP_TYPE type,
+                               const X509_NAME *name, X509_OBJECT *ret)
+{
+    return get_cert_by_subject_with_libctx(xl, type, name, ret, NULL, NULL);
+}
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index f9e1e73fc4..d5e6dde4f8 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -21,6 +21,11 @@ DEFINE_STACK_OF(X509_INFO)
 
 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                         long argl, char **ret);
+static int by_file_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd,
+                                    const char *argc, long argl, char **ret,
+                                    OPENSSL_CTX *libctx, const char *propq);
+
+
 static X509_LOOKUP_METHOD x509_file_lookup = {
     "Load file into cache",
     NULL,                       /* new_item */
@@ -32,6 +37,8 @@ static X509_LOOKUP_METHOD x509_file_lookup = {
     NULL,                       /* get_by_issuer_serial */
     NULL,                       /* get_by_fingerprint */
     NULL,                       /* get_by_alias */
+    NULL,                       /* get_by_subject_with_libctx */
+    by_file_ctrl_with_libctx,   /* ctrl_with_libctx */
 };
 
 X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
@@ -39,8 +46,9 @@ X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
     return &x509_file_lookup;
 }
 
-static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
-                        long argl, char **ret)
+static int by_file_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd,
+                                    const char *argp, long argl, char **ret,
+                                    OPENSSL_CTX *libctx, const char *propq)
 {
     int ok = 0;
     const char *file;
@@ -50,30 +58,40 @@ static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
         if (argl == X509_FILETYPE_DEFAULT) {
             file = ossl_safe_getenv(X509_get_default_cert_file_env());
             if (file)
-                ok = (X509_load_cert_crl_file(ctx, file,
-                                              X509_FILETYPE_PEM) != 0);
+                ok = (X509_load_cert_crl_file_with_libctx(ctx, file,
+                                                          X509_FILETYPE_PEM,
+                                                          libctx, propq) != 0);
 
             else
-                ok = (X509_load_cert_crl_file
-                      (ctx, X509_get_default_cert_file(),
-                       X509_FILETYPE_PEM) != 0);
+                ok = (X509_load_cert_crl_file_with_libctx(
+                         ctx, X509_get_default_cert_file(),
+                         X509_FILETYPE_PEM, libctx, propq) != 0);
 
             if (!ok) {
-                X509err(X509_F_BY_FILE_CTRL, X509_R_LOADING_DEFAULTS);
+                X509err(0, X509_R_LOADING_DEFAULTS);
             }
         } else {
             if (argl == X509_FILETYPE_PEM)
-                ok = (X509_load_cert_crl_file(ctx, argp,
-                                              X509_FILETYPE_PEM) != 0);
+                ok = (X509_load_cert_crl_file_with_libctx(ctx, argp,
+                                                          X509_FILETYPE_PEM,
+                                                          libctx, propq) != 0);
             else
-                ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
+                ok = (X509_load_cert_file_with_libctx(ctx, argp, (int)argl,
+                                                      libctx, propq) != 0);
         }
         break;
     }
     return ok;
 }
 
-int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd,
+                        const char *argp, long argl, char **ret)
+{
+    return by_file_ctrl_with_libctx(ctx, cmd, argp, argl, ret, NULL, NULL);
+}
+
+int X509_load_cert_file_with_libctx(X509_LOOKUP *ctx, const char *file, int type,
+                                    OPENSSL_CTX *libctx, const char *propq)
 {
     int ret = 0;
     BIO *in = NULL;
@@ -83,20 +101,29 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
     in = BIO_new(BIO_s_file());
 
     if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
-        X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_SYS_LIB);
+        X509err(0, ERR_R_SYS_LIB);
+        goto err;
+    }
+
+    if (type != X509_FILETYPE_PEM && type != X509_FILETYPE_ASN1) {
+        X509err(0, X509_R_BAD_X509_FILETYPE);
+        goto err;
+    }
+    x = X509_new_with_libctx(libctx, propq);
+    if (x == NULL) {
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     if (type == X509_FILETYPE_PEM) {
         for (;;) {
-            x = PEM_read_bio_X509_AUX(in, NULL, NULL, "");
-            if (x == NULL) {
+            if (PEM_read_bio_X509_AUX(in, &x, NULL, "") == NULL) {
                 if ((ERR_GET_REASON(ERR_peek_last_error()) ==
                      PEM_R_NO_START_LINE) && (count > 0)) {
                     ERR_clear_error();
                     break;
                 } else {
-                    X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_PEM_LIB);
+                    X509err(0, ERR_R_PEM_LIB);
                     goto err;
                 }
             }
@@ -109,27 +136,28 @@ int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
         }
         ret = count;
     } else if (type == X509_FILETYPE_ASN1) {
-        x = d2i_X509_bio(in, NULL);
-        if (x == NULL) {
-            X509err(X509_F_X509_LOAD_CERT_FILE, ERR_R_ASN1_LIB);
+        if (d2i_X509_bio(in, &x) == NULL) {
+            X509err(0, ERR_R_ASN1_LIB);
             goto err;
         }
         i = X509_STORE_add_cert(ctx->store_ctx, x);
         if (!i)
             goto err;
         ret = i;
-    } else {
-        X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_BAD_X509_FILETYPE);
-        goto err;
     }
     if (ret == 0)
-        X509err(X509_F_X509_LOAD_CERT_FILE, X509_R_NO_CERTIFICATE_FOUND);
+        X509err(0, X509_R_NO_CERTIFICATE_FOUND);
  err:
     X509_free(x);
     BIO_free(in);
     return ret;
 }
 
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+    return X509_load_cert_file_with_libctx(ctx, file, type, NULL, NULL);
+}
+
 int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
 {
     int ret = 0;
@@ -187,7 +215,9 @@ int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
     return ret;
 }
 
-int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+int X509_load_cert_crl_file_with_libctx(X509_LOOKUP *ctx, const char *file,
+                                        int type, OPENSSL_CTX *libctx,
+                                        const char *propq)
 {
     STACK_OF(X509_INFO) *inf;
     X509_INFO *itmp;
@@ -195,16 +225,16 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
     int i, count = 0;
 
     if (type != X509_FILETYPE_PEM)
-        return X509_load_cert_file(ctx, file, type);
+        return X509_load_cert_file_with_libctx(ctx, file, type, libctx, propq);
     in = BIO_new_file(file, "r");
     if (!in) {
-        X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_SYS_LIB);
+        X509err(0, ERR_R_SYS_LIB);
         return 0;
     }
-    inf = PEM_X509_INFO_read_bio(in, NULL, NULL, "");
+    inf = PEM_X509_INFO_read_bio_with_libctx(in, NULL, NULL, "", libctx, propq);
     BIO_free(in);
     if (!inf) {
-        X509err(X509_F_X509_LOAD_CERT_CRL_FILE, ERR_R_PEM_LIB);
+        X509err(0, ERR_R_PEM_LIB);
         return 0;
     }
     for (i = 0; i < sk_X509_INFO_num(inf); i++) {
@@ -221,9 +251,14 @@ int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
         }
     }
     if (count == 0)
-        X509err(X509_F_X509_LOAD_CERT_CRL_FILE,
-                X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
+        X509err(0, X509_R_NO_CERTIFICATE_OR_CRL_FOUND);
  err:
     sk_X509_INFO_pop_free(inf, X509_INFO_free);
     return count;
 }
+
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+    return X509_load_cert_crl_file_with_libctx(ctx, file, type, NULL, NULL);
+}
+
diff --git a/crypto/x509/by_store.c b/crypto/x509/by_store.c
index 7141c1bd2f..debb76150d 100644
--- a/crypto/x509/by_store.c
+++ b/crypto/x509/by_store.c
@@ -17,13 +17,14 @@ DEFINE_STACK_OF_STRING()
 /* Generic object loader, given expected type and criterion */
 static int cache_objects(X509_LOOKUP *lctx, const char *uri,
                          const OSSL_STORE_SEARCH *criterion,
-                         int depth)
+                         int depth, OPENSSL_CTX *libctx, const char *propq)
 {
     int ok = 0;
     OSSL_STORE_CTX *ctx = NULL;
     X509_STORE *xstore = X509_LOOKUP_get_store(lctx);
 
-    if ((ctx = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL)) == NULL)
+    if ((ctx = OSSL_STORE_open_with_libctx(uri, libctx, propq,
+                                           NULL, NULL, NULL, NULL)) == NULL)
         return 0;
 
     /*
@@ -65,7 +66,7 @@ static int cache_objects(X509_LOOKUP *lctx, const char *uri,
              */
             if (depth > 0)
                 ok = cache_objects(lctx, OSSL_STORE_INFO_get0_NAME(info),
-                                   criterion, depth - 1);
+                                   criterion, depth - 1, libctx, propq);
         } else {
             /*
              * We know that X509_STORE_add_{cert|crl} increments the object's
@@ -106,9 +107,10 @@ static void by_store_free(X509_LOOKUP *ctx)
     sk_OPENSSL_STRING_pop_free(uris, free_uri);
 }
 
-static int by_store_ctrl(X509_LOOKUP *ctx, int cmd,
-                         const char *argp, long argl,
-                         char **retp)
+static int by_store_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd,
+                                     const char *argp, long argl,
+                                     char **retp,
+                                     OPENSSL_CTX *libctx, const char *propq)
 {
     switch (cmd) {
     case X509_L_ADD_STORE:
@@ -129,14 +131,21 @@ static int by_store_ctrl(X509_LOOKUP *ctx, int cmd,
         }
     case X509_L_LOAD_STORE:
         /* This is a shortcut for quick loading of specific containers */
-        return cache_objects(ctx, argp, NULL, 0);
+        return cache_objects(ctx, argp, NULL, 0, libctx, propq);
     }
 
     return 0;
 }
 
+static int by_store_ctrl(X509_LOOKUP *ctx, int cmd,
+                         const char *argp, long argl, char **retp)
+{
+    return by_store_ctrl_with_libctx(ctx, cmd, argp, argl, retp, NULL, NULL);
+}
+
 static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
-                    const OSSL_STORE_SEARCH *criterion, X509_OBJECT *ret)
+                    const OSSL_STORE_SEARCH *criterion, X509_OBJECT *ret,
+                    OPENSSL_CTX *libctx, const char *propq)
 {
     STACK_OF(OPENSSL_STRING) *uris = X509_LOOKUP_get_method_data(ctx);
     int i;
@@ -144,7 +153,7 @@ static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
 
     for (i = 0; i < sk_OPENSSL_STRING_num(uris); i++) {
         ok = cache_objects(ctx, sk_OPENSSL_STRING_value(uris, i), criterion,
-                           1 /* depth */);
+                           1 /* depth */, libctx, propq);
 
         if (ok)
             break;
@@ -152,12 +161,13 @@ static int by_store(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
     return ok;
 }
 
-static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
-                            const X509_NAME *name, X509_OBJECT *ret)
+static int by_store_subject_with_libctx(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                                        const X509_NAME *name, X509_OBJECT *ret,
+                                        OPENSSL_CTX *libctx, const char *propq)
 {
     OSSL_STORE_SEARCH *criterion =
         OSSL_STORE_SEARCH_by_name((X509_NAME *)name); /* won't modify it */
-    int ok = by_store(ctx, type, criterion, ret);
+    int ok = by_store(ctx, type, criterion, ret, libctx, propq);
     STACK_OF(X509_OBJECT) *store_objects =
         X509_STORE_get0_objects(X509_LOOKUP_get_store(ctx));
     X509_OBJECT *tmp = NULL;
@@ -205,6 +215,12 @@ static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
     return ok;
 }
 
+static int by_store_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                            const X509_NAME *name, X509_OBJECT *ret)
+{
+    return by_store_subject_with_libctx(ctx, type, name, ret, NULL, NULL);
+}
+
 /*
  * We lack the implementations for get_by_issuer_serial, get_by_fingerprint
  * and get_by_alias.  There's simply not enough support in the X509_LOOKUP
@@ -222,6 +238,8 @@ static X509_LOOKUP_METHOD x509_store_lookup = {
     NULL,                        /* get_by_issuer_serial */
     NULL,                        /* get_by_fingerprint */
     NULL,                        /* get_by_alias */
+    by_store_subject_with_libctx,
+    by_store_ctrl_with_libctx
 };
 
 X509_LOOKUP_METHOD *X509_LOOKUP_store(void)
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index 4a2b549199..9e0190a038 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -84,7 +84,7 @@ int X509_check_purpose(X509 *x, int id, int ca)
     int idx;
     const X509_PURPOSE *pt;
 
-    if (!X509v3_cache_extensions(x, NULL, NULL))
+    if (!x509v3_cache_extensions(x))
         return -1;
 
     /* Return if side-effect only call */
@@ -375,7 +375,7 @@ static int check_sig_alg_match(const EVP_PKEY *pkey, const X509 *subject)
  * e.g., if cert 'x' is self-issued, in x->ex_flags and other internal fields.
  * Set EXFLAG_INVALID and return 0 in case the certificate is invalid.
  */
-int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq)
+int x509v3_cache_extensions(X509 *x)
 {
     BASIC_CONSTRAINTS *bs;
     PROXY_CERT_INFO_EXTENSION *pci;
@@ -384,7 +384,6 @@ int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq)
     EXTENDED_KEY_USAGE *extusage;
     X509_EXTENSION *ex;
     int i;
-    EVP_MD *sha1;
 
 #ifdef tsan_ld_acq
     /* fast lock-free check, see end of the function for details. */
@@ -398,13 +397,8 @@ int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq)
         return (x->ex_flags & EXFLAG_INVALID) == 0;
     }
 
-    /* Cache the SHA1 digest of the cert */
-    sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
-    if (sha1 != NULL) {
-        if (!X509_digest(x, sha1, x->sha1_hash, NULL))
+    if (!X509_digest(x, EVP_sha1(), x->sha1_hash, NULL))
             x->ex_flags |= EXFLAG_INVALID;
-        EVP_MD_free(sha1);
-    }
 
     /* V1 should mean no extensions ... */
     if (X509_get_version(x) == 0)
@@ -636,7 +630,7 @@ void X509_set_proxy_pathlen(X509 *x, long l)
 int X509_check_ca(X509 *x)
 {
     /* Note 0 normally means "not a CA" - but in this case means error. */
-    if (!X509v3_cache_extensions(x, NULL, NULL))
+    if (!x509v3_cache_extensions(x))
         return 0;
 
     return check_ca(x);
@@ -846,19 +840,17 @@ static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
  * Returns 0 for OK, or positive for reason for mismatch
  * where reason codes match those for X509_verify_cert().
  */
-int x509_check_issued_int(X509 *issuer, X509 *subject,
-                          OPENSSL_CTX *libctx, const char *propq)
+int X509_check_issued(X509 *issuer, X509 *subject)
 {
     int ret;
 
-    if ((ret = x509_likely_issued(issuer, subject, libctx, propq)) != X509_V_OK)
+    if ((ret = x509_likely_issued(issuer, subject)) != X509_V_OK)
         return ret;
     return x509_signing_allowed(issuer, subject);
 }
 
 /* do the checks 1., 2., and 3. as described above for X509_check_issued() */
-int x509_likely_issued(X509 *issuer, X509 *subject,
-                       OPENSSL_CTX *libctx, const char *propq)
+int x509_likely_issued(X509 *issuer, X509 *subject)
 {
     int ret;
 
@@ -867,8 +859,8 @@ int x509_likely_issued(X509 *issuer, X509 *subject,
         return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
 
     /* set issuer->skid and subject->akid */
-    if (!X509v3_cache_extensions(issuer, libctx, propq)
-            || !X509v3_cache_extensions(subject, libctx, propq))
+    if (!x509v3_cache_extensions(issuer)
+            || !x509v3_cache_extensions(subject))
         return X509_V_ERR_UNSPECIFIED;
 
     ret = X509_check_akid(issuer, subject->akid);
@@ -896,11 +888,6 @@ int x509_signing_allowed(const X509 *issuer, const X509 *subject)
     return X509_V_OK;
 }
 
-int X509_check_issued(X509 *issuer, X509 *subject)
-{
-    return x509_check_issued_int(issuer, subject, NULL, NULL);
-}
-
 int X509_check_akid(const X509 *issuer, const AUTHORITY_KEYID *akid)
 {
     if (akid == NULL)
diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c
index c0543adf1e..512c7ae13e 100644
--- a/crypto/x509/x509_d2.c
+++ b/crypto/x509/x509_d2.c
@@ -12,14 +12,17 @@
 #include <openssl/crypto.h>
 #include <openssl/x509.h>
 
-int X509_STORE_set_default_paths(X509_STORE *ctx)
+int X509_STORE_set_default_paths_with_libctx(X509_STORE *ctx,
+                                             OPENSSL_CTX *libctx,
+                                             const char *propq)
 {
     X509_LOOKUP *lookup;
 
     lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
     if (lookup == NULL)
         return 0;
-    X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+    X509_LOOKUP_load_file_with_libctx(lookup, NULL, X509_FILETYPE_DEFAULT,
+                                      libctx, propq);
 
     lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
     if (lookup == NULL)
@@ -29,26 +32,37 @@ int X509_STORE_set_default_paths(X509_STORE *ctx)
     lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store());
     if (lookup == NULL)
         return 0;
-    X509_LOOKUP_add_store(lookup, NULL);
+    X509_LOOKUP_add_store_with_libctx(lookup, NULL, libctx, propq);
 
     /* clear any errors */
     ERR_clear_error();
 
     return 1;
 }
+int X509_STORE_set_default_paths(X509_STORE *ctx)
+{
+    return X509_STORE_set_default_paths_with_libctx(ctx, NULL, NULL);
+}
 
-int X509_STORE_load_file(X509_STORE *ctx, const char *file)
+int X509_STORE_load_file_with_libctx(X509_STORE *ctx, const char *file,
+                                     OPENSSL_CTX *libctx, const char *propq)
 {
     X509_LOOKUP *lookup;
 
     if (file == NULL
         || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file())) == NULL
-        || X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) == 0)
+        || X509_LOOKUP_load_file_with_libctx(lookup, file, X509_FILETYPE_PEM,
+                                             libctx, propq) == 0)
         return 0;
 
     return 1;
 }
 
+int X509_STORE_load_file(X509_STORE *ctx, const char *file)
+{
+    return X509_STORE_load_file_with_libctx(ctx, file, NULL, NULL);
+}
+
 int X509_STORE_load_path(X509_STORE *ctx, const char *path)
 {
     X509_LOOKUP *lookup;
@@ -61,26 +75,40 @@ int X509_STORE_load_path(X509_STORE *ctx, const char *path)
     return 1;
 }
 
-int X509_STORE_load_store(X509_STORE *ctx, const char *uri)
+int X509_STORE_load_store_with_libctx(X509_STORE *ctx, const char *uri,
+                                      OPENSSL_CTX *libctx, const char *propq)
 {
     X509_LOOKUP *lookup;
 
     if (uri == NULL
         || (lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_store())) == NULL
-        || X509_LOOKUP_add_store(lookup, uri) == 0)
+        || X509_LOOKUP_add_store_with_libctx(lookup, uri, libctx, propq) == 0)
         return 0;
 
     return 1;
 }
 
-int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
-                              const char *path)
+int X509_STORE_load_store(X509_STORE *ctx, const char *uri)
+{
+    return X509_STORE_load_store_with_libctx(ctx, uri, NULL, NULL);
+}
+
+int X509_STORE_load_locations_with_libctx(X509_STORE *ctx, const char *file,
+                                          const char *path,
+                                          OPENSSL_CTX *libctx, const char *propq)
 {
     if (file == NULL && path == NULL)
         return 0;
-    if (file != NULL && !X509_STORE_load_file(ctx, file))
+    if (file != NULL && !X509_STORE_load_file_with_libctx(ctx, file,
+                                                          libctx, propq))
         return 0;
     if (path != NULL && !X509_STORE_load_path(ctx, path))
         return 0;
     return 1;
 }
+
+int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
+                              const char *path)
+{
+    return X509_STORE_load_locations_with_libctx(ctx, file, path, NULL, NULL);
+}
diff --git a/crypto/x509/x509_local.h b/crypto/x509/x509_local.h
index a1fe4203b9..e944d16afe 100644
--- a/crypto/x509/x509_local.h
+++ b/crypto/x509/x509_local.h
@@ -87,6 +87,12 @@ struct x509_lookup_method_st {
                                X509_OBJECT *ret);
     int (*get_by_alias) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                          const char *str, int len, X509_OBJECT *ret);
+    int (*get_by_subject_with_libctx) (X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                                       const X509_NAME *name, X509_OBJECT *ret,
+                                       OPENSSL_CTX *libctx, const char *propq);
+    int (*ctrl_with_libctx) (X509_LOOKUP *ctx, int cmd,
+                             const char *argc, long argl, char **ret,
+                             OPENSSL_CTX *libctx, const char *propq);
 };
 
 /* This is the functions plus an instance of the local variables. */
@@ -149,6 +155,5 @@ DEFINE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
 
 void x509_set_signature_info(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
                              const ASN1_STRING *sig);
-int x509_likely_issued(X509 *issuer, X509 *subject,
-                       OPENSSL_CTX *libctx, const char *propq);
+int x509_likely_issued(X509 *issuer, X509 *subject);
 int x509_signing_allowed(const X509 *issuer, const X509 *subject);
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index 421f26ba16..e66cfb1825 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -76,25 +76,46 @@ int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
         return 1;
 }
 
-int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
-                     char **ret)
+int X509_LOOKUP_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd, const char *argc,
+                                 long argl, char **ret,
+                                 OPENSSL_CTX *libctx, const char *propq)
 {
     if (ctx->method == NULL)
         return -1;
+    if (ctx->method->ctrl_with_libctx != NULL)
+        return ctx->method->ctrl_with_libctx(ctx, cmd, argc, argl, ret,
+                                             libctx, propq);
     if (ctx->method->ctrl != NULL)
         return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
+    return 1;
+}
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+                     char **ret)
+{
+    return X509_LOOKUP_ctrl_with_libctx(ctx, cmd, argc, argl, ret, NULL, NULL);
+}
+
+int X509_LOOKUP_by_subject_with_libctx(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                                       const X509_NAME *name, X509_OBJECT *ret,
+                                       OPENSSL_CTX *libctx, const char *propq)
+{
+    if (ctx->skip
+        || ctx->method == NULL
+        || (ctx->method->get_by_subject == NULL
+            && ctx->method->get_by_subject_with_libctx == NULL))
+        return 0;
+    if (ctx->method->get_by_subject_with_libctx != NULL)
+        return ctx->method->get_by_subject_with_libctx(ctx, type, name, ret,
+                                                       libctx, propq);
     else
-        return 1;
+        return ctx->method->get_by_subject(ctx, type, name, ret);
 }
 
 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                            const X509_NAME *name, X509_OBJECT *ret)
 {
-    if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
-        return 0;
-    if (ctx->skip)
-        return 0;
-    return ctx->method->get_by_subject(ctx, type, name, ret);
+    return X509_LOOKUP_by_subject_with_libctx(ctx, type, name, ret, NULL, NULL);
 }
 
 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
@@ -168,34 +189,33 @@ X509_STORE *X509_STORE_new(void)
     X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
 
     if (ret == NULL) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     ret->cache = 1;
     if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     ret->lock = CRYPTO_THREAD_lock_new();
     if (ret->lock == NULL) {
-        X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
+        X509err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
-
     ret->references = 1;
     return ret;
 
@@ -315,7 +335,8 @@ int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *vs,
     if (tmp == NULL || type == X509_LU_CRL) {
         for (i = 0; i < sk_X509_LOOKUP_num(store->get_cert_methods); i++) {
             lu = sk_X509_LOOKUP_value(store->get_cert_methods, i);
-            j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
+            j = X509_LOOKUP_by_subject_with_libctx(lu, type, name, &stmp,
+                                                   vs->libctx, vs->propq);
             if (j) {
                 tmp = &stmp;
                 break;
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 3bd23d131c..012f932ee5 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -118,8 +118,7 @@ static int null_callback(int ok, X509_STORE_CTX *e)
  * to match issuer and subject names (i.e., the cert being self-issued) and any
  * present authority key identifier to match the subject key identifier, etc.
  */
-static int x509_self_signed_ex(X509 *cert, int verify_signature,
-                               OPENSSL_CTX *libctx, const char *propq)
+int X509_self_signed(X509 *cert, int verify_signature)
 {
     EVP_PKEY *pkey;
 
@@ -127,24 +126,13 @@ static int x509_self_signed_ex(X509 *cert, int verify_signature,
         X509err(0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
         return -1;
     }
-    if (!X509v3_cache_extensions(cert, libctx, propq))
+    if (!x509v3_cache_extensions(cert))
         return -1;
     if ((cert->ex_flags & EXFLAG_SS) == 0)
         return 0;
     if (!verify_signature)
         return 1;
-    return X509_verify_ex(cert, pkey, libctx, propq);
-}
-
-/* wrapper for internal use */
-static int cert_self_signed(X509_STORE_CTX *ctx, X509 *x, int verify_signature)
-{
-    return x509_self_signed_ex(x, verify_signature, ctx->libctx, ctx->propq);
-}
-
-int X509_self_signed(X509 *cert, int verify_signature)
-{
-    return x509_self_signed_ex(cert, verify_signature, NULL, NULL);
+    return X509_verify(cert, pkey);
 }
 
 /* Given a certificate try and find an exact match in the store */
@@ -367,7 +355,7 @@ static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
  */
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
 {
-    if (x509_likely_issued(issuer, x, ctx->libctx, ctx->propq) != X509_V_OK)
+    if (x509_likely_issued(issuer, x) != X509_V_OK)
         return 0;
     if ((x->ex_flags & EXFLAG_SI) == 0 || sk_X509_num(ctx->chain) != 1) {
         int i;
@@ -1825,7 +1813,7 @@ static int internal_verify(X509_STORE_CTX *ctx)
                 ret = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
                 if (!verify_cb_cert(ctx, xi, issuer_depth, ret))
                     return 0;
-            } else if (X509_verify_ex(xs, pkey, ctx->libctx, ctx->propq) <= 0) {
+            } else if (X509_verify(xs, pkey) <= 0) {
                 ret = X509_V_ERR_CERT_SIGNATURE_FAILURE;
                 if (!verify_cb_cert(ctx, xs, n, ret))
                     return 0;
@@ -2871,7 +2859,7 @@ static int check_dane_pkeys(X509_STORE_CTX *ctx)
         if (t->usage != DANETLS_USAGE_DANE_TA ||
             t->selector != DANETLS_SELECTOR_SPKI ||
             t->mtype != DANETLS_MATCHING_FULL ||
-            X509_verify_ex(cert, t->spki, ctx->libctx, ctx->propq) <= 0)
+            X509_verify(cert, t->spki) <= 0)
             continue;
 
         /* Clear any PKIX-?? matches that failed to extend to a full chain */
@@ -3013,7 +3001,7 @@ static int build_chain(X509_STORE_CTX *ctx)
         return 0;
     }
 
-    self_signed = cert_self_signed(ctx, cert, 0);
+    self_signed = X509_self_signed(cert, 0);
     if (self_signed < 0) {
         ctx->error = X509_V_ERR_UNSPECIFIED;
         return 0;
@@ -3191,7 +3179,7 @@ static int build_chain(X509_STORE_CTX *ctx)
                         search = 0;
                         continue;
                     }
-                    self_signed = cert_self_signed(ctx, x, 0);
+                    self_signed = X509_self_signed(x, 0);
                     if (self_signed < 0) {
                         ctx->error = X509_V_ERR_UNSPECIFIED;
                         return 0;
@@ -3317,7 +3305,7 @@ static int build_chain(X509_STORE_CTX *ctx)
 
             x = xtmp;
             ++ctx->num_untrusted;
-            self_signed = cert_self_signed(ctx, xtmp, 0);
+            self_signed = X509_self_signed(xtmp, 0);
             if (self_signed < 0) {
                 sk_X509_free(sktmp);
                 ctx->error = X509_V_ERR_UNSPECIFIED;
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 6d7f341c7f..b06828f718 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -19,12 +19,12 @@
 #include <openssl/asn1.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
-#include "crypto/x509.h"
 #include <openssl/http.h>
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
 #include <openssl/x509v3.h>
 #include "crypto/asn1.h"
+#include "crypto/x509.h"
 
 static void clean_id_ctx(EVP_MD_CTX *ctx)
 {
@@ -64,7 +64,7 @@ static EVP_MD_CTX *make_id_ctx(EVP_PKEY *r, ASN1_OCTET_STRING *id,
     return NULL;
 }
 
-int X509_verify_ex(X509 *a, EVP_PKEY *r, OPENSSL_CTX *libctx, const char *propq)
+int X509_verify(X509 *a, EVP_PKEY *r)
 {
     int rv = 0;
     EVP_MD_CTX *ctx = NULL;
@@ -74,7 +74,7 @@ int X509_verify_ex(X509 *a, EVP_PKEY *r, OPENSSL_CTX *libctx, const char *propq)
         return 0;
 
     id = a->distinguishing_id;
-    if ((ctx = make_id_ctx(r, id, libctx, propq)) != NULL) {
+    if ((ctx = make_id_ctx(r, id, a->libctx, a->propq)) != NULL) {
         rv = ASN1_item_verify_ctx(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg,
                                   &a->signature, &a->cert_info, ctx);
         clean_id_ctx(ctx);
@@ -82,13 +82,8 @@ int X509_verify_ex(X509 *a, EVP_PKEY *r, OPENSSL_CTX *libctx, const char *propq)
     return rv;
 }
 
-int X509_verify(X509 *a, EVP_PKEY *r)
-{
-    return X509_verify_ex(a, r, NULL, NULL);
-}
-
-int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OPENSSL_CTX *libctx,
-                       const char *propq)
+int X509_REQ_verify_with_libctx(X509_REQ *a, EVP_PKEY *r, OPENSSL_CTX *libctx,
+                                const char *propq)
 {
     int rv = 0;
     EVP_MD_CTX *ctx = NULL;
@@ -105,7 +100,7 @@ int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OPENSSL_CTX *libctx,
 
 int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
 {
-    return X509_REQ_verify_ex(a, r, NULL, NULL);
+    return X509_REQ_verify_with_libctx(a, r, NULL, NULL);
 }
 
 int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r)
@@ -443,19 +438,19 @@ int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
     return EVP_Digest(key->data, key->length, md, len, type, NULL);
 }
 
-int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+int X509_digest(const X509 *cert, const EVP_MD *md, unsigned char *data,
                 unsigned int *len)
 {
-    if (type == EVP_sha1() && (data->ex_flags & EXFLAG_SET) != 0
-            && (data->ex_flags & EXFLAG_INVALID) == 0) {
+    if (EVP_MD_is_a(md, SN_sha1) && (cert->ex_flags & EXFLAG_SET) != 0
+            && (cert->ex_flags & EXFLAG_INVALID) == 0) {
         /* Asking for SHA1 and we already computed it. */
         if (len != NULL)
-            *len = sizeof(data->sha1_hash);
-        memcpy(md, data->sha1_hash, sizeof(data->sha1_hash));
+            *len = sizeof(cert->sha1_hash);
+        memcpy(data, cert->sha1_hash, sizeof(cert->sha1_hash));
         return 1;
     }
-    return (ASN1_item_digest
-            (ASN1_ITEM_rptr(X509), type, (char *)data, md, len));
+    return (asn1_item_digest_with_libctx(ASN1_ITEM_rptr(X509), md, (char *)cert,
+                                         data, len, cert->libctx, cert->propq));
 }
 
 /* calculate cert digest using the same hash algorithm as in its signature */
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 8a216c49cf..9358c46a7f 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -113,9 +113,38 @@ ASN1_SEQUENCE_ref(X509, x509_cb) = {
         ASN1_EMBED(X509, signature, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END_ref(X509, X509)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509)
+IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(X509, X509, X509)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509)
 
+X509 *d2i_X509(X509 **a, const unsigned char **in, long len)
+{
+    X509 *cert = NULL;
+
+    cert = (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (X509_it()));
+    /* Only cache the extensions if the cert object was passed in */
+    if (cert != NULL && a != NULL) {
+        if (!x509v3_cache_extensions(cert))
+            cert = NULL;
+    }
+    return cert;
+}
+int i2d_X509(const X509 *a, unsigned char **out)
+{
+    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (X509_it()));
+}
+
+X509 *X509_new_with_libctx(OPENSSL_CTX *libctx, const char *propq)
+{
+    X509 *cert = NULL;
+
+    cert = (X509 *)ASN1_item_new((X509_it()));
+    if (cert != NULL) {
+        cert->libctx = libctx;
+        cert->propq = propq;
+    }
+    return cert;
+}
+
 int X509_set_ex_data(X509 *r, int idx, void *arg)
 {
     return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
diff --git a/doc/man3/OSSL_STORE_LOADER.pod b/doc/man3/OSSL_STORE_LOADER.pod
index ad9544ebd1..64b15c18c8 100644
--- a/doc/man3/OSSL_STORE_LOADER.pod
+++ b/doc/man3/OSSL_STORE_LOADER.pod
@@ -32,19 +32,14 @@ unregister STORE loaders for different URI schemes
  /* struct ossl_store_loader_ctx_st is defined differently by each loader */
  typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
 
- typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const char *uri,
-                                                      const UI_METHOD *ui_method,
-                                                      void *ui_data);
+ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(
+     const char *uri, const UI_METHOD *ui_method, void *ui_data);
  int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *store_loader,
                                 OSSL_STORE_open_fn store_open_function);
- typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)(const OSSL_STORE_LOADER
-                                                        *loader,
-                                                        BIO *bio,
-                                                        OPENSSL_CTX *libctx,
-                                                        const char *propq,
-                                                        const UI_METHOD
-                                                        *ui_method,
-                                                        void *ui_data);
+ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)
+     (const OSSL_STORE_LOADER *loader, BIO *bio,
+      OPENSSL_CTX *libctx, const char *propq,
+      const UI_METHOD *ui_method, void *ui_data);
  int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader,
                                   OSSL_STORE_attach_fn attach_function);
  typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd,
diff --git a/doc/man3/OSSL_STORE_attach.pod b/doc/man3/OSSL_STORE_attach.pod
index 7df2804964..ae31202141 100644
--- a/doc/man3/OSSL_STORE_attach.pod
+++ b/doc/man3/OSSL_STORE_attach.pod
@@ -8,8 +8,8 @@ OSSL_STORE_attach - Functions to read objects from a BIO
 
  #include <openssl/store.h>
 
- OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, OPENSSL_CTX *libctx,
-                                   const char *scheme, const char *propq,
+ OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
+                                   OPENSSL_CTX *libctx, const char *propq,
                                    const UI_METHOD *ui_method, void *ui_data,
                                    OSSL_STORE_post_process_info_fn post_process,
                                    void *post_process_data);
diff --git a/doc/man3/OSSL_STORE_open.pod b/doc/man3/OSSL_STORE_open.pod
index 917a97822d..ef1a934194 100644
--- a/doc/man3/OSSL_STORE_open.pod
+++ b/doc/man3/OSSL_STORE_open.pod
@@ -2,9 +2,11 @@
 
 =head1 NAME
 
-OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn, OSSL_STORE_open,
-OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, OSSL_STORE_error,
-OSSL_STORE_close - Types and functions to read objects from a URI
+OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn,
+OSSL_STORE_open, OSSL_STORE_open_with_libctx,
+OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof,
+OSSL_STORE_error, OSSL_STORE_close
+- Types and functions to read objects from a URI
 
 =head1 SYNOPSIS
 
@@ -19,6 +21,11 @@ OSSL_STORE_close - Types and functions to read objects from a URI
                                  void *ui_data,
                                  OSSL_STORE_post_process_info_fn post_process,
                                  void *post_process_data);
+ OSSL_STORE_CTX *OSSL_STORE_open_with_libctx
+     (const char *uri, OPENSSL_CTX *libctx, const char *propq,
+      const UI_METHOD *ui_method, void *ui_data,
+      OSSL_STORE_post_process_info_fn post_process, void *post_process_data);
+
  int OSSL_STORE_ctrl(OSSL_STORE_CTX *ctx, int cmd, ... /* args */);
  OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx);
  int OSSL_STORE_eof(OSSL_STORE_CTX *ctx);
@@ -41,15 +48,17 @@ described in L<OSSL_STORE_INFO(3)>.
 =head2 Types
 
 B<OSSL_STORE_CTX> is a context variable that holds all the internal
-information for OSSL_STORE_open(), OSSL_STORE_load(), OSSL_STORE_eof() and
-OSSL_STORE_close() to work together.
+information for OSSL_STORE_open(), OSSL_STORE_open_with_libctx(),
+OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close() to work
+together.
 
 =head2 Functions
 
-OSSL_STORE_open() takes a uri or path I<uri>, password UI method
+OSSL_STORE_open_with_libctx() takes a uri or path I<uri>, password UI method
 I<ui_method> with associated data I<ui_data>, and post processing
 callback I<post_process> with associated data I<post_process_data>,
-opens a channel to the data located at that URI and returns a
+a library context I<libctx> with an associated property query <propq>,
+and opens a channel to the data located at the URI and returns a
 B<OSSL_STORE_CTX> with all necessary internal information.
 The given I<ui_method> and I<ui_data> will be reused by all
 functions that use B<OSSL_STORE_CTX> when interaction is needed,
@@ -61,6 +70,9 @@ will cause OSSL_STORE_load() to start its process over with loading
 the next object, until I<post_process> returns something other than
 NULL, or the end of data is reached as indicated by OSSL_STORE_eof().
 
+OSSL_STORE_open() is similar to OSSL_STORE_open_with_libctx() but uses NULL for
+the library context I<libctx> and property query <propq>.
+
 OSSL_STORE_ctrl() takes a B<OSSL_STORE_CTX>, and command number I<cmd> and
 more arguments not specified here.
 The available loader specific command numbers and arguments they each
@@ -81,8 +93,8 @@ Any other value is an error.
 
 =back
 
-OSSL_STORE_load() takes a B<OSSL_STORE_CTX>, tries to load the next available
-object and return it wrapped with  B<OSSL_STORE_INFO>.
+OSSL_STORE_load() takes a B<OSSL_STORE_CTX> and tries to load the next
+available object and return it wrapped with B<OSSL_STORE_INFO>.
 
 OSSL_STORE_eof() takes a B<OSSL_STORE_CTX> and checks if we've reached the end
 of data.
@@ -127,8 +139,8 @@ See L<passphrase-encoding(7)> for further information.
 OSSL_STORE_open() returns a pointer to a B<OSSL_STORE_CTX> on success, or
 NULL on failure.
 
-OSSL_STORE_load() returns a pointer to a B<OSSL_STORE_INFO> on success, or
-NULL on error or when end of data is reached.
+OSSL_STORE_load() returns a pointer to a B<OSSL_STORE_INFO> on success, or NULL
+on error or when end of data is reached.
 Use OSSL_STORE_error() and OSSL_STORE_eof() to determine the meaning of a
 returned NULL.
 
@@ -147,6 +159,8 @@ L<passphrase-encoding(7)>
 
 =head1 HISTORY
 
+OSSL_STORE_open_with_libctx() was added in OpenSSL 3.0.
+
 OSSL_STORE_CTX(), OSSL_STORE_post_process_info_fn(), OSSL_STORE_open(),
 OSSL_STORE_ctrl(), OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close()
 were added in OpenSSL 1.1.1.
diff --git a/doc/man3/PEM_X509_INFO_read_bio_with_libctx.pod b/doc/man3/PEM_X509_INFO_read_bio_with_libctx.pod
new file mode 100644
index 0000000000..6c729109e3
--- /dev/null
+++ b/doc/man3/PEM_X509_INFO_read_bio_with_libctx.pod
@@ -0,0 +1,65 @@
+=pod
+
+=head1 NAME
+
+PEM_X509_INFO_read_bio_with_libctx, PEM_X509_INFO_read_with_libctx
+- read a PEM-encoded data structure from a bio into one or more B<X509_INFO>
+object's
+
+=head1 SYNOPSIS
+
+ #include <openssl/pem.h>
+
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read_with_libctx(FILE *fp,
+                                                     STACK_OF(X509_INFO) *sk,
+                                                     pem_password_cb *cb,
+                                                     void *u,
+                                                     OPENSSL_CTX *libctx,
+                                                     const char *propq);
+
+ STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio_with_libctx(BIO *bio,
+                                                         STACK_OF(X509_INFO) *sk,
+                                                         pem_password_cb *cb,
+                                                         void *u,
+                                                         OPENSSL_CTX *libctx,
+                                                         const char *propq);
+
+=head1 DESCRIPTION
+
+The loaded B<X509_INFO> object's can contain a CRL, a certificate and a
+corresponding private key.
+
+PEM_X509_INFO_read_with_libctx() loads the B<X509_INFO> objects from a file I<fp>.
+The library context I<libctx> and property query <propq> are used for fetching
+algorithms from providers.
+
+PEM_X509_INFO_read_bio_with_libctx loads the B<X509_INFO> objects using a bio
+I<bp>. The library context I<libctx> and property query <propq> are used for
+fetching algorithms from providers.
+
+
+=head1 RETURN VALUES
+
+PEM_X509_INFO_read_with_libctx() and PEM_X509_INFO_read_bio_with_libctx() return
+a stack of B<X509_INFO> objects or NULL on failure.
+
+=head1 SEE ALSO
+
+L<PEM_read_bio_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+The functions PEM_X509_INFO_read_with_libctx() and
+PEM_X509_INFO_read_bio_with_libctx() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod
index 65ba8a8a83..960a7df89e 100644
--- a/doc/man3/PEM_read_bio_PrivateKey.pod
+++ b/doc/man3/PEM_read_bio_PrivateKey.pod
@@ -425,6 +425,16 @@ The write routines return 1 for success or 0 for failure.
 Although the PEM routines take several arguments in almost all applications
 most of them are set to 0 or NULL.
 
+To read a certificate with a library context in PEM format from a BIO:
+
+ X509 *x = X509_new_with_libctx(libctx, NULL);
+
+ if (x == NULL)
+     /* Error */
+
+ if (PEM_read_bio_X509(bp, &x, 0, NULL) == NULL)
+     /* Error */
+
 Read a certificate in PEM format from a BIO:
 
  X509 *x;
diff --git a/doc/man3/SSL_load_client_CA_file.pod b/doc/man3/SSL_load_client_CA_file.pod
index 488bb61c13..892e362a65 100644
--- a/doc/man3/SSL_load_client_CA_file.pod
+++ b/doc/man3/SSL_load_client_CA_file.pod
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-SSL_load_client_CA_file,
+SSL_load_client_CA_file_with_libctx, SSL_load_client_CA_file,
 SSL_add_file_cert_subjects_to_stack,
 SSL_add_dir_cert_subjects_to_stack,
 SSL_add_store_cert_subjects_to_stack
@@ -12,6 +12,9 @@ SSL_add_store_cert_subjects_to_stack
 
  #include <openssl/ssl.h>
 
+ STACK_OF(X509_NAME) *SSL_load_client_CA_file_with_libctx(const char *file,
+                                                          OPENSSL_CTX *libctx,
+                                                          const char *propq);
  STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
 
  int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
@@ -23,8 +26,12 @@ SSL_add_store_cert_subjects_to_stack
 
 =head1 DESCRIPTION
 
-SSL_load_client_CA_file() reads certificates from I<file> and returns
-a STACK_OF(X509_NAME) with the subject names found.
+SSL_load_client_CA_file_with_libctx() reads certificates from I<file> and returns
+a STACK_OF(X509_NAME) with the subject names found. The library context I<libctx>
+and property query <propq> are used when fetching algorithms from providers.
+
+SSL_load_client_CA_file() is similar to SSL_load_client_CA_file_with_libctx()
+but uses NULL for the library context I<libctx> and property query <propq>.
 
 SSL_add_file_cert_subjects_to_stack() reads certificates from I<file>,
 and adds their subject name to the already existing I<stack>.
@@ -84,7 +91,8 @@ L<SSL_CTX_set_client_CA_list(3)>
 
 =head1 HISTORY
 
-SSL_add_store_cert_subjects_to_stack() was added in OpenSSL 3.0.
+SSL_load_client_CA_file_with_libctx() and SSL_add_store_cert_subjects_to_stack()
+were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/X509_LOOKUP.pod b/doc/man3/X509_LOOKUP.pod
index bd7470d2ba..a89b94aa48 100644
--- a/doc/man3/X509_LOOKUP.pod
+++ b/doc/man3/X509_LOOKUP.pod
@@ -6,10 +6,13 @@ X509_LOOKUP, X509_LOOKUP_TYPE,
 X509_LOOKUP_new, X509_LOOKUP_free, X509_LOOKUP_init,
 X509_LOOKUP_shutdown,
 X509_LOOKUP_set_method_data, X509_LOOKUP_get_method_data,
-X509_LOOKUP_ctrl,
-X509_LOOKUP_load_file, X509_LOOKUP_add_dir, X509_LOOKUP_add_store,
-X509_LOOKUP_load_store,
-X509_LOOKUP_get_store, X509_LOOKUP_by_subject,
+X509_LOOKUP_ctrl_with_libctx, X509_LOOKUP_ctrl,
+X509_LOOKUP_load_file_with_libctx, X509_LOOKUP_load_file,
+X509_LOOKUP_add_dir,
+X509_LOOKUP_add_store_with_libctx, X509_LOOKUP_add_store,
+X509_LOOKUP_load_store_with_libctx, X509_LOOKUP_load_store,
+X509_LOOKUP_get_store,
+X509_LOOKUP_by_subject_with_libctx, X509_LOOKUP_by_subject,
 X509_LOOKUP_by_issuer_serial, X509_LOOKUP_by_fingerprint,
 X509_LOOKUP_by_alias
 - OpenSSL certificate lookup mechanisms
@@ -30,15 +33,29 @@ X509_LOOKUP_by_alias
  int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
  void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);
 
+ int X509_LOOKUP_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd, const char *argc,
+                                  long argl, char **ret, OPENSSL_CTX *libctx,
+                                  const char *propq);
  int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                       long argl, char **ret);
+ int X509_LOOKUP_load_file_with_libctx(X509_LOOKUP *ctx, char *name, long type,
+                                       OPENSSL_CTX *libctx, const char *propq);
  int X509_LOOKUP_load_file(X509_LOOKUP *ctx, char *name, long type);
+ int X509_LOOKUP_load_file_with_libctx(X509_LOOKUP *ctx, char *name, long type,
+                                       OPENSSL_CTX *libctx, const char *propq);
  int X509_LOOKUP_add_dir(X509_LOOKUP *ctx, char *name, long type);
+ int X509_LOOKUP_add_store_with_libctx(X509_LOOKUP *ctx, char *uri,
+                                       OPENSSL_CTX *libctx, const char *propq);
  int X509_LOOKUP_add_store(X509_LOOKUP *ctx, char *uri);
+ int X509_LOOKUP_load_store_with_libctx(X509_LOOKUP *ctx, char *uri,
+                                        OPENSSL_CTX *libctx, const char *propq);
  int X509_LOOKUP_load_store(X509_LOOKUP *ctx, char *uri);
 
  X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);
 
+ int X509_LOOKUP_by_subject_with_libctx(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                                        const X509_NAME *name, X509_OBJECT *ret,
+                                        OPENSSL_CTX *libctx, const char *propq);
  int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                             const X509_NAME *name, X509_OBJECT *ret);
  int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
@@ -74,22 +91,30 @@ X509_LOOKUP_set_method_data() and X509_LOOKUP_get_method_data()
 associates and retrieves a pointer to application data to and from the
 given B<X509_LOOKUP>, respectively.
 
-X509_LOOKUP_ctrl() is used to set or get additional data to or from a
-B<X509_LOOKUP> structure or its associated L<X509_LOOKUP_METHOD(3)>.
+X509_LOOKUP_ctrl_with_libctx() is used to set or get additional data to or from
+a B<X509_LOOKUP> structure or its associated L<X509_LOOKUP_METHOD(3)>.
 The arguments of the control command are passed via I<argc> and I<argl>,
-its return value via I<*ret>.
+its return value via I<*ret>. The library context I<libctx> and property
+query <propq> are used when fetching algorithms from providers.
 The meaning of the arguments depends on the I<cmd> number of the
 control command. In general, this function is not called directly, but
 wrapped by a macro call, see below.
 The control I<cmd>s known to OpenSSL are discussed in more depth
 in L</Control Commands>.
 
-X509_LOOKUP_load_file() passes a filename to be loaded immediately
-into the associated B<X509_STORE>.
+X509_LOOKUP_ctrl() is similar to X509_LOOKUP_ctrl_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
+
+X509_LOOKUP_load_file_with_libctx() passes a filename to be loaded immediately
+into the associated B<X509_STORE>. The library context I<libctx> and property
+query <propq> are used when fetching algorithms from providers.
 I<type> indicates what type of object is expected.
 This can only be used with a lookup using the implementation
 L<X509_LOOKUP_file(3)>.
 
+X509_LOOKUP_load_file() is similar to X509_LOOKUP_load_file_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
+
 X509_LOOKUP_add_dir() passes a directory specification from which
 certificates and CRLs are loaded on demand into the associated
 B<X509_STORE>.
@@ -97,38 +122,50 @@ I<type> indicates what type of object is expected.
 This can only be used with a lookup using the implementation
 L<X509_LOOKUP_hash_dir(3)>.
 
-X509_LOOKUP_add_store() passes a URI for a directory-like structure
+X509_LOOKUP_add_store_with_libctx() passes a URI for a directory-like structure
 from which containers with certificates and CRLs are loaded on demand
-into the associated B<X509_STORE>.
-X509_LOOKUP_load_store() passes a URI for a single container from
+into the associated B<X509_STORE>. The library context I<libctx> and property
+query <propq> are used when fetching algorithms from providers.
+
+X509_LOOKUP_add_store() is similar to X509_LOOKUP_add_store_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
+
+X509_LOOKUP_load_store_with_libctx() passes a URI for a single container from
 which certificates and CRLs are immediately loaded into the associated
-B<X509_STORE>.
+B<X509_STORE>. The library context I<libctx> and property query <propq> are used
+when fetching algorithms from providers.
 These functions can only be used with a lookup using the
 implementation L<X509_LOOKUP_store(3)>.
 
-X509_LOOKUP_load_file(), X509_LOOKUP_add_dir(),
-X509_LOOKUP_add_store(), and X509_LOOKUP_load_store() are implemented
-as macros that use X509_LOOKUP_ctrl().
+X509_LOOKUP_load_store() is similar to X509_LOOKUP_load_store_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
 
-X509_LOOKUP_by_subject(), X509_LOOKUP_by_issuer_serial(),
-X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() look up
-certificates and CRLs in the L<X509_STORE(3)> associated with the
-B<X509_LOOKUP> using different criteria, where the looked up object is
-stored in I<ret>.
+X509_LOOKUP_load_file_with_libctx(), X509_LOOKUP_load_file(),
+X509_LOOKUP_add_dir(),
+X509_LOOKUP_add_store_with_libctx() X509_LOOKUP_add_store(),
+X509_LOOKUP_load_store_with_libctx() and X509_LOOKUP_load_store() are
+implemented as macros that use X509_LOOKUP_ctrl().
+
+X509_LOOKUP_by_subject_with_libctx(), X509_LOOKUP_by_subject(),
+X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and
+X509_LOOKUP_by_alias() look up certificates and CRLs in the L<X509_STORE(3)>
+associated with the B<X509_LOOKUP> using different criteria, where the looked up
+object is stored in I<ret>.
 Some of the underlying B<X509_LOOKUP_METHOD>s will also cache objects
 matching the criteria in the associated B<X509_STORE>, which makes it
 possible to handle cases where the criteria have more than one hit.
 
 =head2 Control Commands
 
-The B<X509_LOOKUP_METHOD>s built into OpenSSL recognise the following
+The B<X509_LOOKUP_METHOD>s built into OpenSSL recognize the following
 X509_LOOKUP_ctrl() I<cmd>s:
 
 =over 4
 
 =item B<X509_L_FILE_LOAD>
 
-This is the command that X509_LOOKUP_load_file() uses.
+This is the command that X509_LOOKUP_load_file_with_libctx() and
+X509_LOOKUP_load_file() use.
 The filename is passed in I<argc>, and the type in I<argl>.
 
 =item B<X509_L_ADD_DIR>
@@ -139,12 +176,14 @@ I<argl>.
 
 =item B<X509_L_ADD_STORE>
 
-This is the command that X509_LOOKUP_add_store() uses.
+This is the command that X509_LOOKUP_add_store_with_libctx() and
+X509_LOOKUP_add_store() use.
 The URI is passed in I<argc>.
 
 =item B<X509_L_LOAD_STORE>
 
-This is the command that X509_LOOKUP_load_store() uses.
+This is the command that X509_LOOKUP_load_store_with_libctx() and
+X509_LOOKUP_load_store() use.
 The URI is passed in I<argc>.
 
 =back
@@ -167,10 +206,10 @@ error.
 X509_LOOKUP_get_store() returns a B<X509_STORE> pointer if there is
 one, otherwise NULL.
 
-X509_LOOKUP_by_subject(), X509_LOOKUP_by_issuer_serial(),
-X509_LOOKUP_by_fingerprint(), and X509_LOOKUP_by_alias() all return 0
-if there is no B<X509_LOOKUP_METHOD> or that method doesn't implement
-the corresponding function.
+X509_LOOKUP_by_subject_with_libctx(), X509_LOOKUP_by_subject(),
+X509_LOOKUP_by_issuer_serial(), X509_LOOKUP_by_fingerprint(), and
+X509_LOOKUP_by_alias() all return 0 if there is no B<X509_LOOKUP_METHOD> or that
+method doesn't implement the corresponding function.
 Otherwise, it returns what the corresponding function in the
 B<X509_LOOKUP_METHOD> returns, which is usually 1 on success and 0 in
 error.
@@ -179,6 +218,15 @@ error.
 
 L<X509_LOOKUP_METHOD(3)>, L<X509_STORE(3)>
 
+=head1 HISTORY
+
+The functions X509_LOOKUP_by_subject_with_libctx() and
+X509_LOOKUP_ctrl_with_libctx() were added in OpenSSL 3.0.
+
+The macros X509_LOOKUP_load_file_with_libctx(),
+X509_LOOKUP_load_store_with_libctx() and 509_LOOKUP_add_store_with_libctx() were
+added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_LOOKUP_hash_dir.pod b/doc/man3/X509_LOOKUP_hash_dir.pod
index 199afa3658..7077b9b59e 100644
--- a/doc/man3/X509_LOOKUP_hash_dir.pod
+++ b/doc/man3/X509_LOOKUP_hash_dir.pod
@@ -3,10 +3,10 @@
 =head1 NAME
 
 X509_LOOKUP_hash_dir, X509_LOOKUP_file, X509_LOOKUP_store,
-X509_load_cert_file,
+X509_load_cert_file_with_libctx, X509_load_cert_file,
 X509_load_crl_file,
-X509_load_cert_crl_file - Default OpenSSL certificate
-lookup methods
+X509_load_cert_crl_file_with_libctx, X509_load_cert_crl_file
+- Default OpenSSL certificate lookup methods
 
 =head1 SYNOPSIS
 
@@ -16,8 +16,14 @@ lookup methods
  X509_LOOKUP_METHOD *X509_LOOKUP_file(void);
  X509_LOOKUP_METHOD *X509_LOOKUP_store(void);
 
+ int X509_load_cert_file_with_libctx(X509_LOOKUP *ctx, const char *file,
+                                     int type, OPENSSL_CTX *libctx,
+                                     const char *propq);
  int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
  int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+ int X509_load_cert_crl_file_with_libctx(X509_LOOKUP *ctx, const char *file,
+                                         int type, OPENSSL_CTX *libctx,
+                                         const char *propq);
  int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
 
 =head1 DESCRIPTION
@@ -145,7 +151,9 @@ L<ossl_store(7)>
 
 =head1 HISTORY
 
-B<X509_LOOKUP_store> was added in OpenSSL 3.0.
+The functions X509_load_cert_file_with_libctx(),
+X509_load_cert_crl_file_with_libctx() and X509_LOOKUP_store() were added in
+OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/X509_STORE_add_cert.pod b/doc/man3/X509_STORE_add_cert.pod
index ce50e368e7..011cd94711 100644
--- a/doc/man3/X509_STORE_add_cert.pod
+++ b/doc/man3/X509_STORE_add_cert.pod
@@ -6,9 +6,10 @@ X509_STORE,
 X509_STORE_add_cert, X509_STORE_add_crl, X509_STORE_set_depth,
 X509_STORE_set_flags, X509_STORE_set_purpose, X509_STORE_set_trust,
 X509_STORE_add_lookup,
-X509_STORE_load_file, X509_STORE_load_path, X509_STORE_load_store,
-X509_STORE_set_default_paths,
-X509_STORE_load_locations
+X509_STORE_load_file_with_libctx, X509_STORE_load_file, X509_STORE_load_path,
+X509_STORE_load_store_with_libctx, X509_STORE_load_store,
+X509_STORE_set_default_paths_with_libctx, X509_STORE_set_default_paths,
+X509_STORE_load_locations_with_libctx, X509_STORE_load_locations
 - X509_STORE manipulation
 
 =head1 SYNOPSIS
@@ -27,11 +28,21 @@ X509_STORE_load_locations
  X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *store,
                                     X509_LOOKUP_METHOD *meth);
 
+ int X509_STORE_set_default_paths_with_libctx(X509_STORE *ctx,
+                                              OPENSSL_CTX *libctx,
+                                              const char *propq);
  int X509_STORE_set_default_paths(X509_STORE *ctx);
+ int X509_STORE_load_file_with_libctx(X509_STORE *ctx, const char *file,
+                                     OPENSSL_CTX *libctx, const char *propq);
  int X509_STORE_load_file(X509_STORE *ctx, const char *file);
  int X509_STORE_load_path(X509_STORE *ctx, const char *dir);
+ int X509_STORE_load_store_with_libctx(X509_STORE *ctx, const char *uri,
+                                       OPENSSL_CTX *libctx, const char *propq);
  int X509_STORE_load_store(X509_STORE *ctx, const char *uri);
-
+ int X509_STORE_load_locations_with_libctx(X509_STORE *ctx,
+                                           const char *file, const char *dir,
+                                           OPENSSL_CTX *libctx,
+                                           const char *propq);
  int X509_STORE_load_locations(X509_STORE *ctx,
                                const char *file, const char *dir);
 
@@ -82,35 +93,54 @@ L<X509_LOOKUP_METHOD(3)> I<meth> and adds it to the B<X509_STORE>
 I<store>.  This also associates the B<X509_STORE> with the lookup, so
 B<X509_LOOKUP> functions can look up objects in that store.
 
-X509_STORE_load_file() loads trusted certificate(s) into an
-B<X509_STORE> from a given file.
+X509_STORE_load_file_with_libctx() loads trusted certificate(s) into an
+B<X509_STORE> from a given file. The library context I<libctx> and property
+query <propq> are used when fetching algorithms from providers.
+
+X509_STORE_load_file() is similar to X509_STORE_load_file_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
 
 X509_STORE_load_path() loads trusted certificate(s) into an
 B<X509_STORE> from a given directory path.
 The certificates in the directory must be in hashed form, as
 documented in L<X509_LOOKUP_hash_dir(3)>.
 
-X509_STORE_load_store() loads trusted certificate(s) into an
-B<X509_STORE> from a store at a given URI.
+X509_STORE_load_store_with_libctx() loads trusted certificate(s) into an
+B<X509_STORE> from a store at a given URI. The library context I<libctx> and
+property query <propq> are used when fetching algorithms from providers.
 
-X509_STORE_load_locations() combines X509_STORE_load_file() and
-X509_STORE_load_dir() for a given file and/or directory path.
+X509_STORE_load_store() is similar to X509_STORE_load_store_with_libctx() but
+uses NULL for the library context I<libctx> and property query <propq>.
+
+X509_STORE_load_locations_with_libctx() combines
+X509_STORE_load_file_with_libctx() and X509_STORE_load_dir() for a given file
+and/or directory path.
 It is permitted to specify just a file, just a directory, or both
 paths.
 
-X509_STORE_set_default_paths() is somewhat misnamed, in that it does not
-set what default paths should be used for loading certificates.  Instead,
+X509_STORE_load_locations() is similar to X509_STORE_load_locations_with_libctx()
+but uses NULL for the library context I<libctx> and property query <propq>.
+
+X509_STORE_set_default_paths_with_libctx() is somewhat misnamed, in that it does
+not set what default paths should be used for loading certificates.  Instead,
 it loads certificates into the B<X509_STORE> from the hardcoded default
-paths.
+paths. The library context I<libctx> and property query <propq> are used when
+fetching algorithms from providers.
+
+X509_STORE_set_default_paths() is similar to
+X509_STORE_set_default_paths_with_libctx() but uses NULL for the library
+context I<libctx> and property query <propq>.
 
 =head1 RETURN VALUES
 
 X509_STORE_add_cert(), X509_STORE_add_crl(), X509_STORE_set_depth(),
-X509_STORE_set_flags(), X509_STORE_set_purpose(),
-X509_STORE_set_trust(), X509_STORE_load_file(),
-X509_STORE_load_path(), X509_STORE_load_store(),
-X509_STORE_load_locations(), and X509_STORE_set_default_paths() return
-1 on success or 0 on failure.
+X509_STORE_set_flags(), X509_STORE_set_purpose(), X509_STORE_set_trust(),
+X509_STORE_load_file_with_libctx(), X509_STORE_load_file(),
+X509_STORE_load_path(),
+X509_STORE_load_store_with_libctx(), X509_STORE_load_store(),
+X509_STORE_load_locations_with_libctx(), X509_STORE_load_locations(),
+X509_STORE_set_default_paths_with_libctx() and X509_STORE_set_default_paths()
+return 1 on success or 0 on failure.
 
 X509_STORE_add_lookup() returns the found or created
 L<X509_LOOKUP(3)>, or NULL on error.
@@ -122,6 +152,12 @@ L<X509_VERIFY_PARAM_set_depth(3)>.
 L<X509_STORE_new(3)>,
 L<X509_STORE_get0_param(3)>
 
+=head1 HISTORY
+
+The functions X509_STORE_set_default_paths_with_libctx(),
+X509_STORE_load_file_with_libctx(), X509_STORE_load_store_with_libctx() and
+X509_STORE_load_locations_with_libctx() were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_STORE_new.pod b/doc/man3/X509_STORE_new.pod
index ccc3b06061..31d466faa4 100644
--- a/doc/man3/X509_STORE_new.pod
+++ b/doc/man3/X509_STORE_new.pod
@@ -2,8 +2,9 @@
 
 =head1 NAME
 
-X509_STORE_new, X509_STORE_up_ref, X509_STORE_free, X509_STORE_lock,
-X509_STORE_unlock - X509_STORE allocation, freeing and locking functions
+X509_STORE_new, X509_STORE_up_ref, X509_STORE_free,
+X509_STORE_lock,X509_STORE_unlock
+- X509_STORE allocation, freeing and locking functions
 
 =head1 SYNOPSIS
 
@@ -48,7 +49,7 @@ functions were added in OpenSSL 1.1.0.
 
 =head1 COPYRIGHT
 
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/doc/man3/X509_new.pod b/doc/man3/X509_new.pod
index e6967dc04d..798f7a7760 100644
--- a/doc/man3/X509_new.pod
+++ b/doc/man3/X509_new.pod
@@ -3,13 +3,15 @@
 =head1 NAME
 
 X509_chain_up_ref,
-X509_new, X509_free, X509_up_ref - X509 certificate ASN1 allocation functions
+X509_new, X509_new_with_libctx,
+X509_free, X509_up_ref - X509 certificate ASN1 allocation functions
 
 =head1 SYNOPSIS
 
  #include <openssl/x509.h>
 
  X509 *X509_new(void);
+ X509 *X509_new_with_libctx(OPENSSL_CTX *libctx, const char *propq);
  void X509_free(X509 *a);
  int X509_up_ref(X509 *a);
  STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *x);
@@ -19,8 +21,15 @@ X509_new, X509_free, X509_up_ref - X509 certificate ASN1 allocation functions
 The X509 ASN1 allocation routines, allocate and free an
 X509 structure, which represents an X509 certificate.
 
-X509_new() allocates and initializes a X509 structure with reference count
-B<1>.
+X509_new_with_libctx() allocates and initializes a X509 structure with a
+library context of I<libctx>, property query of <propq> and a reference
+count of B<1>. Many X509 functions such as X509_check_purpose(), and
+X509_verify() use this library context to select which providers supply the
+fetched algorithms (SHA1 is used internally).
+
+X509_new() is similar to X509_new_with_libctx() but sets the library context
+and property query to NULL. This results in the default (NULL) library context
+being used for any X509 operations requiring algorithm fetches.
 
 X509_free() decrements the reference count of B<X509> structure B<a> and
 frees it up if the reference count is zero. If B<a> is NULL nothing is done.
@@ -71,6 +80,10 @@ L<X509_sign(3)>,
 L<X509V3_get_d2i(3)>,
 L<X509_verify_cert(3)>
 
+=head1 HISTORY
+
+The function X509_new_with_libctx() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/X509_sign.pod b/doc/man3/X509_sign.pod
index 5f621a11e4..a97cbebbef 100644
--- a/doc/man3/X509_sign.pod
+++ b/doc/man3/X509_sign.pod
@@ -54,8 +54,8 @@ L<ERR_get_error(3)>,
 L<X509_NAME_add_entry_by_txt(3)>,
 L<X509_new(3)>,
 L<X509_verify_cert(3)>,
-L<X509_verify_ex(3)>, L<X509_verify(3)>,
-L<X509_REQ_verify_ex(3)>, L<X509_REQ_verify(3)>,
+L<X509_verify(3)>,
+L<X509_REQ_verify_with_libctx(3)>, L<X509_REQ_verify(3)>,
 L<X509_CRL_verify(3)>
 
 =head1 HISTORY
diff --git a/doc/man3/X509_verify.pod b/doc/man3/X509_verify.pod
index e0028473a2..2c8fb0059e 100644
--- a/doc/man3/X509_verify.pod
+++ b/doc/man3/X509_verify.pod
@@ -2,8 +2,8 @@
 
 =head1 NAME
 
-X509_verify_ex, X509_verify, X509_self_signed,
-X509_REQ_verify_ex, X509_REQ_verify,
+X509_verify, X509_self_signed,
+X509_REQ_verify_with_libctx, X509_REQ_verify,
 X509_CRL_verify -
 verify certificate, certificate request, or CRL signature
 
@@ -11,26 +11,19 @@ verify certificate, certificate request, or CRL signature
 
  #include <openssl/x509.h>
 
- int X509_verify_ex(X509 *x, EVP_PKEY *pkey,
-                    OPENSSL_CTX *libctx, const char *propq);
  int X509_verify(X509 *x, EVP_PKEY *pkey);
  int X509_self_signed(X509 *cert, int verify_signature);
 
- int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *pkey,
-                        OPENSSL_CTX *libctx, const char *propq);
+ int X509_REQ_verify_with_libctx(X509_REQ *a, EVP_PKEY *pkey,
+                                 OPENSSL_CTX *libctx, const char *propq);
  int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
  int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
 
 =head1 DESCRIPTION
 
-X509_verify_ex() verifies the signature of certificate I<x> using public key
-I<pkey>. Any cryptographic algorithms required for the verification are fetched
-using the library context I<libctx> and the property query string I<propq>.
-Only the signature is checked:
-no other checks (such as certificate chain validity) are performed.
-
-X509_verify() is the same as X509_verify_ex() except that the default library
-context and property query string are used.
+X509_verify() verifies the signature of certificate I<x> using public key
+I<pkey>. Only the signature is checked: no other checks (such as certificate
+chain validity) are performed.
 
 X509_self_signed() checks whether a certificate is self-signed.
 For success the issuer and subject names must match, the components of the
@@ -38,13 +31,13 @@ authority key identifier (if present) must match the subject key identifier etc.
 The signature itself is actually verified only if B<verify_signature> is 1, as
 for explicitly trusted certificates this verification is not worth the effort.
 
-X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify()
+X509_REQ_verify_with_libctx(), X509_REQ_verify() and X509_CRL_verify()
 verify the signatures of certificate requests and CRLs, respectively.
 
 =head1 RETURN VALUES
 
-X509_verify_ex(), X509_verify(),
-X509_REQ_verify_ex(), X509_REQ_verify() and X509_CRL_verify()
+X509_verify(),
+X509_REQ_verify_with_libctx(), X509_REQ_verify() and X509_CRL_verify()
 return 1 if the signature is valid and 0 if the signature check fails.
 If the signature could not be checked at all because it was ill-formed
 or some other error occurred then -1 is returned.
@@ -75,8 +68,7 @@ L<OPENSSL_CTX(3)>
 The X509_verify(), X509_REQ_verify(), and X509_CRL_verify()
 functions are available in all versions of OpenSSL.
 
-X509_verify_ex(), X509_REQ_verify_ex(), and X509_self_signed()
-were added in OpenSSL 3.0.
+X509_REQ_verify_with_libctx(), and X509_self_signed() were added in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/X509v3_cache_extensions.pod b/doc/man3/X509v3_cache_extensions.pod
deleted file mode 100644
index 766ab50d28..0000000000
--- a/doc/man3/X509v3_cache_extensions.pod
+++ /dev/null
@@ -1,44 +0,0 @@
-=pod
-
-=head1 NAME
-
-X509v3_cache_extensions
-- cache info on various X.509v3 extensions and further derived certificate data
-
-=head1 SYNOPSIS
-
- #include <openssl/x509v3.h>
-
- int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq);
-
-=head1 DESCRIPTION
-
-This function processes any X509v3 extensions that might be present in an X509
-object and caches the result of that processing as well as further derived info,
-for instance if the certificate is self-issued. Many OpenSSL functions that use
-an X509 object will cause extensions to be processed and cached implicitly. If
-this is done implicitly then the default library context and property query
-string will be used. In some cases it may be desirable to use some other library
-context and property query string. If so then an application can call
-X509v3_cache_extensions() explicitly. This should be done before any function
-that needs to use those extensions is called - otherwise calling
-X509v3_cache_extensions() will have no effect. Typically this means calling this
-soon after creation of the X509 object. The X509 object to be processed is
-given in I<x> and the library context and property query string to use are given
-in I<libctx> and I<propq>.
-
-=head1 RETURN VALUES
-
-This function returns 0 if the extensions are invalid or an error occurred.
-Otherwise it returns 1.
-
-=head1 COPYRIGHT
-
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
-
-Licensed under the Apache License 2.0 (the "License").  You may not use
-this file except in compliance with the License.  You can obtain a copy
-in the file LICENSE in the source distribution or at
-L<https://www.openssl.org/source/license.html>.
-
-=cut
diff --git a/doc/man7/x509.pod b/doc/man7/x509.pod
index 095203c912..b2d2902744 100644
--- a/doc/man7/x509.pod
+++ b/doc/man7/x509.pod
@@ -52,6 +52,7 @@ L<X509_NAME_add_entry_by_txt(3)>,
 L<X509_NAME_add_entry_by_NID(3)>,
 L<X509_NAME_print_ex(3)>,
 L<X509_NAME_new(3)>,
+L<PEM_X509_INFO_read(3)>,
 L<d2i_X509(3)>,
 L<d2i_X509_ALGOR(3)>,
 L<d2i_X509_CRL(3)>,
@@ -62,7 +63,7 @@ L<crypto(7)>
 
 =head1 COPYRIGHT
 
-Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2003-2020 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the Apache License 2.0 (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/include/crypto/store.h b/include/crypto/store.h
index c47581a508..8bd2bc022f 100644
--- a/include/crypto/store.h
+++ b/include/crypto/store.h
@@ -14,16 +14,6 @@
 # include <openssl/store.h>
 # include <openssl/ui.h>
 
-/*
- * Two functions to read PEM data off an already opened BIO.  To be used
- * instead of OSSLSTORE_open() and OSSLSTORE_close().  Everything is done
- * as usual with OSSLSTORE_load() and OSSLSTORE_eof().
- */
-OSSL_STORE_CTX *ossl_store_attach_pem_bio(BIO *bp, const UI_METHOD *ui_method,
-                                          void *ui_data, OPENSSL_CTX *libctx,
-                                          const char *propq);
-int ossl_store_detach_pem_bio(OSSL_STORE_CTX *ctx);
-
 void ossl_store_cleanup_int(void);
 
 #endif
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 611713f221..71a67df650 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -189,6 +189,9 @@ struct x509_st {
 
     /* Set on live certificates for authentication purposes */
     ASN1_OCTET_STRING *distinguishing_id;
+
+    OPENSSL_CTX *libctx;
+    const char *propq;
 } /* X509 */ ;
 
 /*
@@ -295,9 +298,11 @@ struct x509_object_st {
 int a2i_ipadd(unsigned char *ipout, const char *ipasc);
 int x509_set1_time(ASN1_TIME **ptm, const ASN1_TIME *tm);
 int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags);
+int x509v3_cache_extensions(X509 *x);
 
 void x509_init_sig_info(X509 *x);
 
-
-int x509_check_issued_int(X509 *issuer, X509 *subject, OPENSSL_CTX *libctx,
-                          const char *propq);
+int asn1_item_digest_with_libctx(const ASN1_ITEM *it, const EVP_MD *type,
+                                 void *data, unsigned char *md,
+                                 unsigned int *len, OPENSSL_CTX *libctx,
+                                 const char *propq);
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index fb63b93db8..f4989e3987 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -286,6 +286,11 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
 
 STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
                                             pem_password_cb *cb, void *u);
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_bio_with_libctx(BIO *bp, STACK_OF(X509_INFO) *sk,
+                                    pem_password_cb *cb, void *u,
+                                    OPENSSL_CTX *libctx, const char *propq);
+
 int PEM_X509_INFO_write_bio(BIO *bp, const X509_INFO *xi, EVP_CIPHER *enc,
                             const unsigned char *kstr, int klen,
                             pem_password_cb *cd, void *u);
@@ -303,6 +308,10 @@ int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
                    pem_password_cb *callback, void *u);
 STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
                                         pem_password_cb *cb, void *u);
+STACK_OF(X509_INFO)
+*PEM_X509_INFO_read_with_libctx(FILE *fp, STACK_OF(X509_INFO) *sk,
+                                pem_password_cb *cb, void *u,
+                                OPENSSL_CTX *libctx, const char *propq);
 #endif
 
 int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type);
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index c030346760..bc003bc4fa 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1629,6 +1629,9 @@ __owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
 __owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
 __owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
 __owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
+__owur STACK_OF(X509_NAME)
+*SSL_load_client_CA_file_with_libctx(const char *file,
+                                     OPENSSL_CTX *libctx, const char *propq);
 __owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
                                                const char *file);
 int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
diff --git a/include/openssl/store.h b/include/openssl/store.h
index ffea2df15b..d5e72a0963 100644
--- a/include/openssl/store.h
+++ b/include/openssl/store.h
@@ -57,6 +57,11 @@ OSSL_STORE_CTX *OSSL_STORE_open(const char *uri, const UI_METHOD *ui_method,
                                 OSSL_STORE_post_process_info_fn post_process,
                                 void *post_process_data);
 
+OSSL_STORE_CTX *OSSL_STORE_open_with_libctx
+    (const char *uri, OPENSSL_CTX *libctx, const char *propq,
+     const UI_METHOD *ui_method, void *ui_data,
+     OSSL_STORE_post_process_info_fn post_process, void *post_process_data);
+
 /*
  * Control / fine tune the OSSL_STORE channel.  |cmd| determines what is to be
  * done, and depends on the underlying loader (use OSSL_STORE_get0_scheme to
@@ -115,8 +120,8 @@ int OSSL_STORE_close(OSSL_STORE_CTX *ctx);
  * Note that this function is considered unsafe, all depending on what the
  * BIO actually reads.
  */
-OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, OPENSSL_CTX *libctx,
-                                  const char *scheme, const char *propq,
+OSSL_STORE_CTX *OSSL_STORE_attach(BIO *bio, const char *scheme,
+                                  OPENSSL_CTX *libctx, const char *propq,
                                   const UI_METHOD *ui_method, void *ui_data,
                                   OSSL_STORE_post_process_info_fn post_process,
                                   void *post_process_data);
@@ -239,21 +244,20 @@ const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader);
 const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader);
 /* struct ossl_store_loader_ctx_st is defined differently by each loader */
 typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX;
-typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)(const OSSL_STORE_LOADER
-                                                     *loader,
-                                                     const char *uri,
-                                                     const UI_METHOD *ui_method,
-                                                     void *ui_data);
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn)
+    (const OSSL_STORE_LOADER *loader, const char *uri,
+     const UI_METHOD *ui_method, void *ui_data);
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_with_libctx_fn)
+    (const OSSL_STORE_LOADER *loader,
+     const char *uri, OPENSSL_CTX *libctx, const char *propq,
+     const UI_METHOD *ui_method, void *ui_data);
+
 int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader,
                                OSSL_STORE_open_fn open_function);
-typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)(const OSSL_STORE_LOADER
-                                                       *loader,
-                                                       BIO *bio,
-                                                       OPENSSL_CTX *libctx,
-                                                       const char *propq,
-                                                       const UI_METHOD
-                                                       *ui_method,
-                                                       void *ui_data);
+typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn)
+    (const OSSL_STORE_LOADER *loader, BIO *bio,
+     OPENSSL_CTX *libctx, const char *propq,
+     const UI_METHOD *ui_method, void *ui_data);
 int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader,
                                  OSSL_STORE_attach_fn attach_function);
 typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd,
@@ -272,6 +276,7 @@ typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx,
                                                void *ui_data);
 int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader,
                                OSSL_STORE_load_fn load_function);
+
 typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx);
 int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader,
                               OSSL_STORE_eof_fn eof_function);
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 2212ceeedc..935699a55a 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -343,12 +343,11 @@ void *X509_CRL_get_meth_data(X509_CRL *crl);
 
 const char *X509_verify_cert_error_string(long n);
 
-int X509_verify_ex(X509 *a, EVP_PKEY *r, OPENSSL_CTX *libctx, const char *propq);
 int X509_verify(X509 *a, EVP_PKEY *r);
 int X509_self_signed(X509 *cert, int verify_signature);
 
-int X509_REQ_verify_ex(X509_REQ *a, EVP_PKEY *r, OPENSSL_CTX *libctx,
-                       const char *propq);
+int X509_REQ_verify_with_libctx(X509_REQ *a, EVP_PKEY *r, OPENSSL_CTX *libctx,
+                                const char *propq);
 int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r);
 int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r);
 int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r);
@@ -558,6 +557,7 @@ int X509_NAME_set(X509_NAME **xn, const X509_NAME *name);
 
 DECLARE_ASN1_FUNCTIONS(X509_CINF)
 DECLARE_ASN1_FUNCTIONS(X509)
+X509 *X509_new_with_libctx(OPENSSL_CTX *libctx, const char *propq);
 DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
 
 #define X509_get_ex_new_index(l, p, newf, dupf, freef) \
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 5cd123f635..2d3bd70ae2 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -88,7 +88,6 @@ typedef STACK_OF(X509_CRL)
                                       const X509_NAME *nm);
 typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx);
 
-
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 
 # define X509_STORE_CTX_set_app_data(ctx,data) \
@@ -113,6 +112,19 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 # define X509_LOOKUP_load_store(x,name) \
                 X509_LOOKUP_ctrl((x),X509_L_LOAD_STORE,(name),0,NULL)
 
+# define X509_LOOKUP_load_file_with_libctx(x, name, type, libctx, propq)       \
+X509_LOOKUP_ctrl_with_libctx((x), X509_L_FILE_LOAD, (name), (long)(type), NULL,\
+                             (libctx), (propq))
+
+# define X509_LOOKUP_load_store_with_libctx(x, name, libctx, propq)            \
+X509_LOOKUP_ctrl_with_libctx((x), X509_L_LOAD_STORE, (name), 0, NULL,          \
+                             (libctx), (propq))
+
+# define X509_LOOKUP_add_store_with_libctx(x, name, libctx, propq)             \
+X509_LOOKUP_ctrl_with_libctx((x), X509_L_ADD_STORE, (name), 0, NULL,           \
+                             (libctx), (propq))
+
+
 # define         X509_V_OK                                       0
 # define         X509_V_ERR_UNSPECIFIED                          1
 # define         X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT            2
@@ -404,10 +416,20 @@ X509_LOOKUP_METHOD *X509_LOOKUP_store(void);
 
 typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc,
                                    long argl, char **ret);
+typedef int (*X509_LOOKUP_ctrl_with_libctx_fn)(
+    X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret,
+    OPENSSL_CTX *libctx, const char *propq);
+
 typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx,
                                              X509_LOOKUP_TYPE type,
                                              const X509_NAME *name,
                                              X509_OBJECT *ret);
+typedef int (*X509_LOOKUP_get_by_subject_with_libctx_fn)(X509_LOOKUP *ctx,
+                                                         X509_LOOKUP_TYPE type,
+                                                         const X509_NAME *name,
+                                                         X509_OBJECT *ret,
+                                                         OPENSSL_CTX *libctx,
+                                                         const char *propq);
 typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx,
                                                    X509_LOOKUP_TYPE type,
                                                    const X509_NAME *name,
@@ -484,16 +506,27 @@ X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
 
 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
                      long argl, char **ret);
+int X509_LOOKUP_ctrl_with_libctx(X509_LOOKUP *ctx, int cmd, const char *argc,
+                                 long argl, char **ret,
+                                 OPENSSL_CTX *libctx, const char *propq);
 
 int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_file_with_libctx(X509_LOOKUP *ctx, const char *file, int type,
+                                    OPENSSL_CTX *libctx, const char *propq);
 int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type);
 int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type);
+int X509_load_cert_crl_file_with_libctx(X509_LOOKUP *ctx, const char *file,
+                                        int type, OPENSSL_CTX *libctx,
+                                        const char *propq);
 
 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method);
 void X509_LOOKUP_free(X509_LOOKUP *ctx);
 int X509_LOOKUP_init(X509_LOOKUP *ctx);
 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                            const X509_NAME *name, X509_OBJECT *ret);
+int X509_LOOKUP_by_subject_with_libctx(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
+                                       const X509_NAME *name, X509_OBJECT *ret,
+                                       OPENSSL_CTX *libctx, const char *propq);
 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
                                  const X509_NAME *name,
                                  const ASN1_INTEGER *serial,
@@ -516,6 +549,17 @@ int X509_STORE_load_locations(X509_STORE *ctx,
                                                const char *dir);
 int X509_STORE_set_default_paths(X509_STORE *ctx);
 
+int X509_STORE_load_file_with_libctx(X509_STORE *ctx, const char *file,
+                                     OPENSSL_CTX *libctx, const char *propq);
+int X509_STORE_load_store_with_libctx(X509_STORE *ctx, const char *store,
+                                      OPENSSL_CTX *libctx, const char *propq);
+int X509_STORE_load_locations_with_libctx(X509_STORE *ctx,
+                                          const char *file, const char *dir,
+                                          OPENSSL_CTX *libctx, const char *propq);
+int X509_STORE_set_default_paths_with_libctx(X509_STORE *ctx,
+                                             OPENSSL_CTX *libctx,
+                                             const char *propq);
+
 #define X509_STORE_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
     CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, l, p, newf, dupf, freef)
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data);
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index 6a207f65d1..24f5a361d0 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -571,8 +571,6 @@ GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
                                   X509V3_CTX *ctx, CONF_VALUE *cnf,
                                   int is_nc);
 
-int X509v3_cache_extensions(X509 *x, OPENSSL_CTX *libctx, const char *propq);
-
 void X509V3_conf_free(CONF_VALUE *val);
 
 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index a7f1e4d83a..8f5aaaf942 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -4001,10 +4001,6 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
                 return 0;
             }
         }
-        if (!X509v3_cache_extensions((X509 *)parg, ctx->libctx, ctx->propq)) {
-            SSLerr(0, ERR_LIB_X509);
-            return 0;
-        }
         if (!sk_X509_push(ctx->extra_certs, (X509 *)parg)) {
             SSLerr(SSL_F_SSL3_CTX_CTRL, ERR_R_MALLOC_FAILURE);
             return 0;
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index e81542a89e..e6262bfaeb 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -257,18 +257,12 @@ int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
 {
     int i, r;
     CERT_PKEY *cpk = s != NULL ? s->cert->key : ctx->cert->key;
-    SSL_CTX *realctx = s != NULL ? s->ctx : ctx;
 
     if (!cpk)
         return 0;
     for (i = 0; i < sk_X509_num(chain); i++) {
         X509 *x = sk_X509_value(chain, i);
 
-        if (!X509v3_cache_extensions(x, realctx->libctx, realctx->propq)) {
-            SSLerr(0, ERR_LIB_X509);
-            return 0;
-        }
-
         r = ssl_security_cert(s, ctx, x, 0, 0);
         if (r != 1) {
             SSLerr(SSL_F_SSL_CERT_SET0_CHAIN, r);
@@ -614,29 +608,39 @@ static unsigned long xname_hash(const X509_NAME *a)
     return X509_NAME_hash((X509_NAME *)a);
 }
 
-STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+STACK_OF(X509_NAME) *SSL_load_client_CA_file_with_libctx(const char *file,
+                                                         OPENSSL_CTX *libctx,
+                                                         const char *propq)
 {
     BIO *in = BIO_new(BIO_s_file());
     X509 *x = NULL;
     X509_NAME *xn = NULL;
     STACK_OF(X509_NAME) *ret = NULL;
     LHASH_OF(X509_NAME) *name_hash = lh_X509_NAME_new(xname_hash, xname_cmp);
+    OPENSSL_CTX *prev_libctx = NULL;
 
     if ((name_hash == NULL) || (in == NULL)) {
-        SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
+    x = X509_new_with_libctx(libctx, propq);
+    if (x == NULL) {
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
     if (!BIO_read_filename(in, file))
         goto err;
 
+    /* Internally lh_X509_NAME_retrieve() needs the libctx to retrieve SHA1 */
+    prev_libctx = OPENSSL_CTX_set0_default(libctx);
     for (;;) {
         if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL)
             break;
         if (ret == NULL) {
             ret = sk_X509_NAME_new_null();
             if (ret == NULL) {
-                SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE, ERR_R_MALLOC_FAILURE);
+                SSLerr(0, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         }
@@ -663,6 +667,8 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
     sk_X509_NAME_pop_free(ret, X509_NAME_free);
     ret = NULL;
  done:
+    /* restore the old libctx */
+    OPENSSL_CTX_set0_default(prev_libctx);
     BIO_free(in);
     X509_free(x);
     lh_X509_NAME_free(name_hash);
@@ -671,6 +677,11 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
     return ret;
 }
 
+STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file)
+{
+    return SSL_load_client_CA_file_with_libctx(file, NULL, NULL);
+}
+
 int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
                                         const char *file)
 {
@@ -841,6 +852,7 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
     X509_STORE_CTX *xs_ctx = NULL;
     STACK_OF(X509) *chain = NULL, *untrusted = NULL;
     X509 *x;
+    SSL_CTX *real_ctx = (s == NULL) ? ctx : s->ctx;
     int i, rv = 0;
 
     if (!cpk->x509) {
@@ -872,10 +884,7 @@ int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags)
             untrusted = cpk->chain;
     }
 
-    if (s == NULL)
-        xs_ctx = X509_STORE_CTX_new_with_libctx(ctx->libctx, ctx->propq);
-    else
-        xs_ctx = X509_STORE_CTX_new_with_libctx(s->ctx->libctx, s->ctx->propq);
+    xs_ctx = X509_STORE_CTX_new_with_libctx(real_ctx->libctx, ctx->propq);
     if (xs_ctx == NULL) {
         SSLerr(SSL_F_SSL_BUILD_CERT_CHAIN, ERR_R_MALLOC_FAILURE);
         goto err;
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index fe9b8ec3ea..56590da207 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -470,13 +470,23 @@ static int do_store(SSL_CONF_CTX *cctx,
 {
     CERT *cert;
     X509_STORE **st;
+    SSL_CTX *ctx;
+    OPENSSL_CTX *libctx = NULL;
+    const char *propq = NULL;
 
-    if (cctx->ctx)
+    if (cctx->ctx != NULL) {
         cert = cctx->ctx->cert;
-    else if (cctx->ssl)
+        ctx = cctx->ctx;
+    } else if (cctx->ssl != NULL) {
         cert = cctx->ssl->cert;
-    else
+        ctx = cctx->ssl->ctx;
+    } else {
         return 1;
+    }
+    if (ctx != NULL) {
+        libctx = ctx->libctx;
+        propq = ctx->propq;
+    }
     st = verify_store ? &cert->verify_store : &cert->chain_store;
     if (*st == NULL) {
         *st = X509_STORE_new();
@@ -484,11 +494,13 @@ static int do_store(SSL_CONF_CTX *cctx,
             return 0;
     }
 
-    if (CAfile != NULL && !X509_STORE_load_file(*st, CAfile))
+    if (CAfile != NULL && !X509_STORE_load_file_with_libctx(*st, CAfile,
+                                                            libctx, propq))
         return 0;
     if (CApath != NULL && !X509_STORE_load_path(*st, CApath))
         return 0;
-    if (CAstore != NULL && !X509_STORE_load_store(*st, CAstore))
+    if (CAstore != NULL && !X509_STORE_load_store_with_libctx(*st, CAstore,
+                                                              libctx, propq))
         return 0;
     return 1;
 }
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c92e361cde..871606cfc1 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -4254,7 +4254,8 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
 
 int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
 {
-    return X509_STORE_set_default_paths(ctx->cert_store);
+    return X509_STORE_set_default_paths_with_libctx(ctx->cert_store,
+                                                    ctx->libctx, ctx->propq);
 }
 
 int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx)
@@ -4286,7 +4287,8 @@ int SSL_CTX_set_default_verify_file(SSL_CTX *ctx)
     /* We ignore errors, in case the directory doesn't exist */
     ERR_set_mark();
 
-    X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+    X509_LOOKUP_load_file_with_libctx(lookup, NULL, X509_FILETYPE_DEFAULT,
+                                      ctx->libctx, ctx->propq);
 
     ERR_pop_to_mark();
 
@@ -4304,7 +4306,7 @@ int SSL_CTX_set_default_verify_store(SSL_CTX *ctx)
     /* We ignore errors, in case the directory doesn't exist */
     ERR_set_mark();
 
-    X509_LOOKUP_add_store(lookup, NULL);
+    X509_LOOKUP_add_store_with_libctx(lookup, NULL, ctx->libctx, ctx->propq);
 
     ERR_pop_to_mark();
 
@@ -4313,7 +4315,8 @@ int SSL_CTX_set_default_verify_store(SSL_CTX *ctx)
 
 int SSL_CTX_load_verify_file(SSL_CTX *ctx, const char *CAfile)
 {
-    return X509_STORE_load_file(ctx->cert_store, CAfile);
+    return X509_STORE_load_file_with_libctx(ctx->cert_store, CAfile,
+                                            ctx->libctx, ctx->propq);
 }
 
 int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath)
@@ -4323,7 +4326,8 @@ int SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath)
 
 int SSL_CTX_load_verify_store(SSL_CTX *ctx, const char *CAstore)
 {
-    return X509_STORE_load_store(ctx->cert_store, CAstore);
+    return X509_STORE_load_store_with_libctx(ctx->cert_store, CAstore,
+                                             ctx->libctx, ctx->propq);
 }
 
 int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
diff --git a/ssl/ssl_mcnf.c b/ssl/ssl_mcnf.c
index 27ba7728d7..66f0bc5abe 100644
--- a/ssl/ssl_mcnf.c
+++ b/ssl/ssl_mcnf.c
@@ -28,6 +28,8 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
     unsigned int flags;
     const SSL_METHOD *meth;
     const SSL_CONF_CMD *cmds;
+    OPENSSL_CTX *prev_libctx = NULL;
+    OPENSSL_CTX *libctx = NULL;
 
     if (s == NULL && ctx == NULL) {
         SSLerr(SSL_F_SSL_DO_CONFIG, ERR_R_PASSED_NULL_PARAMETER);
@@ -53,15 +55,18 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
     if (s != NULL) {
         meth = s->method;
         SSL_CONF_CTX_set_ssl(cctx, s);
+        libctx = s->ctx->libctx;
     } else {
         meth = ctx->method;
         SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
+        libctx = ctx->libctx;
     }
     if (meth->ssl_accept != ssl_undefined_function)
         flags |= SSL_CONF_FLAG_SERVER;
     if (meth->ssl_connect != ssl_undefined_function)
         flags |= SSL_CONF_FLAG_CLIENT;
     SSL_CONF_CTX_set_flags(cctx, flags);
+    prev_libctx = OPENSSL_CTX_set0_default(libctx);
     for (i = 0; i < cmd_count; i++) {
         char *cmdstr, *arg;
 
@@ -79,6 +84,7 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system)
     }
     rv = SSL_CONF_CTX_finish(cctx);
  err:
+    OPENSSL_CTX_set0_default(prev_libctx);
     SSL_CONF_CTX_free(cctx);
     return rv <= 0 ? 0 : 1;
 }
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 3df32b725b..144dd2c374 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -34,10 +34,7 @@ int SSL_use_certificate(SSL *ssl, X509 *x)
         SSLerr(SSL_F_SSL_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    if (!X509v3_cache_extensions(x, ssl->ctx->libctx, ssl->ctx->propq)) {
-        SSLerr(0, ERR_LIB_X509);
-        return 0;
-    }
+
     rv = ssl_security_cert(ssl, NULL, x, 0, 1);
     if (rv != 1) {
         SSLerr(SSL_F_SSL_USE_CERTIFICATE, rv);
@@ -52,7 +49,7 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
     int j;
     BIO *in;
     int ret = 0;
-    X509 *x = NULL;
+    X509 *cert = NULL, *x = NULL;
 
     in = BIO_new(BIO_s_file());
     if (in == NULL) {
@@ -64,19 +61,29 @@ int SSL_use_certificate_file(SSL *ssl, const char *file, int type)
         SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
         goto end;
     }
+
+    if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) {
+        SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
+        goto end;
+    }
+    x = X509_new_with_libctx(ssl->ctx->libctx, ssl->ctx->propq);
+    if (x == NULL) {
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
+        goto end;
+    }
     if (type == SSL_FILETYPE_ASN1) {
         j = ERR_R_ASN1_LIB;
-        x = d2i_X509_bio(in, NULL);
+        cert = d2i_X509_bio(in, &x);
     } else if (type == SSL_FILETYPE_PEM) {
         j = ERR_R_PEM_LIB;
-        x = PEM_read_bio_X509(in, NULL, ssl->default_passwd_callback,
-                              ssl->default_passwd_callback_userdata);
+        cert = PEM_read_bio_X509(in, &x, ssl->default_passwd_callback,
+                                 ssl->default_passwd_callback_userdata);
     } else {
         SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
         goto end;
     }
 
-    if (x == NULL) {
+    if (cert == NULL) {
         SSLerr(SSL_F_SSL_USE_CERTIFICATE_FILE, j);
         goto end;
     }
@@ -93,8 +100,14 @@ int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len)
     X509 *x;
     int ret;
 
-    x = d2i_X509(NULL, &d, (long)len);
+    x = X509_new_with_libctx(ssl->ctx->libctx, ssl->ctx->propq);
     if (x == NULL) {
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    if (d2i_X509(&x, &d, (long)len)== NULL) {
+        X509_free(x);
         SSLerr(SSL_F_SSL_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
         return 0;
     }
@@ -316,10 +329,7 @@ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x)
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    if (!X509v3_cache_extensions(x, ctx->libctx, ctx->propq)) {
-        SSLerr(0, ERR_LIB_X509);
-        return 0;
-    }
+
     rv = ssl_security_cert(NULL, ctx, x, 0, 1);
     if (rv != 1) {
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE, rv);
@@ -390,10 +400,10 @@ static int ssl_set_cert(CERT *c, X509 *x)
 
 int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
 {
-    int j;
+    int j = SSL_R_BAD_VALUE;
     BIO *in;
     int ret = 0;
-    X509 *x = NULL;
+    X509 *x = NULL, *cert = NULL;
 
     in = BIO_new(BIO_s_file());
     if (in == NULL) {
@@ -405,19 +415,24 @@ int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type)
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
         goto end;
     }
+    if (type != SSL_FILETYPE_ASN1 && type != SSL_FILETYPE_PEM) {
+        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
+        goto end;
+    }
+    x = X509_new_with_libctx(ctx->libctx, ctx->propq);
+    if (x == NULL) {
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
+        goto end;
+    }
     if (type == SSL_FILETYPE_ASN1) {
         j = ERR_R_ASN1_LIB;
-        x = d2i_X509_bio(in, NULL);
+        cert = d2i_X509_bio(in, &x);
     } else if (type == SSL_FILETYPE_PEM) {
         j = ERR_R_PEM_LIB;
-        x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback,
-                              ctx->default_passwd_callback_userdata);
-    } else {
-        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, SSL_R_BAD_SSL_FILETYPE);
-        goto end;
+        cert = PEM_read_bio_X509(in, &x, ctx->default_passwd_callback,
+                                 ctx->default_passwd_callback_userdata);
     }
-
-    if (x == NULL) {
+    if (cert == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, j);
         goto end;
     }
@@ -434,8 +449,14 @@ int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d)
     X509 *x;
     int ret;
 
-    x = d2i_X509(NULL, &d, (long)len);
+    x = X509_new_with_libctx(ctx->libctx, ctx->propq);
     if (x == NULL) {
+        SSLerr(0, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    if (d2i_X509(&x, &d, (long)len) == NULL) {
+        X509_free(x);
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1, ERR_R_ASN1_LIB);
         return 0;
     }
@@ -610,6 +631,7 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
     X509 *x = NULL;
     pem_password_cb *passwd_callback;
     void *passwd_callback_userdata;
+    SSL_CTX *real_ctx = (ssl == NULL) ? ctx : ssl->ctx;
 
     ERR_clear_error();          /* clear error stack for
                                  * SSL_CTX_use_certificate() */
@@ -633,9 +655,13 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
         goto end;
     }
 
-    x = PEM_read_bio_X509_AUX(in, NULL, passwd_callback,
-                              passwd_callback_userdata);
+    x = X509_new_with_libctx(real_ctx->libctx, real_ctx->propq);
     if (x == NULL) {
+        SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_MALLOC_FAILURE);
+        goto end;
+    }
+    if (PEM_read_bio_X509_AUX(in, &x, passwd_callback,
+                              passwd_callback_userdata) == NULL) {
         SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_PEM_LIB);
         goto end;
     }
@@ -667,23 +693,32 @@ static int use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file)
             goto end;
         }
 
-        while ((ca = PEM_read_bio_X509(in, NULL, passwd_callback,
-                                       passwd_callback_userdata))
-               != NULL) {
-            if (ctx)
-                r = SSL_CTX_add0_chain_cert(ctx, ca);
-            else
-                r = SSL_add0_chain_cert(ssl, ca);
-            /*
-             * Note that we must not free ca if it was successfully added to
-             * the chain (while we must free the main certificate, since its
-             * reference count is increased by SSL_CTX_use_certificate).
-             */
-            if (!r) {
-                X509_free(ca);
-                ret = 0;
+        while (1) {
+            ca = X509_new_with_libctx(real_ctx->libctx, real_ctx->propq);
+            if (ca == NULL) {
+                SSLerr(SSL_F_USE_CERTIFICATE_CHAIN_FILE, ERR_R_MALLOC_FAILURE);
                 goto end;
             }
+            if (PEM_read_bio_X509(in, &ca, passwd_callback,
+                                  passwd_callback_userdata) != NULL) {
+                if (ctx)
+                    r = SSL_CTX_add0_chain_cert(ctx, ca);
+                else
+                    r = SSL_add0_chain_cert(ssl, ca);
+                /*
+                 * Note that we must not free ca if it was successfully added to
+                 * the chain (while we must free the main certificate, since its
+                 * reference count is increased by SSL_CTX_use_certificate).
+                 */
+                if (!r) {
+                    X509_free(ca);
+                    ret = 0;
+                    goto end;
+                }
+            } else {
+                X509_free(ca);
+                break;
+            }
         }
         /* When the while loop ends, it's usually just EOF. */
         err = ERR_peek_last_error();
@@ -1063,15 +1098,9 @@ static int ssl_set_cert_and_key(SSL *ssl, SSL_CTX *ctx, X509 *x509, EVP_PKEY *pr
     int j;
     int rv;
     CERT *c = ssl != NULL ? ssl->cert : ctx->cert;
-    SSL_CTX *actualctx = ssl == NULL ? ctx : ssl->ctx;
     STACK_OF(X509) *dup_chain = NULL;
     EVP_PKEY *pubkey = NULL;
 
-    if (!X509v3_cache_extensions(x509, actualctx->libctx, actualctx->propq)) {
-        SSLerr(0, ERR_R_X509_LIB);
-        goto out;
-    }
-
     /* Do all security checks before anything else */
     rv = ssl_security_cert(ssl, ctx, x509, 0, 1);
     if (rv != 1) {
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index d7722d76e0..4cd85ef609 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1858,12 +1858,20 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
         }
 
         certstart = certbytes;
-        x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
+        x = X509_new_with_libctx(s->ctx->libctx, s->ctx->propq);
         if (x == NULL) {
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+            SSLerr(0, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (d2i_X509(&x, (const unsigned char **)&certbytes,
+                     cert_len) == NULL) {
             SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
                      SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
             goto err;
         }
+
         if (certbytes != (certstart + cert_len)) {
             SSLfatal(s, SSL_AD_DECODE_ERROR,
                      SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index abffbd6326..b329e89379 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -3676,12 +3676,18 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
         }
 
         certstart = certbytes;
-        x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
+        x = X509_new_with_libctx(s->ctx->libctx, s->ctx->propq);
         if (x == NULL) {
+            SSLfatal(s, SSL_AD_DECODE_ERROR,
+                     SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (d2i_X509(&x, (const unsigned char **)&certbytes, l) == NULL) {
             SSLfatal(s, SSL_AD_DECODE_ERROR,
                      SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
             goto err;
         }
+
         if (certbytes != (certstart + l)) {
             SSLfatal(s, SSL_AD_DECODE_ERROR,
                      SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
diff --git a/test/ssl_test.c b/test/ssl_test.c
index 731f569743..5880468f93 100644
--- a/test/ssl_test.c
+++ b/test/ssl_test.c
@@ -404,7 +404,7 @@ static int test_handshake(int idx)
 
     BIO_snprintf(test_app, sizeof(test_app), "test-%d", idx);
 
-    test_ctx = SSL_TEST_CTX_create(conf, test_app);
+    test_ctx = SSL_TEST_CTX_create(conf, test_app, libctx);
     if (!TEST_ptr(test_ctx))
         goto err;
 
diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c
index 31da26b0d7..726ee37583 100644
--- a/test/ssl_test_ctx.c
+++ b/test/ssl_test_ctx.c
@@ -609,25 +609,27 @@ __owur static int parse_expected_client_sign_hash(SSL_TEST_CTX *test_ctx,
 }
 
 __owur static int parse_expected_ca_names(STACK_OF(X509_NAME) **pnames,
-                                          const char *value)
+                                          const char *value, OPENSSL_CTX *libctx)
 {
     if (value == NULL)
         return 0;
     if (!strcmp(value, "empty"))
         *pnames = sk_X509_NAME_new_null();
     else
-        *pnames = SSL_load_client_CA_file(value);
+        *pnames = SSL_load_client_CA_file_with_libctx(value, libctx, NULL);
     return *pnames != NULL;
 }
 __owur static int parse_expected_server_ca_names(SSL_TEST_CTX *test_ctx,
                                                  const char *value)
 {
-    return parse_expected_ca_names(&test_ctx->expected_server_ca_names, value);
+    return parse_expected_ca_names(&test_ctx->expected_server_ca_names, value,
+                                   test_ctx->libctx);
 }
 __owur static int parse_expected_client_ca_names(SSL_TEST_CTX *test_ctx,
                                                  const char *value)
 {
-    return parse_expected_ca_names(&test_ctx->expected_client_ca_names, value);
+    return parse_expected_ca_names(&test_ctx->expected_client_ca_names, value,
+                                   test_ctx->libctx);
 }
 
 /* ExpectedCipher */
@@ -719,12 +721,13 @@ static const ssl_test_server_option ssl_test_server_options[] = {
     { "SessionTicketAppData", &parse_server_session_ticket_app_data },
 };
 
-SSL_TEST_CTX *SSL_TEST_CTX_new(void)
+SSL_TEST_CTX *SSL_TEST_CTX_new(OPENSSL_CTX *libctx)
 {
     SSL_TEST_CTX *ret;
 
     /* The return code is checked by caller */
     if ((ret = OPENSSL_zalloc(sizeof(*ret))) != NULL) {
+        ret->libctx = libctx;
         ret->app_data_size = default_app_data_size;
         ret->max_fragment_size = default_max_fragment_size;
     }
@@ -758,6 +761,8 @@ static void ssl_test_ctx_free_extra_data(SSL_TEST_CTX *ctx)
 
 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx)
 {
+    if (ctx == NULL)
+        return;
     ssl_test_ctx_free_extra_data(ctx);
     OPENSSL_free(ctx->expected_npn_protocol);
     OPENSSL_free(ctx->expected_alpn_protocol);
@@ -834,7 +839,8 @@ static int parse_server_options(SSL_TEST_SERVER_CONF *server, const CONF *conf,
     return 1;
 }
 
-SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
+SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section,
+                                  OPENSSL_CTX *libctx)
 {
     STACK_OF(CONF_VALUE) *sk_conf = NULL;
     SSL_TEST_CTX *ctx = NULL;
@@ -842,7 +848,7 @@ SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section)
     size_t j;
 
     if (!TEST_ptr(sk_conf = NCONF_get_section(conf, test_section))
-            || !TEST_ptr(ctx = SSL_TEST_CTX_new()))
+            || !TEST_ptr(ctx = SSL_TEST_CTX_new(libctx)))
         goto err;
 
     for (i = 0; i < sk_CONF_VALUE_num(sk_conf); i++) {
diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h
index 29955b45db..4a0d72b682 100644
--- a/test/ssl_test_ctx.h
+++ b/test/ssl_test_ctx.h
@@ -225,6 +225,8 @@ typedef struct {
     char *expected_cipher;
     /* Expected Session Ticket Application Data */
     char *expected_session_ticket_app_data;
+
+    OPENSSL_CTX *libctx;
 } SSL_TEST_CTX;
 
 const char *ssl_test_result_name(ssl_test_result_t result);
@@ -246,9 +248,10 @@ const char *ssl_max_fragment_len_name(int MFL_mode);
  * Load the test case context from |conf|.
  * See test/README.ssltest.md for details on the conf file format.
  */
-SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section);
+SSL_TEST_CTX *SSL_TEST_CTX_create(const CONF *conf, const char *test_section,
+                                  OPENSSL_CTX *libctx);
 
-SSL_TEST_CTX *SSL_TEST_CTX_new(void);
+SSL_TEST_CTX *SSL_TEST_CTX_new(OPENSSL_CTX *libctx);
 
 void SSL_TEST_CTX_free(SSL_TEST_CTX *ctx);
 
diff --git a/test/ssl_test_ctx_test.c b/test/ssl_test_ctx_test.c
index c3591a02d0..16ce32a33f 100644
--- a/test/ssl_test_ctx_test.c
+++ b/test/ssl_test_ctx_test.c
@@ -114,7 +114,7 @@ static SSL_TEST_CTX_TEST_FIXTURE *set_up(const char *const test_case_name)
     if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture))))
         return NULL;
     fixture->test_case_name = test_case_name;
-    if (!TEST_ptr(fixture->expected_ctx = SSL_TEST_CTX_new())) {
+    if (!TEST_ptr(fixture->expected_ctx = SSL_TEST_CTX_new(NULL))) {
         OPENSSL_free(fixture);
         return NULL;
     }
@@ -126,7 +126,8 @@ static int execute_test(SSL_TEST_CTX_TEST_FIXTURE *fixture)
     int success = 0;
     SSL_TEST_CTX *ctx;
 
-    if (!TEST_ptr(ctx = SSL_TEST_CTX_create(conf, fixture->test_section))
+    if (!TEST_ptr(ctx = SSL_TEST_CTX_create(conf, fixture->test_section,
+                                            fixture->expected_ctx->libctx))
             || !testctx_eq(ctx, fixture->expected_ctx))
         goto err;
 
@@ -232,7 +233,7 @@ static int test_bad_configuration(int idx)
     SSL_TEST_CTX *ctx;
 
     if (!TEST_ptr_null(ctx = SSL_TEST_CTX_create(conf,
-                                                 bad_configurations[idx]))) {
+                                                 bad_configurations[idx], NULL))) {
         SSL_TEST_CTX_free(ctx);
         return 0;
     }
diff --git a/test/sslapitest.c b/test/sslapitest.c
index ccee736592..3d6d83a11a 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -799,11 +799,14 @@ static int execute_test_large_message(const SSL_METHOD *smeth,
 
     if (!TEST_ptr(certbio = BIO_new_file(cert, "r")))
         goto end;
-    chaincert = PEM_read_bio_X509(certbio, NULL, NULL, NULL);
+
+    if (!TEST_ptr(chaincert = X509_new_with_libctx(libctx, NULL)))
+        goto end;
+
+    if (PEM_read_bio_X509(certbio, &chaincert, NULL, NULL) == NULL)
+        goto end;
     BIO_free(certbio);
     certbio = NULL;
-    if (!TEST_ptr(chaincert))
-        goto end;
 
     if (!TEST_true(create_ssl_ctx_pair(libctx, smeth, cmeth, min_version,
                                        max_version, &sctx, &cctx, cert,
@@ -852,6 +855,7 @@ static int execute_test_large_message(const SSL_METHOD *smeth,
 
     testresult = 1;
  end:
+    BIO_free(certbio);
     X509_free(chaincert);
     SSL_free(serverssl);
     SSL_free(clientssl);
@@ -1849,8 +1853,8 @@ static int test_tlsext_status_type(void)
     if (!TEST_ptr(certbio = BIO_new_file(cert, "r"))
             || !TEST_ptr(id = OCSP_RESPID_new())
             || !TEST_ptr(ids = sk_OCSP_RESPID_new_null())
-            || !TEST_ptr(ocspcert = PEM_read_bio_X509(certbio,
-                                                      NULL, NULL, NULL))
+            || !TEST_ptr(ocspcert = X509_new_with_libctx(libctx, NULL))
+            || !TEST_ptr(PEM_read_bio_X509(certbio, &ocspcert, NULL, NULL))
             || !TEST_true(OCSP_RESPID_set_by_key_ex(id, ocspcert, libctx, NULL))
             || !TEST_true(sk_OCSP_RESPID_push(ids, id)))
         goto end;
@@ -7482,14 +7486,16 @@ static int cert_cb(SSL *s, void *arg)
             goto out;
         if (!TEST_ptr(in = BIO_new(BIO_s_file()))
                 || !TEST_int_ge(BIO_read_filename(in, rootfile), 0)
-                || !TEST_ptr(rootx = PEM_read_bio_X509(in, NULL, NULL, NULL))
+                || !TEST_ptr(rootx = X509_new_with_libctx(libctx, NULL))
+                || !TEST_ptr(PEM_read_bio_X509(in, &rootx, NULL, NULL))
                 || !TEST_true(sk_X509_push(chain, rootx)))
             goto out;
         rootx = NULL;
         BIO_free(in);
         if (!TEST_ptr(in = BIO_new(BIO_s_file()))
                 || !TEST_int_ge(BIO_read_filename(in, ecdsacert), 0)
-                || !TEST_ptr(x509 = PEM_read_bio_X509(in, NULL, NULL, NULL)))
+                || !TEST_ptr(x509 = X509_new_with_libctx(libctx, NULL))
+                || !TEST_ptr(PEM_read_bio_X509(in, &x509, NULL, NULL)))
             goto out;
         BIO_free(in);
         if (!TEST_ptr(in = BIO_new(BIO_s_file()))
@@ -7626,6 +7632,7 @@ static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
     X509 *xcert;
     EVP_PKEY *privpkey;
     BIO *in = NULL;
+    BIO *priv_in = NULL;
 
     /* Check that SSL_get0_peer_certificate() returns something sensible */
     if (!TEST_ptr(SSL_get0_peer_certificate(ssl)))
@@ -7635,28 +7642,24 @@ static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
     if (!TEST_ptr(in))
         return 0;
 
-    xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
-    BIO_free(in);
-    if (!TEST_ptr(xcert))
-        return 0;
-
-    in = BIO_new_file(privkey, "r");
-    if (!TEST_ptr(in)) {
-        X509_free(xcert);
-        return 0;
-    }
-
-    privpkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
-    BIO_free(in);
-    if (!TEST_ptr(privpkey)) {
-        X509_free(xcert);
-        return 0;
-    }
+    if (!TEST_ptr(xcert = X509_new_with_libctx(libctx, NULL))
+            || !TEST_ptr(PEM_read_bio_X509(in, &xcert, NULL, NULL))
+            || !TEST_ptr(priv_in = BIO_new_file(privkey, "r"))
+            || !TEST_ptr(privpkey = PEM_read_bio_PrivateKey(priv_in, NULL, NULL,
+                                                            NULL)))
+        goto err;
 
     *x509 = xcert;
     *pkey = privpkey;
 
+    BIO_free(in);
+    BIO_free(priv_in);
     return 1;
+err:
+    X509_free(xcert);
+    BIO_free(in);
+    BIO_free(priv_in);
+    return 0;
 }
 
 static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 5e9fa4ac6c..5aff5d5c44 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5030,7 +5030,7 @@ SRP_Calc_B_ex                           ?	3_0_0	EXIST::FUNCTION:SRP
 SRP_Calc_u_ex                           ?	3_0_0	EXIST::FUNCTION:SRP
 SRP_Calc_x_ex                           ?	3_0_0	EXIST::FUNCTION:SRP
 SRP_Calc_client_key_ex                  ?	3_0_0	EXIST::FUNCTION:SRP
-X509v3_cache_extensions                 ?	3_0_0	EXIST::FUNCTION:
+X509v3_cache_extensions                 ?	3_0_0	NOEXIST::FUNCTION:
 EVP_PKEY_gettable_params                ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_get_int_param                  ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_get_size_t_param               ?	3_0_0	EXIST::FUNCTION:
@@ -5075,8 +5075,8 @@ EVP_PKEY_CTX_set_dhx_rfc5114            ?	3_0_0	EXIST::FUNCTION:DH
 X509_VERIFY_PARAM_get0_host             ?	3_0_0	EXIST::FUNCTION:
 X509_VERIFY_PARAM_get0_email            ?	3_0_0	EXIST::FUNCTION:
 X509_VERIFY_PARAM_get1_ip_asc           ?	3_0_0	EXIST::FUNCTION:
-X509_verify_ex                          ?	3_0_0	EXIST::FUNCTION:
-X509_REQ_verify_ex                      ?	3_0_0	EXIST::FUNCTION:
+X509_verify_ex                          ?	3_0_0	NOEXIST::FUNCTION:
+X509_REQ_verify_ex                      ?	3_0_0	NOEXIST::FUNCTION:
 X509_ALGOR_copy                         ?	3_0_0	EXIST::FUNCTION:
 X509_REQ_set0_signature                 ?	3_0_0	EXIST::FUNCTION:
 X509_REQ_set1_signature_algo            ?	3_0_0	EXIST::FUNCTION:
@@ -5136,3 +5136,16 @@ EC_GROUP_new_by_curve_name_with_libctx  ?	3_0_0	EXIST::FUNCTION:EC
 EC_KEY_new_with_libctx                  ?	3_0_0	EXIST::FUNCTION:EC
 EC_KEY_new_by_curve_name_with_libctx    ?	3_0_0	EXIST::FUNCTION:EC
 OPENSSL_CTX_set0_default                ?	3_0_0	EXIST::FUNCTION:
+PEM_X509_INFO_read_bio_with_libctx      ?	3_0_0	EXIST::FUNCTION:
+PEM_X509_INFO_read_with_libctx          ?	3_0_0	EXIST::FUNCTION:STDIO
+X509_REQ_verify_with_libctx             ?	3_0_0	EXIST::FUNCTION:
+X509_new_with_libctx                    ?	3_0_0	EXIST::FUNCTION:
+X509_LOOKUP_ctrl_with_libctx            ?	3_0_0	EXIST::FUNCTION:
+X509_load_cert_file_with_libctx         ?	3_0_0	EXIST::FUNCTION:
+X509_load_cert_crl_file_with_libctx     ?	3_0_0	EXIST::FUNCTION:
+X509_LOOKUP_by_subject_with_libctx      ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_load_file_with_libctx        ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_load_store_with_libctx       ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_load_locations_with_libctx   ?	3_0_0	EXIST::FUNCTION:
+X509_STORE_set_default_paths_with_libctx ?	3_0_0	EXIST::FUNCTION:
+OSSL_STORE_open_with_libctx             ?	3_0_0	EXIST::FUNCTION:
diff --git a/util/libssl.num b/util/libssl.num
index 637e088704..1758525038 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -516,3 +516,4 @@ SSL_CTX_new_with_libctx                 ?	3_0_0	EXIST::FUNCTION:
 SSL_new_session_ticket                  ?	3_0_0	EXIST::FUNCTION:
 SSL_get0_peer_certificate               ?	3_0_0	EXIST::FUNCTION:
 SSL_get1_peer_certificate               ?	3_0_0	EXIST::FUNCTION:
+SSL_load_client_CA_file_with_libctx     ?	3_0_0	EXIST::FUNCTION:
diff --git a/util/other.syms b/util/other.syms
index 351cffa933..54a2b71abb 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -571,8 +571,11 @@ X509_CRL_http_nbio                      define
 X509_http_nbio                          define
 X509_LOOKUP_add_dir                     define
 X509_LOOKUP_add_store                   define
+X509_LOOKUP_add_store_with_libctx       define
 X509_LOOKUP_load_file                   define
+X509_LOOKUP_load_file_with_libctx       define
 X509_LOOKUP_load_store                  define
+X509_LOOKUP_load_store_with_libctx      define
 X509_STORE_set_lookup_crls_cb           define
 X509_STORE_set_verify_func              define
 EVP_PKEY_CTX_set1_id                    define


More information about the openssl-commits mailing list