From: Rich Salz <rsalz@openssl.org>
Date: Sun, 6 Aug 2017 22:12:28 +0000 (-0400)
Subject: Make RAND_DRBG fork-safe
X-Git-Tag: OpenSSL_1_1_1-pre1~886
X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=a35f607c9f9112c649b367d05639394fc1c30771;p=oweals%2Fopenssl.git

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)
---

diff --git a/CHANGES b/CHANGES
index 1582c365a9..ce2d9c565b 100644
--- 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]
 
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;