[openssl] master update

Dr. Paul Dale pauli at openssl.org
Thu Apr 29 23:16:44 UTC 2021


The branch master has been updated
       via  c7d848e220ecb432faa05d2198ae689298d71728 (commit)
       via  b536880c45722777df5ebe62897a6efcef757945 (commit)
      from  d77ba503a2cf1c83098baca345327761b991d191 (commit)


- Log -----------------------------------------------------------------
commit c7d848e220ecb432faa05d2198ae689298d71728
Author: Pauli <pauli at openssl.org>
Date:   Fri Apr 30 09:11:42 2021 +1000

    remove end of line whitespace
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14434)

commit b536880c45722777df5ebe62897a6efcef757945
Author: Jon Spillett <jon.spillett at oracle.com>
Date:   Wed Feb 17 17:56:36 2021 +1000

    Add library context and property query support into the PKCS12 API
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14434)

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

Summary of changes:
 CHANGES.md                              |  21 +++
 apps/build.info                         |   5 +-
 apps/pkcs12.c                           |  52 ++++--
 apps/progs.pl                           |   1 -
 crypto/asn1/p5_pbe.c                    |  27 ++-
 crypto/asn1/p5_pbev2.c                  |  40 ++++-
 crypto/asn1/p5_scrypt.c                 |  24 ++-
 crypto/evp/evp_local.h                  |   4 +
 crypto/evp/evp_pbe.c                    | 118 ++++++++-----
 crypto/evp/p5_crpt2.c                   |  68 +++++--
 crypto/evp/pbe_scrypt.c                 |  20 ++-
 crypto/pkcs12/p12_add.c                 |  76 ++++++--
 crypto/pkcs12/p12_crpt.c                |  49 +++--
 crypto/pkcs12/p12_crt.c                 |  64 +++++--
 crypto/pkcs12/p12_decr.c                |  64 +++++--
 crypto/pkcs12/p12_init.c                |  16 +-
 crypto/pkcs12/p12_key.c                 |  66 ++++---
 crypto/pkcs12/p12_mutl.c                |  66 ++++---
 crypto/pkcs12/p12_p8d.c                 |  17 +-
 crypto/pkcs12/p12_p8e.c                 |  44 +++--
 crypto/pkcs12/p12_sbag.c                |  48 +++--
 crypto/pkcs7/pk7_lib.c                  |  31 ++++
 crypto/pkcs7/pk7_local.h                |   2 +
 doc/build.info                          |  60 +++++++
 doc/man3/EVP_PBE_CipherInit.pod         |  99 +++++++++++
 doc/man3/PKCS12_PBE_keyivgen.pod        | 108 ++++++++++++
 doc/man3/PKCS12_SAFEBAG_create_cert.pod |  28 ++-
 doc/man3/PKCS12_add_cert.pod            |  27 ++-
 doc/man3/PKCS12_add_safe.pod            |  27 ++-
 doc/man3/PKCS12_create.pod              |  23 ++-
 doc/man3/PKCS12_decrypt_skey.pod        |  55 ++++++
 doc/man3/PKCS12_gen_mac.pod             |  72 ++++++++
 doc/man3/PKCS12_init.pod                |  48 +++++
 doc/man3/PKCS12_item_decrypt_d2i.pod    |  73 ++++++++
 doc/man3/PKCS12_key_gen_utf8_ex.pod     | 138 +++++++++++++++
 doc/man3/PKCS12_pack_p7encdata.pod      |  59 +++++++
 doc/man3/PKCS5_PBE_keyivgen.pod         | 170 ++++++++++++++++++
 doc/man3/PKCS5_PBKDF2_HMAC.pod          |   5 +-
 doc/man3/PKCS8_encrypt.pod              |  78 ++++++++
 include/crypto/pkcs7.h                  |   3 +
 include/openssl/core_names.h            |   1 -
 include/openssl/evp.h                   |  24 +++
 include/openssl/pkcs12.h.in             |  79 +++++++++
 include/openssl/x509.h.in               |  14 ++
 test/helpers/pkcs12.c                   | 143 ++++++++++++---
 test/helpers/pkcs12.h                   |  14 +-
 test/pkcs12_format_test.c               | 304 +++++++++++++++++++++++++++++++-
 test/recipes/80-test_pkcs12.t           |  15 +-
 util/libcrypto.num                      |  27 +++
 util/missingcrypto.txt                  |  45 -----
 50 files changed, 2313 insertions(+), 349 deletions(-)
 create mode 100644 doc/man3/EVP_PBE_CipherInit.pod
 create mode 100644 doc/man3/PKCS12_PBE_keyivgen.pod
 create mode 100644 doc/man3/PKCS12_decrypt_skey.pod
 create mode 100644 doc/man3/PKCS12_gen_mac.pod
 create mode 100644 doc/man3/PKCS12_init.pod
 create mode 100644 doc/man3/PKCS12_item_decrypt_d2i.pod
 create mode 100644 doc/man3/PKCS12_key_gen_utf8_ex.pod
 create mode 100644 doc/man3/PKCS12_pack_p7encdata.pod
 create mode 100644 doc/man3/PKCS5_PBE_keyivgen.pod
 create mode 100644 doc/man3/PKCS8_encrypt.pod

diff --git a/CHANGES.md b/CHANGES.md
index 1097c8c749..e93d5df75a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -46,6 +46,27 @@ OpenSSL 3.0
 
    *Shane Lontis*
 
+ * Added enhanced PKCS#12 APIs which accept a library context `OSSL_LIB_CTX`
+   and (where relevant) a property query. Other APIs which handle PKCS#7 and
+   PKCS#8 objects have also been enhanced where required. This includes:
+
+   PKCS12_add_key_ex(), PKCS12_add_safe_ex(), PKCS12_add_safes_ex(),
+   PKCS12_create_ex(), PKCS12_decrypt_skey_ex(), PKCS12_init_ex(),
+   PKCS12_item_decrypt_d2i_ex(), PKCS12_item_i2d_encrypt_ex(),
+   PKCS12_key_gen_asc_ex(), PKCS12_key_gen_uni_ex(), PKCS12_key_gen_utf8_ex(),
+   PKCS12_pack_p7encdata_ex(), PKCS12_pbe_crypt_ex(), PKCS12_PBE_keyivgen_ex(),
+   PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(), PKCS5_pbe2_set_iv_ex(),
+   PKCS5_pbe_set0_algor_ex(), PKCS5_pbe_set_ex(), PKCS5_pbkdf2_set_ex(),
+   PKCS5_v2_PBE_keyivgen_ex(), PKCS5_v2_scrypt_keyivgen_ex(),
+   PKCS8_decrypt_ex(), PKCS8_encrypt_ex(), PKCS8_set0_pbe_ex().
+
+   As part of this change the EVP_PBE_xxx APIs can also accept a library
+   context and property query and will call an extended version of the key/IV
+   derivation function which supports these parameters. This includes
+   EVP_PBE_CipherInit_ex(), EVP_PBE_find_ex() and EVP_PBE_scrypt_ex().
+
+   *Jon Spillett*
+
  * The default manual page suffix ($MANSUFFIX) has been changed to "ossl"
 
    *Matt Caswell*
diff --git a/apps/build.info b/apps/build.info
index aa91ebbb95..cba9803c65 100644
--- a/apps/build.info
+++ b/apps/build.info
@@ -18,10 +18,7 @@ $OPENSSLSRC=\
         pkcs8.c pkey.c pkeyparam.c pkeyutl.c prime.c rand.c req.c \
         s_client.c s_server.c s_time.c sess_id.c smime.c speed.c \
         spkac.c verify.c version.c x509.c rehash.c storeutl.c \
-        list.c info.c fipsinstall.c
-IF[{- !$disabled{'des'} -}]
-  $OPENSSLSRC=$OPENSSLSRC pkcs12.c
-ENDIF
+        list.c info.c fipsinstall.c pkcs12.c
 IF[{- !$disabled{'ec'} -}]
   $OPENSSLSRC=$OPENSSLSRC ec.c ecparam.c
 ENDIF
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 306bcda7b4..c2508163f0 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -58,13 +58,19 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
     OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
-    OPT_DESCERT, OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
+#ifndef OPENSSL_NO_DES
+    OPT_DESCERT,
+#endif
+    OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
     OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
     OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS,
     OPT_NAME, OPT_CSP, OPT_CANAME,
     OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
     OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
-    OPT_R_ENUM, OPT_PROV_ENUM, OPT_LEGACY_ALG
+    OPT_R_ENUM, OPT_PROV_ENUM,
+#ifndef OPENSSL_NO_DES
+    OPT_LEGACY_ALG
+#endif
 } OPTION_CHOICE;
 
 const OPTIONS pkcs12_options[] = {
@@ -79,13 +85,15 @@ const OPTIONS pkcs12_options[] = {
     {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
     {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
     {"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"},
+#ifndef OPENSSL_NO_DES
     {"legacy", OPT_LEGACY_ALG, '-',
-#ifdef OPENSSL_NO_RC2
+# ifdef OPENSSL_NO_RC2
      "Use legacy encryption algorithm 3DES_CBC for keys and certs"
-#else
+# else
      "Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs"
-#endif
+# endif
     },
+#endif
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -130,8 +138,10 @@ const OPTIONS pkcs12_options[] = {
     {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"},
     {"certpbe", OPT_CERTPBE, 's',
      "Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"},
+#ifndef OPENSSL_NO_DES
     {"descert", OPT_DESCERT, '-',
      "Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"},
+#endif
     {"macalg", OPT_MACALG, 's',
      "Digest algorithm to use in MAC (default SHA1)"},
     {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
@@ -149,7 +159,10 @@ int pkcs12_main(int argc, char **argv)
     char *passcertsarg = NULL, *passcerts = NULL;
     char *name = NULL, *csp_name = NULL;
     char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
-    int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0, use_legacy = 0;
+    int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
+#ifndef OPENSSL_NO_DES
+    int use_legacy = 0;
+#endif
     /* use library defaults for the iter, maciter, cert, and key PBE */
     int iter = 0, maciter = 0;
     int cert_pbe = NID_undef;
@@ -214,9 +227,11 @@ int pkcs12_main(int argc, char **argv)
         case OPT_NOMACVER:
             macver = 0;
             break;
+#ifndef OPENSSL_NO_DES
         case OPT_DESCERT:
             cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
             break;
+#endif
         case OPT_EXPORT:
             export_pkcs12 = 1;
             break;
@@ -328,9 +343,11 @@ int pkcs12_main(int argc, char **argv)
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+#ifndef OPENSSL_NO_DES
         case OPT_LEGACY_ALG:
             use_legacy = 1;
             break;
+#endif
         case OPT_PROV_CASES:
             if (!opt_provider(o))
                 goto end;
@@ -410,6 +427,7 @@ int pkcs12_main(int argc, char **argv)
         if (cert_pbe == -1 && maciter == -1)
             WARN_NO_EXPORT("nomac");
     }
+#ifndef OPENSSL_NO_DES
     if (use_legacy) {
         /* load the legacy provider if not loaded already*/
         if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
@@ -421,11 +439,11 @@ int pkcs12_main(int argc, char **argv)
         }
         if (cert_pbe == NID_undef) {
             /* Adapt default algorithm */
-#ifndef OPENSSL_NO_RC2
+# ifndef OPENSSL_NO_RC2
             cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
-#else
+# else
             cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
-#endif
+# endif
         }
 
         if (key_pbe == NID_undef)
@@ -435,7 +453,7 @@ int pkcs12_main(int argc, char **argv)
         if (macalg == NULL)
             macalg = "sha1";
     }
-
+#endif
 
     private = 1;
 
@@ -643,8 +661,9 @@ int pkcs12_main(int argc, char **argv)
         if (!twopass)
             OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
 
-        p12 = PKCS12_create(cpass, name, key, ee_cert, certs,
-                            key_pbe, cert_pbe, iter, -1, keytype);
+        p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
+                               key_pbe, cert_pbe, iter, -1, keytype,
+                               app_get0_libctx(), app_get0_propq());
 
         if (p12 == NULL) {
             BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
@@ -694,7 +713,12 @@ int pkcs12_main(int argc, char **argv)
     if (out == NULL)
         goto end;
 
-    if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
+    p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq());
+    if (p12 == NULL) {
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+    if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) {
         ERR_print_errors(bio_err);
         goto end;
     }
@@ -938,7 +962,7 @@ int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
         break;
 
     case NID_secretBag:
-        if (options & INFO) 
+        if (options & INFO)
             BIO_printf(bio_err, "Secret bag\n");
         print_attribs(out, attrs, "Bag Attributes");
         BIO_printf(bio_err, "Bag Type: ");
diff --git a/apps/progs.pl b/apps/progs.pl
index a03b83139c..74461f5b3f 100644
--- a/apps/progs.pl
+++ b/apps/progs.pl
@@ -98,7 +98,6 @@ EOF
         gendh    => "dh",
         dhparam  => "dh",
         ecparam  => "ec",
-        pkcs12   => "des",
     );
     my %cmd_deprecated = (
 # The format of this table is:
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
index 43cb054d9f..61b8587ebd 100644
--- a/crypto/asn1/p5_pbe.c
+++ b/crypto/asn1/p5_pbe.c
@@ -24,8 +24,9 @@ IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
 
 /* Set an algorithm identifier for a PKCS#5 PBE algorithm */
 
-int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
-                         const unsigned char *salt, int saltlen)
+int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+                            const unsigned char *salt, int saltlen,
+                            OSSL_LIB_CTX *ctx)
 {
     PBEPARAM *pbe = NULL;
     ASN1_STRING *pbe_str = NULL;
@@ -54,7 +55,7 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
     }
     if (salt)
         memcpy(sstr, salt, saltlen);
-    else if (RAND_bytes(sstr, saltlen) <= 0)
+    else if (RAND_bytes_ex(ctx, sstr, saltlen) <= 0)
         goto err;
 
     ASN1_STRING_set0(pbe->salt, sstr, saltlen);
@@ -78,10 +79,17 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
     return 0;
 }
 
+int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+                         const unsigned char *salt, int saltlen)
+{
+    return PKCS5_pbe_set0_algor_ex(algor, alg, iter, salt, saltlen, NULL);
+}
+
 /* Return an algorithm identifier for a PKCS#5 PBE algorithm */
 
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
-                          const unsigned char *salt, int saltlen)
+X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+                             const unsigned char *salt, int saltlen,
+                             OSSL_LIB_CTX *ctx)
 {
     X509_ALGOR *ret;
     ret = X509_ALGOR_new();
@@ -90,9 +98,16 @@ X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
         return NULL;
     }
 
-    if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+    if (PKCS5_pbe_set0_algor_ex(ret, alg, iter, salt, saltlen, ctx))
         return ret;
 
     X509_ALGOR_free(ret);
     return NULL;
 }
+
+X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+                          const unsigned char *salt, int saltlen)
+{
+    return PKCS5_pbe_set_ex(alg, iter, salt, saltlen, NULL);
+}
+
diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
index f5878de323..da227b96e2 100644
--- a/crypto/asn1/p5_pbev2.c
+++ b/crypto/asn1/p5_pbev2.c
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
 #include <openssl/x509.h>
 #include <openssl/rand.h>
 
@@ -37,9 +39,10 @@ IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM)
  * and IV.
  */
 
-X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
-                              unsigned char *salt, int saltlen,
-                              unsigned char *aiv, int prf_nid)
+X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+                                 unsigned char *salt, int saltlen,
+                                 unsigned char *aiv, int prf_nid,
+                                 OSSL_LIB_CTX *libctx)
 {
     X509_ALGOR *scheme = NULL, *ret = NULL;
     int alg_nid, keylen;
@@ -66,7 +69,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
     if (EVP_CIPHER_iv_length(cipher)) {
         if (aiv)
             memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
-        else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
+        else if (RAND_bytes_ex(libctx, iv, EVP_CIPHER_iv_length(cipher)) <= 0)
             goto err;
     }
 
@@ -104,7 +107,8 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
 
     X509_ALGOR_free(pbe2->keyfunc);
 
-    pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
+    pbe2->keyfunc = PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen,
+                                        libctx);
 
     if (pbe2->keyfunc == NULL)
         goto merr;
@@ -139,14 +143,25 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
     return NULL;
 }
 
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+                              unsigned char *salt, int saltlen,
+                              unsigned char *aiv, int prf_nid)
+{
+    return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, aiv, prf_nid,
+                                NULL);
+}
+
 X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
                            unsigned char *salt, int saltlen)
 {
-    return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
+    return PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
+                                NULL);
 }
 
-X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
-                             int prf_nid, int keylen)
+
+X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+                                int prf_nid, int keylen,
+                                OSSL_LIB_CTX *libctx)
 {
     X509_ALGOR *keyfunc = NULL;
     PBKDF2PARAM *kdf = NULL;
@@ -171,7 +186,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
 
     if (salt)
         memcpy(osalt->data, salt, saltlen);
-    else if (RAND_bytes(osalt->data, saltlen) <= 0)
+    else if (RAND_bytes_ex(libctx, osalt->data, saltlen) <= 0)
         goto merr;
 
     if (iter <= 0)
@@ -220,3 +235,10 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
     X509_ALGOR_free(keyfunc);
     return NULL;
 }
+
+X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+                             int prf_nid, int keylen)
+{
+    return PKCS5_pbkdf2_set_ex(iter, salt, saltlen, prf_nid, keylen, NULL);
+}
+
diff --git a/crypto/asn1/p5_scrypt.c b/crypto/asn1/p5_scrypt.c
index 57c0a5ece9..e5a1ed59bc 100644
--- a/crypto/asn1/p5_scrypt.c
+++ b/crypto/asn1/p5_scrypt.c
@@ -10,10 +10,12 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/asn1t.h>
+#include <openssl/core_names.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
 #include <openssl/rand.h>
+#include "crypto/evp.h"
 
 #ifndef OPENSSL_NO_SCRYPT
 /* PKCS#5 scrypt password based encryption structures */
@@ -206,9 +208,10 @@ static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen,
     return NULL;
 }
 
-int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
-                             int passlen, ASN1_TYPE *param,
-                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                int passlen, ASN1_TYPE *param,
+                                const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+                                OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
     uint64_t p, r, N;
@@ -252,7 +255,8 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0
         || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0
         || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0
-        || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) {
+        || EVP_PBE_scrypt_ex(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0,
+                             libctx, propq) == 0) {
         ERR_raise(ERR_LIB_EVP, EVP_R_ILLEGAL_SCRYPT_PARAMETERS);
         goto err;
     }
@@ -261,8 +265,8 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
 
     salt = sparam->salt->data;
     saltlen = sparam->salt->length;
-    if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen)
-        == 0)
+    if (EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, 0, key,
+                          keylen, libctx, propq) == 0)
         goto err;
     rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
  err:
@@ -271,4 +275,12 @@ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     SCRYPT_PARAMS_free(sparam);
     return rv;
 }
+
+int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+                             int passlen, ASN1_TYPE *param,
+                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+{
+    return PKCS5_v2_scrypt_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL);
+}
+
 #endif /* OPENSSL_NO_SCRYPT */
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 82c5641842..1490f0df4f 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -217,6 +217,10 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              int passlen, ASN1_TYPE *param,
                              const EVP_CIPHER *c, const EVP_MD *md,
                              int en_de);
