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)
This commit is contained in:
Rich Salz 2017-08-06 18:12:28 -04:00
parent 99801878c0
commit a35f607c9f
6 changed files with 23 additions and 2 deletions

View file

@ -9,6 +9,11 @@
Changes between 1.1.0f and 1.1.1 [xx XXX xxxx] 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. *) Add SHA3.
[Andy Polyakov] [Andy Polyakov]

View file

@ -18,3 +18,4 @@
#include <openssl/rand.h> #include <openssl/rand.h>
void rand_cleanup_int(void); void rand_cleanup_int(void);
void rand_fork(void);

View file

@ -704,5 +704,6 @@ void OPENSSL_fork_parent(void)
void OPENSSL_fork_child(void) void OPENSSL_fork_child(void)
{ {
rand_fork();
} }
#endif #endif

View file

@ -72,7 +72,7 @@ RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
} }
drbg->size = RANDOMNESS_NEEDED; drbg->size = RANDOMNESS_NEEDED;
drbg->randomness = ucp; drbg->randomness = ucp;
drbg->fork_count = rand_fork_count;
drbg->parent = parent; drbg->parent = parent;
if (RAND_DRBG_set(drbg, type, flags) < 0) if (RAND_DRBG_set(drbg, type, flags) < 0)
goto err; goto err;
@ -266,6 +266,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
return 0; 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) if (drbg->reseed_counter >= drbg->reseed_interval)
drbg->state = DRBG_RESEED; drbg->state = DRBG_RESEED;

View file

@ -88,6 +88,7 @@ struct rand_drbg_st {
CRYPTO_RWLOCK *lock; CRYPTO_RWLOCK *lock;
RAND_DRBG *parent; RAND_DRBG *parent;
int nid; /* the underlying algorithm */ int nid; /* the underlying algorithm */
int fork_count;
unsigned short flags; /* various external flags */ unsigned short flags; /* various external flags */
unsigned short filled; unsigned short filled;
/* /*
@ -127,6 +128,9 @@ extern RAND_BYTES_BUFFER rand_bytes;
extern RAND_DRBG rand_drbg; extern RAND_DRBG rand_drbg;
extern RAND_DRBG priv_drbg; extern RAND_DRBG priv_drbg;
/* How often we've forked (only incremented in child). */
extern int rand_fork_count;
/* Hardware-based seeding functions. */ /* Hardware-based seeding functions. */
void rand_read_tsc(RAND_poll_fn cb, void *arg); void rand_read_tsc(RAND_poll_fn cb, void *arg);
int rand_read_cpu(RAND_poll_fn cb, void *arg); int rand_read_cpu(RAND_poll_fn cb, void *arg);

View file

@ -25,6 +25,7 @@ static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth; static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT; static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
RAND_BYTES_BUFFER rand_bytes; RAND_BYTES_BUFFER rand_bytes;
int rand_fork_count;
#ifdef OPENSSL_RAND_SEED_RDTSC #ifdef OPENSSL_RAND_SEED_RDTSC
/* /*
@ -202,6 +203,11 @@ static void free_drbg(RAND_DRBG *drbg)
RAND_DRBG_uninstantiate(drbg); RAND_DRBG_uninstantiate(drbg);
} }
void rand_fork()
{
rand_fork_count++;
}
DEFINE_RUN_ONCE_STATIC(do_rand_init) DEFINE_RUN_ONCE_STATIC(do_rand_init)
{ {
int ret = 1; int ret = 1;
@ -226,7 +232,6 @@ DEFINE_RUN_ONCE_STATIC(do_rand_init)
return ret; return ret;
} }
void rand_cleanup_int(void) void rand_cleanup_int(void)
{ {
const RAND_METHOD *meth = default_RAND_meth; const RAND_METHOD *meth = default_RAND_meth;