From a83dc59afa2e0207180d7218efed19b20d48de95 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Sun, 14 Oct 2018 12:35:19 +0200 Subject: [PATCH] Fix data race in RAND_DRBG_generate Fixes #7394 Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/7399) --- crypto/rand/drbg_lib.c | 41 +++++++++++++++++++++++++---------------- crypto/rand/rand_lcl.h | 4 +++- crypto/rand/rand_lib.c | 2 ++ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 9d920cb39a..ec4aa69db5 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -374,6 +374,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, max_entropylen += drbg->max_noncelen; } + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + if (drbg->get_entropy != NULL) entropylen = drbg->get_entropy(drbg, &entropy, min_entropy, min_entropylen, max_entropylen, 0); @@ -401,12 +408,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 1; drbg->reseed_time = time(NULL); - if (drbg->reseed_prop_counter > 0) { - if (drbg->parent == NULL) - drbg->reseed_prop_counter++; - else - drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter; - } + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); end: if (entropy != NULL && drbg->cleanup_entropy != NULL) @@ -498,6 +500,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, } drbg->state = DRBG_ERROR; + + drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter); + if (drbg->reseed_next_counter) { + drbg->reseed_next_counter++; + if(!drbg->reseed_next_counter) + drbg->reseed_next_counter = 1; + } + if (drbg->get_entropy != NULL) entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength, drbg->min_entropylen, @@ -515,12 +525,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 1; drbg->reseed_time = time(NULL); - if (drbg->reseed_prop_counter > 0) { - if (drbg->parent == NULL) - drbg->reseed_prop_counter++; - else - drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter; - } + tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter); end: if (entropy != NULL && drbg->cleanup_entropy != NULL) @@ -691,8 +696,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, || now - drbg->reseed_time >= drbg->reseed_time_interval) reseed_required = 1; } - if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) { - if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter) + if (drbg->parent != NULL) { + unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter); + if (reseed_counter > 0 + && tsan_load(&drbg->parent->reseed_prop_counter) + != reseed_counter) reseed_required = 1; } @@ -764,7 +772,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg, RAND_DRBG_get_nonce_fn get_nonce, RAND_DRBG_cleanup_nonce_fn cleanup_nonce) { - if (drbg->state != DRBG_UNINITIALISED) + if (drbg->state != DRBG_UNINITIALISED + || drbg->parent != NULL) return 0; drbg->get_entropy = get_entropy; drbg->cleanup_entropy = cleanup_entropy; @@ -942,7 +951,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent, int drbg_type) goto err; /* enable seed propagation */ - drbg->reseed_prop_counter = 1; + tsan_store(&drbg->reseed_prop_counter, 1); /* * Ignore instantiation error to support just-in-time instantiation. diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 9004809a8b..8abca4c290 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -16,6 +16,7 @@ # include # include # include +# include "internal/tsan_assist.h" # include "internal/numbers.h" @@ -258,7 +259,8 @@ struct rand_drbg_st { * is added by RAND_add() or RAND_seed() will have an immediate effect on * the output of RAND_bytes() resp. RAND_priv_bytes(). */ - unsigned int reseed_prop_counter; + TSAN_QUALIFIER unsigned int reseed_prop_counter; + unsigned int reseed_next_counter; size_t seedlen; DRBG_STATUS state; diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index 29d93a829b..440c19c287 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -174,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg, prediction_resistance, NULL, 0) != 0) bytes = bytes_needed; + drbg->reseed_next_counter + = tsan_load(&drbg->parent->reseed_prop_counter); rand_drbg_unlock(drbg->parent); rand_pool_add_end(pool, bytes, 8 * bytes); -- 2.25.1