[openssl] master update

Dr. Paul Dale pauli at openssl.org
Tue Feb 23 13:41:44 UTC 2021


The branch master has been updated
       via  1263154064d2a15253381353cf804e05af18ad1b (commit)
       via  299f5ff3b5f2a5a9b5666e36a6a01fc430de9198 (commit)
       via  332a245c04dff95f81cfa1f77e0f8a935794f5ee (commit)
       via  d994ce12058d80f1f04257c30f89d04d5f6399e1 (commit)
       via  b3ab537b3a4098857d2039d1d745fee0ea5a96e3 (commit)
       via  9c6ee56318d2fb1c5885fccb4f2c4dde83e8a2ea (commit)
       via  f626c3ffae90cacc1044dbcf01c3379fceea61bc (commit)
       via  786b13fa7786db8f198c46090816d9a3e4ae72fb (commit)
       via  de2ea978b5be4607c677aaefceebff39b1520e0a (commit)
       via  0a89ae97d96275994d96b560400d3fa97f752879 (commit)
       via  ac60c84fc4551761743e087e2f51343181eb8e85 (commit)
      from  f5b00834dd11d766b9232e89e40884db8f3cd7ec (commit)


- Log -----------------------------------------------------------------
commit 1263154064d2a15253381353cf804e05af18ad1b
Author: Pauli <ppzgs1 at gmail.com>
Date:   Sat Feb 20 12:48:33 2021 +1000

    changes: note the deprecation of RAND_METHOD APIs
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit 299f5ff3b5f2a5a9b5666e36a6a01fc430de9198
Author: Pauli <ppzgs1 at gmail.com>
Date:   Thu Feb 18 09:16:26 2021 +1000

    provider: add option to load a provider without disabling the fallbacks.
    
    Add an argument to PROVIDER_try_load() that permits a provider to be
    loaded without changing the fallback status.  This is useful when an
    additional provider needs to be loaded without perturbing any other setup.
    E.g. adding mock providers as part of unit testing.
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit 332a245c04dff95f81cfa1f77e0f8a935794f5ee
Author: Pauli <ppzgs1 at gmail.com>
Date:   Wed Feb 17 11:55:13 2021 +1000

    test: update tests to use the fake random number generator
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit d994ce12058d80f1f04257c30f89d04d5f6399e1
Author: Pauli <ppzgs1 at gmail.com>
Date:   Wed Feb 17 11:54:48 2021 +1000

    test: make the DRBG test work without RAND_METHOD support.
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit b3ab537b3a4098857d2039d1d745fee0ea5a96e3
Author: Pauli <ppzgs1 at gmail.com>
Date:   Wed Feb 17 11:54:01 2021 +1000

    test: add framework for generic fake random number generator
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit 9c6ee56318d2fb1c5885fccb4f2c4dde83e8a2ea
Author: Pauli <ppzgs1 at gmail.com>
Date:   Tue Feb 16 13:32:07 2021 +1000

    rand: add DRBG/seed setting functions
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit f626c3ffae90cacc1044dbcf01c3379fceea61bc
Author: Pauli <ppzgs1 at gmail.com>
Date:   Mon Feb 22 09:45:37 2021 +1000

    rand: allow lock/unlock functions to be absent
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit 786b13fa7786db8f198c46090816d9a3e4ae72fb
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Dec 10 12:05:11 2020 +1000

    RAND_METHOD deprecation: code changes
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit de2ea978b5be4607c677aaefceebff39b1520e0a
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Dec 10 12:04:58 2020 +1000

    RAND_METHOD deprecation: fuzzer
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit 0a89ae97d96275994d96b560400d3fa97f752879
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Dec 10 12:04:45 2020 +1000

    RAND_METHOD deprecation: tests
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

commit ac60c84fc4551761743e087e2f51343181eb8e85
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Dec 10 12:04:27 2020 +1000

    RAND_METHOD deprecation: documentation
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/13652)

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

Summary of changes:
 CHANGES.md                              |   7 ++
 crypto/evp/evp_rand.c                   |   7 +-
 crypto/provider.c                       |   7 +-
 crypto/provider_conf.c                  |   2 +-
 crypto/provider_core.c                  |  10 +-
 crypto/rand/build.info                  |   6 +-
 crypto/rand/rand_lib.c                  | 110 +++++++++++++++---
 doc/internal/man3/ossl_provider_new.pod |   9 +-
 doc/man3/OSSL_PROVIDER.pod              |   9 +-
 doc/man3/RAND_get0_primary.pod          |   1 -
 doc/man3/RAND_set_DRBG_type.pod         |  64 +++++++++++
 doc/man3/RAND_set_rand_method.pod       |  14 ++-
 doc/man7/RAND.pod                       |  10 +-
 fuzz/asn1.c                             |   5 +-
 fuzz/build.info                         |  20 ++--
 fuzz/client.c                           |   5 +-
 fuzz/cmp.c                              |   4 +-
 fuzz/fuzz_rand.c                        | 164 +++++++++++++++++++++++++++
 fuzz/fuzzer.h                           |   2 +
 fuzz/rand.inc                           |  40 -------
 fuzz/server.c                           |   7 +-
 fuzz/x509.c                             |   5 +-
 include/internal/provider.h             |   2 +-
 include/openssl/provider.h              |   3 +-
 include/openssl/rand.h                  |  19 +++-
 test/build.info                         |   2 +-
 test/drbgtest.c                         |   7 ++
 test/ecdsatest.c                        |  57 +++-------
 test/provider_internal_test.c           |   2 +-
 test/sm2_internal_test.c                |  46 ++++----
 test/testutil.h                         |   5 +
 test/testutil/driver.c                  |  12 +-
 test/testutil/fake_random.c             | 192 ++++++++++++++++++++++++++++++++
 util/libcrypto.num                      |  10 +-
 34 files changed, 671 insertions(+), 194 deletions(-)
 create mode 100644 doc/man3/RAND_set_DRBG_type.pod
 create mode 100644 fuzz/fuzz_rand.c
 delete mode 100644 fuzz/rand.inc
 create mode 100644 test/testutil/fake_random.c

diff --git a/CHANGES.md b/CHANGES.md
index e45cb3a1fd..0e9f27824c 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -23,6 +23,13 @@ OpenSSL 3.0
 
 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
 
+* The RAND_METHOD APIs have been deprecated.  The functions deprecated are:
+   RAND_OpenSSL(), RAND_get_rand_method(), RAND_set_rand_engine() and
+   RAND_set_rand_method().  Provider based random number generators should
+   be used instead via EVP_RAND(3).
+
+   *Paul Dale*
+
 * The SRP APIs have been deprecated. The old APIs do not work via providers,
    and there is no EVP interface to them. Unfortunately there is no replacement
    for these APIs at this time.
diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c
index a1206c154f..4d18194a0b 100644
--- a/crypto/evp/evp_rand.c
+++ b/crypto/evp/evp_rand.c
@@ -117,7 +117,7 @@ static void *evp_rand_from_dispatch(int name_id,
                                     OSSL_PROVIDER *prov)
 {
     EVP_RAND *rand = NULL;
-    int fnrandcnt = 0, fnctxcnt = 0, fnlockcnt = 0;
+    int fnrandcnt = 0, fnctxcnt = 0, fnlockcnt = 0, fnenablelockcnt = 0;
 #ifdef FIPS_MODULE
     int fnzeroizecnt = 0;
 #endif
@@ -174,7 +174,7 @@ static void *evp_rand_from_dispatch(int name_id,
             if (rand->enable_locking != NULL)
                 break;
             rand->enable_locking = OSSL_FUNC_rand_enable_locking(fns);
-            fnlockcnt++;
+            fnenablelockcnt++;
             break;
         case OSSL_FUNC_RAND_LOCK:
             if (rand->lock != NULL)
@@ -243,7 +243,8 @@ static void *evp_rand_from_dispatch(int name_id,
      */
     if (fnrandcnt != 3
             || fnctxcnt != 3
-            || (fnlockcnt != 0 && fnlockcnt != 3)
+            || (fnenablelockcnt != 0 && fnenablelockcnt != 1)
+            || (fnlockcnt != 0 && fnlockcnt != 2)
 #ifdef FIPS_MODULE
             || fnzeroizecnt != 1
 #endif
diff --git a/crypto/provider.c b/crypto/provider.c
index bd8f75a2c1..90c31f3ac5 100644
--- a/crypto/provider.c
+++ b/crypto/provider.c
@@ -13,7 +13,8 @@
 #include <openssl/core_names.h>
 #include "internal/provider.h"
 
-OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name)
+OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name,
+                                      int retain_fallbacks)
 {
     OSSL_PROVIDER *prov = NULL;
 
@@ -22,7 +23,7 @@ OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name)
         && (prov = ossl_provider_new(libctx, name, NULL, 0)) == NULL)
         return NULL;
 
-    if (!ossl_provider_activate(prov)) {
+    if (!ossl_provider_activate(prov, retain_fallbacks)) {
         ossl_provider_free(prov);
         return NULL;
     }
@@ -34,7 +35,7 @@ OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name)
 {
     /* Any attempt to load a provider disables auto-loading of defaults */
     if (ossl_provider_disable_fallback_loading(libctx))
-        return OSSL_PROVIDER_try_load(libctx, name);
+        return OSSL_PROVIDER_try_load(libctx, name, 0);
     return NULL;
 }
 
diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c
index 709e7a1c51..cbae99a474 100644
--- a/crypto/provider_conf.c
+++ b/crypto/provider_conf.c
@@ -130,7 +130,7 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
     ok = provider_conf_params(prov, NULL, value, cnf);
 
     if (ok && activate) {
-        if (!ossl_provider_activate(prov)) {
+        if (!ossl_provider_activate(prov, 0)) {
             ok = 0;
         } else {
             if (activated_providers == NULL)
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 627ff384e1..da751e60ce 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -667,14 +667,16 @@ static int provider_activate(OSSL_PROVIDER *prov)
     return 0;
 }
 
-int ossl_provider_activate(OSSL_PROVIDER *prov)
+int ossl_provider_activate(OSSL_PROVIDER *prov, int retain_fallbacks)
 {
     if (prov == NULL)
         return 0;
     if (provider_activate(prov)) {
-        CRYPTO_THREAD_write_lock(prov->store->lock);
-        prov->store->use_fallbacks = 0;
-        CRYPTO_THREAD_unlock(prov->store->lock);
+        if (!retain_fallbacks) {
+            CRYPTO_THREAD_write_lock(prov->store->lock);
+            prov->store->use_fallbacks = 0;
+            CRYPTO_THREAD_unlock(prov->store->lock);
+        }
         return 1;
     }
     return 0;
diff --git a/crypto/rand/build.info b/crypto/rand/build.info
index b9dc16a6c7..500667c332 100644
--- a/crypto/rand/build.info
+++ b/crypto/rand/build.info
@@ -1,12 +1,14 @@
 LIBS=../../libcrypto
 
-$COMMON=rand_lib.c rand_meth.c
+$COMMON=rand_lib.c
 $CRYPTO=randfile.c rand_err.c rand_deprecated.c prov_seed.c rand_pool.c
 
 IF[{- !$disabled{'egd'} -}]
   $CRYPTO=$CRYPTO rand_egd.c
 ENDIF
-
+IF[{- !$disabled{'deprecated-3.0'} -}]
+  $COMMON=$COMMON  rand_meth.c
+ENDIF
 
 SOURCE[../../libcrypto]=$COMMON $CRYPTO
 SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 69afa9d2ea..2a4055f617 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -35,8 +35,10 @@
 static ENGINE *funct_ref;
 static CRYPTO_RWLOCK *rand_engine_lock;
 # endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
 static CRYPTO_RWLOCK *rand_meth_lock;
 static const RAND_METHOD *default_RAND_meth;
+# endif
 static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
 
 static int rand_inited = 0;
@@ -49,9 +51,11 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
         return 0;
 # endif
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     rand_meth_lock = CRYPTO_THREAD_lock_new();
     if (rand_meth_lock == NULL)
         goto err;
+# endif
 
     if (!rand_pool_init())
         goto err;
@@ -60,8 +64,10 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
     return 1;
 
  err:
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
+# endif
 # ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
@@ -71,6 +77,7 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
 
 void rand_cleanup_int(void)
 {
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = default_RAND_meth;
 
     if (!rand_inited)
@@ -79,13 +86,16 @@ void rand_cleanup_int(void)
     if (meth != NULL && meth->cleanup != NULL)
         meth->cleanup();
     RAND_set_rand_method(NULL);
+# endif
     rand_pool_cleanup();
 # ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
 # endif
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
+# endif
     rand_inited = 0;
 }
 
@@ -109,13 +119,13 @@ void RAND_keep_random_devices_open(int keep)
  */
 int RAND_poll(void)
 {
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
     int ret = meth == RAND_OpenSSL();
 
     if (meth == NULL)
         return 0;
 
-#ifndef OPENSSL_NO_DEPRECATED_3_0
     if (!ret) {
         /* fill random pool and seed the current legacy RNG */
         RAND_POOL *pool = rand_pool_new(RAND_DRBG_STRENGTH, 1,
@@ -138,20 +148,26 @@ int RAND_poll(void)
      err:
         rand_pool_free(pool);
     }
-#endif
     return ret;
+# else
+    static const char salt[] = "polling";
+
+    RAND_seed(salt, sizeof(salt));
+    return 1;
+# endif
 }
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
 int RAND_set_rand_method(const RAND_METHOD *meth)
 {
     if (!RUN_ONCE(&rand_init, do_rand_init))
         return 0;
 
     CRYPTO_THREAD_write_lock(rand_meth_lock);
-# ifndef OPENSSL_NO_ENGINE
+#  ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(funct_ref);
     funct_ref = NULL;
-# endif
+#  endif
     default_RAND_meth = meth;
     CRYPTO_THREAD_unlock(rand_meth_lock);
     return 1;
@@ -166,7 +182,7 @@ const RAND_METHOD *RAND_get_rand_method(void)
 
     CRYPTO_THREAD_write_lock(rand_meth_lock);
     if (default_RAND_meth == NULL) {
-# ifndef OPENSSL_NO_ENGINE
+#  ifndef OPENSSL_NO_ENGINE
         ENGINE *e;
 
         /* If we have an engine that can do RAND, use it. */
@@ -178,16 +194,16 @@ const RAND_METHOD *RAND_get_rand_method(void)
             ENGINE_finish(e);
             default_RAND_meth = &rand_meth;
         }
-# else
+#  else
         default_RAND_meth = &rand_meth;
-# endif
+#  endif
     }
     tmp_meth = default_RAND_meth;
     CRYPTO_THREAD_unlock(rand_meth_lock);
     return tmp_meth;
 }
 
-# if !defined(OPENSSL_NO_ENGINE)
+#  if !defined(OPENSSL_NO_ENGINE)
 int RAND_set_rand_engine(ENGINE *engine)
 {
     const RAND_METHOD *tmp_meth = NULL;
@@ -211,22 +227,40 @@ int RAND_set_rand_engine(ENGINE *engine)
     CRYPTO_THREAD_unlock(rand_engine_lock);
     return 1;
 }
-# endif
+#  endif
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
 
 void RAND_seed(const void *buf, int num)
 {
+    EVP_RAND_CTX *drbg;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth != NULL && meth->seed != NULL)
+    if (meth != NULL && meth->seed != NULL) {
         meth->seed(buf, num);
+        return;
+    }
+# endif
+
+    drbg = RAND_get0_primary(NULL);
+    if (drbg != NULL && num > 0)
+        EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
 }
 
 void RAND_add(const void *buf, int num, double randomness)
 {
+    EVP_RAND_CTX *drbg;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
-    if (meth != NULL && meth->add != NULL)
+    if (meth != NULL && meth->add != NULL) {
         meth->add(buf, num, randomness);
+        return;
+    }
+# endif
+    drbg = RAND_get0_primary(NULL);
+    if (drbg != NULL && num > 0)
+        EVP_RAND_reseed(drbg, 0, NULL, 0, buf, num);
 }
 
 # if !defined(OPENSSL_NO_DEPRECATED_1_1_0)
@@ -244,21 +278,25 @@ int RAND_pseudo_bytes(unsigned char *buf, int num)
 int RAND_status(void)
 {
     EVP_RAND_CTX *rand;
+# ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth != NULL && meth != RAND_OpenSSL())
         return meth->status != NULL ? meth->status() : 0;
+# endif
 
     if ((rand = RAND_get0_primary(NULL)) == NULL)
         return 0;
     return EVP_RAND_state(rand) == EVP_RAND_STATE_READY;
 }
-#else  /* !FIPS_MODULE */
+# else  /* !FIPS_MODULE */
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
 const RAND_METHOD *RAND_get_rand_method(void)
 {
     return NULL;
 }
+# endif
 #endif /* !FIPS_MODULE */
 
 /*
@@ -269,6 +307,7 @@ const RAND_METHOD *RAND_get_rand_method(void)
 int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, int num)
 {
     EVP_RAND_CTX *rand;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth != NULL && meth != RAND_OpenSSL()) {
@@ -277,6 +316,7 @@ int RAND_priv_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, int num)
         ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
         return -1;
     }
+#endif
 
     rand = RAND_get0_private(ctx);
     if (rand != NULL)
@@ -293,6 +333,7 @@ int RAND_priv_bytes(unsigned char *buf, int num)
 int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, int num)
 {
     EVP_RAND_CTX *rand;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth != NULL && meth != RAND_OpenSSL()) {
@@ -301,6 +342,7 @@ int RAND_bytes_ex(OSSL_LIB_CTX *ctx, unsigned char *buf, int num)
         ERR_raise(ERR_LIB_RAND, RAND_R_FUNC_NOT_IMPLEMENTED);
         return -1;
     }
+#endif
 
     rand = RAND_get0_public(ctx);
     if (rand != NULL)
@@ -670,11 +712,14 @@ EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx)
 #ifndef FIPS_MODULE
 static int random_set_string(char **p, const char *s)
 {
-    char *d = OPENSSL_strdup(s);
+    char *d = NULL;
 
-    if (d == NULL) {
-        ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
-        return 0;
+    if (s != NULL) {
+        d = OPENSSL_strdup(s);
+        if (d == NULL) {
+            ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
     }
     OPENSSL_free(*p);
     *p = d;
@@ -742,4 +787,37 @@ void ossl_random_add_conf_module(void)
     OSSL_TRACE(CONF, "Adding config module 'random'\n");
     CONF_module_add("random", random_conf_init, random_conf_deinit);
 }
+
+int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+                       const char *cipher, const char *digest)
+{
+    RAND_GLOBAL *dgbl = rand_get_global(ctx);
+
+    if (dgbl == NULL)
+        return 0;
+    if (dgbl->primary != NULL) {
+        ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
+        return 0;
+    }
+    return random_set_string(&dgbl->rng_name, drbg)
+        && random_set_string(&dgbl->rng_propq, propq)
+        && random_set_string(&dgbl->rng_cipher, cipher)
+        && random_set_string(&dgbl->rng_digest, digest);
+}
+
+int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+                              const char *propq)
+{
+    RAND_GLOBAL *dgbl = rand_get_global(ctx);
+
+    if (dgbl == NULL)
+        return 0;
+    if (dgbl->primary != NULL) {
+        ERR_raise(ERR_LIB_CRYPTO, RAND_R_ALREADY_INSTANTIATED);
+        return 0;
+    }
+    return random_set_string(&dgbl->seed_name, seed)
+        && random_set_string(&dgbl->seed_propq, propq);
+}
+
 #endif
diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod
index d01673e767..d74ce57fef 100644
--- a/doc/internal/man3/ossl_provider_new.pod
+++ b/doc/internal/man3/ossl_provider_new.pod
@@ -40,7 +40,7 @@ ossl_provider_get_capabilities
   * Activate the Provider
   * If the Provider is a module, the module will be loaded
   */
- int ossl_provider_activate(OSSL_PROVIDER *prov);
+ int ossl_provider_activate(OSSL_PROVIDER *prov, int retain_fallbacks);
  int ossl_provider_deactivate(OSSL_PROVIDER *prov);
  /* Check if provider is available (activated) */
  int ossl_provider_available(OSSL_PROVIDER *prov);
@@ -178,6 +178,9 @@ be located in that module, and called.
 
 =back
 
+If I<retain_fallbacks> is zero, fallbacks are disabled.  If it is nonzero,
+fallbacks are left unchanged.
+
 ossl_provider_deactivate() "deactivates" the provider for the given
 provider object I<prov> by decrementing its activation count.  When
 that count reaches zero, the activation flag is cleared.
@@ -277,8 +280,8 @@ it has been incremented.
 ossl_provider_free() doesn't return any value.
 
 ossl_provider_set_module_path(), ossl_provider_set_fallback(),
-ossl_provider_activate() and ossl_provider_deactivate() return 1 on
-success, or 0 on error.
+ossl_provider_activate(), ossl_provider_activate_leave_fallbacks() and
+ossl_provider_deactivate() return 1 on success, or 0 on error.
 
 ossl_provider_available() return 1 if the provider is available,
 otherwise 0.
diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod
index 81a2ac2bcb..e5c451259a 100644
--- a/doc/man3/OSSL_PROVIDER.pod
+++ b/doc/man3/OSSL_PROVIDER.pod
@@ -21,7 +21,8 @@ OSSL_PROVIDER_get_capabilities, OSSL_PROVIDER_self_test
                                             const char *path);
 
  OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name);
- OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name);
+ OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name,
+                                       int retain_fallbacks);
  int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
  int OSSL_PROVIDER_available(OSSL_LIB_CTX *libctx, const char *name);
  int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
