[openssl] master update

tomas at openssl.org tomas at openssl.org
Tue Jun 1 10:17:01 UTC 2021


The branch master has been updated
       via  5e2d22d53ed322a7124e26a4fbd116a8210eb77a (commit)
       via  e3c7595521c88579b9eaf02fc11025a2ecdb6ad5 (commit)
       via  169eca602c67f37abf0a44e1605998d5e7f04fa6 (commit)
      from  8ee66a092c07e618191ef49c8912f8235b08bb95 (commit)


- Log -----------------------------------------------------------------
commit 5e2d22d53ed322a7124e26a4fbd116a8210eb77a
Author: Jon Spillett <jon.spillett at oracle.com>
Date:   Tue May 18 13:37:35 2021 +1000

    Pass library context and property query into private key decoders
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14587)

commit e3c7595521c88579b9eaf02fc11025a2ecdb6ad5
Author: Jon Spillett <jon.spillett at oracle.com>
Date:   Thu May 6 11:55:42 2021 +1000

    Fix up encoder/decoder issues caused by not passing a library context to the PKCS8 encrypt/decrypt
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14587)

commit 169eca602c67f37abf0a44e1605998d5e7f04fa6
Author: Jon Spillett <jon.spillett at oracle.com>
Date:   Mon Mar 15 14:26:09 2021 +1000

    Enhance the encoder/decoder tests to allow testing with a non-default library context and configurable providers
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14587)

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

Summary of changes:
 crypto/pem/pvkfmt.c                                | 115 +++++++++-----
 doc/build.info                                     |   6 +
 doc/man3/b2i_PVK_bio_ex.pod                        |  69 +++++++++
 include/crypto/pem.h                               |   4 +
 include/openssl/pem.h                              |   5 +
 .../implementations/encode_decode/decode_der2key.c |   2 +-
 .../implementations/encode_decode/decode_pvk2key.c |  10 +-
 .../implementations/encode_decode/encode_key2any.c |   3 +-
 .../implementations/encode_decode/encode_key2ms.c  |   5 +-
 test/endecode_test.c                               | 166 ++++++++++++++++-----
 test/evp_libctx_test.c                             |   2 +-
 test/recipes/04-test_encoder_decoder.t             |  43 ++++--
 test/testutil.h                                    |   7 +
 test/testutil/provider.c                           |  14 +-
 util/libcrypto.num                                 |   2 +
 util/missingcrypto.txt                             |   2 -
 16 files changed, 357 insertions(+), 98 deletions(-)
 create mode 100644 doc/man3/b2i_PVK_bio_ex.pod

diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index 51d3ec476b..1ff68e2158 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -792,22 +792,27 @@ int ossl_do_PVK_header(const unsigned char **in, unsigned int length,
 #ifndef OPENSSL_NO_RC4
 static int derive_pvk_key(unsigned char *key,
                           const unsigned char *salt, unsigned int saltlen,
-                          const unsigned char *pass, int passlen)
+                          const unsigned char *pass, int passlen,
+                          OSSL_LIB_CTX *libctx, const char *propq)
 {
     EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-    EVP_MD *md = EVP_MD_fetch(NULL, SN_sha1, NULL);
-    int rv = 1;
+    int rv = 0;
+    EVP_MD *sha1 = NULL;
 
-    if (md == NULL
-        || mctx == NULL
-        || !EVP_DigestInit_ex(mctx, md, NULL)
+    if ((sha1 = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL)
+        goto err;
+
+    if (mctx == NULL
+        || !EVP_DigestInit_ex(mctx, sha1, NULL)
         || !EVP_DigestUpdate(mctx, salt, saltlen)
         || !EVP_DigestUpdate(mctx, pass, passlen)
         || !EVP_DigestFinal_ex(mctx, key, NULL))
-        rv = 0;
+        goto err;
 
+    rv = 1;
+err:
     EVP_MD_CTX_free(mctx);
-    EVP_MD_free(md);
+    EVP_MD_free(sha1);
     return rv;
 }
 #endif
@@ -815,14 +820,18 @@ static int derive_pvk_key(unsigned char *key,
 static void *do_PVK_body_key(const unsigned char **in,
                              unsigned int saltlen, unsigned int keylen,
                              pem_password_cb *cb, void *u,
-                             int *isdss, int *ispub)
+                             int *isdss, int *ispub,
+                             OSSL_LIB_CTX *libctx, const char *propq)
 {
     const unsigned char *p = *in;
     unsigned char *enctmp = NULL;
     unsigned char keybuf[20];
     void *key = NULL;
-
+#ifndef OPENSSL_NO_RC4
+    EVP_CIPHER *rc4 = NULL;
+#endif
     EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+
     if (saltlen) {
 #ifndef OPENSSL_NO_RC4
         unsigned int magic;
@@ -844,7 +853,7 @@ static void *do_PVK_body_key(const unsigned char **in,
             goto err;
         }
         if (!derive_pvk_key(keybuf, p, saltlen,
-                            (unsigned char *)psbuf, inlen))
+                            (unsigned char *)psbuf, inlen, libctx, propq))
             goto err;
         p += saltlen;
         /* Copy BLOBHEADER across, decrypt rest */
@@ -856,7 +865,9 @@ static void *do_PVK_body_key(const unsigned char **in,
         }
         inlen = keylen - 8;
         q = enctmp + 8;
-        if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+        if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
+            goto err;
+        if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
             goto err;
         if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
             goto err;
@@ -866,7 +877,7 @@ static void *do_PVK_body_key(const unsigned char **in,
         if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
             q = enctmp + 8;
             memset(keybuf + 5, 0, 11);
-            if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+            if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
                 goto err;
             if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
                 goto err;
@@ -888,6 +899,9 @@ static void *do_PVK_body_key(const unsigned char **in,
     key = do_b2i_key(&p, keylen, isdss, ispub);
  err:
     EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+    EVP_CIPHER_free(rc4);
+#endif
     if (enctmp != NULL) {
         OPENSSL_cleanse(keybuf, sizeof(keybuf));
         OPENSSL_free(enctmp);
@@ -896,7 +910,8 @@ static void *do_PVK_body_key(const unsigned char **in,
 }
 
 static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u,
-                            int *isdss, int *ispub)
+                            int *isdss, int *ispub,
+                            OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned char pvk_hdr[24], *buf = NULL;
     const unsigned char *p;
@@ -923,7 +938,7 @@ static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u,
         ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT);
         goto err;
     }
-    key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub);
+    key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub, libctx, propq);
 
  err:
     OPENSSL_clear_free(buf, buflen);
