aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/rand/drbg_lib.c8
-rw-r--r--crypto/rand/rand_lib.c17
-rw-r--r--ssl/ssl_lib.c17
3 files changed, 38 insertions, 4 deletions
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 0042a931b0..c471b6eda4 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -116,6 +116,8 @@ void RAND_DRBG_free(RAND_DRBG *drbg)
/*
* Instantiate |drbg|, after it has been initialized. Use |pers| and
* |perslen| as prediction-resistance input.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
*/
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
const unsigned char *pers, size_t perslen)
@@ -185,6 +187,8 @@ end:
/*
* Uninstantiate |drbg|. Must be instantiated before it can be used.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
*/
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
{
@@ -197,6 +201,8 @@ int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
/*
* Reseed |drbg|, mixing in the specified data
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
*/
int RAND_DRBG_reseed(RAND_DRBG *drbg,
const unsigned char *adin, size_t adinlen)
@@ -349,6 +355,8 @@ int rand_drbg_restart(RAND_DRBG *drbg,
* to or if |prediction_resistance| is set. Additional input can be
* sent in |adin| and |adinlen|.
*
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
* Returns 1 on success, 0 on failure.
*
*/
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 6f8deca1f9..a290e5c1a2 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -155,12 +155,20 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
if (buffer != NULL) {
size_t bytes = 0;
- /* Get entropy from parent, include our state as additional input */
+ /*
+ * Get random from parent, include our state as additional input.
+ * Our lock is already held, but we need to lock our parent before
+ * generating bits from it.
+ */
+ if (drbg->parent->lock)
+ CRYPTO_THREAD_write_lock(drbg->parent->lock);
if (RAND_DRBG_generate(drbg->parent,
buffer, bytes_needed,
0,
(unsigned char *)drbg, sizeof(*drbg)) != 0)
bytes = bytes_needed;
+ if (drbg->parent->lock)
+ CRYPTO_THREAD_unlock(drbg->parent->lock);
entropy_available = RAND_POOL_add_end(pool, bytes, 8 * bytes);
}
@@ -626,6 +634,7 @@ int RAND_priv_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
RAND_DRBG *drbg;
+ int ret;
if (meth != RAND_OpenSSL())
return RAND_bytes(buf, num);
@@ -634,7 +643,11 @@ int RAND_priv_bytes(unsigned char *buf, int num)
if (drbg == NULL)
return 0;
- return RAND_DRBG_generate(drbg, buf, num, 0, NULL, 0);
+ /* We have to lock the DRBG before generating bits from it. */
+ CRYPTO_THREAD_write_lock(drbg->lock);
+ ret = RAND_DRBG_generate(drbg, buf, num, 0, NULL, 0);
+ CRYPTO_THREAD_unlock(drbg->lock);
+ return ret;
}
int RAND_bytes(unsigned char *buf, int num)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index da74e96ecb..ce45a91613 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -5127,7 +5127,20 @@ uint32_t SSL_get_max_early_data(const SSL *s)
int ssl_randbytes(SSL *s, unsigned char *rnd, size_t size)
{
- if (s->drbg != NULL)
- return RAND_DRBG_generate(s->drbg, rnd, size, 0, NULL, 0);
+ 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_generate(s->drbg, rnd, size, 0, NULL, 0);
+ }
return RAND_bytes(rnd, (int)size);
}