@@ -79,9 +80,9 @@ entry point, C<OSSL_provider_init>.
 
 OSSL_PROVIDER_try_load() functions like OSSL_PROVIDER_load(), except that
 it does not disable the fallback providers if the provider cannot be
-loaded and initialized.
-If the provider loads successfully, however, the fallback providers are
-disabled.
+loaded and initialized or if I<retain_fallbacks> is zero.
+If the provider loads successfully and I<retain_fallbacks> is nonzero, the
+fallback providers are disabled.
 
 OSSL_PROVIDER_unload() unloads the given provider.
 For a provider added with OSSL_PROVIDER_add_builtin(), this simply
diff --git a/doc/man3/RAND_get0_primary.pod b/doc/man3/RAND_get0_primary.pod
index 5d84b330ab..cf0fae95f7 100644
--- a/doc/man3/RAND_get0_primary.pod
+++ b/doc/man3/RAND_get0_primary.pod
@@ -15,7 +15,6 @@ RAND_get0_private
  EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx);
  EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx);
 
-
 =head1 DESCRIPTION
 
 The default RAND API implementation (RAND_OpenSSL()) utilizes three
diff --git a/doc/man3/RAND_set_DRBG_type.pod b/doc/man3/RAND_set_DRBG_type.pod
new file mode 100644
index 0000000000..f78c15ff45
--- /dev/null
+++ b/doc/man3/RAND_set_DRBG_type.pod
@@ -0,0 +1,64 @@
+=pod
+
+=head1 NAME
+
+RAND_set_DRBG_type,
+RAND_set_seed_source_type
+- specify the global random number generator types
+
+=head1 SYNOPSIS
+
+ #include <openssl/rand.h>
+
+ int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+                        const char *cipher, const char *digest);
+ int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+                               const char *propq);
+
+=head1 DESCRIPTION
+
+RAND_set_DRBG_type() specifies the random bit generator that will be
+used within the library context I<ctx>.  A generator of name I<drbg>
+with properties I<propq> will be fetched.  It will be instantiated with
+either I<cipher> or I<digest> as its underlying cryptographic algorithm.
+This specifies the type that will be used for the primary, public and
+private random instances.
+
+RAND_set_seed_source_type() specifies the seed source that will be used
+within the library context I<ctx>.  The seed source of name I<seed>
+with properties I<propq> will be fetched and used to seed the primary
+random big generator.
+
+=head1 RETURN VALUES
+
+These function return 1 on success and 0 on failure.
+
+=head1 NOTES
+
+These functions must be called before the random bit generators are first
+created in the library context.  They will return an error if the call
+is made too late.
+
+The default DRBG is "CTR-DRBG" using the "AES-256-CTR" cipher.
+
+The default seed source is "SEED-SRC".
+
+=head1 SEE ALSO
+
+L<EVP_RAND(3)>,
+L<RAND_get0_primary(3)>
+
+=head1 HISTORY
+
+These functions were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/RAND_set_rand_method.pod b/doc/man3/RAND_set_rand_method.pod
index a989c1c9b4..755e25dde1 100644
--- a/doc/man3/RAND_set_rand_method.pod
+++ b/doc/man3/RAND_set_rand_method.pod
@@ -8,6 +8,10 @@ RAND_set_rand_method, RAND_get_rand_method, RAND_OpenSSL - select RAND method
 
  #include <openssl/rand.h>
 
+Deprecated since OpenSSL 3.0, can be hidden entirely by defining
+B<OPENSSL_API_COMPAT> with a suitable version value, see
+L<openssl_user_macros(7)>:
+
  RAND_METHOD *RAND_OpenSSL(void);
 
  int RAND_set_rand_method(const RAND_METHOD *meth);
@@ -16,6 +20,10 @@ RAND_set_rand_method, RAND_get_rand_method, RAND_OpenSSL - select RAND method
 
 =head1 DESCRIPTION
 
+All of the functions described on this page are deprecated.
+Applications should instead use L<RAND_set_DRBG_type(3)>,
+L<EVP_RAND(3)> and L<EVP_RAND(7)>.
+
 A B<RAND_METHOD> specifies the functions that OpenSSL uses for random number
 generation.
 
@@ -55,14 +63,16 @@ methods.
 
 =head1 SEE ALSO
 
+L<EVP_RAND(3)>,
+L<RAND_set_DRBG_type(3)>,
 L<RAND_bytes(3)>,
 L<ENGINE_by_id(3)>,
+L<EVP_RAND(7)>,
 L<RAND(7)>
 
 =head1 HISTORY
 