+int PKCS5_v2_PBKDF2_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                int passlen, ASN1_TYPE *param,
+                                const EVP_CIPHER *c, const EVP_MD *md,
+                                int en_de, OSSL_LIB_CTX *libctx, const char *propq);
 
 struct evp_Encode_Ctx_st {
     /* number saved in a partial encode/decode */
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
index d9d51e0d78..193920724d 100644
--- a/crypto/evp/evp_pbe.c
+++ b/crypto/evp/evp_pbe.c
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
 #include <openssl/pkcs12.h>
 #include <openssl/x509.h>
 #include "crypto/evp.h"
@@ -25,41 +27,42 @@ struct evp_pbe_st {
     int cipher_nid;
     int md_nid;
     EVP_PBE_KEYGEN *keygen;
+    EVP_PBE_KEYGEN_EX *keygen_ex;
 };
 
 static STACK_OF(EVP_PBE_CTL) *pbe_algs;
 
 static const EVP_PBE_CTL builtin_pbe[] = {
     {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC,
-     NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen},
+     NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen, NULL},
     {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC,
-     NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen},
+     NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen, NULL},
     {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC,
-     NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+     NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen, NULL},
 
     {EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
 
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4,
-     NID_rc4, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_rc4, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4,
-     NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
-     NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
-     NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC,
-     NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
     {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC,
-     NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+     NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen, &PKCS12_PBE_keyivgen_ex},
 
-    {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen},
+    {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen, &PKCS5_v2_PBE_keyivgen_ex},
 
     {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC,
-     NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen},
+     NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen, NULL},
     {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC,
-     NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen},
+     NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen, NULL},
     {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC,
-     NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+     NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen, NULL},
 
     {EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
     {EVP_PBE_TYPE_PRF, NID_hmac_md5, -1, NID_md5, 0},
@@ -76,22 +79,27 @@ static const EVP_PBE_CTL builtin_pbe[] = {
      NID_id_GostR3411_2012_512, 0},
     {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_224, -1, NID_sha512_224, 0},
     {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512_256, -1, NID_sha512_256, 0},
-    {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
+    {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen, &PKCS5_v2_PBKDF2_keyivgen_ex},
 #ifndef OPENSSL_NO_SCRYPT
-    {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen}
+    {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen, &PKCS5_v2_scrypt_keyivgen_ex}
 #endif
 };
 
-int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
-                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
+
+int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                          ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+                          OSSL_LIB_CTX *libctx, const char *propq)
 {
-    const EVP_CIPHER *cipher;
-    const EVP_MD *md;
-    int cipher_nid, md_nid;
+    const EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER *cipher_fetch = NULL;
+    const EVP_MD *md = NULL;
+    EVP_MD *md_fetch = NULL;
+    int ret = 0, cipher_nid, md_nid;
+    EVP_PBE_KEYGEN_EX *keygen_ex;
     EVP_PBE_KEYGEN *keygen;
 
-    if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
-                      &cipher_nid, &md_nid, &keygen)) {
+    if (!EVP_PBE_find_ex(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
+                         &cipher_nid, &md_nid, &keygen, &keygen_ex)) {
         char obj_tmp[80];
 
         if (pbe_obj == NULL)
@@ -100,7 +108,7 @@ int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
             i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), pbe_obj);
         ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_PBE_ALGORITHM,
                        "TYPE=%s", obj_tmp);
-        return 0;
+        goto err;
     }
 
     if (pass == NULL)
@@ -108,28 +116,48 @@ int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
     else if (passlen == -1)
         passlen = strlen(pass);
 
-    if (cipher_nid == -1)
-        cipher = NULL;
-    else {
-        cipher = EVP_get_cipherbynid(cipher_nid);
-        if (!cipher) {
+    if (cipher_nid != -1) {
+        cipher = cipher_fetch = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(cipher_nid), propq);
+        /* Fallback to legacy method */
+        if (cipher == NULL)
+            cipher = EVP_get_cipherbynid(cipher_nid);
+
+        if (cipher == NULL) {
             ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_CIPHER,
                            OBJ_nid2sn(cipher_nid));
-            return 0;
+            goto err;
         }
     }
 
-    if (md_nid == -1)
-        md = NULL;
-    else {
-        md = EVP_get_digestbynid(md_nid);
-        if (!md) {
+    if (md_nid != -1) {
+        md = md_fetch = EVP_MD_fetch(libctx, OBJ_nid2sn(md_nid), propq);
+        /* Fallback to legacy method */
+        if (md == NULL)
+            EVP_get_digestbynid(md_nid);
+
+        if (md == NULL) {
             ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_DIGEST);
-            return 0;
+            goto err;
         }
     }
 
-    return keygen(ctx, pass, passlen, param, cipher, md, en_de);
+    /* Try extended keygen with libctx/propq first, fall back to legacy keygen */
+    if (keygen_ex != NULL)
+        ret = keygen_ex(ctx, pass, passlen, param, cipher, md, en_de, libctx, propq);
+    else
+        ret = keygen(ctx, pass, passlen, param, cipher, md, en_de);
+
+err:
+    EVP_CIPHER_free(cipher_fetch);
+    EVP_MD_free(md_fetch);
+
+    return ret;
+}
+
+int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
+{
+    return EVP_PBE_CipherInit_ex(pbe_obj, pass, passlen, param, ctx, en_de, NULL, NULL);
 }
 
 DECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2);
@@ -205,8 +233,8 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
                                 cipher_nid, md_nid, keygen);
 }
 
-int EVP_PBE_find(int type, int pbe_nid,
-                 int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
+int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+                    EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **pkeygen_ex)
 {
     EVP_PBE_CTL *pbetmp = NULL, pbelu;
     int i;
@@ -225,15 +253,23 @@ int EVP_PBE_find(int type, int pbe_nid,
     }
     if (pbetmp == NULL)
         return 0;
-    if (pcnid)
+    if (pcnid != NULL)
         *pcnid = pbetmp->cipher_nid;
-    if (pmnid)
+    if (pmnid != NULL)
         *pmnid = pbetmp->md_nid;
-    if (pkeygen)
+    if (pkeygen != NULL)
         *pkeygen = pbetmp->keygen;
+    if (pkeygen_ex != NULL)
+        *pkeygen_ex = pbetmp->keygen_ex;
     return 1;
 }
 
+int EVP_PBE_find(int type, int pbe_nid,
+                 int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
+{
+    return EVP_PBE_find_ex(type, pbe_nid, pcnid, pmnid, pkeygen, NULL);
+}
+
 static void free_evp_pbe_ctl(EVP_PBE_CTL *pbe)
 {
     OPENSSL_free(pbe);
diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c
index b8edf4b5a8..e7a2b51091 100644
--- a/crypto/evp/p5_crpt2.c
+++ b/crypto/evp/p5_crpt2.c
@@ -21,8 +21,7 @@
 
 int ossl_pkcs5_pbkdf2_hmac_ex(const char *pass, int passlen,
                               const unsigned char *salt, int saltlen, int iter,
-                              const EVP_MD *digest, int keylen,
-                              unsigned char *out,
+                              const EVP_MD *digest, int keylen, unsigned char *out,
                               OSSL_LIB_CTX *libctx, const char *propq)
 {
     const char *empty = "";
@@ -108,13 +107,16 @@ int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
  * them...
  */
 
-int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
-                          ASN1_TYPE *param, const EVP_CIPHER *c,
-                          const EVP_MD *md, int en_de)
+int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                             ASN1_TYPE *param, const EVP_CIPHER *c,
+                             const EVP_MD *md, int en_de,
+                             OSSL_LIB_CTX *libctx, const char *propq)
 {
     PBE2PARAM *pbe2 = NULL;
-    const EVP_CIPHER *cipher;
-    EVP_PBE_KEYGEN *kdf;
+    char ciph_name[80];
+    const EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER *cipher_fetch = NULL;
+    EVP_PBE_KEYGEN_EX *kdf;
 
     int rv = 0;
 
@@ -125,8 +127,8 @@ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
     }
 
     /* See if we recognise the key derivation function */
-    if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
-                        NULL, NULL, &kdf)) {
+    if (!EVP_PBE_find_ex(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm),
+                         NULL, NULL, NULL, &kdf)) {
         ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
         goto err;
     }
@@ -134,10 +136,17 @@ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
     /*
      * lets see if we recognise the encryption algorithm.
      */
+    if (OBJ_obj2txt(ciph_name, sizeof(ciph_name), pbe2->encryption->algorithm, 0) <= 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
+        goto err;
+    }
 
-    cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
+    cipher = cipher_fetch = EVP_CIPHER_fetch(libctx, ciph_name, propq);
+    /* Fallback to legacy method */
+    if (cipher == NULL)
+        cipher = EVP_get_cipherbyname(ciph_name);
 
-    if (!cipher) {
+    if (cipher == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_CIPHER);
         goto err;
     }
@@ -149,15 +158,24 @@ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
         ERR_raise(ERR_LIB_EVP, EVP_R_CIPHER_PARAMETER_ERROR);
         goto err;
     }
-    rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de);
+    rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de, libctx, propq);
  err:
+    EVP_CIPHER_free(cipher_fetch);
     PBE2PARAM_free(pbe2);
     return rv;
 }
 
-int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
-                             int passlen, ASN1_TYPE *param,
-                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                          ASN1_TYPE *param, const EVP_CIPHER *c,
+                          const EVP_MD *md, int en_de)
+{
+    return PKCS5_v2_PBE_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de, NULL, NULL);
+}
+
+int PKCS5_v2_PBKDF2_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                int passlen, ASN1_TYPE *param,
+                                const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+                                OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
     int saltlen, iter, t;
@@ -165,7 +183,8 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     unsigned int keylen = 0;
     int prf_nid, hmac_md_nid;
     PBKDF2PARAM *kdf = NULL;
-    const EVP_MD *prfmd;
+    const EVP_MD *prfmd = NULL;
+    EVP_MD *prfmd_fetch = NULL;
 
     if (EVP_CIPHER_CTX_get0_cipher(ctx) == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_NO_CIPHER_SET);
@@ -207,7 +226,9 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
         goto err;
     }
 
-    prfmd = EVP_get_digestbynid(hmac_md_nid);
+    prfmd = prfmd_fetch = EVP_MD_fetch(libctx, OBJ_nid2sn(hmac_md_nid), propq);
+    if (prfmd == NULL)
+        prfmd = EVP_get_digestbynid(hmac_md_nid);
     if (prfmd == NULL) {
         ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_PRF);
         goto err;
@@ -222,12 +243,21 @@ int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
     salt = kdf->salt->value.octet_string->data;
     saltlen = kdf->salt->value.octet_string->length;
     iter = ASN1_INTEGER_get(kdf->iter);
-    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
-                           keylen, key))
+    if (!ossl_pkcs5_pbkdf2_hmac_ex(pass, passlen, salt, saltlen, iter, prfmd,
+                                   keylen, key, libctx, propq))
         goto err;
     rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
  err:
     OPENSSL_cleanse(key, keylen);
     PBKDF2PARAM_free(kdf);
+    EVP_MD_free(prfmd_fetch);
     return rv;
 }
+
+int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+                             int passlen, ASN1_TYPE *param,
+                             const EVP_CIPHER *c, const EVP_MD *md, int en_de)
+{
+    return PKCS5_v2_PBKDF2_keyivgen_ex(ctx, pass, passlen, param, c, md, en_de,
+                                       NULL, NULL);
+}
diff --git a/crypto/evp/pbe_scrypt.c b/crypto/evp/pbe_scrypt.c
index 2537a073dd..78b2d13ec9 100644
--- a/crypto/evp/pbe_scrypt.c
+++ b/crypto/evp/pbe_scrypt.c
@@ -34,10 +34,11 @@
 # define SCRYPT_MAX_MEM  (1024 * 1024 * 32)
 #endif
 
-int EVP_PBE_scrypt(const char *pass, size_t passlen,
-                   const unsigned char *salt, size_t saltlen,
-                   uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
-                   unsigned char *key, size_t keylen)
+int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+                      const unsigned char *salt, size_t saltlen,
+                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                      unsigned char *key, size_t keylen,
+                      OSSL_LIB_CTX *ctx, const char *propq)
 {
     const char *empty = "";
     int rv = 1;
@@ -63,7 +64,7 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
         maxmem = SCRYPT_MAX_MEM;
 
     /* Use OSSL_LIB_CTX_set0_default() if you need a library context */
-    kdf = EVP_KDF_fetch(NULL, OSSL_KDF_NAME_SCRYPT, NULL);
+    kdf = EVP_KDF_fetch(ctx, OSSL_KDF_NAME_SCRYPT, propq);
     kctx = EVP_KDF_CTX_new(kdf);
     EVP_KDF_free(kdf);
     if (kctx == NULL)
@@ -86,4 +87,13 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
     return rv;
 }
 
+int EVP_PBE_scrypt(const char *pass, size_t passlen,
+                   const unsigned char *salt, size_t saltlen,
+                   uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                   unsigned char *key, size_t keylen)
+{
+    return EVP_PBE_scrypt_ex(pass, passlen, salt, saltlen, N, r, p, maxmem,
+                             key, keylen, NULL, NULL);
+}
+
 #endif
diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c
index 4b6e6b9c22..f0b0819f84 100644
--- a/crypto/pkcs12/p12_add.c
+++ b/crypto/pkcs12/p12_add.c
@@ -9,8 +9,11 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
+#include <openssl/core.h>
+#include <openssl/core_names.h>
 #include <openssl/pkcs12.h>
 #include "p12_local.h"
+#include "crypto/pkcs7/pk7_local.h"
 
 /* Pack an object into an OCTET STRING and turn into a safebag */
 
@@ -80,15 +83,17 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7)
 
 /* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */
 
-PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
-                             unsigned char *salt, int saltlen, int iter,
-                             STACK_OF(PKCS12_SAFEBAG) *bags)
+PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+                                unsigned char *salt, int saltlen, int iter,
+                                STACK_OF(PKCS12_SAFEBAG) *bags,
+                                OSSL_LIB_CTX *ctx, const char *propq)
 {
     PKCS7 *p7;
     X509_ALGOR *pbe;
-    const EVP_CIPHER *pbe_ciph;
+    const EVP_CIPHER *pbe_ciph = NULL;
+    EVP_CIPHER *pbe_ciph_fetch = NULL;
 
-    if ((p7 = PKCS7_new()) == NULL) {
+    if ((p7 = PKCS7_new_ex(ctx, propq)) == NULL) {
         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -97,12 +102,16 @@ PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
         goto err;
     }
 
-    pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+    pbe_ciph = pbe_ciph_fetch = EVP_CIPHER_fetch(ctx, OBJ_nid2sn(pbe_nid), propq);
+    if (pbe_ciph == NULL)
+        pbe_ciph = EVP_get_cipherbynid(pbe_nid);
 
-    if (pbe_ciph)
-        pbe = PKCS5_pbe2_set(pbe_ciph, iter, salt, saltlen);
-    else
-        pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+    if (pbe_ciph != NULL) {
+        pbe = PKCS5_pbe2_set_iv_ex(pbe_ciph, iter, salt, saltlen, NULL, -1, ctx);
+    } else {
+        ERR_clear_error();
+        pbe = PKCS5_pbe_set_ex(pbe_nid, iter, salt, saltlen, ctx);
+    }
 
     if (pbe == NULL) {
         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
@@ -112,34 +121,52 @@ PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
     p7->d.encrypted->enc_data->algorithm = pbe;
     ASN1_OCTET_STRING_free(p7->d.encrypted->enc_data->enc_data);
     if (!(p7->d.encrypted->enc_data->enc_data =
-          PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass,
-                                  passlen, bags, 1))) {
+          PKCS12_item_i2d_encrypt_ex(pbe, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), pass,
+                                     passlen, bags, 1, ctx, propq))) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
         goto err;
     }
 
+    EVP_CIPHER_free(pbe_ciph_fetch);
     return p7;
 
  err:
     PKCS7_free(p7);
+    EVP_CIPHER_free(pbe_ciph_fetch);
     return NULL;
 }
 
+PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+                             unsigned char *salt, int saltlen, int iter,
+                             STACK_OF(PKCS12_SAFEBAG) *bags)
+{
+    return PKCS12_pack_p7encdata_ex(pbe_nid, pass, passlen, salt, saltlen,
+                                    iter, bags, NULL, NULL);
+}
+
 STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
                                                   int passlen)
 {
     if (!PKCS7_type_is_encrypted(p7))
         return NULL;
-    return PKCS12_item_decrypt_d2i(p7->d.encrypted->enc_data->algorithm,
+    return PKCS12_item_decrypt_d2i_ex(p7->d.encrypted->enc_data->algorithm,
                                    ASN1_ITEM_rptr(PKCS12_SAFEBAGS),
                                    pass, passlen,
-                                   p7->d.encrypted->enc_data->enc_data, 1);
+                                   p7->d.encrypted->enc_data->enc_data, 1,
+                                   p7->ctx.libctx, p7->ctx.propq);
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+                                            const char *pass, int passlen,
+                                            OSSL_LIB_CTX *ctx, const char *propq)
+{
+    return PKCS8_decrypt_ex(bag->value.shkeybag, pass, passlen, ctx, propq);
 }
 
 PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
                                          const char *pass, int passlen)
 {
-    return PKCS8_decrypt(bag->value.shkeybag, pass, passlen);
+    return PKCS12_decrypt_skey_ex(bag, pass, passlen, NULL, NULL);
 }
 
 int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes)
@@ -152,10 +179,25 @@ int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes)
 
 STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12)
 {
+    STACK_OF(PKCS7) *p7s;
+    PKCS7 *p7;
+    int i;
+
     if (!PKCS7_type_is_data(p12->authsafes)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
         return NULL;
     }
-    return ASN1_item_unpack(p12->authsafes->d.data,
-                            ASN1_ITEM_rptr(PKCS12_AUTHSAFES));
+    p7s = ASN1_item_unpack(p12->authsafes->d.data,
+                           ASN1_ITEM_rptr(PKCS12_AUTHSAFES));
+    if (p7s != NULL) {
+        for (i = 0; i < sk_PKCS7_num(p7s); i++) {
+            p7 = sk_PKCS7_value(p7s, i);
+            if (!ossl_pkcs7_ctx_propagate(p12->authsafes, p7))
+                goto err;
+        }
+    }
+    return p7s;
+err:
+    sk_PKCS7_free(p7s);
+    return NULL;
 }
diff --git a/crypto/pkcs12/p12_crpt.c b/crypto/pkcs12/p12_crpt.c
index 8a6f71f7bb..aeea598696 100644
--- a/crypto/pkcs12/p12_crpt.c
+++ b/crypto/pkcs12/p12_crpt.c
@@ -9,6 +9,9 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
+#include <openssl/core.h>
+#include <openssl/core_names.h>
+#include "crypto/evp.h"
 #include <openssl/pkcs12.h>
 
 /* PKCS#12 PBE algorithms now in static table */
@@ -17,21 +20,16 @@ void PKCS12_PBE_add(void)
 {
 }
 
-int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
-                        ASN1_TYPE *param, const EVP_CIPHER *cipher,
-                        const EVP_MD *md, int en_de)
+int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                           ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                           const EVP_MD *md, int en_de,
+                           OSSL_LIB_CTX *libctx, const char *propq)
 {
     PBEPARAM *pbe;
     int saltlen, iter, ret;
     unsigned char *salt;
     unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
-    int (*pkcs12_key_gen)(const char *pass, int passlen,
-                          unsigned char *salt, int slen,
-                          int id, int iter, int n,
-                          unsigned char *out,
-                          const EVP_MD *md_type);
-
-    pkcs12_key_gen = PKCS12_key_gen_utf8;
+    unsigned char *piv = iv;
 
     if (cipher == NULL)
         return 0;
@@ -50,21 +48,36 @@ int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
         iter = ASN1_INTEGER_get(pbe->iter);
     salt = pbe->salt->data;
     saltlen = pbe->salt->length;
-    if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_KEY_ID,
-                           iter, EVP_CIPHER_key_length(cipher), key, md)) {
+    if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_KEY_ID,
+                                iter, EVP_CIPHER_key_length(cipher), key, md,
+                                libctx, propq)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
         PBEPARAM_free(pbe);
         return 0;
     }
-    if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_IV_ID,
-                           iter, EVP_CIPHER_iv_length(cipher), iv, md)) {
-        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_IV_GEN_ERROR);
-        PBEPARAM_free(pbe);
-        return 0;
+    if (EVP_CIPHER_iv_length(cipher) > 0) {
+        if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_IV_ID,
+                                    iter, EVP_CIPHER_iv_length(cipher), iv, md,
+                                    libctx, propq)) {
+            ERR_raise(ERR_LIB_PKCS12, PKCS12_R_IV_GEN_ERROR);
+            PBEPARAM_free(pbe);
+            return 0;
+        }
+    } else {
+        piv = NULL;
     }
     PBEPARAM_free(pbe);
-    ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de);
+    ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, piv, en_de);
     OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
     OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
     return ret;
 }
+
+int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                        ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                        const EVP_MD *md, int en_de)
+{
+    return PKCS12_PBE_keyivgen_ex(ctx, pass, passlen, param, cipher, md, en_de,
+                                  NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c
index f735cb2a67..00c7129746 100644
--- a/crypto/pkcs12/p12_crt.c
+++ b/crypto/pkcs12/p12_crt.c
@@ -28,9 +28,10 @@ static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
     return 1;
 }
 
-PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
-                      STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
-                      int mac_iter, int keytype)
+PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+                         X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+                         int iter, int mac_iter, int keytype,
+                         OSSL_LIB_CTX *ctx, const char *propq)
 {
     PKCS12 *p12 = NULL;
     STACK_OF(PKCS7) *safes = NULL;
@@ -76,14 +77,16 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
             goto err;
     }
 
