[openssl-commits] [openssl] master update

matthias.st.pierre at ncp-e.com matthias.st.pierre at ncp-e.com
Mon Mar 19 14:04:59 UTC 2018


The branch master has been updated
       via  440bce8f813fa661437ce52378c3df38e2fd073b (commit)
       via  16cfc2c90d9e7776965db07c1f31bbec2f6c41e3 (commit)
       via  7caf122e717e79afcb986fe217e77a630b67bf4c (commit)
      from  4e6647506331fc3b3ef5b23e5dbe188279ddd575 (commit)


- Log -----------------------------------------------------------------
commit 440bce8f813fa661437ce52378c3df38e2fd073b
Author: Kurt Roeckx <kurt at roeckx.be>
Date:   Sun Mar 11 15:19:13 2018 +0100

    Add a multithread rand test
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
    (Merged from https://github.com/openssl/openssl/pull/5547)

commit 16cfc2c90d9e7776965db07c1f31bbec2f6c41e3
Author: Kurt Roeckx <kurt at roeckx.be>
Date:   Thu Mar 8 22:30:28 2018 +0100

    Don't use a ssl specific DRBG anymore
    
    Since the public and private DRBG are per thread we don't need one
    per ssl object anymore. It could also try to get entropy from a DRBG
    that's really from an other thread because the SSL object moved to an
    other thread.
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
    (Merged from https://github.com/openssl/openssl/pull/5547)

commit 7caf122e717e79afcb986fe217e77a630b67bf4c
Author: Kurt Roeckx <kurt at roeckx.be>
Date:   Wed Mar 7 19:25:55 2018 +0100

    Make the public and private DRBG thread local
    
    This avoids lock contention.
    
    Reviewed-by: Tim Hudson <tjh at openssl.org>
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
    (Merged from https://github.com/openssl/openssl/pull/5547)

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

Summary of changes:
 crypto/evp/e_aes.c                     | 22 ++-------
 crypto/evp/e_aes_cbc_hmac_sha1.c       | 15 ++----
 crypto/evp/e_aes_cbc_hmac_sha256.c     | 15 ++----
 crypto/evp/e_aria.c                    | 11 ++---
 crypto/evp/e_des.c                     |  8 +--
 crypto/evp/e_des3.c                    | 13 +----
 crypto/evp/evp_enc.c                   | 14 +-----
 crypto/evp/evp_locl.h                  |  1 -
 crypto/evp/p_seal.c                    | 13 ++---
 crypto/include/internal/cryptlib_int.h |  2 +
 crypto/include/internal/rand_int.h     |  1 +
 crypto/init.c                          | 16 ++++++
 crypto/rand/drbg_lib.c                 | 87 +++++++++++++++++++++------------
 crypto/rand/rand_lib.c                 |  3 --
 doc/man3/EVP_EncryptInit.pod           | 14 ------
 include/openssl/evp.h                  |  2 -
 ssl/record/ssl3_record.c               |  2 +-
 ssl/s3_enc.c                           |  1 -
 ssl/s3_lib.c                           |  6 +--
 ssl/ssl_lib.c                          | 37 --------------
 ssl/ssl_locl.h                         |  2 -
 ssl/ssl_sess.c                         |  2 +-
 ssl/statem/statem_clnt.c               |  7 ++-
 ssl/statem/statem_srvr.c               |  9 ++--
 ssl/t1_enc.c                           |  1 -
 ssl/tls13_enc.c                        |  1 -
 ssl/tls_srp.c                          |  4 +-
 test/drbgtest.c                        | 89 ++++++++++++++++++++++++++++++++++
 28 files changed, 200 insertions(+), 198 deletions(-)

diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 2421385..1d5007a 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -17,7 +17,6 @@
 #include "internal/evp_int.h"
 #include "modes_lcl.h"
 #include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
 #include "evp_locl.h"
 
 typedef struct {
@@ -1405,14 +1404,8 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
             memcpy(gctx->iv, ptr, arg);
 
         enc = EVP_CIPHER_CTX_encrypting(c);
-        if (enc) {
-            if (c->drbg != NULL) {
-                if (RAND_DRBG_bytes(c->drbg, gctx->iv + arg, gctx->ivlen - arg) == 0)
-                    return 0;
-            } else if (RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) {
-                return 0;
-            }
-        }
+        if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
+            return 0;
 
         gctx->iv_gen = 1;
         return 1;
@@ -2639,14 +2632,9 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
             return 0;
         if (arg)
             memcpy(gctx->iv, ptr, arg);
-        if (EVP_CIPHER_CTX_encrypting(c)) {
-            if (c->drbg != NULL) {
-                if (RAND_DRBG_bytes(c->drbg, gctx->iv + arg, gctx->ivlen - arg) == 0)
-                    return 0;
-            } else if (RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) {
-                return 0;
-            }
-        }
+        if (EVP_CIPHER_CTX_encrypting(c)
+            && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
+            return 0;
         gctx->iv_gen = 1;
         return 1;
 
diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c
index ac564a2..09d24dc 100644
--- a/crypto/evp/e_aes_cbc_hmac_sha1.c
+++ b/crypto/evp/e_aes_cbc_hmac_sha1.c
@@ -17,11 +17,9 @@
 #include <openssl/aes.h>
 #include <openssl/sha.h>
 #include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
 #include "modes_lcl.h"
 #include "internal/evp_int.h"
 #include "internal/constant_time_locl.h"
-#include "evp_locl.h"
 
 typedef struct {
     AES_KEY ks;
@@ -156,8 +154,7 @@ void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
 static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key,
                                          unsigned char *out,
                                          const unsigned char *inp,
-                                         size_t inp_len, int n4x,
-                                         RAND_DRBG *drbg)
+                                         size_t inp_len, int n4x)
 {                               /* n4x is 1 or 2 */
     HASH_DESC hash_d[8], edges[8];
     CIPH_DESC ciph_d[8];
@@ -177,13 +174,8 @@ static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key,
 #  endif
 
     /* ask for IVs in bulk */
-    IVs = blocks[0].c;
-    if (drbg != NULL) {
-        if (RAND_DRBG_bytes(drbg, IVs, 16 * x4) == 0)
-            return 0;
-    } else if (RAND_bytes(IVs, 16 * x4) <= 0) {
+    if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0)
         return 0;
-    }
 
     ctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */
 
@@ -901,8 +893,7 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
 
             return (int)tls1_1_multi_block_encrypt(key, param->out,
                                                    param->inp, param->len,
-                                                   param->interleave / 4,
-                                                   ctx->drbg);
+                                                   param->interleave / 4);
         }
     case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT:
 # endif
diff --git a/crypto/evp/e_aes_cbc_hmac_sha256.c b/crypto/evp/e_aes_cbc_hmac_sha256.c
index e752d30..caac0c9 100644
--- a/crypto/evp/e_aes_cbc_hmac_sha256.c
+++ b/crypto/evp/e_aes_cbc_hmac_sha256.c
@@ -18,11 +18,9 @@
 #include <openssl/aes.h>
 #include <openssl/sha.h>
 #include <openssl/rand.h>
-#include <openssl/rand_drbg.h>
 #include "modes_lcl.h"
 #include "internal/constant_time_locl.h"
 #include "internal/evp_int.h"
-#include "evp_locl.h"
 
 typedef struct {
     AES_KEY ks;
@@ -152,8 +150,7 @@ void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int);
 static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA256 *key,
                                          unsigned char *out,
                                          const unsigned char *inp,
-                                         size_t inp_len, int n4x,
-                                         RAND_DRBG *drbg)
+                                         size_t inp_len, int n4x)
 {                               /* n4x is 1 or 2 */
     HASH_DESC hash_d[8], edges[8];
     CIPH_DESC ciph_d[8];
@@ -173,13 +170,8 @@ static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA256 *key,
 #  endif
 
     /* ask for IVs in bulk */
-    IVs = blocks[0].c;
-    if (drbg != NULL) {
-        if (RAND_DRBG_bytes(drbg, IVs, 16 * x4) == 0)
-            return 0;
-    } else if (RAND_bytes(IVs, 16 * x4) <= 0) {
+    if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0)
         return 0;
-    }
 
     /* align */
     ctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32));
