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 4e1e2ea..fbe75e6 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 ed7824d..192cfd6 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 48d4ace..621f6de 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 42af048..9e0aba8 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;