-The ability for an B<ENGINE> to replace the RAND API was deprecated in
-OpenSSL 3.0.
+All of these functions were deprecated in OpenSSL 3.0.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man7/RAND.pod b/doc/man7/RAND.pod
index 7bad23a0ca..8ae55ccac8 100644
--- a/doc/man7/RAND.pod
+++ b/doc/man7/RAND.pod
@@ -46,8 +46,8 @@ possible about its internal state, and that a compromise of the "public"
 CSPRNG instance will not affect the secrecy of these private values.
 
 In the rare case where the default implementation does not satisfy your special
-requirements, the default RAND method can be replaced by your own RAND
-method using L<RAND_set_rand_method(3)>.
+requirements, the default RAND internals can be replaced by your own
+L<EVP_RAND(3)> objects.
 
 Changing the default random generator should be necessary
 only in exceptional cases and is not recommended, unless you have a profound
@@ -66,11 +66,9 @@ number generator (CSPRNG), which is described in [NIST SP 800-90A Rev. 1].
 
 L<RAND_bytes(3)>,
 L<RAND_priv_bytes(3)>,
-L<RAND_get_rand_method(3)>,
-L<RAND_set_rand_method(3)>,
-L<RAND_OpenSSL(3)>,
 L<EVP_RAND(3)>,
-L<RAND_get0_primary(3)>
+L<RAND_get0_primary(3)>,
+L<EVP_RAND(7)>
 
 =head1 COPYRIGHT
 
diff --git a/fuzz/asn1.c b/fuzz/asn1.c
index 15a517a72c..449d851e68 100644
--- a/fuzz/asn1.c
+++ b/fuzz/asn1.c
@@ -40,8 +40,6 @@
 #include <internal/nelem.h>
 #include "fuzzer.h"
 