@@ -885,8 +877,7 @@ static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
 
             return (int)tls1_1_multi_block_encrypt(key, param->out,
                                                    param->inp, param->len,
-                                                   param->interleave / 4,
-                                                   ctx->drbg);
+                                                   param->interleave / 4);
         }
     case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT:
 # endif
diff --git a/crypto/evp/e_aria.c b/crypto/evp/e_aria.c
index 9c1036b..ffd9530 100644
--- a/crypto/evp/e_aria.c
+++ b/crypto/evp/e_aria.c
@@ -302,14 +302,9 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
             return 0;
         if (arg)
             memcpy(gctx->iv, ptr, arg);
-        if (EVP_CIPHER_CTX_encrypting(c)) {
-            if (c->drbg != NULL) {
-                if (RAND_DRBG_bytes(c->drbg, gctx->iv + arg, gctx->ivlen - arg) == 0)
-                    return 0;
-            } else if (RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) {
-                return 0;
-            }
-        }
+        if (EVP_CIPHER_CTX_encrypting(c)
+            && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
+            return 0;
         gctx->iv_gen = 1;
         return 1;
 
diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c
index 3b4b714..9b2facf 100644
--- a/crypto/evp/e_des.c
+++ b/crypto/evp/e_des.c
@@ -15,8 +15,6 @@
 # include "internal/evp_int.h"
 # include <openssl/des.h>
 # include <openssl/rand.h>
-# include <openssl/rand_drbg.h>
-# include "evp_locl.h"
 
 typedef struct {
     union {
@@ -231,12 +229,8 @@ static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
 
     switch (type) {
     case EVP_CTRL_RAND_KEY:
-        if (c->drbg != NULL) {
-            if (RAND_DRBG_bytes(c->drbg, ptr, 8) == 0)
-                return 0;
-        } else if (RAND_bytes(ptr, 8) <= 0) {
+        if (RAND_bytes(ptr, 8) <= 0)
             return 0;
-        }
         DES_set_odd_parity((DES_cblock *)ptr);
         return 1;
 
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
index b8fe42c..da77936 100644
--- a/crypto/evp/e_des3.c
+++ b/crypto/evp/e_des3.c
@@ -15,7 +15,6 @@
 # include "internal/evp_int.h"
 # include <openssl/des.h>
 # include <openssl/rand.h>
-# include <openssl/rand_drbg.h>
 # include "evp_locl.h"
 
 typedef struct {
@@ -284,12 +283,8 @@ static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 
     switch (type) {
     case EVP_CTRL_RAND_KEY:
-        if (ctx->drbg != NULL) {
-            if (RAND_DRBG_bytes(ctx->drbg, ptr, EVP_CIPHER_CTX_key_length(ctx)) == 0)
-                return 0;
-        } else if (RAND_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) {
+        if (RAND_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0)
             return 0;
-        }
         DES_set_odd_parity(deskey);
         if (EVP_CIPHER_CTX_key_length(ctx) >= 16)
             DES_set_odd_parity(deskey + 1);
@@ -377,12 +372,8 @@ static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out,
     memcpy(out + inl + 8, sha1tmp, 8);
     OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH);
     /* Generate random IV */
-    if (ctx->drbg != NULL) {
-        if (RAND_DRBG_bytes(ctx->drbg, EVP_CIPHER_CTX_iv_noconst(ctx), 8) == 0)
-            return -1;
-    } else if (RAND_bytes(EVP_CIPHER_CTX_iv_noconst(ctx), 8) <= 0) {
+    if (RAND_bytes(EVP_CIPHER_CTX_iv_noconst(ctx), 8) <= 0)
         return -1;
-    }
     memcpy(out, EVP_CIPHER_CTX_iv_noconst(ctx), 8);
     /* Encrypt everything after IV in place */
     des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8);
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 9832e56..cc71043 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -579,14 +579,6 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 {
     int ret;
 
-    if (type == EVP_CTRL_GET_DRBG) {
-        *(RAND_DRBG **)ptr = ctx->drbg;
-        return 1;
-    }
-    if (type == EVP_CTRL_SET_DRBG) {
-        ctx->drbg = ptr;
-        return 1;
-    }
     if (!ctx->cipher) {
         EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
         return 0;
@@ -610,12 +602,8 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 {
     if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
         return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
-    if (ctx->drbg) {
-        if (RAND_DRBG_bytes(ctx->drbg, key, ctx->key_len) == 0)
-            return 0;
-    } else if (RAND_bytes(key, ctx->key_len) <= 0) {
+    if (RAND_bytes(key, ctx->key_len) <= 0)
         return 0;
-    }
     return 1;
 }
 
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 82b9433..209577b 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -39,7 +39,6 @@ struct evp_cipher_ctx_st {
     int final_used;
     int block_mask;
     unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
-    RAND_DRBG *drbg;
 } /* EVP_CIPHER_CTX */ ;
 
 int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
diff --git a/crypto/evp/p_seal.c b/crypto/evp/p_seal.c
index 7318793..50ea602 100644
--- a/crypto/evp/p_seal.c
+++ b/crypto/evp/p_seal.c
@@ -14,8 +14,6 @@
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include <openssl/x509.h>
-#include <openssl/rand_drbg.h>
-#include "evp_locl.h"
 
 int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
                  unsigned char **ek, int *ekl, unsigned char *iv,
@@ -33,14 +31,9 @@ int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
         return 1;
     if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
         return 0;
-    if (EVP_CIPHER_CTX_iv_length(ctx)) {
-        if (ctx->drbg) {
-            if (RAND_DRBG_bytes(ctx->drbg, iv, EVP_CIPHER_CTX_iv_length(ctx)) == 0)
-                return 0;
-        } else if (RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0) {
-            return 0;
-        }
-    }
+    if (EVP_CIPHER_CTX_iv_length(ctx)
+        && RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0)
+        return 0;
 
     if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
         return 0;
diff --git a/crypto/include/internal/cryptlib_int.h b/crypto/include/internal/cryptlib_int.h
index 3dddf08..6335517 100644
--- a/crypto/include/internal/cryptlib_int.h
+++ b/crypto/include/internal/cryptlib_int.h
@@ -14,6 +14,7 @@
 struct thread_local_inits_st {
     int async;
     int err_state;
+    int rand;
 };
 
 int ossl_init_thread_start(uint64_t opts);
@@ -28,5 +29,6 @@ int ossl_init_thread_start(uint64_t opts);
 /* OPENSSL_INIT_THREAD flags */
 # define OPENSSL_INIT_THREAD_ASYNC           0x01
 # define OPENSSL_INIT_THREAD_ERR_STATE       0x02
+# define OPENSSL_INIT_THREAD_RAND            0x04
 
 void ossl_malloc_setup_failures(void);
diff --git a/crypto/include/internal/rand_int.h b/crypto/include/internal/rand_int.h
index 27ca703..5db2425 100644
--- a/crypto/include/internal/rand_int.h
+++ b/crypto/include/internal/rand_int.h
@@ -25,6 +25,7 @@ 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);
 
 /* Hardware-based seeding functions. */
diff --git a/crypto/init.c b/crypto/init.c
index 4a88e9c..cc3da4f 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -352,6 +352,14 @@ static void ossl_init_thread_stop(struct thread_local_inits_st *locals)
         err_delete_thread_state();
     }
 
+    if (locals->rand) {
+#ifdef OPENSSL_INIT_DEBUG
+        fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
+                        "drbg_delete_thread_state()\n");
+#endif
+        drbg_delete_thread_state();
+    }
+
     OPENSSL_free(locals);
 }
 
@@ -389,6 +397,14 @@ int ossl_init_thread_start(uint64_t opts)
         locals->err_state = 1;
     }
 
+    if (opts & OPENSSL_INIT_THREAD_RAND) {
+#ifdef OPENSSL_INIT_DEBUG
+        fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
+                        "marking thread for rand\n");
+#endif
+        locals->rand = 1;
+    }
+
     return 1;
 }
 
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 360ea7c..723f630 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -14,6 +14,7 @@
 #include "rand_lcl.h"
 #include "internal/thread_once.h"
 #include "internal/rand_int.h"