-    if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
+    if (bags && !PKCS12_add_safe_ex(&safes, bags, nid_cert, iter, pass,
+                                    ctx, propq))
         goto err;
 
     sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
     bags = NULL;
 
     if (pkey) {
-        bag = PKCS12_add_key(&bags, pkey, keytype, iter, nid_key, pass);
+        bag = PKCS12_add_key_ex(&bags, pkey, keytype, iter, nid_key, pass,
+                                ctx, propq);
 
         if (!bag)
             goto err;
@@ -105,7 +108,7 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
     sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
     bags = NULL;
 
-    p12 = PKCS12_add_safes(safes, 0);
+    p12 = PKCS12_add_safes_ex(safes, 0, ctx, propq);
 
     if (p12 == NULL)
         goto err;
@@ -128,6 +131,14 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *
 
 }
 
+PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 *cert,
+                      STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter,
+                      int mac_iter, int keytype)
+{
+    return PKCS12_create_ex(pass, name, pkey, cert, ca, nid_key, nid_cert,
+                            iter, mac_iter, keytype, NULL, NULL);
+}
+
 PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
 {
     PKCS12_SAFEBAG *bag = NULL;
@@ -165,9 +176,10 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
 
 }
 
-PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
-                               EVP_PKEY *key, int key_usage, int iter,
-                               int nid_key, const char *pass)
+PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                                  EVP_PKEY *key, int key_usage, int iter,
+                                  int nid_key, const char *pass,
+                                  OSSL_LIB_CTX *ctx, const char *propq)
 {
 
     PKCS12_SAFEBAG *bag = NULL;
@@ -179,8 +191,8 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
     if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
         goto err;
     if (nid_key != -1) {
-        bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(nid_key, pass, -1, NULL, 0,
-                                                  iter, p8);
+        bag = PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(nid_key, pass, -1, NULL, 0,
+                                                     iter, p8, ctx, propq);
         PKCS8_PRIV_KEY_INFO_free(p8);
     } else
         bag = PKCS12_SAFEBAG_create0_p8inf(p8);
@@ -199,6 +211,14 @@ PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
 
 }
 
+PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                               EVP_PKEY *key, int key_usage, int iter,
+                               int nid_key, const char *pass)
+{
+    return PKCS12_add_key_ex(pbags, key, key_usage, iter, nid_key, pass,
+                             NULL, NULL);
+}
+
 PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags, 
                                   int nid_type, const unsigned char *value, int len)
 {
@@ -217,8 +237,9 @@ PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
     return NULL;
 }
 
-int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
-                    int nid_safe, int iter, const char *pass)
+int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+                       int nid_safe, int iter, const char *pass,
+                       OSSL_LIB_CTX *ctx, const char *propq)
 {
     PKCS7 *p7 = NULL;
     int free_safes = 0;
@@ -240,7 +261,7 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
     if (nid_safe == -1)
         p7 = PKCS12_pack_p7data(bags);
     else
-        p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0, iter, bags);
+        p7 = PKCS12_pack_p7encdata_ex(nid_safe, pass, -1, NULL, 0, iter, bags, ctx, propq);
     if (p7 == NULL)
         goto err;
 
@@ -256,7 +277,12 @@ int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
     }
     PKCS7_free(p7);
     return 0;
+}
 
+int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+                    int nid_safe, int iter, const char *pass)
+{
+    return PKCS12_add_safe_ex(psafes, bags, nid_safe, iter, pass, NULL, NULL);
 }
 
 static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
@@ -285,13 +311,14 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
 
 }
 
-PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int nid_p7,
+                            OSSL_LIB_CTX *ctx, const char *propq)
 {
     PKCS12 *p12;
 
     if (nid_p7 <= 0)
         nid_p7 = NID_pkcs7_data;
-    p12 = PKCS12_init(nid_p7);
+    p12 = PKCS12_init_ex(nid_p7, ctx, propq);
     if (p12 == NULL)
         return NULL;
 
@@ -303,3 +330,8 @@ PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
     return p12;
 
 }
+
+PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+{
+    return PKCS12_add_safes_ex(safes, nid_p7, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c
index e7a32f9cd6..ef316d044b 100644
--- a/crypto/pkcs12/p12_decr.c
+++ b/crypto/pkcs12/p12_decr.c
@@ -16,10 +16,11 @@
  * Encrypt/Decrypt a buffer based on password and algor, result in a
  * OPENSSL_malloc'ed buffer
  */
-unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
-                                const char *pass, int passlen,
-                                const unsigned char *in, int inlen,
-                                unsigned char **data, int *datalen, int en_de)
+unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+                                   const char *pass, int passlen,
+                                   const unsigned char *in, int inlen,
+                                   unsigned char **data, int *datalen, int en_de,
+                                   OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned char *out = NULL;
     int outlen, i;
@@ -32,8 +33,8 @@ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
     }
 
     /* Process data */
-    if (!EVP_PBE_CipherInit(algor->algorithm, pass, passlen,
-                            algor->parameter, ctx, en_de))
+    if (!EVP_PBE_CipherInit_ex(algor->algorithm, pass, passlen,
+                               algor->parameter, ctx, en_de, libctx, propq))
         goto err;
 
     /*
@@ -109,22 +110,33 @@ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
 
 }
 
+unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
+                                const char *pass, int passlen,
+                                const unsigned char *in, int inlen,
+                                unsigned char **data, int *datalen, int en_de)
+{
+    return PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, data, datalen,
+                               en_de, NULL, NULL);
+}
+
 /*
  * Decrypt an OCTET STRING and decode ASN1 structure if zbuf set zero buffer
  * after use.
  */
 
-void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
-                              const char *pass, int passlen,
-                              const ASN1_OCTET_STRING *oct, int zbuf)
+void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+                                 const char *pass, int passlen,
+                                 const ASN1_OCTET_STRING *oct, int zbuf,
+                                 OSSL_LIB_CTX *libctx,
+                                 const char *propq)
 {
     unsigned char *out = NULL;
     const unsigned char *p;
     void *ret;
     int outlen = 0;
 
-    if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length,
-                          &out, &outlen, 0))
+    if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, oct->data, oct->length,
+                             &out, &outlen, 0, libctx, propq))
         return NULL;
     p = out;
     OSSL_TRACE_BEGIN(PKCS12_DECRYPT) {
@@ -141,15 +153,25 @@ void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
     return ret;
 }
 
+void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
+                              const char *pass, int passlen,
+                              const ASN1_OCTET_STRING *oct, int zbuf)
+{
+    return PKCS12_item_decrypt_d2i_ex(algor, it, pass, passlen, oct, zbuf,
+                                      NULL, NULL);
+}
+
 /*
  * Encode ASN1 structure and encrypt, return OCTET STRING if zbuf set zero
  * encoding.
  */
 
-ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
-                                           const ASN1_ITEM *it,
-                                           const char *pass, int passlen,
-                                           void *obj, int zbuf)
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+                                              const ASN1_ITEM *it,
+                                              const char *pass, int passlen,
+                                              void *obj, int zbuf,
+                                              OSSL_LIB_CTX *ctx,
+                                              const char *propq)
 {
     ASN1_OCTET_STRING *oct = NULL;
     unsigned char *in = NULL;
@@ -164,8 +186,8 @@ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCODE_ERROR);
         goto err;
     }
-    if (!PKCS12_pbe_crypt(algor, pass, passlen, in, inlen, &oct->data,
-                          &oct->length, 1)) {
+    if (!PKCS12_pbe_crypt_ex(algor, pass, passlen, in, inlen, &oct->data,
+                             &oct->length, 1, ctx, propq)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
         OPENSSL_free(in);
         goto err;
@@ -178,3 +200,11 @@ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
     ASN1_OCTET_STRING_free(oct);
     return NULL;
 }
+
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
+                                           const ASN1_ITEM *it,
+                                           const char *pass, int passlen,
+                                           void *obj, int zbuf)
+{
+    return PKCS12_item_i2d_encrypt_ex(algor, it, pass, passlen, obj, zbuf, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c
index 3ab7692ab9..dcfdd5ba13 100644
--- a/crypto/pkcs12/p12_init.c
+++ b/crypto/pkcs12/p12_init.c
@@ -10,11 +10,12 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/pkcs12.h>
+#include "crypto/pkcs7.h"
 #include "p12_local.h"
 
 /* Initialise a PKCS12 structure to take data */
 
-PKCS12 *PKCS12_init(int mode)
+PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq)
 {
     PKCS12 *pkcs12;
 
@@ -25,6 +26,13 @@ PKCS12 *PKCS12_init(int mode)
     if (!ASN1_INTEGER_set(pkcs12->version, 3))
         goto err;
     pkcs12->authsafes->type = OBJ_nid2obj(mode);
+
+    ossl_pkcs7_set0_libctx(pkcs12->authsafes, ctx);
+    if (!ossl_pkcs7_set1_propq(pkcs12->authsafes, propq)) {
+        ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
     switch (mode) {
     case NID_pkcs7_data:
         if ((pkcs12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) {
@@ -42,3 +50,9 @@ PKCS12 *PKCS12_init(int mode)
     PKCS12_free(pkcs12);
     return NULL;
 }
+
+PKCS12 *PKCS12_init(int mode)
+{
+    return PKCS12_init_ex(mode, NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c
index fd7f7a926b..a4ed0e516c 100644
--- a/crypto/pkcs12/p12_key.c
+++ b/crypto/pkcs12/p12_key.c
@@ -16,9 +16,10 @@
 #include <openssl/core_names.h>
 #include "internal/provider.h"
 
-int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
-                       int saltlen, int id, int iter, int n,
-                       unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+                          int saltlen, int id, int iter, int n,
+                          unsigned char *out, const EVP_MD *md_type,
+                          OSSL_LIB_CTX *ctx, const char *propq)
 {
     int ret;
     unsigned char *unipass;
@@ -31,15 +32,24 @@ int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
-                             id, iter, n, out, md_type);
+    ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
+                                n, out, md_type, ctx, propq);
     OPENSSL_clear_free(unipass, uniplen);
     return ret > 0;
 }
 
-int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
-                        int saltlen, int id, int iter, int n,
-                        unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+                       int saltlen, int id, int iter, int n,
+                       unsigned char *out, const EVP_MD *md_type)
+{
+    return PKCS12_key_gen_asc_ex(pass, passlen, salt, saltlen, id, iter, n,
+                                  out, md_type, NULL, NULL);    
+}
+
+int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+                           int saltlen, int id, int iter, int n,
+                           unsigned char *out, const EVP_MD *md_type,
+                           OSSL_LIB_CTX *ctx, const char *propq)
 {
     int ret;
     unsigned char *unipass;
@@ -52,15 +62,24 @@ int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
         ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    ret = PKCS12_key_gen_uni(unipass, uniplen, salt, saltlen,
-                             id, iter, n, out, md_type);
+    ret = PKCS12_key_gen_uni_ex(unipass, uniplen, salt, saltlen, id, iter,
+                                n, out, md_type, ctx, propq);
     OPENSSL_clear_free(unipass, uniplen);
     return ret > 0;
 }
 
-int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
-                       int saltlen, int id, int iter, int n,
-                       unsigned char *out, const EVP_MD *md_type)
+int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
+                        int saltlen, int id, int iter, int n,
+                        unsigned char *out, const EVP_MD *md_type)
+{
+    return PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, id, iter, n,
+                                  out, md_type, NULL, NULL);
+}
+
+int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+                          int saltlen, int id, int iter, int n,
+                          unsigned char *out, const EVP_MD *md_type,
+                          OSSL_LIB_CTX *libctx, const char *propq)
 {
     int res = 0;
     EVP_KDF *kdf;
@@ -70,12 +89,7 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
     if (n <= 0)
         return 0;
 
-    /*
-     * The parameter query isn't available but the library context can be
-     * extracted from the passed digest.
-     */
-    kdf = EVP_KDF_fetch(ossl_provider_libctx(EVP_MD_provider(md_type)),
-                        "PKCS12KDF", NULL);
+    kdf = EVP_KDF_fetch(libctx, "PKCS12KDF", propq);
     if (kdf == NULL)
         return 0;
     ctx = EVP_KDF_CTX_new(kdf);
@@ -92,11 +106,9 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
     *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS12_ID, &id);
     *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_ITER, &iter);
     *p = OSSL_PARAM_construct_end();
-    if (!EVP_KDF_CTX_set_params(ctx, params))
-        goto err;
 
     OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
-        BIO_printf(trc_out, "PKCS12_key_gen_uni(): ID %d, ITER %d\n", id, iter);
+        BIO_printf(trc_out, "PKCS12_key_gen_uni_ex(): ID %d, ITER %d\n", id, iter);
         BIO_printf(trc_out, "Password (length %d):\n", passlen);
         BIO_hex_string(trc_out, 0, passlen, pass, passlen);
         BIO_printf(trc_out, "\n");
@@ -105,7 +117,7 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
         BIO_printf(trc_out, "\n");
     } OSSL_TRACE_END(PKCS12_KEYGEN);
 
-    if (EVP_KDF_derive(ctx, out, (size_t)n, NULL)) {
+    if (EVP_KDF_derive(ctx, out, (size_t)n, params)) {
         res = 1;
         OSSL_TRACE_BEGIN(PKCS12_KEYGEN) {
             BIO_printf(trc_out, "Output KEY (length %d)\n", n);
@@ -113,7 +125,13 @@ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
             BIO_printf(trc_out, "\n");
         } OSSL_TRACE_END(PKCS12_KEYGEN);
     }
- err:
     EVP_KDF_CTX_free(ctx);
     return res;
 }
+
+int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
+                       int saltlen, int id, int iter, int n,
+                       unsigned char *out, const EVP_MD *md_type)
+{
+    return PKCS12_key_gen_uni_ex(pass, passlen, salt, saltlen, id, iter, n, out, md_type, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
index 70b3ec702b..f072436110 100644
--- a/crypto/pkcs12/p12_mutl.c
+++ b/crypto/pkcs12/p12_mutl.c
@@ -82,18 +82,17 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
                                                 const EVP_MD *md_type))
 {
     int ret = 0;
-    const EVP_MD *md_type;
+    const EVP_MD *md;
+    EVP_MD *md_fetch;
     HMAC_CTX *hmac = NULL;
     unsigned char key[EVP_MAX_MD_SIZE], *salt;
     int saltlen, iter;
+    char md_name[80];
     int md_size = 0;
-    int md_type_nid;
+    int md_nid;
     const X509_ALGOR *macalg;
     const ASN1_OBJECT *macoid;
 
-    if (pkcs12_key_gen == NULL)
-        pkcs12_key_gen = PKCS12_key_gen_utf8;
-
     if (!PKCS7_type_is_data(p12->authsafes)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA);
         return 0;
@@ -107,32 +106,51 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
         iter = ASN1_INTEGER_get(p12->mac->iter);
     X509_SIG_get0(p12->mac->dinfo, &macalg, NULL);
     X509_ALGOR_get0(&macoid, NULL, NULL, macalg);
-    if ((md_type = EVP_get_digestbyobj(macoid)) == NULL) {
+    if (OBJ_obj2txt(md_name, sizeof(md_name), macoid, 0) < 0)
+        return 0;
+    md = md_fetch = EVP_MD_fetch(p12->authsafes->ctx.libctx, md_name,
+                                 p12->authsafes->ctx.propq);
+    if (md == NULL)
+        md = EVP_get_digestbynid(OBJ_obj2nid(macoid));
+
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
         return 0;
     }
-    md_size = EVP_MD_size(md_type);
-    md_type_nid = EVP_MD_type(md_type);
+    md_size = EVP_MD_size(md);
+    md_nid = EVP_MD_type(md);
     if (md_size < 0)
-        return 0;
-    if ((md_type_nid == NID_id_GostR3411_94
-         || md_type_nid == NID_id_GostR3411_2012_256
-         || md_type_nid == NID_id_GostR3411_2012_512)
+        goto err;
+    if ((md_nid == NID_id_GostR3411_94
+         || md_nid == NID_id_GostR3411_2012_256
+         || md_nid == NID_id_GostR3411_2012_512)
         && ossl_safe_getenv("LEGACY_GOST_PKCS12") == NULL) {
         md_size = TK26_MAC_KEY_LEN;
         if (!pkcs12_gen_gost_mac_key(pass, passlen, salt, saltlen, iter,
-                                     md_size, key, md_type)) {
+                                     md_size, key, md)) {
             ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
             goto err;
         }
-    } else
-        if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
-                               iter, md_size, key, md_type)) {
-        ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
-        goto err;
+    } else {
+        if (pkcs12_key_gen != NULL) {
+            if (!(*pkcs12_key_gen)(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+                                   iter, md_size, key, md)) {
+                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+                goto err;
+            }
+        } else {
+            /* Default to UTF-8 password */
+            if (!PKCS12_key_gen_utf8_ex(pass, passlen, salt, saltlen, PKCS12_MAC_ID,
+                                       iter, md_size, key, md,
+                                       p12->authsafes->ctx.libctx,
+                                       p12->authsafes->ctx.propq)) {
+                ERR_raise(ERR_LIB_PKCS12, PKCS12_R_KEY_GEN_ERROR);
+                goto err;
+            }
+        }
     }
     if ((hmac = HMAC_CTX_new()) == NULL
-        || !HMAC_Init_ex(hmac, key, md_size, md_type, NULL)
+        || !HMAC_Init_ex(hmac, key, md_size, md, NULL)
         || !HMAC_Update(hmac, p12->authsafes->d.data->data,
                         p12->authsafes->d.data->length)
         || !HMAC_Final(hmac, mac, maclen)) {
@@ -143,6 +161,7 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
 err:
     OPENSSL_cleanse(key, sizeof(key));
     HMAC_CTX_free(hmac);
+    EVP_MD_free(md_fetch);
     return ret;
 }
 
@@ -163,8 +182,7 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_ABSENT);
         return 0;
     }
-    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
-                        PKCS12_key_gen_utf8)) {
+    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
         return 0;
     }
@@ -198,8 +216,7 @@ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
     /*
      * Note that output mac is forced to UTF-8...
      */
-    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen,
-                        PKCS12_key_gen_utf8)) {
+    if (!pkcs12_gen_mac(p12, pass, passlen, mac, &maclen, NULL)) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_GENERATION_ERROR);
         return 0;
     }
@@ -242,7 +259,8 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
     }
     p12->mac->salt->length = saltlen;
     if (!salt) {
-        if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0)
+        if (RAND_bytes_ex(p12->authsafes->ctx.libctx, p12->mac->salt->data,
+                          saltlen) <= 0)
             return 0;
     } else
         memcpy(p12->mac->salt->data, salt, saltlen);
diff --git a/crypto/pkcs12/p12_p8d.c b/crypto/pkcs12/p12_p8d.c
index 2577cba46c..599a64f878 100644
--- a/crypto/pkcs12/p12_p8d.c
+++ b/crypto/pkcs12/p12_p8d.c
@@ -11,13 +11,22 @@
 #include "internal/cryptlib.h"
 #include <openssl/pkcs12.h>
 
-PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
-                                   int passlen)
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+                                      int passlen, OSSL_LIB_CTX *ctx,
+                                      const char *propq)
 {
     const X509_ALGOR *dalg;
     const ASN1_OCTET_STRING *doct;
+
     X509_SIG_get0(p8, &dalg, &doct);
-    return PKCS12_item_decrypt_d2i(dalg,
+    return PKCS12_item_decrypt_d2i_ex(dalg,
                                    ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass,
-                                   passlen, doct, 1);
+                                   passlen, doct, 1, ctx, propq);
 }
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
+                                   int passlen)
+{
+    return PKCS8_decrypt_ex(p8, pass, passlen, NULL, NULL);
+}
+
diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c
index d98a1d66c2..ac2c7ef537 100644
--- a/crypto/pkcs12/p12_p8e.c
+++ b/crypto/pkcs12/p12_p8e.c
@@ -9,30 +9,34 @@
 
 #include <stdio.h>
 #include "internal/cryptlib.h"
+#include <openssl/core.h>
 #include <openssl/pkcs12.h>
 #include "crypto/x509.h"
 
-X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
-                        const char *pass, int passlen,
-                        unsigned char *salt, int saltlen, int iter,
-                        PKCS8_PRIV_KEY_INFO *p8inf)
+X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+                           const char *pass, int passlen,
+                           unsigned char *salt, int saltlen, int iter,
+                           PKCS8_PRIV_KEY_INFO *p8inf,
+                           OSSL_LIB_CTX *libctx, const char *propq)
 {
     X509_SIG *p8 = NULL;
     X509_ALGOR *pbe;
 
     if (pbe_nid == -1)
-        pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen);
+        pbe = PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, -1,
+                                   libctx);
     else if (EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0))