@@ -931,40 +946,61 @@ static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u,
 }
 
 #ifndef OPENSSL_NO_DSA
-DSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+DSA *b2i_DSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                        OSSL_LIB_CTX *libctx, const char *propq)
 {
     int isdss = 1;
     int ispub = 0;               /* PVK keys are always private */
 
-    return do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+    return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq);
+}
+
+DSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+    return b2i_DSA_PVK_bio_ex(in, cb, u, NULL, NULL);
 }
 #endif
 
-RSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+RSA *b2i_RSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                        OSSL_LIB_CTX *libctx, const char *propq)
 {
     int isdss = 0;
     int ispub = 0;               /* PVK keys are always private */
 
-    return do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+    return do_PVK_key_bio(in, cb, u, &isdss, &ispub, libctx, propq);
 }
 
-EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+RSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+    return b2i_RSA_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                         OSSL_LIB_CTX *libctx, const char *propq)
 {
     int isdss = -1;
     int ispub = -1;
-    void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+    void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL);
 
     return evp_pkey_new0_key(key, isdss_to_evp_type(isdss));
 }
 
+EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+    return b2i_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+
 static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
-                   pem_password_cb *cb, void *u)
+                   pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+                   const char *propq)
 {
+    int ret = -1;
     int outlen = 24, pklen;
     unsigned char *p = NULL, *start = NULL;
     EVP_CIPHER_CTX *cctx = NULL;
 #ifndef OPENSSL_NO_RC4
     unsigned char *salt = NULL;
+    EVP_CIPHER *rc4 = NULL;
 #endif
 
     if (enclevel)
@@ -1002,7 +1038,7 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
     write_ledword(&p, pklen);
     if (enclevel) {
 #ifndef OPENSSL_NO_RC4
-        if (RAND_bytes(p, PVK_SALTLEN) <= 0)
+        if (RAND_bytes_ex(libctx, p, PVK_SALTLEN, 0) <= 0)
             goto error;
         salt = p;
         p += PVK_SALTLEN;
@@ -1014,7 +1050,6 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
         char psbuf[PEM_BUFSIZE];
         unsigned char keybuf[20];
         int enctmplen, inlen;
-
         if (cb)
             inlen = cb(psbuf, PEM_BUFSIZE, 1, u);
         else
@@ -1024,12 +1059,14 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
             goto error;
         }
         if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
-                            (unsigned char *)psbuf, inlen))
+                            (unsigned char *)psbuf, inlen, libctx, propq))
+            goto error;
+        if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
             goto error;
         if (enclevel == 1)
             memset(keybuf + 5, 0, 11);
         p = salt + PVK_SALTLEN + 8;
-        if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+        if (!EVP_EncryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
             goto error;
         OPENSSL_cleanse(keybuf, 20);
         if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
@@ -1042,27 +1079,28 @@ static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
 #endif
     }
 
-    EVP_CIPHER_CTX_free(cctx);
-
     if (*out == NULL)
         *out = start;
-
-    return outlen;
-
+    ret = outlen;
  error:
     EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+    EVP_CIPHER_free(rc4);
+#endif
     if (*out == NULL)
         OPENSSL_free(start);
-    return -1;
+
+    return ret;
 }
 
-int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
-                pem_password_cb *cb, void *u)
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+                   pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+                   const char *propq)
 {
     unsigned char *tmp = NULL;
     int outlen, wrlen;
 
-    outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
+    outlen = i2b_PVK(&tmp, pk, enclevel, cb, u, libctx, propq);
     if (outlen < 0)
         return -1;
     wrlen = BIO_write(out, tmp, outlen);
@@ -1073,3 +1111,10 @@ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
     ERR_raise(ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE);
     return -1;
 }
