[openssl] master update

Matt Caswell matt at openssl.org
Fri Jun 7 11:57:51 UTC 2019


The branch master has been updated
       via  37ca204b96b036f949b8bc8389c1f8e806e1cbec (commit)
       via  a2f27fd750b9ae62a571a9212c7154889100bdb0 (commit)
       via  4e297b7441a070f9dd557445665365b4377e9498 (commit)
       via  da0d114cd962e89b2614f4707902c404acab7ebd (commit)
      from  bab6046146c4fc8f088c1aaca11598ede7609c04 (commit)


- Log -----------------------------------------------------------------
commit 37ca204b96b036f949b8bc8389c1f8e806e1cbec
Author: Matt Caswell <matt at openssl.org>
Date:   Wed May 29 16:03:57 2019 +0100

    Add documentation for new functions taking an OPENSSL_CTX parameter
    
    Various functions have been added that take an OPENSSL_CTX parameter as
    a result of moving the RAND code into the FIPS module. We document all of
    those functions.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9039)

commit a2f27fd750b9ae62a571a9212c7154889100bdb0
Author: Matt Caswell <matt at openssl.org>
Date:   Fri May 24 16:36:44 2019 +0100

    Move the rand_nonce_lock code into drbg_lib.c
    
    It was previously rand_lib but it makes more sense in drbg_lib.c since
    all the functions that use this lock are only ever called from drbg_lib.c
    
    We add some FIPS_MODE defines in preparation for later moving this code
    into the FIPS module.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9039)

commit 4e297b7441a070f9dd557445665365b4377e9498
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 23 16:51:55 2019 +0100

    Make the rand_crng code OPENSSL_CTX aware
    
    This is in preparation for moving this code inside the FIPS module.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9039)

commit da0d114cd962e89b2614f4707902c404acab7ebd
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 23 14:35:31 2019 +0100

    Convert drbg_lib to use OPENSSL_CTX for its global data
    
    In preparation for moving the RAND code into the FIPS module we make
    drbg_lib.c OPENSSL_CTX aware.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9039)

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

Summary of changes:
 crypto/include/internal/rand_int.h |   1 -
 crypto/init.c                      |   4 +-
 crypto/rand/drbg_lib.c             | 358 ++++++++++++++++++++++++++-----------
 crypto/rand/rand_crng_test.c       | 105 ++++++-----
 crypto/rand/rand_lcl.h             |  18 +-
 crypto/rand/rand_lib.c             | 125 ++++---------
 doc/man3/RAND_DRBG_get0_master.pod |  34 +++-
 doc/man3/RAND_DRBG_new.pod         |  25 ++-
 include/internal/cryptlib.h        |   5 +-
 include/openssl/rand_drbg.h        |   7 +
 test/drbgtest.c                    |  15 +-
 util/libcrypto.num                 |   5 +
 12 files changed, 426 insertions(+), 276 deletions(-)

diff --git a/crypto/include/internal/rand_int.h b/crypto/include/internal/rand_int.h
index b745393..53896ce 100644
--- a/crypto/include/internal/rand_int.h
+++ b/crypto/include/internal/rand_int.h
@@ -24,7 +24,6 @@
 typedef struct rand_pool_st RAND_POOL;
 
 void rand_cleanup_int(void);
-void rand_drbg_cleanup_int(void);
 void drbg_delete_thread_state(void);
 void rand_fork(void);
 
diff --git a/crypto/init.c b/crypto/init.c
index 58fff70..e73c9ba 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -560,9 +560,6 @@ void OPENSSL_cleanup(void)
     OSSL_TRACE(INIT, "OPENSSL_cleanup: rand_cleanup_int()\n");
     rand_cleanup_int();
 
-    OSSL_TRACE(INIT, "OPENSSL_cleanup: rand_drbg_cleanup_int()\n");
-    rand_drbg_cleanup_int();
-
     OSSL_TRACE(INIT, "OPENSSL_cleanup: conf_modules_free_int()\n");
     conf_modules_free_int();
 
@@ -855,5 +852,6 @@ void OPENSSL_fork_parent(void)
 void OPENSSL_fork_child(void)
 {
     rand_fork();
+    /* TODO(3.0): Inform all providers about a fork event */
 }
 #endif
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index fbe75e6..26e2ccb 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -29,49 +29,54 @@
  * a much bigger deal than just re-setting an allocated resource.)
  */
 
-/*
- * The three shared DRBG instances
- *
- * There are three shared DRBG instances: <master>, <public>, and <private>.
- */
 
-/*
- * The <master> DRBG
- *
- * Not used directly by the application, only for reseeding the two other
- * DRBGs. It reseeds itself by pulling either randomness from os entropy
- * sources or by consuming randomness which was added by RAND_add().
- *
- * The <master> DRBG is a global instance which is accessed concurrently by
- * all threads. The necessary locking is managed automatically by its child
- * DRBG instances during reseeding.
- */
-static RAND_DRBG *master_drbg;
-/*
- * The <public> DRBG
- *
- * Used by default for generating random bytes using RAND_bytes().
- *
- * The <public> DRBG is thread-local, i.e., there is one instance per thread.
- */
-static CRYPTO_THREAD_LOCAL public_drbg;
-/*
- * The <private> DRBG
- *
- * Used by default for generating private keys using RAND_priv_bytes()
- *
- * The <private> DRBG is thread-local, i.e., there is one instance per thread.
- */
-static CRYPTO_THREAD_LOCAL private_drbg;
+typedef struct drbg_global_st {
+    /*
+     * The three shared DRBG instances
+     *
+     * There are three shared DRBG instances: <master>, <public>, and <private>.
+     */
 
+    /*
+     * The <master> DRBG
+     *
+     * Not used directly by the application, only for reseeding the two other
+     * DRBGs. It reseeds itself by pulling either randomness from os entropy
+     * sources or by consuming randomness which was added by RAND_add().
+     *
+     * The <master> DRBG is a global instance which is accessed concurrently by
+     * all threads. The necessary locking is managed automatically by its child
+     * DRBG instances during reseeding.
+     */
+    RAND_DRBG *master_drbg;
+    /*
+     * The <public> DRBG
+     *
+     * Used by default for generating random bytes using RAND_bytes().
+     *
+     * The <public> DRBG is thread-local, i.e., there is one instance per
+     * thread.
+     */
+    CRYPTO_THREAD_LOCAL public_drbg;
+    /*
+     * The <private> DRBG
+     *
+     * Used by default for generating private keys using RAND_priv_bytes()
+     *
+     * The <private> DRBG is thread-local, i.e., there is one instance per
+     * thread.
+     */
+    CRYPTO_THREAD_LOCAL private_drbg;
+} DRBG_GLOBAL;
 