-        pbe = PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, pbe_nid);
+        pbe = PKCS5_pbe2_set_iv_ex(cipher, iter, salt, saltlen, NULL, pbe_nid,
+                                   libctx);
     else {
         ERR_clear_error();
-        pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+        pbe = PKCS5_pbe_set_ex(pbe_nid, iter, salt, saltlen, libctx);
     }
     if (pbe == NULL) {
         ERR_raise(ERR_LIB_PKCS12, ERR_R_ASN1_LIB);
         return NULL;
     }
-    p8 = PKCS8_set0_pbe(pass, passlen, p8inf, pbe);
+    p8 = PKCS8_set0_pbe_ex(pass, passlen, p8inf, pbe, libctx, propq);
     if (p8 == NULL) {
         X509_ALGOR_free(pbe);
         return NULL;
@@ -41,15 +45,25 @@ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
     return p8;
 }
 
-X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
-                         PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe)
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+                        const char *pass, int passlen,
+                        unsigned char *salt, int saltlen, int iter,
+                        PKCS8_PRIV_KEY_INFO *p8inf)
+{
+    return PKCS8_encrypt_ex(pbe_nid, cipher, pass, passlen, salt, saltlen, iter,
+                            p8inf, NULL, NULL);
+}
+
+X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+                            PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+                            OSSL_LIB_CTX *ctx, const char *propq)
 {
     X509_SIG *p8;
     ASN1_OCTET_STRING *enckey;
 
     enckey =
-        PKCS12_item_i2d_encrypt(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO),
-                                pass, passlen, p8inf, 1);
+        PKCS12_item_i2d_encrypt_ex(pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO),
+                                   pass, passlen, p8inf, 1, ctx, propq);
     if (!enckey) {
         ERR_raise(ERR_LIB_PKCS12, PKCS12_R_ENCRYPT_ERROR);
         return NULL;
@@ -67,3 +81,9 @@ X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
 
     return p8;
 }
+
+X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+                         PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe)
+{
+    return PKCS8_set0_pbe_ex(pass, passlen, p8inf, pbe, NULL, NULL);
+}
diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c
index 2387a8db43..e439372082 100644
--- a/crypto/pkcs12/p12_sbag.c
+++ b/crypto/pkcs12/p12_sbag.c
@@ -198,29 +198,49 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8)
     return bag;
 }
 
-PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
-                                                    const char *pass,
-                                                    int passlen,
-                                                    unsigned char *salt,
-                                                    int saltlen, int iter,
-                                                    PKCS8_PRIV_KEY_INFO *p8inf)
-{
-    PKCS12_SAFEBAG *bag;
-    const EVP_CIPHER *pbe_ciph;
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+                                                       const char *pass,
+                                                       int passlen,
+                                                       unsigned char *salt,
+                                                       int saltlen, int iter,
+                                                       PKCS8_PRIV_KEY_INFO *p8inf,
+                                                       OSSL_LIB_CTX *ctx,
+                                                       const char *propq)
+{
+    PKCS12_SAFEBAG *bag = NULL;
+    const EVP_CIPHER *pbe_ciph = NULL;
+    EVP_CIPHER *pbe_ciph_fetch = NULL;
     X509_SIG *p8;
 
-    pbe_ciph = EVP_get_cipherbynid(pbe_nid);
-    if (pbe_ciph)
+    pbe_ciph = pbe_ciph_fetch = EVP_CIPHER_fetch(ctx, OBJ_nid2sn(pbe_nid), propq);
+    if (pbe_ciph == NULL)
+        pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+
+    if (pbe_ciph != NULL)
         pbe_nid = -1;
 
-    p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
-                       p8inf);
+    p8 = PKCS8_encrypt_ex(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
+                          p8inf, ctx, propq);
     if (p8 == NULL)
-        return NULL;
+        goto err;
 
     bag = PKCS12_SAFEBAG_create0_pkcs8(p8);
     if (bag == NULL)
         X509_SIG_free(p8);
 
+err:
+    EVP_CIPHER_free(pbe_ciph_fetch);
     return bag;
 }
+
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
+                                                    const char *pass,
+                                                    int passlen,
+                                                    unsigned char *salt,
+                                                    int saltlen, int iter,
+                                                    PKCS8_PRIV_KEY_INFO *p8inf)
+{
+    return PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(pbe_nid, pass, passlen,
+                                                  salt, saltlen, iter, p8inf,
+                                                  NULL, NULL);
+}
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index bf959a28d2..a4b62f40dd 100644
--- a/crypto/pkcs7/pk7_lib.c
+++ b/crypto/pkcs7/pk7_lib.c
@@ -469,6 +469,37 @@ const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7)
     return p7 != NULL ? &p7->ctx : NULL;
 }
 
+void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx)
+{
+    p7->ctx.libctx = ctx;
+}
+
+int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq)
+{
+    if (p7->ctx.propq != NULL) {
+        OPENSSL_free(p7->ctx.propq);
+        p7->ctx.propq = NULL;
+    }
+    if (propq != NULL) {
+        p7->ctx.propq = OPENSSL_strdup(propq);
+        if (p7->ctx.propq == NULL) {
+            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+    }
+    return 1;
+}
+
+int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to)
+{
+    ossl_pkcs7_set0_libctx(to, from->ctx.libctx);
+    if (!ossl_pkcs7_set1_propq(to, from->ctx.propq))
+        return 0;
+
+    ossl_pkcs7_resolve_libctx(to);
+    return 1;
+}
+
 OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx)
 {
     return ctx != NULL ? ctx->libctx : NULL;
diff --git a/crypto/pkcs7/pk7_local.h b/crypto/pkcs7/pk7_local.h
index 177ecc196b..8deb342b79 100644
--- a/crypto/pkcs7/pk7_local.h
+++ b/crypto/pkcs7/pk7_local.h
@@ -12,3 +12,5 @@
 const PKCS7_CTX *ossl_pkcs7_get0_ctx(const PKCS7 *p7);
 OSSL_LIB_CTX *ossl_pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx);
 const char *ossl_pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx);
