From a35f607c9f9112c649b367d05639394fc1c30771 Mon Sep 17 00:00:00 2001 From: Rich Salz Date: Sun, 6 Aug 2017 18:12:28 -0400 Subject: [PATCH] Make RAND_DRBG fork-safe Use atfork to count child forks, and reseed DRBG when the counts don't match. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/4101) --- CHANGES | 5 +++++ crypto/include/internal/rand_int.h | 1 + crypto/init.c | 1 + crypto/rand/drbg_lib.c | 7 ++++++- crypto/rand/rand_lcl.h | 4 ++++ crypto/rand/rand_lib.c | 7 ++++++- 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 1582c365a9..ce2d9c565b 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,11 @@ Changes between 1.1.0f and 1.1.1 [xx XXX xxxx] + *) Add "atfork" functions. If building on a system that without + pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application + requirements. The RAND facility now uses/requires this. + [Rich Salz] + *) Add SHA3. [Andy Polyakov] diff --git a/crypto/include/internal/rand_int.h b/crypto/include/internal/rand_int.h index 30887c4a7c..90b00946a8 100644 --- a/crypto/include/internal/rand_int.h +++ b/crypto/include/internal/rand_int.h @@ -18,3 +18,4 @@ #include void rand_cleanup_int(void); +void rand_fork(void); diff --git a/crypto/init.c b/crypto/init.c index e1ca88f0ca..fc01c827f3 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -704,5 +704,6 @@ void OPENSSL_fork_parent(void) void OPENSSL_fork_child(void) { + rand_fork(); } #endif diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c index 935d5c8fd7..e9502db90d 100644 --- a/crypto/rand/drbg_lib.c +++ b/crypto/rand/drbg_lib.c @@ -72,7 +72,7 @@ RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent) } drbg->size = RANDOMNESS_NEEDED; drbg->randomness = ucp; - + drbg->fork_count = rand_fork_count; drbg->parent = parent; if (RAND_DRBG_set(drbg, type, flags) < 0) goto err; @@ -266,6 +266,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen, return 0; } + if (drbg->fork_count != rand_fork_count) { + drbg->fork_count = rand_fork_count; + drbg->state = DRBG_RESEED; + } + if (drbg->reseed_counter >= drbg->reseed_interval) drbg->state = DRBG_RESEED; diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h index 5c7087c977..c96625456d 100644 --- a/crypto/rand/rand_lcl.h +++ b/crypto/rand/rand_lcl.h @@ -88,6 +88,7 @@ struct rand_drbg_st { CRYPTO_RWLOCK *lock; RAND_DRBG *parent; int nid; /* the underlying algorithm */ + int fork_count; unsigned short flags; /* various external flags */ unsigned short filled; /* @@ -127,6 +128,9 @@ extern RAND_BYTES_BUFFER rand_bytes; extern RAND_DRBG rand_drbg; extern RAND_DRBG priv_drbg; +/* How often we've forked (only incremented in child). */ +extern int rand_fork_count; + /* Hardware-based seeding functions. */ void rand_read_tsc(RAND_poll_fn cb, void *arg); int rand_read_cpu(RAND_poll_fn cb, void *arg); diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c index e76ca2702d..0810518cc6 100644 --- a/crypto/rand/rand_lib.c +++ b/crypto/rand/rand_lib.c @@ -25,6 +25,7 @@ static CRYPTO_RWLOCK *rand_meth_lock; static const RAND_METHOD *default_RAND_meth; static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; RAND_BYTES_BUFFER rand_bytes; +int rand_fork_count; #ifdef OPENSSL_RAND_SEED_RDTSC /* @@ -202,6 +203,11 @@ static void free_drbg(RAND_DRBG *drbg) RAND_DRBG_uninstantiate(drbg); } +void rand_fork() +{ + rand_fork_count++; +} + DEFINE_RUN_ONCE_STATIC(do_rand_init) { int ret = 1; @@ -226,7 +232,6 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init) return ret; } - void rand_cleanup_int(void) { const RAND_METHOD *meth = default_RAND_meth; -- 2.25.1