+
+int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+                pem_password_cb *cb, void *u)
+{
+    return i2b_PVK_bio_ex(out, pk, enclevel, cb, u, NULL, NULL);
+}
+
diff --git a/doc/build.info b/doc/build.info
index b77c04d2b6..42c1804d6c 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -2779,6 +2779,10 @@ DEPEND[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
 GENERATE[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
 DEPEND[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
 GENERATE[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
+DEPEND[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+GENERATE[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+DEPEND[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
+GENERATE[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
 DEPEND[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
 GENERATE[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
 DEPEND[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
@@ -3398,6 +3402,7 @@ html/man3/X509_sign.html \
 html/man3/X509_verify.html \
 html/man3/X509_verify_cert.html \
 html/man3/X509v3_get_ext_by_NID.html \
+html/man3/b2i_PVK_bio_ex.html \
 html/man3/d2i_PKCS8PrivateKey_bio.html \
 html/man3/d2i_PrivateKey.html \
 html/man3/d2i_RSAPrivateKey.html \
@@ -3986,6 +3991,7 @@ man/man3/X509_sign.3 \
 man/man3/X509_verify.3 \
 man/man3/X509_verify_cert.3 \
 man/man3/X509v3_get_ext_by_NID.3 \
+man/man3/b2i_PVK_bio_ex.3 \
 man/man3/d2i_PKCS8PrivateKey_bio.3 \
 man/man3/d2i_PrivateKey.3 \
 man/man3/d2i_RSAPrivateKey.3 \
diff --git a/doc/man3/b2i_PVK_bio_ex.pod b/doc/man3/b2i_PVK_bio_ex.pod
new file mode 100644
index 0000000000..bd670b2614
--- /dev/null
+++ b/doc/man3/b2i_PVK_bio_ex.pod
@@ -0,0 +1,69 @@
+=pod
+
+=head1 NAME
+
+b2i_PVK_bio, b2i_PVK_bio_ex, i2b_PVK_bio, i2b_PVK_bio_ex - Decode and encode
+functions for reading and writing MSBLOB format private keys
+
+=head1 SYNOPSIS
+
+ #include <openssl/pem.h>
+
+ EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+ EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                          OSSL_LIB_CTX *libctx, const char *propq);
+ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+                 pem_password_cb *cb, void *u);
+ int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+                    pem_password_cb *cb, void *u,
+                    OSSL_LIB_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+b2i_PVK_bio_ex() decodes a private key of MSBLOB format read from a B<BIO>. It
+attempts to automatically determine the key type. If the key is encrypted then
+I<cb> is called with the user data I<u> in order to obtain a password to decrypt
+the key. The supplied library context I<libctx> and property query
+string I<propq> are used in any decrypt operation.
+
+b2i_PVK_bio() does the same as b2i_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+i2b_PVK_bio_ex() encodes I<pk> using MSBLOB format. If I<enclevel> is 1 then
+a password obtained via I<pem_password_cb> is used to encrypt the private key.
+If I<enclevel> is 0 then no encryption is applied. The user data in I<u> is
+passed to the password callback. The supplied library context I<libctx> and
+property query string I<propq> are used in any decrypt operation.
+
+i2b_PVK_bio() does the same as i2b_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+=head1 RETURN VALUES
+
+The b2i_PVK_bio() and b2i_PVK_bio_ex() functions return a valid B<EVP_KEY>
+structure or B<NULL> if an error occurs. The error code can be obtained by calling
+L<ERR_get_error(3)>.
+
+i2b_PVK_bio() and i2b_PVK_bio_ex() return the number of bytes successfully
+encoded or a negative value if an error occurs. The error code can be obtained
+by calling L<ERR_get_error(3)>.
+
+=head1 SEE ALSO
+
+L<crypto(7)>,
+L<d2i_PKCS8PrivateKey_bio(3)>
+
+=head1 HISTORY
+
+b2i_PVK_bio_ex() and i2b_PVK_bio_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/pem.h b/include/crypto/pem.h
index 2a0e6424a5..840dc18f06 100644
--- a/include/crypto/pem.h
+++ b/include/crypto/pem.h
@@ -40,8 +40,12 @@ EVP_PKEY *ossl_b2i_bio(BIO *in, int *ispub);
 # ifndef OPENSSL_NO_DEPRECATED_3_0
 #  ifndef OPENSSL_NO_DSA
 DSA *b2i_DSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+DSA *b2i_DSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                        OSSL_LIB_CTX *libctx, const char *propq);
 #  endif
 RSA *b2i_RSA_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+RSA *b2i_RSA_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                        OSSL_LIB_CTX *libctx, const char *propq);
 # endif
 
 #endif
diff --git a/include/openssl/pem.h b/include/openssl/pem.h
index aaf4e262af..80940dfa96 100644
--- a/include/openssl/pem.h
+++ b/include/openssl/pem.h
@@ -524,8 +524,13 @@ EVP_PKEY *b2i_PublicKey_bio(BIO *in);
 int i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk);
 int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk);
 EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+                         OSSL_LIB_CTX *libctx, const char *propq);
 int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
                 pem_password_cb *cb, void *u);
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+                   pem_password_cb *cb, void *u,
+                   OSSL_LIB_CTX *libctx, const char *propq);
 
 # ifdef  __cplusplus
 }
diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c
index 01c050ccb0..b3fd87ca05 100644
--- a/providers/implementations/encode_decode/decode_der2key.c
+++ b/providers/implementations/encode_decode/decode_der2key.c
@@ -134,7 +134,7 @@ static void *der2key_decode_p8(const unsigned char **input_der,
         if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg))
             ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_GET_PASSPHRASE);
         else
