Make RAND_DRBG fork-safe
authorRich Salz <rsalz@openssl.org>
Sun, 6 Aug 2017 22:12:28 +0000 (18:12 -0400)
committerRich Salz <rsalz@openssl.org>
Mon, 7 Aug 2017 12:30:28 +0000 (08:30 -0400)
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)

CHANGES
crypto/include/internal/rand_int.h
crypto/init.c
crypto/rand/drbg_lib.c
crypto/rand/rand_lcl.h
crypto/rand/rand_lib.c

diff --git a/CHANGES b/CHANGES
index 1582c365a9ae5c6a4aaddf7eee451daedda5ad53..ce2d9c565b61e8304a9795cd165e7b473df172a0 100644 (file)
--- 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]
 
index 30887c4a7cbff0f799618bdce7ec24fdd95100e4..90b00946a8302150bc272530c66f371aba7bd951 100644 (file)
@@ -18,3 +18,4 @@
 #include <openssl/rand.h>
 
 void rand_cleanup_int(void);
+void rand_fork(void);
index e1ca88f0ca9af569bc2da978598e0054f7915730..fc01c827f38fdcd122021b01806b133484cf743c 100644 (file)
@@ -704,5 +704,6 @@ void OPENSSL_fork_parent(void)
 
 void OPENSSL_fork_child(void)
 {
+    rand_fork();
 }
 #endif
index 935d5c8fd7433e7feab93484d690b68f098293c8..e9502db90d9de9a315fe1f281a29620a3b6148e4 100644 (file)
@@ -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;
 
index 5c7087c97735ee748112c70b75b213593b317125..c96625456df9ff28f42b371998a88861aa571dfd 100644 (file)
@@ -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);
index e76ca2702d908b33e1828fbe5bae40ca0d3ecefc..0810518cc6a027a2c5764bf5fa27ca189df6544f 100644 (file)
@@ -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;