+typedef struct drbg_nonce_global_st {
+    CRYPTO_RWLOCK *rand_nonce_lock;
+    int rand_nonce_count;
+} DRBG_NONCE_GLOBAL;
 
 /* NIST SP 800-90A DRBG recommends the use of a personalization string. */
 static const char ossl_pers_string[] = DRBG_DEFAULT_PERS_STRING;
 
-static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
-
-
 #define RAND_DRBG_TYPE_FLAGS    ( \
     RAND_DRBG_FLAG_MASTER | RAND_DRBG_FLAG_PUBLIC | RAND_DRBG_FLAG_PRIVATE )
 
@@ -102,9 +107,10 @@ static const unsigned int rand_drbg_used_flags =
     RAND_DRBG_FLAG_CTR_NO_DF | RAND_DRBG_FLAG_HMAC | RAND_DRBG_TYPE_FLAGS;
 
 
-static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type);
+static RAND_DRBG *drbg_setup(OPENSSL_CTX *ctx, RAND_DRBG *parent, int drbg_type);
 
-static RAND_DRBG *rand_drbg_new(int secure,
+static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
+                                int secure,
                                 int type,
                                 unsigned int flags,
                                 RAND_DRBG *parent);
@@ -142,6 +148,149 @@ static int is_digest(int type)
 }
 
 /*
+ * Initialize the OPENSSL_CTX global DRBGs on first use.
+ * Returns the allocated global data on success or NULL on failure.
+ */
+static void *drbg_ossl_ctx_new(OPENSSL_CTX *libctx)
+{
+    DRBG_GLOBAL *dgbl = OPENSSL_zalloc(sizeof(*dgbl));
+
+    if (dgbl == NULL)
+        return NULL;
+
+    if (!CRYPTO_THREAD_init_local(&dgbl->private_drbg, NULL))
+        goto err1;
+
+    if (!CRYPTO_THREAD_init_local(&dgbl->public_drbg, NULL))
+        goto err2;
+
+    dgbl->master_drbg = drbg_setup(libctx, NULL, RAND_DRBG_TYPE_MASTER);
+    if (dgbl->master_drbg == NULL)
+        goto err3;
+
+    return dgbl;
+
+ err3:
+    CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
+ err2:
+    CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
+ err1:
+    OPENSSL_free(dgbl);
+    return NULL;
+}
+
+static void drbg_ossl_ctx_free(void *vdgbl)
+{
+    DRBG_GLOBAL *dgbl = vdgbl;
+
+    RAND_DRBG_free(dgbl->master_drbg);
+    CRYPTO_THREAD_cleanup_local(&dgbl->private_drbg);
+    CRYPTO_THREAD_cleanup_local(&dgbl->public_drbg);
+
+    OPENSSL_free(dgbl);
+}
+
+static const OPENSSL_CTX_METHOD drbg_ossl_ctx_method = {
+    drbg_ossl_ctx_new,
+    drbg_ossl_ctx_free,
+};
+
+/*
+ * drbg_ossl_ctx_new() calls drgb_setup() which calls rand_drbg_get_nonce()
+ * which needs to get the rand_nonce_lock out of the OPENSSL_CTX...but since
+ * drbg_ossl_ctx_new() hasn't finished running yet we need the rand_nonce_lock
+ * to be in a different global data object. Otherwise we will go into an
+ * infinite recursion loop.
+ */
+static void *drbg_nonce_ossl_ctx_new(OPENSSL_CTX *libctx)
+{
+    DRBG_NONCE_GLOBAL *dngbl = OPENSSL_zalloc(sizeof(*dngbl));
+
+    if (dngbl == NULL)
+        return NULL;
+
+    dngbl->rand_nonce_lock = CRYPTO_THREAD_lock_new();
+    if (dngbl->rand_nonce_lock == NULL) {
+        OPENSSL_free(dngbl);
+        return NULL;
+    }
+
+    return dngbl;
+}
+
+static void drbg_nonce_ossl_ctx_free(void *vdngbl)
+{
+    DRBG_NONCE_GLOBAL *dngbl = vdngbl;
+
+    CRYPTO_THREAD_lock_free(dngbl->rand_nonce_lock);
+
+    OPENSSL_free(dngbl);
+}
+
+static const OPENSSL_CTX_METHOD drbg_nonce_ossl_ctx_method = {
+    drbg_nonce_ossl_ctx_new,
+    drbg_nonce_ossl_ctx_free,
+};
+
+static DRBG_GLOBAL *drbg_get_global(OPENSSL_CTX *libctx)
+{
+    return openssl_ctx_get_data(libctx, OPENSSL_CTX_DRBG_INDEX,
+                                &drbg_ossl_ctx_method);
+}
+
+/* Implements the get_nonce() callback (see RAND_DRBG_set_callbacks()) */
+size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
+                           unsigned char **pout,
+                           int entropy, size_t min_len, size_t max_len)
+{
+    size_t ret = 0;
+    RAND_POOL *pool;
+    DRBG_NONCE_GLOBAL *dngbl
+        = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_DRBG_NONCE_INDEX,
+                               &drbg_nonce_ossl_ctx_method);
+    struct {
+        void *instance;
+        int count;
+    } data;
+
+    if (dngbl == NULL)
+        return 0;
+
+    memset(&data, 0, sizeof(data));
+    pool = rand_pool_new(0, min_len, max_len);
+    if (pool == NULL)
+        return 0;
+
+    if (rand_pool_add_nonce_data(pool) == 0)
+        goto err;
+
+    data.instance = drbg;
+    CRYPTO_atomic_add(&dngbl->rand_nonce_count, 1, &data.count,
+                      dngbl->rand_nonce_lock);
+
+    if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0)
+        goto err;
+
+    ret   = rand_pool_length(pool);
+    *pout = rand_pool_detach(pool);
+
+ err:
+    rand_pool_free(pool);
+
+    return ret;
+}
+
+/*
+ * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks())
+ *
+ */
+void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
+                             unsigned char *out, size_t outlen)
+{
+    OPENSSL_secure_clear_free(out, outlen);
+}
+
+/*
  * Set/initialize |drbg| to be of type |type|, with optional |flags|.
  *
  * If |type| and |flags| are zero, use the defaults
@@ -236,7 +385,8 @@ int RAND_DRBG_set_defaults(int type, unsigned int flags)
  *
  * Returns a pointer to the new DRBG instance on success, NULL on failure.
  */
