Fix a race condition in drbgtest.c
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Tue, 30 Oct 2018 21:21:34 +0000 (22:21 +0100)
committerBernd Edlinger <bernd.edlinger@hotmail.de>
Mon, 5 Nov 2018 22:00:57 +0000 (23:00 +0100)
Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7531)

(cherry picked from commit 2bb1b5ddd12c23bbfa7fb60ee3296612ca943fef)

test/drbgtest.c

index 371f138c7b0d4c04ed7d8463dd23e43829b9a3cc..755f0b314c4fdd4204edaad7ce34dc7ac390ca32 100644 (file)
@@ -572,6 +572,8 @@ static void reset_drbg_hook_ctx(void)
  *       1:  it is expected that the specified DRBG is reseeded
  *       0:  it is expected that the specified DRBG is not reseeded
  *      -1:  don't check whether the specified DRBG was reseeded or not
+ * |reseed_time|: if nonzero, used instead of time(NULL) to set the
+ *                |before_reseed| time.
  */
 static int test_drbg_reseed(int expect_success,
                             RAND_DRBG *master,
@@ -579,7 +581,8 @@ static int test_drbg_reseed(int expect_success,
                             RAND_DRBG *private,
                             int expect_master_reseed,
                             int expect_public_reseed,
-                            int expect_private_reseed
+                            int expect_private_reseed,
+                            time_t reseed_time
                            )
 {
     unsigned char buf[32];
@@ -605,8 +608,11 @@ static int test_drbg_reseed(int expect_success,
      * step 2: generate random output
      */
 
+    if (reseed_time == 0)
+        reseed_time = time(NULL);
+
     /* Generate random output from the public and private DRBG */
-    before_reseed = expect_master_reseed == 1 ? time(NULL) : 0;
+    before_reseed = expect_master_reseed == 1 ? reseed_time : 0;
     if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success)
         || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success))
         return 0;
@@ -673,6 +679,7 @@ static int test_rand_drbg_reseed(void)
     RAND_DRBG *master, *public, *private;
     unsigned char rand_add_buf[256];
     int rv=0;
+    time_t before_reseed;
 
     /* Check whether RAND_OpenSSL() is the default method */
     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
@@ -707,7 +714,7 @@ static int test_rand_drbg_reseed(void)
     /*
      * Test initial seeding of shared DRBGs
      */
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -715,7 +722,7 @@ static int test_rand_drbg_reseed(void)
     /*
      * Test initial state of shared DRBGs
      */
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, 0)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -724,7 +731,7 @@ static int test_rand_drbg_reseed(void)
      * reseed counters differ from the master's reseed counter.
      */
     master->reseed_prop_counter++;
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1, 0)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -734,7 +741,7 @@ static int test_rand_drbg_reseed(void)
      */
     master->reseed_prop_counter++;
     private->reseed_prop_counter++;
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0, 0)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -744,7 +751,7 @@ static int test_rand_drbg_reseed(void)
      */
     master->reseed_prop_counter++;
     public->reseed_prop_counter++;
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1, 0)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -753,10 +760,17 @@ static int test_rand_drbg_reseed(void)
     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
 
     /*
-     * Test whether all three DRBGs are reseeded by RAND_add()
+     * Test whether all three DRBGs are reseeded by RAND_add().
+     * The before_reseed time has to be measured here and passed into the
+     * test_drbg_reseed() test, because the master DRBG gets already reseeded
+     * in RAND_add(), whence the check for the condition
+     * before_reseed <= master->reseed_time will fail if the time value happens
+     * to increase between the RAND_add() and the test_drbg_reseed() call.
      */
+    before_reseed = time(NULL);
     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
-    if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1)))
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1,
+                                    before_reseed)))
         goto error;
     reset_drbg_hook_ctx();
 
@@ -767,7 +781,7 @@ static int test_rand_drbg_reseed(void)
     master_ctx.fail = 1;
     master->reseed_prop_counter++;
     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
-    if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0)))
+    if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0)))
         goto error;
     reset_drbg_hook_ctx();