-            p8inf = PKCS8_decrypt(p8, pbuf, plen);
+            p8inf = PKCS8_decrypt_ex(p8, pbuf, plen, PROV_LIBCTX_OF(ctx->provctx), NULL);
         if (p8inf == NULL)
             ctx->flag_fatal = 1;
         X509_SIG_free(p8);
diff --git a/providers/implementations/encode_decode/decode_pvk2key.c b/providers/implementations/encode_decode/decode_pvk2key.c
index 702c89a928..b69b2416a5 100644
--- a/providers/implementations/encode_decode/decode_pvk2key.c
+++ b/providers/implementations/encode_decode/decode_pvk2key.c
@@ -33,7 +33,8 @@
 struct pvk2key_ctx_st;            /* Forward declaration */
 typedef int check_key_fn(void *, struct pvk2key_ctx_st *ctx);
 typedef void adjust_key_fn(void *, struct pvk2key_ctx_st *ctx);
-typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u);
+typedef void *b2i_PVK_of_bio_pw_fn(BIO *in, pem_password_cb *cb, void *u,
+                                   OSSL_LIB_CTX *libctx, const char *propq);
 typedef void free_key_fn(void *);
 struct keytype_desc_st {
     int type;                 /* EVP key type */
@@ -118,7 +119,8 @@ static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin, int selection,
         if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
             goto end;
 
-        key = ctx->desc->read_private_key(in, ossl_pw_pem_password, &pwdata);
+        key = ctx->desc->read_private_key(in, ossl_pw_pem_password, &pwdata,
+                                          PROV_LIBCTX_OF(ctx->provctx), NULL);
 
         /*
          * Because the PVK API doesn't have a separate decrypt call, we need
@@ -204,13 +206,13 @@ static int pvk2key_export_object(void *vctx,
 
 /* ---------------------------------------------------------------------- */
 
-#define dsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio
+#define dsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_DSA_PVK_bio_ex
 #define dsa_adjust              NULL
 #define dsa_free                (void (*)(void *))DSA_free
 
 /* ---------------------------------------------------------------------- */
 
-#define rsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio
+#define rsa_private_key_bio     (b2i_PVK_of_bio_pw_fn *)b2i_RSA_PVK_bio_ex
 
 static void rsa_adjust(void *key, struct pvk2key_ctx_st *ctx)
 {
diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c
index 93f725d906..f95c785522 100644
--- a/providers/implementations/encode_decode/encode_key2any.c
+++ b/providers/implementations/encode_decode/encode_key2any.c
@@ -106,6 +106,7 @@ static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info,
     X509_SIG *p8 = NULL;
     char kstr[PEM_BUFSIZE];
     size_t klen = 0;
+    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
 
     if (ctx->cipher == NULL)
         return NULL;
@@ -116,7 +117,7 @@ static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info,
         return NULL;
     }
     /* First argument == -1 means "standard" */
-    p8 = PKCS8_encrypt(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info);
+    p8 = PKCS8_encrypt_ex(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info, libctx, NULL);
     OPENSSL_cleanse(kstr, klen);
     return p8;
 }