+
+int ossl_pkcs7_ctx_propagate(const PKCS7 *from, PKCS7 *to);
diff --git a/doc/build.info b/doc/build.info
index 86daf403d7..738f10d5f1 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -1118,6 +1118,10 @@ DEPEND[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
 GENERATE[html/man3/EVP_OpenInit.html]=man3/EVP_OpenInit.pod
 DEPEND[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
 GENERATE[man/man3/EVP_OpenInit.3]=man3/EVP_OpenInit.pod
+DEPEND[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
+GENERATE[html/man3/EVP_PBE_CipherInit.html]=man3/EVP_PBE_CipherInit.pod
+DEPEND[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
+GENERATE[man/man3/EVP_PBE_CipherInit.3]=man3/EVP_PBE_CipherInit.pod
 DEPEND[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
 GENERATE[html/man3/EVP_PKEY2PKCS8.html]=man3/EVP_PKEY2PKCS8.pod
 DEPEND[man/man3/EVP_PKEY2PKCS8.3]=man3/EVP_PKEY2PKCS8.pod
@@ -1730,6 +1734,10 @@ DEPEND[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_strea
 GENERATE[html/man3/PEM_write_bio_PKCS7_stream.html]=man3/PEM_write_bio_PKCS7_stream.pod
 DEPEND[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
 GENERATE[man/man3/PEM_write_bio_PKCS7_stream.3]=man3/PEM_write_bio_PKCS7_stream.pod
+DEPEND[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
+GENERATE[html/man3/PKCS12_PBE_keyivgen.html]=man3/PKCS12_PBE_keyivgen.pod
+DEPEND[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
+GENERATE[man/man3/PKCS12_PBE_keyivgen.3]=man3/PKCS12_PBE_keyivgen.pod
 DEPEND[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
 GENERATE[html/man3/PKCS12_SAFEBAG_create_cert.html]=man3/PKCS12_SAFEBAG_create_cert.pod
 DEPEND[man/man3/PKCS12_SAFEBAG_create_cert.3]=man3/PKCS12_SAFEBAG_create_cert.pod
@@ -1770,18 +1778,46 @@ DEPEND[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
 GENERATE[html/man3/PKCS12_create.html]=man3/PKCS12_create.pod
 DEPEND[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
 GENERATE[man/man3/PKCS12_create.3]=man3/PKCS12_create.pod
+DEPEND[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
+GENERATE[html/man3/PKCS12_decrypt_skey.html]=man3/PKCS12_decrypt_skey.pod
+DEPEND[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
+GENERATE[man/man3/PKCS12_decrypt_skey.3]=man3/PKCS12_decrypt_skey.pod
+DEPEND[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
+GENERATE[html/man3/PKCS12_gen_mac.html]=man3/PKCS12_gen_mac.pod
+DEPEND[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
+GENERATE[man/man3/PKCS12_gen_mac.3]=man3/PKCS12_gen_mac.pod
 DEPEND[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
 GENERATE[html/man3/PKCS12_get_friendlyname.html]=man3/PKCS12_get_friendlyname.pod
 DEPEND[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
 GENERATE[man/man3/PKCS12_get_friendlyname.3]=man3/PKCS12_get_friendlyname.pod
+DEPEND[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
+GENERATE[html/man3/PKCS12_init.html]=man3/PKCS12_init.pod
+DEPEND[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
+GENERATE[man/man3/PKCS12_init.3]=man3/PKCS12_init.pod
+DEPEND[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
+GENERATE[html/man3/PKCS12_item_decrypt_d2i.html]=man3/PKCS12_item_decrypt_d2i.pod
+DEPEND[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
+GENERATE[man/man3/PKCS12_item_decrypt_d2i.3]=man3/PKCS12_item_decrypt_d2i.pod
+DEPEND[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
+GENERATE[html/man3/PKCS12_key_gen_utf8_ex.html]=man3/PKCS12_key_gen_utf8_ex.pod
+DEPEND[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
+GENERATE[man/man3/PKCS12_key_gen_utf8_ex.3]=man3/PKCS12_key_gen_utf8_ex.pod
 DEPEND[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
 GENERATE[html/man3/PKCS12_newpass.html]=man3/PKCS12_newpass.pod
 DEPEND[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
 GENERATE[man/man3/PKCS12_newpass.3]=man3/PKCS12_newpass.pod
+DEPEND[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
+GENERATE[html/man3/PKCS12_pack_p7encdata.html]=man3/PKCS12_pack_p7encdata.pod
+DEPEND[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
+GENERATE[man/man3/PKCS12_pack_p7encdata.3]=man3/PKCS12_pack_p7encdata.pod
 DEPEND[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
 GENERATE[html/man3/PKCS12_parse.html]=man3/PKCS12_parse.pod
 DEPEND[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
 GENERATE[man/man3/PKCS12_parse.3]=man3/PKCS12_parse.pod
+DEPEND[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
+GENERATE[html/man3/PKCS5_PBE_keyivgen.html]=man3/PKCS5_PBE_keyivgen.pod
+DEPEND[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
+GENERATE[man/man3/PKCS5_PBE_keyivgen.3]=man3/PKCS5_PBE_keyivgen.pod
 DEPEND[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
 GENERATE[html/man3/PKCS5_PBKDF2_HMAC.html]=man3/PKCS5_PBKDF2_HMAC.pod
 DEPEND[man/man3/PKCS5_PBKDF2_HMAC.3]=man3/PKCS5_PBKDF2_HMAC.pod
@@ -1814,6 +1850,10 @@ DEPEND[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
 GENERATE[html/man3/PKCS7_verify.html]=man3/PKCS7_verify.pod
 DEPEND[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
 GENERATE[man/man3/PKCS7_verify.3]=man3/PKCS7_verify.pod
+DEPEND[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
+GENERATE[html/man3/PKCS8_encrypt.html]=man3/PKCS8_encrypt.pod
+DEPEND[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
+GENERATE[man/man3/PKCS8_encrypt.3]=man3/PKCS8_encrypt.pod
 DEPEND[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
 GENERATE[html/man3/PKCS8_pkey_add1_attr.html]=man3/PKCS8_pkey_add1_attr.pod
 DEPEND[man/man3/PKCS8_pkey_add1_attr.3]=man3/PKCS8_pkey_add1_attr.pod
@@ -2933,6 +2973,7 @@ html/man3/EVP_KEYMGMT.html \
 html/man3/EVP_MAC.html \
 html/man3/EVP_MD_meth_new.html \
 html/man3/EVP_OpenInit.html \
+html/man3/EVP_PBE_CipherInit.html \
 html/man3/EVP_PKEY2PKCS8.html \
 html/man3/EVP_PKEY_ASN1_METHOD.html \
 html/man3/EVP_PKEY_CTX_ctrl.html \
@@ -3086,6 +3127,7 @@ html/man3/PEM_read_bio_PrivateKey.html \
 html/man3/PEM_read_bio_ex.html \
 html/man3/PEM_write_bio_CMS_stream.html \
 html/man3/PEM_write_bio_PKCS7_stream.html \
+html/man3/PKCS12_PBE_keyivgen.html \
 html/man3/PKCS12_SAFEBAG_create_cert.html \
 html/man3/PKCS12_SAFEBAG_get0_attrs.html \
 html/man3/PKCS12_SAFEBAG_get1_cert.html \
@@ -3096,9 +3138,16 @@ html/man3/PKCS12_add_friendlyname_asc.html \
 html/man3/PKCS12_add_localkeyid.html \
 html/man3/PKCS12_add_safe.html \
 html/man3/PKCS12_create.html \
+html/man3/PKCS12_decrypt_skey.html \
+html/man3/PKCS12_gen_mac.html \
 html/man3/PKCS12_get_friendlyname.html \
+html/man3/PKCS12_init.html \
+html/man3/PKCS12_item_decrypt_d2i.html \
+html/man3/PKCS12_key_gen_utf8_ex.html \
 html/man3/PKCS12_newpass.html \
+html/man3/PKCS12_pack_p7encdata.html \
 html/man3/PKCS12_parse.html \
+html/man3/PKCS5_PBE_keyivgen.html \
 html/man3/PKCS5_PBKDF2_HMAC.html \
 html/man3/PKCS7_decrypt.html \
 html/man3/PKCS7_encrypt.html \
@@ -3107,6 +3156,7 @@ html/man3/PKCS7_sign.html \
 html/man3/PKCS7_sign_add_signer.html \
 html/man3/PKCS7_type_is_other.html \
 html/man3/PKCS7_verify.html \
+html/man3/PKCS8_encrypt.html \
 html/man3/PKCS8_pkey_add1_attr.html \
 html/man3/RAND_add.html \
 html/man3/RAND_bytes.html \
@@ -3509,6 +3559,7 @@ man/man3/EVP_KEYMGMT.3 \
 man/man3/EVP_MAC.3 \
 man/man3/EVP_MD_meth_new.3 \
 man/man3/EVP_OpenInit.3 \
+man/man3/EVP_PBE_CipherInit.3 \
 man/man3/EVP_PKEY2PKCS8.3 \
 man/man3/EVP_PKEY_ASN1_METHOD.3 \
 man/man3/EVP_PKEY_CTX_ctrl.3 \
@@ -3662,6 +3713,7 @@ man/man3/PEM_read_bio_PrivateKey.3 \
 man/man3/PEM_read_bio_ex.3 \
 man/man3/PEM_write_bio_CMS_stream.3 \
 man/man3/PEM_write_bio_PKCS7_stream.3 \
+man/man3/PKCS12_PBE_keyivgen.3 \
 man/man3/PKCS12_SAFEBAG_create_cert.3 \
 man/man3/PKCS12_SAFEBAG_get0_attrs.3 \
 man/man3/PKCS12_SAFEBAG_get1_cert.3 \
@@ -3672,9 +3724,16 @@ man/man3/PKCS12_add_friendlyname_asc.3 \
 man/man3/PKCS12_add_localkeyid.3 \
 man/man3/PKCS12_add_safe.3 \
 man/man3/PKCS12_create.3 \
+man/man3/PKCS12_decrypt_skey.3 \
+man/man3/PKCS12_gen_mac.3 \
 man/man3/PKCS12_get_friendlyname.3 \
+man/man3/PKCS12_init.3 \
+man/man3/PKCS12_item_decrypt_d2i.3 \
+man/man3/PKCS12_key_gen_utf8_ex.3 \
 man/man3/PKCS12_newpass.3 \
+man/man3/PKCS12_pack_p7encdata.3 \
 man/man3/PKCS12_parse.3 \
+man/man3/PKCS5_PBE_keyivgen.3 \
 man/man3/PKCS5_PBKDF2_HMAC.3 \
 man/man3/PKCS7_decrypt.3 \
 man/man3/PKCS7_encrypt.3 \
@@ -3683,6 +3742,7 @@ man/man3/PKCS7_sign.3 \
 man/man3/PKCS7_sign_add_signer.3 \
 man/man3/PKCS7_type_is_other.3 \
 man/man3/PKCS7_verify.3 \
+man/man3/PKCS8_encrypt.3 \
 man/man3/PKCS8_pkey_add1_attr.3 \
 man/man3/RAND_add.3 \
 man/man3/RAND_bytes.3 \
diff --git a/doc/man3/EVP_PBE_CipherInit.pod b/doc/man3/EVP_PBE_CipherInit.pod
new file mode 100644
index 0000000000..8f2a53397e
--- /dev/null
+++ b/doc/man3/EVP_PBE_CipherInit.pod
@@ -0,0 +1,99 @@
+=pod
+
+=head1 NAME
+
+EVP_PBE_CipherInit, EVP_PBE_CipherInit_ex,
+EVP_PBE_find, EVP_PBE_find_ex - Password based encryption routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                        ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
+ int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                           ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+                           OSSL_LIB_CTX *libctx, const char *propq);
+
+ int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
+                  EVP_PBE_KEYGEN **pkeygen);
+ int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+                     EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **keygen_ex);
+
+=head1 DESCRIPTION
+
+=head2 PBE operations
+
+EVP_PBE_CipherInit() and EVP_PBE_CipherInit_ex() initialise an B<EVP_CIPHER_CTX>
+I<ctx> for encryption (I<en_de>=1) or decryption (I<en_de>=0) using the password
+I<pass> of length I<passlen>. The PBE algorithm type and parameters are extracted
+from an OID I<pbe_obj> and parameters I<param>.
+
+EVP_PBE_CipherInit_ex() also allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+=head2 PBE algorithm search
+
+EVP_PBE_find() and EVP_PBE_find_ex() search for a matching algorithm using two parameters:
+
+1. An algorithm type I<type> which can be:
+
+=over 4
+
+=item *
+
+EVP_PBE_TYPE_OUTER - A PBE algorithm
+
+=item *
+
+EVP_PBE_TYPE_PRF - A pseudo-random function
+
+=item *
+
+EVP_PBE_TYPE_KDF - A key derivation function
+
+=back
+
+2. A I<pbe_nid> which can represent the algorithm identifier with parameters e.g.
+B<NID_pbeWithSHA1AndRC2_CBC> or an algorithm class e.g. B<NID_pbes2>.
+
+They return the algorithm's cipher ID I<pcnid>, digest ID I<pmnid> and a key
+generation function for the algorithm I<pkeygen>. EVP_PBE_CipherInit_ex() also
+returns an extended key generation function I<keygen_ex> which takes a library
+context and property query.
+
+If a NULL is supplied for any of I<pcnid>, I<pmnid>, I<pkeygen> or I<pkeygen_ex>
+then this parameter is not returned.
+
+=head1 NOTES
+
+The arguments I<pbe_obj> and I<param> to EVP_PBE_CipherInit() and EVP_PBE_CipherInit_ex()
+together form an B<X509_ALGOR> and can often be extracted directly from this structure.
+
+=head1 RETURN VALUES
+
+Return value is 1 for success and 0 if an error occurred.
+
+=head1 SEE ALSO
+
+L<PKCS5_PBE_keyivgen(3)>,
+L<PKCS12_PBE_keyivgen_ex(3)>,
+L<PKCS5_v2_PBE_keyivgen_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<PKCS12_create_ex(3)>
+
+=head1 HISTORY
+
+EVP_PBE_CipherInit_ex() and EVP_PBE_find_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_PBE_keyivgen.pod b/doc/man3/PKCS12_PBE_keyivgen.pod
new file mode 100644
index 0000000000..2cbaa8ed81
--- /dev/null
+++ b/doc/man3/PKCS12_PBE_keyivgen.pod
@@ -0,0 +1,108 @@
+=pod
+
+=head1 NAME
+
+PKCS12_PBE_keyivgen, PKCS12_PBE_keyivgen_ex,
+PKCS12_pbe_crypt, PKCS12_pbe_crypt_ex - PKCS#12 Password based encryption
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                         ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                         const EVP_MD *md_type, int en_de);
+ int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                            ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                            const EVP_MD *md_type, int en_de,
+                            OSSL_LIB_CTX *libctx, const char *propq);
+ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
+                                 const char *pass, int passlen,
+                                 const unsigned char *in, int inlen,
+                                 unsigned char **data, int *datalen,
+                                 int en_de);
+ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+                                    const char *pass, int passlen,
+                                    const unsigned char *in, int inlen,
+                                    unsigned char **data, int *datalen,
+                                    int en_de, OSSL_LIB_CTX *libctx,
+                                    const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_PBE_keyivgen() and PKCS12_PBE_keyivgen_ex() take a password I<pass> of
+length I<passlen>, parameters I<param> and a message digest function I<md_type>
+and perform a key derivation according to PKCS#12. The resulting key is
+then used to initialise the cipher context I<ctx> with a cipher I<cipher> for
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+PKCS12_PBE_keyivgen_ex() also allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+PKCS12_pbe_crypt() and PKCS12_pbe_crypt_ex() will encrypt or decrypt a buffer
+based on the algorithm in I<algor> and password I<pass> of length I<passlen>.
+The input is from I<in> of length I<inlen> and output is into a malloc'd buffer
+returned in I<*data> of length I<datalen>. The operation is determined by I<en_de>,
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+PKCS12_pbe_crypt_ex() allows the application to specify a library context
+I<libctx> and property query I<propq> to select appropriate algorithm
+implementations.
+
+I<pass> is the password used in the derivation of length I<passlen>. I<pass>
+is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+Functions ending in _ex() take optional parameters I<libctx> and I<propq> which
+are used to select appropriate algorithm implementations.
+
+=head1 NOTES
+
+The functions are typically used in PKCS#12 to encrypt objects.
+
+These functions make no assumption regarding the given password.
+It will simply be treated as a byte sequence.
+
+=head1 RETURN VALUES
+
+PKCS12_PBE_keyivgen(), PKCS12_PBE_keyivgen_ex() return 1 on success or 0 on error.
+
+PKCS12_pbe_crypt() and PKCS12_pbe_crypt_ex() return a buffer containing the
+output or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<EVP_PBE_CipherInit_ex(3)>,
+L<PKCS8_encrypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_PBE_keyivgen_ex() and PKCS12_pbe_crypt_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2014-2021 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/PKCS12_SAFEBAG_create_cert.pod b/doc/man3/PKCS12_SAFEBAG_create_cert.pod
index be0aee4226..07ba1425e7 100644
--- a/doc/man3/PKCS12_SAFEBAG_create_cert.pod
+++ b/doc/man3/PKCS12_SAFEBAG_create_cert.pod
@@ -4,8 +4,8 @@
 
 PKCS12_SAFEBAG_create_cert, PKCS12_SAFEBAG_create_crl,
 PKCS12_SAFEBAG_create_secret, PKCS12_SAFEBAG_create0_p8inf, 
-PKCS12_SAFEBAG_create0_pkcs8, PKCS12_SAFEBAG_create_pkcs8_encrypt - Create
-PKCS#12 safeBag objects
+PKCS12_SAFEBAG_create0_pkcs8, PKCS12_SAFEBAG_create_pkcs8_encrypt,
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex - Create PKCS#12 safeBag objects
 
 =head1 SYNOPSIS
 
@@ -24,6 +24,14 @@ PKCS#12 safeBag objects
                                                      unsigned char *salt,
                                                      int saltlen, int iter,
                                                      PKCS8_PRIV_KEY_INFO *p8inf);
+ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+                                                        const char *pass,
+                                                        int passlen,
+                                                        unsigned char *salt,
+                                                        int saltlen, int iter,
+                                                        PKCS8_PRIV_KEY_INFO *p8inf,
+                                                        OSSL_LIB_CTX *ctx,
+                                                        const char *propq);
 
 =head1 DESCRIPTION
 
@@ -34,7 +42,7 @@ PKCS12_SAFEBAG_create_crl() creates a new B<PKCS12_SAFEBAG> of type B<NID_crlBag
 containing the supplied crl.
 
 PKCS12_SAFEBAG_create_secret() creates a new B<PKCS12_SAFEBAG> of type
-corresponding to a PKCS#12 I<secretBag>. The I<secretBag> contents are tagged as
+corresponding to a PKCS#12 B<secretBag>. The B<secretBag> contents are tagged as
 I<type> with an ASN1 value of type I<vtype> constructed using the bytes in
 I<value> of length I<len>.
 
@@ -50,6 +58,10 @@ If I<pbe_nid> is 0, a default encryption algorithm is used. I<pass> is the
 passphrase and I<iter> is the iteration count. If I<iter> is zero then a default
 value of 2048 is used. If I<salt> is NULL then a salt is generated randomly.
 
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex() is identical to PKCS12_SAFEBAG_create_pkcs8_encrypt()
+but allows for a library context I<ctx> and property query I<propq> to be used to select
+algorithm implementations.
+
 =head1 NOTES
 
 PKCS12_SAFEBAG_create_pkcs8_encrypt() makes assumptions regarding the encoding of the given pass
@@ -62,15 +74,23 @@ PKCS12_SAFEBAG_create_secret() was added in OpenSSL 3.0.
 
 All of these functions return a valid B<PKCS12_SAFEBAG> structure or NULL if an error occurred.
 
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
 =head1 SEE ALSO
 
 L<PKCS12_create(3)>,
 L<PKCS12_add_safe(3)>,
 L<PKCS12_add_safes(3)>
 
+=head1 HISTORY
+
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2019-2021 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/PKCS12_add_cert.pod b/doc/man3/PKCS12_add_cert.pod
index bb326f7f4c..ae3b21a13c 100644
--- a/doc/man3/PKCS12_add_cert.pod
+++ b/doc/man3/PKCS12_add_cert.pod
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-PKCS12_add_cert, PKCS12_add_key,
+PKCS12_add_cert, PKCS12_add_key, PKCS12_add_key_ex,
 PKCS12_add_secret - Add an object to a set of PKCS#12 safeBags
 
 =head1 SYNOPSIS
@@ -13,6 +13,11 @@ PKCS12_add_secret - Add an object to a set of PKCS#12 safeBags
  PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
                                EVP_PKEY *key, int key_usage, int iter,
                                int key_nid, const char *pass);
+ PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                                   EVP_PKEY *key, int key_usage, int iter,
+                                   int key_nid, const char *pass,
+                                   OSSL_LIB_CTX *ctx, const char *propq);
+
  PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
                                   int nid_type, const unsigned char *value, int len);
 
@@ -30,13 +35,17 @@ safeBags. If I<key_nid> is not -1 then the key is encrypted with the supplied
 algorithm, using I<pass> as the passphrase and I<iter> as the iteration count. If
 I<iter> is zero then a default value for iteration count of 2048 is used.
 
+PKCS12_add_key_ex() is identical to PKCS12_add_key() but allows for a library
+context I<ctx> and property query I<propq> to be used to select algorithm
+implementations.
+
 PKCS12_add_secret() creates a PKCS#12 secretBag with an OID corresponding to
-the supplied B<nid_type> containing the supplied value as an ASN1 octet string.
+the supplied I<nid_type> containing the supplied value as an ASN1 octet string.
 This is then added to the set of PKCS#12 safeBags.
 
 =head1 NOTES
 
-If a certificate contains an B<alias> or a B<keyid> then this will be
+If a certificate contains an I<alias> or a I<keyid> then this will be
 used for the corresponding B<friendlyName> or B<localKeyID> in the
 PKCS12 structure.
 
@@ -44,19 +53,25 @@ PKCS12_add_key() makes assumptions regarding the encoding of the given pass
 phrase.
 See L<passphrase-encoding(7)> for more information.
 
-PKCS12_add_secret() was added in OpenSSL 3.0.
-
 =head1 RETURN VALUES
 
 A valid B<PKCS12_SAFEBAG> structure or NULL if an error occurred.
 
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
 =head1 SEE ALSO
 
 L<PKCS12_create(3)>
 
+=head1 HISTORY
+
+PKCS12_add_secret() and PKCS12_add_key_ex() were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020-2021 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/PKCS12_add_safe.pod b/doc/man3/PKCS12_add_safe.pod
index ec657aaa07..881ab1d75c 100644
--- a/doc/man3/PKCS12_add_safe.pod
+++ b/doc/man3/PKCS12_add_safe.pod
@@ -2,7 +2,8 @@
 
 =head1 NAME
 
-PKCS12_add_safe, PKCS12_add_safes - Create and add objects to a PKCS#12 structure
+PKCS12_add_safe, PKCS12_add_safe_ex,
+PKCS12_add_safes, PKCS12_add_safes_ex - Create and add objects to a PKCS#12 structure
 
 =head1 SYNOPSIS
 
@@ -10,7 +11,13 @@ PKCS12_add_safe, PKCS12_add_safes - Create and add objects to a PKCS#12 structur
 
  int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
                     int safe_nid, int iter, const char *pass);
+ int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+                        int safe_nid, int iter, const char *pass,
+                        OSSL_LIB_CTX *ctx, const char *propq);
+
  PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+ PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int p7_nid,
+                             OSSL_LIB_CTX *ctx, const char *propq);
 
 =head1 DESCRIPTION
 
@@ -32,10 +39,18 @@ a default encryption algorithm, currently B<NID_pbe_WithSHA1And3_Key_TripleDES_C
 
 =back
 
+PKCS12_add_safe_ex() is identical to PKCS12_add_safe() but allows for a library
+context I<ctx> and property query I<propq> to be used to select algorithm
+implementations.
+
 PKCS12_add_safes() creates a B<PKCS12> structure containing the supplied set of
 PKCS7 contentInfos. The I<safes> are enclosed first within a PKCS7 contentInfo
 of type I<p7_nid>. Currently the only supported type is B<NID_pkcs7_data>.
 
+PKCS12_add_safes_ex() is identical to PKCS12_add_safes() but allows for a
+library context I<ctx> and property query I<propq> to be used to select
+algorithm implementations.
+
 =head1 NOTES
 
 PKCS12_add_safe() makes assumptions regarding the encoding of the given pass
@@ -48,13 +63,21 @@ PKCS12_add_safe() returns a value of 1 indicating success or 0 for failure.
 
 PKCS12_add_safes() returns a valid B<PKCS12> structure or NULL if an error occurred.
 
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
 =head1 SEE ALSO
 
 L<PKCS12_create(3)>
 
+=head1 HISTORY
+
+PKCS12_add_safe_ex() and PKCS12_add_safes_ex() were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2020-2021 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/PKCS12_create.pod b/doc/man3/PKCS12_create.pod
index be898c6795..dc0f06d9d3 100644
--- a/doc/man3/PKCS12_create.pod
+++ b/doc/man3/PKCS12_create.pod
@@ -2,7 +2,7 @@
 
 =head1 NAME
 
-PKCS12_create - create a PKCS#12 structure
+PKCS12_create, PKCS12_create_ex - create a PKCS#12 structure
 
 =head1 SYNOPSIS
 
@@ -11,6 +11,10 @@ PKCS12_create - create a PKCS#12 structure
  PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
                        X509 *cert, STACK_OF(X509) *ca,
                        int nid_key, int nid_cert, int iter, int mac_iter, int keytype);
+ PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+                          X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+                          int iter, int mac_iter, int keytype,
+                          OSSL_LIB_CTX *ctx, const char *propq);
 
 =head1 DESCRIPTION
 
@@ -18,7 +22,7 @@ PKCS12_create() creates a PKCS#12 structure.
 
 I<pass> is the passphrase to use. I<name> is the B<friendlyName> to use for
 the supplied certificate and key. I<pkey> is the private key to include in
-the structure and I<cert> its corresponding certificates. I<ca>, if not NULL
+the structure and I<cert> its corresponding certificates. I<ca>, if not B<NULL>
 is an optional set of certificates to also include in the structure.
 
 I<nid_key> and I<nid_cert> are the encryption algorithms that should be used
@@ -27,6 +31,9 @@ GCM, CCM, XTS, and OCB are unsupported. I<iter> is the encryption algorithm
 iteration count to use and I<mac_iter> is the MAC iteration count to use.
 I<keytype> is the type of key.
 
+PKCS12_create_ex() is identical to PKCS12_create() but allows for a library context
+I<ctx> and property query I<propq> to be used to select algorithm implementations.
+
 =head1 NOTES
 
 The parameters I<nid_key>, I<nid_cert>, I<iter>, I<mac_iter> and I<keytype>
@@ -37,6 +44,10 @@ AES-256-CBC) for private keys and certificates, the PBKDF2 and MAC key
 derivation iteration count of B<PKCS12_DEFAULT_ITER> (currently 2048), and
 MAC algorithm HMAC with SHA2-256.
 
+The default MAC iteration count is 1 in order to retain compatibility with
+old software which did not interpret MAC iteration counts. If such compatibility
+is not required then I<mac_iter> should be set to PKCS12_DEFAULT_ITER.
+
 I<keytype> adds a flag to the store private key. This is a non standard extension
 that is only currently interpreted by MSIE. If set to zero the flag is omitted,
 if set to B<KEY_SIG> the key can be used for signing only, if set to B<KEY_EX>
@@ -49,7 +60,7 @@ If a certificate contains an I<alias> or I<keyid> then this will be
 used for the corresponding B<friendlyName> or B<localKeyID> in the
 PKCS12 structure.
 
-Either I<pkey>, I<cert> or both can be NULL to indicate that no key or
+Either I<pkey>, I<cert> or both can be B<NULL> to indicate that no key or
 certificate is required. In previous versions both had to be present or
 a fatal error is returned.
 
@@ -66,6 +77,10 @@ See L<passphrase-encoding(7)> for more information.
 
 PKCS12_create() returns a valid B<PKCS12> structure or NULL if an error occurred.
 
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
 =head1 SEE ALSO
 
 L<d2i_PKCS12(3)>,
@@ -73,6 +88,8 @@ L<passphrase-encoding(7)>
 
 =head1 HISTORY
 
+PKCS12_create_ex() was added in OpenSSL 3.0.
+
 The defaults for encryption algorithms, MAC algorithm, and the MAC key
 derivation iteration count were changed in OpenSSL 3.0 to more modern
 standards.
diff --git a/doc/man3/PKCS12_decrypt_skey.pod b/doc/man3/PKCS12_decrypt_skey.pod
new file mode 100644
index 0000000000..a376ddc502
--- /dev/null
+++ b/doc/man3/PKCS12_decrypt_skey.pod
@@ -0,0 +1,55 @@
+=pod
+
+=head1 NAME
+
+PKCS12_decrypt_skey, PKCS12_decrypt_skey_ex - PKCS12 shrouded keyBag
+decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
+                                          const char *pass, int passlen);
+ PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+                                             const char *pass, int passlen,
+                                             OSSL_LIB_CTX *ctx,
+                                             const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_decrypt_skey() Decrypt the PKCS#8 shrouded keybag contained within I<bag>
+using the supplied password I<pass> of length I<passlen>.
+
+PKCS12_decrypt_skey_ex() is similar to the above but allows for a library contex 
+I<ctx> and property query I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+Both functions will return the decrypted key or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS8_decrypt_ex(3)>,
+L<PKCS8_encrypt_ex(3)>,
+L<PKCS12_add_key_ex(3)>,
+L<PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_decrypt_skey_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_gen_mac.pod b/doc/man3/PKCS12_gen_mac.pod
new file mode 100644
index 0000000000..53b55e8703
--- /dev/null
+++ b/doc/man3/PKCS12_gen_mac.pod
@@ -0,0 +1,72 @@
+=pod
+
+=head1 NAME
+
+PKCS12_gen_mac, PKCS12_setup_mac, PKCS12_set_mac,
+PKCS12_verify_mac - Functions to create and manipulate a PKCS#12 structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+                    unsigned char *mac, unsigned int *maclen);
+ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
+ int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen,
+                    unsigned char *salt, int saltlen, int iter,
+                    const EVP_MD *md_type);
+ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt,
+                      int saltlen, const EVP_MD *md_type);
+
+=head1 DESCRIPTION
+
+PKCS12_gen_mac() generates an HMAC over the entire PKCS#12 object using the
+supplied password along with a set of already configured paramters.
+
+PKCS12_verify_mac() verifies the PKCS#12 object's HMAC using the supplied
+password.
+
+PKCS12_setup_mac() sets the MAC part of the PKCS#12 structure with the supplied
+parameters.
+
+PKCS12_set_mac() sets the MAC and MAC parameters into the PKCS#12 object.
+
+I<pass> is the passphrase to use in the HMAC. I<salt> is the salt value to use,
+I<iter> is the iteration count and I<md_type> is the message digest
+function to use.
+
+=head1 NOTES
+
+If I<salt> is NULL then a suitable salt will be generated and used.
+
+If I<iter> is 1 then an iteration count will be omitted from the PKCS#12
+structure.
+
+PKCS12_gen_mac(), PKCS12_verify_mac() and PKCS12_set_mac() make assumptions
+regarding the encoding of the given passphrase. See L<passphrase-encoding(7)>
+for more information.
+
+=head1 RETURN VALUES
+
+All functions return 1 on success and 0 if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<d2i_PKCS12(3)>,
+L<PKCS12_create(3)>,
+L<passphrase-encoding(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_init.pod b/doc/man3/PKCS12_init.pod
new file mode 100644
index 0000000000..b0d3aa5fa9
--- /dev/null
+++ b/doc/man3/PKCS12_init.pod
@@ -0,0 +1,48 @@
+=pod
+
+=head1 NAME
+
+PKCS12_init, PKCS12_init_ex - Create a new empty PKCS#12 structure
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS12 *PKCS12_init(int mode);
+ PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_init() creates an empty PKCS#12 structure. Any PKCS#7 authSafes added
+to this structure are enclosed first within a single PKCS#7 contentInfo
+of type I<mode>. Currently the only supported type is B<NID_pkcs7_data>.
+
+PKCS12_init_ex() creates an empty PKCS#12 structure and assigns the supplied
+I<ctx> and I<propq> to be used to select algorithm implementations for
+operations performed on the B<PKCS12> object.
+
+=head1 RETURN VALUES
+
+PKCS12_init() and PKCS12_init_ex() return a valid B<PKCS12> structure or NULL
+if an error occurred.
+
+=head1 SEE ALSO
+
+L<d2i_PKCS12(3)>,
+L<PKCS12_create(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_init_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_item_decrypt_d2i.pod b/doc/man3/PKCS12_item_decrypt_d2i.pod
new file mode 100644
index 0000000000..5bf498e8a8
--- /dev/null
+++ b/doc/man3/PKCS12_item_decrypt_d2i.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+PKCS12_item_decrypt_d2i, PKCS12_item_decrypt_d2i_ex,
+PKCS12_item_i2d_encrypt, PKCS12_item_i2d_encrypt_ex - PKCS12 item
+encrypt/decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
+                               const char *pass, int passlen,
+                               const ASN1_OCTET_STRING *oct, int zbuf);
+ void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+                                  const char *pass, int passlen,
+                                  const ASN1_OCTET_STRING *oct, int zbuf,
+                                  OSSL_LIB_CTX *libctx,
+                                  const char *propq);
+ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
+                                            const ASN1_ITEM *it,
+                                            const char *pass, int passlen,
+                                            void *obj, int zbuf);
+ ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+                                               const ASN1_ITEM *it,
+                                               const char *pass, int passlen,
+                                               void *obj, int zbuf,
+                                               OSSL_LIB_CTX *ctx,
+                                               const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_item_decrypt_d2i() and PKCS12_item_decrypt_d2i_ex() decrypt an octet
+string containing an ASN.1 encoded object using the algorithm I<algor> and
+password I<pass> of length I<passlen>. If I<zbuf> is nonzero then the output
+buffer will zeroed after the decrypt.
+
+PKCS12_item_i2d_encrypt() and PKCS12_item_i2d_encrypt_ex() encrypt an ASN.1
+object I<it> using the algorithm I<algor> and password I<pass> of length
+I<passlen>, returning an encoded object in I<obj>. If I<zbuf> is nonzero then
+the buffer containing the input encoding will be zeroed after the encrypt.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+PKCS12_item_decrypt_d2i() and PKCS12_item_decrypt_d2i_ex() return the decrypted
+object or NULL if an error occurred.
+
+PKCS12_item_i2d_encrypt() and PKCS12_item_i2d_encrypt_ex() return the encrypted
+data as an ASN.1 Octet String or NULL if an error occurred.
+
+=head1 SEE ALSO
+
+L<PKCS12_pbe_crypt_ex(3)>,
+L<PKCS8_encrypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_item_decrypt_d2i_ex() and PKCS12_item_i2d_encrypt_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_key_gen_utf8_ex.pod b/doc/man3/PKCS12_key_gen_utf8_ex.pod
new file mode 100644
index 0000000000..d66f8c7000
--- /dev/null
+++ b/doc/man3/PKCS12_key_gen_utf8_ex.pod
@@ -0,0 +1,138 @@
+=pod
+
+=head1 NAME
+
+PKCS12_key_gen_asc, PKCS12_key_gen_asc_ex,
+PKCS12_key_gen_uni, PKCS12_key_gen_uni_ex,
+PKCS12_key_gen_utf8, PKCS12_key_gen_utf8_ex - PKCS#12 Password based key derivation
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
+                        int saltlen, int id, int iter, int n,
+                        unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+                           int saltlen, int id, int iter, int n,
+                           unsigned char *out, const EVP_MD *md_type,
+                           OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
+                        int saltlen, int id, int iter, int n,
+                        unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+                           int saltlen, int id, int iter, int n,
+                           unsigned char *out, const EVP_MD *md_type,
+                           OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
+                         int saltlen, int id, int iter, int n,
+                         unsigned char *out, const EVP_MD *md_type);
+ int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+                            int saltlen, int id, int iter, int n,
+                            unsigned char *out, const EVP_MD *md_type,
+                            OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+These methods perform a key derivation according to PKCS#12 (RFC7292)
+with an input password I<pass> of length I<passlen>, a salt I<salt> of length
+I<saltlen>, an iteration count I<iter> and a digest algorithm I<md_type>.
+The ID byte I<id> determines how the resulting key is intended to be used:
+
+=over 4
+
+=item *
+
+If ID=1, then the pseudorandom bits being produced are to be used
+as key material for performing encryption or decryption.
+
+=item *
+
+If ID=2, then the pseudorandom bits being produced are to be used
+as an IV (Initial Value) for encryption or decryption.
+
+=item *
+
+If ID=3, then the pseudorandom bits being produced are to be used
+as an integrity key for MACing.
+
+=back
+
+The intended format of the supplied password is determined by the method chosen:
+
+=over 4
+
+=item *
+
+PKCS12_key_gen_asc() and PKCS12_key_gen_asc_ex() expect an ASCII-formatted password.
+
+=item *
+
+PKCS12_key_gen_uni() and PKCS12_key_gen_uni_ex() expect a Unicode-formatted password.
+
+=item *
+
+PKCS12_key_gen_utf8() and PKCS12_key_gen_utf8_ex() expect a UTF-8 encoded password.
+
+=back
+
+I<pass> is the password used in the derivation of length I<passlen>. I<pass>
+is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+The derived key will be written to I<out>. The size of the I<out> buffer
+is specified via I<n>.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 NOTES
+
+A typical application of this function is to derive keying material for an
+encryption algorithm from a password in the I<pass>, a salt in I<salt>,
+and an iteration count.
+
+Increasing the I<iter> parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+=head1 RETURN VALUES
+
+Returns 1 on success or 0 on error.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<PKCS12_create_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS12_key_gen_asc_ex(), PKCS12_key_gen_uni_ex() and PKCS12_key_gen_utf8_ex()
+were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS12_pack_p7encdata.pod b/doc/man3/PKCS12_pack_p7encdata.pod
new file mode 100644
index 0000000000..36a1d5d12d
--- /dev/null
+++ b/doc/man3/PKCS12_pack_p7encdata.pod
@@ -0,0 +1,59 @@
+=pod
+
+=head1 NAME
+
+PKCS12_pack_p7encdata, PKCS12_pack_p7encdata_ex - Pack a set of PKCS#12 safeBags
+into a PKCS#7 encrypted data object
+
+=head1 SYNOPSIS
+
+ #include <openssl/pkcs12.h>
+
+ PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
+                              unsigned char *salt, int saltlen, int iter,
+                              STACK_OF(PKCS12_SAFEBAG) *bags);
+ PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+                                 unsigned char *salt, int saltlen, int iter,
+                                 STACK_OF(PKCS12_SAFEBAG) *bags,
+                                 OSSL_LIB_CTX *ctx, const char *propq);
+
+=head1 DESCRIPTION
+
+PKCS12_pack_p7encdata() generates a PKCS#7 ContentInfo object of encrypted-data
+type from the set of safeBags I<bags>. The algorithm ID in I<pbe_nid> can be
+a PKCS#12 or PKCS#5 password based encryption algorithm, or a cipher algorithm.
+If a cipher algorithm is passed, the PKCS#5 PBES2 algorithm will be used with
+this cipher as a parameter.
+The password I<pass> of length I<passlen>, salt I<salt> of length I<saltlen>
+and iteration count I<iter> are inputs into the encryption operation.
+
+PKCS12_pack_p7encdata_ex() operates similar to the above but allows for a
+library context I<ctx> and property query I<propq> to be used to select the
+algorithm implementation.
+
+=head1 RETURN VALUES
+
+A B<PKCS7> object if successful, or NULL if an error occurred.
+
+=head1 CONFORMING TO
+
+IETF RFC 2315 (L<https://tools.ietf.org/html/rfc2315>)
+
+=head1 SEE ALSO
+
+L<PKCS12_pbe_crypt_ex(3)>
+
+=head1 HISTORY
+
+PKCS12_pack_p7encdata_ex() was added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS5_PBE_keyivgen.pod b/doc/man3/PKCS5_PBE_keyivgen.pod
new file mode 100644
index 0000000000..4515346407
--- /dev/null
+++ b/doc/man3/PKCS5_PBE_keyivgen.pod
@@ -0,0 +1,170 @@
+=pod
+
+=head1 NAME
+
+PKCS5_PBE_keyivgen, PKCS5_pbe2_set, PKCS5_pbe2_set_iv,
+PKCS5_pbe2_set_iv_ex, PKCS5_pbe_set, PKCS5_pbe_set_ex, PKCS5_pbe2_set_scrypt,
+PKCS5_pbe_set0_algor, PKCS5_pbe_set0_algor_ex,
+PKCS5_v2_PBE_keyivgen, PKCS5_v2_PBE_keyivgen_ex,
+PKCS5_v2_scrypt_keyivgen, PKCS5_v2_scrypt_keyivgen_ex,
+PKCS5_pbkdf2_set, PKCS5_pbkdf2_set_ex, EVP_PBE_scrypt, EVP_PBE_scrypt_ex
+- PKCS#5 Password based encryption routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                        ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                        const EVP_MD *md, int en_de);
+ int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                           ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                           const EVP_MD *md, int en_de);
+ int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                              ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                              const EVP_MD *md, int en_de,
+                              OSSL_LIB_CTX *libctx, const char *propq);
+ int EVP_PBE_scrypt(const char *pass, size_t passlen,
+                    const unsigned char *salt, size_t saltlen,
+                    uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                    unsigned char *key, size_t keylen);
+ int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+                       const unsigned char *salt, size_t saltlen,
+                       uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                       unsigned char *key, size_t keylen,
+                       OSSL_LIB_CTX *ctx, const char *propq);
+ int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
+                              int passlen, ASN1_TYPE *param,
+                              const EVP_CIPHER *c, const EVP_MD *md, int en_de);
+ int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                 int passlen, ASN1_TYPE *param,
+                                 const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+                                 OSSL_LIB_CTX *libctx, const char *propq);
+
+ #include <openssl/x509.h>
+
+ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
+                          const unsigned char *salt, int saltlen);
+ int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+                             const unsigned char *salt, int saltlen,
+                             OSSL_LIB_CTX *libctx);
+
+ X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
+                           const unsigned char *salt, int saltlen);
+ X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+                              const unsigned char *salt, int saltlen,
+                              OSSL_LIB_CTX *libctx);
+
+ X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
+                            unsigned char *salt, int saltlen);
+ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
+                               unsigned char *salt, int saltlen,
+                               unsigned char *aiv, int prf_nid);
+ X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+                                  unsigned char *salt, int saltlen,
+                                  unsigned char *aiv, int prf_nid,
+                                  OSSL_LIB_CTX *libctx);
+ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
+                                   const unsigned char *salt, int saltlen,
+                                   unsigned char *aiv, uint64_t N, uint64_t r,
+                                   uint64_t p);
+
+ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
+                              int prf_nid, int keylen);
+ X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+                                 int prf_nid, int keylen,
+                                 OSSL_LIB_CTX *libctx);
+
+=head1 DESCRIPTION
+
+=head2 Key Derivation
+
+PKCS5_PBE_keyivgen() takes a password I<pass> of
+length I<passlen>, parameters I<param> and a message digest function I<md_type>
+and performs a key derivation according to PKCS#5 PBES1. The resulting key is
+then used to initialise the cipher context I<ctx> with a cipher I<cipher> for
+encryption (I<en_de>=1) or decryption (I<en_de>=0).
+
+I<pass> is an optional parameter and can be NULL. If I<passlen> is -1, then the
+function will calculate the length of I<pass> using strlen().
+
+PKCS5_v2_PBE_keyivgen() and PKCS5_v2_PBE_keyivgen_ex() are similar to the above
+but instead use PKCS#5 PBES2 as the encryption algorithm using the supplied
+parameters.
+
+PKCS5_v2_scrypt_keyivgen() and PKCS5_v2_scrypt_keyivgen_ex() use SCRYPT as the
+key derivation part of the encryption algorithm.
+
+I<salt> is the salt used in the derivation of length I<saltlen>. If the
+I<salt> is NULL, then I<saltlen> must be 0. The function will not
+attempt to calculate the length of the I<salt> because it is not assumed to
+be NULL terminated.
+
+I<iter> is the iteration count and its value should be greater than or
+equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
+I<iter> less than 1 is treated as a single iteration.
+
+I<digest> is the message digest function used in the derivation.
+
+Functions ending in _ex() take optional parameters I<libctx> and I<propq> which
+are used to select appropriate algorithm implementations.
+
+=head2 Algorithm Identifier Creation
+
+PKCS5_pbe_set(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set(), PKCS5_pbe2_set_iv(),
+PKCS5_pbe2_set_iv_ex() and PKCS5_pbe2_set_scrypt() generate an B<X509_ALGOR>
+object which represents an AlgorithmIdentifier containing the algorithm OID and
+associated parameters for the PBE algorithm.
+
+PKCS5_pbkdf2_set() and PKCS5_pbkdf2_set_ex() generate an B<X509_ALGOR>
+object which represents an AlgorithmIdentifier containing the algorithm OID and
+associated parameters for the PBKDF2 algorithm.
+
+PKCS5_pbe_set0_algor() and PKCS5_pbe_set0_algor_ex() set the PBE algorithm OID and
+parameters into the supplied B<X509_ALGOR>.
+
+=head1 NOTES
+
+The *_keyivgen() functions are typically used in PKCS#12 to encrypt objects.
+
+These functions make no assumption regarding the given password.
+It will simply be treated as a byte sequence.
+
+=head1 RETURN VALUES
+
+PKCS5_PBE_keyivgen(), PKCS5_v2_PBE_keyivgen(),
+PKCS5_v2_PBE_keyivgen_ex(), PKCS5_v2_scrypt_keyivgen(),
+PKCS5_v2_scrypt_keyivgen_ex(), PKCS5_pbe_set0_algor() and
+PKCS5_pbe_set0_algor_ex() return 1 for success and 0 if an error occurs.
+
+PKCS5_pbe_set(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set(), PKCS5_pbe2_set_iv(),
+PKCS5_pbe2_set_iv_ex(), PKCS5_pbe2_set_scrypt(),
+PKCS5_pbkdf2_set() and PKCS5_pbkdf2_set_ex() return an B<X509_ALGOR> object or
+NULL if an error occurs.
+
+=head1 CONFORMING TO
+
+IETF RFC 8018 (L<https://tools.ietf.org/html/rfc8018>)
+
+=head1 SEE ALSO
+
+L<EVP_PBE_CipherInit_ex(3)>,
+L<PKCS12_pbe_crypt_ex(3)>,
+L<passphrase-encoding(7)>
+
+=head1 HISTORY
+
+PKCS5_v2_PBE_keyivgen_ex(), EVP_PBE_scrypt_ex(), PKCS5_v2_scrypt_keyivgen_ex(),
+PKCS5_pbe_set0_algor_ex(), PKCS5_pbe_set_ex(), PKCS5_pbe2_set_iv_ex() and
+PKCS5_pbkdf2_set_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/PKCS5_PBKDF2_HMAC.pod b/doc/man3/PKCS5_PBKDF2_HMAC.pod
index 51f97e7380..51c8ce8e6d 100644
--- a/doc/man3/PKCS5_PBKDF2_HMAC.pod
+++ b/doc/man3/PKCS5_PBKDF2_HMAC.pod
@@ -35,9 +35,8 @@ B<iter> is the iteration count and its value should be greater than or
 equal to 1. RFC 2898 suggests an iteration count of at least 1000. Any
 B<iter> less than 1 is treated as a single iteration.
 
-B<digest> is the message digest function used in the derivation. Values include
-any of the EVP_* message digests. PKCS5_PBKDF2_HMAC_SHA1() calls
-PKCS5_PBKDF2_HMAC() with EVP_sha1().
+B<digest> is the message digest function used in the derivation.
+PKCS5_PBKDF2_HMAC_SHA1() calls PKCS5_PBKDF2_HMAC() with EVP_sha1().
 
 The derived key will be written to B<out>. The size of the B<out> buffer
 is specified via B<keylen>.
diff --git a/doc/man3/PKCS8_encrypt.pod b/doc/man3/PKCS8_encrypt.pod
new file mode 100644
index 0000000000..8a42b83310
--- /dev/null
+++ b/doc/man3/PKCS8_encrypt.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+PKCS8_decrypt, PKCS8_decrypt_ex, PKCS8_encrypt, PKCS8_encrypt_ex,
+PKCS8_set0_pbe, PKCS8_set0_pbe_ex - PKCS8 encrypt/decrypt functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/x509.h>
+
+ PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
+                                    int passlen);
+ PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+                                       int passlen, OSSL_LIB_CTX *ctx,
+                                       const char *propq);
+ X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+                         const char *pass, int passlen, unsigned char *salt,
+                         int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
+ X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+                            const char *pass, int passlen, unsigned char *salt,
+                            int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8,
+                            OSSL_LIB_CTX *ctx, const char *propq);
+ X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
+                         PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
+ X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+                             PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+                             OSSL_LIB_CTX *ctx);
+
+=head1 DESCRIPTION
+
+PKCS8_encrypt() and PKCS8_encrypt_ex() perform encryption of an object I<p8> using
+the password I<pass> of length I<passlen>, salt I<salt> of length I<saltlen>
+and iteration count I<iter>.
+The resulting B<X509_SIG> contains the encoded algorithm parameters and encrypted
+key.
+
+PKCS8_decrypt() and PKCS8_decrypt_ex() perform decryption of an B<X509_SIG> in
+I<p8> using the password I<pass> of length I<passlen> along with algorithm
+parameters obtained from the I<p8>.
+
+PKCS8_set0_pbe() and PKCS8_set0_pbe_ex() perform encryption of the I<p8inf>
+using the password I<pass> of length I<passlen> and parameters I<pbe>.
+
+Functions ending in _ex() allow for a library context I<ctx> and property query
+I<propq> to be used to select algorithm implementations.
+
+=head1 RETURN VALUES
+
+PKCS8_encrypt(), PKCS8_encrypt_ex(), PKCS8_set0_pbe() and PKCS8_set0_pbe_ex()
+return an encrypted key in a B<X509_SIG> structure or NULL if an error occurs.
+
+PKCS8_decrypt() and PKCS8_decrypt_ex() return a B<PKCS8_PRIV_KEY_INFO> or NULL
+if an error occurs.
+
+=head1 CONFORMING TO
+
+IETF RFC 7292 (L<https://tools.ietf.org/html/rfc7292>)
+
+=head1 SEE ALSO
+
+L<crypto(7)>
+
+=head1 HISTORY
+
+PKCS8_decrypt_ex(), PKCS8_encrypt_ex() and PKCS8_set0_pbe_ex() were added in
+OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
index c63246c663..9caa9af4a2 100644
--- a/include/crypto/pkcs7.h
+++ b/include/crypto/pkcs7.h
@@ -13,4 +13,7 @@
 
 void ossl_pkcs7_resolve_libctx(PKCS7 *p7);
 
+void ossl_pkcs7_set0_libctx(PKCS7 *p7, OSSL_LIB_CTX *ctx);
+int ossl_pkcs7_set1_propq(PKCS7 *p7, const char *propq);
+
 #endif
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index 7c00109621..708f79d480 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -207,7 +207,6 @@ extern "C" {
 #define OSSL_KDF_PARAM_SSHKDF_SESSION_ID "session_id" /* octet string */
 #define OSSL_KDF_PARAM_SSHKDF_TYPE  "type"      /* int */
 #define OSSL_KDF_PARAM_SIZE         "size"      /* size_t */
-#define OSSL_KDF_PARAM_CIPHER       OSSL_ALG_PARAM_CIPHER     /* utf8 string */
 #define OSSL_KDF_PARAM_CONSTANT     "constant"  /* octet string */
 #define OSSL_KDF_PARAM_PKCS12_ID    "id"        /* int */
 #define OSSL_KDF_PARAM_KBKDF_USE_L  "use-l"             /* int */
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index a9a9662370..f527de4d4c 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -487,6 +487,11 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
                               const EVP_CIPHER *cipher, const EVP_MD *md,
                               int en_de);
 
+typedef int (EVP_PBE_KEYGEN_EX) (EVP_CIPHER_CTX *ctx, const char *pass,
+                                 int passlen, ASN1_TYPE *param,
+                                 const EVP_CIPHER *cipher, const EVP_MD *md,
+                                 int en_de, OSSL_LIB_CTX *libctx, const char *propq);
+
 # ifndef OPENSSL_NO_DEPRECATED_3_0
 #  define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
                                                          (rsa))