-#include "rand.inc"
-
 static ASN1_ITEM_EXP *item_type[] = {
     ASN1_ITEM_ref(ACCESS_DESCRIPTION),
 #ifndef OPENSSL_NO_RFC3779
@@ -280,6 +278,7 @@ static ASN1_PCTX *pctx;
 
 int FuzzerInitialize(int *argc, char ***argv)
 {
+    FuzzerSetRand();
     pctx = ASN1_PCTX_new();
     ASN1_PCTX_set_flags(pctx, ASN1_PCTX_FLAGS_SHOW_ABSENT |
         ASN1_PCTX_FLAGS_SHOW_SEQUENCE | ASN1_PCTX_FLAGS_SHOW_SSOF |
@@ -291,7 +290,6 @@ int FuzzerInitialize(int *argc, char ***argv)
     OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
-    FuzzerSetRand();
 
     return 1;
 }
@@ -365,4 +363,5 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 void FuzzerCleanup(void)
 {
     ASN1_PCTX_free(pctx);
+    FuzzerClearRand();
 }
diff --git a/fuzz/build.info b/fuzz/build.info
index e52b8e3b57..7b26b8c152 100644
--- a/fuzz/build.info
+++ b/fuzz/build.info
@@ -23,7 +23,7 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
     PROGRAMS{noinst}=ct
   ENDIF
 
-  SOURCE[asn1]=asn1.c driver.c
+  SOURCE[asn1]=asn1.c driver.c fuzz_rand.c
   INCLUDE[asn1]=../include {- $ex_inc -}
   DEPEND[asn1]=../libcrypto ../libssl {- $ex_lib -}
 
@@ -39,11 +39,11 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
   INCLUDE[bndiv]=../include {- $ex_inc -}
   DEPEND[bndiv]=../libcrypto {- $ex_lib -}
 
-  SOURCE[client]=client.c driver.c
+  SOURCE[client]=client.c driver.c fuzz_rand.c
   INCLUDE[client]=../include {- $ex_inc -}
   DEPEND[client]=../libcrypto ../libssl {- $ex_lib -}
 
-  SOURCE[cmp]=cmp.c driver.c
+  SOURCE[cmp]=cmp.c driver.c fuzz_rand.c
   INCLUDE[cmp]=../include {- $ex_inc -}
   DEPEND[cmp]=../libcrypto {- $ex_lib -}
 
@@ -63,11 +63,11 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
   INCLUDE[ct]=../include {- $ex_inc -}
   DEPEND[ct]=../libcrypto {- $ex_lib -}
 
-  SOURCE[server]=server.c driver.c
+  SOURCE[server]=server.c driver.c fuzz_rand.c
   INCLUDE[server]=../include {- $ex_inc -}
   DEPEND[server]=../libcrypto ../libssl {- $ex_lib -}
 
-  SOURCE[x509]=x509.c driver.c
+  SOURCE[x509]=x509.c driver.c fuzz_rand.c
   INCLUDE[x509]=../include {- $ex_inc -}
   DEPEND[x509]=../libcrypto {- $ex_lib -}
 ENDIF
@@ -87,7 +87,7 @@ IF[{- !$disabled{tests} -}]
     PROGRAMS{noinst}=ct-test
   ENDIF
 
-  SOURCE[asn1-test]=asn1.c test-corpus.c
+  SOURCE[asn1-test]=asn1.c test-corpus.c fuzz_rand.c
   INCLUDE[asn1-test]=../include
   DEPEND[asn1-test]=../libcrypto ../libssl
 
@@ -103,11 +103,11 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[bndiv-test]=../include
   DEPEND[bndiv-test]=../libcrypto
 
-  SOURCE[client-test]=client.c test-corpus.c
+  SOURCE[client-test]=client.c test-corpus.c fuzz_rand.c
   INCLUDE[client-test]=../include
   DEPEND[client-test]=../libcrypto ../libssl
 
-  SOURCE[cmp-test]=cmp.c test-corpus.c
+  SOURCE[cmp-test]=cmp.c test-corpus.c fuzz_rand.c
   INCLUDE[cmp-test]=../include
   DEPEND[cmp-test]=../libcrypto.a
   # referring to static lib allows using non-exported functions
@@ -128,11 +128,11 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[ct-test]=../include
   DEPEND[ct-test]=../libcrypto
 
-  SOURCE[server-test]=server.c test-corpus.c
+  SOURCE[server-test]=server.c test-corpus.c fuzz_rand.c
   INCLUDE[server-test]=../include
   DEPEND[server-test]=../libcrypto ../libssl
 
-  SOURCE[x509-test]=x509.c test-corpus.c
+  SOURCE[x509-test]=x509.c test-corpus.c fuzz_rand.c
   INCLUDE[x509-test]=../include
   DEPEND[x509-test]=../libcrypto
 ENDIF
diff --git a/fuzz/client.c b/fuzz/client.c
index 2c2cd90fb8..007b0d6443 100644
--- a/fuzz/client.c
+++ b/fuzz/client.c
@@ -18,8 +18,6 @@
 #include <openssl/err.h>
 #include "fuzzer.h"
 
-#include "rand.inc"
-
 /* unused, to avoid warning. */
 static int idx;
 
@@ -42,12 +40,12 @@ int FuzzerInitialize(int *argc, char ***argv)
 {
     STACK_OF(SSL_COMP) *comp_methods;
 
+    FuzzerSetRand();
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
     OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
     idx = SSL_get_ex_data_X509_STORE_CTX_idx();
-    FuzzerSetRand();
     comp_methods = SSL_COMP_get_compression_methods();
     if (comp_methods != NULL)
         sk_SSL_COMP_sort(comp_methods);
@@ -99,4 +97,5 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 
 void FuzzerCleanup(void)
 {
+    FuzzerClearRand();
 }
diff --git a/fuzz/cmp.c b/fuzz/cmp.c
index ae4c1ec753..82a812baba 100644
--- a/fuzz/cmp.c
+++ b/fuzz/cmp.c
@@ -16,14 +16,13 @@
 #include "../crypto/cmp/cmp_local.h"
 #include <openssl/err.h>
 #include "fuzzer.h"
-#include "rand.inc"
 
 int FuzzerInitialize(int *argc, char ***argv)
 {
+    FuzzerSetRand();
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
-    FuzzerSetRand();
     return 1;
 }
 
@@ -200,4 +199,5 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 
 void FuzzerCleanup(void)
 {
+    FuzzerClearRand();
 }
diff --git a/fuzz/fuzz_rand.c b/fuzz/fuzz_rand.c
new file mode 100644
index 0000000000..99c32509c6
--- /dev/null
+++ b/fuzz/fuzz_rand.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * https://www.openssl.org/source/license.html
+ * or in the file LICENSE in the source distribution.
+ */
+
+#include <openssl/core_names.h>
+#include <openssl/rand.h>
+#include <openssl/provider.h>
+#include "fuzzer.h"
+
+static OSSL_FUNC_rand_newctx_fn fuzz_rand_newctx;
+static OSSL_FUNC_rand_freectx_fn fuzz_rand_freectx;
+static OSSL_FUNC_rand_instantiate_fn fuzz_rand_instantiate;
+static OSSL_FUNC_rand_uninstantiate_fn fuzz_rand_uninstantiate;
+static OSSL_FUNC_rand_generate_fn fuzz_rand_generate;
+static OSSL_FUNC_rand_gettable_ctx_params_fn fuzz_rand_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn fuzz_rand_get_ctx_params;
+static OSSL_FUNC_rand_enable_locking_fn fuzz_rand_enable_locking;
+
+static void *fuzz_rand_newctx(
+         void *provctx, void *parent, const OSSL_DISPATCH *parent_dispatch)
+{
+    int *st = OPENSSL_malloc(sizeof(*st));
+
+    if (st != NULL)
+        *st = EVP_RAND_STATE_UNINITIALISED;
+    return st;
+}
+
+static void fuzz_rand_freectx(ossl_unused void *vrng)
+{
+    OPENSSL_free(vrng);
+}
+
+static int fuzz_rand_instantiate(ossl_unused void *vrng,
+                                 ossl_unused unsigned int strength,
+                                 ossl_unused int prediction_resistance,
+                                 ossl_unused const unsigned char *pstr,
+                                 ossl_unused size_t pstr_len)
+{
+    *(int *)vrng = EVP_RAND_STATE_READY;
+    return 1;
+}
+
+static int fuzz_rand_uninstantiate(ossl_unused void *vrng)
+{
+    *(int *)vrng = EVP_RAND_STATE_UNINITIALISED;
+    return 1;
+}
+
+static int fuzz_rand_generate(ossl_unused void *vdrbg,
+                              unsigned char *out, size_t outlen,
+                              ossl_unused unsigned int strength,
+                              ossl_unused int prediction_resistance,
+                              ossl_unused const unsigned char *adin,
+                              ossl_unused size_t adinlen)
+{
+    unsigned char val = 1;
+    size_t i;
+
+    for (i = 0; i < outlen; i++)
+        out[i] = val++;
+    return 1;
+}
+
+static int fuzz_rand_enable_locking(ossl_unused void *vrng)
+{
+    return 1;
+}
+
+static int fuzz_rand_get_ctx_params(void *vrng, OSSL_PARAM params[])
+{
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+    if (p != NULL && !OSSL_PARAM_set_int(p, *(int *)vrng))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+    if (p != NULL && !OSSL_PARAM_set_int(p, 500))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, INT_MAX))
+        return 0;
+    return 1;
+}
+
+static const OSSL_PARAM *fuzz_rand_gettable_ctx_params(ossl_unused void *provctx)
+{
+    static const OSSL_PARAM known_gettable_ctx_params[] = {
+        OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
+        OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+        OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+        OSSL_PARAM_END
+    };
+    return known_gettable_ctx_params;
+}
+
+static const OSSL_DISPATCH fuzz_rand_functions[] = {
+    { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))fuzz_rand_newctx },
+    { OSSL_FUNC_RAND_FREECTX, (void (*)(void))fuzz_rand_freectx },
+    { OSSL_FUNC_RAND_INSTANTIATE, (void (*)(void))fuzz_rand_instantiate },
+    { OSSL_FUNC_RAND_UNINSTANTIATE, (void (*)(void))fuzz_rand_uninstantiate },
+    { OSSL_FUNC_RAND_GENERATE, (void (*)(void))fuzz_rand_generate },
+    { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))fuzz_rand_enable_locking },
+    { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+      (void(*)(void))fuzz_rand_gettable_ctx_params },
+    { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))fuzz_rand_get_ctx_params },
+    { 0, NULL }
+};
+
+static const OSSL_ALGORITHM fuzz_rand_rand[] = {
+    { "fuzz", "provider=fuzz-rand", fuzz_rand_functions },
+    { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM *fuzz_rand_query(void *provctx,
+                                             int operation_id,
+                                             int *no_cache)
+{
+    *no_cache = 0;
+    switch (operation_id) {
+    case OSSL_OP_RAND:
+        return fuzz_rand_rand;
+    }
+    return NULL;
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH fuzz_rand_method[] = {
+    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fuzz_rand_query },
+    { 0, NULL }
+};
+
+static int fuzz_rand_provider_init(const OSSL_CORE_HANDLE *handle,
+                                   const OSSL_DISPATCH *in,
+                                   const OSSL_DISPATCH **out, void **provctx)
+{
+    *provctx = OSSL_LIB_CTX_new();
+    *out = fuzz_rand_method;
+    return 1;
+}
+
+static OSSL_PROVIDER *r_prov;
+
+void FuzzerSetRand(void)
+{
+    if (!OSSL_PROVIDER_add_builtin(NULL, "fuzz-rand", fuzz_rand_provider_init)
+        || !RAND_set_DRBG_type(NULL, "fuzz", NULL, NULL, NULL)
+        || (r_prov = OSSL_PROVIDER_try_load(NULL, "fuzz-rand", 1)) == NULL)
+        exit(1);
+}
+
+void FuzzerClearRand(void)
+{
+    OSSL_PROVIDER_unload(r_prov);
+}
diff --git a/fuzz/fuzzer.h b/fuzz/fuzzer.h
index b4605f8c8f..517a8622d9 100644
--- a/fuzz/fuzzer.h
+++ b/fuzz/fuzzer.h
@@ -11,4 +11,6 @@
 int FuzzerTestOneInput(const uint8_t *buf, size_t len);
 int FuzzerInitialize(int *argc, char ***argv);
 void FuzzerCleanup(void);
+
 void FuzzerSetRand(void);
+void FuzzerClearRand(void);
diff --git a/fuzz/rand.inc b/fuzz/rand.inc
deleted file mode 100644
index d0eebff896..0000000000
--- a/fuzz/rand.inc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016 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 may obtain a copy of the License at
- * https://www.openssl.org/source/license.html
- * or in the file LICENSE in the source distribution.
- */
-#include <openssl/rand.h>
-
-static int fuzz_bytes(unsigned char *buf, int num)
-{
-    unsigned char val = 1;
-
-    while (--num >= 0)
-        *buf++ = val++;
-    return 1;
-}
-
-static int fuzz_status(void)
-{
-    return 1;
-}
-
-static RAND_METHOD fuzz_rand_method = {
-    NULL,
-    fuzz_bytes,
-    NULL,
-    NULL,
-    fuzz_bytes,
-    fuzz_status
-};
-
-void FuzzerSetRand(void)
-{
-    RAND_set_rand_method(&fuzz_rand_method);
-}
-
-
diff --git a/fuzz/server.c b/fuzz/server.c
index c381bbfae8..6234e15ccc 100644
--- a/fuzz/server.c
+++ b/fuzz/server.c
@@ -12,7 +12,7 @@
 
 /* Test first part of SSL server handshake. */
 
-/* We need to use the deprecated RSA/EC low level calls */
+/* We need to use some deprecated APIs */
 #define OPENSSL_SUPPRESS_DEPRECATED
 
 #include <time.h>
@@ -25,8 +25,6 @@
 #include <openssl/err.h>
 #include "fuzzer.h"
 
-#include "rand.inc"
-
 static const uint8_t kCertificateDER[] = {
     0x30, 0x82, 0x02, 0xff, 0x30, 0x82, 0x01, 0xe7, 0xa0, 0x03, 0x02, 0x01,
     0x02, 0x02, 0x11, 0x00, 0xb1, 0x84, 0xee, 0x34, 0x99, 0x98, 0x76, 0xfb,
@@ -495,12 +493,12 @@ int FuzzerInitialize(int *argc, char ***argv)
 {
     STACK_OF(SSL_COMP) *comp_methods;
 
+    FuzzerSetRand();
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
     OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
     idx = SSL_get_ex_data_X509_STORE_CTX_idx();
-    FuzzerSetRand();
     comp_methods = SSL_COMP_get_compression_methods();
     if (comp_methods != NULL)
         sk_SSL_COMP_sort(comp_methods);
@@ -663,4 +661,5 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 
 void FuzzerCleanup(void)
 {
+    FuzzerClearRand();
 }
diff --git a/fuzz/x509.c b/fuzz/x509.c
index dd9075acd7..78061d176a 100644
--- a/fuzz/x509.c
+++ b/fuzz/x509.c
@@ -14,14 +14,12 @@
 #include <openssl/rand.h>
 #include "fuzzer.h"
 
-#include "rand.inc"
-
 int FuzzerInitialize(int *argc, char ***argv)
 {
+    FuzzerSetRand();
     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
     ERR_clear_error();
     CRYPTO_free_ex_index(0, -1);
-    FuzzerSetRand();
     return 1;
 }
 
@@ -50,4 +48,5 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len)
 
 void FuzzerCleanup(void)
 {
+    FuzzerClearRand();
 }
diff --git a/include/internal/provider.h b/include/internal/provider.h
index a91c515f04..fbe3154b53 100644
--- a/include/internal/provider.h
+++ b/include/internal/provider.h
@@ -49,7 +49,7 @@ int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx);
  * Activate the Provider
  * If the Provider is a module, the module will be loaded
  */
-int ossl_provider_activate(OSSL_PROVIDER *prov);
+int ossl_provider_activate(OSSL_PROVIDER *prov, int retain_fallbacks);
 int ossl_provider_deactivate(OSSL_PROVIDER *prov);
 /* Check if the provider is available (activated) */
 int ossl_provider_available(OSSL_PROVIDER *prov);
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
index 723201e1c5..a8720aaa7e 100644
--- a/include/openssl/provider.h
+++ b/include/openssl/provider.h
@@ -22,7 +22,8 @@ int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *, const char *path);
 
 /* Load and unload a provider */
 OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *, const char *name);
-OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *, const char *name);
+OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *, const char *name,
+                                      int retain_fallbacks);
 int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov);
 int OSSL_PROVIDER_available(OSSL_LIB_CTX *, const char *name);
 int OSSL_PROVIDER_do_all(OSSL_LIB_CTX *ctx,
diff --git a/include/openssl/rand.h b/include/openssl/rand.h
index 2570b8463e..08593705c3 100644
--- a/include/openssl/rand.h
+++ b/include/openssl/rand.h
@@ -36,6 +36,7 @@ extern "C" {
  */
 # define RAND_DRBG_STRENGTH             256
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
 struct rand_meth_st {
     int (*seed) (const void *buf, int num);
     int (*bytes) (unsigned char *buf, int num);
@@ -45,13 +46,14 @@ struct rand_meth_st {
     int (*status) (void);
 };
 
-int RAND_set_rand_method(const RAND_METHOD *meth);
-const RAND_METHOD *RAND_get_rand_method(void);
-# ifndef OPENSSL_NO_ENGINE
-int RAND_set_rand_engine(ENGINE *engine);
-# endif
+OSSL_DEPRECATEDIN_3_0 int RAND_set_rand_method(const RAND_METHOD *meth);
+OSSL_DEPRECATEDIN_3_0 const RAND_METHOD *RAND_get_rand_method(void);
+#  ifndef OPENSSL_NO_ENGINE
+OSSL_DEPRECATEDIN_3_0 int RAND_set_rand_engine(ENGINE *engine);
+#  endif
 
-RAND_METHOD *RAND_OpenSSL(void);
+OSSL_DEPRECATEDIN_3_0 RAND_METHOD *RAND_OpenSSL(void);
+# endif /* OPENSSL_NO_DEPRECATED_3_0 */
 
 # ifndef OPENSSL_NO_DEPRECATED_1_1_0
 #   define RAND_cleanup() while(0) continue
@@ -72,6 +74,11 @@ EVP_RAND_CTX *RAND_get0_primary(OSSL_LIB_CTX *ctx);
 EVP_RAND_CTX *RAND_get0_public(OSSL_LIB_CTX *ctx);
 EVP_RAND_CTX *RAND_get0_private(OSSL_LIB_CTX *ctx);
 
+int RAND_set_DRBG_type(OSSL_LIB_CTX *ctx, const char *drbg, const char *propq,
+                       const char *cipher, const char *digest);
+int RAND_set_seed_source_type(OSSL_LIB_CTX *ctx, const char *seed,
+                              const char *propq);
+
 void RAND_seed(const void *buf, int num);
 void RAND_keep_random_devices_open(int keep);
 
diff --git a/test/build.info b/test/build.info
index 3f65d68b8c..5bf35dcb10 100644
--- a/test/build.info
+++ b/test/build.info
@@ -20,7 +20,7 @@ IF[{- !$disabled{tests} -}]
   LIBS{noinst,has_main}=libtestutil.a
   SOURCE[libtestutil.a]=testutil/basic_output.c testutil/output.c \
           testutil/driver.c testutil/tests.c testutil/cb.c testutil/stanza.c \
-          testutil/format_output.c testutil/load.c \
+          testutil/format_output.c testutil/load.c testutil/fake_random.c \
           testutil/test_cleanup.c testutil/main.c testutil/testutil_init.c \
           testutil/options.c testutil/test_options.c testutil/provider.c \
           testutil/apps_mem.c testutil/random.c $LIBAPPSSRC
diff --git a/test/drbgtest.c b/test/drbgtest.c
index 765c2d23df..1276f726cc 100644
--- a/test/drbgtest.c
+++ b/test/drbgtest.c
@@ -7,6 +7,9 @@
  * https://www.openssl.org/source/license.html
  */
 
+/* We need to use some deprecated APIs */
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <string.h>
 #include "internal/nelem.h"
 #include <openssl/crypto.h>
@@ -44,6 +47,7 @@
  */
 static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
 {
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth != NULL && meth != RAND_OpenSSL()) {
@@ -51,6 +55,7 @@ static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
             return meth->bytes(buf, num);
         return -1;
     }
+#endif
 
     if (drbg != NULL)
         return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0);
@@ -548,9 +553,11 @@ static int test_rand_reseed(void)
     if (crngt_skip())
         return TEST_skip("CRNGT cannot be disabled");
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     /* Check whether RAND_OpenSSL() is the default method */
     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
         return 0;
+#endif
 
     /* All three DRBGs should be non-null */
     if (!TEST_ptr(primary = RAND_get0_primary(NULL))
diff --git a/test/ecdsatest.c b/test/ecdsatest.c
index 8340d28912..d03eb6f01e 100644
--- a/test/ecdsatest.c
+++ b/test/ecdsatest.c
@@ -25,48 +25,18 @@
 # include "internal/nelem.h"
 # include "ecdsatest.h"
 
-/* functions to change the RAND_METHOD */
-static int fbytes(unsigned char *buf, int num);
-
-static RAND_METHOD fake_rand;
-static const RAND_METHOD *old_rand;
-static int use_fake = 0;
 static const char *numbers[2];
 static size_t crv_len = 0;
 static EC_builtin_curve *curves = NULL;
+static OSSL_PROVIDER *fake_rand = NULL;
 
-static int change_rand(void)
-{
-    /* save old rand method */
-    if (!TEST_ptr(old_rand = RAND_get_rand_method()))
-        return 0;
-
-    fake_rand = *old_rand;
-    /* use own random function */
-    fake_rand.bytes = fbytes;
-    /* set new RAND_METHOD */
-    if (!TEST_true(RAND_set_rand_method(&fake_rand)))
-        return 0;
-    return 1;
-}
-
-static int restore_rand(void)
-{
-    if (!TEST_true(RAND_set_rand_method(old_rand)))
-        return 0;
-    return 1;
-}
-
-static int fbytes(unsigned char *buf, int num)
+static int fbytes(unsigned char *buf, size_t num)
 {
     int ret = 0;
     static int fbytes_counter = 0;
     BIGNUM *tmp = NULL;
 
-    if (use_fake == 0)
-        return old_rand->bytes(buf, num);
-
-    use_fake = 0;
+    fake_rand_set_callback(NULL);
 
     if (!TEST_ptr(tmp = BN_new())
         || !TEST_int_lt(fbytes_counter, OSSL_NELEM(numbers))
@@ -140,13 +110,11 @@ static int x9_62_tests(int n)
         || !TEST_ptr(r = BN_new())
         || !TEST_ptr(s = BN_new())
         || !TEST_true(BN_hex2bn(&r, r_in))
-        || !TEST_true(BN_hex2bn(&s, s_in))
-        /* swap the RNG source */
-        || !TEST_true(change_rand()))
+        || !TEST_true(BN_hex2bn(&s, s_in)))
         goto err;
 
     /* public key must match KAT */
-    use_fake = 1;
+    fake_rand_set_callback(&fbytes);
     if (!TEST_true(EC_KEY_generate_key(key))
         || !TEST_true(p_len = EC_KEY_key2buf(key, POINT_CONVERSION_UNCOMPRESSED,
                                              &pbuf, NULL))
@@ -156,7 +124,7 @@ static int x9_62_tests(int n)
         goto err;
 
     /* create the signature via ECDSA_sign_setup to avoid use of ECDSA nonces */
-    use_fake = 1;
+    fake_rand_set_callback(&fbytes);
     if (!TEST_true(ECDSA_sign_setup(key, NULL, &kinv, &rp))
         || !TEST_ptr(signature = ECDSA_do_sign_ex(digest, dgst_len,
                                                   kinv, rp, key))
@@ -173,10 +141,6 @@ static int x9_62_tests(int n)
     ret = 1;
 
  err:
-    /* restore the RNG source */
-    if (!TEST_true(restore_rand()))
-        ret = 0;
-
     OPENSSL_free(message);
     OPENSSL_free(pbuf);
     OPENSSL_free(qbuf);
@@ -393,11 +357,17 @@ int setup_tests(void)
 #ifdef OPENSSL_NO_EC
     TEST_note("Elliptic curves are disabled.");
 #else
+    fake_rand = fake_rand_start(NULL);
+    if (fake_rand == NULL)
+        return 0;
+
     /* get a list of all internal curves */
     crv_len = EC_get_builtin_curves(NULL, 0);
     if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len))
-        || !TEST_true(EC_get_builtin_curves(curves, crv_len)))
+        || !TEST_true(EC_get_builtin_curves(curves, crv_len))) {
+        fake_rand_finish(fake_rand);
         return 0;
+    }
     ADD_ALL_TESTS(test_builtin_as_ec, crv_len);
 # ifndef OPENSSL_NO_SM2
     ADD_ALL_TESTS(test_builtin_as_sm2, crv_len);
@@ -410,6 +380,7 @@ int setup_tests(void)
 void cleanup_tests(void)
 {
 #ifndef OPENSSL_NO_EC
+    fake_rand_finish(fake_rand);
     OPENSSL_free(curves);
 #endif
 }
diff --git a/test/provider_internal_test.c b/test/provider_internal_test.c
index 4b2b6d5349..fc04d2d925 100644
--- a/test/provider_internal_test.c
+++ b/test/provider_internal_test.c
@@ -26,7 +26,7 @@ static int test_provider(OSSL_PROVIDER *prov, const char *expected_greeting)
     int ret = 0;
 
     ret =
-        TEST_true(ossl_provider_activate(prov))
+        TEST_true(ossl_provider_activate(prov, 0))
         && TEST_true(ossl_provider_get_params(prov, greeting_request))
         && TEST_ptr(greeting = greeting_request[0].data)
         && TEST_size_t_gt(greeting_request[0].data_size, 0)
diff --git a/test/sm2_internal_test.c b/test/sm2_internal_test.c
index 7dae25cf9f..77b76e64f8 100644
--- a/test/sm2_internal_test.c
+++ b/test/sm2_internal_test.c
@@ -28,19 +28,14 @@
 
 # include "crypto/sm2.h"
 
-static RAND_METHOD fake_rand;
-static const RAND_METHOD *saved_rand;
-
+static OSSL_PROVIDER *fake_rand = NULL;
 static uint8_t *fake_rand_bytes = NULL;
 static size_t fake_rand_bytes_offset = 0;
 static size_t fake_rand_size = 0;
 
-static int get_faked_bytes(unsigned char *buf, int num)
+static int get_faked_bytes(unsigned char *buf, size_t num)
 {
-    if (fake_rand_bytes == NULL)
-        return saved_rand->bytes(buf, num);
-
-    if (!TEST_size_t_gt(fake_rand_size, 0))
+    if (!TEST_ptr(fake_rand_bytes) || !TEST_size_t_gt(fake_rand_size, 0))
         return 0;
 
     while (num-- > 0) {
@@ -54,32 +49,24 @@ static int get_faked_bytes(unsigned char *buf, int num)
 
 static int start_fake_rand(const char *hex_bytes)
 {
-    /* save old rand method */
-    if (!TEST_ptr(saved_rand = RAND_get_rand_method()))
-        return 0;
-
-    fake_rand = *saved_rand;
-    /* use own random function */
-    fake_rand.bytes = get_faked_bytes;
-
-    fake_rand_bytes = OPENSSL_hexstr2buf(hex_bytes, NULL);
+    OPENSSL_free(fake_rand_bytes);
     fake_rand_bytes_offset = 0;
     fake_rand_size = strlen(hex_bytes) / 2;
-
-    /* set new RAND_METHOD */
-    if (!TEST_true(RAND_set_rand_method(&fake_rand)))
+    if (!TEST_ptr(fake_rand_bytes = OPENSSL_hexstr2buf(hex_bytes, NULL)))
         return 0;
+
+    /* use own random function */
+    fake_rand_set_callback(get_faked_bytes);
     return 1;
+
 }
 
-static int restore_rand(void)
+static void restore_rand(void)
 {
+    fake_rand_set_callback(NULL);
     OPENSSL_free(fake_rand_bytes);
     fake_rand_bytes = NULL;
     fake_rand_bytes_offset = 0;
-    if (!TEST_true(RAND_set_rand_method(saved_rand)))
-        return 0;
-    return 1;
 }
 
 static EC_GROUP *create_EC_group(const char *p_hex, const char *a_hex,
@@ -375,8 +362,19 @@ int setup_tests(void)
 #ifdef OPENSSL_NO_SM2
     TEST_note("SM2 is disabled.");
 #else
+    fake_rand = fake_rand_start(NULL);
+    if (fake_rand == NULL)
+        return 0;
+
     ADD_TEST(sm2_crypt_test);
     ADD_TEST(sm2_sig_test);
 #endif
     return 1;
 }
+
+void cleanup_tests(void)
+{
+#ifdef OPENSSL_NO_SM2
+    fake_rand_finish(fake_rand);
+#endif
+}
diff --git a/test/testutil.h b/test/testutil.h
index 491082c3f4..93c91a4a41 100644
--- a/test/testutil.h
+++ b/test/testutil.h
@@ -566,6 +566,11 @@ char *glue_strings(const char *list[], size_t *out_len);
 uint32_t test_random(void);
 void test_random_seed(uint32_t sd);
 
+/* Fake non-secure random number generator */
+OSSL_PROVIDER *fake_rand_start(OSSL_LIB_CTX *libctx);
+void fake_rand_finish(OSSL_PROVIDER *p);
+void fake_rand_set_callback(int (*cb)(unsigned char *out, size_t outlen));
+
 /* Create a file path from a directory and a filename */
 char *test_mk_file_path(const char *dir, const char *file);
 
diff --git a/test/testutil/driver.c b/test/testutil/driver.c
index 0b4332b492..467c3e8eb3 100644
--- a/test/testutil/driver.c
+++ b/test/testutil/driver.c
@@ -44,6 +44,8 @@ static int single_test = -1;
 static int single_iter = -1;
 static int level = 0;
 static int seed = 0;
+static int rand_order = 0;
+
 /*
  * A parameterised test runs a loop of test cases.
  * |num_test_cases| counts the total number of test cases
@@ -103,8 +105,12 @@ int setup_test_framework(int argc, char *argv[])
     if (TAP_levels != NULL)
         level = 4 * atoi(TAP_levels);
     test_adjust_streams_tap_level(level);
-    if (test_seed != NULL)
+    if (test_seed != NULL) {
+        rand_order = 1;
         set_seed(atoi(test_seed));
+    } else {
+        set_seed(0);
+    }
 
 #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
     argv = copy_argv(&argc, argv);
@@ -294,7 +300,7 @@ int run_tests(const char *test_prog_name)
 
     for (i = 0; i < num_tests; i++)
         permute[i] = i;
-    if (seed != 0)
+    if (rand_order != 0)
         for (i = num_tests - 1; i >= 1; i--) {
             j = test_random() % (1 + i);
             ii = permute[j];
@@ -340,7 +346,7 @@ int run_tests(const char *test_prog_name)
             }
 
             j = -1;
-            if (seed == 0 || all_tests[i].num < 3)
+            if (rand_order == 0 || all_tests[i].num < 3)
                 jstep = 1;
             else
                 do
diff --git a/test/testutil/fake_random.c b/test/testutil/fake_random.c
new file mode 100644
index 0000000000..95a3023cd4
--- /dev/null
+++ b/test/testutil/fake_random.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * https://www.openssl.org/source/license.html
+ * or in the file LICENSE in the source distribution.
+ */
+
+#include <string.h>
+#include <openssl/core_names.h>
+#include <openssl/rand.h>
+#include <openssl/provider.h>
+#include "../testutil.h"
+
+typedef struct {
+    int (*cb)(unsigned char *out, size_t outlen);
+    int state;
+} FAKE_RAND;
+
+static FAKE_RAND fake_rand;
+
+static OSSL_FUNC_rand_newctx_fn fake_rand_newctx;
+static OSSL_FUNC_rand_freectx_fn fake_rand_freectx;
+static OSSL_FUNC_rand_instantiate_fn fake_rand_instantiate;
+static OSSL_FUNC_rand_uninstantiate_fn fake_rand_uninstantiate;
+static OSSL_FUNC_rand_generate_fn fake_rand_generate;
+static OSSL_FUNC_rand_gettable_ctx_params_fn fake_rand_gettable_ctx_params;
+static OSSL_FUNC_rand_get_ctx_params_fn fake_rand_get_ctx_params;
+static OSSL_FUNC_rand_enable_locking_fn fake_rand_enable_locking;
+
+static void *fake_rand_newctx(void *provctx, void *parent,
+                              const OSSL_DISPATCH *parent_dispatch)
+{
+    fake_rand.cb = NULL;
+    fake_rand.state = EVP_RAND_STATE_UNINITIALISED;
+    return &fake_rand;
+}
+
+static void fake_rand_freectx(void *vrng)
+{
+    FAKE_RAND *frng = (FAKE_RAND *)vrng;
+
+    frng->cb = NULL;
+    frng->state = EVP_RAND_STATE_UNINITIALISED;
+}
+
+static int fake_rand_instantiate(void *vrng, ossl_unused unsigned int strength,
+                                 ossl_unused  int prediction_resistance,
+                                 ossl_unused const unsigned char *pstr,
+                                 size_t pstr_len)
+{
+    FAKE_RAND *frng = (FAKE_RAND *)vrng;
+
+    frng->state = EVP_RAND_STATE_READY;
+    return 1;
+}
+
+static int fake_rand_uninstantiate(void *vrng)
+{
+    FAKE_RAND *frng = (FAKE_RAND *)vrng;
+
+    frng->state = EVP_RAND_STATE_UNINITIALISED;
+    return 1;
+}
+
+static int fake_rand_generate(void *vrng, unsigned char *out, size_t outlen,
+                              unsigned int strength, int prediction_resistance,
+                              const unsigned char *adin, size_t adinlen)
+{
+    FAKE_RAND *frng = (FAKE_RAND *)vrng;
+    size_t l;
+    uint32_t r;
+
+    if (frng->cb != NULL)
+        return (*frng->cb)(out, outlen);
+    while (outlen > 0) {
+        r = test_random();
+        l = outlen < sizeof(r) ? outlen : sizeof(r);
+
+        memcpy(out, &r, l);
+        out += l;
+        outlen -= l;
+    }
+    return 1;
+}
+
+static int fake_rand_enable_locking(void *vrng)
+{
+    return 1;
+}
+
+static int fake_rand_get_ctx_params(ossl_unused void *vrng, OSSL_PARAM params[])
+{
+    FAKE_RAND *frng = (FAKE_RAND *)vrng;
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STATE);
+    if (p != NULL && !OSSL_PARAM_set_int(p, frng->state))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_STRENGTH);
+    if (p != NULL && !OSSL_PARAM_set_int(p, 256))
+        return 0;
+
+    p = OSSL_PARAM_locate(params, OSSL_RAND_PARAM_MAX_REQUEST);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, INT_MAX))
+        return 0;
+    return 1;
+}
+
+static const OSSL_PARAM *fake_rand_gettable_ctx_params(void *vrng)
+{
+    static const OSSL_PARAM known_gettable_ctx_params[] = {
+        OSSL_PARAM_int(OSSL_RAND_PARAM_STATE, NULL),
+        OSSL_PARAM_uint(OSSL_RAND_PARAM_STRENGTH, NULL),
+        OSSL_PARAM_size_t(OSSL_RAND_PARAM_MAX_REQUEST, NULL),
+        OSSL_PARAM_END
+    };
+    return known_gettable_ctx_params;
+}
+
+static const OSSL_DISPATCH fake_rand_functions[] = {
+    { OSSL_FUNC_RAND_NEWCTX, (void (*)(void))fake_rand_newctx },
+    { OSSL_FUNC_RAND_FREECTX, (void (*)(void))fake_rand_freectx },
+    { OSSL_FUNC_RAND_INSTANTIATE, (void (*)(void))fake_rand_instantiate },
+    { OSSL_FUNC_RAND_UNINSTANTIATE, (void (*)(void))fake_rand_uninstantiate },
+    { OSSL_FUNC_RAND_GENERATE, (void (*)(void))fake_rand_generate },
+    { OSSL_FUNC_RAND_ENABLE_LOCKING, (void (*)(void))fake_rand_enable_locking },
+    { OSSL_FUNC_RAND_GETTABLE_CTX_PARAMS,
+      (void(*)(void))fake_rand_gettable_ctx_params },
+    { OSSL_FUNC_RAND_GET_CTX_PARAMS, (void(*)(void))fake_rand_get_ctx_params },
+    { 0, NULL }
+};
+
+static const OSSL_ALGORITHM fake_rand_rand[] = {
+    { "FAKE", "provider=fake", fake_rand_functions },
+    { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM *fake_rand_query(void *provctx,
+                                             int operation_id,
+                                             int *no_cache)
+{
+    *no_cache = 0;
+    switch (operation_id) {
+    case OSSL_OP_RAND:
+        return fake_rand_rand;
+    }
+    return NULL;
+}
+
+/* Functions we provide to the core */
+static const OSSL_DISPATCH fake_rand_method[] = {
+    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_rand_query },
+    { 0, NULL }
+};
+
+static int fake_rand_provider_init(const OSSL_CORE_HANDLE *handle,
+                                   const OSSL_DISPATCH *in,
+                                   const OSSL_DISPATCH **out, void **provctx)
+{
+    if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new()))
+        return 0;
+    *out = fake_rand_method;
+    return 1;
+}
+
+OSSL_PROVIDER *fake_rand_start(OSSL_LIB_CTX *libctx)
+{
+    OSSL_PROVIDER *p;
+
+    if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-rand",
+                                             fake_rand_provider_init))
+            || !TEST_true(RAND_set_DRBG_type(libctx, "fake", NULL, NULL, NULL))
+            || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-rand", 1)))
+        return NULL;
+    return p;
+}
+
+void fake_rand_finish(OSSL_PROVIDER *p)
+{
+    OSSL_PROVIDER_unload(p);
+}
+
+void fake_rand_set_callback(int (*cb)(unsigned char *out, size_t outlen))
+{
+    fake_rand.cb = cb;
+}
+
diff --git a/util/libcrypto.num b/util/libcrypto.num
index a16b6e17eb..25d8619471 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -73,7 +73,7 @@ NETSCAPE_SPKI_print                     74	3_0_0	EXIST::FUNCTION:
 X509_set_pubkey                         75	3_0_0	EXIST::FUNCTION:
 ASN1_item_print                         76	3_0_0	EXIST::FUNCTION:
 CONF_set_nconf                          77	3_0_0	EXIST::FUNCTION:
