Ignore entropy from RAND_add()/RAND_seed() in FIPS mode
authorDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Wed, 10 Apr 2019 22:06:37 +0000 (00:06 +0200)
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Fri, 10 May 2019 05:22:05 +0000 (07:22 +0200)
The functions RAND_add() and RAND_seed() provide a legacy API which
enables the application to seed the CSPRNG.

But NIST SP-800-90A clearly mandates that entropy *shall not* be provided
by the consuming application, neither for instantiation, nor for reseeding.

The provided random data will be mixed into the DRBG state as additional
data only, and no entropy will accounted for it.

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

crypto/rand/drbg_lib.c
doc/man3/RAND_add.pod
doc/man7/RAND_DRBG.pod
test/drbgtest.c

index 4e1e2ea5e06441ff9f13eafec35376b2cea380a8..fbe75e66cb22145c28f365df55b2120215ef647f 100644 (file)
@@ -1101,6 +1101,17 @@ static int drbg_add(const void *buf, int num, double randomness)
 
     buflen = (size_t)num;
 
+#ifdef FIPS_MODE
+    /*
+     * NIST SP-800-90A mandates that entropy *shall not* be provided
+     * by the consuming application. By setting the randomness to zero,
+     * we ensure that the buffer contents will be added to the internal
+     * state of the DRBG only as additional data.
+     *
+     * (NIST SP-800-90Ar1, Sections 9.1 and 9.2)
+     */
+    randomness = 0.0;
+#endif
     if (buflen < seedlen || randomness < (double) seedlen) {
 #if defined(OPENSSL_RAND_SEED_NONE)
         /*
@@ -1117,7 +1128,7 @@ static int drbg_add(const void *buf, int num, double randomness)
         return ret;
 #else
         /*
-         * If an os entropy source is avaible then we declare the buffer content
+         * If an os entropy source is available then we declare the buffer content
          * as additional data by setting randomness to zero and trigger a regular
          * reseeding.
          */
@@ -1125,7 +1136,6 @@ static int drbg_add(const void *buf, int num, double randomness)
 #endif
     }
 
-
     if (randomness > (double)seedlen) {
         /*
          * The purpose of this check is to bound |randomness| by a
index ed7824db7fd05937e59d7f02bd33ece8601ab7a6..192cfd618758c8d346c68d342c304ad58b76979c 100644 (file)
@@ -55,6 +55,11 @@ The content of B<buf> cannot be recovered from subsequent random generator outpu
 Applications that intend to save and restore random state in an external file
 should consider using L<RAND_load_file(3)> instead.
 
+NOTE: In FIPS mode, random data provided by the application is not considered to
+be a trusted entropy source. It is mixed into the internal state of the RNG as
+additional data only and this does not count as a full reseed.
+For more details, see L<RAND_DRBG(7)>.
+
 RAND_seed() is equivalent to RAND_add() with B<randomness> set to B<num>.
 
 RAND_keep_random_devices_open() is used to control file descriptor
@@ -86,6 +91,7 @@ L<RAND_bytes(3)>,
 L<RAND_egd(3)>,
 L<RAND_load_file(3)>,
 L<RAND(7)>
+L<RAND_DRBG(7)>
 
 =head1 HISTORY
 
index 48d4ace09c86caa1a495a30d668e46631cfd681c..621f6ded5a34a515948db7738bd8a9b526420117 100644 (file)
@@ -264,6 +264,13 @@ from the trusted entropy sources.
 
 =back
 
+NOTE: Manual reseeding is *not allowed* in FIPS mode, because
+NIST SP-800-90A mandates that entropy *shall not* be provided by the
+consuming application, neither for instantiation, nor for reseeding.
+[NIST SP 800-90Ar1, Sections 9.1 and 9.2]. For that reason the B<randomness>
+argument is ignored and the random bytes provided by the L<RAND_add(3)> and
+L<RAND_seed(3)> calls are treated as additional data.
+
 =head2 Reseeding the master DRBG with automatic seeding disabled
 
 Calling RAND_poll() will always fail.
index 42af048699e30ea2579ee781818477945d29b31f..9e0aba83ab54d8e138748861027ecec41031b051 100644 (file)
@@ -802,6 +802,7 @@ static int test_rand_drbg_reseed(void)
     /* fill 'randomness' buffer with some arbitrary data */
     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
 
+#ifndef FIPS_MODE
     /*
      * Test whether all three DRBGs are reseeded by RAND_add().
      * The before_reseed time has to be measured here and passed into the
@@ -827,6 +828,20 @@ static int test_rand_drbg_reseed(void)
     if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0)))
         goto error;
     reset_drbg_hook_ctx();
+#else /* FIPS_MODE */
+    /*
+     * In FIPS mode, random data provided by the application via RAND_add()
+     * is not considered a trusted entropy source. It is only treated as
+     * additional_data and no reseeding is forced. This test assures that
+     * no reseeding occurs.
+     */
+    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, 0, 0, 0,
+                                    before_reseed)))
+        goto error;
+    reset_drbg_hook_ctx();
+#endif
 
     rv = 1;