[openssl] master update

Dr. Paul Dale pauli at openssl.org
Sat Mar 7 09:43:34 UTC 2020


The branch master has been updated
       via  6bd4e3f231d74578b97821d981d42583fec5c2f3 (commit)
       via  5e98904c231f5a40c6ce291df85799cca7c8d125 (commit)
      from  55f02cb6849f0366dd8b787dbe8e74b56c15bfd1 (commit)


- Log -----------------------------------------------------------------
commit 6bd4e3f231d74578b97821d981d42583fec5c2f3
Author: Pauli <paul.dale at oracle.com>
Date:   Tue Feb 25 14:29:30 2020 +1000

    cmdline app: add provider commandline options.
    
    Add a -provider option to allow providers to be loaded. This option can be
    specified multiple times.
    
    Add a -provider_path option to allow the path to providers to be specified.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11167)

commit 5e98904c231f5a40c6ce291df85799cca7c8d125
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Feb 27 07:45:31 2020 +1000

    man1: make all openssl command line tool documentation generated.
    
    With the introduction of provider command line options which are applicable to
    almost all of the command line tools, it seemed reasonable to make them all
    generated.  This simplifes the .gitignore and avoids having to keep two lists
    in sync.
    
    Reviewed-by: Tomas Mraz <tmraz at fedoraproject.org>
    (Merged from https://github.com/openssl/openssl/pull/11167)

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

Summary of changes:
 .gitignore                                         | 38 +---------
 apps/ca.c                                          |  7 +-
 apps/ciphers.c                                     |  7 +-
 apps/cms.c                                         |  6 ++
 apps/crl.c                                         |  8 ++-
 apps/crl2p7.c                                      |  9 ++-
 apps/dgst.c                                        |  7 +-
 apps/dhparam.c                                     |  7 +-
 apps/dsa.c                                         |  8 ++-
 apps/dsaparam.c                                    |  7 +-
 apps/ec.c                                          |  8 ++-
 apps/ecparam.c                                     |  7 +-
 apps/enc.c                                         |  7 +-
 apps/gendsa.c                                      |  7 +-
 apps/genpkey.c                                     | 10 ++-
 apps/genrsa.c                                      |  7 +-
 apps/include/opt.h                                 | 19 +++++
 apps/kdf.c                                         |  9 ++-
 apps/lib/app_provider.c                            | 51 ++++++++++++++
 apps/lib/build.info                                |  2 +-
 apps/list.c                                        |  9 ++-
 apps/mac.c                                         |  9 ++-
 apps/nseq.c                                        |  9 ++-
 apps/ocsp.c                                        |  7 +-
 apps/passwd.c                                      |  7 +-
 apps/pkcs12.c                                      |  7 +-
 apps/pkcs7.c                                       |  9 ++-
 apps/pkcs8.c                                       |  7 +-
 apps/pkey.c                                        |  8 ++-
 apps/pkeyparam.c                                   |  9 ++-
 apps/pkeyutl.c                                     |  7 +-
 apps/prime.c                                       |  9 ++-
 apps/rand.c                                        |  7 +-
 apps/rehash.c                                      |  9 ++-
 apps/req.c                                         |  7 +-
 apps/rsa.c                                         |  9 ++-
 apps/rsautl.c                                      |  7 +-
 apps/s_client.c                                    |  7 +-
 apps/s_server.c                                    |  8 ++-
 apps/s_time.c                                      |  8 ++-
 apps/smime.c                                       |  7 +-
 apps/speed.c                                       |  7 +-
 apps/spkac.c                                       |  9 ++-
 apps/srp.c                                         |  7 +-
 apps/storeutl.c                                    |  8 ++-
 apps/ts.c                                          |  7 +-
 apps/verify.c                                      |  9 ++-
 apps/x509.c                                        |  7 +-
 crypto/provider_core.c                             | 42 ++++++++++-
 doc/man1/build.info                                | 82 +++++++++++++++++-----
 ...nssl-asn1parse.pod => openssl-asn1parse.pod.in} |  1 +
 doc/man1/openssl-ca.pod.in                         |  3 +
 ...{openssl-ciphers.pod => openssl-ciphers.pod.in} |  4 ++
 doc/man1/{openssl-cmds.pod => openssl-cmds.pod.in} |  1 +
 doc/man1/openssl-cms.pod.in                        |  3 +
 doc/man1/openssl-crl.pod.in                        |  3 +
 ...nssl-crl2pkcs7.pod => openssl-crl2pkcs7.pod.in} |  4 ++
 doc/man1/openssl-dgst.pod.in                       |  3 +
 doc/man1/openssl-dhparam.pod.in                    |  3 +
 doc/man1/openssl-dsa.pod.in                        |  3 +
 doc/man1/openssl-dsaparam.pod.in                   |  3 +
 doc/man1/openssl-ec.pod.in                         |  3 +
 doc/man1/openssl-ecparam.pod.in                    |  3 +
 doc/man1/openssl-enc.pod.in                        |  3 +
 .../{openssl-engine.pod => openssl-engine.pod.in}  |  1 +
 .../{openssl-errstr.pod => openssl-errstr.pod.in}  |  1 +
 ...-fipsinstall.pod => openssl-fipsinstall.pod.in} |  1 +
 doc/man1/openssl-gendsa.pod.in                     |  3 +
 doc/man1/openssl-genpkey.pod.in                    |  3 +
 doc/man1/openssl-genrsa.pod.in                     |  3 +
 doc/man1/{openssl-info.pod => openssl-info.pod.in} |  1 +
 doc/man1/{openssl-kdf.pod => openssl-kdf.pod.in}   |  4 ++
 doc/man1/{openssl-list.pod => openssl-list.pod.in} |  4 ++
 doc/man1/{openssl-mac.pod => openssl-mac.pod.in}   |  4 ++
 doc/man1/{openssl-nseq.pod => openssl-nseq.pod.in} |  4 ++
 doc/man1/openssl-ocsp.pod.in                       |  3 +
 doc/man1/openssl-passwd.pod.in                     |  3 +
 doc/man1/openssl-pkcs12.pod.in                     |  3 +
 doc/man1/openssl-pkcs7.pod.in                      |  3 +
 doc/man1/openssl-pkcs8.pod.in                      |  3 +
 doc/man1/openssl-pkey.pod.in                       |  3 +
 doc/man1/openssl-pkeyparam.pod.in                  |  3 +
 doc/man1/openssl-pkeyutl.pod.in                    |  3 +
 .../{openssl-prime.pod => openssl-prime.pod.in}    |  4 ++
 ...penssl-provider.pod => openssl-provider.pod.in} |  1 +
 doc/man1/openssl-rand.pod.in                       |  3 +
 .../{openssl-rehash.pod => openssl-rehash.pod.in}  |  5 ++
 doc/man1/openssl-req.pod.in                        |  3 +
 doc/man1/openssl-rsa.pod.in                        |  3 +
 doc/man1/openssl-rsautl.pod.in                     |  3 +
 doc/man1/openssl-s_client.pod.in                   |  3 +
 doc/man1/openssl-s_server.pod.in                   |  3 +
 doc/man1/openssl-s_time.pod.in                     |  3 +
 ...{openssl-sess_id.pod => openssl-sess_id.pod.in} |  1 +
 doc/man1/openssl-smime.pod.in                      |  3 +
 doc/man1/openssl-speed.pod.in                      |  3 +
 doc/man1/openssl-spkac.pod.in                      |  3 +
 doc/man1/openssl-srp.pod.in                        |  3 +
 doc/man1/openssl-storeutl.pod.in                   |  3 +
 doc/man1/openssl-ts.pod.in                         |  5 ++
 doc/man1/openssl-verify.pod.in                     |  3 +
 ...{openssl-version.pod => openssl-version.pod.in} |  1 +
 doc/man1/openssl-x509.pod.in                       |  3 +
 doc/man1/openssl.pod                               | 20 ++++++
 doc/man3/OSSL_PROVIDER.pod                         |  9 +++
 doc/perlvars.pm                                    | 11 +++
 include/openssl/provider.h                         |  3 +
 util/libcrypto.num                                 |  1 +
 108 files changed, 671 insertions(+), 100 deletions(-)
 create mode 100644 apps/lib/app_provider.c
 rename doc/man1/{openssl-asn1parse.pod => openssl-asn1parse.pod.in} (99%)
 rename doc/man1/{openssl-ciphers.pod => openssl-ciphers.pod.in} (99%)
 rename doc/man1/{openssl-cmds.pod => openssl-cmds.pod.in} (98%)
 rename doc/man1/{openssl-crl2pkcs7.pod => openssl-crl2pkcs7.pod.in} (95%)
 rename doc/man1/{openssl-engine.pod => openssl-engine.pod.in} (98%)
 rename doc/man1/{openssl-errstr.pod => openssl-errstr.pod.in} (95%)
 rename doc/man1/{openssl-fipsinstall.pod => openssl-fipsinstall.pod.in} (98%)
 rename doc/man1/{openssl-info.pod => openssl-info.pod.in} (97%)
 rename doc/man1/{openssl-kdf.pod => openssl-kdf.pod.in} (97%)
 rename doc/man1/{openssl-list.pod => openssl-list.pod.in} (96%)
 rename doc/man1/{openssl-mac.pod => openssl-mac.pod.in} (96%)
 rename doc/man1/{openssl-nseq.pod => openssl-nseq.pod.in} (92%)
 rename doc/man1/{openssl-prime.pod => openssl-prime.pod.in} (89%)
 rename doc/man1/{openssl-provider.pod => openssl-provider.pod.in} (95%)
 rename doc/man1/{openssl-rehash.pod => openssl-rehash.pod.in} (95%)
 rename doc/man1/{openssl-sess_id.pod => openssl-sess_id.pod.in} (98%)
 rename doc/man1/{openssl-version.pod => openssl-version.pod.in} (96%)

diff --git a/.gitignore b/.gitignore
index f51ccce56d..0578fd5c1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,43 +26,7 @@
 /include/openssl/opensslv.h
 
 # Auto generated doc files
-# Keep this in sync with doc/man1/build.info
-doc/man1/openssl-ca.pod
-doc/man1/openssl-cms.pod
-doc/man1/openssl-crl.pod
-doc/man1/openssl-dgst.pod
-doc/man1/openssl-dhparam.pod
-doc/man1/openssl-dsa.pod
-doc/man1/openssl-dsaparam.pod
-doc/man1/openssl-ec.pod
-doc/man1/openssl-ecparam.pod
-doc/man1/openssl-enc.pod
-doc/man1/openssl-gendsa.pod
-doc/man1/openssl-genpkey.pod
-doc/man1/openssl-genrsa.pod
-doc/man1/openssl-ocsp.pod
-doc/man1/openssl-passwd.pod
-doc/man1/openssl-pkcs12.pod
-doc/man1/openssl-pkcs7.pod
-doc/man1/openssl-pkcs8.pod
-doc/man1/openssl-pkey.pod
-doc/man1/openssl-pkeyparam.pod
-doc/man1/openssl-pkeyutl.pod
-doc/man1/openssl-rand.pod
-doc/man1/openssl-req.pod
-doc/man1/openssl-rsa.pod
-doc/man1/openssl-rsautl.pod
-doc/man1/openssl-s_client.pod
-doc/man1/openssl-s_server.pod
-doc/man1/openssl-s_time.pod
-doc/man1/openssl-smime.pod
-doc/man1/openssl-speed.pod
-doc/man1/openssl-spkac.pod
-doc/man1/openssl-srp.pod
-doc/man1/openssl-storeutl.pod
-doc/man1/openssl-ts.pod
-doc/man1/openssl-verify.pod
-doc/man1/openssl-x509.pod
+doc/man1/openssl-*.pod
 
 # error code files
 /crypto/err/openssl.txt.old
diff --git a/apps/ca.c b/apps/ca.c
index f201efe3af..84e1905d38 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -148,7 +148,7 @@ typedef enum OPTION_choice {
     OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
     OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
     OPT_RAND_SERIAL,
-    OPT_R_ENUM, OPT_SM2ID, OPT_SM2HEXID,
+    OPT_R_ENUM, OPT_SM2ID, OPT_SM2HEXID, OPT_PROV_ENUM,
     /* Do not change the order here; see related case statements below */
     OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
 } OPTION_CHOICE;