@@ -1432,16 +1437,29 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
 int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
                           ASN1_TYPE *param, const EVP_CIPHER *cipher,
                           const EVP_MD *md, int en_de);
+int PKCS5_v2_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                             ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                             const EVP_MD *md, int en_de,
+                             OSSL_LIB_CTX *libctx, const char *propq);
 
 #ifndef OPENSSL_NO_SCRYPT
 int EVP_PBE_scrypt(const char *pass, size_t passlen,
                    const unsigned char *salt, size_t saltlen,
                    uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
                    unsigned char *key, size_t keylen);
+int EVP_PBE_scrypt_ex(const char *pass, size_t passlen,
+                      const unsigned char *salt, size_t saltlen,
+                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                      unsigned char *key, size_t keylen,
+                      OSSL_LIB_CTX *ctx, const char *propq);
 
 int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              int passlen, ASN1_TYPE *param,
                              const EVP_CIPHER *c, const EVP_MD *md, int en_de);
+int PKCS5_v2_scrypt_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass,
+                                int passlen, ASN1_TYPE *param,
+                                const EVP_CIPHER *c, const EVP_MD *md, int en_de,
+                                OSSL_LIB_CTX *libctx, const char *propq);
 #endif
 
 void PKCS5_PBE_add(void);
@@ -1449,6 +1467,10 @@ void PKCS5_PBE_add(void);
 int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
                        ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
 
+int EVP_PBE_CipherInit_ex(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+                          ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de,
+                          OSSL_LIB_CTX *libctx, const char *propq);
+
 /* PBE type */
 
 /* Can appear as the outermost AlgorithmIdentifier */
@@ -1464,6 +1486,8 @@ int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
                     EVP_PBE_KEYGEN *keygen);
 int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
                  EVP_PBE_KEYGEN **pkeygen);
+int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid,
+                    EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **pkeygen_ex);
 void EVP_PBE_cleanup(void);
 int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
 
diff --git a/include/openssl/pkcs12.h.in b/include/openssl/pkcs12.h.in
index 76b19d3dc9..48b0998b2c 100644
--- a/include/openssl/pkcs12.h.in
+++ b/include/openssl/pkcs12.h.in
@@ -23,6 +23,7 @@ use OpenSSL::stackhash qw(generate_stack_macros);
 # endif
 
 # include <openssl/bio.h>
+# include <openssl/core.h>
 # include <openssl/x509.h>
 # include <openssl/pkcs12err.h>
 
@@ -124,23 +125,50 @@ PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
                                                     unsigned char *salt,
                                                     int saltlen, int iter,
                                                     PKCS8_PRIV_KEY_INFO *p8inf);
+PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt_ex(int pbe_nid,
+                                                       const char *pass,
+                                                       int passlen,
+                                                       unsigned char *salt,
+                                                       int saltlen, int iter,
+                                                       PKCS8_PRIV_KEY_INFO *p8inf,
+                                                       OSSL_LIB_CTX *ctx,
+                                                       const char *propq);
 
 PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it,
                                          int nid1, int nid2);
 PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass,
                                    int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_ex(const X509_SIG *p8, const char *pass,
+                                      int passlen, OSSL_LIB_CTX *ctx,
+                                      const char *propq);
 PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag,
                                          const char *pass, int passlen);
+PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey_ex(const PKCS12_SAFEBAG *bag,
+                                            const char *pass, int passlen,
+                                            OSSL_LIB_CTX *ctx,
+                                            const char *propq);
 X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
                         const char *pass, int passlen, unsigned char *salt,
                         int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8);
+X509_SIG *PKCS8_encrypt_ex(int pbe_nid, const EVP_CIPHER *cipher,
+                           const char *pass, int passlen, unsigned char *salt,
+                           int saltlen, int iter, PKCS8_PRIV_KEY_INFO *p8,
+                           OSSL_LIB_CTX *ctx, const char *propq);
 X509_SIG *PKCS8_set0_pbe(const char *pass, int passlen,
                         PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe);
+X509_SIG *PKCS8_set0_pbe_ex(const char *pass, int passlen,
+                            PKCS8_PRIV_KEY_INFO *p8inf, X509_ALGOR *pbe,
+                            OSSL_LIB_CTX *ctx, const char *propq);
 PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk);
 STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7);
 PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen,
                              unsigned char *salt, int saltlen, int iter,
                              STACK_OF(PKCS12_SAFEBAG) *bags);
+PKCS7 *PKCS12_pack_p7encdata_ex(int pbe_nid, const char *pass, int passlen,
+                                unsigned char *salt, int saltlen, int iter,
+                                STACK_OF(PKCS12_SAFEBAG) *bags,
+                                OSSL_LIB_CTX *ctx, const char *propq);
+
 STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
                                                   int passlen);
 
@@ -172,26 +200,62 @@ unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor,
                                 const unsigned char *in, int inlen,
                                 unsigned char **data, int *datalen,
                                 int en_de);
+unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor,
+                                   const char *pass, int passlen,
+                                   const unsigned char *in, int inlen,
+                                   unsigned char **data, int *datalen,
+                                   int en_de, OSSL_LIB_CTX *libctx,
+                                   const char *propq);
 void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it,
                               const char *pass, int passlen,
                               const ASN1_OCTET_STRING *oct, int zbuf);
+void *PKCS12_item_decrypt_d2i_ex(const X509_ALGOR *algor, const ASN1_ITEM *it,
+                                 const char *pass, int passlen,
+                                 const ASN1_OCTET_STRING *oct, int zbuf,
+                                 OSSL_LIB_CTX *libctx, 
+                                 const char *propq);
 ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor,
                                            const ASN1_ITEM *it,
                                            const char *pass, int passlen,
                                            void *obj, int zbuf);
+ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt_ex(X509_ALGOR *algor,
+                                              const ASN1_ITEM *it,
+                                              const char *pass, int passlen,
+                                              void *obj, int zbuf,
+                                              OSSL_LIB_CTX *ctx,
+                                              const char *propq);
 PKCS12 *PKCS12_init(int mode);
+PKCS12 *PKCS12_init_ex(int mode, OSSL_LIB_CTX *ctx, const char *propq);
+
 int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt,
                        int saltlen, int id, int iter, int n,
                        unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_asc_ex(const char *pass, int passlen, unsigned char *salt,
+                          int saltlen, int id, int iter, int n,
+                          unsigned char *out, const EVP_MD *md_type,
+                          OSSL_LIB_CTX *ctx, const char *propq);
 int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
                        int saltlen, int id, int iter, int n,
                        unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_uni_ex(unsigned char *pass, int passlen, unsigned char *salt,
+                          int saltlen, int id, int iter, int n,
+                          unsigned char *out, const EVP_MD *md_type,
+                          OSSL_LIB_CTX *ctx, const char *propq);
 int PKCS12_key_gen_utf8(const char *pass, int passlen, unsigned char *salt,
                         int saltlen, int id, int iter, int n,
                         unsigned char *out, const EVP_MD *md_type);
+int PKCS12_key_gen_utf8_ex(const char *pass, int passlen, unsigned char *salt,
+                           int saltlen, int id, int iter, int n,
+                           unsigned char *out, const EVP_MD *md_type,
+                           OSSL_LIB_CTX *ctx, const char *propq);
+
 int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
                         ASN1_TYPE *param, const EVP_CIPHER *cipher,
                         const EVP_MD *md_type, int en_de);
+int PKCS12_PBE_keyivgen_ex(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
+                           ASN1_TYPE *param, const EVP_CIPHER *cipher,
+                           const EVP_MD *md_type, int en_de,
+                           OSSL_LIB_CTX *libctx, const char *propq);
 int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
                    unsigned char *mac, unsigned int *maclen);
 int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen);
@@ -221,16 +285,31 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
 PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey,
                       X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
                       int iter, int mac_iter, int keytype);
+PKCS12 *PKCS12_create_ex(const char *pass, const char *name, EVP_PKEY *pkey,
+                         X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert,
+                         int iter, int mac_iter, int keytype,
+                         OSSL_LIB_CTX *ctx, const char *propq);
 
 PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert);
 PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags,
                                EVP_PKEY *key, int key_usage, int iter,
                                int key_nid, const char *pass);
+PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags,
+                                  EVP_PKEY *key, int key_usage, int iter,
+                                  int key_nid, const char *pass,
+                                  OSSL_LIB_CTX *ctx, const char *propq);
+
 PKCS12_SAFEBAG *PKCS12_add_secret(STACK_OF(PKCS12_SAFEBAG) **pbags,
                                   int nid_type, const unsigned char *value, int len);
 int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
                     int safe_nid, int iter, const char *pass);
+int PKCS12_add_safe_ex(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+                       int safe_nid, int iter, const char *pass,
+                       OSSL_LIB_CTX *ctx, const char *propq);
+
 PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid);
+PKCS12 *PKCS12_add_safes_ex(STACK_OF(PKCS7) *safes, int p7_nid,
+                            OSSL_LIB_CTX *ctx, const char *propq);
 
 int i2d_PKCS12_bio(BIO *bp, const PKCS12 *p12);
 # ifndef OPENSSL_NO_STDIO
diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
index cd28bd1d70..1726ecf4dc 100644
--- a/include/openssl/x509.h.in
+++ b/include/openssl/x509.h.in
@@ -1067,14 +1067,25 @@ DECLARE_ASN1_FUNCTIONS(SCRYPT_PARAMS)
 
 int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
                          const unsigned char *salt, int saltlen);
+int PKCS5_pbe_set0_algor_ex(X509_ALGOR *algor, int alg, int iter,
+                            const unsigned char *salt, int saltlen,
+                            OSSL_LIB_CTX *libctx);
 
 X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
                           const unsigned char *salt, int saltlen);
+X509_ALGOR *PKCS5_pbe_set_ex(int alg, int iter,
+                             const unsigned char *salt, int saltlen,
+                             OSSL_LIB_CTX *libctx);
+
 X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
                            unsigned char *salt, int saltlen);
 X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
                               unsigned char *salt, int saltlen,
                               unsigned char *aiv, int prf_nid);
+X509_ALGOR *PKCS5_pbe2_set_iv_ex(const EVP_CIPHER *cipher, int iter,
+                                 unsigned char *salt, int saltlen,
+                                 unsigned char *aiv, int prf_nid,
+                                 OSSL_LIB_CTX *libctx);
 
 #ifndef OPENSSL_NO_SCRYPT
 X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
@@ -1085,6 +1096,9 @@ X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher,
 
 X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
                              int prf_nid, int keylen);
+X509_ALGOR *PKCS5_pbkdf2_set_ex(int iter, unsigned char *salt, int saltlen,
+                                int prf_nid, int keylen,
+                                OSSL_LIB_CTX *libctx);
 
 /* PKCS#8 utilities */
 
diff --git a/test/helpers/pkcs12.c b/test/helpers/pkcs12.c
index 92ef7c378c..bdc8585535 100644
--- a/test/helpers/pkcs12.c
+++ b/test/helpers/pkcs12.c
@@ -22,7 +22,12 @@
 #include "pkcs12.h" /* from the same directory */
 
 /* Set this to > 0 write test data to file */
-int write_files = 0;
+static int write_files = 0;
+
+static int legacy = 0;
+
+static OSSL_LIB_CTX *test_ctx = NULL;
+static const char *test_propq = NULL;
 
 /* -------------------------------------------------------------------------
  * Local function declarations
@@ -40,6 +45,31 @@ static int check_asn1_string(const ASN1_TYPE *av, const char *txt);
 static int check_attrs(const STACK_OF(X509_ATTRIBUTE) *bag_attrs, const PKCS12_ATTR *attrs);
 
 
+/* --------------------------------------------------------------------------
+ * Global settings
+ */
+
+void PKCS12_helper_set_write_files(int enable)
+{
+    write_files = enable;
+}
+
+void PKCS12_helper_set_legacy(int enable)
+{
+    legacy = enable;
+}
+
+void PKCS12_helper_set_libctx(OSSL_LIB_CTX *libctx)
+{
+    test_ctx = libctx;
+}
+
+void PKCS12_helper_set_propq(const char *propq)
+{
+    test_propq = propq;
+}
+
+
 /* --------------------------------------------------------------------------
  * Test data load functions
  */
@@ -116,6 +146,7 @@ void end_pkcs12_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 {
     PKCS12 *p12;
+    EVP_MD *md = NULL;
 
     if (!pb->success)
         return;
@@ -125,7 +156,10 @@ static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
         pb->success = 0;
         return;
     }
-    p12 = PKCS12_add_safes(pb->safes, 0);
+    if (legacy)
+        p12 = PKCS12_add_safes(pb->safes, 0);
+    else
+        p12 = PKCS12_add_safes_ex(pb->safes, 0, test_ctx, test_propq);
     if (!TEST_ptr(p12)) {
         pb->success = 0;
         goto err;
@@ -133,8 +167,13 @@ static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
     sk_PKCS7_pop_free(pb->safes, PKCS7_free);
 
     if (mac != NULL) {
+        if (legacy)
+            md = (EVP_MD *)EVP_get_digestbynid(mac->nid);
+        else
+            md = EVP_MD_fetch(test_ctx, OBJ_nid2sn(mac->nid), test_propq);
+
         if (!TEST_true(PKCS12_set_mac(p12, mac->pass, strlen(mac->pass),
-                                      NULL, 0, mac->iter, EVP_get_digestbynid(mac->nid)))) {
+                                      NULL, 0, mac->iter, md))) {
             pb->success = 0;
             goto err;
         }
@@ -145,6 +184,8 @@ static void generate_p12(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
     if (write_files)
         write_p12(p12, pb->filename);
 err:
+    if (!legacy && md != NULL)
+        EVP_MD_free(md);
     PKCS12_free(p12);
 }
 
