From: Bernd Edlinger Date: Sun, 14 Oct 2018 10:35:19 +0000 (+0200) Subject: Fix data race in RAND_DRBG_generate X-Git-Tag: OpenSSL_1_1_1a~79 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=1f98527659b8290d442c4e1532452b9ba6463f1e;p=oweals%2Fopenssl.git Fix data race in RAND_DRBG_generate Fixes #7394 Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/7399) (cherry picked from commit a83dc59afa2e0207180d7218efed19b20d48de95) --- diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 27235a7213..f396f83478 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -316,6 +316,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); @@ -343,12 +350,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 0; 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) @@ -423,6 +425,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, @@ -440,12 +450,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg, drbg->state = DRBG_READY; drbg->reseed_gen_counter = 0; 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) @@ -616,8 +621,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; } @@ -689,7 +697,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; @@ -866,7 +875,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent) 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 f0be4f150d..10323a019d 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" @@ -231,7 +232,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);