[openssl] master update

shane.lontis at oracle.com shane.lontis at oracle.com
Sun Aug 9 07:42:40 UTC 2020


The branch master has been updated
       via  dda4e259e51aeaf05a2417ef577accf778c9f6f6 (commit)
       via  28ba642779ec5c320fc95515bce17bda5e531105 (commit)
       via  0ab18e7924727f7b613edc187f3a5074d0ce9bc6 (commit)
       via  11eef7e766ad76158be8da497fba2bc048b02ca1 (commit)
       via  831564543a706fbeff580789d02a3e2e85ae7f2a (commit)
       via  57e8420609b54cc9723dec2c8e770feb157ebbdc (commit)
       via  90a1f2d76f53effefafbae31e2f425a3508bda45 (commit)
       via  45b22d6a35678ac3f22a18302a2647bfd9cb244c (commit)
       via  dcc679cd99835560d75a84719ab73a70a952f035 (commit)
       via  c1669f41eab0e2d9a8c2498718d06b4cd48a9890 (commit)
      from  82a7b2fb001e2ff50389d0894c276880b3bad336 (commit)


- Log -----------------------------------------------------------------
commit dda4e259e51aeaf05a2417ef577accf778c9f6f6
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Thu Aug 6 13:56:57 2020 +1000

    Add some of the missing CMS API documentation
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 28ba642779ec5c320fc95515bce17bda5e531105
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sun Jul 26 17:36:33 2020 +1000

    Change CMS tests to use a library context.
    
    A DHX related test has been commented out and TODO(3) added, until DHX is added correctly to a provider.
    Added generated files.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 0ab18e7924727f7b613edc187f3a5074d0ce9bc6
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sun Jul 26 17:32:05 2020 +1000

    Add EVP signature with libctx methods.
    
    -Added EVP_SignFinal_with_libctx() and EVP_VerifyFinal_with_libctx()
    -Renamed EVP_DigestSignInit_ex() and EVP_DigestVerifyInit_with_libctx() to
      EVP_DigestSignInit_with_libctx() and EVP_DigestVerifyInit_with_libctx()
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 11eef7e766ad76158be8da497fba2bc048b02ca1
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sun Jul 26 17:26:43 2020 +1000

    Use libctx for EVP_CIPHER_CTX_rand_key() method.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 831564543a706fbeff580789d02a3e2e85ae7f2a
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sun Jul 26 17:23:41 2020 +1000

    Add libctx to ecdh_KDF_X9_63.
    
    Code is now correctly included in the fips provider.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 57e8420609b54cc9723dec2c8e770feb157ebbdc
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sat Jul 25 19:28:14 2020 +1000

    Fix EVP_PKEY_CTX_get_rsa_oaep_md() & EVP_PKEY_CTX_get_rsa_mgf1_md() so they use a libctx to retrieve the digest
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 90a1f2d76f53effefafbae31e2f425a3508bda45
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sat Jul 25 19:11:03 2020 +1000

    Add libctx support to PKCS7.
    
    -Public PKCS7 methods that create a PKCS7 object now have variants that also add a libctx and propq.
     This includes PKCS7_new_with_libctx(), PKCS7_sign_with_libctx() and PKCS7_encrypt_with_libctx()
    -Added SMIME_read_PKCS7_ex() so that a created PKCS7 object can be passed to the read.
    -d2i_PKCS7_bio() has been modified so that after it loads the PKCS7 object it then resolves any subobjects that require
     the libctx/propq (such as objects containing X509 certificates).
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit 45b22d6a35678ac3f22a18302a2647bfd9cb244c
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sat Jul 25 18:59:28 2020 +1000

    Add libctx to SMIME ASN1
    
    Added SMIME_write_ASN1_with_libctx() since it fetches rand internally.
    Added SMIME_read_CMS_ex() so that a created object (CMS_ContentInfo) can be passed to the read.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit dcc679cd99835560d75a84719ab73a70a952f035
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sat Jul 25 18:44:25 2020 +1000

    Add internal method x509_set0_libctx().
    
    This should only be called during (or right after) using d2iXXX on a object that contains embedded certificate(s)
    that require a non default library context. X509_new_with_libctx() should be used if possible.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

commit c1669f41eab0e2d9a8c2498718d06b4cd48a9890
Author: Shane Lontis <shane.lontis at oracle.com>
Date:   Sat Jul 25 18:04:55 2020 +1000

    Add libctx support to CMS.
    
    -Public CMS methods that create a CMS_ContentInfo object now have variants that also add a libctx and propq.
     This includes CMS_ContentInfo_new_with_libctx(), CMS_sign_with_libctx(), CMS_data_create_with_libctx(),
     CMS_digest_create_with_libctx(), CMS_EncryptedData_encrypt_with_libctx(), CMS_EnvelopedData_create_with_libctx().
    -Added CMS_ReceiptRequest_create0_with_libctx().
    -Added SMIME_read_CMS_ex() so that a new CMS_ContentInfo object (created using CMS_ContentInfo_new_with_libctx()) can
    be passed to the read.
    -d2i_CMS_bio() has been modified so that after it loads the CMS_ContentInfo() it then resolves any subobjects that require
     the libctx/propq (such as objects containing X509 certificates).
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/11884)

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

Summary of changes:
 apps/cms.c                                     | 123 +++++++-----
 apps/pkcs7.c                                   |  17 +-
 apps/smime.c                                   |  32 ++-
 crypto/asn1/asn_mime.c                         |  55 ++++--
 crypto/cms/cms_cd.c                            |   7 +-
 crypto/cms/cms_dd.c                            |  12 +-
 crypto/cms/cms_enc.c                           |  38 ++--
 crypto/cms/cms_env.c                           | 126 ++++++++----
 crypto/cms/cms_ess.c                           |  47 +++--
 crypto/cms/cms_io.c                            |  33 +++-
 crypto/cms/cms_kari.c                          |  52 +++--
 crypto/cms/cms_lib.c                           | 116 ++++++++++-
 crypto/cms/cms_local.h                         |  49 ++++-
 crypto/cms/cms_pwri.c                          |  32 +--
 crypto/cms/cms_sd.c                            | 137 +++++++++----
 crypto/cms/cms_smime.c                         | 214 +++++++++++++-------
 crypto/ct/ct_vfy.c                             |   5 +-
 crypto/ec/build.info                           |   4 +-
 crypto/ec/ec_ameth.c                           |  29 ++-
 crypto/evp/digest.c                            |   5 +-
 crypto/evp/evp_enc.c                           |  17 +-
 crypto/evp/m_sigver.c                          |  27 +--
 crypto/evp/p_sign.c                            |  16 +-
 crypto/evp/p_verify.c                          |  16 +-
 crypto/pkcs7/pk7_asn1.c                        |  48 ++++-
 crypto/pkcs7/pk7_doit.c                        | 101 +++++++---
 crypto/pkcs7/pk7_lib.c                         |  69 +++++++
 crypto/pkcs7/pk7_local.h                       |  14 ++
 crypto/pkcs7/pk7_mime.c                        |  24 ++-
 crypto/pkcs7/pk7_smime.c                       |  85 ++++----
 crypto/rsa/rsa_lib.c                           |   4 +-
 crypto/x509/x_all.c                            |  15 +-
 crypto/x509/x_x509.c                           |  14 ++
 doc/man1/openssl-cms.pod.in                    |   3 +
 doc/man1/openssl-smime.pod.in                  |   3 +
 doc/man3/CMS_EncryptedData_decrypt.pod         |  49 +++++
 doc/man3/CMS_EncryptedData_encrypt.pod         |  65 ++++++
 doc/man3/CMS_EnvelopedData_create.pod          |  22 ++-
 doc/man3/CMS_data_create.pod                   |  55 ++++++
 doc/man3/CMS_digest_create.pod                 |  58 ++++++
 doc/man3/CMS_encrypt.pod                       |  26 ++-
 doc/man3/CMS_get1_ReceiptRequest.pod           |  44 +++--
 doc/man3/CMS_sign.pod                          |  31 ++-
 doc/man3/EVP_DigestSignInit.pod                |  48 ++---
 doc/man3/EVP_DigestVerifyInit.pod              |  43 ++--
 doc/man3/EVP_SignInit.pod                      |  28 ++-
 doc/man3/EVP_VerifyInit.pod                    |  36 ++--
 doc/man3/PKCS7_encrypt.pod                     |  25 ++-
 doc/man3/PKCS7_sign.pod                        |  25 ++-
 doc/man3/SMIME_read_ASN1.pod                   |  77 ++++++++
 doc/man3/SMIME_read_CMS.pod                    |  23 ++-
 doc/man3/SMIME_read_PKCS7.pod                  |  18 +-
 doc/man3/SMIME_write_ASN1.pod                  |  82 ++++++++
 doc/man3/X509_dup.pod                          |  15 +-
 include/crypto/pkcs7.h                         |  10 +
 include/crypto/x509.h                          |   1 +
 include/openssl/asn1.h                         |   7 +
 include/openssl/cms.h                          |  48 ++++-
 include/openssl/evp.h                          |  22 ++-
 include/openssl/pkcs7.h                        |  17 ++
 providers/implementations/exchange/ecdh_exch.c |   6 -
 ssl/statem/extensions.c                        |   5 +-
 ssl/statem/extensions_srvr.c                   |   9 +-
 ssl/statem/statem_clnt.c                       |   7 +-
 ssl/statem/statem_lib.c                        |  14 +-
 ssl/statem/statem_srvr.c                       |   7 +-
 ssl/t1_enc.c                                   |   6 +-
 test/acvp_test.c                               |  15 +-
 test/evp_extra_test.c                          |   5 +-
 test/evp_test.c                                |  10 +-
 test/recipes/80-test_cms.t                     | 264 ++++++++++++++-----------
 util/libcrypto.num                             |  23 ++-
 util/missingcrypto.txt                         |   6 -
 73 files changed, 2116 insertions(+), 725 deletions(-)
 create mode 100644 crypto/pkcs7/pk7_local.h
 create mode 100644 doc/man3/CMS_EncryptedData_decrypt.pod
 create mode 100644 doc/man3/CMS_EncryptedData_encrypt.pod
 create mode 100644 doc/man3/CMS_data_create.pod
 create mode 100644 doc/man3/CMS_digest_create.pod
 create mode 100644 doc/man3/SMIME_read_ASN1.pod
 create mode 100644 doc/man3/SMIME_write_ASN1.pod
 create mode 100644 include/crypto/pkcs7.h

diff --git a/apps/cms.c b/apps/cms.c
index 2cb92ab85f..7e48cc1c82 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -32,9 +32,9 @@ DEFINE_STACK_OF_STRING()
 static int save_certs(char *signerfile, STACK_OF(X509) *signers);
 static int cms_cb(int ok, X509_STORE_CTX *ctx);
 static void receipt_request_print(CMS_ContentInfo *cms);
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
-                                                *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
-                                                *rr_from);
+static CMS_ReceiptRequest *make_receipt_request(
+    STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
+    STACK_OF(OPENSSL_STRING) *rr_from, OPENSSL_CTX *libctx, const char *propq);
 static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
                               STACK_OF(OPENSSL_STRING) *param);
 
@@ -89,7 +89,7 @@ typedef enum OPTION_choice {
     OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
     OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
     OPT_R_ENUM,
-    OPT_PROV_ENUM,
+    OPT_PROV_ENUM, OPT_CONFIG,
     OPT_V_ENUM,
     OPT_CIPHER,
     OPT_ORIGINATOR
@@ -124,6 +124,7 @@ const OPTIONS cms_options[] = {
 # ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
 # endif
+    OPT_CONFIG_OPTION,
 
     OPT_SECTION("Action"),
     {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
@@ -236,8 +237,44 @@ const OPTIONS cms_options[] = {
     {NULL}
 };
 
+static CMS_ContentInfo *load_content_info(int informat, BIO *in, BIO **indata,
+                                          const char *name,
+                                          OPENSSL_CTX *libctx, const char *propq)
+{
+    CMS_ContentInfo *ret, *ci;
+
+    ret = CMS_ContentInfo_new_with_libctx(libctx, propq);
+    if (ret == NULL) {
+        BIO_printf(bio_err, "Error allocating CMS_contentinfo\n");
+        return NULL;
+    }
+    switch (informat) {
+    case FORMAT_SMIME:
+        ci = SMIME_read_CMS_ex(in, indata, &ret);
+        break;
+    case FORMAT_PEM:
+        ci = PEM_read_bio_CMS(in, &ret, NULL, NULL);
+        break;
+    case FORMAT_ASN1:
+        ci = d2i_CMS_bio(in, &ret);
+        break;
+    default:
+        BIO_printf(bio_err, "Bad input format for %s\n", name);
+        goto err;
+    }
+    if (ci == NULL) {
+        BIO_printf(bio_err, "Error reading %s Content Info\n", name);
+        goto err;
+    }
+    return ret;
+err:
+    CMS_ContentInfo_free(ret);
+    return NULL;
+}
+
 int cms_main(int argc, char **argv)
 {
+    CONF *conf = NULL;
     ASN1_OBJECT *econtent_type = NULL;
     BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
     CMS_ContentInfo *cms = NULL, *rcms = NULL;
@@ -270,6 +307,8 @@ int cms_main(int argc, char **argv)
     long ltmp;
     const char *mime_eol = "\n";
     OPTION_CHOICE o;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
         return 1;
@@ -417,14 +456,14 @@ int cms_main(int argc, char **argv)
             rr_allorfirst = 1;
             break;
         case OPT_RCTFORM:
-            if (rctformat == FORMAT_SMIME)
-                rcms = SMIME_read_CMS(rctin, NULL);
-            else if (rctformat == FORMAT_PEM)
-                rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
-            else if (rctformat == FORMAT_ASN1)
+            if (rctformat == FORMAT_ASN1) {
                 if (!opt_format(opt_arg(),
                                 OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
                     goto opthelp;
+            } else {
+                rcms = load_content_info(rctformat, rctin, NULL, "recipient",
+                                         libctx, propq);
+            }
             break;
         case OPT_CERTFILE:
             certfile = opt_arg();
@@ -639,6 +678,11 @@ int cms_main(int argc, char **argv)
             if (!opt_provider(o))
                 goto end;
             break;
+        case OPT_CONFIG:
+            conf = app_load_config_modules(opt_arg());
+            if (conf == NULL)
+                goto end;
+            break;
         case OPT_3DES_WRAP:
 # ifndef OPENSSL_NO_DES
             wrap_cipher = EVP_des_ede3_wrap();
@@ -830,21 +874,9 @@ int cms_main(int argc, char **argv)
         goto end;
 
     if (operation & SMIME_IP) {
-        if (informat == FORMAT_SMIME) {
-            cms = SMIME_read_CMS(in, &indata);
-        } else if (informat == FORMAT_PEM) {
-            cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
-        } else if (informat == FORMAT_ASN1) {
-            cms = d2i_CMS_bio(in, NULL);
-        } else {
-            BIO_printf(bio_err, "Bad input format for CMS file\n");
-            goto end;
-        }
-
-        if (cms == NULL) {
-            BIO_printf(bio_err, "Error reading S/MIME message\n");
+        cms = load_content_info(informat, in, &indata, "SMIME", libctx, propq);
+        if (cms == NULL)
             goto end;
-        }
         if (contfile != NULL) {
             BIO_free(indata);
             if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
@@ -872,21 +904,10 @@ int cms_main(int argc, char **argv)
             goto end;
         }
 
-        if (rctformat == FORMAT_SMIME) {
-            rcms = SMIME_read_CMS(rctin, NULL);
-        } else if (rctformat == FORMAT_PEM) {
-            rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
-        } else if (rctformat == FORMAT_ASN1) {
-            rcms = d2i_CMS_bio(rctin, NULL);
-        } else {
-            BIO_printf(bio_err, "Bad input format for receipt\n");
-            goto end;
-        }
-
-        if (rcms == NULL) {
-            BIO_printf(bio_err, "Error reading receipt\n");
+        rcms = load_content_info(rctformat, rctin, NULL, "recipient", libctx,
+                                 propq);
+        if (rcms == NULL)
             goto end;
-        }
     }
 
     out = bio_open_default(outfile, 'w', outformat);
@@ -905,15 +926,15 @@ int cms_main(int argc, char **argv)
     ret = 3;
 
     if (operation == SMIME_DATA_CREATE) {
-        cms = CMS_data_create(in, flags);
+        cms = CMS_data_create_with_libctx(in, flags, libctx, propq);
     } else if (operation == SMIME_DIGEST_CREATE) {
-        cms = CMS_digest_create(in, sign_md, flags);
+        cms = CMS_digest_create_with_libctx(in, sign_md, flags, libctx, propq);
     } else if (operation == SMIME_COMPRESS) {
         cms = CMS_compress(in, -1, flags);
     } else if (operation == SMIME_ENCRYPT) {
         int i;
         flags |= CMS_PARTIAL;
-        cms = CMS_encrypt(NULL, in, cipher, flags);
+        cms = CMS_encrypt_with_libctx(NULL, in, cipher, flags, libctx, propq);
         if (cms == NULL)
             goto end;
         for (i = 0; i < sk_X509_num(encerts); i++) {
@@ -978,8 +999,9 @@ int cms_main(int argc, char **argv)
                 goto end;
         }
     } else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
-        cms = CMS_EncryptedData_encrypt(in, cipher,
-                                        secret_key, secret_keylen, flags);
+        cms = CMS_EncryptedData_encrypt_with_libctx(in, cipher, secret_key,
+                                                    secret_keylen, flags,
+                                                    libctx, propq);
 
     } else if (operation == SMIME_SIGN_RECEIPT) {
         CMS_ContentInfo *srcms = NULL;
@@ -1007,14 +1029,15 @@ int cms_main(int argc, char **argv)
                     flags |= CMS_STREAM;
             }
             flags |= CMS_PARTIAL;
-            cms = CMS_sign(NULL, NULL, other, in, flags);
+            cms = CMS_sign_with_libctx(NULL, NULL, other, in, flags, libctx, propq);
             if (cms == NULL)
                 goto end;
             if (econtent_type != NULL)
                 CMS_set1_eContentType(cms, econtent_type);
 
             if (rr_to != NULL) {
-                rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
+                rr = make_receipt_request(rr_to, rr_allorfirst, rr_from, libctx,
+                                          propq);
                 if (rr == NULL) {
                     BIO_puts(bio_err,
                              "Signed Receipt Request Creation Error\n");
@@ -1231,6 +1254,7 @@ int cms_main(int argc, char **argv)
     BIO_free(indata);
     BIO_free_all(out);
     OPENSSL_free(passin);
+    NCONF_free(conf);
     return ret;
 }
 
@@ -1367,9 +1391,10 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
     return NULL;
 }
 
-static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
-                                                *rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
-                                                *rr_from)
+static CMS_ReceiptRequest *make_receipt_request(
+   STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
+   STACK_OF(OPENSSL_STRING) *rr_from,
+   OPENSSL_CTX *libctx, const char *propq)
 {
     STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
     CMS_ReceiptRequest *rr;
@@ -1383,8 +1408,8 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
     } else {
         rct_from = NULL;
     }
-    rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
-                                    rct_to);
+    rr = CMS_ReceiptRequest_create0_with_libctx(NULL, -1, rr_allorfirst,
+                                                rct_from, rct_to, libctx, propq);
     return rr;
  err:
     sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index 2416584dd6..95d3ca0845 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -57,12 +57,14 @@ const OPTIONS pkcs7_options[] = {
 int pkcs7_main(int argc, char **argv)
 {
     ENGINE *e = NULL;
-    PKCS7 *p7 = NULL;
+    PKCS7 *p7 = NULL, *p7i;
     BIO *in = NULL, *out = NULL;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM;
     char *infile = NULL, *outfile = NULL, *prog;
     int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
     OPTION_CHOICE o;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     prog = opt_init(argc, argv, pkcs7_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -119,11 +121,18 @@ int pkcs7_main(int argc, char **argv)
     if (in == NULL)
         goto end;
 
+    p7 = PKCS7_new_with_libctx(libctx, propq);
+    if (p7 == NULL) {
+        BIO_printf(bio_err, "unable to allocate PKCS7 object\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+
     if (informat == FORMAT_ASN1)
-        p7 = d2i_PKCS7_bio(in, NULL);
+        p7i = d2i_PKCS7_bio(in, &p7);
     else
-        p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
-    if (p7 == NULL) {
+        p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
+    if (p7i == NULL) {
         BIO_printf(bio_err, "unable to load PKCS7 object\n");
         ERR_print_errors(bio_err);
         goto end;
diff --git a/apps/smime.c b/apps/smime.c
index 6b7d51b76a..4dfc80d440 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -45,7 +45,7 @@ typedef enum OPTION_choice {
     OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
     OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
     OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
-    OPT_R_ENUM, OPT_PROV_ENUM,
+    OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
     OPT_V_ENUM,
     OPT_IN, OPT_INFORM, OPT_OUT,
     OPT_OUTFORM, OPT_CONTENT
@@ -70,6 +70,7 @@ const OPTIONS smime_options[] = {
     {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
     {"indef", OPT_INDEF, '-', "Same as -stream" },
     {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+    OPT_CONFIG_OPTION,
 
     OPT_SECTION("Action"),
     {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
@@ -133,6 +134,7 @@ const OPTIONS smime_options[] = {
 
 int smime_main(int argc, char **argv)
 {
+    CONF *conf = NULL;
     BIO *in = NULL, *out = NULL, *indata = NULL;
     EVP_PKEY *key = NULL;
     PKCS7 *p7 = NULL;
@@ -155,6 +157,8 @@ int smime_main(int argc, char **argv)
     int vpmtouched = 0, rv = 0;
     ENGINE *e = NULL;
     const char *mime_eol = "\n";
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
         return 1;
@@ -252,6 +256,11 @@ int smime_main(int argc, char **argv)
             if (!opt_provider(o))
                 goto end;
             break;
+        case OPT_CONFIG:
+            conf = app_load_config_modules(opt_arg());
+            if (conf == NULL)
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
@@ -476,18 +485,25 @@ int smime_main(int argc, char **argv)
         goto end;
 
     if (operation & SMIME_IP) {
+        PKCS7 *p7_in = NULL;
+
+        p7 = PKCS7_new_with_libctx(libctx, propq);
+        if (p7 == NULL) {
+            BIO_printf(bio_err, "Error allocating PKCS7 object\n");
+            goto end;
+        }
         if (informat == FORMAT_SMIME) {
-            p7 = SMIME_read_PKCS7(in, &indata);
+            p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7);
         } else if (informat == FORMAT_PEM) {
-            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+            p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
         } else if (informat == FORMAT_ASN1) {
-            p7 = d2i_PKCS7_bio(in, NULL);
+            p7_in = d2i_PKCS7_bio(in, &p7);
         } else {
             BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
             goto end;
         }
 
-        if (p7 == NULL) {
+        if (p7_in == NULL) {
             BIO_printf(bio_err, "Error reading S/MIME message\n");
             goto end;
         }
@@ -518,7 +534,7 @@ int smime_main(int argc, char **argv)
     if (operation == SMIME_ENCRYPT) {
         if (indef)
             flags |= PKCS7_STREAM;
-        p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+        p7 = PKCS7_encrypt_with_libctx(encerts, in, cipher, flags, libctx, propq);
     } else if (operation & SMIME_SIGNERS) {
         int i;
         /*
@@ -533,7 +549,8 @@ int smime_main(int argc, char **argv)
                 flags |= PKCS7_STREAM;
             }
             flags |= PKCS7_PARTIAL;
-            p7 = PKCS7_sign(NULL, NULL, other, in, flags);
+            p7 = PKCS7_sign_with_libctx(NULL, NULL, other, in, flags, libctx,
+                                        propq);
             if (p7 == NULL)
                 goto end;
             if (flags & PKCS7_NOCERTS) {
@@ -643,6 +660,7 @@ int smime_main(int argc, char **argv)
     BIO_free(indata);
     BIO_free_all(out);
     OPENSSL_free(passin);
+    NCONF_free(conf);
     return ret;
 }
 
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
index dab89e57d5..461ffbb332 100644
--- a/crypto/asn1/asn_mime.c
+++ b/crypto/asn1/asn_mime.c
@@ -14,6 +14,7 @@
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/cms.h>
 #include "crypto/evp.h"
 #include "internal/bio.h"
 #include "asn1_local.h"
@@ -132,7 +133,7 @@ int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
     return r;
 }
 
-static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
+static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it, ASN1_VALUE **x)
 {
     BIO *b64;
     ASN1_VALUE *val;
@@ -142,7 +143,7 @@ static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
         return 0;
     }
     bio = BIO_push(b64, bio);
-    val = ASN1_item_d2i_bio(it, bio, NULL);
+    val = ASN1_item_d2i_bio(it, bio, x);
     if (!val)
         ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR);
     (void)BIO_flush(bio);
@@ -231,14 +232,17 @@ static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
 
 /* SMIME sender */
 
-int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
-                     int ctype_nid, int econt_nid,
-                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+int SMIME_write_ASN1_with_libctx(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                                 int ctype_nid, int econt_nid,
+                                 STACK_OF(X509_ALGOR) *mdalgs,
+                                 const ASN1_ITEM *it,
+                                 OPENSSL_CTX *libctx, const char *propq)
 {
     char bound[33], c;
     int i;
     const char *mime_prefix, *mime_eol, *cname = "smime.p7m";
     const char *msg_type = NULL;
+
     if (flags & SMIME_OLDMIME)
         mime_prefix = "application/x-pkcs7-";
     else
@@ -251,7 +255,7 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
     if ((flags & SMIME_DETACHED) && data) {
         /* We want multipart/signed */
         /* Generate a random boundary */
-        if (RAND_bytes((unsigned char *)bound, 32) <= 0)
+        if (RAND_bytes_ex(libctx, (unsigned char *)bound, 32) <= 0)
             return 0;
         for (i = 0; i < 32; i++) {
             c = bound[i] & 0xf;
@@ -321,6 +325,14 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
     return 1;
 }
 
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                     int ctype_nid, int econt_nid,
+                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it)
+{
+    return SMIME_write_ASN1_with_libctx(bio, val, data, flags, ctype_nid,
+                                        econt_nid, mdalgs, it, NULL, NULL);
+}
+
 /* Handle output of ASN1 data */
 
 /* cannot constify val because of CMS_dataFinal() */
@@ -380,7 +392,8 @@ static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
  * opaque this is set to NULL
  */
 
-ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, BIO **bcont, const ASN1_ITEM *it,
+                               ASN1_VALUE **x)
 {
     BIO *asnin;
     STACK_OF(MIME_HEADER) *headers = NULL;
@@ -394,14 +407,14 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         *bcont = NULL;
 
     if ((headers = mime_parse_hdr(bio)) == NULL) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR);
+        ASN1err(0, ASN1_R_MIME_PARSE_ERROR);
         return NULL;
     }
 
     if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
         || hdr->value == NULL) {
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE);
+        ASN1err(0, ASN1_R_NO_CONTENT_TYPE);
         return NULL;
     }
 
@@ -412,13 +425,13 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         prm = mime_param_find(hdr, "boundary");
         if (prm == NULL || prm->param_value == NULL) {
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY);
+            ASN1err(0, ASN1_R_NO_MULTIPART_BOUNDARY);
             return NULL;
         }
         ret = multi_split(bio, prm->param_value, &parts);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         if (!ret || (sk_BIO_num(parts) != 2)) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE);
+            ASN1err(0, ASN1_R_NO_MULTIPART_BODY_FAILURE);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -427,7 +440,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         asnin = sk_BIO_value(parts, 1);
 
         if ((headers = mime_parse_hdr(asnin)) == NULL) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR);
+            ASN1err(0, ASN1_R_MIME_SIG_PARSE_ERROR);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -437,14 +450,14 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         if ((hdr = mime_hdr_find(headers, "content-type")) == NULL
             || hdr->value == NULL) {
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE);
+            ASN1err(0, ASN1_R_NO_SIG_CONTENT_TYPE);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
 
         if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
             strcmp(hdr->value, "application/pkcs7-signature")) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE);
+            ASN1err(0, ASN1_R_SIG_INVALID_MIME_TYPE);
             ERR_add_error_data(2, "type: ", hdr->value);
             sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
             sk_BIO_pop_free(parts, BIO_vfree);
@@ -452,8 +465,8 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
         }
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         /* Read in ASN1 */
-        if ((val = b64_read_asn1(asnin, it)) == NULL) {
-            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR);
+        if ((val = b64_read_asn1(asnin, it, x)) == NULL) {
+            ASN1err(0, ASN1_R_ASN1_SIG_PARSE_ERROR);
             sk_BIO_pop_free(parts, BIO_vfree);
             return NULL;
         }
@@ -471,7 +484,7 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
 
     if (strcmp(hdr->value, "application/x-pkcs7-mime") &&
         strcmp(hdr->value, "application/pkcs7-mime")) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE);
+        ASN1err(0, ASN1_R_INVALID_MIME_TYPE);
         ERR_add_error_data(2, "type: ", hdr->value);
         sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
         return NULL;
@@ -479,12 +492,16 @@ ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
 
     sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
 
-    if ((val = b64_read_asn1(bio, it)) == NULL) {
-        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR);
+    if ((val = b64_read_asn1(bio, it, x)) == NULL) {
+        ASN1err(0, ASN1_R_ASN1_PARSE_ERROR);
         return NULL;
     }
     return val;
+}
 
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+{
+    return SMIME_read_ASN1_ex(bio, bcont, it, NULL);
 }
 
 /* Copy text from one BIO to another making the output CRLF at EOL */
diff --git a/crypto/cms/cms_cd.c b/crypto/cms/cms_cd.c
index ac40275b63..c596eab2c2 100644
--- a/crypto/cms/cms_cd.c
+++ b/crypto/cms/cms_cd.c
@@ -21,10 +21,12 @@
 
 /* CMS CompressedData Utilities */
 
-CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
+CMS_ContentInfo *cms_CompressedData_create(int comp_nid, OPENSSL_CTX *libctx,
+                                           const char *propq)
 {
     CMS_ContentInfo *cms;
     CMS_CompressedData *cd;
+
     /*
      * Will need something cleverer if there is ever more than one
      * compression algorithm or parameters have some meaning...
@@ -34,7 +36,7 @@ CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
                CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
         return NULL;
     }
-    cms = CMS_ContentInfo_new();
+    cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
     if (cms == NULL)
         return NULL;
 
@@ -64,6 +66,7 @@ BIO *cms_CompressedData_init_bio(const CMS_ContentInfo *cms)
 {
     CMS_CompressedData *cd;
     const ASN1_OBJECT *compoid;
+
     if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) {
         CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
                CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA);
diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c
index 9da26476e0..2b2d970acd 100644
--- a/crypto/cms/cms_dd.c
+++ b/crypto/cms/cms_dd.c
@@ -17,11 +17,13 @@
 
 /* CMS DigestedData Utilities */
 
-CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
+CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md,
+                                         OPENSSL_CTX *libctx, const char *propq)
 {
     CMS_ContentInfo *cms;
     CMS_DigestedData *dd;
-    cms = CMS_ContentInfo_new();
+
+    cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
     if (cms == NULL)
         return NULL;
 
@@ -47,9 +49,9 @@ CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
 
 BIO *cms_DigestedData_init_bio(const CMS_ContentInfo *cms)
 {
-    CMS_DigestedData *dd;
-    dd = cms->d.digestedData;
-    return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm);
+    CMS_DigestedData *dd = cms->d.digestedData;
+
+    return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm, cms_get0_cmsctx(cms));
 }
 
 int cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, int verify)
diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c
index 3eb2f41a6a..e25453ec9c 100644
--- a/crypto/cms/cms_enc.c
+++ b/crypto/cms/cms_enc.c
@@ -20,19 +20,19 @@
 
 /* Return BIO based on EncryptedContentInfo and key */
 
-BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
+BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
+                                   const CMS_CTX *cms_ctx)
 {
     BIO *b;
     EVP_CIPHER_CTX *ctx;
-    const EVP_CIPHER *ciph;
+    EVP_CIPHER *fetched_ciph = NULL;
+    const EVP_CIPHER *cipher = NULL;
     X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
     unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
     unsigned char *tkey = NULL;
     int len;
     size_t tkeylen = 0;
-
     int ok = 0;
-
     int enc, keep_key = 0;
 
     enc = ec->cipher ? 1 : 0;
@@ -46,26 +46,29 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
     BIO_get_cipher_ctx(b, &ctx);
 
     if (enc) {
-        ciph = ec->cipher;
+        cipher = ec->cipher;
         /*
          * If not keeping key set cipher to NULL so subsequent calls decrypt.
          */
-        if (ec->key)
+        if (ec->key != NULL)
             ec->cipher = NULL;
     } else {
-        ciph = EVP_get_cipherbyobj(calg->algorithm);
-
-        if (!ciph) {
+        cipher = EVP_get_cipherbyobj(calg->algorithm);
+    }
+    if (cipher != NULL) {
+        fetched_ciph = EVP_CIPHER_fetch(cms_ctx->libctx, EVP_CIPHER_name(cipher),
+                                        cms_ctx->propq);
+        if (fetched_ciph == NULL) {
             CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
             goto err;
         }
     }
-
-    if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
+    if (EVP_CipherInit_ex(ctx, fetched_ciph, NULL, NULL, NULL, enc) <= 0) {
         CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
                CMS_R_CIPHER_INITIALISATION_ERROR);
         goto err;
     }
+    EVP_CIPHER_free(fetched_ciph);
 
     if (enc) {
         int ivlen;
@@ -73,7 +76,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
         /* Generate a random IV if we need one */
         ivlen = EVP_CIPHER_CTX_iv_length(ctx);
         if (ivlen > 0) {
-            if (RAND_bytes(iv, ivlen) <= 0)
+            if (RAND_bytes_ex(cms_ctx->libctx, iv, ivlen) <= 0)
                 goto err;
             piv = iv;
         }
@@ -169,7 +172,8 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
 
 int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
                               const EVP_CIPHER *cipher,
-                              const unsigned char *key, size_t keylen)
+                              const unsigned char *key, size_t keylen,
+                              const CMS_CTX *cms_ctx)
 {
     ec->cipher = cipher;
     if (key) {
@@ -180,7 +184,7 @@ int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
         memcpy(ec->key, key, keylen);
     }
     ec->keylen = keylen;
-    if (cipher)
+    if (cipher != NULL)
         ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
     return 1;
 }
@@ -189,6 +193,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
                                const unsigned char *key, size_t keylen)
 {
     CMS_EncryptedContentInfo *ec;
+
     if (!key || !keylen) {
         CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
         return 0;
@@ -206,7 +211,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
         return 0;
     }
     ec = cms->d.encryptedData->encryptedContentInfo;
-    return cms_EncryptedContent_init(ec, ciph, key, keylen);
+    return cms_EncryptedContent_init(ec, ciph, key, keylen, cms_get0_cmsctx(cms));
 }
 
 BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
@@ -214,5 +219,6 @@ BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
     CMS_EncryptedData *enc = cms->d.encryptedData;
     if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
         enc->version = 2;
-    return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
+    return cms_EncryptedContent_init_bio(enc->encryptedContentInfo,
+                                         cms_get0_cmsctx(cms));
 }
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
index a5ef2ddee5..94961cd038 100644
--- a/crypto/cms/cms_env.c
+++ b/crypto/cms/cms_env.c
@@ -14,9 +14,10 @@
 #include <openssl/err.h>
 #include <openssl/cms.h>
 #include <openssl/evp.h>
-#include "cms_local.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/x509.h"
+#include "cms_local.h"
 
 DEFINE_STACK_OF(CMS_RecipientInfo)
 DEFINE_STACK_OF(CMS_RevocationInfoChoice)
@@ -94,6 +95,37 @@ STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
     return env->recipientInfos;
 }
 
+void cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
+{
+    int i;
+    CMS_RecipientInfo *ri;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+    STACK_OF(CMS_RecipientInfo) *rinfos = CMS_get0_RecipientInfos(cms);
+
+    for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
+        ri = sk_CMS_RecipientInfo_value(rinfos, i);
+        if (ri != NULL) {
+            switch (ri->type) {
+            case CMS_RECIPINFO_AGREE:
+                ri->d.kari->cms_ctx = ctx;
+                break;
+            case CMS_RECIPINFO_TRANS:
+                ri->d.ktri->cms_ctx = ctx;
+                x509_set0_libctx(ri->d.ktri->recip, ctx->libctx, ctx->propq);
+                break;
+            case CMS_RECIPINFO_KEK:
+                ri->d.kekri->cms_ctx = ctx;
+                break;
+            case CMS_RECIPINFO_PASS:
+                ri->d.pwri->cms_ctx = ctx;
+                break;
+            default:
+                break;
+            }
+        }
+    }
+}
+
 int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
 {
     return ri->type;
@@ -108,26 +140,35 @@ EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
     return NULL;
 }
 
-CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+CMS_ContentInfo *CMS_EnvelopedData_create_with_libctx(const EVP_CIPHER *cipher,
+                                                      OPENSSL_CTX *libctx,
+                                                      const char *propq)
 {
     CMS_ContentInfo *cms;
     CMS_EnvelopedData *env;
-    cms = CMS_ContentInfo_new();
+
+    cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
     if (cms == NULL)
         goto merr;
     env = cms_enveloped_data_init(cms);
     if (env == NULL)
         goto merr;
-    if (!cms_EncryptedContent_init(env->encryptedContentInfo,
-                                   cipher, NULL, 0))
+
+    if (!cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL, 0,
+                                   cms_get0_cmsctx(cms)))
         goto merr;
     return cms;
  merr:
     CMS_ContentInfo_free(cms);
-    CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
+    CMSerr(0, ERR_R_MALLOC_FAILURE);
     return NULL;
 }
 
+CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+{
+    return CMS_EnvelopedData_create_with_libctx(cipher, NULL, NULL);
+}
+
 int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
 {
     CMS_EnvelopedData *env = NULL;
@@ -174,7 +215,8 @@ int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
 /* Initialise a ktri based on passed certificate and key */
 
 static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
-                                       EVP_PKEY *pk, unsigned int flags)
+                                       EVP_PKEY *pk, unsigned int flags,
+                                       const CMS_CTX *ctx)
 {
     CMS_KeyTransRecipientInfo *ktri;
     int idtype;
@@ -185,6 +227,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
     ri->type = CMS_RECIPINFO_TRANS;
 
     ktri = ri->d.ktri;
+    ktri->cms_ctx = ctx;
 
     if (flags & CMS_USE_KEYID) {
         ktri->version = 2;
@@ -199,7 +242,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
      * structure.
      */
 
-    if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype))
+    if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx))
         return 0;
 
     X509_up_ref(recip);
@@ -209,7 +252,8 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
     ktri->recip = recip;
 
     if (flags & CMS_KEY_PARAM) {
-        ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+        ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ktri->pkey,
+                                                ctx->propq);
         if (ktri->pctx == NULL)
             return 0;
         if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
@@ -230,6 +274,8 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
     CMS_RecipientInfo *ri = NULL;
     CMS_EnvelopedData *env;
     EVP_PKEY *pk = NULL;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+
     env = cms_get0_enveloped(cms);
     if (!env)
         goto err;
@@ -248,12 +294,13 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
     switch (cms_pkey_get_ri_type(pk)) {
 
     case CMS_RECIPINFO_TRANS:
-        if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags))
+        if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags, ctx))
             goto err;
         break;
 
     case CMS_RECIPINFO_AGREE:
-        if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator, originatorPrivKey, flags))
+        if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator,
+                                         originatorPrivKey, flags, ctx))
             goto err;
         break;
 
@@ -352,6 +399,7 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
     EVP_PKEY_CTX *pctx;
     unsigned char *ek = NULL;
     size_t eklen;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
 
     int ret = 0;
 
@@ -368,7 +416,7 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
         if (!cms_env_asn1_ctrl(ri, 0))
             goto err;
     } else {
-        pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+        pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ktri->pkey, ctx->propq);
         if (pctx == NULL)
             return 0;
 
@@ -405,7 +453,6 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
     ktri->pctx = NULL;
     OPENSSL_free(ek);
     return ret;
-
 }
 
 /* Decrypt content key from KTRI */
@@ -419,7 +466,10 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
     size_t eklen;
     int ret = 0;
     size_t fixlen = 0;
+    EVP_CIPHER *ciph = NULL;
     CMS_EncryptedContentInfo *ec;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+
     ec = cms->d.envelopedData->encryptedContentInfo;
 
     if (ktri->pkey == NULL) {
@@ -430,19 +480,21 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
     if (cms->d.envelopedData->encryptedContentInfo->havenocert
             && !cms->d.envelopedData->encryptedContentInfo->debug) {
         X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
-        const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm);
+        const char *name = OBJ_nid2sn(OBJ_obj2nid(calg->algorithm));
 
+        ciph = EVP_CIPHER_fetch(ctx->libctx, name, ctx->propq);
         if (ciph == NULL) {
             CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER);
             return 0;
         }
 
         fixlen = EVP_CIPHER_key_length(ciph);
+        EVP_CIPHER_free(ciph);
     }
 
-    ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
+    ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq);
     if (ktri->pctx == NULL)
-        return 0;
+        goto err;
 
     if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
         goto err;
@@ -627,7 +679,6 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
  err:
     M_ASN1_free_of(ri, CMS_RecipientInfo);
     return NULL;
-
 }
 
 int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
@@ -679,20 +730,24 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
     return 1;
 }
 
-static const EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen)
+static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx)
 {
+    const char *alg = NULL;
+
     switch(keylen) {
     case 16:
-        return EVP_aes_128_wrap();
-
+        alg = "AES-128-WRAP";
+        break;
     case 24:
-        return EVP_aes_192_wrap();
-
+        alg = "AES-192-WRAP";
+        break;
     case 32:
-        return EVP_aes_256_wrap();
+        alg = "AES-256-WRAP";
+        break;
+    default:
+        return NULL;
     }
-
-    return NULL;
+    return EVP_CIPHER_fetch(ctx->libctx, alg, ctx->propq);
 }
 
 
@@ -706,9 +761,10 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
     unsigned char *wkey = NULL;
     int wkeylen;
     int r = 0;
-    const EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER *cipher = NULL;
     int outlen = 0;
     EVP_CIPHER_CTX *ctx = NULL;
+    const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
 
     ec = cms->d.envelopedData->encryptedContentInfo;
 
@@ -719,7 +775,7 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
         return 0;
     }
 
-    cipher = cms_get_key_wrap_cipher(kekri->keylen);
+    cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
     if (cipher == NULL) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_INVALID_KEY_LENGTH);
         goto err;
@@ -756,12 +812,12 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
     r = 1;
 
  err:
+    EVP_CIPHER_free(cipher);
     if (!r)
         OPENSSL_free(wkey);
     EVP_CIPHER_CTX_free(ctx);
 
     return r;
-
 }
 
 /* Decrypt content key in KEK recipient info */
@@ -774,9 +830,10 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
     unsigned char *ukey = NULL;
     int ukeylen;
     int r = 0, wrap_nid;
-    const EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER *cipher = NULL;
     int outlen = 0;
     EVP_CIPHER_CTX *ctx = NULL;
+    const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
 
     ec = cms->d.envelopedData->encryptedContentInfo;
 
@@ -802,7 +859,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
         goto err;
     }
 
-    cipher = cms_get_key_wrap_cipher(kekri->keylen);
+    cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
     if (cipher == NULL) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_INVALID_KEY_LENGTH);
         goto err;
@@ -836,12 +893,12 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
     r = 1;
 
  err:
+    EVP_CIPHER_free(cipher);
     if (!r)
         OPENSSL_free(ukey);
     EVP_CIPHER_CTX_free(ctx);
 
     return r;
-
 }
 
 int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
@@ -951,7 +1008,7 @@ static void cms_env_set_version(CMS_EnvelopedData *env)
 static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
 {
     CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
-    BIO *contentBio = cms_EncryptedContent_init_bio(ec);
+    BIO *contentBio = cms_EncryptedContent_init_bio(ec, cms_get0_cmsctx(cms));
     EVP_CIPHER_CTX *ctx = NULL;
 
     if (contentBio == NULL)
@@ -986,7 +1043,7 @@ static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
     /* Get BIO first to set up key */
 
     ec = cms->d.envelopedData->encryptedContentInfo;
-    ret = cms_EncryptedContent_init_bio(ec);
+    ret = cms_EncryptedContent_init_bio(ec, cms_get0_cmsctx(cms));
 
     /* If error end of processing */
     if (!ret)
@@ -1051,7 +1108,8 @@ int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
     if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
         int i, r;
 
-        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED, ri_type, &r);
+        i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED,
+                                 ri_type, &r);
         if (i > 0)
             return r;
     }
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
index e3604f7db8..3e545b7add 100644
--- a/crypto/cms/cms_ess.c
+++ b/crypto/cms/cms_ess.c
@@ -15,9 +15,10 @@
 #include <openssl/err.h>
 #include <openssl/cms.h>
 #include <openssl/ess.h>
-#include "cms_local.h"
 #include "crypto/ess.h"
 #include "crypto/cms.h"
+#include "crypto/x509.h"
+#include "cms_local.h"
 
 DEFINE_STACK_OF(GENERAL_NAMES)
 DEFINE_STACK_OF(CMS_SignerInfo)
@@ -119,11 +120,10 @@ int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain)
     return ret;
 }
 
-CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
-                                               int allorfirst,
-                                               STACK_OF(GENERAL_NAMES)
-                                               *receiptList, STACK_OF(GENERAL_NAMES)
-                                               *receiptsTo)
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0_with_libctx(
+    unsigned char *id, int idlen, int allorfirst,
+    STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo,
+    OPENSSL_CTX *libctx, const char *propq)
 {
     CMS_ReceiptRequest *rr;
 
@@ -135,14 +135,14 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
     else {
         if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
             goto merr;
-        if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
+        if (RAND_bytes_ex(libctx, rr->signedContentIdentifier->data, 32) <= 0)
             goto err;
     }
 
     sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
     rr->receiptsTo = receiptsTo;
 
-    if (receiptList) {
+    if (receiptList != NULL) {
         rr->receiptsFrom->type = 1;
         rr->receiptsFrom->d.receiptList = receiptList;
     } else {
@@ -153,7 +153,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
     return rr;
 
  merr:
-    CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
+    CMSerr(0, ERR_R_MALLOC_FAILURE);
 
  err:
     CMS_ReceiptRequest_free(rr);
@@ -161,6 +161,15 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
 
 }
 
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+    unsigned char *id, int idlen, int allorfirst,
+    STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo)
+{
+    return CMS_ReceiptRequest_create0_with_libctx(id, idlen, allorfirst,
+                                                  receiptList, receiptsTo,
+                                                  NULL, NULL);
+}
+
 int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
 {
     unsigned char *rrder = NULL;
@@ -192,20 +201,20 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
                                     STACK_OF(GENERAL_NAMES) **plist,
                                     STACK_OF(GENERAL_NAMES) **prto)
 {
-    if (pcid)
+    if (pcid != NULL)
         *pcid = rr->signedContentIdentifier;
     if (rr->receiptsFrom->type == 0) {
-        if (pallorfirst)
+        if (pallorfirst != NULL)
             *pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
-        if (plist)
+        if (plist != NULL)
             *plist = NULL;
     } else {
-        if (pallorfirst)
+        if (pallorfirst != NULL)
             *pallorfirst = -1;
-        if (plist)
+        if (plist != NULL)
             *plist = rr->receiptsFrom->d.receiptList;
     }
-    if (prto)
+    if (prto != NULL)
         *prto = rr->receiptsTo;
 }
 
@@ -214,13 +223,13 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
 static int cms_msgSigDigest(CMS_SignerInfo *si,
                             unsigned char *dig, unsigned int *diglen)
 {
-    const EVP_MD *md;
+    const EVP_MD *md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
 
-    md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
     if (md == NULL)
         return 0;
-    if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
-                          si->signedAttrs, dig, diglen))
+    if (!asn1_item_digest_with_libctx(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
+                                      si->signedAttrs, dig, diglen,
+                                      si->cms_ctx->libctx, si->cms_ctx->propq))
         return 0;
     return 1;
 }
diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c
index ef72164181..70a7c652e9 100644
--- a/crypto/cms/cms_io.c
+++ b/crypto/cms/cms_io.c
@@ -35,7 +35,12 @@ int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
 
 CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms)
 {
-    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
+    CMS_ContentInfo *ci;
+
+    ci = ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
+    if (ci != NULL && cms != NULL)
+        cms_resolve_libctx(ci);
+    return ci;
 }
 
 int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
@@ -71,19 +76,33 @@ int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags)
     STACK_OF(X509_ALGOR) *mdalgs;
     int ctype_nid = OBJ_obj2nid(cms->contentType);
     int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms));
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+
     if (ctype_nid == NID_pkcs7_signed)
         mdalgs = cms->d.signedData->digestAlgorithms;
     else
         mdalgs = NULL;
 
-    return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags,
-                            ctype_nid, econt_nid, mdalgs,
-                            ASN1_ITEM_rptr(CMS_ContentInfo));
+    return SMIME_write_ASN1_with_libctx(bio, (ASN1_VALUE *)cms, data, flags,
+                                        ctype_nid, econt_nid, mdalgs,
+                                        ASN1_ITEM_rptr(CMS_ContentInfo),
+                                        cms_ctx_get0_libctx(ctx),
+                                        cms_ctx_get0_propq(ctx));
+}
+
+CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, BIO **bcont, CMS_ContentInfo **cms)
+{
+    CMS_ContentInfo *ci;
+
+    ci = (CMS_ContentInfo *)SMIME_read_ASN1_ex(bio, bcont,
+                                               ASN1_ITEM_rptr(CMS_ContentInfo),
+                                               (ASN1_VALUE **)cms);
+    if (ci != NULL && cms != NULL)
+        cms_resolve_libctx(ci);
+    return ci;
 }
 
 CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont)
 {
-    return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont,
-                                              ASN1_ITEM_rptr
-                                              (CMS_ContentInfo));
+    return SMIME_read_CMS_ex(bio, bcont, NULL);
 }
diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c
index 30d38b5fd6..97b601b3bc 100644
--- a/crypto/cms/cms_kari.c
+++ b/crypto/cms/cms_kari.c
@@ -64,6 +64,7 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
                                         ASN1_INTEGER **sno)
 {
     CMS_OriginatorIdentifierOrKey *oik;
+
     if (ri->type != CMS_RECIPINFO_AGREE) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID,
                CMS_R_NOT_KEY_AGREEMENT);
@@ -101,6 +102,7 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
 int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
 {
     CMS_OriginatorIdentifierOrKey *oik;
+
     if (ri->type != CMS_RECIPINFO_AGREE) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP,
                CMS_R_NOT_KEY_AGREEMENT);
@@ -121,6 +123,7 @@ int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
                                       X509_NAME **issuer, ASN1_INTEGER **sno)
 {
     CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
+
     if (rid->type == CMS_REK_ISSUER_SERIAL) {
         if (issuer)
             *issuer = rid->d.issuerAndSerialNumber->issuer;
@@ -152,6 +155,7 @@ int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
                                        X509 *cert)
 {
     CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
+
     if (rid->type == CMS_REK_ISSUER_SERIAL)
         return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
     else if (rid->type == CMS_REK_KEYIDENTIFIER)
@@ -170,7 +174,8 @@ int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *p
     if (pk == NULL)
         return 1;
 
-    pctx = EVP_PKEY_CTX_new(pk, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(kari->cms_ctx->libctx, pk,
+                                      kari->cms_ctx->propq);
     if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
         goto err;
 
@@ -215,6 +220,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
     int rv = 0;
     unsigned char *out = NULL;
     int outlen;
+
     keklen = EVP_CIPHER_CTX_key_length(kari->ctx);
     if (keklen > EVP_MAX_KEY_LENGTH)
         return 0;
@@ -303,8 +309,9 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
     EVP_PKEY_CTX *pctx = NULL;
     EVP_PKEY *ekey = NULL;
     int rv = 0;
+    const CMS_CTX *ctx = kari->cms_ctx;
 
-    pctx = EVP_PKEY_CTX_new(pk, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pk, ctx->propq);
     if (pctx == NULL)
         goto err;
     if (EVP_PKEY_keygen_init(pctx) <= 0)
@@ -312,7 +319,7 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
     if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
         goto err;
     EVP_PKEY_CTX_free(pctx);
-    pctx = EVP_PKEY_CTX_new(ekey, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ekey, ctx->propq);
     if (pctx == NULL)
         goto err;
     if (EVP_PKEY_derive_init(pctx) <= 0)
@@ -327,12 +334,14 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
 }
 
 /* Set originator private key and initialise context based on it */
-static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *originatorPrivKey )
+static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
+                                               EVP_PKEY *originatorPrivKey )
 {
     EVP_PKEY_CTX *pctx = NULL;
     int rv = 0;
+    const CMS_CTX *ctx = kari->cms_ctx;
 
-    pctx = EVP_PKEY_CTX_new(originatorPrivKey, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, originatorPrivKey, ctx->propq);
     if (pctx == NULL)
         goto err;
     if (EVP_PKEY_derive_init(pctx) <= 0)
@@ -348,18 +357,22 @@ static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
 
 /* Initialise a kari based on passed certificate and key */
 
-int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri,  X509 *recip, EVP_PKEY *recipPubKey, X509 * originator, EVP_PKEY *originatorPrivKey, unsigned int flags)
+int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri,  X509 *recip,
+                                EVP_PKEY *recipPubKey, X509 *originator,
+                                EVP_PKEY *originatorPrivKey, unsigned int flags,
+                                const CMS_CTX *ctx)
 {
     CMS_KeyAgreeRecipientInfo *kari;
     CMS_RecipientEncryptedKey *rek = NULL;
 
     ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
-    if (!ri->d.kari)
+    if (ri->d.kari == NULL)
         return 0;
     ri->type = CMS_RECIPINFO_AGREE;
 
     kari = ri->d.kari;
     kari->version = 3;
+    kari->cms_ctx = ctx;
 
     rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
     if (rek == NULL)
@@ -419,8 +432,11 @@ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri,  X509 *recip, EVP_PKEY *r
 static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
                          const EVP_CIPHER *cipher)
 {
+    const CMS_CTX *cms_ctx = kari->cms_ctx;
     EVP_CIPHER_CTX *ctx = kari->ctx;
     const EVP_CIPHER *kekcipher;
+    EVP_CIPHER *fetched_kekcipher;
+    const char *kekcipher_name;
     int keylen;
     int ret;
 
@@ -444,8 +460,8 @@ static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
         if (kekcipher != NULL) {
              if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
                  return 0;
-
-             return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
+             kekcipher_name = EVP_CIPHER_name(kekcipher);
+             goto enc;
         }
     }
 
@@ -455,16 +471,23 @@ static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
      */
 #ifndef OPENSSL_NO_DES
     if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
-        kekcipher = EVP_des_ede3_wrap();
+        kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
     else
 #endif
     if (keylen <= 16)
-        kekcipher = EVP_aes_128_wrap();
+        kekcipher_name = SN_id_aes128_wrap;
     else if (keylen <= 24)
-        kekcipher = EVP_aes_192_wrap();
+        kekcipher_name = SN_id_aes192_wrap;
     else
-        kekcipher = EVP_aes_256_wrap();
-    return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
+        kekcipher_name = SN_id_aes256_wrap;
+enc:
+    fetched_kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, kekcipher_name,
+                                         cms_ctx->propq);
+    if (fetched_kekcipher == NULL)
+        return 0;
+    ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
+    EVP_CIPHER_free(fetched_kekcipher);
+    return ret;
 }
 
 /* Encrypt content key in key agreement recipient info */
@@ -542,5 +565,4 @@ int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
     }
 
     return 1;
-
 }
diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c
index 6e2a20c4b3..61f965c6dc 100644
--- a/crypto/cms/cms_lib.c
+++ b/crypto/cms/cms_lib.c
@@ -14,24 +14,118 @@
 #include <openssl/bio.h>
 #include <openssl/asn1.h>
 #include <openssl/cms.h>
+#include <openssl/cms.h>
+#include "crypto/x509.h"
 #include "cms_local.h"
 
+static STACK_OF(CMS_CertificateChoices)
+**cms_get0_certificate_choices(CMS_ContentInfo *cms);
+
 DEFINE_STACK_OF(CMS_RevocationInfoChoice)
 DEFINE_STACK_OF(X509)
 DEFINE_STACK_OF(X509_CRL)
 
-IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo)
 IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 
+CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
+                                     const unsigned char **in, long len)
+{
+    CMS_ContentInfo *ci;
+
+    ci = (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+                                          (CMS_ContentInfo_it()));
+    if (ci != NULL && a != NULL)
+        cms_resolve_libctx(ci);
+    return ci;
+}
+
+int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
+{
+    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
+}
+
+CMS_ContentInfo *CMS_ContentInfo_new_with_libctx(OPENSSL_CTX *libctx,
+                                                 const char *propq)
+{
+    CMS_ContentInfo *ci;
+
+    ci = (CMS_ContentInfo *)ASN1_item_new(ASN1_ITEM_rptr(CMS_ContentInfo));
+    if (ci != NULL) {
+        ci->ctx.libctx = libctx;
+        ci->ctx.propq = NULL;
+        if (propq != NULL) {
+            ci->ctx.propq = OPENSSL_strdup(propq);
+            if (ci->ctx.propq == NULL) {
+                CMS_ContentInfo_free(ci);
+                ci = NULL;
+                ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+            }
+        }
+    }
+    return ci;
+}
+
+CMS_ContentInfo *CMS_ContentInfo_new(void)
+{
+    return CMS_ContentInfo_new_with_libctx(NULL, NULL);
+}
+
+void CMS_ContentInfo_free(CMS_ContentInfo *cms)
+{
+    if (cms != NULL) {
+        OPENSSL_free(cms->ctx.propq);
+        ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
+    }
+}
+
+const CMS_CTX *cms_get0_cmsctx(const CMS_ContentInfo *cms)
+{
+    return cms != NULL ? &cms->ctx : NULL;
+}
+
+OPENSSL_CTX *cms_ctx_get0_libctx(const CMS_CTX *ctx)
+{
+    return ctx->libctx;
+}
+
+const char *cms_ctx_get0_propq(const CMS_CTX *ctx)
+{
+    return ctx->propq;
+}
+
+void cms_resolve_libctx(CMS_ContentInfo *ci)
+{
+    int i;
+    CMS_CertificateChoices *cch;
+    STACK_OF(CMS_CertificateChoices) **pcerts;
+    const CMS_CTX *ctx;
+
+    if (ci == NULL)
+        return;
+
+    ctx = cms_get0_cmsctx(ci);
+    cms_SignerInfos_set_cmsctx(ci);
+    cms_RecipientInfos_set_cmsctx(ci);
+
+    pcerts = cms_get0_certificate_choices(ci);
+    if (pcerts != NULL) {
+        for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
+            cch = sk_CMS_CertificateChoices_value(*pcerts, i);
+            if (cch->type == CMS_CERTCHOICE_CERT)
+                x509_set0_libctx(cch->d.certificate, ctx->libctx, ctx->propq);
+        }
+    }
+}
+
 const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
 {
     return cms->contentType;
 }
 
