Ignore entropy from RAND_add()/RAND_seed() in FIPS mode

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)
This commit is contained in:
Dr. Matthias St. Pierre 2019-04-11 00:06:37 +02:00
parent c5f7a99645
commit 3a50a8a91a
4 changed files with 40 additions and 2 deletions

View 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

View 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

View 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.

View 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;