-RAND_set_rand_method                    78	3_0_0	EXIST::FUNCTION:
+RAND_set_rand_method                    78	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 BN_GF2m_mod_mul                         79	3_0_0	EXIST::FUNCTION:EC2M
 UI_add_input_boolean                    80	3_0_0	EXIST::FUNCTION:
 ASN1_TIME_adj                           81	3_0_0	EXIST::FUNCTION:
@@ -167,7 +167,7 @@ EVP_MD_type                             170	3_0_0	EXIST::FUNCTION:
 EVP_PKCS82PKEY                          171	3_0_0	EXIST::FUNCTION:
 BN_generate_prime_ex                    172	3_0_0	EXIST::FUNCTION:
 EVP_EncryptInit                         173	3_0_0	EXIST::FUNCTION:
-RAND_OpenSSL                            174	3_0_0	EXIST::FUNCTION:
+RAND_OpenSSL                            174	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 BN_uadd                                 175	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_derive_init                    176	3_0_0	EXIST::FUNCTION:
 PEM_write_bio_ASN1_stream               177	3_0_0	EXIST::FUNCTION:
@@ -1397,7 +1397,7 @@ OCSP_RESPBYTES_it                       1429	3_0_0	EXIST::FUNCTION:OCSP
 EVP_aes_192_wrap                        1430	3_0_0	EXIST::FUNCTION:
 OCSP_CERTID_it                          1431	3_0_0	EXIST::FUNCTION:OCSP
 ENGINE_get_RSA                          1432	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0,ENGINE