-CMS_ContentInfo *cms_Data_create(void)
+CMS_ContentInfo *cms_Data_create(OPENSSL_CTX *libctx, const char *propq)
 {
-    CMS_ContentInfo *cms;
-    cms = CMS_ContentInfo_new();
+    CMS_ContentInfo *cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
+
     if (cms != NULL) {
         cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
         /* Never detached */
@@ -295,14 +389,18 @@ int CMS_set_detached(CMS_ContentInfo *cms, int detached)
 
 /* Create a digest BIO from an X509_ALGOR structure */
 
-BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
+BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
+                                  const CMS_CTX *ctx)
 {
     BIO *mdbio = NULL;
     const ASN1_OBJECT *digestoid;
-    const EVP_MD *digest;
+    EVP_MD *digest = NULL;
+    const char *alg;
+
     X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
-    digest = EVP_get_digestbyobj(digestoid);
-    if (!digest) {
+    alg = OBJ_nid2sn(OBJ_obj2nid(digestoid));
+    digest = EVP_MD_fetch(ctx->libctx, alg, ctx->propq);
+    if (digest == NULL) {
         CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
                CMS_R_UNKNOWN_DIGEST_ALGORITHM);
         goto err;
@@ -312,8 +410,10 @@ BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
         CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
         goto err;
     }
+    EVP_MD_free(digest);
     return mdbio;
  err:
+    EVP_MD_free(digest);
     BIO_free(mdbio);
     return NULL;
 }
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
index 68c885622b..4e85459a54 100644
--- a/crypto/cms/cms_local.h
+++ b/crypto/cms/cms_local.h
@@ -43,6 +43,12 @@ typedef struct CMS_KEKRecipientInfo_st CMS_KEKRecipientInfo;
 typedef struct CMS_PasswordRecipientInfo_st CMS_PasswordRecipientInfo;
 typedef struct CMS_OtherRecipientInfo_st CMS_OtherRecipientInfo;
 typedef struct CMS_ReceiptsFrom_st CMS_ReceiptsFrom;
+typedef struct CMS_CTX_st CMS_CTX;
+
+struct CMS_CTX_st {
+    OPENSSL_CTX *libctx;
+    char *propq;
+};
 
 struct CMS_ContentInfo_st {
     ASN1_OBJECT *contentType;
@@ -58,6 +64,7 @@ struct CMS_ContentInfo_st {
         /* Other types ... */
         void *otherData;
     } d;
+    CMS_CTX ctx;
 };
 
 DEFINE_STACK_OF(CMS_CertificateChoices)
@@ -92,6 +99,7 @@ struct CMS_SignerInfo_st {
     /* Digest and public key context for alternative parameters */
     EVP_MD_CTX *mctx;
     EVP_PKEY_CTX *pctx;
+    const CMS_CTX *cms_ctx;
 };
 
 struct CMS_SignerIdentifier_st {
@@ -152,6 +160,7 @@ struct CMS_KeyTransRecipientInfo_st {
     EVP_PKEY *pkey;
     /* Public key context for this operation */
     EVP_PKEY_CTX *pctx;
+    const CMS_CTX *cms_ctx;
 };
 
 struct CMS_KeyAgreeRecipientInfo_st {
@@ -164,6 +173,7 @@ struct CMS_KeyAgreeRecipientInfo_st {
     EVP_PKEY_CTX *pctx;
     /* Cipher context for CEK wrapping */
     EVP_CIPHER_CTX *ctx;
+    const CMS_CTX *cms_ctx;
 };
 
 struct CMS_OriginatorIdentifierOrKey_st {
@@ -209,6 +219,7 @@ struct CMS_KEKRecipientInfo_st {
     /* Extra info: symmetric key to use */
     unsigned char *key;
     size_t keylen;
+    const CMS_CTX *cms_ctx;
 };
 
 struct CMS_KEKIdentifier_st {
@@ -225,6 +236,7 @@ struct CMS_PasswordRecipientInfo_st {
     /* Extra info: password to use */
     unsigned char *pass;
     size_t passlen;
+    const CMS_CTX *cms_ctx;
 };
 
 struct CMS_OtherRecipientInfo_st {
@@ -363,27 +375,34 @@ DECLARE_ASN1_ALLOC_FUNCTIONS(CMS_IssuerAndSerialNumber)
 # define CMS_OIK_PUBKEY                  2
 
 BIO *cms_content_bio(CMS_ContentInfo *cms);
+const CMS_CTX *cms_get0_cmsctx(const CMS_ContentInfo *cms);
+OPENSSL_CTX *cms_ctx_get0_libctx(const CMS_CTX *ctx);
+const char *cms_ctx_get0_propq(const CMS_CTX *ctx);
+void cms_resolve_libctx(CMS_ContentInfo *ci);
 
-CMS_ContentInfo *cms_Data_create(void);
+CMS_ContentInfo *cms_Data_create(OPENSSL_CTX *ctx, const char *propq);
 
-CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md);
+CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md,
+                                         OPENSSL_CTX *libctx, const char *propq);
 BIO *cms_DigestedData_init_bio(const CMS_ContentInfo *cms);
 int cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, int verify);
 
 BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms);
 int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain);
 int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert,
-                              int type);
+                              int type, const CMS_CTX *ctx);
 int cms_SignerIdentifier_get0_signer_id(CMS_SignerIdentifier *sid,
                                         ASN1_OCTET_STRING **keyid,
                                         X509_NAME **issuer,
                                         ASN1_INTEGER **sno);
 int cms_SignerIdentifier_cert_cmp(CMS_SignerIdentifier *sid, X509 *cert);
 
-CMS_ContentInfo *cms_CompressedData_create(int comp_nid);
+CMS_ContentInfo *cms_CompressedData_create(int comp_nid, OPENSSL_CTX *libctx,
+                                           const char *propq);
 BIO *cms_CompressedData_init_bio(const CMS_ContentInfo *cms);
 
-BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm);
+BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
+                                  const CMS_CTX *ctx);
 int cms_DigestAlgorithm_find_ctx(EVP_MD_CTX *mctx, BIO *chain,
                                  X509_ALGOR *mdalg);
 
@@ -392,11 +411,13 @@ int cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert);
 int cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert);
 int cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert);
 
-BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec);
+BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
+                                   const CMS_CTX *ctx);
 BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms);
 int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
                               const EVP_CIPHER *cipher,
-                              const unsigned char *key, size_t keylen);
+                              const unsigned char *key, size_t keylen,
+                              const CMS_CTX *ctx);
 
 int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms);
 int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src);
@@ -405,21 +426,29 @@ ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si);
 BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
 int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
 CMS_EnvelopedData *cms_get0_enveloped(CMS_ContentInfo *cms);
+
+/* RecipientInfo routines */
 int cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd);
 int cms_pkey_get_ri_type(EVP_PKEY *pk);
 int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type);
+
+void cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms);
+
 /* KARI routines */
 int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
                                 EVP_PKEY *recipPubKey, X509 *originator,
-                                EVP_PKEY *originatorPrivKey, unsigned int flags);
+                                EVP_PKEY *originatorPrivKey, unsigned int flags,
+                                const CMS_CTX *ctx);
 int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
                                    CMS_RecipientInfo *ri);
 
 /* PWRI routines */
-int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
-                                 int en_de);
+int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
+                                 CMS_RecipientInfo *ri, int en_de);
 /* SignerInfo routines */
 int CMS_si_check_attributes(const CMS_SignerInfo *si);
+void cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms);
+
 
 /* ESS routines */
 int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain);
diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c
index 4726165234..1ca5a7ee07 100644
--- a/crypto/cms/cms_pwri.c
+++ b/crypto/cms/cms_pwri.c
@@ -51,6 +51,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
     X509_ALGOR *encalg = NULL;
     unsigned char iv[EVP_MAX_IV_LENGTH];
     int ivlen;
+    const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
 
     env = cms_get0_enveloped(cms);
     if (!env)
@@ -91,7 +92,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
     ivlen = EVP_CIPHER_CTX_iv_length(ctx);
 
     if (ivlen > 0) {
-        if (RAND_bytes(iv, ivlen) <= 0)
+        if (RAND_bytes_ex(cms_ctx->libctx, iv, ivlen) <= 0)
             goto err;
         if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
             CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
@@ -125,6 +126,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
     ri->type = CMS_RECIPINFO_PASS;
 
     pwri = ri->d.pwri;
+    pwri->cms_ctx = cms_ctx;
     /* Since this is overwritten, free up empty structure already there */
     X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
     pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
@@ -232,7 +234,7 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen,
 
 static int kek_wrap_key(unsigned char *out, size_t *outlen,
                         const unsigned char *in, size_t inlen,
-                        EVP_CIPHER_CTX *ctx)
+                        EVP_CIPHER_CTX *ctx, const CMS_CTX *cms_ctx)
 {
     size_t blocklen = EVP_CIPHER_CTX_block_size(ctx);
     size_t olen;
@@ -260,7 +262,8 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
         memcpy(out + 4, in, inlen);
         /* Add random padding to end */
         if (olen > inlen + 4
-            && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0)
+            && RAND_bytes_ex(cms_ctx->libctx, out + 4 + inlen,
+                             olen - 4 - inlen) <= 0)
             return 0;
         /* Encrypt twice */
         if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen)
@@ -275,17 +278,19 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
 
 /* Encrypt/Decrypt content key in PWRI recipient info */
 
-int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
-                                 int en_de)
+int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms,
+                                 CMS_RecipientInfo *ri, int en_de)
 {
     CMS_EncryptedContentInfo *ec;
     CMS_PasswordRecipientInfo *pwri;
     int r = 0;
     X509_ALGOR *algtmp, *kekalg = NULL;
     EVP_CIPHER_CTX *kekctx = NULL;
-    const EVP_CIPHER *kekcipher;
+    const char *name;
+    EVP_CIPHER *kekcipher;
     unsigned char *key = NULL;
     size_t keylen;
+    const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
 
     ec = cms->d.envelopedData->encryptedContentInfo;
 
@@ -312,17 +317,18 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *
         return 0;
     }
 
-    kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+    name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
+    kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, name, cms_ctx->propq);
 
-    if (!kekcipher) {
+    if (kekcipher == NULL) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, CMS_R_UNKNOWN_CIPHER);
-        return 0;
+        goto err;
     }
 
     kekctx = EVP_CIPHER_CTX_new();
     if (kekctx == NULL) {
         CMSerr(CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT, ERR_R_MALLOC_FAILURE);
-        return 0;
+        goto err;
     }
     /* Fixup cipher based on AlgorithmIdentifier to set IV etc */
     if (!EVP_CipherInit_ex(kekctx, kekcipher, NULL, NULL, NULL, en_de))
@@ -349,7 +355,7 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *
 
     if (en_de) {
 
-        if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx))
+        if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
             goto err;
 
         key = OPENSSL_malloc(keylen);
@@ -357,7 +363,7 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *
         if (key == NULL)
             goto err;
 
-        if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx))
+        if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx, cms_ctx))
             goto err;
         pwri->encryptedKey->data = key;
         pwri->encryptedKey->length = keylen;
@@ -384,7 +390,7 @@ int cms_RecipientInfo_pwri_crypt(const CMS_ContentInfo *cms, CMS_RecipientInfo *
     r = 1;
 
  err:
-
+    EVP_CIPHER_free(kekcipher);
     EVP_CIPHER_CTX_free(kekctx);
 
     if (!r)
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
index 54a836028f..9b345de553 100644
--- a/crypto/cms/cms_sd.c
+++ b/crypto/cms/cms_sd.c
@@ -67,6 +67,7 @@ int CMS_SignedData_init(CMS_ContentInfo *cms)
         return 0;
 }
 
+
 /* Check structures and fixup version numbers (if necessary) */
 
 static void cms_sd_set_version(CMS_SignedData *sd)
@@ -146,9 +147,11 @@ static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
     STACK_OF(CMS_SignerInfo) *sinfos;
     CMS_SignerInfo *sitmp;
     int i;
+
     sinfos = CMS_get0_SignerInfos(cms);
     for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
         ASN1_OCTET_STRING *messageDigest;
+
         sitmp = sk_CMS_SignerInfo_value(sinfos, i);
         if (sitmp == si)
             continue;
@@ -178,7 +181,8 @@ static int cms_copy_messageDigest(CMS_ContentInfo *cms, CMS_SignerInfo *si)
     return 0;
 }
 
-int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
+int cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type,
+                              const CMS_CTX *ctx)
 {
     switch (type) {
     case CMS_SIGNERINFO_ISSUER_SERIAL:
@@ -233,6 +237,7 @@ static int cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
 {
     EVP_PKEY *pkey = si->pkey;
     int i;
+
     if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
         return 1;
     i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
@@ -255,6 +260,8 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
     CMS_SignerInfo *si = NULL;
     X509_ALGOR *alg;
     int i, type;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+
     if (!X509_check_private_key(signer, pk)) {
         CMSerr(CMS_F_CMS_ADD1_SIGNER,
                CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
@@ -272,6 +279,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
     X509_up_ref(signer);
     EVP_PKEY_up_ref(pk);
 
+    si->cms_ctx = ctx;
     si->pkey = pk;
     si->signer = signer;
     si->mctx = EVP_MD_CTX_new();
@@ -292,7 +300,7 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
         si->version = 1;
     }
 
-    if (!cms_set1_SignerIdentifier(si->sid, signer, type))
+    if (!cms_set1_SignerIdentifier(si->sid, signer, type, ctx))
         goto err;
 
     if (md == NULL) {
@@ -311,6 +319,11 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
         goto err;
     }
 
+    if (md == NULL) {
+        CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET);
+        goto err;
+    }
+
     X509_ALGOR_set_md(si->digestAlgorithm, md);
 
     /* See if digest is present in digestAlgorithms */
@@ -395,15 +408,20 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
 
     if (flags & CMS_KEY_PARAM) {
         if (flags & CMS_NOATTR) {
-            si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+            si->pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, si->pkey,
+                                                  ctx->propq);
             if (si->pctx == NULL)
                 goto err;
             if (EVP_PKEY_sign_init(si->pctx) <= 0)
                 goto err;
             if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0)
                 goto err;
-        } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <= 0)
+        } else if (EVP_DigestSignInit_with_libctx(si->mctx, &si->pctx,
+                                                  EVP_MD_name(md),
+                                                  ctx->libctx, ctx->propq,
+                                                  pk) <= 0) {
             goto err;
+        }
     }
 
     if (!sd->signerInfos)
@@ -421,16 +439,31 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
 
 }
 
+void cms_SignerInfos_set_cmsctx(CMS_ContentInfo *cms)
+{
+    int i;
+    CMS_SignerInfo *si;
+    STACK_OF(CMS_SignerInfo) *sinfos = CMS_get0_SignerInfos(cms);
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
+
+    for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
+        si = sk_CMS_SignerInfo_value(sinfos, i);
+        if (si != NULL)
+            si->cms_ctx = ctx;
+    }
+}
+
 static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
 {
     ASN1_TIME *tt;
     int r = 0;
-    if (t)
+
+    if (t != NULL)
         tt = t;
     else
         tt = X509_gmtime_adj(NULL, 0);
 
-    if (!tt)
+    if (tt == NULL)
         goto merr;
 
     if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
@@ -438,10 +471,8 @@ static int cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
         goto merr;
 
     r = 1;
-
  merr:
-
-    if (!t)
+    if (t == NULL)
         ASN1_TIME_free(tt);
 
     if (!r)
@@ -463,11 +494,9 @@ EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
 
 STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms)
 {
-    CMS_SignedData *sd;
-    sd = cms_get0_signed(cms);
-    if (!sd)
-        return NULL;
-    return sd->signerInfos;
+    CMS_SignedData *sd = cms_get0_signed(cms);
+
+    return sd != NULL ? sd->signerInfos : NULL;
 }
 
 STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
@@ -476,13 +505,14 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
     STACK_OF(CMS_SignerInfo) *sinfos;
     CMS_SignerInfo *si;
     int i;
+
     sinfos = CMS_get0_SignerInfos(cms);
     for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
         si = sk_CMS_SignerInfo_value(sinfos, i);
-        if (si->signer) {
-            if (!signers) {
+        if (si->signer != NULL) {
+            if (signers == NULL) {
                 signers = sk_X509_new_null();
-                if (!signers)
+                if (signers == NULL)
                     return NULL;
             }
             if (!sk_X509_push(signers, si->signer)) {
@@ -496,7 +526,7 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms)
 
 void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
 {
-    if (signer) {
+    if (signer != NULL) {
         X509_up_ref(signer);
         EVP_PKEY_free(si->pkey);
         si->pkey = X509_get_pubkey(signer);
@@ -527,13 +557,14 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
     X509 *x;
     int i, j;
     int ret = 0;
+
     sd = cms_get0_signed(cms);
-    if (!sd)
+    if (sd == NULL)
         return -1;
     certs = sd->certificates;
     for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
         si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
-        if (si->signer)
+        if (si->signer != NULL)
             continue;
 
         for (j = 0; j < sk_X509_num(scerts); j++) {
@@ -545,7 +576,7 @@ int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
             }
         }
 
-        if (si->signer || (flags & CMS_NOINTERN))
+        if (si->signer != NULL || (flags & CMS_NOINTERN))
             continue;
 
         for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
@@ -567,13 +598,13 @@ void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk,
                               X509 **signer, X509_ALGOR **pdig,
                               X509_ALGOR **psig)
 {
-    if (pk)
+    if (pk != NULL)
         *pk = si->pkey;
-    if (signer)
+    if (signer != NULL)
         *signer = si->signer;
-    if (pdig)
+    if (pdig != NULL)
         *pdig = si->digestAlgorithm;
-    if (psig)
+    if (psig != NULL)
         *psig = si->signatureAlgorithm;
 }
 
@@ -588,13 +619,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
     EVP_MD_CTX *mctx = EVP_MD_CTX_new();
     int r = 0;
     EVP_PKEY_CTX *pctx = NULL;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
 
     if (mctx == NULL) {
         CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
-    if (!si->pkey) {
+    if (si->pkey == NULL) {
         CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_NO_PRIVATE_KEY);
         goto err;
     }
@@ -612,6 +644,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
     if (CMS_signed_get_attr_count(si) >= 0) {
         unsigned char md[EVP_MAX_MD_SIZE];
         unsigned int mdlen;
+
         if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
             goto err;
         if (!CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
@@ -628,6 +661,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
         size_t siglen;
         unsigned char md[EVP_MAX_MD_SIZE];
         unsigned int mdlen;
+
         pctx = si->pctx;
         if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
             goto err;
@@ -645,12 +679,14 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
     } else {
         unsigned char *sig;
         unsigned int siglen;
+
         sig = OPENSSL_malloc(EVP_PKEY_size(si->pkey));
         if (sig == NULL) {
             CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, ERR_R_MALLOC_FAILURE);
             goto err;
         }
-        if (!EVP_SignFinal(mctx, sig, &siglen, si->pkey)) {
+        if (!EVP_SignFinal_with_libctx(mctx, sig, &siglen, si->pkey,
+                                       ctx->libctx, ctx->propq)) {
             CMSerr(CMS_F_CMS_SIGNERINFO_CONTENT_SIGN, CMS_R_SIGNFINAL_ERROR);
             OPENSSL_free(sig);
             goto err;
@@ -672,6 +708,7 @@ int cms_SignedData_final(CMS_ContentInfo *cms, BIO *chain)
     STACK_OF(CMS_SignerInfo) *sinfos;
     CMS_SignerInfo *si;
     int i;
+
     sinfos = CMS_get0_SignerInfos(cms);
     for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
         si = sk_CMS_SignerInfo_value(sinfos, i);
@@ -689,10 +726,10 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
     unsigned char *abuf = NULL;
     int alen;
     size_t siglen;
-    const EVP_MD *md = NULL;
+    const CMS_CTX *ctx = si->cms_ctx;
+    const char *md_name = OBJ_nid2sn(OBJ_obj2nid(si->digestAlgorithm->algorithm));
 
-    md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
-    if (md == NULL)
+    if (md_name == NULL)
         return 0;
 
     if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
@@ -707,7 +744,9 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
         pctx = si->pctx;
     else {
         EVP_MD_CTX_reset(mctx);
-        if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
+        if (EVP_DigestSignInit_with_libctx(mctx, &pctx,
+                                           md_name, ctx->libctx, ctx->propq,
+                                           si->pkey) <= 0)
             goto err;
         si->pctx = pctx;
     }
@@ -780,9 +819,11 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
     EVP_MD_CTX *mctx = NULL;
     unsigned char *abuf = NULL;
     int alen, r = -1;
-    const EVP_MD *md = NULL;
+    const char *name;
+    EVP_MD *md = NULL;
+    const CMS_CTX *ctx = si->cms_ctx;
 
-    if (!si->pkey) {
+    if (si->pkey == NULL) {
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_NO_PUBLIC_KEY);
         return -1;
     }
@@ -790,15 +831,18 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
     if (!CMS_si_check_attributes(si))
         return -1;
 
-    md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
+    name = OBJ_nid2sn(OBJ_obj2nid(si->digestAlgorithm->algorithm));
+    md = EVP_MD_fetch(ctx->libctx, name, ctx->propq);
     if (md == NULL)
         return -1;
     if (si->mctx == NULL && (si->mctx = EVP_MD_CTX_new()) == NULL) {
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, ERR_R_MALLOC_FAILURE);
-        return -1;
+        goto err;
     }
     mctx = si->mctx;
-    if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0)
+    if (EVP_DigestVerifyInit_with_libctx(mctx, &si->pctx,
+                                         EVP_MD_name(md), ctx->libctx, NULL,
+                                         si->pkey) <= 0)
         goto err;
 
     if (!cms_sd_asn1_ctrl(si, 1))
@@ -819,6 +863,7 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
     if (r <= 0)
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY, CMS_R_VERIFICATION_FAILURE);
  err:
+    EVP_MD_free(md);
     EVP_MD_CTX_reset(mctx);
     return r;
 }
@@ -830,19 +875,21 @@ BIO *cms_SignedData_init_bio(CMS_ContentInfo *cms)
     int i;
     CMS_SignedData *sd;
     BIO *chain = NULL;
+
     sd = cms_get0_signed(cms);
-    if (!sd)
+    if (sd == NULL)
         return NULL;
     if (cms->d.signedData->encapContentInfo->partial)
         cms_sd_set_version(sd);
     for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
         X509_ALGOR *digestAlgorithm;
         BIO *mdbio;
+
         digestAlgorithm = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
-        mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm);
-        if (!mdbio)
+        mdbio = cms_DigestAlgorithm_init_bio(digestAlgorithm, cms_get0_cmsctx(cms));
+        if (mdbio == NULL)
             goto err;
-        if (chain)
+        if (chain != NULL)
             BIO_push(chain, mdbio);
         else
             chain = mdbio;
@@ -871,7 +918,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
         os = CMS_signed_get0_data_by_OBJ(si,
                                          OBJ_nid2obj(NID_pkcs9_messageDigest),
                                          -3, V_ASN1_OCTET_STRING);
-        if (!os) {
+        if (os == NULL) {
             CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
                    CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
             goto err;
@@ -889,7 +936,7 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
 
     /* If messageDigest found compare it */
 
-    if (os) {
+    if (os != NULL) {
         if (mlen != (unsigned int)os->length) {
             CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT,
                    CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
@@ -904,7 +951,9 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
             r = 1;
     } else {
         const EVP_MD *md = EVP_MD_CTX_md(mctx);
-        pkctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+        const CMS_CTX *ctx = si->cms_ctx;
+
+        pkctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, si->pkey, ctx->propq);
         if (pkctx == NULL)
             goto err;
         if (EVP_PKEY_verify_init(pkctx) <= 0)
@@ -934,6 +983,7 @@ int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs)
 {
     unsigned char *smder = NULL;
     int smderlen, r;
+
     smderlen = i2d_X509_ALGORS(algs, &smder);
     if (smderlen <= 0)
         return 0;
@@ -948,6 +998,7 @@ int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs,
 {
     X509_ALGOR *alg;
     ASN1_INTEGER *key = NULL;
+
     if (keysize > 0) {
         key = ASN1_INTEGER_new();
         if (key == NULL || !ASN1_INTEGER_set(key, keysize)) {
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index a83edce0f7..11c9fed1a8 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -25,6 +25,7 @@ DEFINE_STACK_OF(CMS_RecipientInfo)
 static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
 {
     BIO *rbio;
+
     if (out == NULL)
         rbio = BIO_new(BIO_s_null());
     else if (flags & CMS_TEXT) {
@@ -61,7 +62,7 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
             break;
         }
 
-        if (tmpout && (BIO_write(tmpout, buf, i) != i))
+        if (tmpout != NULL && (BIO_write(tmpout, buf, i) != i))
             goto err;
     }
 
@@ -73,7 +74,6 @@ static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
     }
 
     r = 1;
-
  err:
     if (tmpout != out)
         BIO_free(tmpout);
@@ -96,62 +96,73 @@ static void do_free_upto(BIO *f, BIO *upto)
 {
     if (upto != NULL) {
         BIO *tbio;
+
         do {
             tbio = BIO_pop(f);
             BIO_free(f);
             f = tbio;
         } while (f != NULL && f != upto);
-    } else
+    } else {
         BIO_free_all(f);
+    }
 }
 
 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags)
 {
     BIO *cont;
     int r;
+
     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_data) {
         CMSerr(CMS_F_CMS_DATA, CMS_R_TYPE_NOT_DATA);
         return 0;
     }
     cont = CMS_dataInit(cms, NULL);
-    if (!cont)
+    if (cont == NULL)
         return 0;
     r = cms_copy_content(out, cont, flags);
     BIO_free_all(cont);
     return r;
 }
 
-CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
+CMS_ContentInfo *CMS_data_create_with_libctx(BIO *in, unsigned int flags,
+                                             OPENSSL_CTX *libctx,
+                                             const char *propq)
 {
-    CMS_ContentInfo *cms;
-    cms = cms_Data_create();
-    if (!cms)
+    CMS_ContentInfo *cms = cms_Data_create(libctx, propq);
+
+    if (cms == NULL)
         return NULL;
 
     if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
         return cms;
 
     CMS_ContentInfo_free(cms);
-
     return NULL;
 }
 
+CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags)
+{
+    return CMS_data_create_with_libctx(in, flags, NULL, NULL);
+}
+
 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
                       unsigned int flags)
 {
     BIO *cont;
     int r;
+
     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_digest) {
         CMSerr(CMS_F_CMS_DIGEST_VERIFY, CMS_R_TYPE_NOT_DIGESTED_DATA);
         return 0;
     }
 
-    if (!dcont && !check_content(cms))
+    if (dcont == NULL && !check_content(cms))
         return 0;
 
     cont = CMS_dataInit(cms, dcont);
-    if (!cont)
+    if (cont == NULL)
         return 0;
+
     r = cms_copy_content(out, cont, flags);
     if (r)
         r = cms_DigestedData_do_final(cms, cont, 1);
@@ -159,14 +170,18 @@ int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
     return r;
 }
 
-CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
-                                   unsigned int flags)
+CMS_ContentInfo *CMS_digest_create_with_libctx(BIO *in,
+                                               const EVP_MD *md,
+                                               unsigned int flags,
+                                               OPENSSL_CTX *ctx,
+                                               const char *propq)
 {
     CMS_ContentInfo *cms;
-    if (!md)
+
+    if (md == NULL)
         md = EVP_sha1();
-    cms = cms_DigestedData_create(md);
-    if (!cms)
+    cms = cms_DigestedData_create(md, ctx, propq);
+    if (cms == NULL)
         return NULL;
 
     if (!(flags & CMS_DETACHED))
@@ -179,41 +194,53 @@ CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
     return NULL;
 }
 
+CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+                                   unsigned int flags)
+{
+    return CMS_digest_create_with_libctx(in, md, flags, NULL, NULL);
+}
+
 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
                               const unsigned char *key, size_t keylen,
                               BIO *dcont, BIO *out, unsigned int flags)
 {
     BIO *cont;
     int r;
+
     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_encrypted) {
         CMSerr(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT,
                CMS_R_TYPE_NOT_ENCRYPTED_DATA);
         return 0;
     }
 
-    if (!dcont && !check_content(cms))
+    if (dcont == NULL && !check_content(cms))
         return 0;
 
     if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
         return 0;
     cont = CMS_dataInit(cms, dcont);
-    if (!cont)
+    if (cont == NULL)
         return 0;
     r = cms_copy_content(out, cont, flags);
     do_free_upto(cont, dcont);
     return r;
 }
 
-CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
-                                           const unsigned char *key,
-                                           size_t keylen, unsigned int flags)
+CMS_ContentInfo *CMS_EncryptedData_encrypt_with_libctx(BIO *in,
+                                                       const EVP_CIPHER *cipher,
+                                                       const unsigned char *key,
+                                                       size_t keylen,
+                                                       unsigned int flags,
+                                                       OPENSSL_CTX *libctx,
+                                                       const char *propq)
 {
     CMS_ContentInfo *cms;
-    if (!cipher) {
-        CMSerr(CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT, CMS_R_NO_CIPHER);
+
+    if (cipher == NULL) {
+        CMSerr(0, CMS_R_NO_CIPHER);
         return NULL;
     }
-    cms = CMS_ContentInfo_new();
+    cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
     if (cms == NULL)
         return NULL;
     if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
@@ -230,16 +257,26 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
     return NULL;
 }
 
+CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+                                           const unsigned char *key,
+                                           size_t keylen, unsigned int flags)
+{
+    return CMS_EncryptedData_encrypt_with_libctx(in, cipher, key, keylen, flags,
+                                                 NULL, NULL);
+}
+
 static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
                                       X509_STORE *store,
                                       STACK_OF(X509) *certs,
                                       STACK_OF(X509_CRL) *crls,