+#include "internal/cryptlib_int.h"
 
 /*
  * Support framework for NIST SP 800-90A DRBG, AES-CTR mode.
@@ -40,18 +41,6 @@
  * sources or by consuming randomnes which was added by RAND_add()
  */
 static RAND_DRBG *drbg_master;
-/*
- * THE PUBLIC DRBG
- *
- * Used by default for generating random bytes using RAND_bytes().
- */
-static RAND_DRBG *drbg_public;
-/*
- * THE PRIVATE DRBG
- *
- * Used by default for generating private keys using RAND_priv_bytes()
- */
-static RAND_DRBG *drbg_private;
 /*+
  * DRBG HIERARCHY
  *
@@ -112,6 +101,8 @@ static RAND_DRBG *drbg_private;
 static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG";
 
 static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_THREAD_LOCAL private_drbg_thread_local_key;
+static CRYPTO_THREAD_LOCAL public_drbg_thread_local_key;
 
 
 
@@ -236,13 +227,18 @@ static RAND_DRBG *rand_drbg_new(int secure,
     if (RAND_DRBG_set(drbg, type, flags) == 0)
         goto err;
 
-    if (parent != NULL && drbg->strength > parent->strength) {
-        /*
-         * We currently don't support the algorithm from NIST SP 800-90C
-         * 10.1.2 to use a weaker DRBG as source
-         */
-        RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK);
-        goto err;
+    if (parent != NULL) {
+        rand_drbg_lock(parent);
+        if (drbg->strength > parent->strength) {
+            /*
+             * We currently don't support the algorithm from NIST SP 800-90C
+             * 10.1.2 to use a weaker DRBG as source
+             */
+            rand_drbg_unlock(parent);
+            RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK);
+            goto err;
+        }
+        rand_drbg_unlock(parent);
     }
 
     if (!RAND_DRBG_set_callbacks(drbg, rand_drbg_get_entropy,
@@ -900,7 +896,8 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent)
     if (drbg == NULL)
         return NULL;
 
-    if (rand_drbg_enable_locking(drbg) == 0)
+    /* Only the master DRBG needs to have a lock */
+    if (parent == NULL && rand_drbg_enable_locking(drbg) == 0)
         goto err;
 
     /* enable seed propagation */
@@ -928,6 +925,8 @@ err:
  */
 DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
 {
+    int ret = 1;
+
     /*
      * ensure that libcrypto is initialized, otherwise the
      * DRBG locks are not cleaned up properly
@@ -935,11 +934,14 @@ DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
     if (!OPENSSL_init_crypto(0, NULL))
         return 0;
 
+    ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);
+
     drbg_master = drbg_setup(NULL);
-    drbg_public = drbg_setup(drbg_master);
-    drbg_private = drbg_setup(drbg_master);
 
-    if (drbg_master == NULL || drbg_public == NULL || drbg_private == NULL)
+    ret &= CRYPTO_THREAD_init_local(&private_drbg_thread_local_key, NULL);
+    ret &= CRYPTO_THREAD_init_local(&public_drbg_thread_local_key, NULL);
+
+    if (drbg_master == NULL || ret == 0)
         return 0;
 
     return 1;
@@ -948,11 +950,22 @@ DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
 /* Clean up the global DRBGs before exit */
 void rand_drbg_cleanup_int(void)
 {
-    RAND_DRBG_free(drbg_private);
-    RAND_DRBG_free(drbg_public);
     RAND_DRBG_free(drbg_master);
+    drbg_master = NULL;
 
-    drbg_private = drbg_public = drbg_master = NULL;
+    CRYPTO_THREAD_cleanup_local(&private_drbg_thread_local_key);
+    CRYPTO_THREAD_cleanup_local(&public_drbg_thread_local_key);
+}
+
+void drbg_delete_thread_state()
+{
+    RAND_DRBG *drbg;
+
+    drbg = CRYPTO_THREAD_get_local(&public_drbg_thread_local_key);
+    RAND_DRBG_free(drbg);
+
+    drbg = CRYPTO_THREAD_get_local(&private_drbg_thread_local_key);
+    RAND_DRBG_free(drbg);
 }
 
 /* Implements the default OpenSSL RAND_bytes() method */
@@ -964,9 +977,7 @@ static int drbg_bytes(unsigned char *out, int count)
     if (drbg == NULL)
         return 0;
 
-    rand_drbg_lock(drbg);
     ret = RAND_DRBG_bytes(drbg, out, count);
-    rand_drbg_unlock(drbg);
 
     return ret;
 }
@@ -1042,10 +1053,18 @@ RAND_DRBG *RAND_DRBG_get0_master(void)
  */
 RAND_DRBG *RAND_DRBG_get0_public(void)
 {
+    RAND_DRBG *drbg;
+
     if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
         return NULL;
 
-    return drbg_public;
+    drbg = CRYPTO_THREAD_get_local(&public_drbg_thread_local_key);
+    if (drbg == NULL) {
+        ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);
+        drbg = drbg_setup(drbg_master);
+        CRYPTO_THREAD_set_local(&public_drbg_thread_local_key, drbg);
+    }
+    return drbg;
 }
 
 /*
@@ -1054,10 +1073,18 @@ RAND_DRBG *RAND_DRBG_get0_public(void)
  */
 RAND_DRBG *RAND_DRBG_get0_private(void)
 {
+    RAND_DRBG *drbg;
+
     if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
         return NULL;
 
-    return drbg_private;
+    drbg = CRYPTO_THREAD_get_local(&private_drbg_thread_local_key);
+    if (drbg == NULL) {
+        ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND);
+        drbg = drbg_setup(drbg_master);
+        CRYPTO_THREAD_set_local(&private_drbg_thread_local_key, drbg);
+    }
+    return drbg;
 }
 
 RAND_METHOD rand_meth = {
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index dfffb84..defa3ec 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -826,10 +826,7 @@ int RAND_priv_bytes(unsigned char *buf, int num)
     if (drbg == NULL)
         return 0;
 
-    /* We have to lock the DRBG before generating bits from it. */
-    rand_drbg_lock(drbg);
     ret = RAND_DRBG_bytes(drbg, buf, num);
-    rand_drbg_unlock(drbg);
     return ret;
 }
 
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index b1b51cb..030b010 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -457,20 +457,6 @@ This call is only valid when decrypting data.
 
 =back
 