-static RAND_DRBG *rand_drbg_new(int secure,
+static RAND_DRBG *rand_drbg_new(OPENSSL_CTX *ctx,
+                                int secure,
                                 int type,
                                 unsigned int flags,
                                 RAND_DRBG *parent)
@@ -249,6 +399,7 @@ static RAND_DRBG *rand_drbg_new(int secure,
         return NULL;
     }
 
+    drbg->libctx = ctx;
     drbg->secure = secure && CRYPTO_secure_allocated(drbg);
     drbg->fork_count = rand_fork_count;
     drbg->parent = parent;
@@ -305,16 +456,27 @@ static RAND_DRBG *rand_drbg_new(int secure,
     return NULL;
 }
 
+RAND_DRBG *RAND_DRBG_new_ex(OPENSSL_CTX *ctx, int type, unsigned int flags,
+                            RAND_DRBG *parent)
+{
+    return rand_drbg_new(ctx, 0, type, flags, parent);
+}
+
 RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
 {
-    return rand_drbg_new(0, type, flags, parent);
+    return RAND_DRBG_new_ex(NULL, type, flags, parent);
 }
 
-RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent)
+RAND_DRBG *RAND_DRBG_secure_new_ex(OPENSSL_CTX *ctx, int type,
+                                   unsigned int flags, RAND_DRBG *parent)
 {
-    return rand_drbg_new(1, type, flags, parent);
+    return rand_drbg_new(ctx, 1, type, flags, parent);
 }
 
+RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent)
+{
+    return RAND_DRBG_secure_new_ex(NULL, type, flags, parent);
+}
 /*
  * Uninstantiate |drbg| and free all memory.
  */
@@ -943,12 +1105,12 @@ void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx)
  *
  * Returns a pointer to the new DRBG instance on success, NULL on failure.
  */
-static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type)
+static RAND_DRBG *drbg_setup(OPENSSL_CTX *ctx, RAND_DRBG *parent, int drbg_type)
 {
     RAND_DRBG *drbg;
 
-    drbg = RAND_DRBG_secure_new(rand_drbg_type[drbg_type],
-                                rand_drbg_flags[drbg_type], parent);
+    drbg = RAND_DRBG_secure_new_ex(ctx, rand_drbg_type[drbg_type],
+                                   rand_drbg_flags[drbg_type], parent);
     if (drbg == NULL)
         return NULL;
 
@@ -975,60 +1137,21 @@ err:
     return NULL;
 }
 
-/*
- * Initialize the global DRBGs on first use.
- * Returns 1 on success, 0 on failure.
- */
-DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
-{
-    /*
-     * ensure that libcrypto is initialized, otherwise the
-     * DRBG locks are not cleaned up properly
-     */
-    if (!OPENSSL_init_crypto(0, NULL))
-        return 0;
-
-    if (!CRYPTO_THREAD_init_local(&private_drbg, NULL))
-        return 0;
-
-    if (!CRYPTO_THREAD_init_local(&public_drbg, NULL))
-        goto err1;
-
-    master_drbg = drbg_setup(NULL, RAND_DRBG_TYPE_MASTER);
-    if (master_drbg == NULL)
-        goto err2;
-
-    return 1;
-
-err2:
-    CRYPTO_THREAD_cleanup_local(&public_drbg);
-err1:
-    CRYPTO_THREAD_cleanup_local(&private_drbg);
-    return 0;
-}
-
-/* Clean up the global DRBGs before exit */
-void rand_drbg_cleanup_int(void)
-{
-    if (master_drbg != NULL) {
-        RAND_DRBG_free(master_drbg);
-        master_drbg = NULL;
-
-        CRYPTO_THREAD_cleanup_local(&private_drbg);
-        CRYPTO_THREAD_cleanup_local(&public_drbg);
-    }
-}
-
 void drbg_delete_thread_state(void)
 {
+    /* TODO(3.0): Other PRs will pass the ctx as a param to this function */
+    OPENSSL_CTX *ctx = NULL;
+    DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
     RAND_DRBG *drbg;
 
-    drbg = CRYPTO_THREAD_get_local(&public_drbg);
-    CRYPTO_THREAD_set_local(&public_drbg, NULL);
+    if (dgbl == NULL)
+        return;
+    drbg = CRYPTO_THREAD_get_local(&dgbl->public_drbg);
+    CRYPTO_THREAD_set_local(&dgbl->public_drbg, NULL);
     RAND_DRBG_free(drbg);
 
-    drbg = CRYPTO_THREAD_get_local(&private_drbg);
-    CRYPTO_THREAD_set_local(&private_drbg, NULL);
+    drbg = CRYPTO_THREAD_get_local(&dgbl->private_drbg);
+    CRYPTO_THREAD_set_local(&dgbl->private_drbg, NULL);
     RAND_DRBG_free(drbg);
 }
 