-                                      STACK_OF(X509) **chain)
+                                      STACK_OF(X509) **chain,
+                                      const CMS_CTX *cms_ctx)
 {
-    X509_STORE_CTX *ctx = X509_STORE_CTX_new();
+    X509_STORE_CTX *ctx;
     X509 *signer;
     int i, j, r = 0;
 
+    ctx = X509_STORE_CTX_new_with_libctx(cms_ctx->libctx, cms_ctx->propq);
     if (ctx == NULL) {
         CMSerr(CMS_F_CMS_SIGNERINFO_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
         goto err;
@@ -250,7 +287,7 @@ static int cms_signerinfo_verify_cert(CMS_SignerInfo *si,
         goto err;
     }
     X509_STORE_CTX_set_default(ctx, "smime_sign");
-    if (crls)
+    if (crls != NULL)
         X509_STORE_CTX_set0_crls(ctx, crls);
 
     i = X509_verify_cert(ctx);
@@ -285,11 +322,13 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
     int i, scount = 0, ret = 0;
     BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
     int cadesVerify = (flags & CMS_CADES) != 0;
+    const CMS_CTX *ctx = cms_get0_cmsctx(cms);
 
-    if (!dcont && !check_content(cms))
+    if (dcont == NULL && !check_content(cms))
         return 0;
-    if (dcont && !(flags & CMS_BINARY)) {
+    if (dcont != NULL && !(flags & CMS_BINARY)) {
         const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
+
         if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
             flags |= CMS_ASCIICRLF;
     }
@@ -337,7 +376,8 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
             si = sk_CMS_SignerInfo_value(sinfos, i);
 
             if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls,
-                                            si_chains ? &si_chains[i] : NULL))
+                                            si_chains ? &si_chains[i] : NULL,
+                                            ctx))
                 goto err;
         }
     }
@@ -367,17 +407,19 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
      * reading from a read write memory BIO when signatures are calculated.
      */
 
-    if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
+    if (dcont != NULL && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
         char *ptr;
         long len;
+
         len = BIO_get_mem_data(dcont, &ptr);
         tmpin = BIO_new_mem_buf(ptr, len);
         if (tmpin == NULL) {
             CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
             goto err2;
         }
-    } else
+    } else {
         tmpin = dcont;
+    }
     /*
      * If not binary mode and detached generate digests by *writing* through
      * the BIO. That makes it possible to canonicalise the input.
@@ -388,12 +430,12 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
          * included content doesn't override detached content.
          */
         tmpout = cms_get_text_bio(out, flags);
-        if (!tmpout) {
+        if (tmpout == NULL) {
             CMSerr(CMS_F_CMS_VERIFY, ERR_R_MALLOC_FAILURE);
             goto err;
         }
         cmsbio = CMS_dataInit(cms, tmpout);
-        if (!cmsbio)
+        if (cmsbio == NULL)
             goto err;
         /*
          * Don't use SMIME_TEXT for verify: it adds headers and we want to
@@ -409,7 +451,7 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
         }
     } else {
         cmsbio = CMS_dataInit(cms, tmpin);
-        if (!cmsbio)
+        if (cmsbio == NULL)
             goto err;
 
         if (!cms_copy_content(out, cmsbio, flags))
@@ -427,7 +469,6 @@ int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs,
     }
 
     ret = 1;
-
  err:
     if (!(flags & SMIME_BINARY) && dcont) {
         do_free_upto(cmsbio, tmpout);
@@ -460,6 +501,7 @@ int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
                        X509_STORE *store, unsigned int flags)
 {
     int r;
+
     flags &= ~(CMS_DETACHED | CMS_TEXT);
     r = CMS_verify(rcms, certs, store, NULL, NULL, flags);
     if (r <= 0)
@@ -467,14 +509,15 @@ int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
     return cms_Receipt_verify(rcms, ocms);
 }
 
-CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
-                          STACK_OF(X509) *certs, BIO *data,
-                          unsigned int flags)
+CMS_ContentInfo *CMS_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                                      STACK_OF(X509) *certs, BIO *data,
+                                      unsigned int flags,
+                                      OPENSSL_CTX *libctx, const char *propq)
 {
     CMS_ContentInfo *cms;
     int i;
 
-    cms = CMS_ContentInfo_new();
+    cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
     if (cms == NULL || !CMS_SignedData_init(cms))
         goto merr;
     if (flags & CMS_ASCIICRLF
@@ -482,13 +525,14 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
                                   OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
         goto err;
 
-    if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
-        CMSerr(CMS_F_CMS_SIGN, CMS_R_ADD_SIGNER_ERROR);
+    if (pkey != NULL && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
+        CMSerr(0, CMS_R_ADD_SIGNER_ERROR);
         goto err;
     }
 
     for (i = 0; i < sk_X509_num(certs); i++) {
         X509 *x = sk_X509_value(certs, i);
+
         if (!CMS_add1_cert(cms, x))
             goto merr;
     }
@@ -503,13 +547,19 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
         goto err;
 
  merr:
-    CMSerr(CMS_F_CMS_SIGN, ERR_R_MALLOC_FAILURE);
+    CMSerr(0, ERR_R_MALLOC_FAILURE);
 
  err:
     CMS_ContentInfo_free(cms);
     return NULL;
 }
 
+CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                          BIO *data, unsigned int flags)
+{
+    return CMS_sign_with_libctx(signcert, pkey, certs, data, flags, NULL, NULL);
+}
+
 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
                                   X509 *signcert, EVP_PKEY *pkey,
                                   STACK_OF(X509) *certs, unsigned int flags)
@@ -519,6 +569,7 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
     ASN1_OCTET_STRING **pos, *os;
     BIO *rct_cont = NULL;
     int r = 0;
+    const CMS_CTX *ctx = si->cms_ctx;
 
     flags &= ~(CMS_STREAM | CMS_TEXT);
     /* Not really detached but avoids content being allocated */
@@ -530,8 +581,9 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 
     /* Initialize signed data */
 
-    cms = CMS_sign(NULL, NULL, certs, NULL, flags);
-    if (!cms)
+    cms = CMS_sign_with_libctx(NULL, NULL, certs, NULL, flags,
+                               ctx->libctx, ctx->propq);
+    if (cms == NULL)
         goto err;
 
     /* Set inner content type to signed receipt */
@@ -545,13 +597,12 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
     }
 
     os = cms_encode_Receipt(si);
-
-    if (!os)
+    if (os == NULL)
         goto err;
 
     /* Set content to digest */
     rct_cont = BIO_new_mem_buf(os->data, os->length);
-    if (!rct_cont)
+    if (rct_cont == NULL)
         goto err;
 
     /* Add msgSigDigest attribute */
@@ -578,19 +629,22 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 
 }
 
-CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
-                             const EVP_CIPHER *cipher, unsigned int flags)
+CMS_ContentInfo *CMS_encrypt_with_libctx(STACK_OF(X509) *certs,
+                                         BIO *data, const EVP_CIPHER *cipher,
+                                         unsigned int flags,
+                                         OPENSSL_CTX *libctx, const char *propq)
 {
     CMS_ContentInfo *cms;
     int i;
     X509 *recip;
-    cms = CMS_EnvelopedData_create(cipher);
-    if (!cms)
+
+    cms = CMS_EnvelopedData_create_with_libctx(cipher, libctx, propq);
+    if (cms == NULL)
         goto merr;
     for (i = 0; i < sk_X509_num(certs); i++) {
         recip = sk_X509_value(certs, i);
         if (!CMS_add1_recipient_cert(cms, recip, flags)) {
-            CMSerr(CMS_F_CMS_ENCRYPT, CMS_R_RECIPIENT_ERROR);
+            CMSerr(0, CMS_R_RECIPIENT_ERROR);
             goto err;
         }
     }
@@ -605,13 +659,20 @@ CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
         goto err;
 
  merr:
-    CMSerr(CMS_F_CMS_ENCRYPT, ERR_R_MALLOC_FAILURE);
+    CMSerr(0, ERR_R_MALLOC_FAILURE);
  err:
     CMS_ContentInfo_free(cms);
     return NULL;
 }
 
-static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data,
+                             const EVP_CIPHER *cipher, unsigned int flags)
+{
+    return CMS_encrypt_with_libctx(certs, data, cipher, flags, NULL, NULL);
+}
+
+static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms,
+                                       CMS_RecipientInfo *ri,
                                        EVP_PKEY *pk, X509 *cert, X509 *peer)
 {
     int i;
@@ -621,6 +682,7 @@ static int cms_kari_set1_pkey_and_peer(CMS_ContentInfo *cms, CMS_RecipientInfo *
     reks = CMS_RecipientInfo_kari_get0_reks(ri);
     for (i = 0; i < sk_CMS_RecipientEncryptedKey_num(reks); i++) {
         int rv;
+
         rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
         if (cert != NULL && CMS_RecipientEncryptedKey_cert_cmp(rek, cert))
             continue;
@@ -639,14 +701,16 @@ int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
      return CMS_decrypt_set1_pkey_and_peer(cms, pk, cert, NULL);
 }
 
-int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, X509 *peer)
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
+                                   X509 *cert, X509 *peer)
 {
     STACK_OF(CMS_RecipientInfo) *ris;
     CMS_RecipientInfo *ri;
     int i, r, cms_pkey_ri_type;
     int debug = 0, match_ri = 0;
+
     ris = CMS_get0_RecipientInfos(cms);
-    if (ris)
+    if (ris != NULL)
         debug = cms->d.envelopedData->encryptedContentInfo->debug;
 
     cms_pkey_ri_type = cms_pkey_get_ri_type(pk);
@@ -675,12 +739,12 @@ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cer
          * If we have a cert try matching RecipientInfo otherwise try them
          * all.
          */
-        else if (!cert || !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
+        else if (cert == NULL|| !CMS_RecipientInfo_ktri_cert_cmp(ri, cert)) {
             EVP_PKEY_up_ref(pk);
             CMS_RecipientInfo_set0_pkey(ri, pk);
             r = CMS_RecipientInfo_decrypt(cms, ri);
             CMS_RecipientInfo_set0_pkey(ri, NULL);
-            if (cert) {
+            if (cert != NULL) {
                 /*
                  * If not debugging clear any error and return success to
                  * avoid leaking of information useful to MMA
@@ -704,7 +768,10 @@ int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cer
         }
     }
     /* If no cert, key transport and not debugging always return success */
-    if (cert == NULL && cms_pkey_ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
+    if (cert == NULL
+        && cms_pkey_ri_type == CMS_RECIPINFO_TRANS
+        && match_ri
+        && !debug) {
         ERR_clear_error();
         return 1;
     }
@@ -721,6 +788,7 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
     STACK_OF(CMS_RecipientInfo) *ris;
     CMS_RecipientInfo *ri;
     int i, r;
+
     ris = CMS_get0_RecipientInfos(cms);
     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
         ri = sk_CMS_RecipientInfo_value(ris, i);
@@ -731,13 +799,13 @@ int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
          * If we have an id try matching RecipientInfo otherwise try them
          * all.
          */
-        if (!id || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
+        if (id == NULL || (CMS_RecipientInfo_kekri_id_cmp(ri, id, idlen) == 0)) {
             CMS_RecipientInfo_set0_key(ri, key, keylen);
             r = CMS_RecipientInfo_decrypt(cms, ri);
             CMS_RecipientInfo_set0_key(ri, NULL, 0);
             if (r > 0)
                 return 1;
-            if (id) {
+            if (id != NULL) {
                 CMSerr(CMS_F_CMS_DECRYPT_SET1_KEY, CMS_R_DECRYPT_ERROR);
                 return 0;
             }
@@ -756,6 +824,7 @@ int CMS_decrypt_set1_password(CMS_ContentInfo *cms,
     STACK_OF(CMS_RecipientInfo) *ris;
     CMS_RecipientInfo *ri;
     int i, r;
+
     ris = CMS_get0_RecipientInfos(cms);
     for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
         ri = sk_CMS_RecipientInfo_value(ris, i);
@@ -783,13 +852,13 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
         CMSerr(CMS_F_CMS_DECRYPT, CMS_R_TYPE_NOT_ENVELOPED_DATA);
         return 0;
     }
-    if (!dcont && !check_content(cms))
+    if (dcont == NULL && !check_content(cms))
         return 0;
     if (flags & CMS_DEBUG_DECRYPT)
         cms->d.envelopedData->encryptedContentInfo->debug = 1;
     else
         cms->d.envelopedData->encryptedContentInfo->debug = 0;
-    if (!cert)
+    if (cert == NULL)
         cms->d.envelopedData->encryptedContentInfo->havenocert = 1;
     else
         cms->d.envelopedData->encryptedContentInfo->havenocert = 0;
@@ -815,7 +884,7 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
         return 0;
     }
 
-    SMIME_crlf_copy(data, cmsbio, flags);
+    ret = SMIME_crlf_copy(data, cmsbio, flags);
 
     (void)BIO_flush(cmsbio);
 
@@ -823,10 +892,7 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
         CMSerr(CMS_F_CMS_FINAL, CMS_R_CMS_DATAFINAL_ERROR);
         goto err;
     }
-
-    ret = 1;
-
- err:
+err:
     do_free_upto(cmsbio, dcont);
 
     return ret;
@@ -840,16 +906,17 @@ int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 {
     BIO *cont;
     int r;
+
     if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_id_smime_ct_compressedData) {
         CMSerr(CMS_F_CMS_UNCOMPRESS, CMS_R_TYPE_NOT_COMPRESSED_DATA);
         return 0;
     }
 
-    if (!dcont && !check_content(cms))
+    if (dcont == NULL && !check_content(cms))
         return 0;
 
     cont = CMS_dataInit(cms, dcont);
-    if (!cont)
+    if (cont == NULL)
         return 0;
     r = cms_copy_content(out, cont, flags);
     do_free_upto(cont, dcont);
@@ -859,10 +926,11 @@ int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
 CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags)
 {
     CMS_ContentInfo *cms;
+
     if (comp_nid <= 0)
         comp_nid = NID_zlib_compression;
-    cms = cms_CompressedData_create(comp_nid);
-    if (!cms)
+    cms = cms_CompressedData_create(comp_nid, NULL, NULL);
+    if (cms == NULL)
         return NULL;
 
     if (!(flags & CMS_DETACHED))
diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c
index f270e4378a..b05e77b8a1 100644
--- a/crypto/ct/ct_vfy.c
+++ b/crypto/ct/ct_vfy.c
@@ -122,8 +122,9 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
     if (ctx == NULL)
         goto end;
 
-    if (!EVP_DigestVerifyInit_ex(ctx, NULL, "SHA2-256", sctx->propq, sctx->pkey,
-                                 sctx->libctx))
+    if (!EVP_DigestVerifyInit_with_libctx(ctx, NULL,
+                                          "SHA2-256", sctx->libctx, sctx->propq,
+                                          sctx->pkey))
         goto end;
 
     if (!sct_ctx_update(ctx, sctx, sct))
diff --git a/crypto/ec/build.info b/crypto/ec/build.info
index 8e4a6a9f4b..496a932e4c 100644
--- a/crypto/ec/build.info
+++ b/crypto/ec/build.info
@@ -50,14 +50,14 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
         ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
         curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
         curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
-        $ECASM ec_backend.c ecx_backend.c
+        $ECASM ec_backend.c ecx_backend.c ecdh_kdf.c
 
 IF[{- !$disabled{'ec_nistp_64_gcc_128'} -}]
   $COMMON=$COMMON ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c
 ENDIF
 
 SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \
-                        ec_err.c ecdh_kdf.c eck_prn.c ec_ctrl.c
+                        ec_err.c eck_prn.c ec_ctrl.c
 SOURCE[../../providers/libfips.a]=$COMMON
 
 # Implementations are now spread across several libraries, so the defines
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 8a33b3232c..f8251a6de2 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -35,6 +35,7 @@ static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
 {
     const EC_GROUP *group;
     int nid;
+
     if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
         ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
         return 0;
@@ -192,6 +193,7 @@ static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
     const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
     const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
         *pb = EC_KEY_get0_public_key(b->pkey.ec);
+
     if (group == NULL || pa == NULL || pb == NULL)
         return -2;
     r = EC_POINT_cmp(group, pa, pb, NULL);
@@ -299,6 +301,7 @@ static int ec_bits(const EVP_PKEY *pkey)
 static int ec_security_bits(const EVP_PKEY *pkey)
 {
     int ecbits = ec_bits(pkey);
+
     if (ecbits >= 512)
         return 256;
     if (ecbits >= 384)
@@ -343,6 +346,7 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
 {
     const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
         *group_b = EC_KEY_get0_group(b->pkey.ec);
+
     if (group_a == NULL || group_b == NULL)
         return -2;
     if (EC_GROUP_cmp(group_a, group_b, NULL))
@@ -486,6 +490,7 @@ static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
         if (arg1 == 0) {
             int snid, hnid;
             X509_ALGOR *alg1, *alg2;
+
             PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
             if (alg1 == NULL || alg1->algorithm == NULL)
                 return -1;
@@ -626,7 +631,8 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl)
         if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
             return 0;
 
-        if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, 0))
+        if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME,
+                                             curve_name, 0))
             return 0;
     }
 
@@ -878,6 +884,7 @@ static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
     EC_KEY *ecpeer = NULL;
     const unsigned char *p;
     int plen;
+
     X509_ALGOR_get0(&aoid, &atype, &aval, alg);
     if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
         goto err;
@@ -961,8 +968,9 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
     const unsigned char *p;
     unsigned char *der = NULL;
     int plen, keylen;
-    const EVP_CIPHER *kekcipher;
+    EVP_CIPHER *kekcipher = NULL;
     EVP_CIPHER_CTX *kekctx;
+    const char *name;
 
     if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
         return 0;
@@ -978,13 +986,14 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
     p = alg->parameter->value.sequence->data;
     plen = alg->parameter->value.sequence->length;
     kekalg = d2i_X509_ALGOR(NULL, &p, plen);
-    if (!kekalg)
+    if (kekalg == NULL)
         goto err;
     kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
-    if (!kekctx)
+    if (kekctx == NULL)
         goto err;
-    kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
-    if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
+    name = OBJ_nid2sn(OBJ_obj2nid(kekalg->algorithm));
+    kekcipher = EVP_CIPHER_fetch(pctx->libctx, name, NULL);
+    if (kekcipher == NULL || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
         goto err;
     if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
         goto err;
@@ -1006,6 +1015,7 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
 
     rv = 1;
  err:
+    EVP_CIPHER_free(kekcipher);
     X509_ALGOR_free(kekalg);
     OPENSSL_free(der);
     return rv;
@@ -1014,13 +1024,15 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
 static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
 {
     EVP_PKEY_CTX *pctx;
+
     pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (!pctx)
+    if (pctx == NULL)
         return 0;
     /* See if we need to set peer key */
     if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
         X509_ALGOR *alg;
         ASN1_BIT_STRING *pubkey;
+
         if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
                                                  NULL, NULL, NULL))
             return 0;
@@ -1055,8 +1067,9 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
     int rv = 0;
     int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
     const EVP_MD *kdf_md;
+
     pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
-    if (!pctx)
+    if (pctx == NULL)
         return 0;
     /* Get ephemeral key */
     pkey = EVP_PKEY_CTX_get0_pkey(pctx);
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 58cd160502..7476efd9bc 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -295,8 +295,9 @@ int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
          * Prior to OpenSSL 3.0 EVP_DigestSignUpdate() and
          * EVP_DigestVerifyUpdate() were just macros for EVP_DigestUpdate().
          * Some code calls EVP_DigestUpdate() directly even when initialised
-         * with EVP_DigestSignInit_ex() or EVP_DigestVerifyInit_ex(), so we
-         * detect that and redirect to the correct EVP_Digest*Update() function
+         * with EVP_DigestSignInit_with_libctx() or
+         * EVP_DigestVerifyInit_with_libctx(), so we detect that and redirect to
+         * the correct EVP_Digest*Update() function
          */
         if (ctx->pctx->operation == EVP_PKEY_OP_SIGNCTX)
             return EVP_DigestSignUpdate(ctx, data, count);
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 2f00f9a13b..74d4afdac4 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -1180,6 +1180,20 @@ const OSSL_PARAM *EVP_CIPHER_gettable_ctx_params(const EVP_CIPHER *cipher)
     return NULL;
 }
 
+#ifndef FIPS_MODULE
+static OPENSSL_CTX *EVP_CIPHER_CTX_get_libctx(EVP_CIPHER_CTX *ctx)
+{
+    const EVP_CIPHER *cipher = ctx->cipher;
+    const OSSL_PROVIDER *prov;
+
+    if (cipher == NULL)
+        return NULL;
+
+    prov = EVP_CIPHER_provider(cipher);
+    return ossl_provider_library_context(prov);
+}
+#endif
+
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 {
     if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
@@ -1190,9 +1204,10 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 #else
     {
         int kl;
+        OPENSSL_CTX *libctx = EVP_CIPHER_CTX_get_libctx(ctx);
 
         kl = EVP_CIPHER_CTX_key_length(ctx);
-        if (kl <= 0 || RAND_priv_bytes(key, kl) <= 0)
+        if (kl <= 0 || RAND_priv_bytes_ex(libctx, key, kl) <= 0)
             return 0;
         return 1;
     }
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
index 8d37f19d6c..04ac121e25 100644
--- a/crypto/evp/m_sigver.c
+++ b/crypto/evp/m_sigver.c
@@ -38,8 +38,8 @@ static const char *canon_mdname(const char *mdname)
 
 static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                           const EVP_MD *type, const char *mdname,
-                          const char *props, ENGINE *e, EVP_PKEY *pkey,
-                          OPENSSL_CTX *libctx, int ver)
+                          OPENSSL_CTX *libctx, const char *props,
+                          ENGINE *e, EVP_PKEY *pkey, int ver)
 {
     EVP_PKEY_CTX *locpctx = NULL;
     EVP_SIGNATURE *signature = NULL;
@@ -285,31 +285,32 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
     return 1;
 }
 
-int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                          const char *mdname, const char *props, EVP_PKEY *pkey,
-                          OPENSSL_CTX *libctx)
+int EVP_DigestSignInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                   const char *mdname,
+                                   OPENSSL_CTX *libctx, const char *props,
+                                   EVP_PKEY *pkey)
 {
-    return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx,
-                          0);
+    return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 0);
 }
 
 int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                        const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
 {
-    return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 0);
+    return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 0);
 }
 
-int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                            const char *mdname, const char *props,
-                            EVP_PKEY *pkey, OPENSSL_CTX *libctx)
+int EVP_DigestVerifyInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                     const char *mdname,
+                                     OPENSSL_CTX *libctx, const char *props,
+                                     EVP_PKEY *pkey)
 {
-    return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx, 1);
+    return do_sigver_init(ctx, pctx, NULL, mdname, libctx, props, NULL, pkey, 1);
 }
 
 int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                          const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
 {
-    return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 1);
+    return do_sigver_init(ctx, pctx, type, NULL, NULL, NULL, e, pkey, 1);
 }
 #endif /* FIPS_MDOE */
 
diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c
index 44a69083b2..2c4f49a528 100644
--- a/crypto/evp/p_sign.c
+++ b/crypto/evp/p_sign.c
@@ -14,8 +14,9 @@
 #include <openssl/x509.h>
 #include "crypto/evp.h"
 
-int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
-                  unsigned int *siglen, EVP_PKEY *pkey)
+int EVP_SignFinal_with_libctx(EVP_MD_CTX *ctx, unsigned char *sigret,
+                              unsigned int *siglen, EVP_PKEY *pkey,
+                              OPENSSL_CTX *libctx, const char *propq)
 {
     unsigned char m[EVP_MAX_MD_SIZE];
     unsigned int m_len = 0;
@@ -30,8 +31,9 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     } else {
         int rv = 0;
         EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
+
         if (tmp_ctx == NULL) {
-            EVPerr(EVP_F_EVP_SIGNFINAL, ERR_R_MALLOC_FAILURE);
+            EVPerr(0, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
@@ -44,7 +46,7 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
 
     sltmp = (size_t)EVP_PKEY_size(pkey);
     i = 0;
-    pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+    pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
     if (pkctx == NULL)
         goto err;
     if (EVP_PKEY_sign_init(pkctx) <= 0)
@@ -59,3 +61,9 @@ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
     EVP_PKEY_CTX_free(pkctx);
     return i;
 }
+
+int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
+                  unsigned int *siglen, EVP_PKEY *pkey)
+{
+    return EVP_SignFinal_with_libctx(ctx, sigret, siglen, pkey, NULL, NULL);
+}
diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c
index fe4b7b568d..db14866af0 100644
--- a/crypto/evp/p_verify.c
+++ b/crypto/evp/p_verify.c
@@ -14,8 +14,9 @@
 #include <openssl/x509.h>
 #include "crypto/evp.h"
 
-int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
-                    unsigned int siglen, EVP_PKEY *pkey)
+int EVP_VerifyFinal_with_libctx(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+                                unsigned int siglen, EVP_PKEY *pkey,
+                                OPENSSL_CTX *libctx, const char *propq)
 {
     unsigned char m[EVP_MAX_MD_SIZE];
     unsigned int m_len = 0;
@@ -28,8 +29,9 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
     } else {
         int rv = 0;
         EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
+
         if (tmp_ctx == NULL) {
-            EVPerr(EVP_F_EVP_VERIFYFINAL, ERR_R_MALLOC_FAILURE);
+            EVPerr(0, ERR_R_MALLOC_FAILURE);
             return 0;
         }
         rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx);
@@ -41,7 +43,7 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
     }
 
     i = -1;
-    pkctx = EVP_PKEY_CTX_new(pkey, NULL);
+    pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
     if (pkctx == NULL)
         goto err;
     if (EVP_PKEY_verify_init(pkctx) <= 0)
@@ -53,3 +55,9 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
     EVP_PKEY_CTX_free(pkctx);
     return i;
 }
+
+int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+                    unsigned int siglen, EVP_PKEY *pkey)
+{
+    return EVP_VerifyFinal_with_libctx(ctx, sigbuf, siglen, pkey, NULL, NULL);
+}
diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c
index 08852418cc..f04e4b34ce 100644
--- a/crypto/pkcs7/pk7_asn1.c
+++ b/crypto/pkcs7/pk7_asn1.c
@@ -12,6 +12,7 @@
 #include <openssl/asn1t.h>
 #include <openssl/pkcs7.h>
 #include <openssl/x509.h>
+#include "pk7_local.h"
 
 /* PKCS#7 ASN1 module */
 
@@ -62,7 +63,52 @@ ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = {
         ASN1_ADB_OBJECT(PKCS7)
 }ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7)
 
-IMPLEMENT_ASN1_FUNCTIONS(PKCS7)
+PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len)
+{
+    PKCS7 *ret;
+
+    ret = (PKCS7 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (PKCS7_it()));
+    if (ret != NULL && a != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
+}
+
+int i2d_PKCS7(const PKCS7 *a, unsigned char **out)
+{
+    return ASN1_item_i2d((const ASN1_VALUE *)a, out, (PKCS7_it()));\
+}
+
+PKCS7 *PKCS7_new(void)
+{
+    return (PKCS7 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS7));
+}
+
+PKCS7 *PKCS7_new_with_libctx(OPENSSL_CTX *libctx, const char *propq)
+{
+    PKCS7 *pkcs7 = PKCS7_new();
+
+    if (pkcs7 != NULL) {
+        pkcs7->ctx.libctx = libctx;
+        pkcs7->ctx.propq = NULL;
+        if (propq != NULL) {
+            pkcs7->ctx.propq = OPENSSL_strdup(propq);
+            if (pkcs7->ctx.propq == NULL) {
+                PKCS7_free(pkcs7);
+                pkcs7 = NULL;
+                ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+            }
+        }
+    }
+    return pkcs7;
+}
+
+void PKCS7_free(PKCS7 *p7)
+{
+    if (p7 != NULL) {
+        OPENSSL_free(p7->ctx.propq);
+        ASN1_item_free((ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7));
+    }
+}
 
 IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7)
 
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index b815a4a77b..1d2a1eb898 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -14,6 +14,7 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
+#include "pk7_local.h"
 
 DEFINE_STACK_OF(X509_ALGOR)
 DEFINE_STACK_OF(X509_ATTRIBUTE)
@@ -57,22 +58,27 @@ static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
     return NULL;
 }
 
-static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
+static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg,
+                                const PKCS7_CTX *ctx)
 {
     BIO *btmp;
-    const EVP_MD *md;
+    const char *name;
+    EVP_MD *fetched = NULL;
+
     if ((btmp = BIO_new(BIO_f_md())) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB);
         goto err;
     }
 
-    md = EVP_get_digestbyobj(alg->algorithm);
-    if (md == NULL) {
+    name = OBJ_nid2sn(OBJ_obj2nid(alg->algorithm));
+    fetched = EVP_MD_fetch(ctx->libctx, name, ctx->propq);
+    if (fetched == NULL) {
         PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE);
         goto err;
     }
 
-    BIO_set_md(btmp, md);
+    BIO_set_md(btmp, fetched);
+    EVP_MD_free(fetched);
     if (*pbio == NULL)
         *pbio = btmp;
     else if (!BIO_push(*pbio, btmp)) {
@@ -86,7 +92,6 @@ static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
  err:
     BIO_free(btmp);
     return 0;
-
 }
 
 static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
@@ -97,12 +102,13 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
     unsigned char *ek = NULL;
     int ret = 0;
     size_t eklen;
+    const PKCS7_CTX *ctx = ri->ctx;
 
     pkey = X509_get0_pubkey(ri->cert);
     if (pkey == NULL)
         return 0;
 
-    pctx = EVP_PKEY_CTX_new(pkey, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq);
     if (pctx == NULL)
         return 0;
 
@@ -148,8 +154,9 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
     unsigned char *ek = NULL;
     size_t eklen;
     int ret = -1;