-=head1 Random numbers
-
-The following can be used to select the DRBG that is used to generate the random
-numbers:
-
-EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_DRBG, 0, drbg)
-
-The following can be used to get the DRBG:
-
-EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_DRBG, 0, &drbg)
-
-By default it's set to NULL which results in RAND_bytes() being used.
-
-
 =head1 NOTES
 
 Where possible the B<EVP> interface to symmetric ciphers should be used in
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 29fd3e2..328587d 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -347,8 +347,6 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
 # define         EVP_CTRL_SET_PIPELINE_INPUT_BUFS        0x23
 /* Set the input buffer lengths to use for a pipelined operation */
 # define         EVP_CTRL_SET_PIPELINE_INPUT_LENS        0x24
-# define         EVP_CTRL_GET_DRBG                       0x25
-# define         EVP_CTRL_SET_DRBG                       0x26
 
 /* Padding modes */
 #define EVP_PADDING_PKCS7       1
diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c
index fa902f3..c21a478 100644
--- a/ssl/record/ssl3_record.c
+++ b/ssl/record/ssl3_record.c
@@ -972,7 +972,7 @@ int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
                         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
                                  ERR_R_INTERNAL_ERROR);
                         return -1;
-                    } else if (ssl_randbytes(s, recs[ctr].input, ivlen) <= 0) {
+                    } else if (RAND_bytes(recs[ctr].input, ivlen) <= 0) {
                         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS1_ENC,
                                  ERR_R_INTERNAL_ERROR);
                         return -1;
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 966d498..d6a08de 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -168,7 +168,6 @@ int ssl3_change_cipher_state(SSL *s, int which)
              */
             EVP_CIPHER_CTX_reset(s->enc_write_ctx);
         }