-RAND_get_rand_method                    1433	3_0_0	EXIST::FUNCTION:
+RAND_get_rand_method                    1433	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 ERR_load_DSA_strings                    1434	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0,DSA
 ASN1_check_infinite_end                 1435	3_0_0	EXIST::FUNCTION:
 i2d_PKCS7_DIGEST                        1436	3_0_0	EXIST::FUNCTION:
@@ -1746,7 +1746,7 @@ NAME_CONSTRAINTS_check                  1786	3_0_0	EXIST::FUNCTION:
 X509_CERT_AUX_it                        1787	3_0_0	EXIST::FUNCTION:
 X509_get_X509_PUBKEY                    1789	3_0_0	EXIST::FUNCTION:
 TXT_DB_create_index                     1790	3_0_0	EXIST::FUNCTION:
-RAND_set_rand_engine                    1791	3_0_0	EXIST::FUNCTION:ENGINE
+RAND_set_rand_engine                    1791	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0,ENGINE
 X509_set_serialNumber                   1792	3_0_0	EXIST::FUNCTION:
 BN_mod_exp_mont_consttime               1793	3_0_0	EXIST::FUNCTION:
 X509V3_parse_list                       1794	3_0_0	EXIST::FUNCTION:
@@ -5301,3 +5301,5 @@ EVP_PKEY_fromdata_settable              ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_param_check_quick              ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_public_check_quick             ?	3_0_0	EXIST::FUNCTION:
 EVP_PKEY_CTX_is_a                       ?	3_0_0	EXIST::FUNCTION:
+RAND_set_DRBG_type                      ?	3_0_0	EXIST::FUNCTION:
+RAND_set_seed_source_type               ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list