@@ -1180,56 +1303,75 @@ static int drbg_status(void)
  * Returns pointer to the DRBG on success, NULL on failure.
  *
  */
-RAND_DRBG *RAND_DRBG_get0_master(void)
+RAND_DRBG *OPENSSL_CTX_get0_master_drbg(OPENSSL_CTX *ctx)
 {
-    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
+    DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
+
+    if (dgbl == NULL)
         return NULL;
 
-    return master_drbg;
+    return dgbl->master_drbg;
+}
+
+RAND_DRBG *RAND_DRBG_get0_master(void)
+{
+    return OPENSSL_CTX_get0_master_drbg(NULL);
 }
 
 /*
  * Get the public DRBG.
  * Returns pointer to the DRBG on success, NULL on failure.
  */
-RAND_DRBG *RAND_DRBG_get0_public(void)
+RAND_DRBG *OPENSSL_CTX_get0_public_drbg(OPENSSL_CTX *ctx)
 {
+    DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
     RAND_DRBG *drbg;
 
-    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
+    if (dgbl == NULL)
         return NULL;
 
-    drbg = CRYPTO_THREAD_get_local(&public_drbg);
+    drbg = CRYPTO_THREAD_get_local(&dgbl->public_drbg);
     if (drbg == NULL) {
         if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
             return NULL;
-        drbg = drbg_setup(master_drbg, RAND_DRBG_TYPE_PUBLIC);
-        CRYPTO_THREAD_set_local(&public_drbg, drbg);
+        drbg = drbg_setup(ctx, dgbl->master_drbg, RAND_DRBG_TYPE_PUBLIC);
+        CRYPTO_THREAD_set_local(&dgbl->public_drbg, drbg);
     }
     return drbg;
 }
 
+RAND_DRBG *RAND_DRBG_get0_public(void)
+{
+    return OPENSSL_CTX_get0_public_drbg(NULL);
+}
+
 /*
  * Get the private DRBG.
  * Returns pointer to the DRBG on success, NULL on failure.
  */
-RAND_DRBG *RAND_DRBG_get0_private(void)
+RAND_DRBG *OPENSSL_CTX_get0_private_drbg(OPENSSL_CTX *ctx)
 {
+    DRBG_GLOBAL *dgbl = drbg_get_global(ctx);
     RAND_DRBG *drbg;
 
-    if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
+    if (dgbl == NULL)
         return NULL;
 
-    drbg = CRYPTO_THREAD_get_local(&private_drbg);
+    drbg = CRYPTO_THREAD_get_local(&dgbl->private_drbg);
     if (drbg == NULL) {
         if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
             return NULL;
-        drbg = drbg_setup(master_drbg, RAND_DRBG_TYPE_PRIVATE);
-        CRYPTO_THREAD_set_local(&private_drbg, drbg);
+        drbg = drbg_setup(ctx, dgbl->master_drbg, RAND_DRBG_TYPE_PRIVATE);
+        CRYPTO_THREAD_set_local(&dgbl->private_drbg, drbg);
     }
     return drbg;
 }
 
+RAND_DRBG *RAND_DRBG_get0_private(void)
+{
+    return OPENSSL_CTX_get0_private_drbg(NULL);
+}
+
 RAND_METHOD rand_meth = {
     drbg_seed,
     drbg_bytes,
@@ -1241,5 +1383,9 @@ RAND_METHOD rand_meth = {
 
 RAND_METHOD *RAND_OpenSSL(void)
 {
+#ifndef FIPS_MODE
     return &rand_meth;
+#else
+    return NULL;
+#endif
 }
diff --git a/crypto/rand/rand_crng_test.c b/crypto/rand/rand_crng_test.c
index 1b4f167..11d85f3 100644
--- a/crypto/rand/rand_crng_test.c
+++ b/crypto/rand/rand_crng_test.c
@@ -16,64 +16,78 @@
 #include <openssl/evp.h>
 #include "internal/rand_int.h"
 #include "internal/thread_once.h"
+#include "internal/cryptlib.h"
 #include "rand_lcl.h"
 
-static RAND_POOL *crngt_pool;
-static unsigned char crngt_prev[EVP_MAX_MD_SIZE];
+typedef struct crng_test_global_st {
+    unsigned char crngt_prev[EVP_MAX_MD_SIZE];
+    RAND_POOL *crngt_pool;
+} CRNG_TEST_GLOBAL;
 
-int (*crngt_get_entropy)(unsigned char *, unsigned char *, unsigned int *)
+int (*crngt_get_entropy)(OPENSSL_CTX *, unsigned char *, unsigned char *,
+                         unsigned int *)
     = &rand_crngt_get_entropy_cb;
 
-int rand_crngt_get_entropy_cb(unsigned char *buf, unsigned char *md,
-                              unsigned int *md_size)
+static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
 {
-    int r;
-    size_t n;
-    unsigned char *p;
+    CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
 
-    n = rand_pool_acquire_entropy(crngt_pool);
-    if (n >= CRNGT_BUFSIZ) {
-        p = rand_pool_detach(crngt_pool);
-        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL);
-        if (r != 0)
-            memcpy(buf, p, CRNGT_BUFSIZ);
-        rand_pool_reattach(crngt_pool, p);
-        return r;
-    }
-    return 0;
-}
-
-void rand_crngt_cleanup(void)
-{
-    rand_pool_free(crngt_pool);
-    crngt_pool = NULL;
+    rand_pool_free(crngt_glob->crngt_pool);
+    OPENSSL_free(crngt_glob);
 }
 
-int rand_crngt_init(void)
+static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
 {
     unsigned char buf[CRNGT_BUFSIZ];
+    CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
 
-    if ((crngt_pool = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL)
-        return 0;
-    if (crngt_get_entropy(buf, crngt_prev, NULL)) {
+    if (crngt_glob == NULL)
+        return NULL;
+
+    if ((crngt_glob->crngt_pool
+         = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
+        OPENSSL_free(crngt_glob);
+        return NULL;
+    }
+    if (crngt_get_entropy(ctx, buf, crngt_glob->crngt_prev, NULL)) {
         OPENSSL_cleanse(buf, sizeof(buf));
-        return 1;
+        return crngt_glob;
     }
-    rand_crngt_cleanup();
-    return 0;
+    rand_pool_free(crngt_glob->crngt_pool);
+    OPENSSL_free(crngt_glob);
+    return NULL;
 }
 
-static CRYPTO_ONCE rand_crngt_init_flag = CRYPTO_ONCE_STATIC_INIT;
-DEFINE_RUN_ONCE_STATIC(do_rand_crngt_init)
-{
-    return OPENSSL_init_crypto(0, NULL)
-        && rand_crngt_init()
-        && OPENSSL_atexit(&rand_crngt_cleanup);
-}
+static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
+    rand_crng_ossl_ctx_new,
+    rand_crng_ossl_ctx_free,
+};
 
-int rand_crngt_single_init(void)
+int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
+                              unsigned char *buf,
+                              unsigned char *md,
+                              unsigned int *md_size)
 {
-    return RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init);
+    int r;
+    size_t n;
+    unsigned char *p;
+    CRNG_TEST_GLOBAL *crngt_glob
+        = openssl_ctx_get_data(ctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
+                               &rand_crng_ossl_ctx_method);
+
+    if (crngt_glob == NULL)
+        return 0;
+
+    n = rand_pool_acquire_entropy(crngt_glob->crngt_pool);
+    if (n >= CRNGT_BUFSIZ) {
+        p = rand_pool_detach(crngt_glob->crngt_pool);
+        r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL);
+        if (r != 0)
+            memcpy(buf, p, CRNGT_BUFSIZ);
+        rand_pool_reattach(crngt_glob->crngt_pool, p);
+        return r;
+    }
+    return 0;
 }
 
 size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