+    const PKCS7_CTX *ctx = ri->ctx;
 
-    pctx = EVP_PKEY_CTX_new(pkey, NULL);
+    pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq);
     if (pctx == NULL)
         return -1;
 
@@ -201,17 +208,21 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
     int i;
     BIO *out = NULL, *btmp = NULL;
     X509_ALGOR *xa = NULL;
+    EVP_CIPHER *fetched_cipher = NULL;
     const EVP_CIPHER *evp_cipher = NULL;
     STACK_OF(X509_ALGOR) *md_sk = NULL;
     STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
     X509_ALGOR *xalg = NULL;
     PKCS7_RECIP_INFO *ri = NULL;
     ASN1_OCTET_STRING *os = NULL;
+    const PKCS7_CTX *p7_ctx;
 
     if (p7 == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
         return NULL;
     }
+    p7_ctx = pkcs7_get0_ctx(p7);
+
     /*
      * The content field in the PKCS7 ContentInfo is optional, but that really
      * only applies to inner content (precisely, detached signatures).
@@ -266,10 +277,10 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
     }
 
     for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++)
-        if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
+        if (!pkcs7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i), p7_ctx))
             goto err;
 
-    if (xa && !PKCS7_bio_add_digest(&out, xa))
+    if (xa && !pkcs7_bio_add_digest(&out, xa, p7_ctx))
         goto err;
 
     if (evp_cipher != NULL) {
@@ -287,10 +298,21 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
         ivlen = EVP_CIPHER_iv_length(evp_cipher);
         xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
         if (ivlen > 0)
-            if (RAND_bytes(iv, ivlen) <= 0)
+            if (RAND_bytes_ex(p7_ctx->libctx, iv, ivlen) <= 0)
                 goto err;
-        if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0)
+
+        fetched_cipher = EVP_CIPHER_fetch(p7_ctx->libctx,
+                                          EVP_CIPHER_name(evp_cipher),
+                                          p7_ctx->propq);
+        if (fetched_cipher == NULL)
             goto err;
+
+        if (EVP_CipherInit_ex(ctx, fetched_cipher, NULL, NULL, NULL, 1) <= 0)
+            goto err;
+
+        EVP_CIPHER_free(fetched_cipher);
+        fetched_cipher = NULL;
+
         if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
             goto err;
         if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
@@ -342,6 +364,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
     return out;
 
  err:
+    EVP_CIPHER_free(fetched_cipher);
     BIO_free_all(out);
     BIO_free_all(btmp);
     return NULL;
@@ -361,12 +384,12 @@ static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
 /* int */
 BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 {
-    int i, j, len;
+    int i, len;
     BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL;
     X509_ALGOR *xa;
     ASN1_OCTET_STRING *data_body = NULL;
-    const EVP_MD *evp_md;
-    const EVP_CIPHER *evp_cipher = NULL;
+    EVP_MD *evp_md = NULL;
+    EVP_CIPHER *evp_cipher = NULL;
     EVP_CIPHER_CTX *evp_ctx = NULL;
     X509_ALGOR *enc_alg = NULL;
     STACK_OF(X509_ALGOR) *md_sk = NULL;
@@ -374,12 +397,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
     PKCS7_RECIP_INFO *ri = NULL;
     unsigned char *ek = NULL, *tkey = NULL;
     int eklen = 0, tkeylen = 0;
+    const char *name;
+    const PKCS7_CTX *p7_ctx;
 
     if (p7 == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
         return NULL;
     }
 
+    p7_ctx = pkcs7_get0_ctx(p7);
+
     if (p7->d.ptr == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
         return NULL;
@@ -410,7 +437,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
         /* data_body is NULL if the optional EncryptedContent is missing. */
         data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
         enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
-        evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
+
+        name = OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm));
+        evp_cipher = EVP_CIPHER_fetch(p7_ctx->libctx, name, p7_ctx->propq);
         if (evp_cipher == NULL) {
             PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                      PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
@@ -422,7 +451,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
         enc_alg = p7->d.enveloped->enc_data->algorithm;
         /* data_body is NULL if the optional EncryptedContent is missing. */
         data_body = p7->d.enveloped->enc_data->enc_data;
-        evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
+        name = OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm));
+        evp_cipher = EVP_CIPHER_fetch(p7_ctx->libctx, name, p7_ctx->propq);
         if (evp_cipher == NULL) {
             PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                      PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
@@ -449,8 +479,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
                 goto err;
             }
 
-            j = OBJ_obj2nid(xa->algorithm);
-            evp_md = EVP_get_digestbynid(j);
+            name = OBJ_nid2sn(OBJ_obj2nid(xa->algorithm));
+            evp_md = EVP_MD_fetch(p7_ctx->libctx, name, p7_ctx->propq);
             if (evp_md == NULL) {
                 PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                          PKCS7_R_UNKNOWN_DIGEST_TYPE);
@@ -458,6 +488,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
             }
 
             BIO_set_md(btmp, evp_md);
+            EVP_MD_free(evp_md);
             if (out == NULL)
                 out = btmp;
             else
@@ -504,13 +535,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
              */
             for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
                 ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
-
+                ri->ctx = p7_ctx;
                 if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
                         EVP_CIPHER_key_length(evp_cipher)) < 0)
                     goto err;
                 ERR_clear_error();
             }
         } else {
+            ri->ctx = p7_ctx;
             /* Only exit on fatal errors, not decrypt failure */
             if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
                 goto err;
@@ -585,9 +617,11 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
     }
     BIO_push(out, bio);
     bio = NULL;
+    EVP_CIPHER_free(evp_cipher);
     return out;
 
  err:
+    EVP_CIPHER_free(evp_cipher);
     OPENSSL_clear_free(ek, eklen);
     OPENSSL_clear_free(tkey, tkeylen);
     BIO_free_all(out);
@@ -658,12 +692,15 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
     STACK_OF(X509_ATTRIBUTE) *sk;
     STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
     ASN1_OCTET_STRING *os = NULL;
+    const PKCS7_CTX *p7_ctx;
 
     if (p7 == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
         return 0;
     }
 
+    p7_ctx = pkcs7_get0_ctx(p7);
+
     if (p7->d.ptr == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
         return 0;
@@ -771,7 +808,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
                 if (abuf == NULL)
                     goto err;
 
-                if (!EVP_SignFinal(ctx_tmp, abuf, &abuflen, si->pkey)) {
+                if (!EVP_SignFinal_with_libctx(ctx_tmp, abuf, &abuflen, si->pkey,
+                                               p7_ctx->libctx, p7_ctx->propq)) {
                     OPENSSL_free(abuf);
                     PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB);
                     goto err;
@@ -830,6 +868,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
     int alen;
     size_t siglen;
     const EVP_MD *md = NULL;
+    const PKCS7_CTX *ctx = si->ctx;
 
     md = EVP_get_digestbyobj(si->digest_alg->algorithm);
     if (md == NULL)
@@ -837,11 +876,13 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
 
     mctx = EVP_MD_CTX_new();
     if (mctx == NULL) {
-        PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, ERR_R_MALLOC_FAILURE);
+        PKCS7err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
-    if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0)
+    if (EVP_DigestSignInit_with_libctx(mctx, &pctx,
+                                       EVP_MD_name(md), ctx->libctx, ctx->propq,
+                                       si->pkey) <= 0)
         goto err;
 
     /*
@@ -863,7 +904,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
 #if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) {
-        PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
+        PKCS7err(0, PKCS7_R_CTRL_ERROR);
         goto err;
     }
 #endif
@@ -903,7 +944,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
 #if 0
     if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
                           EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) {
-        PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR);
+        PKCS7err(0, PKCS7_R_CTRL_ERROR);
         goto err;
     }
 #endif
@@ -918,7 +959,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
     OPENSSL_free(abuf);
     EVP_MD_CTX_free(mctx);
     return 0;
-
 }
 
 int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
@@ -983,11 +1023,13 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
 {
     ASN1_OCTET_STRING *os;
     EVP_MD_CTX *mdc_tmp, *mdc;
+    EVP_MD *fetched_md = NULL;
     int ret = 0, i;
     int md_type;
     STACK_OF(X509_ATTRIBUTE) *sk;
     BIO *btmp;
     EVP_PKEY *pkey;
+    const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7);
 
     mdc_tmp = EVP_MD_CTX_new();
     if (mdc_tmp == NULL) {
@@ -1055,7 +1097,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
             goto err;
         }
 
-        if (!EVP_VerifyInit_ex(mdc_tmp, EVP_get_digestbynid(md_type), NULL))
+        fetched_md = EVP_MD_fetch(ctx->libctx, OBJ_nid2sn(md_type), ctx->propq);
+        if (fetched_md == NULL || !EVP_VerifyInit_ex(mdc_tmp, fetched_md, NULL))
             goto err;
 
         alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
@@ -1078,7 +1121,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
         goto err;
     }
 
-    i = EVP_VerifyFinal(mdc_tmp, os->data, os->length, pkey);
+    i = EVP_VerifyFinal_with_libctx(mdc_tmp, os->data, os->length, pkey,
+                                    ctx->libctx, ctx->propq);
     if (i <= 0) {
         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE);
         ret = -1;
@@ -1087,6 +1131,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
     ret = 1;
  err:
     EVP_MD_CTX_free(mdc_tmp);
+    EVP_MD_free(fetched_md);
     return ret;
 }
 
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index cb8c67b65a..abe3570c68 100644
--- a/crypto/pkcs7/pk7_lib.c
+++ b/crypto/pkcs7/pk7_lib.c
@@ -13,6 +13,8 @@
 #include <openssl/x509.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/x509.h"
+#include "pk7_local.h"
 
 DEFINE_STACK_OF(X509)
 DEFINE_STACK_OF(X509_CRL)
@@ -236,6 +238,7 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
         }
     }
 
+    psi->ctx = pkcs7_get0_ctx(p7);
     if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi))
         return 0;
     return 1;
@@ -380,6 +383,70 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey,
     return NULL;
 }
 
+static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7)
+{
+    if (PKCS7_type_is_signed(p7))
+        return p7->d.sign->cert;
+    if (PKCS7_type_is_signedAndEnveloped(p7))
+        return p7->d.signed_and_enveloped->cert;
+    return NULL;
+}
+
+static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7)
+{
+    if (PKCS7_type_is_signedAndEnveloped(p7))
+        return p7->d.signed_and_enveloped->recipientinfo;
+    if (PKCS7_type_is_enveloped(p7))
+        return p7->d.enveloped->recipientinfo;
+    return NULL;
+}
+
+/*
+ * Set up the library context into any loaded structure that needs it.
+ * i.e loaded X509 objects.
+ */
+void pkcs7_resolve_libctx(PKCS7 *p7)
+{
+    int i;
+    const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7);
+    STACK_OF(PKCS7_RECIP_INFO) *rinfos = pkcs7_get_recipient_info(p7);
+    STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7);
+    STACK_OF(X509) *certs = pkcs7_get_signer_certs(p7);
+
+    if (ctx == NULL)
+        return;
+
+    for (i = 0; i < sk_X509_num(certs); i++)
+        x509_set0_libctx(sk_X509_value(certs, i), ctx->libctx, ctx->propq);
+
+    for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) {
+        PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i);
+
+        x509_set0_libctx(ri->cert, ctx->libctx, ctx->propq);
+    }
+
+    for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+        PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+
+        if (si != NULL)
+            si->ctx = ctx;
+    }
+}
+
+const PKCS7_CTX *pkcs7_get0_ctx(const PKCS7 *p7)
+{
+    return p7 != NULL ? &p7->ctx : NULL;
+}
+
+OPENSSL_CTX *pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx)
+{
+    return ctx != NULL ? ctx->libctx : NULL;
+}
+const char *pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx)
+{
+    return ctx != NULL ? ctx->propq : NULL;
+}
+
 int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md)
 {
     if (PKCS7_type_is_digest(p7)) {
@@ -435,6 +502,7 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
         goto err;
     if (!PKCS7_add_recipient_info(p7, ri))
         goto err;
+    ri->ctx = pkcs7_get0_ctx(p7);
     return ri;
  err:
     PKCS7_RECIP_INFO_free(ri);
@@ -547,6 +615,7 @@ int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
     }
 
     ec->cipher = cipher;
+    ec->ctx = pkcs7_get0_ctx(p7);
     return 1;
 }
 
diff --git a/crypto/pkcs7/pk7_local.h b/crypto/pkcs7/pk7_local.h
new file mode 100644
index 0000000000..b9f9c35340
--- /dev/null
+++ b/crypto/pkcs7/pk7_local.h
@@ -0,0 +1,14 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto/pkcs7.h"
+
+const PKCS7_CTX *pkcs7_get0_ctx(const PKCS7 *p7);
+OPENSSL_CTX *pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx);
+const char *pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx);
diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c
index 6f3981ec6b..2099e8d9ef 100644
--- a/crypto/pkcs7/pk7_mime.c
+++ b/crypto/pkcs7/pk7_mime.c
@@ -11,6 +11,7 @@
 #include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
+#include "pk7_local.h"
 
 /* PKCS#7 wrappers round generalised stream and MIME routines */
 
@@ -30,6 +31,8 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 {
     STACK_OF(X509_ALGOR) *mdalgs;
     int ctype_nid = OBJ_obj2nid(p7->type);
+    const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7);
+
     if (ctype_nid == NID_pkcs7_signed)
         mdalgs = p7->d.sign->md_algs;
     else
@@ -37,12 +40,25 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 
     flags ^= SMIME_OLDMIME;
 
-    return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags,
-                            ctype_nid, NID_undef, mdalgs,
-                            ASN1_ITEM_rptr(PKCS7));
+    return SMIME_write_ASN1_with_libctx(bio, (ASN1_VALUE *)p7, data, flags,
+                                        ctype_nid, NID_undef, mdalgs,
+                                        ASN1_ITEM_rptr(PKCS7),
+                                        pkcs7_ctx_get0_libctx(ctx),
+                                        pkcs7_ctx_get0_propq(ctx));
+}
+
+PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7)
+{
+    PKCS7 *ret;
+
+    ret = (PKCS7 *)SMIME_read_ASN1_ex(bio, bcont, ASN1_ITEM_rptr(PKCS7),
+                                      (ASN1_VALUE **)p7);
+    if (ret != NULL && p7 != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
 }
 
 PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont)
 {
-    return (PKCS7 *)SMIME_read_ASN1(bio, bcont, ASN1_ITEM_rptr(PKCS7));
+    return SMIME_read_PKCS7_ex(bio, bcont, NULL);
 }
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
index 385b4af42e..1dfdd69e51 100644
--- a/crypto/pkcs7/pk7_smime.c
+++ b/crypto/pkcs7/pk7_smime.c
@@ -13,6 +13,7 @@
 #include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
+#include "pk7_local.h"
 
 #define BUFFERSIZE 4096
 
@@ -23,14 +24,15 @@ DEFINE_STACK_OF(PKCS7_SIGNER_INFO)
 
 static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
 
-PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
-                  BIO *data, int flags)
+PKCS7 *PKCS7_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                              STACK_OF(X509) *certs, BIO *data, int flags,
+                              OPENSSL_CTX *libctx, const char *propq)
 {
     PKCS7 *p7;
     int i;
 
-    if ((p7 = PKCS7_new()) == NULL) {
-        PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE);
+    if ((p7 = PKCS7_new_with_libctx(libctx, propq)) == NULL) {
+        PKCS7err(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
@@ -41,7 +43,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
         goto err;
 
     if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) {
-        PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
+        PKCS7err(0, PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
         goto err;
     }
 
@@ -66,6 +68,13 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
     return NULL;
 }
 
+PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                  BIO *data, int flags)
+{
+    return PKCS7_sign_with_libctx(signcert, pkey, certs, data, flags, NULL, NULL);
+}
+
+
 int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
 {
     BIO *p7bio;
@@ -84,10 +93,8 @@ int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
         PKCS7err(PKCS7_F_PKCS7_FINAL, PKCS7_R_PKCS7_DATASIGN);
         goto err;
     }
-
     ret = 1;
-
- err:
+err:
     BIO_free_all(p7bio);
 
     return ret;
@@ -116,6 +123,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
 {
     PKCS7_SIGNER_INFO *si = NULL;
     STACK_OF(X509_ALGOR) *smcap = NULL;
+
     if (!X509_check_private_key(signcert, pkey)) {
         PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
                  PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
@@ -128,6 +136,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
         return NULL;
     }
 
+    si->ctx = pkcs7_get0_ctx(p7);
     if (!(flags & PKCS7_NOCERTS)) {
         if (!PKCS7_add_certificate(p7, signcert))
             goto err;
@@ -162,7 +171,8 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
         if (flags & PKCS7_REUSE_DIGEST) {
             if (!pkcs7_copy_existing_digest(p7, si))
                 goto err;
-            if (!(flags & PKCS7_PARTIAL) && !PKCS7_SIGNER_INFO_sign(si))
+            if (!(flags & PKCS7_PARTIAL)
+                && !PKCS7_SIGNER_INFO_sign(si))
                 goto err;
         }
     }
@@ -197,7 +207,7 @@ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
 
     }
 
-    if (osdig)
+    if (osdig != NULL)
         return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length);
 
     PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST,
@@ -217,20 +227,21 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     int i, j = 0, k, ret = 0;
     BIO *p7bio = NULL;
     BIO *tmpin = NULL, *tmpout = NULL;
+    const PKCS7_CTX *p7_ctx;
 
     if (p7 == NULL) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER);
+        PKCS7err(0, PKCS7_R_INVALID_NULL_POINTER);
         return 0;
     }
 
     if (!PKCS7_type_is_signed(p7)) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_WRONG_CONTENT_TYPE);
+        PKCS7err(0, PKCS7_R_WRONG_CONTENT_TYPE);
         return 0;
     }
 
     /* Check for no data and no content: no data to verify signature */
     if (PKCS7_get_detached(p7) && !indata) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_CONTENT);
+        PKCS7err(0, PKCS7_R_NO_CONTENT);
         return 0;
     }
 
@@ -243,7 +254,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
          * process is different, but the existing PKCs7 verification works.
          */
         if (!PKCS7_get_detached(p7) && indata) {
-            PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT);
+            PKCS7err(0, PKCS7_R_CONTENT_AND_DATA_PRESENT);
             return 0;
         }
     }
@@ -251,17 +262,17 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     sinfos = PKCS7_get_signer_info(p7);
 
     if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_SIGNATURES_ON_DATA);
+        PKCS7err(0, PKCS7_R_NO_SIGNATURES_ON_DATA);
         return 0;
     }
 
     signers = PKCS7_get0_signers(p7, certs, flags);
-    if (!signers)
+    if (signers == NULL)
         return 0;
 
     /* Now verify the certificates */
-
-    cert_ctx = X509_STORE_CTX_new();
+    p7_ctx = pkcs7_get0_ctx(p7);
+    cert_ctx = X509_STORE_CTX_new_with_libctx(p7_ctx->libctx, p7_ctx->propq);
     if (cert_ctx == NULL)
         goto err;
     if (!(flags & PKCS7_NOVERIFY))
@@ -270,12 +281,12 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
             if (!(flags & PKCS7_NOCHAIN)) {
                 if (!X509_STORE_CTX_init(cert_ctx, store, signer,
                                          p7->d.sign->cert)) {
-                    PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
+                    PKCS7err(0, ERR_R_X509_LIB);
                     goto err;
                 }
                 X509_STORE_CTX_set_default(cert_ctx, "smime_sign");
             } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) {
-                PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
+                PKCS7err(0, ERR_R_X509_LIB);
                 goto err;
             }
             if (!(flags & PKCS7_NOCRL))
@@ -285,8 +296,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
                 j = X509_STORE_CTX_get_error(cert_ctx);
             X509_STORE_CTX_cleanup(cert_ctx);
             if (i <= 0) {
-                PKCS7err(PKCS7_F_PKCS7_VERIFY,
-                         PKCS7_R_CERTIFICATE_VERIFY_ERROR);
+                PKCS7err(0, PKCS7_R_CERTIFICATE_VERIFY_ERROR);
                 ERR_add_error_data(2, "Verify error:",
                                    X509_verify_cert_error_string(j));
                 goto err;
@@ -307,7 +317,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
         len = BIO_get_mem_data(indata, &ptr);
         tmpin = BIO_new_mem_buf(ptr, len);
         if (tmpin == NULL) {
-            PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+            PKCS7err(0, ERR_R_MALLOC_FAILURE);
             goto err;
         }
     } else
@@ -318,7 +328,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
 
     if (flags & PKCS7_TEXT) {
         if ((tmpout = BIO_new(BIO_s_mem())) == NULL) {
-            PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+            PKCS7err(0, ERR_R_MALLOC_FAILURE);
             goto err;
         }
         BIO_set_mem_eof_return(tmpout, 0);
@@ -327,7 +337,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
 
     /* We now have to 'read' from p7bio to calculate digests etc. */
     if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+        PKCS7err(0, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     for (;;) {
@@ -340,7 +350,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
 
     if (flags & PKCS7_TEXT) {
         if (!SMIME_text(tmpout, out)) {
-            PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SMIME_TEXT_ERROR);
+            PKCS7err(0, PKCS7_R_SMIME_TEXT_ERROR);
             BIO_free(tmpout);
             goto err;
         }
@@ -354,7 +364,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
             signer = sk_X509_value(signers, i);
             j = PKCS7_signatureVerify(p7bio, p7, si, signer);
             if (j <= 0) {
-                PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE);
+                PKCS7err(0, PKCS7_R_SIGNATURE_FAILURE);
                 goto err;
             }
         }
@@ -437,29 +447,31 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
 
 /* Build a complete PKCS#7 enveloped data */
 
-PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
-                     int flags)
+PKCS7 *PKCS7_encrypt_with_libctx(STACK_OF(X509) *certs, BIO *in,
+                                 const EVP_CIPHER *cipher, int flags,
+                                 OPENSSL_CTX *libctx, const char *propq)
 {
     PKCS7 *p7;
     BIO *p7bio = NULL;
     int i;
     X509 *x509;
-    if ((p7 = PKCS7_new()) == NULL) {
-        PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE);
+
+    if ((p7 = PKCS7_new_with_libctx(libctx, propq)) == NULL) {
+        PKCS7err(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
     if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
         goto err;
     if (!PKCS7_set_cipher(p7, cipher)) {
-        PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_SETTING_CIPHER);
+        PKCS7err(0, PKCS7_R_ERROR_SETTING_CIPHER);
         goto err;
     }
 
     for (i = 0; i < sk_X509_num(certs); i++) {
         x509 = sk_X509_value(certs, i);
         if (!PKCS7_add_recipient(p7, x509)) {
-            PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_ADDING_RECIPIENT);
+            PKCS7err(0, PKCS7_R_ERROR_ADDING_RECIPIENT);
             goto err;
         }
     }
@@ -478,6 +490,13 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
 
 }
 
+PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+                     int flags)
+{
+    return PKCS7_encrypt_with_libctx(certs, in, cipher, flags, NULL, NULL);
+}
+
+
 int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
 {
     BIO *tmpmem;
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index 428cd145fa..858d3d72c8 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -1006,7 +1006,7 @@ int EVP_PKEY_CTX_get_rsa_oaep_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
         return -1;
 
     /* May be NULL meaning "unknown" */
-    *md = EVP_get_digestbyname(name);
+    *md = evp_get_digestbyname_ex(ctx->libctx, name);
 
     return 1;
 }
@@ -1159,7 +1159,7 @@ int EVP_PKEY_CTX_get_rsa_mgf1_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
         return -1;
 
     /* May be NULL meaning "unknown" */
-    *md = EVP_get_digestbyname(name);
+    *md = evp_get_digestbyname_ex(ctx->libctx, name);
 
     return 1;
 }
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index b06828f718..868b187c5d 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -24,6 +24,7 @@
 #include <openssl/dsa.h>
 #include <openssl/x509v3.h>
 #include "crypto/asn1.h"
+#include "crypto/pkcs7.h"
 #include "crypto/x509.h"
 
 static void clean_id_ctx(EVP_MD_CTX *ctx)
@@ -232,7 +233,12 @@ int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl)
 #ifndef OPENSSL_NO_STDIO
 PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
 {
-    return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+    PKCS7 *ret;
+
+    ret = ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+    if (ret != NULL && p7 != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
 }
 
 int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
@@ -243,7 +249,12 @@ int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
 
 PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
 {
-    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+    PKCS7 *ret;
+
+    ret = ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+    if (ret != NULL && p7 != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
 }
 
 int i2d_PKCS7_bio(BIO *bp, const PKCS7 *p7)
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 9358c46a7f..64bf5faa83 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -133,6 +133,20 @@ int i2d_X509(const X509 *a, unsigned char **out)
     return ASN1_item_i2d((const ASN1_VALUE *)a, out, (X509_it()));
 }
 
+/*
+ * This should only be used if the X509 object was embedded inside another
+ * asn1 object and it needs a libctx to operate.
+ * Use X509_new_with_libctx() instead if possible.
+ */
+int x509_set0_libctx(X509 *x, OPENSSL_CTX *libctx, const char *propq)
+{
+    if (x != NULL) {
+        x->libctx = libctx;
+        x->propq = propq;
+    }
+    return 1;
+}
+
 X509 *X509_new_with_libctx(OPENSSL_CTX *libctx, const char *propq)
 {
     X509 *cert = NULL;
diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in
index 6ee411d550..a72b4c9fa0 100644
--- a/doc/man1/openssl-cms.pod.in
+++ b/doc/man1/openssl-cms.pod.in
@@ -83,6 +83,7 @@ B<openssl> B<cms>
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
 [I<recipient-cert> ...]
 
 =for openssl ifdef des-wrap engine
@@ -501,6 +502,8 @@ Any verification errors cause the command to exit.
 
 {- $OpenSSL::safe::opt_provider_item -}
 
+{- $OpenSSL::safe::opt_config_item -}
+
 =item I<recipient-cert> ...
 
 One or more certificates of message recipients: used when encrypting
diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in
index b15be731c0..9f42c0c1fe 100644
--- a/doc/man1/openssl-smime.pod.in
+++ b/doc/man1/openssl-smime.pod.in
@@ -50,6 +50,7 @@ B<openssl> B<smime>
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_v_synopsis -}
 {- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
 I<recipcert> ...
 
 =for openssl ifdef engine
@@ -292,6 +293,8 @@ Any verification errors cause the command to exit.
 
 {- $OpenSSL::safe::opt_provider_item -}
 
+{- $OpenSSL::safe::opt_config_item -}
+
 =item I<recipcert> ...
 
 One or more certificates of message recipients, used when encrypting
diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod
new file mode 100644
index 0000000000..17850a98af
--- /dev/null
+++ b/doc/man3/CMS_EncryptedData_decrypt.pod
@@ -0,0 +1,49 @@
+=pod
+
+=head1 NAME
+
+CMS_EncryptedData_decrypt
+- Decrypt CMS EncryptedData
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
+                               const unsigned char *key, size_t keylen,
+                               BIO *dcont, BIO *out, unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_EncryptedData_decrypt() decrypts a I<cms> EncryptedData object using the
+symmetric I<key> of size I<keylen> bytes. I<out> is a BIO to write the content
+to and I<flags> is an optional set of flags.
+I<dcont> is used in the rare case where the encrypted content is detached. It
+will normally be set to NULL.
+
+The following flags can be passed in the B<flags> parameter.
+
+If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
+from the content. If the content is not of type B<text/plain> then an error is
+returned.
+
+=head1 RETURN VALUES
+
+CMS_EncryptedData_decrypt() returns 0 if an error occurred otherwise it
+returns 1.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_EncryptedData_encrypt(3)>
+
+
+=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/CMS_EncryptedData_encrypt.pod b/doc/man3/CMS_EncryptedData_encrypt.pod
new file mode 100644
index 0000000000..cb2672f629
--- /dev/null
+++ b/doc/man3/CMS_EncryptedData_encrypt.pod
@@ -0,0 +1,65 @@
+=pod
+
+=head1 NAME
+
+CMS_EncryptedData_encrypt_with_libctx, CMS_EncryptedData_encrypt
+- Create CMS EncryptedData
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_EncryptedData_encrypt_with_libctx(BIO *in,
+     const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen,
+     unsigned int flags, OPENSSL_CTX *ctx, const char *propq);
+
+ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in,
+     const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen,
+     unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_EncryptedData_encrypt_with_libctx() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_encrypted>. I<in> is a BIO containing the data to
+encrypt using I<cipher> and the encryption key I<key> of size I<keylen> bytes.
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. I<flags> is a set of optional flags.
+
+The I<flags> field supports the options B<CMS_DETACHED>, B<CMS_STREAM> and
+B<CMS_PARTIAL>. Internally CMS_final() is called unless B<CMS_STREAM> and/or
+B<CMS_PARTIAL> is specified.
+
+The algorithm passed in the I<cipher> parameter must support ASN1 encoding of
+its parameters.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_EncryptedData_encrypt() is similar to CMS_EncryptedData_encrypt_with_libctx()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_EncryptedData_encrypt_with_libctx() and
+CMS_EncryptedData_encrypt() return NULL and set an error code that can be
+obtained by L<ERR_get_error(3)>. Otherwise they return a pointer to the newly
+allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>, L<CMS_EncryptedData_decrypt(3)>
+
+head1 HISTORY
+
+The CMS_EncryptedData_encrypt_with_libctx() method was 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/CMS_EnvelopedData_create.pod b/doc/man3/CMS_EnvelopedData_create.pod
index 625daa8029..e6903ea3f8 100644
--- a/doc/man3/CMS_EnvelopedData_create.pod
+++ b/doc/man3/CMS_EnvelopedData_create.pod
@@ -2,20 +2,26 @@
 
 =head1 NAME
 
-CMS_EnvelopedData_create - Create CMS envelope
+CMS_EnvelopedData_create_with_libctx, CMS_EnvelopedData_create
+- Create CMS envelope
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
+ CMS_ContentInfo *CMS_EnvelopedData_create_with_libctx(const EVP_CIPHER *cipher,
+                                                       OPENSSL_CTX *libctx,
+                                                       const char *propq);
  CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
 
 =head1 DESCRIPTION
 
-CMS_EnvelopedData_create() creates a B<CMS_ContentInfo> structure with
-a type B<NID_pkcs7_enveloped>. B<cipher> is the symmetric cipher to use.
+CMS_EnvelopedData_create_with_libctx() creates a B<CMS_ContentInfo> structure with
+a type B<NID_pkcs7_enveloped>. I<cipher> is the symmetric cipher to use. The
+library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers.
 
-The algorithm passed in the B<cipher> parameter must support ASN1 encoding of
+The algorithm passed in the I<cipher> parameter must support ASN1 encoding of
 its parameters.
 
 The recipients can be added later using L<CMS_add1_recipient_cert(3)> or
@@ -24,6 +30,10 @@ L<CMS_add0_recipient_key(3)>.
 The B<CMS_ContentInfo> structure needs to be finalized using L<CMS_final(3)>
 and then freed using L<CMS_ContentInfo_free(3)>.
 
+CMS_EnvelopedData_create() is similar to CMS_EnvelopedData_create_with_libctx()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
 =head1 NOTES
 
 Although CMS_EnvelopedData_create() allocates a new B<CMS_ContentInfo>
@@ -40,6 +50,10 @@ Otherwise it returns a pointer to the newly allocated structure.
 
 L<ERR_get_error(3)>, L<CMS_encrypt(3)>, L<CMS_decrypt(3)>, L<CMS_final(3)>
 
+head1 HISTORY
+
+The CMS_EnvelopedData_create_with_libctx() method was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/CMS_data_create.pod b/doc/man3/CMS_data_create.pod
new file mode 100644
index 0000000000..b64a7a1d46
--- /dev/null
+++ b/doc/man3/CMS_data_create.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+CMS_data_create_with_libctx, CMS_data_create
+- Create CMS Data object
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_data_create_with_libctx(BIO *in, unsigned int flags,
+                                              OPENSSL_CTX *libctx,
+                                              const char *propq);
+ CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_data_create_with_libctx() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_data>. The data is supplied via the I<in> BIO.
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. The I<flags> field supports the
+B<CMS_STREAM> flag. Internally CMS_final() is called unless B<CMS_STREAM> is
+specified.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_data_create() is similar to CMS_data_create_with_libctx()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_data_create_with_libctx() and CMS_data_create()
+return NULL and set an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise they return a pointer to the newly allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>
+
+head1 HISTORY
+
+The CMS_data_create_with_libctx() method was 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/CMS_digest_create.pod b/doc/man3/CMS_digest_create.pod
new file mode 100644
index 0000000000..0eba22cfe6
--- /dev/null
+++ b/doc/man3/CMS_digest_create.pod
@@ -0,0 +1,58 @@
+=pod
+
+=head1 NAME
+
+CMS_digest_create_with_libctx, CMS_digest_create
+- Create CMS DigestedData object
+
+=head1 SYNOPSIS
+
+ #include <openssl/cms.h>
+
+ CMS_ContentInfo *CMS_digest_create_with_libctx(BIO *in,
+     const EVP_MD *md, unsigned int flags,
+     OPENSSL_CTX *ctx, const char *propq);
+
+ CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
+                                    unsigned int flags);
+
+=head1 DESCRIPTION
+
+CMS_digest_create_with_libctx() creates a B<CMS_ContentInfo> structure
+with a type B<NID_pkcs7_digest>. The data supplied via the I<in> BIO is digested
+using I<md>. The library context I<libctx> and the property query I<propq> are
+used when retrieving algorithms from providers.
+The I<flags> field supports the B<CMS_DETACHED> and B<CMS_STREAM> flags,
+Internally CMS_final() is called unless B<CMS_STREAM> is specified.
+
+The B<CMS_ContentInfo> structure can be freed using L<CMS_ContentInfo_free(3)>.
+
+CMS_digest_create() is similar to CMS_digest_create_with_libctx()
+but uses default values of NULL for the library context I<libctx> and the
+property query I<propq>.
+
+
+=head1 RETURN VALUES
+
+If the allocation fails, CMS_digest_create_with_libctx() and CMS_digest_create()
+return NULL and set an error code that can be obtained by L<ERR_get_error(3)>.
+Otherwise they return a pointer to the newly allocated structure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>, L<CMS_final(3)>>
+
+head1 HISTORY
+
+The CMS_digest_create_with_libctx() method was 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/CMS_encrypt.pod b/doc/man3/CMS_encrypt.pod
index 1bc9fd041d..211ec18d36 100644
--- a/doc/man3/CMS_encrypt.pod
+++ b/doc/man3/CMS_encrypt.pod
@@ -2,20 +2,26 @@
 
 =head1 NAME
 
-CMS_encrypt - create a CMS envelopedData structure
+CMS_encrypt_with_libctx, CMS_encrypt - create a CMS envelopedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
+ CMS_ContentInfo *CMS_encrypt_with_libctx(STACK_OF(X509) *certs,
+                                          BIO *in, const EVP_CIPHER *cipher,
+                                          unsigned int flags,
+                                          OPENSSL_CTX *libctx, const char *propq);
  CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
                               const EVP_CIPHER *cipher, unsigned int flags);
 
 =head1 DESCRIPTION
 