diff --git a/providers/implementations/encode_decode/encode_key2ms.c b/providers/implementations/encode_decode/encode_key2ms.c
index 81dfcd0ecc..79012e673e 100644
--- a/providers/implementations/encode_decode/encode_key2ms.c
+++ b/providers/implementations/encode_decode/encode_key2ms.c
@@ -52,10 +52,11 @@ static int write_pvk(struct key2ms_ctx_st *ctx, OSSL_CORE_BIO *cout,
 {
     BIO *out = NULL;
     int ret = 0;
+    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
 
     out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
-    ret = i2b_PVK_bio(out, pkey, ctx->pvk_encr_level,
-                      ossl_pw_pem_password, &ctx->pwdata);
+    ret = i2b_PVK_bio_ex(out, pkey, ctx->pvk_encr_level,
+                         ossl_pw_pem_password, &ctx->pwdata, libctx, NULL);
     BIO_free(out);
 
     return ret;
diff --git a/test/endecode_test.c b/test/endecode_test.c
index f851f73ffd..f800d7738c 100644
--- a/test/endecode_test.c
+++ b/test/endecode_test.c
@@ -41,6 +41,17 @@
 # define OPENSSL_NO_KEYPARAMS
 #endif
 
+static int default_libctx = 1;
+static int is_fips = 0;
+
+static OSSL_LIB_CTX *testctx = NULL;
+static OSSL_LIB_CTX *keyctx = NULL;
+static char *testpropq = NULL;
+
+static OSSL_PROVIDER *nullprov = NULL;
+static OSSL_PROVIDER *deflprov = NULL;
+static OSSL_PROVIDER *keyprov = NULL;
+
 #ifndef OPENSSL_NO_EC
 static BN_CTX *bnctx = NULL;
 static OSSL_PARAM_BLD *bld_prime_nc = NULL;
@@ -68,16 +79,17 @@ static EVP_PKEY *make_template(const char *type, OSSL_PARAM *genparams)
      * for testing only. Use a minimum key size of 2048 for security purposes.
      */
     if (strcmp(type, "DH") == 0)
-        return get_dh512(NULL);
+        return get_dh512(keyctx);
+
     if (strcmp(type, "X9.42 DH") == 0)
-        return get_dhx512(NULL);
+        return get_dhx512(keyctx);
 # endif
 
     /*
      * No real need to check the errors other than for the cascade
      * effect.  |pkey| will simply remain NULL if something goes wrong.
      */
-    (void)((ctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL)) != NULL
+    (void)((ctx = EVP_PKEY_CTX_new_from_name(keyctx, type, testpropq)) != NULL
            && EVP_PKEY_paramgen_init(ctx) > 0
            && (genparams == NULL
                || EVP_PKEY_CTX_set_params(ctx, genparams) > 0)
@@ -95,8 +107,8 @@ static EVP_PKEY *make_key(const char *type, EVP_PKEY *template,
     EVP_PKEY *pkey = NULL;
     EVP_PKEY_CTX *ctx =
         template != NULL
-        ? EVP_PKEY_CTX_new(template, NULL)
-        : EVP_PKEY_CTX_new_from_name(NULL, type, NULL);
+        ? EVP_PKEY_CTX_new_from_pkey(keyctx, template, testpropq)
+        : EVP_PKEY_CTX_new_from_name(keyctx, type, testpropq);
 
     /*
      * No real need to check the errors other than for the cascade
@@ -215,7 +227,7 @@ static int encode_EVP_PKEY_prov(const char *file, const int line,
     if (!TEST_FL_ptr(ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection,
                                                        output_type,
                                                        output_structure,
-                                                       NULL))
+                                                       testpropq))
         || !TEST_FL_int_gt(OSSL_ENCODER_CTX_get_num_encoders(ectx), 0)
         || (pass != NULL
             && !TEST_FL_true(OSSL_ENCODER_CTX_set_passphrase(ectx, upass,
@@ -278,7 +290,7 @@ static int decode_EVP_PKEY_prov(const char *file, const int line,
                                                            structure_type,
                                                            keytype,
                                                            selection,
-                                                           NULL, NULL))
+                                                           testctx, testpropq))
             || (pass != NULL
                 && !OSSL_DECODER_CTX_set_passphrase(dctx, upass, strlen(pass)))
             || !TEST_FL_int_gt(BIO_reset(encoded_bio), 0)
@@ -331,7 +343,7 @@ static int encode_EVP_PKEY_legacy_PEM(const char *file, const int line,
 
     if (pcipher != NULL && pass != NULL) {
         passlen = strlen(pass);
-        if (!TEST_FL_ptr(cipher = EVP_CIPHER_fetch(NULL, pcipher, NULL)))
+        if (!TEST_FL_ptr(cipher = EVP_CIPHER_fetch(testctx, pcipher, testpropq)))
             goto end;
     }
     if (!TEST_FL_ptr(mem_ser = BIO_new(BIO_s_mem()))
@@ -416,8 +428,8 @@ static int encode_EVP_PKEY_PVK(const char *file, const int line,
     if (!TEST_FL_true(ossl_assert((selection
                                 & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0))
         || !TEST_FL_ptr(mem_ser = BIO_new(BIO_s_mem()))
-        || !TEST_FL_int_ge(i2b_PVK_bio(mem_ser, pkey, enc,
-                                    pass_pw, (void *)pass), 0)
+        || !TEST_FL_int_ge(i2b_PVK_bio_ex(mem_ser, pkey, enc,
+                                          pass_pw, (void *)pass, testctx, testpropq), 0)
         || !TEST_FL_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
         || !TEST_FL_ptr(*encoded = mem_buf->data)
         || !TEST_FL_long_gt(*encoded_len = mem_buf->length, 0))
@@ -491,7 +503,7 @@ static int check_unprotected_PKCS8_DER(const char *file, const int line,
     int ok = 0;
 
     if (TEST_FL_ptr(p8inf)) {
-        EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
+        EVP_PKEY *pkey = EVP_PKCS82PKEY_ex(p8inf, testctx, testpropq);
         char *namelist = NULL;
 
         if (TEST_FL_ptr(pkey)) {
@@ -513,7 +525,7 @@ static int test_unprotected_via_DER(const char *type, EVP_PKEY *key)
 {
     return test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_KEYPAIR
-                              | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+                              | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
                               "DER", "pkcs8", NULL, NULL,
                               encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
                               test_mem, check_unprotected_PKCS8_DER,
@@ -533,8 +545,9 @@ static int check_unprotected_PKCS8_PEM(const char *file, const int line,
 
 static int test_unprotected_via_PEM(const char *type, EVP_PKEY *key)
 {
-    return test_encode_decode(__FILE__, __LINE__, type, key, OSSL_KEYMGMT_SELECT_KEYPAIR
-                              | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+    return test_encode_decode(__FILE__, __LINE__, type, key,
+                              OSSL_KEYMGMT_SELECT_KEYPAIR
+                              | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
                               "PEM", "pkcs8", NULL, NULL,
                               encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
                               test_text, check_unprotected_PKCS8_PEM,
@@ -615,6 +628,9 @@ static int check_unprotected_legacy_PEM(const char *file, const int line,
 
 static int test_unprotected_via_legacy_PEM(const char *type, EVP_PKEY *key)
 {
+    if (!default_libctx || is_fips)
+        return TEST_skip("Test not available if using a non-default library context or FIPS provider");
+
     return test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_KEYPAIR
                               | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
@@ -731,6 +747,9 @@ static int check_protected_legacy_PEM(const char *file, const int line,
 
 static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key)
 {
+    if (!default_libctx || is_fips)
+        return TEST_skip("Test not available if using a non-default library context or FIPS provider");
+
     return test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_KEYPAIR
                               | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
@@ -743,12 +762,19 @@ static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key)
 #ifndef OPENSSL_NO_RC4
 static int test_protected_via_PVK(const char *type, EVP_PKEY *key)
 {
-    return test_encode_decode(__FILE__, __LINE__, type, key,
+    int ret = 0;
+    OSSL_PROVIDER *lgcyprov = OSSL_PROVIDER_load(testctx, "legacy");
+    if (lgcyprov == NULL)
+        return TEST_skip("Legacy provider not available");
+
+    ret = test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_KEYPAIR
                               | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
                               "PVK", NULL, pass, NULL,
                               encode_EVP_PKEY_PVK, decode_EVP_PKEY_prov,
                               test_mem, check_PVK, dump_der, 0);
+    OSSL_PROVIDER_unload(lgcyprov);
+    return ret;
 }
 #endif
 
@@ -756,7 +782,7 @@ static int check_public_DER(const char *file, const int line,
                             const char *type, const void *data, size_t data_len)
 {
     const unsigned char *datap = data;
-    EVP_PKEY *pkey = d2i_PUBKEY(NULL, &datap, data_len);
+    EVP_PKEY *pkey = d2i_PUBKEY_ex(NULL, &datap, data_len, testctx, testpropq);
     int ok = (TEST_FL_ptr(pkey) && TEST_FL_true(EVP_PKEY_is_a(pkey, type)));
 
     EVP_PKEY_free(pkey);
@@ -767,7 +793,7 @@ static int test_public_via_DER(const char *type, EVP_PKEY *key)
 {
     return test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_PUBLIC_KEY
-                              | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+                              | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
                               "DER", "SubjectPublicKeyInfo", NULL, NULL,
                               encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
                               test_mem, check_public_DER, dump_der, 0);
@@ -788,7 +814,7 @@ static int test_public_via_PEM(const char *type, EVP_PKEY *key)
 {
     return test_encode_decode(__FILE__, __LINE__, type, key,
                               OSSL_KEYMGMT_SELECT_PUBLIC_KEY
-                              | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+                              | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
                               "PEM", "SubjectPublicKeyInfo", NULL, NULL,
                               encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
                               test_text, check_public_PEM, dump_pem, 0);
@@ -1184,14 +1210,42 @@ static int create_ec_explicit_trinomial_params(OSSL_PARAM_BLD *bld)
 # endif /* OPENSSL_NO_EC2M */
 #endif /* OPENSSL_NO_EC */
 
-#define USAGE "rsa-key.pem rsa-pss-key.pem\n"
-OPT_TEST_DECLARE_USAGE(USAGE)
+typedef enum OPTION_choice {
+    OPT_ERR = -1,
+    OPT_EOF = 0,
+    OPT_CONTEXT,
+    OPT_RSA_FILE,
+    OPT_RSA_PSS_FILE,
+    OPT_CONFIG_FILE,
+    OPT_PROVIDER_NAME,
+    OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+    static const OPTIONS options[] = {
+        OPT_TEST_OPTIONS_DEFAULT_USAGE,
+        { "context", OPT_CONTEXT, '-',
+          "Explicitly use a non-default library context" },
+        { "rsa", OPT_RSA_FILE, '<',
+          "PEM format RSA key file to encode/decode" },
+        { "pss", OPT_RSA_PSS_FILE, '<',
+          "PEM format RSA-PSS key file to encode/decode" },
+        { "config", OPT_CONFIG_FILE, '<',
+          "The configuration file to use for the library context" },
+        { "provider", OPT_PROVIDER_NAME, 's',
+          "The provider to load (The default value is 'default')" },
+        { NULL }
+    };
+    return options;
+}
 
 int setup_tests(void)
 {
-# ifndef OPENSSL_NO_RC4
-    int use_legacy = OSSL_PROVIDER_available(NULL, "legacy");
-#endif
+    const char *rsa_file = NULL;
+    const char *rsa_pss_file = NULL;
+    const char *prov_name = "default";
+    char *config_file = NULL;
     int ok = 1;
 
 #ifndef OPENSSL_NO_DSA
@@ -1212,17 +1266,51 @@ int setup_tests(void)
     };
 #endif
 
-    if (!test_skip_common_options()) {
-        TEST_error("Error parsing test options\n");
-        return 0;
+    OPTION_CHOICE o;
+
+    while ((o = opt_next()) != OPT_EOF) {
+        switch (o) {
+        case OPT_CONTEXT:
+            default_libctx = 0;
+            break;
+        case OPT_PROVIDER_NAME:
+            prov_name = opt_arg();
+            break;
+        case OPT_CONFIG_FILE:
+            config_file = opt_arg();
+            break;
+        case OPT_RSA_FILE:
+            rsa_file = opt_arg();
+            break;
+        case OPT_RSA_PSS_FILE:
+            rsa_pss_file = opt_arg();
+            break;
+        case OPT_TEST_CASES:
+            break;
+        default:
+            return 0;
+        }
     }
-    if (test_get_argument_count() != 2) {
-        TEST_error("usage: endecode_test %s", USAGE);
-        return 0;
+
+    if (strcmp(prov_name, "fips") == 0)
+        is_fips = 1;
+
+    if (default_libctx) {
+        if (!test_get_libctx(NULL, NULL, config_file, &deflprov, prov_name))
+            return 0;
+    } else {
+        if (!test_get_libctx(&testctx, &nullprov, config_file, &deflprov, prov_name))
+            return 0;
     }
 
+    /* Separate provider/ctx for generating the test data */
+    if (!TEST_ptr(keyctx = OSSL_LIB_CTX_new()))
+        return 0;
+    if (!TEST_ptr(keyprov = OSSL_PROVIDER_load(keyctx, "default")))
+        return 0;
+
 #ifndef OPENSSL_NO_EC
-    if (!TEST_ptr(bnctx = BN_CTX_new_ex(NULL))
+    if (!TEST_ptr(bnctx = BN_CTX_new_ex(testctx))
         || !TEST_ptr(bld_prime_nc = OSSL_PARAM_BLD_new())
         || !TEST_ptr(bld_prime = OSSL_PARAM_BLD_new())
         || !create_ec_explicit_prime_params_namedcurve(bld_prime_nc)
@@ -1267,9 +1355,9 @@ int setup_tests(void)
     MAKE_KEYS(X448, "X448", NULL);
 #endif
     TEST_info("Loading RSA key...");
-    ok = ok && TEST_ptr(key_RSA = load_pkey_pem(test_get_argument(0), NULL));
+    ok = ok && TEST_ptr(key_RSA = load_pkey_pem(rsa_file, keyctx));
     TEST_info("Loading RSA_PSS key...");
-    ok = ok && TEST_ptr(key_RSA_PSS = load_pkey_pem(test_get_argument(1), NULL));
+    ok = ok && TEST_ptr(key_RSA_PSS = load_pkey_pem(rsa_pss_file, keyctx));
     TEST_info("Generating keys done");
 
     if (ok) {
@@ -1290,9 +1378,7 @@ int setup_tests(void)
         ADD_TEST_SUITE_MSBLOB(DSA);
         ADD_TEST_SUITE_UNPROTECTED_PVK(DSA);
 # ifndef OPENSSL_NO_RC4
-        if (use_legacy) {
-            ADD_TEST_SUITE_PROTECTED_PVK(DSA);
-        }
+        ADD_TEST_SUITE_PROTECTED_PVK(DSA);
 # endif
 #endif
 #ifndef OPENSSL_NO_EC
@@ -1328,9 +1414,7 @@ int setup_tests(void)
         ADD_TEST_SUITE_MSBLOB(RSA);
         ADD_TEST_SUITE_UNPROTECTED_PVK(RSA);
 # ifndef OPENSSL_NO_RC4
-        if (use_legacy) {
-            ADD_TEST_SUITE_PROTECTED_PVK(RSA);
-        }
+        ADD_TEST_SUITE_PROTECTED_PVK(RSA);
 # endif
     }
 
@@ -1375,4 +1459,10 @@ void cleanup_tests(void)
 #endif
     FREE_KEYS(RSA);
     FREE_KEYS(RSA_PSS);
+
+    OSSL_PROVIDER_unload(nullprov);
+    OSSL_PROVIDER_unload(deflprov);
+    OSSL_PROVIDER_unload(keyprov);
+    OSSL_LIB_CTX_free(testctx);
+    OSSL_LIB_CTX_free(keyctx);
 }
diff --git a/test/evp_libctx_test.c b/test/evp_libctx_test.c
index 5e8f436cca..f51de88c55 100644
--- a/test/evp_libctx_test.c
+++ b/test/evp_libctx_test.c
@@ -55,7 +55,7 @@ const OPTIONS *test_get_options(void)
         { "config", OPT_CONFIG_FILE, '<',
           "The configuration file to use for the libctx" },
         { "provider", OPT_PROVIDER_NAME, 's',
-          "The provider to load (The default value is 'default'" },
+          "The provider to load (The default value is 'default')" },
         { NULL }
     };
     return test_options;
diff --git a/test/recipes/04-test_encoder_decoder.t b/test/recipes/04-test_encoder_decoder.t
index 0152519716..19541610a9 100644
--- a/test/recipes/04-test_encoder_decoder.t
+++ b/test/recipes/04-test_encoder_decoder.t
@@ -1,5 +1,5 @@
 #! /usr/bin/env perl
-# 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
@@ -9,18 +9,43 @@
 use strict;
 use warnings;
 
-use OpenSSL::Test::Simple;
-use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir/;
-use Cwd qw(abs_path);
+use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
+use OpenSSL::Test::Utils;
 
-setup("test_encoder_decoder");
+BEGIN {
+    setup("test_encoder_decoder");
+}
 
-plan tests => 1;
+use lib srctop_dir('Configurations');
+use lib bldtop_dir('.');
+use platform;
 
-$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("providers"));
-$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-legacy.cnf"));
+my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
 
 my $rsa_key = srctop_file("test", "certs", "ee-key.pem");
 my $pss_key = srctop_file("test", "certs", "ca-pss-key.pem");
 
-ok(run(test(["endecode_test", $rsa_key, $pss_key])));
+plan tests => ($no_fips ? 0 : 1) + 2;     # FIPS install test + test
+
+my $conf = srctop_file("test", "default.cnf");
+ok(run(test(["endecode_test", "-rsa", $rsa_key,
+                              "-pss", $pss_key,
+                              "-config", $conf,
+                              "-provider", "default"])));
+
+# Run with non-default library context
+ok(run(test(["endecode_test", "-rsa", $rsa_key,
+                              "-pss", $pss_key,
+                              "-context",
+                              "-config", $conf,
+                              "-provider", "default"])));
+
+unless ($no_fips) {
+    # Run with fips library context
+    my $conf = srctop_file("test", "fips-and-base.cnf");
+    ok(run(test(["endecode_test", "-rsa", $rsa_key,
+                                  "-pss", $pss_key,
+                                  "-config", $conf,
+                                  "-provider", "fips"])));
+}
+
diff --git a/test/testutil.h b/test/testutil.h
index 9311e2ce58..710f51c147 100644
--- a/test/testutil.h
+++ b/test/testutil.h
@@ -206,6 +206,13 @@ size_t test_get_argument_count(void);
  */
 int test_skip_common_options(void);
 
+/*
+ * Get a library context for the tests, populated with the specified provider
+ * and configuration. If default_null_prov is not NULL, a "null" provider is
+ * loaded into the default library context to prevent it being used.
+ * If libctx is NULL, the specified provider is loaded into the default library
+ * context.
+ */
 int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
                     const char *config_file,
                     OSSL_PROVIDER **provider, const char *module_name);
diff --git a/test/testutil/provider.c b/test/testutil/provider.c
index c50ef035fc..5a571bf5de 100644
--- a/test/testutil/provider.c
+++ b/test/testutil/provider.c
@@ -15,9 +15,13 @@ int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
                     const char *config_file,
                     OSSL_PROVIDER **provider, const char *module_name)
 {
-    if ((*libctx = OSSL_LIB_CTX_new()) == NULL) {
-        opt_printf_stderr("Failed to create libctx\n");
-        goto err;
+    OSSL_LIB_CTX *new_libctx = NULL;
+
+    if (libctx != NULL) {
+        if ((new_libctx = *libctx = OSSL_LIB_CTX_new()) == NULL) {
+            opt_printf_stderr("Failed to create libctx\n");
+            goto err;
+        }
     }
 
     if (default_null_prov != NULL
@@ -27,13 +31,13 @@ int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
     }
 
     if (config_file != NULL
-            && !OSSL_LIB_CTX_load_config(*libctx, config_file)) {
+            && !OSSL_LIB_CTX_load_config(new_libctx, config_file)) {
         opt_printf_stderr("Error loading config from file %s\n", config_file);
         goto err;
     }
 
     if (module_name != NULL
-            && (*provider = OSSL_PROVIDER_load(*libctx, module_name)) == NULL) {
+            && (*provider = OSSL_PROVIDER_load(new_libctx, module_name)) == NULL) {
         opt_printf_stderr("Failed to load provider %s\n", module_name);
         goto err;
     }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 1016d9c327..c7d89421a2 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5416,3 +5416,5 @@ OSSL_PROVIDER_get0_dispatch             5543	3_0_0	EXIST::FUNCTION:
 PKCS5_PBE_keyivgen_ex                   5544	3_0_0	EXIST::FUNCTION:
 EVP_MAC_CTX_get_block_size              5545	3_0_0	EXIST::FUNCTION:
 BIO_debug_callback_ex                   5546	3_0_0	EXIST::FUNCTION:
+b2i_PVK_bio_ex                          5547	3_0_0	EXIST::FUNCTION:
+i2b_PVK_bio_ex                          5548	3_0_0	EXIST::FUNCTION:
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index 04eace5da7..df71963deb 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -1413,7 +1413,6 @@ a2i_ASN1_STRING(3)
 a2i_GENERAL_NAME(3)
 a2i_IPADDRESS(3)
 a2i_IPADDRESS_NC(3)
-b2i_PVK_bio(3)
 b2i_PrivateKey(3)
 b2i_PrivateKey_bio(3)
 b2i_PublicKey(3)
@@ -1429,7 +1428,6 @@ i2a_ASN1_ENUMERATED(3)
 i2a_ASN1_INTEGER(3)
 i2a_ASN1_OBJECT(3)
 i2a_ASN1_STRING(3)
-i2b_PVK_bio(3)
 i2b_PrivateKey_bio(3)
 i2b_PublicKey_bio(3)
 i2d_X509_bio(3)


More information about the openssl-commits mailing list