@@ -86,8 +100,11 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
     RAND_POOL *pool;
     size_t q, r = 0, s, t = 0;
     int attempts = 3;
+    CRNG_TEST_GLOBAL *crngt_glob
+        = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
+                               &rand_crng_ossl_ctx_method);
 
-    if (!RUN_ONCE(&rand_crngt_init_flag, do_rand_crngt_init))
+    if (crngt_glob == NULL)
         return 0;
 
     if ((pool = rand_pool_new(entropy, min_len, max_len)) == NULL)
@@ -95,11 +112,11 @@ size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
 
     while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
         s = q > sizeof(buf) ? sizeof(buf) : q;
-        if (!crngt_get_entropy(buf, md, &sz)
-            || memcmp(crngt_prev, md, sz) == 0
+        if (!crngt_get_entropy(drbg->libctx, buf, md, &sz)
+            || memcmp(crngt_glob->crngt_prev, md, sz) == 0
             || !rand_pool_add(pool, buf, s, s * 8))
             goto err;
-        memcpy(crngt_prev, md, sz);
+        memcpy(crngt_glob->crngt_prev, md, sz);
         t += s;
         attempts++;
     }
diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h
index 3ce5f7a..97126bc 100644
--- a/crypto/rand/rand_lcl.h
+++ b/crypto/rand/rand_lcl.h
@@ -192,6 +192,8 @@ struct rand_pool_st {
  */
 struct rand_drbg_st {
     CRYPTO_RWLOCK *lock;
+    /* The library context this DRBG is associated with, if any */
+    OPENSSL_CTX *libctx;
     RAND_DRBG *parent;
     int secure; /* 1: allocated on the secure heap, 0: otherwise */
     int type; /* the nid of the underlying algorithm */
@@ -334,18 +336,10 @@ int drbg_hmac_init(RAND_DRBG *drbg);
  * Entropy call back for the FIPS 140-2 section 4.9.2 Conditional Tests.
  * These need to be exposed for the unit tests.
  */
-int rand_crngt_get_entropy_cb(unsigned char *buf, unsigned char *md,
-                              unsigned int *md_size);
-extern int (*crngt_get_entropy)(unsigned char *buf, unsigned char *md,
+int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx, unsigned char *buf,
+                              unsigned char *md, unsigned int *md_size);
+extern int (*crngt_get_entropy)(OPENSSL_CTX *ctx, unsigned char *buf,
+                                unsigned char *md,
                                 unsigned int *md_size);
-int rand_crngt_init(void);
-void rand_crngt_cleanup(void);
-
-/*
- * Expose the run once initialisation function for the unit tests because.
- * they need to restart from scratch to validate the first block is skipped
- * properly.
- */
-int rand_crngt_single_init(void);
 
 #endif
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 2b77960..45742f5 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -17,21 +17,20 @@
 #include "rand_lcl.h"
 #include "e_os.h"
 
-#ifndef OPENSSL_NO_ENGINE
+#ifndef FIPS_MODE
+# ifndef OPENSSL_NO_ENGINE
 /* non-NULL if default_RAND_meth is ENGINE-provided */
 static ENGINE *funct_ref;
 static CRYPTO_RWLOCK *rand_engine_lock;
-#endif
+# endif
 static CRYPTO_RWLOCK *rand_meth_lock;
 static const RAND_METHOD *default_RAND_meth;
 static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
 
-int rand_fork_count;
-
-static CRYPTO_RWLOCK *rand_nonce_lock;
-static int rand_nonce_count;
-
 static int rand_inited = 0;
+#endif /* FIPS_MODE */
+
+int rand_fork_count;
 
 #ifdef OPENSSL_RAND_SEED_RDTSC
 /*
@@ -208,56 +207,6 @@ void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
         OPENSSL_secure_clear_free(out, outlen);
 }
 
-
-/*
- * Implements the get_nonce() callback (see RAND_DRBG_set_callbacks())
- *
- */
-size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
-                           unsigned char **pout,
-                           int entropy, size_t min_len, size_t max_len)
-{
-    size_t ret = 0;
-    RAND_POOL *pool;
-
-    struct {
-        void * instance;
-        int count;
-    } data;
-
-    memset(&data, 0, sizeof(data));
-    pool = rand_pool_new(0, min_len, max_len);
-    if (pool == NULL)
-        return 0;
-
-    if (rand_pool_add_nonce_data(pool) == 0)
-        goto err;
-
-    data.instance = drbg;
-    CRYPTO_atomic_add(&rand_nonce_count, 1, &data.count, rand_nonce_lock);
-
-    if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0)
-        goto err;
-
-    ret   = rand_pool_length(pool);
-    *pout = rand_pool_detach(pool);
-
- err:
-    rand_pool_free(pool);
-
-    return ret;
-}
-
-/*
- * Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks())
- *
- */
-void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
-                             unsigned char *out, size_t outlen)
-{
-    OPENSSL_secure_clear_free(out, outlen);
-}
-
 /*
  * Generate additional data that can be used for the drbg. The data does
  * not need to contain entropy, but it's useful if it contains at least
@@ -292,39 +241,32 @@ void rand_fork(void)
     rand_fork_count++;
 }
 
+#ifndef FIPS_MODE
 DEFINE_RUN_ONCE_STATIC(do_rand_init)
 {
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     rand_engine_lock = CRYPTO_THREAD_lock_new();
     if (rand_engine_lock == NULL)
         return 0;
-#endif
+# endif
 
     rand_meth_lock = CRYPTO_THREAD_lock_new();
     if (rand_meth_lock == NULL)
-        goto err1;
-
-    rand_nonce_lock = CRYPTO_THREAD_lock_new();
-    if (rand_nonce_lock == NULL)
-        goto err2;
+        goto err;
 
     if (!rand_pool_init())
-        goto err3;
+        goto err;
 
     rand_inited = 1;
     return 1;
 
-err3:
-    CRYPTO_THREAD_lock_free(rand_nonce_lock);
-    rand_nonce_lock = NULL;
-err2:
+ err:
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
-err1:
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
-#endif
+# endif
     return 0;
 }
 
@@ -339,17 +281,16 @@ void rand_cleanup_int(void)
         meth->cleanup();
     RAND_set_rand_method(NULL);
     rand_pool_cleanup();
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
     CRYPTO_THREAD_lock_free(rand_engine_lock);
     rand_engine_lock = NULL;
-#endif
+# endif
     CRYPTO_THREAD_lock_free(rand_meth_lock);
     rand_meth_lock = NULL;
-    CRYPTO_THREAD_lock_free(rand_nonce_lock);
-    rand_nonce_lock = NULL;
     rand_inited = 0;
 }
 
+/* TODO(3.0): Do we need to handle this somehow in the FIPS module? */
 /*
  * RAND_close_seed_files() ensures that any seed file decriptors are
  * closed after use.
@@ -371,8 +312,6 @@ int RAND_poll(void)
 {
     int ret = 0;
 
-    RAND_POOL *pool = NULL;
-
     const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth == RAND_OpenSSL()) {
@@ -389,6 +328,8 @@ int RAND_poll(void)
         return ret;
 
     } else {
+        RAND_POOL *pool = NULL;
+
         /* fill random pool and seed the current legacy RNG */
         pool = rand_pool_new(RAND_DRBG_STRENGTH,
                              (RAND_DRBG_STRENGTH + 7) / 8,
@@ -406,12 +347,14 @@ int RAND_poll(void)
             goto err;
 
         ret = 1;
+
+     err:
+        rand_pool_free(pool);
     }
 
