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 1582c36..ce2d9c5 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 30887c4..90b0094 100644 (file)
@@ -18,3 +18,4 @@
 #include <openssl/rand.h>
 
 void rand_cleanup_int(void);
+void rand_fork(void);
index e1ca88f..fc01c82 100644 (file)
@@ -704,5 +704,6 @@ void OPENSSL_fork_parent(void)
 
 void OPENSSL_fork_child(void)
 {
+    rand_fork();
 }
 #endif
index 935d5c8..e9502db 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 5c7087c..c966254 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 e76ca27..0810518 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;