-CMS_encrypt() creates and returns a CMS EnvelopedData structure. B<certs>
-is a list of recipient certificates. B<in> is the content to be encrypted.
-B<cipher> is the symmetric cipher to use. B<flags> is an optional set of flags.
+CMS_encrypt_with_libctx() creates and returns a CMS EnvelopedData structure.
+I<certs> is a list of recipient certificates. I<in> is the content to be
+encrypted. I<cipher> is the symmetric cipher to use. I<flags> is an optional set
+of flags. The library context I<libctx> and the property query I<propq> are used
+internally when retrieving algorithms from providers.
 
 Only certificates carrying RSA, Diffie-Hellman or EC keys are supported by this
 function.
@@ -75,10 +81,14 @@ and CMS_add0_recipient_key().
 The parameter B<certs> may be NULL if B<CMS_PARTIAL> is set and recipients
 added later using CMS_add1_recipient_cert() or CMS_add0_recipient_key().
 
+CMS_encrypt() is similar to CMS_encrypt_with_libctx() but uses default values of
+NULL for the library context I<libctx> and the property query I<propq>.
+
 =head1 RETURN VALUES
 
-CMS_encrypt() returns either a CMS_ContentInfo structure or NULL if an error
-occurred. The error can be obtained from ERR_get_error(3).
+CMS_encrypt_with_libctx() and CMS_encrypt() return either a CMS_ContentInfo
+structure or NULL if an error occurred. The error can be obtained from
+ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -86,11 +96,13 @@ L<ERR_get_error(3)>, L<CMS_decrypt(3)>
 
 =head1 HISTORY
 
+The function CMS_encrypt_with_libctx() was added in OpenSSL 3.0.
+
 The B<CMS_STREAM> flag was first supported in OpenSSL 1.0.0.
 
 =head1 COPYRIGHT
 
-Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-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/CMS_get1_ReceiptRequest.pod b/doc/man3/CMS_get1_ReceiptRequest.pod
index d9a4796dac..704d4bac01 100644
--- a/doc/man3/CMS_get1_ReceiptRequest.pod
+++ b/doc/man3/CMS_get1_ReceiptRequest.pod
@@ -2,16 +2,21 @@
 
 =head1 NAME
 
-CMS_ReceiptRequest_create0, CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CMS_ReceiptRequest_get0_values - CMS signed receipt request functions
+CMS_ReceiptRequest_create0_with_libctx, CMS_ReceiptRequest_create0,
+CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CMS_ReceiptRequest_get0_values
+- CMS signed receipt request functions
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
- CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
-                                                int allorfirst,
-                                                STACK_OF(GENERAL_NAMES) *receiptList,
-                                                STACK_OF(GENERAL_NAMES) *receiptsTo);
+ CMS_ReceiptRequest *CMS_ReceiptRequest_create0_with_libctx(
+     unsigned char *id, int idlen, int allorfirst,
+     STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo,
+     OPENSSL_CTX *libctx, const char *propq);
+ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+     unsigned char *id, int idlen, int allorfirst,
+     STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo);
  int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
  int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
  void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid,
@@ -21,13 +26,18 @@ CMS_ReceiptRequest_create0, CMS_add1_ReceiptRequest, CMS_get1_ReceiptRequest, CM
 
 =head1 DESCRIPTION
 
-CMS_ReceiptRequest_create0() creates a signed receipt request structure. The
-B<signedContentIdentifier> field is set using B<id> and B<idlen>, or it is set
-to 32 bytes of pseudo random data if B<id> is NULL. If B<receiptList> is NULL
-the allOrFirstTier option in B<receiptsFrom> is used and set to the value of
-the B<allorfirst> parameter. If B<receiptList> is not NULL the B<receiptList>
-option in B<receiptsFrom> is used. The B<receiptsTo> parameter specifies the
-B<receiptsTo> field value.
+CMS_ReceiptRequest_create0_with_libctx() creates a signed receipt request
+structure. The B<signedContentIdentifier> field is set using I<id> and I<idlen>,
+or it is set to 32 bytes of pseudo random data if I<id> is NULL.
+If I<receiptList> is NULL the allOrFirstTier option in I<receiptsFrom> is used
+and set to the value of the I<allorfirst> parameter. If I<receiptList> is not
+NULL the I<receiptList> option in I<receiptsFrom> is used. The I<receiptsTo>
+parameter specifies the I<receiptsTo> field value. The library context I<libctx>
+and the property query I<propq> are used when retrieving algorithms from providers.
+
+CMS_ReceiptRequest_create0() is similar to
+CMS_ReceiptRequest_create0_with_libctx() but uses default values of NULL for the
+library context I<libctx> and the property query I<propq>.
 
 The CMS_add1_ReceiptRequest() function adds a signed receipt request B<rr>
 to SignerInfo structure B<si>.
@@ -51,8 +61,8 @@ CMS_verify().
 
 =head1 RETURN VALUES
 
-CMS_ReceiptRequest_create0() returns a signed receipt request structure or
-NULL if an error occurred.
+CMS_ReceiptRequest_create0_with_libctx() and CMS_ReceiptRequest_create0() return
+a signed receipt request structure or NULL if an error occurred.
 
 CMS_add1_ReceiptRequest() returns 1 for success or 0 if an error occurred.
 
@@ -66,9 +76,13 @@ L<ERR_get_error(3)>, L<CMS_sign(3)>,
 L<CMS_sign_receipt(3)>, L<CMS_verify(3)>
 L<CMS_verify_receipt(3)>
 
+=head1 HISTORY
+
+The function CMS_ReceiptRequest_create0_with_libctx() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-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/CMS_sign.pod b/doc/man3/CMS_sign.pod
index cc20f8f003..cf92d35303 100644
--- a/doc/man3/CMS_sign.pod
+++ b/doc/man3/CMS_sign.pod
@@ -2,27 +2,36 @@
 
 =head1 NAME
 
-CMS_sign - create a CMS SignedData structure
+CMS_sign, CMS_sign_with_libctx - create a CMS SignedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
+ CMS_ContentInfo *CMS_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                                       STACK_OF(X509) *certs, BIO *data,
+                                       unsigned int flags,
+                                       OPENSSL_CTX *ctx, const char *propq);
  CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                            BIO *data, unsigned int flags);
 
 =head1 DESCRIPTION
 
-CMS_sign() creates and returns a CMS SignedData structure. B<signcert> is
-the certificate to sign with, B<pkey> is the corresponding private key.
-B<certs> is an optional additional set of certificates to include in the CMS
-structure (for example any intermediate CAs in the chain). Any or all of
-these parameters can be B<NULL>, see B<NOTES> below.
+CMS_sign_with_libctx() creates and returns a CMS SignedData structure.
+I<signcert> is the certificate to sign with, I<pkey> is the corresponding
+private key. I<certs> is an optional additional set of certificates to include
+in the CMS structure (for example any intermediate CAs in the chain). The
+library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers. Any or all of these parameters can be
+B<NULL>, see B<NOTES> below.
 
 The data to be signed is read from BIO B<data>.
 
 B<flags> is an optional set of flags.
 
+CMS_sign() is similar to CMS_sign_with_libctx() but uses default values of NULL
+for the library context I<libctx> and the property query I<propq>.
+
 =head1 NOTES
 
 Any of the following flags (ored together) can be passed in the B<flags>
@@ -57,7 +66,8 @@ omitted.
 If present the SMIMECapabilities attribute indicates support for the following
 algorithms in preference order: 256 bit AES, Gost R3411-94, Gost 28147-89, 192
 bit AES, 128 bit AES, triple DES, 128 bit RC2, 64 bit RC2, DES and 40 bit RC2.
-If any of these algorithms is not available then it will not be included: for example the GOST algorithms will not be included if the GOST ENGINE is
+If any of these algorithms is not available then it will not be included:
+for example the GOST algorithms will not be included if the GOST ENGINE is
 not loaded.
 
 OpenSSL will by default identify signing certificates using issuer name
@@ -105,8 +115,9 @@ Some attributes such as counter signatures are not supported.
 
 =head1 RETURN VALUES
 
-CMS_sign() returns either a valid CMS_ContentInfo structure or NULL if an error
-occurred. The error can be obtained from ERR_get_error(3).
+CMS_sign_with_libctx() and CMS_sign() return either a valid CMS_ContentInfo
+structure or NULL if an error occurred. The error can be obtained from
+ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -117,6 +128,8 @@ L<ERR_get_error(3)>, L<CMS_verify(3)>
 The B<CMS_STREAM> flag is only supported for detached data in OpenSSL 0.9.8,
 it is supported for embedded data in OpenSSL 1.0.0 and later.
 
+The CMS_sign_with_libctx() method was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_DigestSignInit.pod b/doc/man3/EVP_DigestSignInit.pod
index 69dec1c74d..923de31a31 100644
--- a/doc/man3/EVP_DigestSignInit.pod
+++ b/doc/man3/EVP_DigestSignInit.pod
@@ -2,16 +2,17 @@
 
 =head1 NAME
 
-EVP_DigestSignInit_ex, EVP_DigestSignInit, EVP_DigestSignUpdate,
+EVP_DigestSignInit_with_libctx, EVP_DigestSignInit, EVP_DigestSignUpdate,
 EVP_DigestSignFinal, EVP_DigestSign - EVP signing functions
 
 =head1 SYNOPSIS
 
  #include <openssl/evp.h>
 
- int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                           const char *mdname, const char *props,
-                           EVP_PKEY *pkey, OPENSSL_CTX *libctx);
+ int EVP_DigestSignInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                    const char *mdname,
+                                    OPENSSL_CTX *libctx, const char *props,
+                                    EVP_PKEY *pkey);
  int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
  int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
@@ -26,12 +27,12 @@ EVP_DigestSignFinal, EVP_DigestSign - EVP signing functions
 The EVP signature routines are a high-level interface to digital signatures.
 Input data is digested first before the signing takes place.
 
-EVP_DigestSignInit_ex() sets up signing context I<ctx> to use a digest with the
-name I<mdname> and private key I<pkey>. The name of the digest to be used is
-passed to the provider of the signature algorithm in use. How that provider
-interprets the digest name is provider specific. The provider may implement
-that digest directly itself or it may (optionally) choose to fetch it (which
-could result in a digest from a different provider being selected). If the
+EVP_DigestSignInit_with_libctx() sets up signing context I<ctx> to use a digest
+with the name I<mdname> and private key I<pkey>. The name of the digest to be
+used is passed to the provider of the signature algorithm in use. How that
+provider interprets the digest name is provider specific. The provider may
+implement that digest directly itself or it may (optionally) choose to fetch it
+(which could result in a digest from a different provider being selected). If the
 provider supports fetching the digest then it may use the I<props> argument for
 the properties to be used during the fetch.
 
@@ -49,18 +50,19 @@ I<pctx> is not NULL, the EVP_PKEY_CTX of the signing operation will be written
 to I<*pctx>: this can be used to set alternative signing options. Note that any
 existing value in I<*pctx> is overwritten. The EVP_PKEY_CTX value returned must
 not be freed directly by the application if I<ctx> is not assigned an
-EVP_PKEY_CTX value before being passed to EVP_DigestSignInit_ex() (which means
-the EVP_PKEY_CTX is created inside EVP_DigestSignInit_ex() and it will be freed
-automatically when the EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be used is
-created by EVP_DigestSignInit_ex then it will use the B<OPENSSL_CTX> specified
-in I<libctx> and the property query string specified in I<props>.
+EVP_PKEY_CTX value before being passed to EVP_DigestSignInit_with_libctx()
+(which means the EVP_PKEY_CTX is created inside EVP_DigestSignInit_with_libctx()
+and it will be freed automatically when the EVP_MD_CTX is freed). If the
+EVP_PKEY_CTX to be used is created by EVP_DigestSignInit_with_libctx then it
+will use the B<OPENSSL_CTX> specified in I<libctx> and the property query string
+specified in I<props>.
 
 The digest I<mdname> may be NULL if the signing algorithm supports it. The
 I<props> argument can always be NULL.
 
-No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit_ex() if the passed
-I<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>. See also
-L<SM2(7)>.
+No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit_with_libctx() if the
+passed I<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>.
+See also L<SM2(7)>.
 
 Only EVP_PKEY types that support signing can be used with these functions. This
 includes MAC algorithms where the MAC generation is considered as a form of
@@ -108,10 +110,10 @@ Will ignore any digest provided.
 
 If RSA-PSS is used and restrictions apply then the digest must match.
 
-EVP_DigestSignInit() works in the same way as EVP_DigestSignInit_ex() except
-that the I<mdname> parameter will be inferred from the supplied digest I<type>,
-and I<props> will be NULL. Where supplied the ENGINE I<e> will be used for the
-signing and digest algorithm implementations. I<e> may be NULL.
+EVP_DigestSignInit() works in the same way as EVP_DigestSignInit_with_libctx()
+except that the I<mdname> parameter will be inferred from the supplied
+digest I<type>, and I<props> will be NULL. Where supplied the ENGINE I<e> will
+be used for the signing and digest algorithm implementations. I<e> may be NULL.
 
 EVP_DigestSignUpdate() hashes I<cnt> bytes of data at I<d> into the
 signature context I<ctx>. This function can be called several times on the
@@ -182,7 +184,7 @@ L<RAND(7)>
 EVP_DigestSignInit(), EVP_DigestSignUpdate() and EVP_DigestSignFinal()
 were added in OpenSSL 1.0.0.
 
-EVP_DigestSignInit_ex() was added in OpenSSL 3.0.
+EVP_DigestSignInit_with_libctx() was added in OpenSSL 3.0.
 
 EVP_DigestSignUpdate() was converted from a macro to a function in OpenSSL 3.0.
 
diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod
index 9ea0014a5a..f0061f4548 100644
--- a/doc/man3/EVP_DigestVerifyInit.pod
+++ b/doc/man3/EVP_DigestVerifyInit.pod
@@ -2,16 +2,17 @@
 
 =head1 NAME
 
-EVP_DigestVerifyInit_ex, EVP_DigestVerifyInit, EVP_DigestVerifyUpdate,
+EVP_DigestVerifyInit_with_libctx, EVP_DigestVerifyInit, EVP_DigestVerifyUpdate,
 EVP_DigestVerifyFinal, EVP_DigestVerify - EVP signature verification functions
 
 =head1 SYNOPSIS
 
  #include <openssl/evp.h>
 
- int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                             const char *mdname, const char *props,
-                             EVP_PKEY *pkey, OPENSSL_CTX *libctx);
+ int EVP_DigestVerifyInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                      const char *mdname,
+                                      OPENSSL_CTX *libctx, const char *props,
+                                      EVP_PKEY *pkey);
  int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                           const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
  int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
@@ -25,9 +26,9 @@ EVP_DigestVerifyFinal, EVP_DigestVerify - EVP signature verification functions
 The EVP signature routines are a high-level interface to digital signatures.
 Input data is digested first before the signature verification takes place.
 
-EVP_DigestVerifyInit_ex() sets up verification context B<ctx> to use a digest
-with the name B<mdname> and public key B<pkey>. The name of the digest to be
-used is passed to the provider of the signature algorithm in use. How that
+EVP_DigestVerifyInit_with_libctx() sets up verification context B<ctx> to use a
+digest with the name B<mdname> and public key B<pkey>. The name of the digest to
+be used is passed to the provider of the signature algorithm in use. How that
 provider interprets the digest name is provider specific. The provider may
 implement that digest directly itself or it may (optionally) choose to fetch it
 (which could result in a digest from a different provider being selected). If
@@ -48,15 +49,16 @@ B<pctx> is not NULL, the EVP_PKEY_CTX of the verification operation will be
 written to B<*pctx>: this can be used to set alternative verification options.
 Note that any existing value in B<*pctx> is overwritten. The EVP_PKEY_CTX value
 returned must not be freed directly by the application if B<ctx> is not assigned
-an EVP_PKEY_CTX value before being passed to EVP_DigestVerifyInit_ex() (which
-means the EVP_PKEY_CTX is created inside EVP_DigestVerifyInit_ex() and it will
-be freed automatically when the EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be
-used is created by EVP_DigestVerifyInit_ex then it will use the B<OPENSSL_CTX>
-specified in I<libctx> and the property query string specified in I<props>.
+an EVP_PKEY_CTX value before being passed to EVP_DigestVerifyInit_with_libctx()
+(which means the EVP_PKEY_CTX is created inside
+EVP_DigestVerifyInit_with_libctx() and it will be freed automatically when the
+EVP_MD_CTX is freed). If the EVP_PKEY_CTX to be used is created by
+EVP_DigestVerifyInit_with_libctx then it will use the B<OPENSSL_CTX> specified
+in I<libctx> and the property query string specified in I<props>.
 
-No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit_ex() if the passed
-B<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>. See also
-L<SM2(7)>.
+No B<EVP_PKEY_CTX> will be created by EVP_DigestSignInit_with_libctx() if the
+passed B<ctx> has already been assigned one via L<EVP_MD_CTX_set_pkey_ctx(3)>.
+See also L<SM2(7)>.
 
 Not all digests can be used for all key types. The following combinations apply.
 
@@ -99,10 +101,11 @@ Will ignore any digest provided.
 
 If RSA-PSS is used and restrictions apply then the digest must match.
 
-EVP_DigestVerifyInit() works in the same way as EVP_DigestVerifyInit_ex() except
-that the B<mdname> parameter will be inferred from the supplied digest B<type>,
-and B<props> will be NULL. Where supplied the ENGINE B<e> will be used for the
-signature verification and digest algorithm implementations. B<e> may be NULL.
+EVP_DigestVerifyInit() works in the same way as
+EVP_DigestVerifyInit_with_libctx() except that the B<mdname> parameter will be
+inferred from the supplied digest B<type>, and B<props> will be NULL. Where
+supplied the ENGINE B<e> will be used for the signature verification and digest
+algorithm implementations. B<e> may be NULL.
 
 EVP_DigestVerifyUpdate() hashes B<cnt> bytes of data at B<d> into the
 verification context B<ctx>. This function can be called several times on the
@@ -170,7 +173,7 @@ L<RAND(7)>
 EVP_DigestVerifyInit(), EVP_DigestVerifyUpdate() and EVP_DigestVerifyFinal()
 were added in OpenSSL 1.0.0.
 
-EVP_DigestVerifyInit_ex() was added in OpenSSL 3.0.
+EVP_DigestVerifyInit_with_libctx() was added in OpenSSL 3.0.
 
 EVP_DigestVerifyUpdate() was converted from a macro to a function in OpenSSL
 3.0.
diff --git a/doc/man3/EVP_SignInit.pod b/doc/man3/EVP_SignInit.pod
index 13bba5b507..f6165f0468 100644
--- a/doc/man3/EVP_SignInit.pod
+++ b/doc/man3/EVP_SignInit.pod
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate, EVP_SignFinal
+EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate,
+EVP_SignFinal_with_libctx, EVP_SignFinal
 - EVP signing functions
 
 =head1 SYNOPSIS
@@ -11,7 +12,11 @@ EVP_SignInit, EVP_SignInit_ex, EVP_SignUpdate, EVP_SignFinal
 
  int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
  int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
- int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sig, unsigned int *s, EVP_PKEY *pkey);
+ int EVP_SignFinal_with_libctx(EVP_MD_CTX *ctx, unsigned char *md,
+                               unsigned int *s, EVP_PKEY *pkey,
+                               OPENSSL_CTX *libctx, const char *propq);
+ int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sig, unsigned int *s,
+                   EVP_PKEY *pkey);
 
  void EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type);
 
@@ -28,20 +33,25 @@ EVP_SignUpdate() hashes I<cnt> bytes of data at I<d> into the
 signature context I<ctx>. This function can be called several times on the
 same I<ctx> to include additional data.
 
-EVP_SignFinal() signs the data in I<ctx> using the private key I<pkey> and
-places the signature in I<sig>. I<sig> must be at least C<EVP_PKEY_size(pkey)>
-bytes in size. I<s> is an OUT parameter, and not used as an IN parameter.
+EVP_SignFinal_with_libctx() signs the data in I<ctx> using the private key
+I<pkey> and places the signature in I<sig>. The library context I<libctx> and
+property query I<propq> are used when creating a context to use with the key
+I<pkey>. I<sig> must be at least C<EVP_PKEY_size(pkey)> bytes in size. I<s> is
+an OUT parameter, and not used as an IN parameter.
 The number of bytes of data written (i.e. the length of the signature)
 will be written to the integer at I<s>, at most C<EVP_PKEY_size(pkey)> bytes
 will be written.
 
+EVP_SignFinal() is similar to EVP_SignFinal_with_libctx() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
 EVP_SignInit() initializes a signing context I<ctx> to use the default
 implementation of digest I<type>.
 
 =head1 RETURN VALUES
 
-EVP_SignInit_ex(), EVP_SignUpdate() and EVP_SignFinal() return 1
-for success and 0 for failure.
+EVP_SignInit_ex(), EVP_SignUpdate(), EVP_SignFinal_with_libctx() and
+EVP_SignFinal() return 1 for success and 0 for failure.
 
 The error codes can be obtained by L<ERR_get_error(3)>.
 
@@ -87,6 +97,10 @@ L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
 L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
 L<SHA1(3)>, L<openssl-dgst(1)>
 
+=head1 HISTORY
+
+The function EVP_SignFinal_with_libctx() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_VerifyInit.pod b/doc/man3/EVP_VerifyInit.pod
index 3686980b2f..be5332a55d 100644
--- a/doc/man3/EVP_VerifyInit.pod
+++ b/doc/man3/EVP_VerifyInit.pod
@@ -3,7 +3,7 @@
 =head1 NAME
 
 EVP_VerifyInit_ex,
-EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
+EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal_with_libctx, EVP_VerifyFinal
 - EVP signature verification functions
 
 =head1 SYNOPSIS
@@ -12,6 +12,9 @@ EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
 
  int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
  int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
+ int EVP_VerifyFinal_with_libctx(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+                                 unsigned int siglen, EVP_PKEY *pkey,
+                                 OPENSSL_CTX *libctx, const char *propq);
  int EVP_VerifyFinal(EVP_MD_CTX *ctx, unsigned char *sigbuf, unsigned int siglen,
                      EVP_PKEY *pkey);
 
@@ -22,27 +25,32 @@ EVP_VerifyInit, EVP_VerifyUpdate, EVP_VerifyFinal
 The EVP signature verification routines are a high-level interface to digital
 signatures.
 
-EVP_VerifyInit_ex() sets up verification context B<ctx> to use digest
-B<type> from ENGINE B<impl>. B<ctx> must be created by calling
+EVP_VerifyInit_ex() sets up verification context I<ctx> to use digest
+I<type> from ENGINE I<impl>. I<ctx> must be created by calling
 EVP_MD_CTX_new() before calling this function.
 
-EVP_VerifyUpdate() hashes B<cnt> bytes of data at B<d> into the
-verification context B<ctx>. This function can be called several times on the
-same B<ctx> to include additional data.
+EVP_VerifyUpdate() hashes I<cnt> bytes of data at I<d> into the
+verification context I<ctx>. This function can be called several times on the
+same I<ctx> to include additional data.
 
-EVP_VerifyFinal() verifies the data in B<ctx> using the public key B<pkey>
-and against the B<siglen> bytes at B<sigbuf>.
+EVP_VerifyFinal_with_libctx() verifies the data in I<ctx> using the public key
+I<pkey> and I<siglen> bytes in I<sigbuf>.
+The library context I<libctx> and property query I<propq> are used when creating
+a context to use with the key I<pkey>.
 
-EVP_VerifyInit() initializes verification context B<ctx> to use the default
-implementation of digest B<type>.
+EVP_VerifyFinal() is similar to EVP_VerifyFinal_with_libctx() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
+EVP_VerifyInit() initializes verification context I<ctx> to use the default
+implementation of digest I<type>.
 
 =head1 RETURN VALUES
 
 EVP_VerifyInit_ex() and EVP_VerifyUpdate() return 1 for success and 0 for
 failure.
 
-EVP_VerifyFinal() returns 1 for a correct signature, 0 for failure and -1 if some
-other error occurred.
+EVP_VerifyFinal()_with_libctx() and EVP_VerifyFinal() return 1 for a correct
+signature, 0 for failure and -1 if some other error occurred.
 
 The error codes can be obtained by L<ERR_get_error(3)>.
 
@@ -83,6 +91,10 @@ L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
 L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
 L<SHA1(3)>, L<openssl-dgst(1)>
 
