diff mbox series

[RFC,38/41] random: enable NIST SP800-90B startup tests

Message ID 20200921075857.4424-39-nstange@suse.de (mailing list archive)
State Not Applicable
Delegated to: Herbert Xu
Headers show
Series random: possible ways towards NIST SP800-90B compliance | expand

Commit Message

Nicolai Stange Sept. 21, 2020, 7:58 a.m. UTC
NIST SP800-90B, section 4.3 requires an entropy source to inhibit output
until the so-called "startup" tests have completed. These "startup" test
shall process at least 1024 consecutive samples by means of the continuous
health tests, i.e. the already implemented Repetition Count Test (RCT) and
Adaptive Proportion Test (APT).

Introduce a new field ->warmup to struct health_test. Initialize it to 1024
from health_test_reset(). Make health_test_process() decrement ->warmup
once per event processed without test failure, but reset ->warmup to the
intitial value upon failure. Prevent health_test_process() from returning
health_dispatch as long as ->warmup hasn't dropped to zero. This will cause
the caller, i.e. add_interrupt_randomness(), to not dispatch any entropy to
the global balance until the startup tests have finished.

Note that this change will delay the initial seeding of the primary_crng,
especially for those values of the estimated per-IRQ min-entropy H where
the mimimum of 1024 events from above is by several factors larger than
128/H, the number of events to be processed by a single APT run. That
would only affect systems running with fips_enabled though and there's
simply no way to avoid it without violating the specs.

Signed-off-by: Nicolai Stange <nstange@suse.de>
---
 drivers/char/random.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 54ee082ca4a8..bd8c24e433d0 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -880,6 +880,7 @@  static void discard_queued_entropy(struct entropy_store *r,
 }
 
 struct health_test {
+	unsigned short warmup;
 	unsigned short apt_event_count;
 	union {
 		u32 apt_presearch_bit_counters;
@@ -1059,6 +1060,13 @@  health_test_apt(struct health_test *h, unsigned int event_entropy_shift,
 
 static void health_test_reset(struct health_test *h)
 {
+	/*
+	 * Don't dispatch until at least 1024 events have been
+	 * processed by the continuous health tests as required by
+	 * NIST SP800-90B for the startup tests.
+	 */
+	h->warmup = 1024;
+
 	health_apt_reset(h);
 }
 
@@ -1067,7 +1075,7 @@  health_test_process(struct health_test *h, unsigned int event_entropy_shift,
 		    u8 sample)
 {
 	u8 sample_delta;
-	enum health_result rct;
+	enum health_result rct, apt;
 
 	/*
 	 * The min-entropy estimate has been made for the lower eight
@@ -1083,6 +1091,8 @@  health_test_process(struct health_test *h, unsigned int event_entropy_shift,
 		 * Something is really off, get_cycles() has become
 		 * (or always been) a constant.
 		 */
+		if (h->warmup)
+			health_test_reset(h);
 		return health_discard;
 	}
 
@@ -1091,7 +1101,18 @@  health_test_process(struct health_test *h, unsigned int event_entropy_shift,
 	 * don't care about whether the RCT needs to consume more
 	 * samples to complete.
 	 */
-	return health_test_apt(h, event_entropy_shift, sample_delta);
+	apt = health_test_apt(h, event_entropy_shift, sample_delta);
+	if (unlikely(h->warmup) && --h->warmup) {
+		if (apt == health_discard)
+			health_test_reset(h);
+		/*
+		 * Don't allow the caller to dispatch until warmup
+		 * has completed.
+		 */
+		return apt == health_dispatch ? health_queue : apt;
+	}
+
+	return apt;
 }
 
 struct fast_pool {