@@ -169,7 +210,13 @@ static PKCS12 *from_bio_p12(BIO *bio, const PKCS12_ENC *mac)
 {
     PKCS12 *p12 = NULL;
 
-    p12 = d2i_PKCS12_bio(bio, NULL);
+    /* Supply a p12 with library context/propq to the d2i decoder*/
+    if (!legacy) {
+        p12 = PKCS12_init_ex(NID_pkcs7_data, test_ctx, test_propq);
+        if (!TEST_ptr(p12))
+            goto err;
+    }
+    p12 = d2i_PKCS12_bio(bio, &p12);
     BIO_free(bio);
     if (!TEST_ptr(p12))
         goto err;
@@ -245,10 +292,18 @@ void end_contentinfo(PKCS12_BUILDER *pb)
 void end_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc)
 {
     if (pb->success) {
-        if (pb->bags 
-            && !TEST_true(PKCS12_add_safe(&pb->safes, pb->bags, enc->nid, enc->iter, enc->pass))) {
-            pb->success = 0;
-            return;
+        if (pb->bags) {
+            if (legacy) {
+                if (!TEST_true(PKCS12_add_safe(&pb->safes, pb->bags, enc->nid, enc->iter, enc->pass))) {
+                    pb->success = 0;
+                    return;
+                }
+            } else {
+                if (!TEST_true(PKCS12_add_safe_ex(&pb->safes, pb->bags, enc->nid, enc->iter, enc->pass, test_ctx, test_propq))) {
+                    pb->success = 0;
+                    return;
+                }
+            }
         }
     }
     sk_PKCS12_SAFEBAG_pop_free(pb->bags, PKCS12_SAFEBAG_free);
@@ -259,9 +314,13 @@ void end_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc)
 static STACK_OF(PKCS12_SAFEBAG) *decode_contentinfo(STACK_OF(PKCS7) *safes, int idx, const PKCS12_ENC *enc)
 {
     STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
+    int bagnid;
     PKCS7 *p7 = sk_PKCS7_value(safes, idx);
-    int bagnid = OBJ_obj2nid(p7->type);
 
+    if (!TEST_ptr(p7))
+        goto err;
+
+    bagnid = OBJ_obj2nid(p7->type);
     if (enc) {
         if (!TEST_int_eq(bagnid, NID_pkcs7_encrypted))
             goto err;
@@ -370,7 +429,11 @@ void add_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
         return;
     }
 
-    bag = PKCS12_add_key(&pb->bags, pkey, 0 /*keytype*/, enc->iter, enc->nid, enc->pass);
+    if (legacy)
+        bag = PKCS12_add_key(&pb->bags, pkey, 0 /*keytype*/, enc->iter, enc->nid, enc->pass);
+    else
+        bag = PKCS12_add_key_ex(&pb->bags, pkey, 0 /*keytype*/, enc->iter, enc->nid, enc->pass,
+                                test_ctx, test_propq);
     if (!TEST_ptr(bag)) {
         pb->success = 0;
         goto err;
@@ -550,7 +613,11 @@ void check_keybag(PKCS12_BUILDER *pb, const unsigned char *bytes, int len,
         break;
 
     case NID_pkcs8ShroudedKeyBag:
-        if (!TEST_ptr(p8 = PKCS12_decrypt_skey(bag, enc->pass, strlen(enc->pass)))) {
+        if (legacy)
+            p8 = PKCS12_decrypt_skey(bag, enc->pass, strlen(enc->pass));
+        else
+            p8 = PKCS12_decrypt_skey_ex(bag, enc->pass, strlen(enc->pass), test_ctx, test_propq);
+        if (!TEST_ptr(p8)) {
             pb->success = 0;
             goto err;
         }
@@ -584,13 +651,13 @@ void check_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret, con
 
     if (!pb->success)
         return;
-        
+
     bag = sk_PKCS12_SAFEBAG_value(pb->bags, pb->bag_idx++);
     if (!TEST_ptr(bag)) {
         pb->success = 0;
         return;
-    }   
-    
+    }
+
     if (!check_attrs(PKCS12_SAFEBAG_get0_attrs(bag), attrs)
         || !TEST_int_eq(PKCS12_SAFEBAG_get_nid(bag), NID_secretBag)
         || !TEST_int_eq(PKCS12_SAFEBAG_get_bag_nid(bag), secret_nid)
@@ -601,7 +668,12 @@ void check_secretbag(PKCS12_BUILDER *pb, int secret_nid, const char *secret, con
 
 void start_check_pkcs12(PKCS12_BUILDER *pb)
 {
-    PKCS12 *p12 = from_bio_p12(pb->p12bio, NULL);
+    PKCS12 *p12;
+
+    if (!pb->success)
+        return;
+
+    p12 = from_bio_p12(pb->p12bio, NULL);
     if (!TEST_ptr(p12)) {
         pb->success = 0;
         return;
@@ -616,13 +688,18 @@ void start_check_pkcs12(PKCS12_BUILDER *pb)
 
 void start_check_pkcs12_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 {
-    PKCS12 *p12 = from_bio_p12(pb->p12bio, mac); 
+    PKCS12 *p12;
+
+    if (!pb->success)
+        return;
+
+    p12 = from_bio_p12(pb->p12bio, mac);
     if (!TEST_ptr(p12)) {
         pb->success = 0;
         return;
     }
-    pb->safes = PKCS12_unpack_authsafes(p12); 
-    if (!TEST_ptr(pb->safes)) 
+    pb->safes = PKCS12_unpack_authsafes(p12);
+    if (!TEST_ptr(pb->safes))
         pb->success = 0;
 
     pb->safe_idx = 0;
@@ -631,7 +708,12 @@ void start_check_pkcs12_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 
 void start_check_pkcs12_file(PKCS12_BUILDER *pb)
 {
-    PKCS12 *p12 = read_p12(pb->filename, NULL);
+    PKCS12 *p12;
+
+    if (!pb->success)
+        return;
+
+    p12 = read_p12(pb->filename, NULL);
     if (!TEST_ptr(p12)) {
         pb->success = 0;
         return;
@@ -642,11 +724,16 @@ void start_check_pkcs12_file(PKCS12_BUILDER *pb)
 
     pb->safe_idx = 0;
     PKCS12_free(p12);
-}       
-        
+}
+
 void start_check_pkcs12_file_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 {
-    PKCS12 *p12 = read_p12(pb->filename, mac);
+    PKCS12 *p12;
+
+    if (!pb->success)
+        return;
+
+    p12 = read_p12(pb->filename, mac);
     if (!TEST_ptr(p12)) {
         pb->success = 0;
         return;
@@ -661,12 +748,18 @@ void start_check_pkcs12_file_with_mac(PKCS12_BUILDER *pb, const PKCS12_ENC *mac)
 
 void end_check_pkcs12(PKCS12_BUILDER *pb)
 {
+    if (!pb->success)
+        return;
+
     sk_PKCS7_pop_free(pb->safes, PKCS7_free);
 }
 
 
 void start_check_contentinfo(PKCS12_BUILDER *pb)
 {
+    if (!pb->success)
+        return;
+
     pb->bag_idx = 0;
     pb->bags = decode_contentinfo(pb->safes, pb->safe_idx++, NULL);
     if (!TEST_ptr(pb->bags)) {
@@ -678,6 +771,9 @@ void start_check_contentinfo(PKCS12_BUILDER *pb)
 
 void start_check_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc)
 {
+    if (!pb->success)
+        return;
+
     pb->bag_idx = 0;
     pb->bags = decode_contentinfo(pb->safes, pb->safe_idx++, enc);
     if (!TEST_ptr(pb->bags)) {
@@ -690,6 +786,9 @@ void start_check_contentinfo_encrypted(PKCS12_BUILDER *pb, const PKCS12_ENC *enc
 
 void end_check_contentinfo(PKCS12_BUILDER *pb)
 {
+    if (!pb->success)
+        return;
+
     if (!TEST_int_eq(sk_PKCS12_SAFEBAG_num(pb->bags), pb->bag_idx))
         pb->success = 0;
     sk_PKCS12_SAFEBAG_pop_free(pb->bags, PKCS12_SAFEBAG_free);
diff --git a/test/helpers/pkcs12.h b/test/helpers/pkcs12.h
index 01e1cf1595..7805875806 100644
--- a/test/helpers/pkcs12.h
+++ b/test/helpers/pkcs12.h
@@ -20,8 +20,6 @@
 
 #include "../testutil.h"
 
-/* Set this to > 0 write test data to file */
-extern int write_files;
 
 /* -------------------------------------------------------------------------
  * PKCS#12 Test structures
@@ -36,9 +34,9 @@ typedef struct pkcs12_attr {
 
 /* Holds encryption parameters */
 typedef struct pkcs12_enc {
-    int      nid;
-    char    *pass;
-    int      iter;
+    int         nid;
+    const char *pass;
+    int         iter;
 } PKCS12_ENC;
 
 /* Set of variables required for constructing the PKCS#12 structure */
@@ -57,6 +55,12 @@ typedef struct pkcs12_builder {
  * PKCS#12 Test function declarations
  */
 
+/* Global settings */
+void PKCS12_helper_set_write_files(int enable);
+void PKCS12_helper_set_legacy(int enable);
+void PKCS12_helper_set_libctx(OSSL_LIB_CTX *libctx);
+void PKCS12_helper_set_propq(const char *propq);
+
 /* Allocate and initialise a PKCS#12 builder object */
 PKCS12_BUILDER *new_pkcs12_builder(const char *filename);
 
diff --git a/test/pkcs12_format_test.c b/test/pkcs12_format_test.c
index 8b1448f19c..45eb24eca3 100644
--- a/test/pkcs12_format_test.c
+++ b/test/pkcs12_format_test.c
@@ -21,6 +21,12 @@
 #include "testutil.h"
 #include "helpers/pkcs12.h"
 
+static int default_libctx = 1;
+
+static OSSL_LIB_CTX *testctx = NULL;
+static OSSL_PROVIDER *nullprov = NULL;
+static OSSL_PROVIDER *deflprov = NULL;
+static OSSL_PROVIDER *lgcyprov = NULL;
 
 /* --------------------------------------------------------------------------
  * PKCS12 component test data
@@ -200,7 +206,11 @@ static const PKCS12_ATTR ATTRS2[] = {
 };
 
 static const PKCS12_ENC enc_default = {
+#ifndef OPENSSL_NO_DES
     NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+#else
+    NID_aes_128_cbc,
+#endif
     "Password1",
     1000
 };
@@ -211,6 +221,79 @@ static const PKCS12_ENC mac_default = {
     1000
 };
 
+static const int enc_nids_all[] = {
+    /* NOTE: To use PBES2 we pass the desired cipher NID instead of NID_pbes2 */
+    NID_aes_128_cbc,
+    NID_aes_256_cbc,
+#ifndef OPENSSL_NO_DES
+    NID_des_ede3_cbc,
+    NID_des_cbc,
+#endif
+
+#ifndef OPENSSL_NO_MD2
+# ifndef OPENSSL_NO_DES
+    NID_pbeWithMD2AndDES_CBC,
+# endif
+# ifndef OPENSSL_NO_RC2
+    NID_pbeWithMD2AndRC2_CBC,
+# endif
+#endif
+
+#ifndef OPENSSL_NO_MD5
+# ifndef OPENSSL_NO_DES
+    NID_pbeWithMD5AndDES_CBC,
+# endif
+# ifndef OPENSSL_NO_RC2
+    NID_pbeWithMD5AndRC2_CBC,
+# endif
+#endif
+#ifndef OPENSSL_NO_DES
+    NID_pbeWithSHA1AndDES_CBC,
+#endif
+#ifndef OPENSSL_NO_RC2
+    NID_pbe_WithSHA1And128BitRC2_CBC,
+    NID_pbe_WithSHA1And40BitRC2_CBC,
+    NID_pbeWithSHA1AndRC2_CBC,
+#endif
+#ifndef OPENSSL_NO_RC4
+    NID_pbe_WithSHA1And128BitRC4,
+    NID_pbe_WithSHA1And40BitRC4,
+#endif
+#ifndef OPENSSL_NO_DES
+    NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
+    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+#endif
+};
+
+static const int enc_nids_no_legacy[] = {
+    /* NOTE: To use PBES2 we pass the desired cipher NID instead of NID_pbes2 */
+    NID_aes_128_cbc,
+    NID_aes_256_cbc,
+#ifndef OPENSSL_NO_DES
+    NID_des_ede3_cbc,
+    NID_pbe_WithSHA1And2_Key_TripleDES_CBC,
+    NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+#endif
+};
+
+static const int mac_nids[] = {
+    NID_sha1,
+    NID_md5,
+    NID_sha256,
+    NID_sha512,
+    NID_sha3_256,
+    NID_sha3_512
+};
+
+static const int iters[] = {
+    1,
+    1000
+};
+
+static const char *passwords[] = {
+    "Password1",
+    "",
+};
 
 /* --------------------------------------------------------------------------
  * Local functions
@@ -261,9 +344,79 @@ static int test_single_cert_no_attrs(void)
     return end_pkcs12_builder(pb);
 }
 
+static int test_single_key(PKCS12_ENC *enc)
+{
+    char fname[80];
+    PKCS12_BUILDER *pb;
+
+    sprintf(fname, "1key_ciph-%s_iter-%d.p12", OBJ_nid2sn(enc->nid), enc->iter);
+
+    pb = new_pkcs12_builder(fname);
+
+    /* Generate/encode */
+    start_pkcs12(pb);
+
+        start_contentinfo(pb);
+
+            add_keybag(pb, KEY1, sizeof(KEY1), NULL, enc);
+
+        end_contentinfo(pb);
+
+    end_pkcs12(pb);
+
+    /* Read/decode */
+    start_check_pkcs12(pb);
+
+        start_check_contentinfo(pb);
+
+            check_keybag(pb, KEY1, sizeof(KEY1), NULL, enc);
+
+        end_check_contentinfo(pb);
+
+    end_check_pkcs12(pb);
+
+    return end_pkcs12_builder(pb);
+}
+
+static int test_single_key_enc_alg(int z)
+{
+    PKCS12_ENC enc;
+
+    if (lgcyprov == NULL)
+        enc.nid = enc_nids_no_legacy[z];
+    else
+        enc.nid = enc_nids_all[z];
+    enc.pass = enc_default.pass;
+    enc.iter = enc_default.iter;
+
+    return test_single_key(&enc);
+}
+
+static int test_single_key_enc_pass(int z)
+{
+    PKCS12_ENC enc;
+
+    enc.nid = enc_default.nid;
+    enc.pass = passwords[z];
+    enc.iter = enc_default.iter;
+
+    return test_single_key(&enc);
+}
+
+static int test_single_key_enc_iter(int z)
+{
+    PKCS12_ENC enc;
+
+    enc.nid = enc_default.nid;
+    enc.pass = enc_default.pass;
+    enc.iter = iters[z];
+
+    return test_single_key(&enc);
+}
+
 static int test_single_key_with_attrs(void)
 {
-    PKCS12_BUILDER *pb = new_pkcs12_builder("1key.p12");
+    PKCS12_BUILDER *pb = new_pkcs12_builder("1keyattrs.p12");
     
     /* Generate/encode */
     start_pkcs12(pb);
@@ -290,6 +443,73 @@ static int test_single_key_with_attrs(void)
     return end_pkcs12_builder(pb);
 }
 
+static int test_single_cert_mac(PKCS12_ENC *mac)
+{
+    char fname[80];
+    PKCS12_BUILDER *pb;
+
+    sprintf(fname, "1cert_mac-%s_iter-%d.p12", OBJ_nid2sn(mac->nid), mac->iter);
+
+    pb = new_pkcs12_builder(fname);
+
+    /* Generate/encode */
+    start_pkcs12(pb);
+
+        start_contentinfo(pb);
+
+            add_certbag(pb, CERT1, sizeof(CERT1), NULL);
+
+        end_contentinfo(pb);
+
+    end_pkcs12_with_mac(pb, mac);
+
+    /* Read/decode */
+    start_check_pkcs12_with_mac(pb, mac);
+
+        start_check_contentinfo(pb);
+
+            check_certbag(pb, CERT1, sizeof(CERT1), NULL);
+
+        end_check_contentinfo(pb);
+
+    end_check_pkcs12(pb);
+
+    return end_pkcs12_builder(pb);
+}
+
+static int test_single_cert_mac_alg(int z)
+{
+    PKCS12_ENC mac;
+
+    mac.nid = mac_nids[z];
+    mac.pass = mac_default.pass;
+    mac.iter = mac_default.iter;
+
+    return test_single_cert_mac(&mac);
+}
+
+static int test_single_cert_mac_pass(int z)
+{
+    PKCS12_ENC mac;
+
+    mac.nid = mac_default.nid;
+    mac.pass = passwords[z];
+    mac.iter = mac_default.iter;
+
+    return test_single_cert_mac(&mac);
+}
+
+static int test_single_cert_mac_iter(int z)
+{
+    PKCS12_ENC mac;
+
+    mac.nid = mac_default.nid;
+    mac.pass = mac_default.pass;
+    mac.iter = iters[z];
+
+    return test_single_cert_mac(&mac);
+}
+
 static int test_cert_key_with_attrs_and_mac(void)
 {
     PKCS12_BUILDER *pb = new_pkcs12_builder("1cert1key.p12");
@@ -430,11 +650,86 @@ static int test_multiple_contents(void)
     return end_pkcs12_builder(pb);
 }
 
+typedef enum OPTION_choice {
+    OPT_ERR = -1,
+    OPT_EOF = 0,
+    OPT_WRITE,
+    OPT_LEGACY,
+    OPT_CONTEXT,
+    OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+    static const OPTIONS options[] = {
+        OPT_TEST_OPTIONS_DEFAULT_USAGE,
+        { "write",   OPT_WRITE,   '-', "Write PKCS12 objects to file" },
+        { "legacy",  OPT_LEGACY,  '-', "Test the legacy APIs" },
+        { "context", OPT_CONTEXT, '-', "Explicitly use a non-default library context" },
+        { NULL }
+    };
+    return options;
+}
 
 int setup_tests(void)
 {
+    OPTION_CHOICE o;
+
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_WRITE:
+            PKCS12_helper_set_write_files(1);
+            break;
+        case OPT_LEGACY:
+            PKCS12_helper_set_legacy(1);
+            break;
+        case OPT_CONTEXT:
+            default_libctx = 0;
+            break;
+        case OPT_TEST_CASES:
+            break;
+        default:
+            return 0;
+        }
+    }
+
+    if (!default_libctx) {
+        testctx = OSSL_LIB_CTX_new();
+        if (!TEST_ptr(testctx))
+            return 0;
+        nullprov = OSSL_PROVIDER_load(NULL, "null");
+        if (!TEST_ptr(nullprov))
+            return 0;
+    }
+
+    deflprov = OSSL_PROVIDER_load(testctx, "default");
+    if (!TEST_ptr(deflprov))
+        return 0;
+    lgcyprov = OSSL_PROVIDER_load(testctx, "legacy");
+
+    PKCS12_helper_set_libctx(testctx);
+
+    /*
+     * Verify that the default and fips providers in the default libctx are not
+     * available if we are using a standalone context
+     */
+    if (!default_libctx) {
+        if (!TEST_false(OSSL_PROVIDER_available(NULL, "default"))
+                || !TEST_false(OSSL_PROVIDER_available(NULL, "fips")))
+            return 0;
+    }
+
     ADD_TEST(test_single_cert_no_attrs);
+    if (lgcyprov == NULL)
+        ADD_ALL_TESTS(test_single_key_enc_alg, OSSL_NELEM(enc_nids_no_legacy));
+    else
+        ADD_ALL_TESTS(test_single_key_enc_alg, OSSL_NELEM(enc_nids_all));
+    ADD_ALL_TESTS(test_single_key_enc_pass, OSSL_NELEM(passwords));
+    ADD_ALL_TESTS(test_single_key_enc_iter, OSSL_NELEM(iters));
     ADD_TEST(test_single_key_with_attrs);
+    ADD_ALL_TESTS(test_single_cert_mac_alg, OSSL_NELEM(mac_nids));
+    ADD_ALL_TESTS(test_single_cert_mac_pass, OSSL_NELEM(passwords));
+    ADD_ALL_TESTS(test_single_cert_mac_iter, OSSL_NELEM(iters));
     ADD_TEST(test_cert_key_with_attrs_and_mac);
     ADD_TEST(test_cert_key_encrypted_content);
     ADD_TEST(test_single_secret_encrypted_content);
@@ -442,3 +737,10 @@ int setup_tests(void)
     return 1;
 }
 
+void cleanup_tests(void)
+{
+    OSSL_PROVIDER_unload(nullprov);
+    OSSL_PROVIDER_unload(deflprov);
+    OSSL_PROVIDER_unload(lgcyprov);
+    OSSL_LIB_CTX_free(testctx);
+}
diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t
index 49eb2b5225..b259c1a335 100644
--- a/test/recipes/80-test_pkcs12.t
+++ b/test/recipes/80-test_pkcs12.t
@@ -16,9 +16,6 @@ use Encode;
 
 setup("test_pkcs12");
 
-plan skip_all => "The PKCS12 command line utility is not supported by this OpenSSL build"
-    if disabled("des");
-
 my $pass = "σύνθημα γνώρισμα";
 
 my $savedcp;
@@ -57,10 +54,14 @@ if (eval { require Win32::API; 1; }) {
 }
 $ENV{OPENSSL_WIN32_UTF8}=1;
 
-plan tests => 5;
+plan tests => 7;
 
 # Test different PKCS#12 formats
 ok(run(test(["pkcs12_format_test"])), "test pkcs12 formats");
+# Test with legacy APIs
+ok(run(test(["pkcs12_format_test", "-legacy"])), "test pkcs12 formats using legacy APIs");
+# Test with a non-default library context (and no loaded providers in the default context)
+ok(run(test(["pkcs12_format_test", "-context"])), "test pkcs12 formats using a non-default library context");
 
 # just see that we can read shibboleth.pfx protected with $pass
 ok(run(app(["openssl", "pkcs12", "-noout",
@@ -82,13 +83,17 @@ ok(run(app(["openssl", "pkcs12", "-export", "-chain",
    "test_pkcs12_chain_untrusted");
 
 # Test the -passcerts option
-ok(run(app(["openssl", "pkcs12", "-export",
+SKIP: {
+    skip "Skipping PKCS#12 test because DES is disabled in this build", 1
+        if disabled("des");
+    ok(run(app(["openssl", "pkcs12", "-export",
             "-in", srctop_file(@path, "ee-cert.pem"),
             "-certfile", srctop_file(@path, "v3-certs-TDES.p12"),
             "-passcerts", "pass:v3-certs",
             "-nokeys", "-passout", "pass:v3-certs", "-descert",
             "-out", $outfile2])),
    "test_pkcs12_passcerts");
+}
 
 SKIP: {
     skip "Skipping legacy PKCS#12 test because RC2 is disabled in this build", 1
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 54978afe20..d8a8eca05f 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5368,3 +5368,30 @@ EVP_SIGNATURE_name                      ?	3_0_0	EXIST::FUNCTION:
 EVP_ASYM_CIPHER_name                    ?	3_0_0	EXIST::FUNCTION:
 EVP_KEM_name                            ?	3_0_0	EXIST::FUNCTION:
 EVP_KEYEXCH_name                        ?	3_0_0	EXIST::FUNCTION:
+PKCS5_v2_PBE_keyivgen_ex                ?	3_0_0	EXIST::FUNCTION:
+EVP_PBE_scrypt_ex                       ?	3_0_0	EXIST::FUNCTION:SCRYPT
+PKCS5_v2_scrypt_keyivgen_ex             ?	3_0_0	EXIST::FUNCTION:SCRYPT
+EVP_PBE_CipherInit_ex                   ?	3_0_0	EXIST::FUNCTION:
+EVP_PBE_find_ex                         ?	3_0_0	EXIST::FUNCTION:
+PKCS12_SAFEBAG_create_pkcs8_encrypt_ex  ?	3_0_0	EXIST::FUNCTION:
+PKCS8_decrypt_ex                        ?	3_0_0	EXIST::FUNCTION:
+PKCS12_decrypt_skey_ex                  ?	3_0_0	EXIST::FUNCTION:
+PKCS8_encrypt_ex                        ?	3_0_0	EXIST::FUNCTION:
+PKCS8_set0_pbe_ex                       ?	3_0_0	EXIST::FUNCTION:
+PKCS12_pack_p7encdata_ex                ?	3_0_0	EXIST::FUNCTION:
+PKCS12_pbe_crypt_ex                     ?	3_0_0	EXIST::FUNCTION:
+PKCS12_item_decrypt_d2i_ex              ?	3_0_0	EXIST::FUNCTION:
+PKCS12_item_i2d_encrypt_ex              ?	3_0_0	EXIST::FUNCTION:
+PKCS12_init_ex                          ?	3_0_0	EXIST::FUNCTION:
+PKCS12_key_gen_asc_ex                   ?	3_0_0	EXIST::FUNCTION:
+PKCS12_key_gen_uni_ex                   ?	3_0_0	EXIST::FUNCTION:
+PKCS12_key_gen_utf8_ex                  ?	3_0_0	EXIST::FUNCTION:
+PKCS12_PBE_keyivgen_ex                  ?	3_0_0	EXIST::FUNCTION:
+PKCS12_create_ex                        ?	3_0_0	EXIST::FUNCTION:
+PKCS12_add_key_ex                       ?	3_0_0	EXIST::FUNCTION:
+PKCS12_add_safe_ex                      ?	3_0_0	EXIST::FUNCTION:
+PKCS12_add_safes_ex                     ?	3_0_0	EXIST::FUNCTION:
+PKCS5_pbe_set0_algor_ex                 ?	3_0_0	EXIST::FUNCTION:
+PKCS5_pbe_set_ex                        ?	3_0_0	EXIST::FUNCTION:
+PKCS5_pbe2_set_iv_ex                    ?	3_0_0	EXIST::FUNCTION:
+PKCS5_pbkdf2_set_ex                     ?	3_0_0	EXIST::FUNCTION:
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index 662fec4a1c..efd3c7516a 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -650,13 +650,10 @@ EVP_CIPHER_set_asn1_iv(3)
 EVP_KDF_ctrl(3)
 EVP_MD_do_all(3)
 EVP_MD_do_all_sorted(3)
-EVP_PBE_CipherInit(3)
 EVP_PBE_alg_add(3)
 EVP_PBE_alg_add_type(3)
 EVP_PBE_cleanup(3)
-EVP_PBE_find(3)
 EVP_PBE_get(3)
-EVP_PBE_scrypt(3)
 EVP_PKEY_CTX_get0_peerkey(3)
 EVP_PKEY_CTX_get0_pkey(3)
 EVP_PKEY_CTX_get_data(3)
@@ -884,61 +881,22 @@ PKCS12_AUTHSAFES_it(3)
 PKCS12_BAGS_it(3)
 PKCS12_MAC_DATA_it(3)
 PKCS12_PBE_add(3)
-PKCS12_PBE_keyivgen(3)
 PKCS12_SAFEBAGS_it(3)
-PKCS12_SAFEBAG_create0_p8inf(3)
-PKCS12_SAFEBAG_create0_pkcs8(3)
-PKCS12_SAFEBAG_create_cert(3)
-PKCS12_SAFEBAG_create_crl(3)
-PKCS12_SAFEBAG_create_pkcs8_encrypt(3)
-PKCS12_SAFEBAG_get0_attr(3)
-PKCS12_SAFEBAG_get0_p8inf(3)
-PKCS12_SAFEBAG_get0_pkcs8(3)
-PKCS12_SAFEBAG_get0_safes(3)
-PKCS12_SAFEBAG_get0_type(3)
-PKCS12_SAFEBAG_get1_cert(3)
 PKCS12_SAFEBAG_get1_crl(3)
-PKCS12_SAFEBAG_get_bag_nid(3)
-PKCS12_SAFEBAG_get_nid(3)
 PKCS12_SAFEBAG_it(3)
-PKCS12_add_cert(3)
-PKCS12_add_key(3)
-PKCS12_add_safe(3)
-PKCS12_add_safes(3)
-PKCS12_decrypt_skey(3)
-PKCS12_gen_mac(3)
 PKCS12_get0_mac(3)
 PKCS12_get_attr(3)
-PKCS12_init(3)
 PKCS12_it(3)
-PKCS12_item_decrypt_d2i(3)
-PKCS12_item_i2d_encrypt(3)
 PKCS12_item_pack_safebag(3)
-PKCS12_key_gen_asc(3)
-PKCS12_key_gen_uni(3)
-PKCS12_key_gen_utf8(3)
 PKCS12_mac_present(3)
 PKCS12_pack_authsafes(3)
 PKCS12_pack_p7data(3)
 PKCS12_pack_p7encdata(3)
-PKCS12_pbe_crypt(3)
-PKCS12_set_mac(3)
-PKCS12_setup_mac(3)
 PKCS12_unpack_authsafes(3)
 PKCS12_unpack_p7data(3)
 PKCS12_unpack_p7encdata(3)
-PKCS12_verify_mac(3)
 PKCS1_MGF1(3)
 PKCS5_PBE_add(3)
-PKCS5_PBE_keyivgen(3)
-PKCS5_pbe2_set(3)
-PKCS5_pbe2_set_iv(3)
-PKCS5_pbe2_set_scrypt(3)
-PKCS5_pbe_set(3)
-PKCS5_pbe_set0_algor(3)
-PKCS5_pbkdf2_set(3)
-PKCS5_v2_PBE_keyivgen(3)
-PKCS5_v2_scrypt_keyivgen(3)
 PKCS7_ATTR_SIGN_it(3)
 PKCS7_ATTR_VERIFY_it(3)
 PKCS7_DIGEST_it(3)
@@ -995,12 +953,9 @@ PKCS7_stream(3)
 PKCS7_to_TS_TST_INFO(3)
 PKCS8_PRIV_KEY_INFO_it(3)
 PKCS8_add_keyusage(3)
-PKCS8_decrypt(3)
-PKCS8_encrypt(3)
 PKCS8_get_attr(3)
 PKCS8_pkey_get0(3)
 PKCS8_pkey_set0(3)
-PKCS8_set0_pbe(3)
 PKEY_USAGE_PERIOD_it(3)
 POLICYINFO_it(3)
 POLICYQUALINFO_it(3)


More information about the openssl-commits mailing list