+head1 HISTORY
+
+The function EVP_VerifyFinal_with_libctx() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/PKCS7_encrypt.pod b/doc/man3/PKCS7_encrypt.pod
index b2d07e8e15..36d638c8c6 100644
--- a/doc/man3/PKCS7_encrypt.pod
+++ b/doc/man3/PKCS7_encrypt.pod
@@ -2,20 +2,26 @@
 
 =head1 NAME
 
-PKCS7_encrypt - create a PKCS#7 envelopedData structure
+PKCS7_encrypt_with_libctx, PKCS7_encrypt
+- create a PKCS#7 envelopedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ PKCS7 *PKCS7_encrypt_with_libctx(STACK_OF(X509) *certs, BIO *in,
+                                  const EVP_CIPHER *cipher, int flags,
+                                  OPENSSL_CTX *libctx, const char *propq);
  PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
                       int flags);
 
 =head1 DESCRIPTION
 
-PKCS7_encrypt() creates and returns a PKCS#7 envelopedData structure. B<certs>
-is a list of recipient certificates. B<in> is the content to be encrypted.
-B<cipher> is the symmetric cipher to use. B<flags> is an optional set of flags.
+PKCS7_encrypt_with_libctx() creates and returns a PKCS#7 envelopedData structure.
+I<certs> is a list of recipient certificates. I<in> is the content to be
+encrypted. I<cipher> is the symmetric cipher to use. I<flags> is an optional set
+of flags. The library context I<libctx> and the property query I<propq> are used
+when retrieving algorithms from providers.
 
 Only RSA keys are supported in PKCS#7 and envelopedData so the recipient
 certificates supplied to this function must all contain RSA public keys, though
@@ -60,10 +66,13 @@ PEM_write_bio_PKCS7_stream() finalize the structure. Alternatively finalization
 can be performed by obtaining the streaming ASN1 B<BIO> directly using
 BIO_new_PKCS7().
 
+PKCS7_encrypt() is similar to PKCS7_encrypt_with_libctx() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
 =head1 RETURN VALUES
 
-PKCS7_encrypt() returns either a PKCS7 structure or NULL if an error occurred.
-The error can be obtained from ERR_get_error(3).
+PKCS7_encrypt_with_libctx() and PKCS7_encrypt() return either a PKCS7 structure
+or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -71,11 +80,13 @@ L<ERR_get_error(3)>, L<PKCS7_decrypt(3)>
 
 =head1 HISTORY
 
+The function PKCS7_encrypt_with_libctx() was added in OpenSSL 3.0.
+
 The B<PKCS7_STREAM> flag was added in OpenSSL 1.0.0.
 
 =head1 COPYRIGHT
 
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-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/PKCS7_sign.pod b/doc/man3/PKCS7_sign.pod
index f53e7b4c17..c5d6fd73c3 100644
--- a/doc/man3/PKCS7_sign.pod
+++ b/doc/man3/PKCS7_sign.pod
@@ -2,21 +2,27 @@
 
 =head1 NAME
 
-PKCS7_sign - create a PKCS#7 signedData structure
+PKCS7_sign_with_libctx, PKCS7_sign
+- create a PKCS#7 signedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ PKCS7 *PKCS7_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                               STACK_OF(X509) *certs, BIO *data, int flags,
+                               OPENSSL_CTX *libctx, const char *propq);
  PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                    BIO *data, int flags);
 
 =head1 DESCRIPTION
 
-PKCS7_sign() creates and returns a PKCS#7 signedData structure. B<signcert> is
-the certificate to sign with, B<pkey> is the corresponding private key.
-B<certs> is an optional additional set of certificates to include in the PKCS#7
-structure (for example any intermediate CAs in the chain).
+PKCS7_sign_with_libctx() creates and returns a PKCS#7 signedData structure.
+I<igncert> is the certificate to sign with, Ipkey> is the corresponding
+private key. I<certs> is an optional additional set of certificates to include
+in the PKCS#7 structure (for example any intermediate CAs in the chain). The
+library context I<libctx> and property query I<propq> are used when
+retrieving algorithms from providers.
 
 The data to be signed is read from BIO B<data>.
 
@@ -88,14 +94,17 @@ PKCS#7 structure is output.
 In versions of OpenSSL before 1.0.0 the B<signcert> and B<pkey> parameters must
 B<NOT> be NULL.
 
+PKCS7_sign() is similar to PKCS7_sign_with_libctx() but uses default values of
+NULL for the library context I<libctx> and the property query I<propq>.
+
 =head1 BUGS
 
 Some advanced attributes such as counter signatures are not supported.
 
 =head1 RETURN VALUES
 
-PKCS7_sign() returns either a valid PKCS7 structure or NULL if an error
-occurred.  The error can be obtained from ERR_get_error(3).
+PKCS7_sign_with_libctx() and PKCS7_sign() return either a valid PKCS7 structure
+or NULL if an error occurred.  The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -103,6 +112,8 @@ L<ERR_get_error(3)>, L<PKCS7_verify(3)>
 
 =head1 HISTORY
 
+The function PKCS7_sign_with_libctx() was added in OpenSSL 3.0.
+
 The B<PKCS7_PARTIAL> flag, and the ability for B<certs>, B<signcert>,
 and B<pkey> parameters to be B<NULL> were added in OpenSSL 1.0.0.
 
diff --git a/doc/man3/SMIME_read_ASN1.pod b/doc/man3/SMIME_read_ASN1.pod
new file mode 100644
index 0000000000..5b995f1aee
--- /dev/null
+++ b/doc/man3/SMIME_read_ASN1.pod
@@ -0,0 +1,77 @@
+=pod
+
+=head1 NAME
+
+SMIME_read_ASN1_ex, SMIME_read_ASN1
+- parse S/MIME message
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ ASN1_VALUE *SMIME_read_ASN1_ex(BIO *in, BIO **bcont, const ASN1_ITEM *it,
+                                ASN1_VALUE **x);
+ ASN1_VALUE *SMIME_read_ASN1(BIO *in, BIO **bcont, const ASN1_ITEM *it);
+
+=head1 DESCRIPTION
+
+SMIME_read_ASN1_ex() parses a message in S/MIME format.
+
+I<in> is a BIO to read the message from. I<x> can be used to optionally supply
+a previously created I<it> ASN1_VALUE object (such as CMS_ContentInfo or PKCS7),
+it can be set to NULL. Valid values that can be used by ASN.1 structure I<it>
+are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo).
+
+If cleartext signing is used then the content is saved in a memory bio which is
+written to I<*bcont>, otherwise I<*bcont> is set to NULL.
+
+The parsed ASN1_VALUE structure is returned or NULL if an error occurred.
+
+SMIME_read_ASN1() is similar to SMIME_read_ASN1_ex() but sets the value of I<x>
+to NULL.
+
+=head1 NOTES
+
+The higher level functions L<SMIME_read_CMS_ex(3)> and
+L<SMIME_read_PKCS7_ex(3)> should be used instead of SMIME_read_ASN1_ex().
+
+To support future functionality if I<bcont> is not NULL I<*bcont> should be
+initialized to NULL.
+
+=head1 BUGS
+
+The MIME parser used by SMIME_read_ASN1_ex() is somewhat primitive. While it will
+handle most S/MIME messages more complex compound formats may not work.
+
+The use of a memory BIO to hold the signed content limits the size of message
+which can be processed due to memory restraints: a streaming single pass option
+should be available.
+
+=head1 RETURN VALUES
+
+SMIME_read_ASN1_ex() and SMIME_read_ASN1() return a valid B<ASN1_VALUE>
+structure or B<NULL> if an error occurred. The error can be obtained from
+ERR_get_error(3).
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>,
+L<SMIME_read_CMS_ex(3)>,
+L<SMIME_read_PKCS7_ex(3)>,
+L<SMIME_write_ASN1(3)>,
+L<SMIME_write_ASN1_with_libctx(3)>
+
+=head1 HISTORY
+
+The function SMIME_read_ASN1_ex() was 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/SMIME_read_CMS.pod b/doc/man3/SMIME_read_CMS.pod
index 136bfd8f0a..c7ca845eee 100644
--- a/doc/man3/SMIME_read_CMS.pod
+++ b/doc/man3/SMIME_read_CMS.pod
@@ -2,12 +2,14 @@
 
 =head1 NAME
 
-SMIME_read_CMS - parse S/MIME message
+SMIME_read_CMS_ex, SMIME_read_CMS - parse S/MIME message
 
 =head1 SYNOPSIS
 
  #include <openssl/cms.h>
 
+ CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, BIO **bcont,
+                                    CMS_ContentInfo **cms);
  CMS_ContentInfo *SMIME_read_CMS(BIO *in, BIO **bcont);
 
 =head1 DESCRIPTION
@@ -22,6 +24,11 @@ written to B<*bcont>, otherwise B<*bcont> is set to NULL.
 The parsed CMS_ContentInfo structure is returned or NULL if an
 error occurred.
 
+SMIME_read_CMS_ex() is similar to SMIME_read_CMS() but can optionally supply a
+previously created I<cms> CMS_ContentInfo object. If I<cms> is NULL then it is
+identical to SMIME_read_CMS().
+To create a I<cms> object use L<CMS_ContentInfo_new_with_libctx(3)>.
+
 =head1 NOTES
 
 If B<*bcont> is not NULL then the message is clear text signed. B<*bcont> can
@@ -53,16 +60,22 @@ should be available.
 
 =head1 RETURN VALUES
 
-SMIME_read_CMS() returns a valid B<CMS_ContentInfo> structure or B<NULL>
-if an error occurred. The error can be obtained from ERR_get_error(3).
+SMIME_read_CMS_ex() and SMIME_read_CMS() return a valid B<CMS_ContentInfo>
+structure or B<NULL> if an error occurred. The error can be obtained from
+ERR_get_error(3).
 
 =head1 SEE ALSO
 
 L<ERR_get_error(3)>,
-L<SMIME_read_CMS(3)>, L<CMS_sign(3)>,
-L<CMS_verify(3)>, L<CMS_encrypt(3)>,
+L<CMS_sign(3)>,
+L<CMS_verify(3)>,
+L<CMS_encrypt(3)>,
 L<CMS_decrypt(3)>
 
+=head1 HISTORY
+
+The function SMIME_read_CMS_ex() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2008-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/SMIME_read_PKCS7.pod b/doc/man3/SMIME_read_PKCS7.pod
index 4b03f641e3..791c49ff75 100644
--- a/doc/man3/SMIME_read_PKCS7.pod
+++ b/doc/man3/SMIME_read_PKCS7.pod
@@ -2,12 +2,13 @@
 
 =head1 NAME
 
-SMIME_read_PKCS7 - parse S/MIME message
+SMIME_read_PKCS7_ex, SMIME_read_PKCS7 - parse S/MIME message
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
  PKCS7 *SMIME_read_PKCS7(BIO *in, BIO **bcont);
 
 =head1 DESCRIPTION
@@ -23,6 +24,11 @@ B<*bcont> is set to B<NULL>.
 The parsed PKCS#7 structure is returned or B<NULL> if an
 error occurred.
 
+SMIME_read_PKCS7_ex() is similar to SMIME_read_PKCS7() but can optionally supply
+a previously created I<p7> PKCS#7 object. If I<p7> is NULL then it is identical
+to SMIME_read_PKCS7().
+To create a I<p7> object use L<PKCS7_new_with_libctx(3)>.
+
 =head1 NOTES
 
 If B<*bcont> is not B<NULL> then the message is clear text
@@ -56,8 +62,8 @@ streaming single pass option should be available.
 
 =head1 RETURN VALUES
 
-SMIME_read_PKCS7() returns a valid B<PKCS7> structure or B<NULL>
-if an error occurred. The error can be obtained from ERR_get_error(3).
+SMIME_read_PKCS7_ex() and SMIME_read_PKCS7() return a valid B<PKCS7> structure
+or B<NULL> if an error occurred. The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -66,9 +72,13 @@ L<SMIME_read_PKCS7(3)>, L<PKCS7_sign(3)>,
 L<PKCS7_verify(3)>, L<PKCS7_encrypt(3)>
 L<PKCS7_decrypt(3)>
 
+=head1 HISTORY
+
+The function SMIME_read_PKCS7_ex() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-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/SMIME_write_ASN1.pod b/doc/man3/SMIME_write_ASN1.pod
new file mode 100644
index 0000000000..5f46ce1b45
--- /dev/null
+++ b/doc/man3/SMIME_write_ASN1.pod
@@ -0,0 +1,82 @@
+=pod
+
+=head1 NAME
+
+SMIME_write_ASN1_with_libctx, SMIME_write_ASN1
+- convert structure to S/MIME format
+
+=head1 SYNOPSIS
+
+ #include <openssl/asn1.h>
+
+ int SMIME_write_ASN1_with_libctx(BIO *out,
+     ASN1_VALUE *val, BIO *data, int flags, int ctype_nid, int econt_nid,
+     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it,
+     OPENSSL_CTX *libctx, const char *propq);
+
+ int SMIME_write_ASN1(BIO *out,
+     ASN1_VALUE *val, BIO *data, int flags, int ctype_nid, int econt_nid,
+     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
+
+=head1 DESCRIPTION
+
+SMIME_write_ASN1_with_libctx() adds the appropriate MIME headers to an object
+structure to produce an S/MIME message.
+
+I<out> is the BIO to write the data to. I<value> is the appropriate ASN1_VALUE
+structure (either CMS_ContentInfo or PKCS7). If streaming is enabled then the
+content must be supplied via I<data>.
+I<flags> is an optional set of flags. I<ctype_nid> is the NID of the content
+type, I<econt_nid> is the NID of the embedded content type and I<mdalgs> is a
+list of signed data digestAlgorithms. Valid values that can be used by the
+ASN.1 structure I<it> are ASN1_ITEM_rptr(PKCS7) or ASN1_ITEM_rptr(CMS_ContentInfo).
+The library context I<libctx> and the property query I<propq> are used when
+retrieving algorithms from providers.
+
+=head1 NOTES
+
+The higher level functions L<SMIME_write_CMS(3)> and
+L<SMIME_write_PKCS7(3)> should be used instead of SMIME_write_ASN1().
+
+The following flags can be passed in the B<flags> parameter.
+
+If B<CMS_DETACHED> is set then cleartext signing will be used, this option only
+makes sense for SignedData where B<CMS_DETACHED> is also set when the sign()
+method is called.
+
+If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are added to
+the content, this only makes sense if B<CMS_DETACHED> is also set.
+
+If the B<CMS_STREAM> flag is set streaming is performed. This flag should only
+be set if B<CMS_STREAM> was also set in the previous call to a CMS_ContentInfo
+or PKCS7 creation function.
+
+If cleartext signing is being used and B<CMS_STREAM> not set then the data must
+be read twice: once to compute the signature in sign method and once to output
+the S/MIME message.
+
+If streaming is performed the content is output in BER format using indefinite
+length constructed encoding except in the case of signed data with detached
+content where the content is absent and DER format is used.
+
+=head1 RETURN VALUES
+
+SMIME_write_ASN1_with_libctx() and SMIME_write_ASN1() return 1 for success or
+0 for failure.
+
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>,
+L<SMIME_write_CMS(3)>,
+L<SMIME_write_PKCS7(3)>
+
+=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/X509_dup.pod b/doc/man3/X509_dup.pod
index 18ba40cee6..76b77c1195 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -29,6 +29,7 @@ CERTIFICATEPOLICIES_free,
 CERTIFICATEPOLICIES_new,
 CMS_ContentInfo_free,
 CMS_ContentInfo_new,
+CMS_ContentInfo_new_with_libctx,
 CMS_ContentInfo_print_ctx,
 CMS_ReceiptRequest_free,
 CMS_ReceiptRequest_new,
@@ -201,6 +202,7 @@ PKCS7_SIGN_ENVELOPE_free,
 PKCS7_SIGN_ENVELOPE_new,
 PKCS7_dup,
 PKCS7_free,
+PKCS7_new_with_libctx,
 PKCS7_new,
 PKCS7_print_ctx,
 PKCS8_PRIV_KEY_INFO_free,
@@ -335,6 +337,10 @@ to generate the function bodies.
 B<I<TYPE>_new>() allocates an empty object of the indicated type.
 The object returned must be released by calling B<I<TYPE>_free>().
 
+B<I<TYPE>_new_with_libctx>() is similiar to B<I<TYPE>_new>() but also passes the
+library context I<libctx> and the property query I<propq> to use when retrieving
+algorithms from providers.
+
 B<I<TYPE>_dup>() copies an existing object, leaving it untouched.
 
 B<I<TYPE>_free>() releases the object and all pointers and sub-objects
@@ -348,11 +354,16 @@ user-defined, then pass in any I<pctx> down to any nested calls.
 
 =head1 RETURN VALUES
 
-B<I<TYPE>_new>() and B<I<TYPE>_dup>() return a pointer to the object or NULL on
-failure.
+B<I<TYPE>_new>(), B<I<TYPE>_new_ex>() and B<I<TYPE>_dup>() return a pointer to
+the object or NULL on failure.
 
 B<I<TYPE>_print_ctx>() returns 1 on success or zero on failure.
 
+=head1 HISTORY
+
+The functions PKCS7_new_with_libctx() and CMS_ContentInfo_new_with_libctx() were
+added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
new file mode 100644
index 0000000000..60e01e5c39
--- /dev/null
+++ b/include/crypto/pkcs7.h
@@ -0,0 +1,10 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+void pkcs7_resolve_libctx(PKCS7 *p7);
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 71a67df650..712aa1cc86 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -299,6 +299,7 @@ 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);
+int x509_set0_libctx(X509 *x, OPENSSL_CTX *libctx, const char *propq);
 
 void x509_init_sig_info(X509 *x);
 
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index c9917492d5..a62d4d7755 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -845,7 +845,14 @@ int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
 int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
                      int ctype_nid, int econt_nid,
                      STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it);
+int SMIME_write_ASN1_with_libctx(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+                                 int ctype_nid, int econt_nid,
+                                 STACK_OF(X509_ALGOR) *mdalgs,
+                                 const ASN1_ITEM *it,
+                                 OPENSSL_CTX *libctx, const char *propq);
 ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1_ex(BIO *bio, BIO **bcont, const ASN1_ITEM *it,
+                               ASN1_VALUE **x);
 int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
 int SMIME_text(BIO *in, BIO *out);
 
diff --git a/include/openssl/cms.h b/include/openssl/cms.h
index a0f4b6a0ec..7397008fcb 100644
--- a/include/openssl/cms.h
+++ b/include/openssl/cms.h
@@ -45,6 +45,9 @@ DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
 DECLARE_ASN1_FUNCTIONS(CMS_ReceiptRequest)
 DECLARE_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
 
+CMS_ContentInfo *CMS_ContentInfo_new_with_libctx(OPENSSL_CTX *libctx,
+                                                 const char *propq);
+
 # define CMS_SIGNERINFO_ISSUER_SERIAL    0
 # define CMS_SIGNERINFO_KEYIDENTIFIER    1
 
@@ -104,6 +107,7 @@ int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags);
 int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in,
                              int flags);
 CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont);
+CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, BIO **bcont, CMS_ContentInfo **ci);
 int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags);
 
 int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
@@ -112,6 +116,10 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont,
 CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey,
                           STACK_OF(X509) *certs, BIO *data,
                           unsigned int flags);
+CMS_ContentInfo *CMS_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                                      STACK_OF(X509) *certs, BIO *data,
+                                      unsigned int flags,
+                                      OPENSSL_CTX *ctx, const char *propq);
 
 CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
                                   X509 *signcert, EVP_PKEY *pkey,
@@ -119,11 +127,18 @@ CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si,
 
 int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags);
 CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags);
+CMS_ContentInfo *CMS_data_create_with_libctx(BIO *in, unsigned int flags,
+                                             OPENSSL_CTX *ctx,
+                                             const char *propq);
 
 int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out,
                       unsigned int flags);
 CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md,
                                    unsigned int flags);
+CMS_ContentInfo *CMS_digest_create_with_libctx(BIO *in, const EVP_MD *md,
+                                               unsigned int flags,
+                                               OPENSSL_CTX *ctx,
+                                               const char *propq);
 
 int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
                               const unsigned char *key, size_t keylen,
@@ -132,6 +147,13 @@ int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms,
 CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
                                            const unsigned char *key,
                                            size_t keylen, unsigned int flags);
+CMS_ContentInfo *CMS_EncryptedData_encrypt_with_libctx(BIO *in,
+                                                       const EVP_CIPHER *cipher,
+                                                       const unsigned char *key,
+                                                       size_t keylen,
+                                                       unsigned int flags,
+                                                       OPENSSL_CTX *ctx,
+                                                       const char *propq);
 
 int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
                                const unsigned char *key, size_t keylen);
@@ -147,12 +169,17 @@ STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
 
 CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in,
                              const EVP_CIPHER *cipher, unsigned int flags);
+CMS_ContentInfo *CMS_encrypt_with_libctx(STACK_OF(X509) *certs,
+                                         BIO *in, const EVP_CIPHER *cipher,
+                                         unsigned int flags,
+                                         OPENSSL_CTX *ctx, const char *propq);
 
 int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert,
                 BIO *dcont, BIO *out, unsigned int flags);
 
 int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert);
-int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, X509 *peer);
+int CMS_decrypt_set1_pkey_and_peer(CMS_ContentInfo *cms, EVP_PKEY *pk,
+                                   X509 *cert, X509 *peer);
 int CMS_decrypt_set1_key(CMS_ContentInfo *cms,
                          unsigned char *key, size_t keylen,
                          const unsigned char *id, size_t idlen);
@@ -163,6 +190,10 @@ STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms);
 int CMS_RecipientInfo_type(CMS_RecipientInfo *ri);
 EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri);
 CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher);
+CMS_ContentInfo *CMS_EnvelopedData_create_with_libctx(const EVP_CIPHER *cipher,
+                                                      OPENSSL_CTX *ctx,
+                                                      const char *propq);
+
 CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms,
                                            X509 *recip, unsigned int flags);
 CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
@@ -297,11 +328,16 @@ void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid,
                                     int lastpos, int type);
 
 int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr);
-CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
-                                               int allorfirst,
-                                               STACK_OF(GENERAL_NAMES)
-                                               *receiptList, STACK_OF(GENERAL_NAMES)
-                                               *receiptsTo);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
+    unsigned char *id, int idlen, int allorfirst,
+    STACK_OF(GENERAL_NAMES) *receiptList,
+    STACK_OF(GENERAL_NAMES) *receiptsTo);
+CMS_ReceiptRequest *CMS_ReceiptRequest_create0_with_libctx(
+    unsigned char *id, int idlen, int allorfirst,
+    STACK_OF(GENERAL_NAMES) *receiptList,
+    STACK_OF(GENERAL_NAMES) *receiptsTo,
+    OPENSSL_CTX *ctx, const char *propq);
+
 int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr);
 void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
                                     ASN1_STRING **pcid,
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 0d21c035fe..6ff1e5602e 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -637,6 +637,7 @@ __owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md,
 
 __owur EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
                             const char *properties);
+
 int EVP_MD_up_ref(EVP_MD *md);
 void EVP_MD_free(EVP_MD *md);
 
@@ -697,6 +698,9 @@ __owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
 
 __owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
                          EVP_PKEY *pkey);
+__owur int EVP_SignFinal_with_libctx(EVP_MD_CTX *ctx, unsigned char *md,
+                                     unsigned int *s, EVP_PKEY *pkey,
+                                     OPENSSL_CTX *libctx, const char *propq);
 
 __owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
                           size_t *siglen, const unsigned char *tbs,
@@ -704,14 +708,19 @@ __owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
 
 __owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
                            unsigned int siglen, EVP_PKEY *pkey);
+__owur int EVP_VerifyFinal_with_libctx(EVP_MD_CTX *ctx,
+                                       const unsigned char *sigbuf,
+                                       unsigned int siglen, EVP_PKEY *pkey,
+                                       OPENSSL_CTX *libctx, const char *propq);
 
 __owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
                             size_t siglen, const unsigned char *tbs,
                             size_t tbslen);
 
-int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                          const char *mdname, const char *props, EVP_PKEY *pkey,
-                          OPENSSL_CTX *libctx);
+int EVP_DigestSignInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                   const char *mdname,
+                                   OPENSSL_CTX *libctx, const char *props,
+                                   EVP_PKEY *pkey);
 /*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                                   const EVP_MD *type, ENGINE *e,
                                   EVP_PKEY *pkey);
@@ -719,9 +728,10 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize);
 __owur int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                                size_t *siglen);
 
-int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
-                            const char *mdname, const char *props,
-                            EVP_PKEY *pkey, OPENSSL_CTX *libctx);
+int EVP_DigestVerifyInit_with_libctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
+                                     const char *mdname,
+                                     OPENSSL_CTX *libctx, const char *props,
+                                     EVP_PKEY *pkey);
 __owur int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                                 const EVP_MD *type, ENGINE *e,
                                 EVP_PKEY *pkey);
diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h
index 0e1c50032f..f4b75cca36 100644
--- a/include/openssl/pkcs7.h
+++ b/include/openssl/pkcs7.h
@@ -36,6 +36,11 @@ Digest_Encryption_ID    rsaEncryption
 Key_Encryption_ID       rsaEncryption
 */
 
+typedef struct PKCS7_CTX_st {
+    OPENSSL_CTX *libctx;
+    char *propq;
+} PKCS7_CTX;
+
 typedef struct pkcs7_issuer_and_serial_st {
     X509_NAME *issuer;
     ASN1_INTEGER *serial;
@@ -51,6 +56,7 @@ typedef struct pkcs7_signer_info_st {
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
+    const PKCS7_CTX *ctx;
 } PKCS7_SIGNER_INFO;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
 
@@ -60,6 +66,7 @@ typedef struct pkcs7_recip_info_st {
     X509_ALGOR *key_enc_algor;
     ASN1_OCTET_STRING *enc_key;
     X509 *cert;                 /* get the pub-key from this */
+    const PKCS7_CTX *ctx;
 } PKCS7_RECIP_INFO;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7_RECIP_INFO)
 
@@ -82,6 +89,7 @@ typedef struct pkcs7_enc_content_st {
     X509_ALGOR *algorithm;
     ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
     const EVP_CIPHER *cipher;
+    const PKCS7_CTX *ctx;
 } PKCS7_ENC_CONTENT;
 
 typedef struct pkcs7_enveloped_st {
@@ -147,6 +155,7 @@ typedef struct pkcs7_st {
         /* Anything else */
         ASN1_TYPE *other;
     } d;
+    PKCS7_CTX ctx;
 } PKCS7;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7)
 
@@ -231,6 +240,7 @@ DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
 DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
 DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
 DECLARE_ASN1_FUNCTIONS(PKCS7)
+PKCS7 *PKCS7_new_with_libctx(OPENSSL_CTX *libctx, const char *propq);
 
 DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
 DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
@@ -289,6 +299,9 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
 
 PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                   BIO *data, int flags);
+PKCS7 *PKCS7_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey,
+                              STACK_OF(X509) *certs, BIO *data, int flags,
+                              OPENSSL_CTX *libctx, const char *propq);
 
 PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7,
                                          X509 *signcert, EVP_PKEY *pkey,
@@ -301,6 +314,9 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
                                    int flags);
 PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
                      int flags);
+PKCS7 *PKCS7_encrypt_with_libctx(STACK_OF(X509) *certs, BIO *in,
+                                 const EVP_CIPHER *cipher, int flags,
+                                 OPENSSL_CTX *libctx, const char *propq);
 int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data,
                   int flags);
 
@@ -315,6 +331,7 @@ int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
                              const unsigned char *md, int mdlen);
 
 int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
 PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
 
 BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7);
diff --git a/providers/implementations/exchange/ecdh_exch.c b/providers/implementations/exchange/ecdh_exch.c
index 08fb0cf224..a93f67b0b5 100644
--- a/providers/implementations/exchange/ecdh_exch.c
+++ b/providers/implementations/exchange/ecdh_exch.c
@@ -458,7 +458,6 @@ int ecdh_plain_derive(void *vpecdhctx, unsigned char *secret,
     return ret;
 }
 
-#ifndef FIPS_MODULE
 static ossl_inline
 int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
                           size_t *psecretlen, size_t outlen)
@@ -499,7 +498,6 @@ int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
     OPENSSL_secure_clear_free(stmp, stmplen);
     return ret;
 }
