Fix data race in RAND_DRBG_generate
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Sun, 14 Oct 2018 10:35:19 +0000 (12:35 +0200)
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Sat, 27 Oct 2018 11:04:55 +0000 (13:04 +0200)
Fixes #7394

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7399)

(cherry picked from commit a83dc59afa2e0207180d7218efed19b20d48de95)

crypto/rand/drbg_lib.c
crypto/rand/rand_lcl.h
crypto/rand/rand_lib.c

index 27235a72130f2277ca421ff932985ba506536568..f396f83478bee228822b27f6a7ba33127ed006f7 100644 (file)
@@ -316,6 +316,13 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
         max_entropylen += drbg->max_noncelen;
     }
 
+    drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
+    if (drbg->reseed_next_counter) {
+        drbg->reseed_next_counter++;
+        if(!drbg->reseed_next_counter)
+            drbg->reseed_next_counter = 1;
+    }
+
     if (drbg->get_entropy != NULL)
         entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
                                        min_entropylen, max_entropylen, 0);
@@ -343,12 +350,7 @@ int RAND_DRBG_instantiate(RAND_DRBG *drbg,
     drbg->state = DRBG_READY;
     drbg->reseed_gen_counter = 0;
     drbg->reseed_time = time(NULL);
-    if (drbg->reseed_prop_counter > 0) {
-        if (drbg->parent == NULL)
-            drbg->reseed_prop_counter++;
-        else
-            drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
-    }
+    tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
 
  end:
     if (entropy != NULL && drbg->cleanup_entropy != NULL)
@@ -423,6 +425,14 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
     }
 
     drbg->state = DRBG_ERROR;
+
+    drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
+    if (drbg->reseed_next_counter) {
+        drbg->reseed_next_counter++;
+        if(!drbg->reseed_next_counter)
+            drbg->reseed_next_counter = 1;
+    }
+
     if (drbg->get_entropy != NULL)
         entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
                                        drbg->min_entropylen,
@@ -440,12 +450,7 @@ int RAND_DRBG_reseed(RAND_DRBG *drbg,
     drbg->state = DRBG_READY;
     drbg->reseed_gen_counter = 0;
     drbg->reseed_time = time(NULL);
-    if (drbg->reseed_prop_counter > 0) {
-        if (drbg->parent == NULL)
-            drbg->reseed_prop_counter++;
-        else
-            drbg->reseed_prop_counter = drbg->parent->reseed_prop_counter;
-    }
+    tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
 
  end:
     if (entropy != NULL && drbg->cleanup_entropy != NULL)
@@ -616,8 +621,11 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
             || now - drbg->reseed_time >= drbg->reseed_time_interval)
             reseed_required = 1;
     }
-    if (drbg->reseed_prop_counter > 0 && drbg->parent != NULL) {
-        if (drbg->reseed_prop_counter != drbg->parent->reseed_prop_counter)
+    if (drbg->parent != NULL) {
+        unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
+        if (reseed_counter > 0
+                && tsan_load(&drbg->parent->reseed_prop_counter)
+                   != reseed_counter)
             reseed_required = 1;
     }
 
@@ -689,7 +697,8 @@ int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
                             RAND_DRBG_get_nonce_fn get_nonce,
                             RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
 {
-    if (drbg->state != DRBG_UNINITIALISED)
+    if (drbg->state != DRBG_UNINITIALISED
+            || drbg->parent != NULL)
         return 0;
     drbg->get_entropy = get_entropy;
     drbg->cleanup_entropy = cleanup_entropy;
@@ -866,7 +875,7 @@ static RAND_DRBG *drbg_setup(RAND_DRBG *parent)
         goto err;
 
     /* enable seed propagation */
-    drbg->reseed_prop_counter = 1;
+    tsan_store(&drbg->reseed_prop_counter, 1);
 
     /*
      * Ignore instantiation error to support just-in-time instantiation.
index f0be4f150dd330d8e885ea65cb8d5825e30dca65..10323a019ddc4292666ff1520ed56e082ec19487 100644 (file)
@@ -16,6 +16,7 @@
 # include <openssl/hmac.h>
 # include <openssl/ec.h>
 # include <openssl/rand_drbg.h>
+# include "internal/tsan_assist.h"
 
 # include "internal/numbers.h"
 
@@ -231,7 +232,8 @@ struct rand_drbg_st {
      * is added by RAND_add() or RAND_seed() will have an immediate effect on
      * the output of RAND_bytes() resp. RAND_priv_bytes().
      */
-    unsigned int reseed_prop_counter;
+    TSAN_QUALIFIER unsigned int reseed_prop_counter;
+    unsigned int reseed_next_counter;
 
     size_t seedlen;
     DRBG_STATUS state;
index 29d93a829bf60727daa317f508606fc5385d0755..440c19c2872947e847cf0b2a1e123664c4d310ac 100644 (file)
@@ -174,6 +174,8 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
                                    prediction_resistance,
                                    NULL, 0) != 0)
                 bytes = bytes_needed;
+            drbg->reseed_next_counter
+                = tsan_load(&drbg->parent->reseed_prop_counter);
             rand_drbg_unlock(drbg->parent);
 
             rand_pool_add_end(pool, bytes, 8 * bytes);