diff options
author | Rich Salz <rsalz@openssl.org> | 2017-08-06 18:12:28 -0400 |
---|---|---|
committer | Rich Salz <rsalz@openssl.org> | 2017-08-07 08:30:28 -0400 |
commit | a35f607c9f9112c649b367d05639394fc1c30771 (patch) | |
tree | c27b67822ed2816005cae84502c5b5e2ae6aee14 | |
parent | 99801878c09404e45d8176739d3a555c41b77d0b (diff) |
Make RAND_DRBG fork-safe
Use atfork to count child forks, and reseed DRBG when the counts don't
match.
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/4101)
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | crypto/include/internal/rand_int.h | 1 | ||||
-rw-r--r-- | crypto/init.c | 1 | ||||
-rw-r--r-- | crypto/rand/drbg_lib.c | 7 | ||||
-rw-r--r-- | crypto/rand/rand_lcl.h | 4 | ||||
-rw-r--r-- | crypto/rand/rand_lib.c | 7 |
6 files changed, 23 insertions, 2 deletions
@@ -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 <openssl/rand.h> 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; |