-        EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, EVP_CTRL_SET_DRBG, 0, s->drbg);
         dd = s->enc_write_ctx;
         if (ssl_replace_hash(&s->write_hash, m) == NULL) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHANGE_CIPHER_STATE,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index f230b5f..bbf49a2 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -4524,12 +4524,12 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, size_t len,
         unsigned char *p = result;
 
         l2n(Time, p);
-        ret = ssl_randbytes(s, p, len - 4);
+        ret = RAND_bytes(p, len - 4);
     } else {
-        ret = ssl_randbytes(s, result, len);
+        ret = RAND_bytes(result, len);
     }
 #ifndef OPENSSL_NO_TLS13DOWNGRADE
-    if (ret) {
+    if (ret > 0) {
         if (!ossl_assert(sizeof(tls11downgrade) < len)
                 || !ossl_assert(sizeof(tls12downgrade) < len))
              return 0;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index cd972ae..e423331 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -690,20 +690,6 @@ SSL *SSL_new(SSL_CTX *ctx)
         goto err;
     }
 
-    /*
-     * If not using the standard RAND (say for fuzzing), then don't use a
-     * chained DRBG.
-     */
-    if (RAND_get_rand_method() == RAND_OpenSSL()) {
-        s->drbg =
-            RAND_DRBG_new(0, 0, RAND_DRBG_get0_public());
-        if (s->drbg == NULL
-            || RAND_DRBG_instantiate(s->drbg,
-                                     (const unsigned char *) SSL_version_str,
-                                     sizeof(SSL_version_str) - 1) == 0)
-            goto err;
-    }
-
     RECORD_LAYER_init(&s->rlayer, s);
 
     s->options = ctx->options;
@@ -1220,7 +1206,6 @@ void SSL_free(SSL *s)
     sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
 #endif
 
-    RAND_DRBG_free(s->drbg);
     CRYPTO_THREAD_lock_free(s->lock);
 
     OPENSSL_free(s);
@@ -5397,28 +5382,6 @@ uint32_t SSL_get_max_early_data(const SSL *s)
     return s->max_early_data;
 }
 