-#endif /* FIPS_MODULE */
 
 static
 int ecdh_derive(void *vpecdhctx, unsigned char *secret,
@@ -510,15 +508,11 @@ int ecdh_derive(void *vpecdhctx, unsigned char *secret,
     switch (pecdhctx->kdf_type) {
         case PROV_ECDH_KDF_NONE:
             return ecdh_plain_derive(vpecdhctx, secret, psecretlen, outlen);
-#ifndef FIPS_MODULE
         case PROV_ECDH_KDF_X9_63:
             return ecdh_X9_63_kdf_derive(vpecdhctx, secret, psecretlen, outlen);
-
-#endif /* FIPS_MODULE */
         default:
             break;
     }
-
     return 0;
 }
 
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 9086348618..1a8e3cf829 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1610,8 +1610,9 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
         binderout = tmpbinder;
 
     bindersize = hashsize;
-    if (EVP_DigestSignInit_ex(mctx, NULL, EVP_MD_name(md), s->ctx->propq,
-                              mackey, s->ctx->libctx) <= 0
+    if (EVP_DigestSignInit_with_libctx(mctx, NULL, EVP_MD_name(md),
+                                       s->ctx->libctx, s->ctx->propq,
+                                       mackey) <= 0
             || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
             || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
             || bindersize != hashsize) {
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 27ddef9aaf..3eeafef828 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -784,8 +784,8 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
     }
 
     hmaclen = SHA256_DIGEST_LENGTH;
-    if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->propq, pkey,
-                              s->ctx->libctx) <= 0
+    if (EVP_DigestSignInit_with_libctx(hctx, NULL, "SHA2-256",
+                                       s->ctx->libctx, s->ctx->propq, pkey) <= 0
             || EVP_DigestSign(hctx, hmac, &hmaclen, data,
                               rawlen - SHA256_DIGEST_LENGTH) <= 0
             || hmaclen != SHA256_DIGEST_LENGTH) {
@@ -1873,8 +1873,9 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
         goto err;
     }
 
-    if (EVP_DigestSignInit_ex(hctx, NULL, "SHA2-256", s->ctx->propq, pkey,
-                              s->ctx->libctx) <= 0
+    if (EVP_DigestSignInit_with_libctx(hctx, NULL, "SHA2-256",
+                                       s->ctx->libctx, s->ctx->propq,
+                                       pkey) <= 0
             || EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
                               totcookielen) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 4cd85ef609..ff48759436 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -2377,9 +2377,10 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
             goto err;
         }
 
-        if (EVP_DigestVerifyInit_ex(md_ctx, &pctx,
-                                    md == NULL ? NULL : EVP_MD_name(md),
-                                    s->ctx->propq, pkey, s->ctx->libctx) <= 0) {
+        if (EVP_DigestVerifyInit_with_libctx(md_ctx, &pctx,
+                                             md == NULL ? NULL : EVP_MD_name(md),
+                                             s->ctx->libctx, s->ctx->propq,
+                                             pkey) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
                      ERR_R_EVP_LIB);
             goto err;
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index d8aab20e92..39ec4a92fd 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -277,9 +277,10 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
         goto err;
     }
 
-    if (EVP_DigestSignInit_ex(mctx, &pctx,
-                              md == NULL ? NULL : EVP_MD_name(md),
-                              s->ctx->propq, pkey, s->ctx->libctx) <= 0) {
+    if (EVP_DigestSignInit_with_libctx(mctx, &pctx,
+                                       md == NULL ? NULL : EVP_MD_name(md),
+                                       s->ctx->libctx, s->ctx->propq,
+                                       pkey) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
                  ERR_R_EVP_LIB);
         goto err;
@@ -472,9 +473,10 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
     OSSL_TRACE1(TLS, "Using client verify alg %s\n",
                 md == NULL ? "n/a" : EVP_MD_name(md));
 
-    if (EVP_DigestVerifyInit_ex(mctx, &pctx,
-                                md == NULL ? NULL : EVP_MD_name(md),
-                                s->ctx->propq, pkey, s->ctx->libctx) <= 0) {
+    if (EVP_DigestVerifyInit_with_libctx(mctx, &pctx,
+                                         md == NULL ? NULL : EVP_MD_name(md),
+                                         s->ctx->libctx, s->ctx->propq,
+                                         pkey) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
                  ERR_R_EVP_LIB);
         goto err;
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index b329e89379..c46254c858 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -2807,9 +2807,10 @@ int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
             goto err;
         }
 
-        if (EVP_DigestSignInit_ex(md_ctx, &pctx,
-                                  md == NULL ? NULL : EVP_MD_name(md),
-                                  s->ctx->propq, pkey, s->ctx->libctx) <= 0) {
+        if (EVP_DigestSignInit_with_libctx(md_ctx, &pctx,
+                                           md == NULL ? NULL : EVP_MD_name(md),
+                                           s->ctx->libctx, s->ctx->propq,
+                                           pkey) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                      SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
                      ERR_R_INTERNAL_ERROR);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 11eea82fff..8285e5cd27 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -380,9 +380,9 @@ int tls1_change_cipher_state(SSL *s, int which)
         mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,
                                                (int)*mac_secret_size);
         if (mac_key == NULL
-            || EVP_DigestSignInit_ex(mac_ctx, NULL,
-                                     EVP_MD_name(m), s->ctx->propq,
-                                     mac_key, s->ctx->libctx) <= 0) {
+            || EVP_DigestSignInit_with_libctx(mac_ctx, NULL, EVP_MD_name(m),
+                                              s->ctx->libctx, s->ctx->propq,
+                                              mac_key) <= 0) {
             EVP_PKEY_free(mac_key);
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_CHANGE_CIPHER_STATE,
                      ERR_R_INTERNAL_ERROR);
diff --git a/test/acvp_test.c b/test/acvp_test.c
index 737d2c61bb..b33881d4db 100644
--- a/test/acvp_test.c
+++ b/test/acvp_test.c
@@ -92,8 +92,9 @@ static int sig_gen(EVP_PKEY *pkey, OSSL_PARAM *params, const char *digest_name,
 
     if (!TEST_ptr(sig = OPENSSL_malloc(sz))
         || !TEST_ptr(md_ctx = EVP_MD_CTX_new())
-        || !TEST_int_eq(EVP_DigestSignInit_ex(md_ctx, NULL, digest_name, NULL,
-                                              pkey, libctx), 1)
+        || !TEST_int_eq(EVP_DigestSignInit_with_libctx(md_ctx, NULL,
+                                                       digest_name, libctx, NULL,
+                                                       pkey), 1)
         || !TEST_int_gt(EVP_DigestSign(md_ctx, sig, &sig_len, msg, msg_len), 0))
         goto err;
     *sig_out = sig;
@@ -296,8 +297,9 @@ static int ecdsa_sigver_test(int id)
 
     ret = TEST_int_gt((sig_len = i2d_ECDSA_SIG(sign, &sig)), 0)
           && TEST_ptr(md_ctx = EVP_MD_CTX_new())
-          && TEST_true(EVP_DigestVerifyInit_ex(md_ctx, NULL, tst->digest_alg,
-                                               NULL, pkey, libctx)
+          && TEST_true(EVP_DigestVerifyInit_with_libctx(md_ctx, NULL,
+                                                        tst->digest_alg,
+                                                        libctx, NULL, pkey)
           && TEST_int_eq(EVP_DigestVerify(md_ctx, sig, sig_len,
                                           tst->msg, tst->msg_len), tst->pass));
 err:
@@ -1238,8 +1240,9 @@ static int rsa_sigver_test(int id)
         || !TEST_true(rsa_create_pkey(&pkey, tst->n, tst->n_len,
                                       tst->e, tst->e_len, NULL, 0, bn_ctx))
         || !TEST_ptr(md_ctx = EVP_MD_CTX_new())
-        || !TEST_true(EVP_DigestVerifyInit_ex(md_ctx, &pkey_ctx, tst->digest_alg,
-                                              NULL, pkey, libctx)
+        || !TEST_true(EVP_DigestVerifyInit_with_libctx(md_ctx, &pkey_ctx,
+                                                       tst->digest_alg,
+                                                       libctx, NULL, pkey)
         || !TEST_true(EVP_PKEY_CTX_set_params(pkey_ctx, params))
         || !TEST_int_eq(EVP_DigestVerify(md_ctx, tst->sig, tst->sig_len,
                                          tst->msg, tst->msg_len), tst->pass)))
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 51b517fb95..de615c80ab 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -1461,8 +1461,9 @@ static int test_EVP_PKEY_CTX_get_set_params(EVP_PKEY *pkey)
      */
     mdctx = EVP_MD_CTX_new();
     if (!TEST_ptr(mdctx)
-        || !TEST_true(EVP_DigestSignInit_ex(mdctx, NULL, "SHA1", NULL, pkey,
-                                            NULL)))
+        || !TEST_true(EVP_DigestSignInit_with_libctx(mdctx, NULL,
+                                                     "SHA1", NULL, NULL,
+                                                     pkey)))
         goto err;
 
     /*
diff --git a/test/evp_test.c b/test/evp_test.c
index 30a0aa11ef..bff1ecb558 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -1183,7 +1183,7 @@ static int mac_test_run_pkey(EVP_TEST *t)
         t->err = "INTERNAL_ERROR";
         goto err;
     }
-    if (!EVP_DigestSignInit_ex(mctx, &pctx, mdname, NULL, key, libctx)) {
+    if (!EVP_DigestSignInit_with_libctx(mctx, &pctx, mdname, libctx, NULL, key)) {
         t->err = "DIGESTSIGNINIT_ERROR";
         goto err;
     }
@@ -2899,13 +2899,13 @@ static int digestsigver_test_parse(EVP_TEST *t,
             return 1;
         }
         if (mdata->is_verify) {
-            if (!EVP_DigestVerifyInit_ex(mdata->ctx, &mdata->pctx,
-                                         name, NULL, pkey, libctx))
+            if (!EVP_DigestVerifyInit_with_libctx(mdata->ctx, &mdata->pctx,
+                                                  name, libctx, NULL, pkey))
                 t->err = "DIGESTVERIFYINIT_ERROR";
             return 1;
         }
-        if (!EVP_DigestSignInit_ex(mdata->ctx, &mdata->pctx,
-                                   name, NULL, pkey, libctx))
+        if (!EVP_DigestSignInit_with_libctx(mdata->ctx, &mdata->pctx,
+                                            name, libctx, NULL, pkey))
             t->err = "DIGESTSIGNINIT_ERROR";
         return 1;
     }
diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t
index 76342481fb..38028c291a 100644
--- a/test/recipes/80-test_cms.t
+++ b/test/recipes/80-test_cms.t
@@ -13,16 +13,34 @@ use warnings;
 use POSIX;
 use File::Spec::Functions qw/catfile/;
 use File::Compare qw/compare_text/;
-use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir/;
+use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
+
 use OpenSSL::Test::Utils;
 
-setup("test_cms");
+BEGIN {
+    setup("test_cms");
+}
+
+use lib srctop_dir('Configurations');
+use lib bldtop_dir('.');
+use platform;
+
+my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
 
 plan skip_all => "CMS is not supported by this OpenSSL build"
     if disabled("cms");
 
 my $provpath = bldtop_dir("providers");
-my @prov = ("-provider_path", $provpath, "-provider", "default", "-provider", "legacy");
+
+# Some tests require legacy algorithms to be included.
+my @legacyprov = ("-provider_path", $provpath,
+                  "-provider", "default",
+                  "-provider", "legacy" );
+my @defaultprov = ("-provider_path", $provpath,
+                   "-provider", "default");
+
+my @config = ( );
+my $provname = 'default';
 
 my $datadir = srctop_dir("test", "recipes", "80-test_cms_data");
 my $smdir    = srctop_dir("test", "smime-certs");
@@ -30,173 +48,191 @@ my $smcont   = srctop_file("test", "smcont.txt");
 my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
     = disabled qw/des dh dsa ec ec2m rc2 zlib/;
 
-plan tests => 10;
+plan tests =>
+    ($no_fips ? 0 : 1)          # FIPS install test
+    + 10;
+
+unless ($no_fips) {
+    my $infile = bldtop_file('providers', platform->dso('fips'));
+
+    ok(run(app(['openssl', 'fipsinstall',
+                '-out', bldtop_file('providers', 'fipsmodule.cnf'),
+                '-module', $infile])),
+       "fipsinstall");
+    @config = ( "-config", srctop_file("test", "fips.cnf") );
+    $provname = 'fips';
+}
+
+$ENV{OPENSSL_TEST_LIBCTX} = "1";
+my @prov = ("-provider_path", $provpath,
+            @config,
+            "-provider", $provname);
 
 my @smime_pkcs7_tests = (
 
     [ "signed content DER format, RSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}",  @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed detached content DER format, RSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
         "-content", $smcont ],
       \&final_compare
     ],
 
     [ "signed content test streaming BER format, RSA",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
         "-stream",
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content DER format, DSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed detached content DER format, DSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
         "-content", $smcont ],
       \&final_compare
     ],
 
     [ "signed detached content DER format, add RSA signer (with DSA existing)",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd1}", "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
+      [ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER",
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}2.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}2.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt",
         "-content", $smcont ],
       \&final_compare
     ],
 
     [ "signed content test streaming BER format, DSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-nodetach", "-stream",
         "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-nodetach", "-stream",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-noattr", "-nodetach", "-stream",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content S/MIME format, RSA key SHA1",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-md", "sha1",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-md", "sha1",
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming S/MIME format, 2 DSA and 2 RSA keys",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming multipart S/MIME format, 2 DSA and 2 RSA keys",
-      [ "{cmd1}", "-sign", "-in", $smcont,
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont,
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, 3 recipients",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         catfile($smdir, "smrsa1.pem"),
         catfile($smdir, "smrsa2.pem"),
         catfile($smdir, "smrsa3.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, 3rd used",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         catfile($smdir, "smrsa1.pem"),
         catfile($smdir, "smrsa2.pem"),
         catfile($smdir, "smrsa3.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa3.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, key only used",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         catfile($smdir, "smrsa1.pem"),
         catfile($smdir, "smrsa2.pem"),
         catfile($smdir, "smrsa3.pem") ],
-      [ "{cmd2}", "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, AES-256 cipher, 3 recipients",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
         "-aes256", "-stream", "-out", "{output}.cms",
         catfile($smdir, "smrsa1.pem"),
         catfile($smdir, "smrsa2.pem"),
         catfile($smdir, "smrsa3.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
@@ -206,68 +242,68 @@ my @smime_pkcs7_tests = (
 my @smime_cms_tests = (
 
     [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, keyid",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER",
         "-nodetach", "-keyid",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming PEM format, 2 DSA and 2 RSA keys",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-signer", catfile($smdir, "smdsa1.pem"),
         "-signer", catfile($smdir, "smdsa2.pem"),
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content MIME format, RSA key, signed receipt request",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed receipt MIME format, RSA key",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-receipt_request_to", "test\@openssl.org", "-receipt_request_all",
         "-out", "{output}.cms" ],
-      [ "{cmd1}", "-sign_receipt", "-in", "{output}.cms",
+      [ "{cmd1}", @prov, "-sign_receipt", "-in", "{output}.cms",
         "-signer", catfile($smdir, "smrsa2.pem"), "-out", "{output}2.cms" ],
-      [ "{cmd2}", "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-verify_receipt", "{output}2.cms", "-in", "{output}.cms",
         "-CAfile", catfile($smdir, "smroot.pem") ]
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, 3 recipients, keyid",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms", "-keyid",
         catfile($smdir, "smrsa1.pem"),
         catfile($smdir, "smrsa2.pem"),
         catfile($smdir, "smrsa3.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming PEM format, KEK",
-      [ "{cmd1}", "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
         "-stream", "-out", "{output}.cms",
         "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-secretkeyid", "C0FEE0" ],
-      [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
+      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
         "-inform", "PEM",
         "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-secretkeyid", "C0FEE0" ],
@@ -275,30 +311,30 @@ my @smime_cms_tests = (
     ],
 
     [ "enveloped content test streaming PEM format, KEK, key only",
-      [ "{cmd1}", "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont, "-outform", "PEM", "-aes128",
         "-stream", "-out", "{output}.cms",
         "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-secretkeyid", "C0FEE0" ],
-      [ "{cmd2}", "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
+      [ "{cmd2}", @prov, "-decrypt", "-in", "{output}.cms", "-out", "{output}.txt",
         "-inform", "PEM",
         "-secretkey", "000102030405060708090A0B0C0D0E0F" ],
       \&final_compare
     ],
 
     [ "data content test streaming PEM format",
-      [ "{cmd1}", "-data_create", "-in", $smcont, "-outform", "PEM",
+      [ "{cmd1}", @prov, "-data_create", "-in", $smcont, "-outform", "PEM",
         "-nodetach", "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-data_out", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-data_out", "-in", "{output}.cms", "-inform", "PEM",
         "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "encrypted content test streaming PEM format, 128 bit RC2 key",
-      [ "{cmd1}", @prov, "-EncryptedData_encrypt",
+      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
         "-in", $smcont, "-outform", "PEM",
         "-rc2", "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
+      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
         "-inform", "PEM",
         "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-out", "{output}.txt" ],
@@ -306,21 +342,21 @@ my @smime_cms_tests = (
     ],
 
     [ "encrypted content test streaming PEM format, 40 bit RC2 key",
-      [ "{cmd1}", @prov, "-EncryptedData_encrypt",
+      [ "{cmd1}", @legacyprov, "-EncryptedData_encrypt",
         "-in", $smcont, "-outform", "PEM",
         "-rc2", "-secretkey", "0001020304",
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
+      [ "{cmd2}", @legacyprov, "-EncryptedData_decrypt", "-in", "{output}.cms",
         "-inform", "PEM",
         "-secretkey", "0001020304", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "encrypted content test streaming PEM format, triple DES key",
-      [ "{cmd1}", "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
         "-des3", "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-EncryptedData_decrypt", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
         "-inform", "PEM",
         "-secretkey", "000102030405060708090A0B0C0D0E0F1011121314151617",
         "-out", "{output}.txt" ],
@@ -328,10 +364,10 @@ my @smime_cms_tests = (
     ],
 
     [ "encrypted content test streaming PEM format, 128 bit AES key",
-      [ "{cmd1}", "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
+      [ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
         "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-EncryptedData_decrypt", "-in", "{output}.cms",
+      [ "{cmd2}", @prov, "-EncryptedData_decrypt", "-in", "{output}.cms",
         "-inform", "PEM",
         "-secretkey", "000102030405060708090A0B0C0D0E0F",
         "-out", "{output}.txt" ],
@@ -343,57 +379,57 @@ my @smime_cms_tests = (
 my @smime_cms_cades_tests = (
 
     [ "signed content DER format, RSA key, CAdES-BES compatible",
-      [ "{cmd1}", "-sign", "-cades", "-in", $smcont, "-outform", "DER",
+      [ "{cmd1}", @prov, "-sign", "-cades", "-in", $smcont, "-outform", "DER",
          "-nodetach",
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
-      [ "{cmd1}", "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
+      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha256", "-in", $smcont, "-outform",
         "DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content DER format, RSA key, SHA512 md, CAdES-BES compatible",
-      [ "{cmd1}", "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
+      [ "{cmd1}", @prov, "-sign", "-cades", "-md", "sha512", "-in", $smcont, "-outform",
         "DER", "-nodetach", "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content DER format, RSA key, SHA256 md, CAdES-BES compatible",
-      [ "{cmd1}", "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
+      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
         "-in", $smcont, "-outform", "DER", 
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-outform", "DER", "-out", "{output}.cms"  ],
-      [ "{cmd2}", "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "resigned content DER format, RSA key, SHA256 md, CAdES-BES compatible",
-      [ "{cmd1}", "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
+      [ "{cmd1}", @prov, "-sign", "-cades", "-binary",  "-nodetach", "-nosmimecap", "-md", "sha256",
         "-in", $smcont, "-outform", "DER", 
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-outform", "DER", "-out", "{output}.cms"  ],
-      [ "{cmd1}", "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
+      [ "{cmd1}", @prov, "-resign", "-cades", "-binary", "-nodetach", "-nosmimecap", "-md", "sha256",
         "-inform", "DER", "-in", "{output}.cms",
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa2.pem"),
         "-outform", "DER", "-out", "{output}2.cms" ],
 
-      [ "{cmd2}", "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-cades", "-in", "{output}2.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
@@ -401,10 +437,10 @@ my @smime_cms_cades_tests = (
 
 my @smime_cms_cades_ko_tests = (
     [ "signed content DER format, RSA key, but verified as CAdES-BES compatible",
-      [ "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
+      [ @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach",
         "-certfile", catfile($smdir, "smroot.pem"),
         "-signer", catfile($smdir, "smrsa1.pem"), "-out", "{output}.cms" ],
-      [ "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
+      [ @prov, "-verify", "-cades", "-in", "{output}.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ]
@@ -424,9 +460,9 @@ my @smime_cms_cades_invalid_option_tests = (
 my @smime_cms_comp_tests = (
 
     [ "compressed content test streaming PEM format",
-      [ "{cmd1}", "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-compress", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-stream", "-out", "{output}.cms" ],
-      [ "{cmd2}", "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-uncompress", "-in", "{output}.cms", "-inform", "PEM",
         "-out", "{output}.txt" ],
       \&final_compare
     ]
@@ -435,137 +471,139 @@ my @smime_cms_comp_tests = (
 
 my @smime_cms_param_tests = (
     [ "signed content test streaming PEM format, RSA keys, PSS signature",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:pss",
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming PEM format, RSA keys, PSS signature, saltlen=max",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_pss_saltlen:max",
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-noattr",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:pss",
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "signed content test streaming PEM format, RSA keys, PSS signature, SHA384 MGF1",
-      [ "{cmd1}", "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
+      [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach",
         "-signer", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:pss", "-keyopt", "rsa_mgf1_md:sha384",
         "-out", "{output}.cms" ],
-      [ "{cmd2}", "-verify", "-in", "{output}.cms", "-inform", "PEM",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, OAEP default parameters",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:oaep" ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, OAEP SHA256",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smrsa1.pem"),
         "-keyopt", "rsa_padding_mode:oaep",
         "-keyopt", "rsa_oaep_md:sha256" ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smrsa1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, ECDH",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smec1.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, DES, ECDH, 2 recipients, key only used",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         catfile($smdir, "smec1.pem"),
         catfile($smdir, "smec3.pem") ],
-      [ "{cmd2}", "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smec3.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, ECDH, DES, key identifier",
-      [ "{cmd1}", "-encrypt", "-keyid", "-in", $smcont,
+      [ "{cmd1}", @defaultprov, "-encrypt", "-keyid", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smec1.pem") ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+      [ "{cmd2}", @defaultprov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, ECDH, AES128, SHA256 KDF",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smec1.pem"), "-aes128",
         "-keyopt", "ecdh_kdf_md:sha256" ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
+      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec1.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ],
 
     [ "enveloped content test streaming S/MIME format, ECDH, K-283, cofactor DH",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
+      [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
         "-stream", "-out", "{output}.cms",
         "-recip", catfile($smdir, "smec2.pem"), "-aes128",
         "-keyopt", "ecdh_kdf_md:sha256", "-keyopt", "ecdh_cofactor_mode:1" ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
-        "-in", "{output}.cms", "-out", "{output}.txt" ],
-      \&final_compare
-    ],
-
-    [ "enveloped content test streaming S/MIME format, X9.42 DH",
-      [ "{cmd1}", "-encrypt", "-in", $smcont,
-        "-stream", "-out", "{output}.cms",
-        "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
-      [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
+      [ "{cmd2}", @prov, "-decrypt", "-recip", catfile($smdir, "smec2.pem"),
         "-in", "{output}.cms", "-out", "{output}.txt" ],
       \&final_compare
     ]
+
+    # TODO(3.0) Add this test back in when "dhpublicnumber" is supported
+    # in the keymanger.
+    #[ "enveloped content test streaming S/MIME format, X9.42 DH",
+    #  [ "{cmd1}", @prov, "-encrypt", "-in", $smcont,
+    #    "-stream", "-out", "{output}.cms",
+    #    "-recip", catfile($smdir, "smdh.pem"), "-aes128" ],
+    #  [ "{cmd2}", "-decrypt", "-recip", catfile($smdir, "smdh.pem"),
+    #    "-in", "{output}.cms", "-out", "{output}.txt" ],
+    #  \&final_compare
+    #]
 );
 
 my @contenttype_cms_test = (
     [ "signed content test - check that content type is added to additional signerinfo, RSA keys",
-      [ "{cmd1}", "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
+      [ "{cmd1}", @prov, "-sign", "-binary", "-nodetach", "-stream", "-in", $smcont,
         "-outform", "DER",
         "-signer", catfile($smdir, "smrsa1.pem"), "-md", "SHA256",
         "-out", "{output}.cms" ],
-      [ "{cmd1}", "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
+      [ "{cmd1}", @prov, "-resign", "-binary", "-nodetach", "-in", "{output}.cms",
         "-inform", "DER", "-outform", "DER",
         "-signer", catfile($smdir, "smrsa2.pem"), "-md", "SHA256",
         "-out", "{output}2.cms" ],
       sub { my %opts = @_; contentType_matches("$opts{output}2.cms") == 2; },
-      [ "{cmd2}", "-verify", "-in", "{output}2.cms", "-inform", "DER",
+      [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER",
         "-CAfile", catfile($smdir, "smroot.pem"), "-out", "{output}.txt" ]
     ],
 );
@@ -690,7 +728,7 @@ subtest "CMS Check that bad attributes fail when verifying signers\n" => sub {
     foreach my $name (@incorrect_attribute_cms_test) {
         my $out = "incorrect-$cnt.txt";
 
-        ok(!run(app(["openssl", "cms", "-verify", "-in",
+        ok(!run(app(["openssl", "cms", @prov, "-verify", "-in",
                      catfile($datadir, $name), "-inform", "DER", "-CAfile",
                      catfile($smdir, "smroot.pem"), "-out", $out ])),
             $name);
@@ -706,7 +744,7 @@ subtest "CMS Decrypt message encrypted with OpenSSL 1.1.1\n" => sub {
 
         my $out = "smtst.txt";
 
-        ok(run(app(["openssl", "cms", "-decrypt",
+        ok(run(app(["openssl", "cms", @defaultprov, "-decrypt",
                     "-inkey", catfile($smdir, "smec3.pem"),
                     "-in", catfile($datadir, "ciphertext_from_1_1_1.cms"),
                     "-out", $out ]))
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 813c86b4c1..8cfe55f4fa 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4806,9 +4806,9 @@ OSSL_CMP_print_to_bio                   ?	3_0_0	EXIST::FUNCTION:CMP
 OSSL_CMP_print_errors_cb                ?	3_0_0	EXIST::FUNCTION:CMP
 OSSL_CRMF_CERTID_get0_issuer            ?	3_0_0	EXIST::FUNCTION:CRMF
 OSSL_CRMF_CERTID_get0_serialNumber      ?	3_0_0	EXIST::FUNCTION:CRMF
-EVP_DigestSignInit_ex                   ?	3_0_0	EXIST::FUNCTION:
+EVP_DigestSignInit_ex                   ?	3_0_0	NOEXIST::FUNCTION:
 EVP_DigestSignUpdate                    ?	3_0_0	EXIST::FUNCTION:
-EVP_DigestVerifyInit_ex                 ?	3_0_0	EXIST::FUNCTION:
+EVP_DigestVerifyInit_ex                 ?	3_0_0	NOEXIST::FUNCTION:
 EVP_DigestVerifyUpdate                  ?	3_0_0	EXIST::FUNCTION:
 BN_check_prime                          ?	3_0_0	EXIST::FUNCTION:
 EVP_KEYMGMT_is_a                        ?	3_0_0	EXIST::FUNCTION:
@@ -5206,3 +5206,22 @@ PKCS12_SAFEBAG_create_secret            ?	3_0_0	EXIST::FUNCTION:
 PKCS12_add1_attr_by_NID                 ?	3_0_0	EXIST::FUNCTION:
 PKCS12_add1_attr_by_txt                 ?	3_0_0	EXIST::FUNCTION:
 PKCS12_add_secret                       ?	3_0_0	EXIST::FUNCTION:
+SMIME_write_ASN1_with_libctx            ?	3_0_0	EXIST::FUNCTION:
+SMIME_read_ASN1_ex                      ?	3_0_0	EXIST::FUNCTION:
+CMS_ContentInfo_new_with_libctx         ?	3_0_0	EXIST::FUNCTION:CMS
+SMIME_read_CMS_ex                       ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_sign_with_libctx                    ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_data_create_with_libctx             ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_digest_create_with_libctx           ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_EncryptedData_encrypt_with_libctx   ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_encrypt_with_libctx                 ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_EnvelopedData_create_with_libctx    ?	3_0_0	EXIST::FUNCTION:CMS
+CMS_ReceiptRequest_create0_with_libctx  ?	3_0_0	EXIST::FUNCTION:CMS
+EVP_SignFinal_with_libctx               ?	3_0_0	EXIST::FUNCTION:
+EVP_VerifyFinal_with_libctx             ?	3_0_0	EXIST::FUNCTION:
+EVP_DigestSignInit_with_libctx          ?	3_0_0	EXIST::FUNCTION:
+EVP_DigestVerifyInit_with_libctx        ?	3_0_0	EXIST::FUNCTION:
+PKCS7_new_with_libctx                   ?	3_0_0	EXIST::FUNCTION:
+PKCS7_sign_with_libctx                  ?	3_0_0	EXIST::FUNCTION:
+PKCS7_encrypt_with_libctx               ?	3_0_0	EXIST::FUNCTION:
+SMIME_read_PKCS7_ex                     ?	3_0_0	EXIST::FUNCTION:
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index 0e5bb35878..3e8c62c610 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -309,8 +309,6 @@ CMAC_Init(3)
 CMAC_Update(3)
 CMAC_resume(3)
 CMS_ContentInfo_it(3)
-CMS_EncryptedData_decrypt(3)
-CMS_EncryptedData_encrypt(3)
 CMS_EncryptedData_set1_key(3)
 CMS_ReceiptRequest_it(3)
 CMS_RecipientEncryptedKey_cert_cmp(3)
@@ -340,10 +338,8 @@ CMS_add_standard_smimecap(3)
 CMS_data(3)
 CMS_dataFinal(3)
 CMS_dataInit(3)
-CMS_data_create(3)
 CMS_decrypt_set1_key(3)
 CMS_decrypt_set1_password(3)
-CMS_digest_create(3)
 CMS_digest_verify(3)
 CMS_is_detached(3)
 CMS_set1_signers_certs(3)
@@ -1119,9 +1115,7 @@ SHA1_Transform(3)
 SHA256_Transform(3)
 SHA512_Transform(3)
 SMIME_crlf_copy(3)
-SMIME_read_ASN1(3)
 SMIME_text(3)
-SMIME_write_ASN1(3)
 SRP_Verify_A_mod_N(3)
 SRP_Verify_B_mod_N(3)
 SSL_CTX_set0_ctlog_store(3)


More information about the openssl-commits mailing list