-err:
-    rand_pool_free(pool);
     return ret;
 }
+#endif /* FIPS_MODE */
 
 /*
  * Allocate memory and initialize a new random pool
@@ -708,23 +651,28 @@ int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
     return 1;
 }
 
+#ifndef FIPS_MODE
 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;
 }
+#endif
 
 const RAND_METHOD *RAND_get_rand_method(void)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     const RAND_METHOD *tmp_meth = NULL;
 
     if (!RUN_ONCE(&rand_init, do_rand_init))
@@ -732,7 +680,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. */
@@ -744,16 +692,17 @@ 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;
+#endif
 }
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
 int RAND_set_rand_engine(ENGINE *engine)
 {
     const RAND_METHOD *tmp_meth = NULL;
@@ -802,9 +751,9 @@ void RAND_add(const void *buf, int num, double randomness)
  */
 int RAND_priv_bytes(unsigned char *buf, int num)
 {
-    const RAND_METHOD *meth = RAND_get_rand_method();
     RAND_DRBG *drbg;
     int ret;
+    const RAND_METHOD *meth = RAND_get_rand_method();
 
     if (meth != RAND_OpenSSL())
         return RAND_bytes(buf, num);
@@ -827,7 +776,7 @@ int RAND_bytes(unsigned char *buf, int num)
     return -1;
 }
 
-#if !OPENSSL_API_1_1_0
+#if !OPENSSL_API_1_1_0 && !defined(FIPS_MODE)
 int RAND_pseudo_bytes(unsigned char *buf, int num)
 {
     const RAND_METHOD *meth = RAND_get_rand_method();
diff --git a/doc/man3/RAND_DRBG_get0_master.pod b/doc/man3/RAND_DRBG_get0_master.pod
index 62f6fdb..77d0ab7 100644
--- a/doc/man3/RAND_DRBG_get0_master.pod
+++ b/doc/man3/RAND_DRBG_get0_master.pod
@@ -2,6 +2,9 @@
 
 =head1 NAME
 
+OPENSSL_CTX_get0_master_drbg,
+OPENSSL_CTX_get0_public_drbg,
+OPENSSL_CTX_get0_private_drbg,
 RAND_DRBG_get0_master,
 RAND_DRBG_get0_public,
 RAND_DRBG_get0_private
@@ -11,6 +14,9 @@ RAND_DRBG_get0_private
 
  #include <openssl/rand_drbg.h>
 
+ RAND_DRBG *OPENSSL_CTX_get0_master_drbg(OPENSSL_CTX *ctx);
+ RAND_DRBG *OPENSSL_CTX_get0_public_drbg(OPENSSL_CTX *ctx);
+ RAND_DRBG *OPENSSL_CTX_get0_private_drbg(OPENSSL_CTX *ctx);
  RAND_DRBG *RAND_DRBG_get0_master(void);
  RAND_DRBG *RAND_DRBG_get0_public(void);
  RAND_DRBG *RAND_DRBG_get0_private(void);
@@ -21,26 +27,35 @@ RAND_DRBG_get0_private
 The default RAND API implementation (RAND_OpenSSL()) utilizes three
 shared DRBG instances which are accessed via the RAND API:
 
-The <public> and <private> DRBG are thread-local instances, which are used
+The I<public> and I<private> DRBG are thread-local instances, which are used
 by RAND_bytes() and RAND_priv_bytes(), respectively.
-The <master> DRBG is a global instance, which is not intended to be used
+The I<master> DRBG is a global instance, which is not intended to be used
 directly, but is used internally to reseed the other two instances.
 
 These functions here provide access to the shared DRBG instances.
 
 =head1 RETURN VALUES
 
-RAND_DRBG_get0_master() returns a pointer to the <master> DRBG instance.
+OPENSSL_CTX_get0_master_drbg() returns a pointer to the I<master> DRBG instance
+for the given OPENSSL_CTX B<ctx>.
 
-RAND_DRBG_get0_public() returns a pointer to the <public> DRBG instance.
+OPENSSL_CTX_get0_public_drbg() returns a pointer to the I<public> DRBG instance
+for the given OPENSSL_CTX B<ctx>.
 
-RAND_DRBG_get0_private() returns a pointer to the <private> DRBG instance.
+OPENSSL_CTX_get0_private_drbg() returns a pointer to the I<private> DRBG instance
+for the given OPENSSL_CTX B<ctx>.
 
+In all the above cases the B<ctx> parameter can
+be NULL in which case the default OPENSSL_CTX is used. RAND_DRBG_get0_master(),
+RAND_DRBG_get0_public() and RAND_DRBG_get0_private() are the same as
+OPENSSL_CTX_get0_master_drbg(), OPENSSL_CTX_get0_public_drbg() and
+OPENSSL_CTX_get0_private_drbg() respectively except that the default OPENSSL_CTX
+is always used.
 
 =head1 NOTES
 
-It is not thread-safe to access the <master> DRBG instance.
-The <public> and <private> DRBG instance can be accessed safely, because
+It is not thread-safe to access the I<master> DRBG instance.
+The I<public> and I<private> DRBG instance can be accessed safely, because
 they are thread-local. Note however, that changes to these two instances
 apply only to the current thread.
 
@@ -65,7 +80,10 @@ L<RAND_DRBG(7)>
 
 =head1 HISTORY
 
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
+The OPENSSL_CTX_get0_master_drbg(), OPENSSL_CTX_get0_public_drbg() and
+OPENSSL_CTX_get0_private_drbg() functions were added in OpenSSL 3.0.
+
+All other RAND_DRBG functions were added in OpenSSL 1.1.1.
 
 =head1 COPYRIGHT
 
diff --git a/doc/man3/RAND_DRBG_new.pod b/doc/man3/RAND_DRBG_new.pod
index 8b73840..3ff98ae 100644
--- a/doc/man3/RAND_DRBG_new.pod
+++ b/doc/man3/RAND_DRBG_new.pod
@@ -2,7 +2,9 @@
 
 =head1 NAME
 
+RAND_DRBG_new_ex,
 RAND_DRBG_new,
+RAND_DRBG_secure_new_ex,
 RAND_DRBG_secure_new,
 RAND_DRBG_set,
 RAND_DRBG_set_defaults,
@@ -15,11 +17,20 @@ RAND_DRBG_free
 
  #include <openssl/rand_drbg.h>
 
+ RAND_DRBG *RAND_DRBG_new_ex(OPENSSL_CTX *ctx,
+                             int type,
+                             unsigned int flags,
+                             RAND_DRBG *parent);
 
  RAND_DRBG *RAND_DRBG_new(int type,
                           unsigned int flags,
                           RAND_DRBG *parent);
 
+ RAND_DRBG *RAND_DRBG_secure_new_ex(OPENSSL_CTX *ctx,
+                                    int type,
+                                    unsigned int flags,
+                                    RAND_DRBG *parent);
+
  RAND_DRBG *RAND_DRBG_secure_new(int type,
                                  unsigned int flags,
                                  RAND_DRBG *parent);
@@ -39,10 +50,13 @@ RAND_DRBG_free
 
 =head1 DESCRIPTION
 
-RAND_DRBG_new() and RAND_DRBG_secure_new()
+RAND_DRBG_new_ex() and RAND_DRBG_secure_new_ex()
 create a new DRBG instance of the given B<type>, allocated from the heap resp.
-the secure heap
-(using OPENSSL_zalloc() resp. OPENSSL_secure_zalloc()).
+the secure heap, for the given OPENSSL_CTX <ctx>
+(using OPENSSL_zalloc() resp. OPENSSL_secure_zalloc()). The <ctx> parameter can
+be NULL in which case the default OPENSSL_CTX is used. RAND_DRBG_new() and
+RAND_DRBG_secure_new() are the same as RAND_DRBG_new_ex() and
+RAND_DRBG_secure_new_ex() except that the default OPENSSL_CTX is always used.
 
 RAND_DRBG_set() initializes the B<drbg> with the given B<type> and B<flags>.
 
@@ -108,8 +122,9 @@ uninstantiated state.
 =head1 RETURN VALUES
 
 
-RAND_DRBG_new() and RAND_DRBG_secure_new() return a pointer to a DRBG
-instance allocated on the heap, resp. secure heap.
+RAND_DRBG_new_ex(), RAND_DRBG_new(), RAND_DRBG_secure_new_ex() and
+RAND_DRBG_secure_new() return a pointer to a DRBG instance allocated on the
+heap, resp. secure heap.
 
 RAND_DRBG_set(),
 RAND_DRBG_instantiate(), and
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 1ce822d..d76f9e1 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -146,7 +146,10 @@ typedef struct ossl_ex_data_global_st {
 # define OPENSSL_CTX_PROPERTY_DEFN_INDEX            2
 # define OPENSSL_CTX_PROPERTY_STRING_INDEX          3
 # define OPENSSL_CTX_NAMEMAP_INDEX                  4
-# define OPENSSL_CTX_MAX_INDEXES                    5
+# define OPENSSL_CTX_DRBG_INDEX                     5
+# define OPENSSL_CTX_DRBG_NONCE_INDEX               6
+# define OPENSSL_CTX_RAND_CRNGT_INDEX               7
+# define OPENSSL_CTX_MAX_INDEXES                    8
 
 typedef struct openssl_ctx_method {
     void *(*new_func)(OPENSSL_CTX *ctx);
diff --git a/include/openssl/rand_drbg.h b/include/openssl/rand_drbg.h
index 32c6dcf..4e99d71 100644
--- a/include/openssl/rand_drbg.h
+++ b/include/openssl/rand_drbg.h
@@ -72,6 +72,10 @@ extern "C" {
 /*
  * Object lifetime functions.
  */
+RAND_DRBG *RAND_DRBG_new_ex(OPENSSL_CTX *ctx, int type, unsigned int flags,
+                            RAND_DRBG *parent);
+RAND_DRBG *RAND_DRBG_secure_new_ex(OPENSSL_CTX *ctx, int type,
+                                   unsigned int flags, RAND_DRBG *parent);
 RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent);
 RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent);
 int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags);
@@ -102,6 +106,9 @@ int RAND_DRBG_set_reseed_defaults(
                                   time_t slave_reseed_time_interval
                                   );
 
+RAND_DRBG *OPENSSL_CTX_get0_master_drbg(OPENSSL_CTX *ctx);
+RAND_DRBG *OPENSSL_CTX_get0_public_drbg(OPENSSL_CTX *ctx);
+RAND_DRBG *OPENSSL_CTX_get0_private_drbg(OPENSSL_CTX *ctx);
 RAND_DRBG *RAND_DRBG_get0_master(void);
 RAND_DRBG *RAND_DRBG_get0_public(void);
 RAND_DRBG *RAND_DRBG_get0_private(void);
diff --git a/test/drbgtest.c b/test/drbgtest.c
index 9e0aba8..618403f 100644
--- a/test/drbgtest.c
+++ b/test/drbgtest.c
@@ -1264,7 +1264,8 @@ static const size_t crngt_num_cases = 6;
 
 static size_t crngt_case, crngt_idx;
 
-static int crngt_entropy_cb(unsigned char *buf, unsigned char *md,
+static int crngt_entropy_cb(OPENSSL_CTX *ctx, unsigned char *buf,
+                            unsigned char *md,
                             unsigned int *md_size)
 {
     size_t i, z;
@@ -1288,19 +1289,16 @@ static int test_crngt(int n)
     size_t ent;
     int res = 0;
     int expect;
+    OPENSSL_CTX *ctx = OPENSSL_CTX_new();
 
-    if (!TEST_true(rand_crngt_single_init()))
-        return 0;
-    rand_crngt_cleanup();
-
-    if (!TEST_ptr(drbg = RAND_DRBG_new(dt->nid, dt->flags, NULL)))
+    if (!TEST_ptr(ctx))
         return 0;
+    if (!TEST_ptr(drbg = RAND_DRBG_new_ex(ctx, dt->nid, dt->flags, NULL)))
+        goto err;
     ent = (drbg->min_entropylen + CRNGT_BUFSIZ - 1) / CRNGT_BUFSIZ;
     crngt_case = n % crngt_num_cases;
     crngt_idx = 0;
     crngt_get_entropy = &crngt_entropy_cb;
-    if (!TEST_true(rand_crngt_init()))
-        goto err;
 #ifndef FIPS_MODE
     if (!TEST_true(RAND_DRBG_set_callbacks(drbg, &rand_crngt_get_entropy,
                                            &rand_crngt_cleanup_entropy,
@@ -1333,6 +1331,7 @@ err:
     uninstantiate(drbg);
     RAND_DRBG_free(drbg);
     crngt_get_entropy = &rand_crngt_get_entropy_cb;
+    OPENSSL_CTX_free(ctx);
     return res;
 }
 
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 28b6bb9..af17aba 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4824,3 +4824,8 @@ OSSL_CMP_MSG_dup                        4768	3_0_0	EXIST::FUNCTION:CMP
 ERR_load_CMP_strings                    4769	3_0_0	EXIST::FUNCTION:CMP
 EVP_MD_CTX_set_params                   4770	3_0_0	EXIST::FUNCTION:
 EVP_MD_CTX_get_params                   4771	3_0_0	EXIST::FUNCTION:
+RAND_DRBG_new_ex                        4772	3_0_0	EXIST::FUNCTION:
+RAND_DRBG_secure_new_ex                 4773	3_0_0	EXIST::FUNCTION:
+OPENSSL_CTX_get0_master_drbg            4774	3_0_0	EXIST::FUNCTION:
+OPENSSL_CTX_get0_public_drbg            4775	3_0_0	EXIST::FUNCTION:
+OPENSSL_CTX_get0_private_drbg           4776	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list