aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRich Salz <rsalz@openssl.org>2017-08-06 18:12:28 -0400
committerRich Salz <rsalz@openssl.org>2017-08-07 08:30:28 -0400
commita35f607c9f9112c649b367d05639394fc1c30771 (patch)
treec27b67822ed2816005cae84502c5b5e2ae6aee14 /crypto
parent99801878c09404e45d8176739d3a555c41b77d0b (diff)
downloadopenssl-a35f607c9f9112c649b367d05639394fc1c30771.tar.gz
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)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/include/internal/rand_int.h1
-rw-r--r--crypto/init.c1
-rw-r--r--crypto/rand/drbg_lib.c7
-rw-r--r--crypto/rand/rand_lcl.h4
-rw-r--r--crypto/rand/rand_lib.c7
5 files changed, 18 insertions, 2 deletions
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;