-int ssl_randbytes(SSL *s, unsigned char *rnd, size_t size)
-{
-    if (s->drbg != NULL) {
-        /*
-         * Currently, it's the duty of the caller to serialize the generate
-         * requests to the DRBG. So formally we have to check whether
-         * s->drbg->lock != NULL and take the lock if this is the case.
-         * However, this DRBG is unique to a given SSL object, and we already
-         * require that SSL objects are only accessed by a single thread at
-         * a given time. Also, SSL DRBGs have no child DRBG, so there is
-         * no risk that this DRBG is accessed by a child DRBG in parallel
-         * for reseeding.  As such, we can rely on the application's
-         * serialization of SSL accesses for the needed concurrency protection
-         * here.
-         */
-        return RAND_DRBG_bytes(s->drbg, rnd, size);
-    }
-    if (size > INT_MAX)
-        return 0;
-    return RAND_bytes(rnd, size);
-}
-
 __owur unsigned int ssl_get_max_send_fragment(const SSL *ssl)
 {
     /* Return any active Max Fragment Len extension */
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 4b8482a..83a0334 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1407,7 +1407,6 @@ struct ssl_st {
     size_t block_padding;
 
     CRYPTO_RWLOCK *lock;
-    RAND_DRBG *drbg;
 };
 
 /*
@@ -2238,7 +2237,6 @@ __owur int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags);
 __owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
                                    int ref);
 
-__owur int ssl_randbytes(SSL *s, unsigned char *buf, size_t num);
 __owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other);
 __owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid,
                             void *other);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 6513bf8..2dd5456 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -295,7 +295,7 @@ static int def_generate_session_id(SSL *ssl, unsigned char *id,
 {
     unsigned int retry = 0;
     do
-        if (ssl_randbytes(ssl, id, *id_len) <= 0)
+        if (RAND_bytes(id, *id_len) <= 0)
             return 0;
     while (SSL_has_matching_session_id(ssl, id, *id_len) &&
            (++retry < MAX_SESS_ID_ATTEMPTS)) ;
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index d770706..86cf5b6 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1188,8 +1188,7 @@ int tls_construct_client_hello(SSL *s, WPACKET *pkt)
             s->tmp_session_id_len = sess_id_len;
             session_id = s->tmp_session_id;
             if (s->hello_retry_request == SSL_HRR_NONE
-                    && ssl_randbytes(s, s->tmp_session_id,
-                                     sess_id_len) <= 0) {
+                    && RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                          SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
                          ERR_R_INTERNAL_ERROR);
@@ -2925,7 +2924,7 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
     pms[0] = s->client_version >> 8;
     pms[1] = s->client_version & 0xff;
     /* TODO(size_t): Convert this function */
-    if (ssl_randbytes(s, pms + 2, (int)(pmslen - 2)) <= 0) {
+    if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
                  ERR_R_MALLOC_FAILURE);
         goto err;
@@ -3146,7 +3145,7 @@ static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
         /* Generate session key
          * TODO(size_t): Convert this function
          */
-        || ssl_randbytes(s, pms, (int)pmslen) <= 0) {
+        || RAND_bytes(pms, (int)pmslen) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
                  ERR_R_INTERNAL_ERROR);
         goto err;
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index c198aa7..8826b7f 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -2737,7 +2737,7 @@ int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
             OPENSSL_free(s->pha_context);
             s->pha_context_len = 32;
             if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL
-                    || ssl_randbytes(s, s->pha_context, s->pha_context_len) <= 0
+                    || RAND_bytes(s->pha_context, s->pha_context_len) <= 0
                     || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                          SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
@@ -2926,7 +2926,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
      * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
      */
 
-    if (ssl_randbytes(s, rand_premaster_secret,
+    if (RAND_bytes(rand_premaster_secret,
                       sizeof(rand_premaster_secret)) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
                  ERR_R_INTERNAL_ERROR);
@@ -3692,7 +3692,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
             /* SSLfatal() already called */
             goto err;
         }
-        if (ssl_randbytes(s, age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
+        if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                      SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
                      ERR_R_INTERNAL_ERROR);
@@ -3758,7 +3758,6 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
                  SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
         goto err;
     }
-    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_DRBG, 0, s->drbg);
 
     p = senc;
     if (!i2d_SSL_SESSION(s->session, &p)) {
@@ -3830,7 +3829,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
         const EVP_CIPHER *cipher = EVP_aes_256_cbc();
 
         iv_len = EVP_CIPHER_iv_length(cipher);
-        if (ssl_randbytes(s, iv, iv_len) <= 0
+        if (RAND_bytes(iv, iv_len) <= 0
                 || !EVP_EncryptInit_ex(ctx, cipher, NULL,
                                        tctx->ext.tick_aes_key, iv)
                 || !HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key,
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index a138b60..58d5e25 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -171,7 +171,6 @@ int tls1_change_cipher_state(SSL *s, int which)
                      ERR_R_MALLOC_FAILURE);
             goto err;
         }
-        EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, EVP_CTRL_SET_DRBG, 0, s->drbg);
         dd = s->enc_write_ctx;
         if (SSL_IS_DTLS(s)) {
             mac_ctx = EVP_MD_CTX_new();
diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c
index 7f43958..a793e0c 100644
--- a/ssl/tls13_enc.c
+++ b/ssl/tls13_enc.c
@@ -407,7 +407,6 @@ int tls13_change_cipher_state(SSL *s, int which)
                          SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
-            EVP_CIPHER_CTX_ctrl(s->enc_write_ctx, EVP_CTRL_SET_DRBG, 0, s->drbg);
         }
         ciph_ctx = s->enc_write_ctx;
         iv = s->write_iv;
diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c
index d732328..87614cb 100644
--- a/ssl/tls_srp.c
+++ b/ssl/tls_srp.c
@@ -157,7 +157,7 @@ int SSL_srp_server_param_with_username(SSL *s, int *ad)
         (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
         return SSL3_AL_FATAL;
 
-    if (ssl_randbytes(s, b, sizeof(b)) <= 0)
+    if (RAND_bytes(b, sizeof(b)) <= 0)
         return SSL3_AL_FATAL;
     s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
     OPENSSL_cleanse(b, sizeof(b));
@@ -369,7 +369,7 @@ int SRP_Calc_A_param(SSL *s)
 {
     unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
 
-    if (ssl_randbytes(s, rnd, sizeof(rnd)) <= 0)
+    if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
         return 0;
     s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
     OPENSSL_cleanse(rnd, sizeof(rnd));
diff --git a/test/drbgtest.c b/test/drbgtest.c
index 4c872f8..ca8a211 100644
--- a/test/drbgtest.c
+++ b/test/drbgtest.c
@@ -17,6 +17,10 @@
 #include <openssl/aes.h>
 #include "../crypto/rand/rand_lcl.h"
 
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
 #include "testutil.h"
 #include "drbgtest.h"
 
@@ -762,6 +766,88 @@ error:
     return rv;
 }
 
+#if defined(OPENSSL_THREADS)
+
+static void run_multi_thread_test(void)
+{
+    unsigned char buf[256];
+    time_t start = time(NULL);
+    RAND_DRBG *public, *private;
+
+    public = RAND_DRBG_get0_public();
+    private = RAND_DRBG_get0_private();
+    RAND_DRBG_set_reseed_time_interval(public, 1);
+    RAND_DRBG_set_reseed_time_interval(private, 1);
+
+    do {
+        RAND_bytes(buf, sizeof(buf));
+        RAND_priv_bytes(buf, sizeof(buf));
+    }
+    while(time(NULL) - start < 5);
+}
+
+# if defined(OPENSSL_SYS_WINDOWS)
+
+typedef HANDLE thread_t;
+
+static DWORD WINAPI thread_run(LPVOID arg)
+{
+    run_multi_thread_test();
+    return 0;
+}
+
+static int run_thread(thread_t *t)
+{
+    *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
+    return *t != NULL;
+}
+
+static int wait_for_thread(thread_t thread)
+{
+    return WaitForSingleObject(thread, INFINITE) == 0;
+}
+
+# else
+
+typedef pthread_t thread_t;
+
+static void *thread_run(void *arg)
+{
+    run_multi_thread_test();
+    return NULL;
+}
+
+static int run_thread(thread_t *t)
+{
+    return pthread_create(t, NULL, thread_run, NULL) == 0;
+}
+
+static int wait_for_thread(thread_t thread)
+{
+    return pthread_join(thread, NULL) == 0;
+}
+
+# endif
+
+/*
+ * The main thread will also run the test, so we'll have THREADS+1 parallel
+ * tests running
+ */
+#define THREADS 3
+
+static int test_multi_thread(void)
+{
+    thread_t t[THREADS];
+    int i;
+
+    for (i = 0; i < THREADS; i++)
+        run_thread(&t[i]);
+    run_multi_thread_test();
+    for (i = 0; i < THREADS; i++)
+        wait_for_thread(t[i]);
+    return 1;
+}
+#endif
 
 int setup_tests(void)
 {
@@ -770,5 +856,8 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test));
     ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test));
     ADD_TEST(test_rand_reseed);
+#if defined(OPENSSL_THREADS)
+    ADD_TEST(test_multi_thread);
+#endif
     return 1;
 }


More information about the openssl-commits mailing list