@@ -237,6 +237,7 @@ const OPTIONS ca_options[] = {
     {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"certreq", 0, 0, "Certificate requests to be signed (optional)"},
@@ -361,6 +362,10 @@ opthelp:
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_KEY:
             key = opt_arg();
             break;
diff --git a/apps/ciphers.c b/apps/ciphers.c
index 280a5ab477..9bbc12aeec 100644
--- a/apps/ciphers.c
+++ b/apps/ciphers.c
@@ -27,7 +27,7 @@ typedef enum OPTION_choice {
     OPT_PSK,
     OPT_SRP,
     OPT_CIPHERSUITES,
-    OPT_V, OPT_UPPER_V, OPT_S
+    OPT_V, OPT_UPPER_V, OPT_S, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ciphers_options[] = {
@@ -67,6 +67,7 @@ const OPTIONS ciphers_options[] = {
 #endif
     {"ciphersuites", OPT_CIPHERSUITES, 's',
      "Configure the TLSv1.3 ciphersuites to use"},
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"cipher", 0, 0, "Cipher string to decode (optional)"},
@@ -169,6 +170,10 @@ int ciphers_main(int argc, char **argv)
         case OPT_CIPHERSUITES:
             ciphersuites = opt_arg();
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argv = opt_rest();
diff --git a/apps/cms.c b/apps/cms.c
index 9c92e79658..c8c303ea37 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -83,6 +83,7 @@ typedef enum OPTION_choice {
     OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
     OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
     OPT_R_ENUM,
+    OPT_PROV_ENUM,
     OPT_V_ENUM,
     OPT_CIPHER,
     OPT_ORIGINATOR
@@ -220,6 +221,7 @@ const OPTIONS cms_options[] = {
 
     OPT_R_OPTIONS,
     OPT_V_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"cert", 0, 0, "Recipient certs (optional; used only when encrypting)"},
@@ -621,6 +623,10 @@ int cms_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_3DES_WRAP:
 # ifndef OPENSSL_NO_DES
             wrap_cipher = EVP_des_ede3_wrap();
diff --git a/apps/crl.c b/apps/crl.c
index 14410f3512..5e0a517a1b 100644
--- a/apps/crl.c
+++ b/apps/crl.c
@@ -24,7 +24,7 @@ typedef enum OPTION_choice {
     OPT_ISSUER, OPT_LASTUPDATE, OPT_NEXTUPDATE, OPT_FINGERPRINT,
     OPT_CRLNUMBER, OPT_BADSIG, OPT_GENDELTA, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
     OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_VERIFY, OPT_TEXT, OPT_HASH,
-    OPT_HASH_OLD, OPT_NOOUT, OPT_NAMEOPT, OPT_MD
+    OPT_HASH_OLD, OPT_NOOUT, OPT_NAMEOPT, OPT_MD, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS crl_options[] = {
@@ -69,6 +69,7 @@ const OPTIONS crl_options[] = {
      "Do not load certificates from the default certificates directory"},
     {"no-CAstore", OPT_NOCASTORE, '-',
      "Do not load certificates from the default certificates store"},
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -193,6 +194,11 @@ int crl_main(int argc, char **argv)
         case OPT_MD:
             if (!opt_md(opt_unknown(), &digest))
                 goto opthelp;
+            break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/crl2p7.c b/apps/crl2p7.c
index ffbee4cbff..53bc88f750 100644
--- a/apps/crl2p7.c
+++ b/apps/crl2p7.c
@@ -23,7 +23,8 @@ static int add_certs_from_file(STACK_OF(X509) *stack, char *certfile);
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE
+    OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOCRL, OPT_CERTFILE,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS crl2pkcs7_options[] = {
@@ -40,6 +41,8 @@ const OPTIONS crl2pkcs7_options[] = {
     OPT_SECTION("Output"),
     {"out", OPT_OUT, '>', "Output file"},
     {"outform", OPT_OUTFORM, 'F', "Output format - DER or PEM"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -93,6 +96,10 @@ int crl2pkcs7_main(int argc, char **argv)
             if (!sk_OPENSSL_STRING_push(certflst, opt_arg()))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/dgst.c b/apps/dgst.c
index 7a81cb28dc..dcb4c094c7 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -42,7 +42,7 @@ typedef enum OPTION_choice {
     OPT_HEX, OPT_BINARY, OPT_DEBUG, OPT_FIPS_FINGERPRINT,
     OPT_HMAC, OPT_MAC, OPT_SIGOPT, OPT_MACOPT,
     OPT_DIGEST,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dgst_options[] = {
@@ -82,6 +82,7 @@ const OPTIONS dgst_options[] = {
      "Compute HMAC with the key used in OpenSSL-FIPS fingerprint"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"file", 0, 0, "Files to digest (optional; default is stdin)"},
@@ -208,6 +209,10 @@ int dgst_main(int argc, char **argv)
                 goto opthelp;
             md = m;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/dhparam.c b/apps/dhparam.c
index acff366158..3f694c5a35 100644
--- a/apps/dhparam.c
+++ b/apps/dhparam.c
@@ -41,7 +41,7 @@ typedef enum OPTION_choice {
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT,
     OPT_ENGINE, OPT_CHECK, OPT_TEXT, OPT_NOOUT,
     OPT_DSAPARAM, OPT_C, OPT_2, OPT_3, OPT_5,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dhparam_options[] = {
@@ -73,6 +73,7 @@ const OPTIONS dhparam_options[] = {
     {"5", OPT_5, '-', "Generate parameters using 5 as the generator value"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
@@ -151,6 +152,10 @@ int dhparam_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/dsa.c b/apps/dsa.c
index 9704a34c39..082aa96476 100644
--- a/apps/dsa.c
+++ b/apps/dsa.c
@@ -35,7 +35,8 @@ typedef enum OPTION_choice {
     /* Do not change the order here; see case statements below */
     OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
     OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_PUBIN,
-    OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT
+    OPT_PUBOUT, OPT_CIPHER, OPT_PASSIN, OPT_PASSOUT,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dsa_options[] = {
@@ -66,6 +67,7 @@ const OPTIONS dsa_options[] = {
     {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
 
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -147,6 +149,10 @@ int dsa_main(int argc, char **argv)
             if (!opt_cipher(opt_unknown(), &enc))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/dsaparam.c b/apps/dsaparam.c
index eebffa0ee5..04e09e7950 100644
--- a/apps/dsaparam.c
+++ b/apps/dsaparam.c
@@ -36,7 +36,7 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
     OPT_NOOUT, OPT_GENKEY, OPT_ENGINE, OPT_VERBOSE,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS dsaparam_options[] = {
@@ -62,6 +62,7 @@ const OPTIONS dsaparam_options[] = {
     {"genkey", OPT_GENKEY, '-', "Generate a DSA key"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"numbits", 0, 0, "Number of bits if generating parameters (optional)"},
@@ -122,6 +123,10 @@ int dsaparam_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_NOOUT:
             noout = 1;
             break;
diff --git a/apps/ec.c b/apps/ec.c
index 3d901bbad3..6a3879922c 100644
--- a/apps/ec.c
+++ b/apps/ec.c
@@ -40,7 +40,7 @@ typedef enum OPTION_choice {
     OPT_INFORM, OPT_OUTFORM, OPT_ENGINE, OPT_IN, OPT_OUT,
     OPT_NOOUT, OPT_TEXT, OPT_PARAM_OUT, OPT_PUBIN, OPT_PUBOUT,
     OPT_PASSIN, OPT_PASSOUT, OPT_PARAM_ENC, OPT_CONV_FORM, OPT_CIPHER,
-    OPT_NO_PUBLIC, OPT_CHECK
+    OPT_NO_PUBLIC, OPT_CHECK, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ec_options[] = {
@@ -70,6 +70,8 @@ const OPTIONS ec_options[] = {
     {"pubout", OPT_PUBOUT, '-', "Output public key, not private"},
     {"no_public", OPT_NO_PUBLIC, '-', "exclude public key from private key"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -161,6 +163,10 @@ int ec_main(int argc, char **argv)
         case OPT_CHECK:
             check = 1;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/ecparam.c b/apps/ecparam.c
index 307eb1f37e..ed4f4f1fd8 100644
--- a/apps/ecparam.c
+++ b/apps/ecparam.c
@@ -31,7 +31,7 @@ typedef enum OPTION_choice {
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT, OPT_C,
     OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
     OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, OPT_CHECK_NAMED,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ecparam_options[] = {
@@ -67,6 +67,7 @@ const OPTIONS ecparam_options[] = {
     {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -169,6 +170,10 @@ int ecparam_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
diff --git a/apps/enc.c b/apps/enc.c
index 2b23564fab..74fd6f8469 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -45,7 +45,7 @@ typedef enum OPTION_choice {
     OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
     OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
     OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS enc_options[] = {
@@ -97,6 +97,7 @@ const OPTIONS enc_options[] = {
     {"", OPT_CIPHER, '-', "Any supported cipher"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -288,6 +289,10 @@ int enc_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     if (opt_num_rest() != 0) {
diff --git a/apps/gendsa.c b/apps/gendsa.c
index a64ac16a97..cf24416bd7 100644
--- a/apps/gendsa.c
+++ b/apps/gendsa.c
@@ -31,7 +31,7 @@ NON_EMPTY_TRANSLATION_UNIT
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_OUT, OPT_PASSOUT, OPT_ENGINE, OPT_CIPHER, OPT_VERBOSE,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS gendsa_options[] = {
@@ -47,6 +47,7 @@ const OPTIONS gendsa_options[] = {
     {"out", OPT_OUT, '>', "Output the key to the specified file"},
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
     {"verbose", OPT_VERBOSE, '-', "Verbose output"},
 
@@ -92,6 +93,10 @@ int gendsa_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_CIPHER:
             if (!opt_cipher(opt_unknown(), &enc))
                 goto end;
diff --git a/apps/genpkey.c b/apps/genpkey.c
index 3ae508c1c8..ef2979dd55 100644
--- a/apps/genpkey.c
+++ b/apps/genpkey.c
@@ -24,7 +24,8 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx);
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ENGINE, OPT_OUTFORM, OPT_OUT, OPT_PASS, OPT_PARAMFILE,
-    OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER
+    OPT_ALGORITHM, OPT_PKEYOPT, OPT_GENPARAM, OPT_TEXT, OPT_CIPHER,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS genpkey_options[] = {
@@ -46,6 +47,8 @@ const OPTIONS genpkey_options[] = {
     {"text", OPT_TEXT, '-', "Print the in text"},
     {"", OPT_CIPHER, '-', "Cipher to use to encrypt the key"},
 
+    OPT_PROV_OPTIONS,
+
     /* This is deliberately last. */
     {OPT_HELP_STR, 1, 1,
      "Order of options may be important!  See the documentation.\n"},
@@ -131,6 +134,11 @@ int genpkey_main(int argc, char **argv)
                 BIO_printf(bio_err, "%s: cipher mode not supported\n", prog);
                 goto end;
             }
+            break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/genrsa.c b/apps/genrsa.c
index c45fe19b12..3f76d9bada 100644
--- a/apps/genrsa.c
+++ b/apps/genrsa.c
@@ -41,7 +41,7 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_3, OPT_F4, OPT_ENGINE,
     OPT_OUT, OPT_PASSOUT, OPT_CIPHER, OPT_PRIMES, OPT_VERBOSE,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS genrsa_options[] = {
@@ -66,6 +66,7 @@ const OPTIONS genrsa_options[] = {
     {"", OPT_CIPHER, '-', "Encrypt the output with any supported cipher"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"numbits", 0, 0, "Size of key in bits"},
@@ -121,6 +122,10 @@ opthelp:
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_PASSOUT:
             passoutarg = opt_arg();
             break;
diff --git a/apps/include/opt.h b/apps/include/opt.h
index ac2c236024..b4257cca7d 100644
--- a/apps/include/opt.h
+++ b/apps/include/opt.h
@@ -265,6 +265,24 @@
         OPT_R__FIRST: case OPT_R__LAST: break; \
         case OPT_R_RAND: case OPT_R_WRITERAND
 
+/*
+ * Provider options.
+ */
+# define OPT_PROV_ENUM \
+        OPT_PROV__FIRST=1600, \
+        OPT_PROV_PROVIDER, OPT_PROV_PROVIDER_PATH, \
+        OPT_PROV__LAST
+
+# define OPT_PROV_OPTIONS \
+        OPT_SECTION("Provider"), \
+        { "provider", OPT_PROV_PROVIDER, 's', "Provder to load (can be specified multiple times)" }, \
+        { "provider_path", OPT_PROV_PROVIDER_PATH, 's', "Provider load path" }
+
+# define OPT_PROV_CASES \
+        OPT_PROV__FIRST: case OPT_PROV__LAST: break; \
+        case OPT_PROV_PROVIDER: \
+        case OPT_PROV_PROVIDER_PATH
+
 /*
  * Option parsing.
  */
@@ -348,6 +366,7 @@ char **opt_rest(void);
 int opt_num_rest(void);
 int opt_verify(int i, X509_VERIFY_PARAM *vpm);
 int opt_rand(int i);
+int opt_provider(int i);
 void opt_help(const OPTIONS * list);
 void opt_print(const OPTIONS * opt, int doingparams, int width);
 int opt_format_error(const char *s, unsigned long flags);
diff --git a/apps/kdf.c b/apps/kdf.c
index 82818f1ff3..0162ac899a 100644
--- a/apps/kdf.c
+++ b/apps/kdf.c
@@ -19,7 +19,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT
+    OPT_KDFOPT, OPT_BIN, OPT_KEYLEN, OPT_OUT,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS kdf_options[] = {
@@ -36,6 +37,8 @@ const OPTIONS kdf_options[] = {
     {"binary", OPT_BIN, '-',
         "Output in binary format (default is hexadecimal)"},
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"kdf_name", 0, 0, "Name of the KDF algorithm"},
     {NULL}
@@ -80,6 +83,10 @@ opthelp:
             if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
                 goto opthelp;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto err;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/lib/app_provider.c b/apps/lib/app_provider.c
new file mode 100644
index 0000000000..ac01e8826b
--- /dev/null
+++ b/apps/lib/app_provider.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "apps.h"
+#include <openssl/err.h>
+#include <openssl/provider.h>
+
+/*
+ * See comments in opt_verify for explanation of this.
+ */
+enum prov_range { OPT_PROV_ENUM };
+
+static int opt_provider_load(const char *provider)
+{
+    OSSL_PROVIDER *prov;
+
+    prov = OSSL_PROVIDER_load(NULL, provider);
+    if (prov == NULL) {
+        opt_printf_stderr("%s: unable to load provider %s\n",
+                          opt_getprog(), provider);
+        return 0;
+    }
+    return 1;
+}
+
+static int opt_provider_path(const char *path)
+{
+    if (path != NULL && *path == '\0')
+        path = NULL;
+    return OSSL_PROVIDER_set_default_search_path(NULL, path);
+}
+
+int opt_provider(int opt)
+{
+    switch ((enum prov_range)opt) {
+    case OPT_PROV__FIRST:
+    case OPT_PROV__LAST:
+        return 1;
+    case OPT_PROV_PROVIDER:
+        return opt_provider_load(opt_arg());
+    case OPT_PROV_PROVIDER_PATH:
+        return opt_provider_path(opt_arg());
+    }
+    return 0;
+}
diff --git a/apps/lib/build.info b/apps/lib/build.info
index 3f68a2ed35..a7be58b101 100644
--- a/apps/lib/build.info
+++ b/apps/lib/build.info
@@ -9,7 +9,7 @@ ENDIF
 
 # Source for libapps
 $LIBAPPSSRC=apps.c apps_ui.c opt.c fmt.c s_cb.c s_socket.c app_rand.c \
-        columns.c app_params.c names.c
+        columns.c app_params.c names.c app_provider.c
 
 IF[{- !$disabled{apps} -}]
   LIBS{noinst}=../libapps.a
diff --git a/apps/list.c b/apps/list.c
index e8bb8533bb..28fd5c800e 100644
--- a/apps/list.c
+++ b/apps/list.c
@@ -617,7 +617,8 @@ typedef enum HELPLIST_CHOICE {
     OPT_COMMANDS, OPT_DIGEST_COMMANDS, OPT_MAC_ALGORITHMS, OPT_OPTIONS,
     OPT_DIGEST_ALGORITHMS, OPT_CIPHER_COMMANDS, OPT_CIPHER_ALGORITHMS,
     OPT_PK_ALGORITHMS, OPT_PK_METHOD, OPT_ENGINES, OPT_DISABLED,
-    OPT_KDF_ALGORITHMS, OPT_MISSING_HELP, OPT_OBJECTS
+    OPT_KDF_ALGORITHMS, OPT_MISSING_HELP, OPT_OBJECTS,
+    OPT_PROV_ENUM
 } HELPLIST_CHOICE;
 
 const OPTIONS list_options[] = {
@@ -655,6 +656,8 @@ const OPTIONS list_options[] = {
      "List options for specified command"},
     {"objects", OPT_OBJECTS, '-',
      "List built in objects (OID<->name mappings)"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -741,6 +744,10 @@ opthelp:
         case OPT_VERBOSE:
             verbose = 1;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                return 1;
+            break;
         }
         done = 1;
     }
diff --git a/apps/mac.c b/apps/mac.c
index 6abcfcd4e8..bc236a7bf8 100644
--- a/apps/mac.c
+++ b/apps/mac.c
@@ -21,7 +21,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT
+    OPT_MACOPT, OPT_BIN, OPT_IN, OPT_OUT,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS mac_options[] = {
@@ -40,6 +41,8 @@ const OPTIONS mac_options[] = {
     {"binary", OPT_BIN, '-',
         "Output in binary format (default is hexadecimal)"},
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"mac_name", 0, 0, "MAC algorithm"},
     {NULL}
@@ -89,6 +92,10 @@ opthelp:
             if (opts == NULL || !sk_OPENSSL_STRING_push(opts, opt_arg()))
                 goto opthelp;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto err;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/nseq.c b/apps/nseq.c
index 9d1e0950e8..e9aeea98a0 100644
--- a/apps/nseq.c
+++ b/apps/nseq.c
@@ -16,7 +16,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_TOSEQ, OPT_IN, OPT_OUT
+    OPT_TOSEQ, OPT_IN, OPT_OUT,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS nseq_options[] = {
@@ -29,6 +30,8 @@ const OPTIONS nseq_options[] = {
     OPT_SECTION("Output"),
     {"toseq", OPT_TOSEQ, '-', "Output NS Sequence file"},
     {"out", OPT_OUT, '>', "Output file"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -62,6 +65,10 @@ int nseq_main(int argc, char **argv)
         case OPT_OUT:
             outfile = opt_arg();
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/ocsp.c b/apps/ocsp.c
index 3297b4287a..3c6b8cbd88 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -137,7 +137,7 @@ typedef enum OPTION_choice {
     OPT_RCID,
     OPT_V_ENUM,
     OPT_MD,
-    OPT_MULTI
+    OPT_MULTI, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ocsp_options[] = {
@@ -230,6 +230,7 @@ const OPTIONS ocsp_options[] = {
     {"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
 
     OPT_V_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -541,6 +542,10 @@ int ocsp_main(int argc, char **argv)
             multi = atoi(opt_arg());
 # endif
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     if (trailing_md) {
diff --git a/apps/passwd.c b/apps/passwd.c
index 4626eeb249..f3faa58536 100644
--- a/apps/passwd.c
+++ b/apps/passwd.c
@@ -58,7 +58,7 @@ typedef enum OPTION_choice {
     OPT_IN,
     OPT_NOVERIFY, OPT_QUIET, OPT_TABLE, OPT_REVERSE, OPT_APR1,
     OPT_1, OPT_5, OPT_6, OPT_CRYPT, OPT_AIXMD5, OPT_SALT, OPT_STDIN,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS passwd_options[] = {
@@ -90,6 +90,7 @@ const OPTIONS passwd_options[] = {
 #endif
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"password", 0, 0, "Password text to digest (optional)"},
@@ -191,6 +192,10 @@ int passwd_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkcs12.c b/apps/pkcs12.c
index 091318b67d..c2448a74f5 100644
--- a/apps/pkcs12.c
+++ b/apps/pkcs12.c
@@ -58,7 +58,7 @@ typedef enum OPTION_choice {
     OPT_INKEY, OPT_CERTFILE, 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_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs12_options[] = {
@@ -130,6 +130,7 @@ const OPTIONS pkcs12_options[] = {
     {"", OPT_CIPHER, '-', "Any supported cipher"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -307,6 +308,10 @@ int pkcs12_main(int argc, char **argv)
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index bd1cb1013c..9c74d99aca 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -23,7 +23,8 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_NOOUT,
-    OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE
+    OPT_TEXT, OPT_PRINT, OPT_PRINT_CERTS, OPT_ENGINE,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs7_options[] = {
@@ -45,6 +46,8 @@ const OPTIONS pkcs7_options[] = {
     {"print", OPT_PRINT, '-', "Print out all fields of the PKCS7 structure"},
     {"print_certs", OPT_PRINT_CERTS, '-',
      "Print_certs  print any certs or crl in the input"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -99,6 +102,10 @@ int pkcs7_main(int argc, char **argv)
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkcs8.c b/apps/pkcs8.c
index 1ccaff06f8..b058ea1980 100644
--- a/apps/pkcs8.c
+++ b/apps/pkcs8.c
@@ -26,7 +26,7 @@ typedef enum OPTION_choice {
 #endif
     OPT_V2, OPT_V1, OPT_V2PRF, OPT_ITER, OPT_PASSIN, OPT_PASSOUT,
     OPT_TRADITIONAL,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkcs8_options[] = {
@@ -63,6 +63,7 @@ const OPTIONS pkcs8_options[] = {
 #endif
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -127,6 +128,10 @@ int pkcs8_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_TRADITIONAL:
             traditional = 1;
             break;
diff --git a/apps/pkey.c b/apps/pkey.c
index 54709f656e..e90b3a5960 100644
--- a/apps/pkey.c
+++ b/apps/pkey.c
@@ -37,7 +37,8 @@ typedef enum OPTION_choice {
     OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE,
     OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB,
     OPT_TEXT, OPT_NOOUT, OPT_MD, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK,
-    OPT_EC_PARAM_ENC, OPT_EC_CONV_FORM
+    OPT_EC_PARAM_ENC, OPT_EC_CONV_FORM,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkey_options[] = {
@@ -72,6 +73,7 @@ const OPTIONS pkey_options[] = {
     {"text", OPT_TEXT, '-', "Output in plaintext as well"},
     {"noout", OPT_NOOUT, '-', "Don't output the key"},
 
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -177,6 +179,10 @@ int pkey_main(int argc, char **argv)
             ec_asn1_flag = i;
             break;
 #endif
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c
index 5521909d99..441523ddc4 100644
--- a/apps/pkeyparam.c
+++ b/apps/pkeyparam.c
@@ -19,7 +19,8 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_IN, OPT_OUT, OPT_TEXT, OPT_NOOUT,
-    OPT_ENGINE, OPT_CHECK
+    OPT_ENGINE, OPT_CHECK,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS pkeyparam_options[] = {
@@ -37,6 +38,8 @@ const OPTIONS pkeyparam_options[] = {
     {"out", OPT_OUT, '>', "Output file"},
     {"text", OPT_TEXT, '-', "Print parameters as text"},
     {"noout", OPT_NOOUT, '-', "Don't output encoded parameters"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -81,6 +84,10 @@ int pkeyparam_main(int argc, char **argv)
         case OPT_CHECK:
             check = 1;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c
index 5bc436576d..7f11b168f5 100644
--- a/apps/pkeyutl.c
+++ b/apps/pkeyutl.c
@@ -44,7 +44,7 @@ typedef enum OPTION_choice {
     OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
     OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN,
     OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_PKEYOPT_PASSIN, OPT_KDF,
-    OPT_KDFLEN, OPT_R_ENUM,
+    OPT_KDFLEN, OPT_R_ENUM, OPT_PROV_ENUM,
     OPT_RAWIN, OPT_DIGEST
 } OPTION_CHOICE;
 
@@ -92,6 +92,7 @@ const OPTIONS pkeyutl_options[] = {
     {"kdflen", OPT_KDFLEN, 'p', "KDF algorithm output length"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -165,6 +166,10 @@ int pkeyutl_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
diff --git a/apps/prime.c b/apps/prime.c
index 5345e5b6d0..ff25f9085b 100644
--- a/apps/prime.c
+++ b/apps/prime.c
@@ -15,7 +15,8 @@
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS
+    OPT_HEX, OPT_GENERATE, OPT_BITS, OPT_SAFE, OPT_CHECKS,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS prime_options[] = {
@@ -32,6 +33,8 @@ const OPTIONS prime_options[] = {
     {"safe", OPT_SAFE, '-',
      "When used with -generate, generate a safe prime"},
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"number", 0, 0, "Number(s) to check for primality if not generating"},
     {NULL}
@@ -72,6 +75,10 @@ opthelp:
             /* ignore parameter and argument */
             opt_arg();
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/rand.c b/apps/rand.c
index 421ebfc203..7dc14cb3b2 100644
--- a/apps/rand.c
+++ b/apps/rand.c
@@ -21,7 +21,7 @@
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_OUT, OPT_ENGINE, OPT_BASE64, OPT_HEX,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rand_options[] = {
@@ -39,6 +39,7 @@ const OPTIONS rand_options[] = {
     {"hex", OPT_HEX, '-', "Hex encode output"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"num", 0, 0, "Number of bytes to generate"},
@@ -81,6 +82,10 @@ int rand_main(int argc, char **argv)
         case OPT_HEX:
             format = FORMAT_TEXT;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/rehash.c b/apps/rehash.c
index b7e6e7ec18..de54064244 100644
--- a/apps/rehash.c
+++ b/apps/rehash.c
@@ -447,7 +447,8 @@ static int do_dir(const char *dirname, enum Hash h)
 
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
-    OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE
+    OPT_COMPAT, OPT_OLD, OPT_N, OPT_VERBOSE,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rehash_options[] = {
@@ -463,6 +464,8 @@ const OPTIONS rehash_options[] = {
     OPT_SECTION("Output"),
     {"v", OPT_VERBOSE, '-', "Verbose output"},
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"directory", 0, 0, "One or more directories to process (optional)"},
     {NULL}
@@ -499,6 +502,10 @@ int rehash_main(int argc, char **argv)
         case OPT_VERBOSE:
             verbose = 1;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/req.c b/apps/req.c
index 7140705f09..dcad9dc238 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -91,7 +91,7 @@ typedef enum OPTION_choice {
     OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509,
     OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS,
     OPT_REQEXTS, OPT_PRECERT, OPT_MD, OPT_SM2ID, OPT_SM2HEXID,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS req_options[] = {
@@ -160,6 +160,7 @@ const OPTIONS req_options[] = {
     {"modulus", OPT_MODULUS, '-', "RSA modulus"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -331,6 +332,10 @@ int req_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_NEWKEY:
             keyalg = opt_arg();
             newreq = 1;
diff --git a/apps/rsa.c b/apps/rsa.c
index 7d03a862a0..d626bbb31a 100644
--- a/apps/rsa.c
+++ b/apps/rsa.c
@@ -36,7 +36,8 @@ typedef enum OPTION_choice {
     OPT_RSAPUBKEY_IN, OPT_RSAPUBKEY_OUT,
     /* Do not change the order here; see case statements below */
     OPT_PVK_NONE, OPT_PVK_WEAK, OPT_PVK_STRONG,
-    OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER
+    OPT_NOOUT, OPT_TEXT, OPT_MODULUS, OPT_CHECK, OPT_CIPHER,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rsa_options[] = {
@@ -71,6 +72,8 @@ const OPTIONS rsa_options[] = {
     {"pvk-weak", OPT_PVK_WEAK, '-', "Enable 'Weak' PVK encoding level"},
     {"pvk-none", OPT_PVK_NONE, '-', "Don't enforce PVK encoding"},
 # endif
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -160,6 +163,10 @@ int rsa_main(int argc, char **argv)
             if (!opt_cipher(opt_unknown(), &enc))
                 goto opthelp;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/rsautl.c b/apps/rsautl.c
index 7bb9096bcd..b72f527ce4 100644
--- a/apps/rsautl.c
+++ b/apps/rsautl.c
@@ -37,7 +37,7 @@ typedef enum OPTION_choice {
     OPT_RSA_RAW, OPT_OAEP, OPT_SSL, OPT_PKCS, OPT_X931,
     OPT_SIGN, OPT_VERIFY, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT,
     OPT_PUBIN, OPT_CERTIN, OPT_INKEY, OPT_PASSIN, OPT_KEYFORM,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS rsautl_options[] = {
@@ -72,6 +72,7 @@ const OPTIONS rsautl_options[] = {
     {"hexdump", OPT_HEXDUMP, '-', "Hex dump output"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -169,6 +170,10 @@ int rsautl_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/s_client.c b/apps/s_client.c
index 7803785018..c06f2c824f 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -600,7 +600,7 @@ typedef enum OPTION_choice {
     OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
     OPT_ENABLE_PHA,
     OPT_SCTP_LABEL_BUG,
-    OPT_R_ENUM
+    OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS s_client_options[] = {
@@ -817,6 +817,7 @@ const OPTIONS s_client_options[] = {
     {"chainCAfile", OPT_CHAINCAFILE, '<',
      "CA file for certificate chain (PEM format)"},
     OPT_X_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"host:port", 0, 0, "Where to connect; same as -connect option"},
@@ -1225,6 +1226,10 @@ int s_client_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_IGN_EOF:
             c_ign_eof = 1;
             break;
diff --git a/apps/s_server.c b/apps/s_server.c
index 69d9e04876..4016270d54 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -757,7 +757,8 @@ typedef enum OPTION_choice {
     OPT_R_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
-    OPT_X_ENUM
+    OPT_X_ENUM,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS s_server_options[] = {
@@ -992,6 +993,7 @@ const OPTIONS s_server_options[] = {
     {"chainCAfile", OPT_CHAINCAFILE, '<',
      "CA file for certificate chain (PEM format)"},
     OPT_X_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -1566,6 +1568,10 @@ int s_server_main(int argc, char *argv[])
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_SERVERNAME:
             tlsextcbp.servername = opt_arg();
             break;
diff --git a/apps/s_time.c b/apps/s_time.c
index babbdbe13e..28e82f7cae 100644
--- a/apps/s_time.c
+++ b/apps/s_time.c
@@ -48,7 +48,8 @@ typedef enum OPTION_choice {
     OPT_CAPATH, OPT_CAFILE, OPT_CASTORE,
     OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
     OPT_NEW, OPT_REUSE, OPT_BUGS, OPT_VERIFY, OPT_TIME, OPT_SSL3,
-    OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3
+    OPT_WWW, OPT_TLS1, OPT_TLS1_1, OPT_TLS1_2, OPT_TLS1_3,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS s_time_options[] = {
@@ -99,6 +100,7 @@ const OPTIONS s_time_options[] = {
     {"no-CAstore", OPT_NOCASTORE, '-',
      "Do not load certificates from the default certificates store URI"},
 
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -226,6 +228,10 @@ int s_time_main(int argc, char **argv)
             min_version = TLS1_3_VERSION;
             max_version = TLS1_3_VERSION;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/smime.c b/apps/smime.c
index 149d3151ee..c7f74d4812 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -42,7 +42,7 @@ typedef enum OPTION_choice {
     OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
     OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
     OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
-    OPT_R_ENUM,
+    OPT_R_ENUM, OPT_PROV_ENUM,
     OPT_V_ENUM,
     OPT_IN, OPT_INFORM, OPT_OUT,
     OPT_OUTFORM, OPT_CONTENT
@@ -121,6 +121,7 @@ const OPTIONS smime_options[] = {
 
     OPT_R_OPTIONS,
     OPT_V_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"cert", 0, 0, "Recipient certs, used when encrypting"},
@@ -244,6 +245,10 @@ int smime_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
diff --git a/apps/speed.c b/apps/speed.c
index 13285d6355..9d4ab2c330 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -253,7 +253,7 @@ static int opt_found(const char *name, unsigned int *result,
 typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
-    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
+    OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM,
     OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
 } OPTION_CHOICE;
 
@@ -301,6 +301,7 @@ const OPTIONS speed_options[] = {
      "Use specified offset to mis-align buffers"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"algorithm", 0, 0, "Algorithm(s) to test (optional; otherwise tests all)"},
@@ -1706,6 +1707,10 @@ int speed_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_PRIMES:
 #ifndef OPENSSL_NO_DEPRECATED_3_0
             if (!opt_int(opt_arg(), &primes))
diff --git a/apps/spkac.c b/apps/spkac.c
index 75e246a110..dbd3d45216 100644
--- a/apps/spkac.c
+++ b/apps/spkac.c
@@ -24,7 +24,8 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_NOOUT, OPT_PUBKEY, OPT_VERIFY, OPT_IN, OPT_OUT,
     OPT_ENGINE, OPT_KEY, OPT_CHALLENGE, OPT_PASSIN, OPT_SPKAC,
-    OPT_SPKSECT, OPT_KEYFORM
+    OPT_SPKSECT, OPT_KEYFORM,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS spkac_options[] = {
@@ -49,6 +50,8 @@ const OPTIONS spkac_options[] = {
     {"noout", OPT_NOOUT, '-', "Don't print SPKAC"},
     {"pubkey", OPT_PUBKEY, '-', "Output public key"},
     {"verify", OPT_VERIFY, '-', "Verify SPKAC signature"},
+
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -116,6 +119,10 @@ int spkac_main(int argc, char **argv)
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/srp.c b/apps/srp.c
index e7a18d68cb..646e86f11a 100644
--- a/apps/srp.c
+++ b/apps/srp.c
@@ -193,7 +193,7 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_VERBOSE, OPT_CONFIG, OPT_NAME, OPT_SRPVFILE, OPT_ADD,
     OPT_DELETE, OPT_MODIFY, OPT_LIST, OPT_GN, OPT_USERINFO,
-    OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM
+    OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE, OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS srp_options[] = {
@@ -222,6 +222,7 @@ const OPTIONS srp_options[] = {
     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
 
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
 
     OPT_PARAMETERS(),
     {"user", 0, 0, "Username(s) to process (optional)"},
@@ -297,6 +298,10 @@ int srp_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/storeutl.c b/apps/storeutl.c
index 85fb1ed860..c03eb08f0b 100644
--- a/apps/storeutl.c
+++ b/apps/storeutl.c
@@ -27,7 +27,7 @@ typedef enum OPTION_choice {
     OPT_SEARCHFOR_CERTS, OPT_SEARCHFOR_KEYS, OPT_SEARCHFOR_CRLS,
     OPT_CRITERION_SUBJECT, OPT_CRITERION_ISSUER, OPT_CRITERION_SERIAL,
     OPT_CRITERION_FINGERPRINT, OPT_CRITERION_ALIAS,
-    OPT_MD
+    OPT_MD, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS storeutl_options[] = {
@@ -59,6 +59,8 @@ const OPTIONS storeutl_options[] = {
     {"text", OPT_TEXT, '-', "Print a text form of the objects"},
     {"noout", OPT_NOOUT, '-', "No PEM output, just status"},
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"uri", 0, 0, "URI of the store object"},
     {NULL}
@@ -250,6 +252,10 @@ int storeutl_main(int argc, char *argv[])
         case OPT_MD:
             if (!opt_md(opt_unknown(), &digest))
                 goto opthelp;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/ts.c b/apps/ts.c
index c651c8e5cd..3d380bebf0 100644
--- a/apps/ts.c
+++ b/apps/ts.c
@@ -86,7 +86,7 @@ typedef enum OPTION_choice {
     OPT_IN, OPT_TOKEN_IN, OPT_OUT, OPT_TOKEN_OUT, OPT_TEXT,
     OPT_REPLY, OPT_QUERYFILE, OPT_PASSIN, OPT_INKEY, OPT_SIGNER,
     OPT_CHAIN, OPT_VERIFY, OPT_CAPATH, OPT_CAFILE, OPT_CASTORE, OPT_UNTRUSTED,
-    OPT_MD, OPT_V_ENUM, OPT_R_ENUM
+    OPT_MD, OPT_V_ENUM, OPT_R_ENUM, OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS ts_options[] = {
@@ -127,6 +127,7 @@ const OPTIONS ts_options[] = {
 
     OPT_R_OPTIONS,
     OPT_V_OPTIONS,
+    OPT_PROV_OPTIONS,
     {NULL}
 };
 
@@ -219,6 +220,10 @@ int ts_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_TSPOLICY:
             policy = opt_arg();
             break;
diff --git a/apps/verify.c b/apps/verify.c
index 5c5042117d..82ca35e971 100644
--- a/apps/verify.c
+++ b/apps/verify.c
@@ -31,7 +31,8 @@ typedef enum OPTION_choice {
     OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE,
     OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN,
     OPT_V_ENUM, OPT_NAMEOPT,
-    OPT_VERBOSE, OPT_SM2ID, OPT_SM2HEXID
+    OPT_VERBOSE, OPT_SM2ID, OPT_SM2HEXID,
+    OPT_PROV_ENUM
 } OPTION_CHOICE;
 
 const OPTIONS verify_options[] = {
@@ -73,6 +74,8 @@ const OPTIONS verify_options[] = {
      "Specify a hex ID string to verify an SM2 certificate"},
 #endif
 
+    OPT_PROV_OPTIONS,
+
     OPT_PARAMETERS(),
     {"cert", 0, 0, "Certificate(s) to verify (optional; stdin used otherwise)"},
     {NULL}
@@ -209,6 +212,10 @@ int verify_main(int argc, char **argv)
                 goto end;
             }
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         }
     }
     argc = opt_num_rest();
diff --git a/apps/x509.c b/apps/x509.c
index a8ec118180..3176cf528c 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -61,7 +61,7 @@ typedef enum OPTION_choice {
     OPT_SUBJECT_HASH_OLD,
     OPT_ISSUER_HASH_OLD,
     OPT_BADSIG, OPT_MD, OPT_ENGINE, OPT_NOCERT, OPT_PRESERVE_DATES,
-    OPT_R_ENUM, OPT_EXT
+    OPT_R_ENUM, OPT_PROV_ENUM, OPT_EXT
 } OPTION_CHOICE;
 
 const OPTIONS x509_options[] = {
@@ -144,6 +144,7 @@ const OPTIONS x509_options[] = {
      "The CA key, must be PEM format; if not in CAfile"},
     {"extfile", OPT_EXTFILE, '<', "File with X509V3 extensions to add"},
     OPT_R_OPTIONS,
+    OPT_PROV_OPTIONS,
     {"CAform", OPT_CAFORM, 'F', "CA format - default PEM"},
     {"CAkeyform", OPT_CAKEYFORM, 'E', "CA key format - default PEM"},
     {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"},
@@ -270,6 +271,10 @@ int x509_main(int argc, char **argv)
             if (!opt_rand(o))
                 goto end;
             break;
+        case OPT_PROV_CASES:
+            if (!opt_provider(o))
+                goto end;
+            break;
         case OPT_EXTENSIONS:
             extsect = opt_arg();
             break;
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index cac325407f..026e784bae 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -10,6 +10,7 @@
 #include <openssl/core.h>
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
+#include <openssl/provider.h>
 #include <openssl/params.h>
 #include <openssl/opensslv.h>
 #include "crypto/cryptlib.h"
@@ -92,6 +93,7 @@ static int ossl_provider_cmp(const OSSL_PROVIDER * const *a,
 struct provider_store_st {
     STACK_OF(OSSL_PROVIDER) *providers;
     CRYPTO_RWLOCK *lock;
+    char *default_path;
     unsigned int use_fallbacks:1;
 };
 
@@ -101,6 +103,7 @@ static void provider_store_free(void *vstore)
 
     if (store == NULL)
         return;
+    OPENSSL_free(store->default_path);
     sk_OSSL_PROVIDER_pop_free(store->providers, ossl_provider_free);
     CRYPTO_THREAD_lock_free(store->lock);
     OPENSSL_free(store);
@@ -384,6 +387,29 @@ int ossl_provider_add_parameter(OSSL_PROVIDER *prov,
  */
 static const OSSL_DISPATCH *core_dispatch; /* Define further down */
 
+int OSSL_PROVIDER_set_default_search_path(OPENSSL_CTX *libctx, const char *path)
+{
+    struct provider_store_st *store;
+    char *p = NULL;
+
+    if (path != NULL) {
+        p = OPENSSL_strdup(path);
+        if (p == NULL) {
+            CRYPTOerr(0, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+    }
+    if ((store = get_provider_store(libctx)) != NULL
+            && CRYPTO_THREAD_write_lock(store->lock)) {
+        OPENSSL_free(store->default_path);
+        store->default_path = p;
+        CRYPTO_THREAD_unlock(store->lock);
+        return 1;
+    }
+    OPENSSL_free(p);
+    return 0;
+}
+
 /*
  * Internal version that doesn't affect the store flags, and thereby avoid
  * locking.  Direct callers must remember to set the store flags when
@@ -413,15 +439,24 @@ static int provider_activate(OSSL_PROVIDER *prov)
             char *allocated_path = NULL;
             const char *module_path = NULL;
             char *merged_path = NULL;
-            const char *load_dir = ossl_safe_getenv("OPENSSL_MODULES");
+            const char *load_dir = NULL;
+            struct provider_store_st *store;
 
             if ((prov->module = DSO_new()) == NULL) {
                 /* DSO_new() generates an error already */
                 return 0;
             }
 
-            if (load_dir == NULL)
-                load_dir = MODULESDIR;
+            if ((store = get_provider_store(prov->libctx)) == NULL
+                    || !CRYPTO_THREAD_read_lock(store->lock))
+                return 0;
+            load_dir = store->default_path;
+
+            if (load_dir == NULL) {
+                load_dir = ossl_safe_getenv("OPENSSL_MODULES");
+                if (load_dir == NULL)
+                    load_dir = MODULESDIR;
+            }
 
             DSO_ctrl(prov->module, DSO_CTRL_SET_FLAGS,
                      DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL);
@@ -432,6 +467,7 @@ static int provider_activate(OSSL_PROVIDER *prov)
                     DSO_convert_filename(prov->module, prov->name);
             if (module_path != NULL)
                 merged_path = DSO_merge(prov->module, module_path, load_dir);
+            CRYPTO_THREAD_unlock(store->lock);
 
             if (merged_path == NULL
                 || (DSO_load(prov->module, merged_path, NULL, 0)) == NULL) {
diff --git a/doc/man1/build.info b/doc/man1/build.info
index 13012d4432..c48ff0acbe 100644
--- a/doc/man1/build.info
+++ b/doc/man1/build.info
@@ -1,113 +1,163 @@
 
-# Keep this in sync with .gitignore!
 DEPEND[]= \
+         openssl-asn1parse.pod \
          openssl-ca.pod \
+         openssl-ciphers.pod \
+         openssl-cmds.pod \
          openssl-cms.pod \
+         openssl-crl2pkcs7.pod \
          openssl-crl.pod \
          openssl-dgst.pod \
          openssl-dhparam.pod \
-         openssl-dsa.pod \
          openssl-dsaparam.pod \
-         openssl-ec.pod \
+         openssl-dsa.pod \
          openssl-ecparam.pod \
+         openssl-ec.pod \
          openssl-enc.pod \
+         openssl-engine.pod \
+         openssl-errstr.pod \
+         openssl-fipsinstall.pod \
          openssl-gendsa.pod \
          openssl-genpkey.pod \
          openssl-genrsa.pod \
+         openssl-info.pod \
+         openssl-kdf.pod \
+         openssl-list.pod \
+         openssl-mac.pod \
+         openssl-nseq.pod \
          openssl-ocsp.pod \
          openssl-passwd.pod \
          openssl-pkcs12.pod \
          openssl-pkcs7.pod \
          openssl-pkcs8.pod \
-         openssl-pkey.pod \
          openssl-pkeyparam.pod \
+         openssl-pkey.pod \
          openssl-pkeyutl.pod \
+         openssl-prime.pod \
+         openssl-provider.pod \
          openssl-rand.pod \
+         openssl-rehash.pod \
          openssl-req.pod \
          openssl-rsa.pod \
          openssl-rsautl.pod \
          openssl-s_client.pod \
-         openssl-s_server.pod \
-         openssl-s_time.pod \
+         openssl-sess_id.pod \
          openssl-smime.pod \
          openssl-speed.pod \
          openssl-spkac.pod \
          openssl-srp.pod \
+         openssl-s_server.pod \
+         openssl-s_time.pod \
          openssl-storeutl.pod \
          openssl-ts.pod \
          openssl-verify.pod \
+         openssl-version.pod \
          openssl-x509.pod
 
+DEPEND[openssl-asn1parse.pod]=../perlvars.pm
 DEPEND[openssl-ca.pod]=../perlvars.pm
+DEPEND[openssl-ciphers.pod]=../perlvars.pm
+DEPEND[openssl-cmds.pod]=../perlvars.pm
 DEPEND[openssl-cms.pod]=../perlvars.pm
+DEPEND[openssl-crl2pkcs7.pod]=../perlvars.pm
 DEPEND[openssl-crl.pod]=../perlvars.pm
 DEPEND[openssl-dgst.pod]=../perlvars.pm
 DEPEND[openssl-dhparam.pod]=../perlvars.pm
-DEPEND[openssl-dsa.pod]=../perlvars.pm
 DEPEND[openssl-dsaparam.pod]=../perlvars.pm
-DEPEND[openssl-ec.pod]=../perlvars.pm
+DEPEND[openssl-dsa.pod]=../perlvars.pm
 DEPEND[openssl-ecparam.pod]=../perlvars.pm
+DEPEND[openssl-ec.pod]=../perlvars.pm
 DEPEND[openssl-enc.pod]=../perlvars.pm
+DEPEND[openssl-engine.pod]=../perlvars.pm
+DEPEND[openssl-errstr.pod]=../perlvars.pm
+DEPEND[openssl-fipsinstall.pod]=../perlvars.pm
 DEPEND[openssl-gendsa.pod]=../perlvars.pm
 DEPEND[openssl-genpkey.pod]=../perlvars.pm
 DEPEND[openssl-genrsa.pod]=../perlvars.pm
+DEPEND[openssl-info.pod]=../perlvars.pm
+DEPEND[openssl-kdf.pod]=../perlvars.pm
+DEPEND[openssl-list.pod]=../perlvars.pm
+DEPEND[openssl-mac.pod]=../perlvars.pm
+DEPEND[openssl-nseq.pod]=../perlvars.pm
 DEPEND[openssl-ocsp.pod]=../perlvars.pm
 DEPEND[openssl-passwd.pod]=../perlvars.pm
 DEPEND[openssl-pkcs12.pod]=../perlvars.pm
 DEPEND[openssl-pkcs7.pod]=../perlvars.pm
 DEPEND[openssl-pkcs8.pod]=../perlvars.pm
-DEPEND[openssl-pkey.pod]=../perlvars.pm
 DEPEND[openssl-pkeyparam.pod]=../perlvars.pm
+DEPEND[openssl-pkey.pod]=../perlvars.pm
 DEPEND[openssl-pkeyutl.pod]=../perlvars.pm
+DEPEND[openssl-prime.pod]=../perlvars.pm
+DEPEND[openssl-provider.pod]=../perlvars.pm
 DEPEND[openssl-rand.pod]=../perlvars.pm
+DEPEND[openssl-rehash.pod]=../perlvars.pm
 DEPEND[openssl-req.pod]=../perlvars.pm
 DEPEND[openssl-rsa.pod]=../perlvars.pm
 DEPEND[openssl-rsautl.pod]=../perlvars.pm
 DEPEND[openssl-s_client.pod]=../perlvars.pm
-DEPEND[openssl-s_server.pod]=../perlvars.pm
-DEPEND[openssl-s_time.pod]=../perlvars.pm
+DEPEND[openssl-sess_id.pod]=../perlvars.pm
 DEPEND[openssl-smime.pod]=../perlvars.pm
 DEPEND[openssl-speed.pod]=../perlvars.pm
 DEPEND[openssl-spkac.pod]=../perlvars.pm
 DEPEND[openssl-srp.pod]=../perlvars.pm
+DEPEND[openssl-s_server.pod]=../perlvars.pm
+DEPEND[openssl-s_time.pod]=../perlvars.pm
 DEPEND[openssl-storeutl.pod]=../perlvars.pm
 DEPEND[openssl-ts.pod]=../perlvars.pm
 DEPEND[openssl-verify.pod]=../perlvars.pm
+DEPEND[openssl-version.pod]=../perlvars.pm
 DEPEND[openssl-x509.pod]=../perlvars.pm
 
+GENERATE[openssl-asn1parse.pod]=openssl-asn1parse.pod.in
 GENERATE[openssl-ca.pod]=openssl-ca.pod.in
+GENERATE[openssl-ciphers.pod]=openssl-ciphers.pod.in
+GENERATE[openssl-cmds.pod]=openssl-cmds.pod.in
 GENERATE[openssl-cms.pod]=openssl-cms.pod.in
+GENERATE[openssl-crl2pkcs7.pod]=openssl-crl2pkcs7.pod.in
 GENERATE[openssl-crl.pod]=openssl-crl.pod.in
 GENERATE[openssl-dgst.pod]=openssl-dgst.pod.in
 GENERATE[openssl-dhparam.pod]=openssl-dhparam.pod.in
-GENERATE[openssl-dsa.pod]=openssl-dsa.pod.in
 GENERATE[openssl-dsaparam.pod]=openssl-dsaparam.pod.in
-GENERATE[openssl-ec.pod]=openssl-ec.pod.in
+GENERATE[openssl-dsa.pod]=openssl-dsa.pod.in
 GENERATE[openssl-ecparam.pod]=openssl-ecparam.pod.in
+GENERATE[openssl-ec.pod]=openssl-ec.pod.in
 GENERATE[openssl-enc.pod]=openssl-enc.pod.in
+GENERATE[openssl-engine.pod]=openssl-engine.pod.in
+GENERATE[openssl-errstr.pod]=openssl-errstr.pod.in
+GENERATE[openssl-fipsinstall.pod]=openssl-fipsinstall.pod.in
 GENERATE[openssl-gendsa.pod]=openssl-gendsa.pod.in
 GENERATE[openssl-genpkey.pod]=openssl-genpkey.pod.in
 GENERATE[openssl-genrsa.pod]=openssl-genrsa.pod.in
+GENERATE[openssl-info.pod]=openssl-info.pod.in
+GENERATE[openssl-kdf.pod]=openssl-kdf.pod.in
+GENERATE[openssl-list.pod]=openssl-list.pod.in
+GENERATE[openssl-mac.pod]=openssl-mac.pod.in
+GENERATE[openssl-nseq.pod]=openssl-nseq.pod.in
 GENERATE[openssl-ocsp.pod]=openssl-ocsp.pod.in
 GENERATE[openssl-passwd.pod]=openssl-passwd.pod.in
 GENERATE[openssl-pkcs12.pod]=openssl-pkcs12.pod.in
 GENERATE[openssl-pkcs7.pod]=openssl-pkcs7.pod.in
 GENERATE[openssl-pkcs8.pod]=openssl-pkcs8.pod.in
-GENERATE[openssl-pkey.pod]=openssl-pkey.pod.in
 GENERATE[openssl-pkeyparam.pod]=openssl-pkeyparam.pod.in
+GENERATE[openssl-pkey.pod]=openssl-pkey.pod.in
 GENERATE[openssl-pkeyutl.pod]=openssl-pkeyutl.pod.in
+GENERATE[openssl-prime.pod]=openssl-prime.pod.in
+GENERATE[openssl-provider.pod]=openssl-provider.pod.in
 GENERATE[openssl-rand.pod]=openssl-rand.pod.in
+GENERATE[openssl-rehash.pod]=openssl-rehash.pod.in
 GENERATE[openssl-req.pod]=openssl-req.pod.in
 GENERATE[openssl-rsa.pod]=openssl-rsa.pod.in
 GENERATE[openssl-rsautl.pod]=openssl-rsautl.pod.in
 GENERATE[openssl-s_client.pod]=openssl-s_client.pod.in
-GENERATE[openssl-s_server.pod]=openssl-s_server.pod.in
-GENERATE[openssl-s_time.pod]=openssl-s_time.pod.in
+GENERATE[openssl-sess_id.pod]=openssl-sess_id.pod.in
 GENERATE[openssl-smime.pod]=openssl-smime.pod.in
 GENERATE[openssl-speed.pod]=openssl-speed.pod.in
 GENERATE[openssl-spkac.pod]=openssl-spkac.pod.in
 GENERATE[openssl-srp.pod]=openssl-srp.pod.in
+GENERATE[openssl-s_server.pod]=openssl-s_server.pod.in
+GENERATE[openssl-s_time.pod]=openssl-s_time.pod.in
 GENERATE[openssl-storeutl.pod]=openssl-storeutl.pod.in
 GENERATE[openssl-ts.pod]=openssl-ts.pod.in
 GENERATE[openssl-verify.pod]=openssl-verify.pod.in
+GENERATE[openssl-version.pod]=openssl-version.pod.in
 GENERATE[openssl-x509.pod]=openssl-x509.pod.in
diff --git a/doc/man1/openssl-asn1parse.pod b/doc/man1/openssl-asn1parse.pod.in
similarity index 99%
rename from doc/man1/openssl-asn1parse.pod
rename to doc/man1/openssl-asn1parse.pod.in
index 698ce47897..9b95966440 100644
--- a/doc/man1/openssl-asn1parse.pod
+++ b/doc/man1/openssl-asn1parse.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-ca.pod.in b/doc/man1/openssl-ca.pod.in
index 720db228cb..8eef310ca4 100644
--- a/doc/man1/openssl-ca.pod.in
+++ b/doc/man1/openssl-ca.pod.in
@@ -59,6 +59,7 @@ B<openssl> B<ca>
 [B<-sm2-hex-id> I<hex-string>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<certreq>...]
 
 =for openssl ifdef engine sm2-id sm2-hex-id
@@ -308,6 +309,8 @@ certificate. The argument for this option is string of hexadecimal digits.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 CRL OPTIONS
diff --git a/doc/man1/openssl-ciphers.pod b/doc/man1/openssl-ciphers.pod.in
similarity index 99%
rename from doc/man1/openssl-ciphers.pod
rename to doc/man1/openssl-ciphers.pod.in
index 8ba80ba15d..6e6b150d24 100644
--- a/doc/man1/openssl-ciphers.pod
+++ b/doc/man1/openssl-ciphers.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -22,6 +23,7 @@ B<openssl> B<ciphers>
 [B<-stdname>]
 [B<-convert> I<name>]
 [B<-ciphersuites> I<val>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<cipherlist>]
 
 =for openssl ifdef ssl3 tls1 tls1_1 tls1_2 tls1_3 psk srp
@@ -40,6 +42,8 @@ determine the appropriate cipherlist.
 
 Print a usage message.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item B<-s>
 
 Only list supported ciphers: those consistent with the security level, and
diff --git a/doc/man1/openssl-cmds.pod b/doc/man1/openssl-cmds.pod.in
similarity index 98%
rename from doc/man1/openssl-cmds.pod
rename to doc/man1/openssl-cmds.pod.in
index d44d40cfec..50f0bc66e4 100644
--- a/doc/man1/openssl-cmds.pod
+++ b/doc/man1/openssl-cmds.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in
index 161408fdcb..944135bbed 100644
--- a/doc/man1/openssl-cms.pod.in
+++ b/doc/man1/openssl-cms.pod.in
@@ -81,6 +81,7 @@ B<openssl> B<cms>
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<cert.pem> ...]
 
 =for openssl ifdef des-wrap engine
@@ -490,6 +491,8 @@ Any verification errors cause the command to exit.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<cert.pem> ...
 
 One or more certificates of message recipients: used when encrypting
diff --git a/doc/man1/openssl-crl.pod.in b/doc/man1/openssl-crl.pod.in
index c1272c2580..c1bd31a4a2 100644
--- a/doc/man1/openssl-crl.pod.in
+++ b/doc/man1/openssl-crl.pod.in
@@ -29,6 +29,7 @@ B<openssl> B<crl>
 [B<-nextupdate>]
 {- $OpenSSL::safe::opt_name_synopsis -}
 {- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef hash_old
 
@@ -123,6 +124,8 @@ Output the nextUpdate field.
 
 {- $OpenSSL::safe::opt_trust_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-crl2pkcs7.pod b/doc/man1/openssl-crl2pkcs7.pod.in
similarity index 95%
rename from doc/man1/openssl-crl2pkcs7.pod
rename to doc/man1/openssl-crl2pkcs7.pod.in
index 70662d4e0f..ee7f57d7a4 100644
--- a/doc/man1/openssl-crl2pkcs7.pod
+++ b/doc/man1/openssl-crl2pkcs7.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -14,6 +15,7 @@ B<openssl> B<crl2pkcs7>
 [B<-out> I<filename>]
 [B<-certfile> I<filename>]
 [B<-nocrl>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =head1 DESCRIPTION
 
@@ -61,6 +63,8 @@ files.
 Normally a CRL is included in the output file. With this option no CRL is
 included in the output file and a CRL is not read from the input file.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-dgst.pod.in b/doc/man1/openssl-dgst.pod.in
index caa5b0a45a..fad5b93fe3 100644
--- a/doc/man1/openssl-dgst.pod.in
+++ b/doc/man1/openssl-dgst.pod.in
@@ -32,6 +32,7 @@ B<openssl> B<dgst>|I<digest>
 {- $OpenSSL::safe::opt_engine_synopsis -}
 [B<-engine_impl> I<id>]
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<file> ...]
 
 =head1 DESCRIPTION
@@ -184,6 +185,8 @@ used or it is configured to do so, see L<config(5)/Engine Configuration Module>.
 When used with the B<-engine> option, it specifies to also use
 engine I<id> for digest operations.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<file> ...
 
 File or files to digest. If no files are specified then standard input is
diff --git a/doc/man1/openssl-dhparam.pod.in b/doc/man1/openssl-dhparam.pod.in
index 906af1c25c..2e45b248cf 100644
--- a/doc/man1/openssl-dhparam.pod.in
+++ b/doc/man1/openssl-dhparam.pod.in
@@ -23,6 +23,7 @@ B<openssl dhparam>
 [B<-5>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<numbits>]
 
 =for openssl ifdef dsaparam engine
@@ -109,6 +110,8 @@ be loaded by calling the get_dhNNNN() function.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-dsa.pod.in b/doc/man1/openssl-dsa.pod.in
index 03fcb7d09b..ef05e978f1 100644
--- a/doc/man1/openssl-dsa.pod.in
+++ b/doc/man1/openssl-dsa.pod.in
@@ -37,6 +37,7 @@ B<openssl> B<dsa>
 [B<-pubin>]
 [B<-pubout>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef pvk-string pvk-weak pvk-none engine
 
@@ -123,6 +124,8 @@ a public key.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-dsaparam.pod.in b/doc/man1/openssl-dsaparam.pod.in
index 51d44bd9ac..13e8d78857 100644
--- a/doc/man1/openssl-dsaparam.pod.in
+++ b/doc/man1/openssl-dsaparam.pod.in
@@ -20,6 +20,7 @@ B<openssl dsaparam>
 [B<-verbose>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<numbits>]
 
 =head1 DESCRIPTION
@@ -93,6 +94,8 @@ This option specifies that a parameter set should be generated of size
 I<numbits>. It must be the last option. If this option is included then
 the input file (if any) is ignored.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 SEE ALSO
diff --git a/doc/man1/openssl-ec.pod.in b/doc/man1/openssl-ec.pod.in
index ed85ca04b8..f493a5373a 100644
--- a/doc/man1/openssl-ec.pod.in
+++ b/doc/man1/openssl-ec.pod.in
@@ -32,6 +32,7 @@ B<openssl> B<ec>
 [B<-no_public>]
 [B<-check>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -141,6 +142,8 @@ This option checks the consistency of an EC private or public key.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-ecparam.pod.in b/doc/man1/openssl-ecparam.pod.in
index 934bf5a380..a42fa35ee4 100644
--- a/doc/man1/openssl-ecparam.pod.in
+++ b/doc/man1/openssl-ecparam.pod.in
@@ -26,6 +26,7 @@ B<openssl ecparam>
 [B<-genkey>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -130,6 +131,8 @@ This option will generate an EC private key using the specified parameters.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-enc.pod.in b/doc/man1/openssl-enc.pod.in
index 6b8ab2a265..a2cb11a6b9 100644
--- a/doc/man1/openssl-enc.pod.in
+++ b/doc/man1/openssl-enc.pod.in
@@ -40,6 +40,7 @@ B<openssl> B<enc>|I<cipher>
 [B<-none>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef z engine ciphers
 
@@ -197,6 +198,8 @@ Use NULL cipher (no encryption or decryption of input).
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 {- $OpenSSL::safe::opt_engine_item -}
 
 =back
diff --git a/doc/man1/openssl-engine.pod b/doc/man1/openssl-engine.pod.in
similarity index 98%
rename from doc/man1/openssl-engine.pod
rename to doc/man1/openssl-engine.pod.in
index 7110ceecbc..c4b0665376 100644
--- a/doc/man1/openssl-engine.pod
+++ b/doc/man1/openssl-engine.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-errstr.pod b/doc/man1/openssl-errstr.pod.in
similarity index 95%
rename from doc/man1/openssl-errstr.pod
rename to doc/man1/openssl-errstr.pod.in
index ea838d9eb2..3a4e5163f9 100644
--- a/doc/man1/openssl-errstr.pod
+++ b/doc/man1/openssl-errstr.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-fipsinstall.pod b/doc/man1/openssl-fipsinstall.pod.in
similarity index 98%
rename from doc/man1/openssl-fipsinstall.pod
rename to doc/man1/openssl-fipsinstall.pod.in
index 9c7c856b0d..6ea3fca4d9 100644
--- a/doc/man1/openssl-fipsinstall.pod
+++ b/doc/man1/openssl-fipsinstall.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-gendsa.pod.in b/doc/man1/openssl-gendsa.pod.in
index f1f8fe5b91..88fc6118a2 100644
--- a/doc/man1/openssl-gendsa.pod.in
+++ b/doc/man1/openssl-gendsa.pod.in
@@ -26,6 +26,7 @@ B<openssl> B<gendsa>
 [B<-verbose>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<paramfile>]
 
 =for openssl ifdef engine
@@ -76,6 +77,8 @@ The DSA parameter file to use. The parameters in this file determine
 the size of the private key. DSA parameters can be generated and
 examined using the L<openssl-dsaparam(1)> command.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-genpkey.pod.in b/doc/man1/openssl-genpkey.pod.in
index c031f238af..4f1128a049 100644
--- a/doc/man1/openssl-genpkey.pod.in
+++ b/doc/man1/openssl-genpkey.pod.in
@@ -23,6 +23,7 @@ B<openssl> B<genpkey>
 [B<-genparam>]
 [B<-text>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -104,6 +105,8 @@ parameters along with the PEM or DER structure.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 KEY GENERATION OPTIONS
diff --git a/doc/man1/openssl-genrsa.pod.in b/doc/man1/openssl-genrsa.pod.in
index 348f8cbbc6..a351a53cdb 100644
--- a/doc/man1/openssl-genrsa.pod.in
+++ b/doc/man1/openssl-genrsa.pod.in
@@ -30,6 +30,7 @@ B<openssl> B<genrsa>
 [B<-verbose>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [B<numbits>]
 
 =for openssl ifdef engine
@@ -85,6 +86,8 @@ Print extra details about the operations being performed.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item B<numbits>
 
 The size of the private key to generate in bits. This must be the last option
diff --git a/doc/man1/openssl-info.pod b/doc/man1/openssl-info.pod.in
similarity index 97%
rename from doc/man1/openssl-info.pod
rename to doc/man1/openssl-info.pod.in
index 6e16bb809f..c8965b2ab6 100644
--- a/doc/man1/openssl-info.pod
+++ b/doc/man1/openssl-info.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-kdf.pod b/doc/man1/openssl-kdf.pod.in
similarity index 97%
rename from doc/man1/openssl-kdf.pod
rename to doc/man1/openssl-kdf.pod.in
index d89f84fd43..d7d8732c80 100644
--- a/doc/man1/openssl-kdf.pod
+++ b/doc/man1/openssl-kdf.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -12,6 +13,7 @@ B<openssl kdf>
 [B<-keylen> I<num>]
 [B<-out> I<filename>]
 [B<-binary>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 I<kdf_name>
 
 =head1 DESCRIPTION
@@ -79,6 +81,8 @@ To see the list of supported digests, use the command I<list -digest-commands>.
 
 =back
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<kdf_name>
 
 Specifies the name of a supported KDF algorithm which will be used.
diff --git a/doc/man1/openssl-list.pod b/doc/man1/openssl-list.pod.in
similarity index 96%
rename from doc/man1/openssl-list.pod
rename to doc/man1/openssl-list.pod.in
index 88bcc751e6..4ac7b5dce3 100644
--- a/doc/man1/openssl-list.pod
+++ b/doc/man1/openssl-list.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -23,6 +24,7 @@ B<openssl list>
 [B<-disabled>]
 [B<-objects>]
 [B<-options> I<command>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =head1 DESCRIPTION
 
@@ -102,6 +104,8 @@ of what type of parameter it takes, if any.
 This is an internal option, used for checking that the documentation
 is complete.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head2 Display of algorithm names
diff --git a/doc/man1/openssl-mac.pod b/doc/man1/openssl-mac.pod.in
similarity index 96%
rename from doc/man1/openssl-mac.pod
rename to doc/man1/openssl-mac.pod.in
index e5ec76395e..3090149032 100644
--- a/doc/man1/openssl-mac.pod
+++ b/doc/man1/openssl-mac.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -12,6 +13,7 @@ B<openssl mac>
 [B<-in> I<filename>]
 [B<-out> I<filename>]
 [B<-binary>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 I<mac_name>
 
 =head1 DESCRIPTION
@@ -99,6 +101,8 @@ The default is the empty string "".
 
 =back
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<mac_name>
 
 Specifies the name of a supported MAC algorithm which will be used.
diff --git a/doc/man1/openssl-nseq.pod b/doc/man1/openssl-nseq.pod.in
similarity index 92%
rename from doc/man1/openssl-nseq.pod
rename to doc/man1/openssl-nseq.pod.in
index 5404e1f340..02db15323e 100644
--- a/doc/man1/openssl-nseq.pod
+++ b/doc/man1/openssl-nseq.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -11,6 +12,7 @@ B<openssl> B<nseq>
 [B<-in> I<filename>]
 [B<-out> I<filename>]
 [B<-toseq>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =head1 DESCRIPTION
 
@@ -48,6 +50,8 @@ is the certificates contained in it. With the B<-toseq> option the
 situation is reversed: a Netscape certificate sequence is created from
 a file of certificates.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-ocsp.pod.in b/doc/man1/openssl-ocsp.pod.in
index 6b4c25cda9..efa627b8a9 100644
--- a/doc/man1/openssl-ocsp.pod.in
+++ b/doc/man1/openssl-ocsp.pod.in
@@ -70,6 +70,7 @@ B<openssl> B<ocsp>
 [B<-I<digest>>]
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef multi
 
@@ -269,6 +270,8 @@ digest used by subsequent certificate identifiers.
 
 {- $OpenSSL::safe::opt_v_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head2 OCSP Server Options
diff --git a/doc/man1/openssl-passwd.pod.in b/doc/man1/openssl-passwd.pod.in
index 83ef7ba674..ce2b69134c 100644
--- a/doc/man1/openssl-passwd.pod.in
+++ b/doc/man1/openssl-passwd.pod.in
@@ -23,6 +23,7 @@ B<openssl passwd>
 [B<-table>]
 [B<-reverse>]
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<password>]
 
 =for openssl ifdef crypt
@@ -100,6 +101,8 @@ When the B<-table> option is used, reverse the order of cleartext and hash.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in
index 7d562b002e..631eec7282 100644
--- a/doc/man1/openssl-pkcs12.pod.in
+++ b/doc/man1/openssl-pkcs12.pod.in
@@ -57,6 +57,7 @@ B<openssl> B<pkcs12>
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -293,6 +294,8 @@ Write I<name> as a Microsoft CSP name.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-pkcs7.pod.in b/doc/man1/openssl-pkcs7.pod.in
index 77ef9f9558..0a12d2379a 100644
--- a/doc/man1/openssl-pkcs7.pod.in
+++ b/doc/man1/openssl-pkcs7.pod.in
@@ -22,6 +22,7 @@ B<openssl> B<pkcs7>
 [B<-text>]
 [B<-noout>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -77,6 +78,8 @@ if B<-print_certs> is set).
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-pkcs8.pod.in b/doc/man1/openssl-pkcs8.pod.in
index 34b469ddbc..f9e5fb1dcb 100644
--- a/doc/man1/openssl-pkcs8.pod.in
+++ b/doc/man1/openssl-pkcs8.pod.in
@@ -29,6 +29,7 @@ B<openssl> B<pkcs8>
 [B<-scrypt_p> I<p>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine scrypt scrypt_N scrypt_r scrypt_p
 
@@ -150,6 +151,8 @@ Sets the scrypt I<N>, I<r> or I<p> parameters.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-pkey.pod.in b/doc/man1/openssl-pkey.pod.in
index 31bf005f74..8460aed1fa 100644
--- a/doc/man1/openssl-pkey.pod.in
+++ b/doc/man1/openssl-pkey.pod.in
@@ -31,6 +31,7 @@ B<openssl> B<pkey>
 [B<-ec_conv_form> I<arg>]
 [B<-ec_param_enc> I<arg>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -142,6 +143,8 @@ is currently not implemented in OpenSSL.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-pkeyparam.pod.in b/doc/man1/openssl-pkeyparam.pod.in
index 4488119121..7f9d351ac2 100644
--- a/doc/man1/openssl-pkeyparam.pod.in
+++ b/doc/man1/openssl-pkeyparam.pod.in
@@ -19,6 +19,7 @@ B<openssl> B<pkeyparam>
 [B<-noout>]
 [B<-check>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -59,6 +60,8 @@ This option checks the correctness of parameters.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-pkeyutl.pod.in b/doc/man1/openssl-pkeyutl.pod.in
index c239a0469a..0bca483871 100644
--- a/doc/man1/openssl-pkeyutl.pod.in
+++ b/doc/man1/openssl-pkeyutl.pod.in
@@ -37,6 +37,7 @@ B<openssl> B<pkeyutl>
 {- $OpenSSL::safe::opt_engine_synopsis -}
 [B<-engine_impl>]
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine engine_impl
 
@@ -188,6 +189,8 @@ engine I<id> for crypto operations.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-prime.pod b/doc/man1/openssl-prime.pod.in
similarity index 89%
rename from doc/man1/openssl-prime.pod
rename to doc/man1/openssl-prime.pod.in
index aa9af22102..3aee9014a0 100644
--- a/doc/man1/openssl-prime.pod
+++ b/doc/man1/openssl-prime.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
@@ -12,6 +13,7 @@ B<openssl prime>
 [B<-generate>]
 [B<-bits> I<num>]
 [B<-safe>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [B<-checks> I<num>]
 [I<number> ...]
 
@@ -48,6 +50,8 @@ Generate a prime with I<num> bits.
 When used with B<-generate>, generates a "safe" prime. If the number
 generated is I<n>, then check that C<(I<n>-1)/2> is also prime.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item B<-checks> I<num>
 
 This parameter is ignored.
diff --git a/doc/man1/openssl-provider.pod b/doc/man1/openssl-provider.pod.in
similarity index 95%
rename from doc/man1/openssl-provider.pod
rename to doc/man1/openssl-provider.pod.in
index b29d2f5a26..774f92b9ac 100644
--- a/doc/man1/openssl-provider.pod
+++ b/doc/man1/openssl-provider.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-rand.pod.in b/doc/man1/openssl-rand.pod.in
index 5e76b228ab..8a6c8933a9 100644
--- a/doc/man1/openssl-rand.pod.in
+++ b/doc/man1/openssl-rand.pod.in
@@ -14,6 +14,7 @@ B<openssl rand>
 [B<-hex>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 I<num>
 
 =for openssl ifdef engine
@@ -53,6 +54,8 @@ Show the output as a hex string.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 SEE ALSO
diff --git a/doc/man1/openssl-rehash.pod b/doc/man1/openssl-rehash.pod.in
similarity index 95%
rename from doc/man1/openssl-rehash.pod
rename to doc/man1/openssl-rehash.pod.in
index 241f225380..e21d07e9a9 100644
--- a/doc/man1/openssl-rehash.pod
+++ b/doc/man1/openssl-rehash.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =for comment
 Original text by James Westby, contributed under the OpenSSL license.
@@ -18,6 +19,7 @@ B<rehash>
 [B<-compat>]
 [B<-n>]
 [B<-v>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<directory>] ...
 
 B<c_rehash>
@@ -26,6 +28,7 @@ B<c_rehash>
 [B<-old>]
 [B<-n>]
 [B<-v>]
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<directory>] ...
 
 =head1 DESCRIPTION
@@ -116,6 +119,8 @@ releases.
 Print messages about old links removed and new links created.
 By default, this command only lists each directory as it is processed.
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 ENVIRONMENT
diff --git a/doc/man1/openssl-req.pod.in b/doc/man1/openssl-req.pod.in
index 598e6a8d54..703a208bc1 100644
--- a/doc/man1/openssl-req.pod.in
+++ b/doc/man1/openssl-req.pod.in
@@ -51,6 +51,7 @@ B<openssl> B<req>
 {- $OpenSSL::safe::opt_name_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine keygen_engine sm2-id sm2-hex-id
 
@@ -323,6 +324,8 @@ argument for this option is string of hexadecimal digits.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 CONFIGURATION FILE FORMAT
diff --git a/doc/man1/openssl-rsa.pod.in b/doc/man1/openssl-rsa.pod.in
index 5b867225ac..e2c0b24a1a 100644
--- a/doc/man1/openssl-rsa.pod.in
+++ b/doc/man1/openssl-rsa.pod.in
@@ -40,6 +40,7 @@ B<openssl> B<rsa>
 [B<-RSAPublicKey_in>]
 [B<-RSAPublicKey_out>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef pvk-strong pvk-weak pvk-none engine
 
@@ -136,6 +137,8 @@ Like B<-pubin> and B<-pubout> except B<RSAPublicKey> format is used instead.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-rsautl.pod.in b/doc/man1/openssl-rsautl.pod.in
index 1a3a1516e3..d28e672817 100644
--- a/doc/man1/openssl-rsautl.pod.in
+++ b/doc/man1/openssl-rsautl.pod.in
@@ -33,6 +33,7 @@ B<openssl> B<rsautl>
 [B<-asn1parse>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -126,6 +127,8 @@ B<-verify> option.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 NOTES
diff --git a/doc/man1/openssl-s_client.pod.in b/doc/man1/openssl-s_client.pod.in
index 0d3f54e1a2..982c54ae9e 100644
--- a/doc/man1/openssl-s_client.pod.in
+++ b/doc/man1/openssl-s_client.pod.in
@@ -120,6 +120,7 @@ B<openssl> B<s_client>
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_s_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
 [B<-ssl_client_engine> I<id>]
 {- $OpenSSL::safe::opt_v_synopsis -}
@@ -758,6 +759,8 @@ Set the minimal acceptable length, in bits, for B<N>.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 {- $OpenSSL::safe::opt_engine_item -}
 
 =item B<-ssl_client_engine> I<id>
diff --git a/doc/man1/openssl-s_server.pod.in b/doc/man1/openssl-s_server.pod.in
index b31d4f6a2c..9a5ef10d0a 100644
--- a/doc/man1/openssl-s_server.pod.in
+++ b/doc/man1/openssl-s_server.pod.in
@@ -140,6 +140,7 @@ B<openssl> B<s_server>
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef unix 4 6 unlink no_dhe nextprotoneg use_srtp engine
 
@@ -661,6 +662,8 @@ data that was sent will be rejected.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 {- $OpenSSL::safe::opt_v_item -}
 
 If the server requests a client certificate, then
diff --git a/doc/man1/openssl-s_time.pod.in b/doc/man1/openssl-s_time.pod.in
index cf8759108a..8cdc2b4347 100644
--- a/doc/man1/openssl-s_time.pod.in
+++ b/doc/man1/openssl-s_time.pod.in
@@ -28,6 +28,7 @@ B<openssl> B<s_time>
 {- $OpenSSL::safe::opt_name_synopsis -}
 [B<-cafile> I<file>]
 {- $OpenSSL::safe::opt_trust_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef ssl3 tls1 tls1_1 tls1_2 tls1_3
 
@@ -122,6 +123,8 @@ can establish.
 
 {- $OpenSSL::safe::opt_trust_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item B<-cafile> I<file>
 
 This is an obsolete synonym for B<-CAfile>.
diff --git a/doc/man1/openssl-sess_id.pod b/doc/man1/openssl-sess_id.pod.in
similarity index 98%
rename from doc/man1/openssl-sess_id.pod
rename to doc/man1/openssl-sess_id.pod.in
index bb49dbd56b..f68f180739 100644
--- a/doc/man1/openssl-sess_id.pod
+++ b/doc/man1/openssl-sess_id.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in
index e9500924ef..c6775505a9 100644
--- a/doc/man1/openssl-smime.pod.in
+++ b/doc/man1/openssl-smime.pod.in
@@ -49,6 +49,7 @@ B<openssl> B<smime>
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 I<cert.pem> ...
 
 =for openssl ifdef engine
@@ -288,6 +289,8 @@ Any verification errors cause the command to exit.
 
 {- $OpenSSL::safe::opt_r_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<cert.pem> ...
 
 One or more certificates of message recipients, used when encrypting
diff --git a/doc/man1/openssl-speed.pod.in b/doc/man1/openssl-speed.pod.in
index a15320c0fb..ac0e6b1ced 100644
--- a/doc/man1/openssl-speed.pod.in
+++ b/doc/man1/openssl-speed.pod.in
@@ -25,6 +25,7 @@ B<openssl speed>
 [B<-mr>]
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<algorithm> ...]
 
 =for openssl ifdef hmac cmac multi async_jobs engine
@@ -103,6 +104,8 @@ Produce the summary in a mechanical, machine-readable, format.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item I<algorithm> ...
 
 If any I<algorithm> is given, then those algorithms are tested, otherwise a
diff --git a/doc/man1/openssl-spkac.pod.in b/doc/man1/openssl-spkac.pod.in
index bfb17d1208..4ea15fa57a 100644
--- a/doc/man1/openssl-spkac.pod.in
+++ b/doc/man1/openssl-spkac.pod.in
@@ -25,6 +25,7 @@ B<openssl> B<spkac>
 [B<-noout>]
 [B<-verify>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -99,6 +100,8 @@ Verifies the digital signature on the supplied SPKAC.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 EXAMPLES
diff --git a/doc/man1/openssl-srp.pod.in b/doc/man1/openssl-srp.pod.in
index e9955d5c40..ce480246ee 100644
--- a/doc/man1/openssl-srp.pod.in
+++ b/doc/man1/openssl-srp.pod.in
@@ -23,6 +23,7 @@ B<openssl srp>
 [B<-passout> I<arg>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [I<user> ...]
 
 =for openssl ifdef engine
@@ -74,6 +75,8 @@ see L<openssl(1)/Pass Phrase Options>.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 {- $OpenSSL::safe::opt_r_synopsis -}
 
 =back
diff --git a/doc/man1/openssl-storeutl.pod.in b/doc/man1/openssl-storeutl.pod.in
index 3bfca0873e..75c30651fc 100644
--- a/doc/man1/openssl-storeutl.pod.in
+++ b/doc/man1/openssl-storeutl.pod.in
@@ -28,6 +28,7 @@ B<openssl> B<storeutl>
 [B<-fingerprint> I<arg>]
 [B<-I<digest>>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 I<uri> ...
 
 =head1 DESCRIPTION
@@ -110,6 +111,8 @@ The digest that was used to compute the fingerprint given with B<-fingerprint>.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head1 SEE ALSO
diff --git a/doc/man1/openssl-ts.pod.in b/doc/man1/openssl-ts.pod.in
index f115f45072..8d5e66e6d6 100644
--- a/doc/man1/openssl-ts.pod.in
+++ b/doc/man1/openssl-ts.pod.in
@@ -23,6 +23,7 @@ B<-query>
 [B<-out> I<request.tsq>]
 [B<-text>]
 {- $OpenSSL::safe::opt_r_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 B<openssl> B<ts>
 B<-reply>
@@ -42,6 +43,7 @@ B<-reply>
 [B<-token_out>]
 [B<-text>]
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 B<openssl> B<ts>
 B<-verify>
@@ -54,6 +56,7 @@ B<-verify>
 [B<-CApath> I<dir>]
 [B<-CAstore> I<uri>]
 {- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine
 
@@ -285,6 +288,8 @@ instead of DER. (Optional)
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head2 Timestamp Response verification
diff --git a/doc/man1/openssl-verify.pod.in b/doc/man1/openssl-verify.pod.in
index 3f13f307e1..fd41bbeb37 100644
--- a/doc/man1/openssl-verify.pod.in
+++ b/doc/man1/openssl-verify.pod.in
@@ -21,6 +21,7 @@ B<openssl> B<verify>
 {- $OpenSSL::safe::opt_trust_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
 {- $OpenSSL::safe::opt_v_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 [B<-->]
 [I<certificate> ...]
 
@@ -91,6 +92,8 @@ B<-trusted>, B<-untrusted> or B<-CRLfile> options.
 
 {- $OpenSSL::safe::opt_v_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =item B<-->
 
 Indicates the last option. All arguments following this are assumed to be
diff --git a/doc/man1/openssl-version.pod b/doc/man1/openssl-version.pod.in
similarity index 96%
rename from doc/man1/openssl-version.pod
rename to doc/man1/openssl-version.pod.in
index 62d50ce701..d2aaaecbf3 100644
--- a/doc/man1/openssl-version.pod
+++ b/doc/man1/openssl-version.pod.in
@@ -1,4 +1,5 @@
 =pod
+{- OpenSSL::safe::output_do_not_edit_headers(); -}
 
 =head1 NAME
 
diff --git a/doc/man1/openssl-x509.pod.in b/doc/man1/openssl-x509.pod.in
index 1ec2110100..8cf03d937e 100644
--- a/doc/man1/openssl-x509.pod.in
+++ b/doc/man1/openssl-x509.pod.in
@@ -75,6 +75,7 @@ B<openssl> B<x509>
 {- $OpenSSL::safe::opt_name_synopsis -}
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_engine_synopsis -}
+{- $OpenSSL::safe::opt_provider_synopsis -}
 
 =for openssl ifdef engine subject_hash_old issuer_hash_old
 
@@ -135,6 +136,8 @@ Cannot be used with the B<-days> option.
 
 {- $OpenSSL::safe::opt_engine_item -}
 
+{- $OpenSSL::safe::opt_provider_item -}
+
 =back
 
 =head2 Display Options
diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod
index bd3daa1a14..2f56ab7592 100644
--- a/doc/man1/openssl.pod
+++ b/doc/man1/openssl.pod
@@ -755,6 +755,26 @@ This file can be used in a subsequent command invocation.
 
 =back
 
+=head2 Provider Options
+
+With the move to provider based cryptographic operations in OpenSSL 3.0,
+options were added to allow specific providers or sets of providers to be used.
+
+=over 4
+
+=item B<-provider> I<name>
+
+Use the provider identified by I<name> and use all the methods it
+implements (algorithms, key storage, etc.).  This option can be specified
+multiple time to load more than one provider.
+
+=item B<-provider_path> I<path>
+
+Specify the search I<path> that is used to locate provider modules.  The format
+of I<path> varies depending on the operating system being used.
+
+=back
+
 =head2 Extended Verification Options
 
 Sometimes there may be more than one certificate chain leading to an
diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod
index f4f8a3bd5e..8cedbadf09 100644
--- a/doc/man3/OSSL_PROVIDER.pod
+++ b/doc/man3/OSSL_PROVIDER.pod
@@ -2,6 +2,7 @@
 
 =head1 NAME
 
+OSSL_PROVIDER_set_default_search_path,
 OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_unload,
 OSSL_PROVIDER_available,
 OSSL_PROVIDER_gettable_params, OSSL_PROVIDER_get_params,
@@ -13,6 +14,9 @@ OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines
 
  typedef struct ossl_provider_st OSSL_PROVIDER;
 
+ void OSSL_PROVIDER_set_default_search_path(OPENSSL_CTX *libctx,
+                                            const char *path);
+
  OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *libctx, const char *name);
  int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
  int OSSL_PROVIDER_available(OPENSSL_CTX *libctx, const char *name);
@@ -39,6 +43,11 @@ L<OPENSSL_CTX(3)> for further details.
 
 =head2 Functions
 
+OSSL_PROVIDER_set_default_search_path() specifies the default search B<path>
+that is to be used for looking for providers in the specified B<libctx>.
+If left unspecified, an environment variable and a fall back default value will
+be used instead.
+
 OSSL_PROVIDER_add_builtin() is used to add a built in provider to
 B<OSSL_PROVIDER> store in the given library context, by associating a
 provider name with a provider initialization function.
diff --git a/doc/perlvars.pm b/doc/perlvars.pm
index bae8b15e83..82d6e5a157 100644
--- a/doc/perlvars.pm
+++ b/doc/perlvars.pm
@@ -88,6 +88,17 @@ $OpenSSL::safe::opt_r_item = ""
 . "\n"
 . "See L<openssl(1)/Random State Options> for details.";
 
+# Provider options
+$OpenSSL::safe::opt_provider_synopsis = ""
+. "[B<-provider> I<name>]\n"
+. "[B<-provider_path> I<path>]";
+$OpenSSL::safe::opt_provider_item = ""
+. "=item B<-provider> I<name>\n"
+. "\n"
+. "=item B<-provider_path> I<path>\n"
+. "\n"
+. "See L<openssl(1)/Provider Options>.";
+
 # Engine option
 $OpenSSL::safe::opt_engine_synopsis = ""
 . "[B<-engine> I<id>]";
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
index 86dabf42ce..c17f1d46fc 100644
--- a/include/openssl/provider.h
+++ b/include/openssl/provider.h
@@ -16,6 +16,9 @@
 extern "C" {
 # endif
 
+/* Set the default provider search path */
+int OSSL_PROVIDER_set_default_search_path(OPENSSL_CTX *, const char *path);
+
 /* Load and unload a provider */
 OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *, const char *name);
 int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 8334b99361..d7a94f8adf 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4955,3 +4955,4 @@ OSSL_SELF_TEST_free                     ?	3_0_0	EXIST::FUNCTION:
 OSSL_SELF_TEST_onbegin                  ?	3_0_0	EXIST::FUNCTION:
 OSSL_SELF_TEST_oncorrupt_byte           ?	3_0_0	EXIST::FUNCTION:
 OSSL_SELF_TEST_onend                    ?	3_0_0	EXIST::FUNCTION:
+OSSL_PROVIDER_set_default_search_path   ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list