From: Nicolai Stange <nstange@suse.de>
To: "Theodore Y. Ts'o" <tytso@mit.edu>
Cc: linux-crypto@vger.kernel.org, LKML <linux-kernel@vger.kernel.org>,
"Arnd Bergmann" <arnd@arndb.de>,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
"Alexander E. Patrakov" <patrakov@gmail.com>,
"Ahmed S. Darwish" <darwish.07@gmail.com>,
"Willy Tarreau" <w@1wt.eu>,
"Matthew Garrett" <mjg59@srcf.ucam.org>,
"Vito Caputo" <vcaputo@pengaru.com>,
"Andreas Dilger" <adilger.kernel@dilger.ca>,
"Jan Kara" <jack@suse.cz>, "Ray Strode" <rstrode@redhat.com>,
"William Jon McCann" <mccann@jhu.edu>,
zhangjs <zachary@baishancloud.com>,
"Andy Lutomirski" <luto@kernel.org>,
"Florian Weimer" <fweimer@redhat.com>,
"Lennart Poettering" <mzxreary@0pointer.de>,
"Peter Matthias" <matthias.peter@bsi.bund.de>,
"Marcelo Henrique Cerri" <marcelo.cerri@canonical.com>,
"Roman Drahtmueller" <draht@schaltsekun.de>,
"Neil Horman" <nhorman@redhat.com>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Julia Lawall" <julia.lawall@inria.fr>,
"Dan Carpenter" <dan.carpenter@oracle.com>,
"Andy Lavr" <andy.lavr@gmail.com>,
"Eric Biggers" <ebiggers@kernel.org>,
"Jason A. Donenfeld" <Jason@zx2c4.com>,
"Stephan Müller" <smueller@chronox.de>,
"Torsten Duwe" <duwe@suse.de>, "Petr Tesarik" <ptesarik@suse.cz>,
"Nicolai Stange" <nstange@suse.de>
Subject: [RFC PATCH 34/41] random: implement the "Adaptive Proportion" NIST SP800-90B health test
Date: Mon, 21 Sep 2020 09:58:50 +0200 [thread overview]
Message-ID: <20200921075857.4424-35-nstange@suse.de> (raw)
In-Reply-To: <20200921075857.4424-1-nstange@suse.de>
NIST SP800-90B requires an implementation of the "Adaptive Proportion"
health test (APT) or similar for detecting noise source entropy
degradations.
This tests works by counting how many times the first sample value in a
sequence of n events occurs among the remaining n-1 samples. The test will
reject if this number exceeds a certain threshold.
With a min-entropy estimate of H=2^-event_entropy_shift per IRQ event, the
probability of observing any particular sample value is bounded by
p <= 2^-H. Assuming i.i.d., the number of occurences of such a sample
value among n - 1 events follows the binomial distribution with parameters
n - 1 and p. The probability to observe up to k occurences of a given
sample value is not less than that distribution's CDF F(n - 1, p, k) at
point k, per the definition of CDFs and the fact that
F(n - 1, p1, k) >= F(n - 1, p2, k) for p1 <= p2 in the particular case of
Binomial distributions. It follows that an upper bound on the probability
of observing the same value c or more times among n - 1 consecutive samples
is given by 1 - F(n - 1, p, c - 1). In conclusion, the probability of false
positives is <= p * (1 - F(n - 1, p, c - 1)) for the Adaptive Proportion
test.
NIST SP800-90B recommends to set n to either 512 or 1024 and to choose a
cut-off value c such that the probability of false positives is <= 2^-20.
However, assuming an estimated per-IRQ entropy of 1 bit, it would take
1024/128 == 8 minimum crng seed sizes worth of entropy before the APT
eventually completes and the accumulated entropy may get released to the
global reserve. Thus, it is desirable to set n such that the APT will
complete within 128 bits worth of entropy, i.e. to n = 128 / H. However,
for such relatively small values of n, an upper bound as small as 2^-20
for the false positives probability would make the test's statistical
power, i.e. the capability to detect degraded noise sources, plummet to
uselessness. Note that add_interrupt_randomness() will continue to
unconditionally mix all events into the fast_pools, independent of the
APT's outcome. Thus, allowing for a higher probability of false positives
cannot change the output distribution, but only potentially affect the
entropy accounting. Choose an upper bound of 2^-16 for the probability of
false positives.
The resulting cut-off values for the different supported values of per-IRQ
entropy estimates are tabulated below. The "power" column lists the
probabilities (again for i.i.d.) that the APT would report a failure in
case the actual entropy has degraded to one half of the assumed estimate.
H n c power
--------------------
1 128 87 52.5%
1/2 256 210 67.5%
1/4 512 463 76.7%
1/8 1024 973 82.8%
1/16 2048 1997 82.6%
1/32 4096 4044 85.8%
1/64 8192 8140 85.8%
Add a couple of new fields to struct health_test for storing the required
APT state to struct health_test:
- ->apt_event_count: total number of samples processed by the currently
pending APT,
- ->apt_candidate: the sample value whose number of occurences the
currently pending APT is counting,
- ->apt_candidate_count: the number of occurences of ->apt_candidate
the currently pending APT has encountered so far.
Implement the APT logic and wrap it in a new function, health_test_apt().
Invoke it from health_test_process().
Signed-off-by: Nicolai Stange <nstange@suse.de>
---
drivers/char/random.c | 56 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 54 insertions(+), 2 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 33f9b7b59f92..131302cbc495 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -880,6 +880,10 @@ static void discard_queued_entropy(struct entropy_store *r,
}
struct health_test {
+ unsigned short apt_event_count;
+ unsigned short apt_candidate_count;
+ u8 apt_candidate;
+
u8 previous_sample;
};
@@ -890,8 +894,56 @@ enum health_result {
health_discard,
};
+/* Adaptive Proportion Test */
+static void health_apt_reset(struct health_test *h)
+{
+ h->apt_event_count = 0;
+}
+
+static enum health_result
+health_test_apt(struct health_test *h, unsigned int event_entropy_shift,
+ u8 sample_delta)
+{
+ unsigned int n = 128 << event_entropy_shift;
+ /*
+ * Observing some particular sample value more often than
+ * these thresholds, specified for the different possible
+ * values of event_entropy_shift each, should have probability
+ * <= 2^-16.
+ */
+ static const unsigned int c[] = {87, 210, 463, 973, 1997, 4044, 8140};
+
+ if (!h->apt_event_count) {
+ h->apt_event_count = 1;
+ h->apt_candidate = sample_delta;
+ h->apt_candidate_count = 0;
+ return health_queue;
+ }
+
+ ++h->apt_event_count;
+ if (unlikely(h->apt_candidate == sample_delta &&
+ ++h->apt_candidate_count == c[event_entropy_shift])) {
+ health_apt_reset(h);
+ return health_discard;
+ } else if (c[event_entropy_shift] - h->apt_candidate_count >
+ n - h->apt_event_count) {
+ /*
+ * The currently pending APT might not have seen all n
+ * events yet, but it's already known by now that it
+ * can't fail anymore. Note that the above condition
+ * also coverts the case h->apt_event_count == n.
+ */
+ health_apt_reset(h);
+ return health_dispatch;
+ }
+
+ return health_queue;
+}
+
static void health_test_reset(struct health_test *h)
-{}
+{
+ health_apt_reset(h);
+}
static enum health_result
health_test_process(struct health_test *h, unsigned int event_entropy_shift,
@@ -907,7 +959,7 @@ health_test_process(struct health_test *h, unsigned int event_entropy_shift,
sample_delta = sample - h->previous_sample;
h->previous_sample = sample;
- return health_none;
+ return health_test_apt(h, event_entropy_shift, sample_delta);
}
struct fast_pool {
--
2.26.2
next prev parent reply other threads:[~2020-09-21 8:01 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-21 7:58 [DISCUSSION PATCH 00/41] random: possible ways towards NIST SP800-90B compliance Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 01/41] random: remove dead code in credit_entropy_bits() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 02/41] random: remove dead code for nbits < 0 " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 03/41] random: prune dead assignment to entropy_bits " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 04/41] random: drop 'reserved' parameter from extract_entropy() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 05/41] random: don't reset entropy to zero on overflow Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 06/41] random: factor the exponential approximation in credit_entropy_bits() out Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 07/41] random: let pool_entropy_delta() take nbits in units of 2^-ENTROPY_SHIFT Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 08/41] random: introduce __credit_entropy_bits_fast() for hot paths Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 09/41] random: protect ->entropy_count with the pool spinlock Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 10/41] random: implement support for delayed entropy dispatching Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 11/41] random: convert add_timer_randomness() to queued_entropy API Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 12/41] random: convert add_interrupt_randomness() " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 13/41] random: convert try_to_generate_entropy() " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 14/41] random: drop __credit_entropy_bits_fast() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 15/41] random: convert add_hwgenerator_randomness() to queued_entropy API Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 16/41] random: convert random_ioctl() " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 17/41] random: drop credit_entropy_bits() and credit_entropy_bits_safe() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 18/41] random: move arch_get_random_seed() calls in crng_reseed() into own loop Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 19/41] random: reintroduce arch_has_random() + arch_has_random_seed() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 20/41] random: provide min_crng_reseed_pool_entropy() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 21/41] random: don't invoke arch_get_random_long() from add_interrupt_randomness() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 22/41] random: introduce arch_has_sp800_90b_random_seed() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 23/41] random: don't award entropy to non-SP800-90B arch RNGs in FIPS mode Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 24/41] init: call time_init() before rand_initialize() Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 25/41] random: probe cycle counter resolution at initialization Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 26/41] random: implement support for evaluating larger fast_pool entropies Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 27/41] random: increase per-IRQ event entropy estimate if in FIPS mode Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 28/41] random: don't award entropy to disk + input events " Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 29/41] random: move definition of struct queued_entropy and related API upwards Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 30/41] random: add a queued_entropy instance to struct fast_pool Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 31/41] random: introduce struct health_test + health_test_reset() placeholders Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 32/41] random: introduce health test stub and wire it up Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 33/41] random: make health_test_process() maintain the get_cycles() delta Nicolai Stange
2020-09-21 7:58 ` Nicolai Stange [this message]
2020-09-21 7:58 ` [RFC PATCH 35/41] random: improve the APT's statistical power Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 36/41] random: optimize the APT's presearch Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 37/41] random: implement the "Repetition Count" NIST SP800-90B health test Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 38/41] random: enable NIST SP800-90B startup tests Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 39/41] random: make the startup tests include muliple APT invocations Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 40/41] random: trigger startup health test on any failure of the health tests Nicolai Stange
2020-09-21 7:58 ` [RFC PATCH 41/41] random: lower per-IRQ entropy estimate upon health test failure Nicolai Stange
2020-09-21 8:09 ` [DISCUSSION PATCH 00/41] random: possible ways towards NIST SP800-90B compliance Jason A. Donenfeld
2020-09-21 8:40 ` Stephan Mueller
2020-09-22 13:23 ` Torsten Duwe
2020-09-22 16:21 ` Greg Kroah-Hartman
2020-09-22 17:48 ` Torsten Duwe
2020-10-02 12:38 ` Torsten Duwe
2020-10-02 13:15 ` Willy Tarreau
2020-10-02 13:33 ` Greg Kroah-Hartman
2020-10-02 14:05 ` Torsten Duwe
2020-10-02 13:56 ` Stephan Mueller
2020-10-16 17:26 ` Torsten Duwe
2020-10-19 19:28 ` [PATCH v36 00/13] /dev/random - a new approach Stephan Müller
2020-10-19 19:30 ` [PATCH v36 01/13] Linux Random Number Generator Stephan Müller
2020-10-19 19:31 ` [PATCH v36 02/13] LRNG - allocate one DRNG instance per NUMA node Stephan Müller
2020-10-19 19:32 ` [PATCH v36 03/13] LRNG - sysctls and /proc interface Stephan Müller
2020-10-19 19:32 ` [PATCH v36 04/13] LRNG - add switchable DRNG support Stephan Müller
2020-10-19 19:33 ` [PATCH v36 05/13] LRNG - add common generic hash support Stephan Müller
2020-10-19 19:34 ` [PATCH v36 06/13] crypto: DRBG - externalize DRBG functions for LRNG Stephan Müller
2020-10-19 19:34 ` [PATCH v36 07/13] LRNG - add SP800-90A DRBG extension Stephan Müller
2020-10-19 19:35 ` [PATCH v36 08/13] LRNG - add kernel crypto API PRNG extension Stephan Müller
2020-10-19 19:35 ` [PATCH v36 09/13] crypto: provide access to a static Jitter RNG state Stephan Müller
2020-10-19 19:36 ` [PATCH v36 10/13] LRNG - add Jitter RNG fast noise source Stephan Müller
2020-10-19 19:37 ` [PATCH v36 11/13] LRNG - add SP800-90B compliant health tests Stephan Müller
2020-10-19 19:37 ` [PATCH v36 12/13] LRNG - add interface for gathering of raw entropy Stephan Müller
2020-10-19 19:38 ` [PATCH v36 13/13] LRNG - add power-on and runtime self-tests Stephan Müller
2020-10-28 17:51 ` [PATCH v36 00/13] /dev/random - a new approach Torsten Duwe
2020-10-28 18:07 ` Greg Kroah-Hartman
2020-11-02 13:44 ` Torsten Duwe
2020-11-04 14:26 ` Marcelo Henrique Cerri
2020-11-17 14:01 ` Torsten Duwe
2020-11-10 10:22 ` Stephan Mueller
2020-10-02 13:35 ` [DISCUSSION PATCH 00/41] random: possible ways towards NIST SP800-90B compliance Van Leeuwen, Pascal
2020-10-02 14:04 ` Greg Kroah-Hartman
2020-10-02 14:34 ` Van Leeuwen, Pascal
2020-10-02 15:13 ` Greg Kroah-Hartman
2020-10-02 15:39 ` Van Leeuwen, Pascal
2020-10-02 16:30 ` Randy Dunlap
2020-10-02 18:14 ` Theodore Y. Ts'o
2020-10-02 19:09 ` Van Leeuwen, Pascal
2020-10-07 4:24 ` Eric Biggers
2020-10-07 5:52 ` Stephan Mueller
2020-10-07 10:38 ` Nicolai Stange
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200921075857.4424-35-nstange@suse.de \
--to=nstange@suse.de \
--cc=Jason@zx2c4.com \
--cc=adilger.kernel@dilger.ca \
--cc=andy.lavr@gmail.com \
--cc=arnd@arndb.de \
--cc=dan.carpenter@oracle.com \
--cc=darwish.07@gmail.com \
--cc=draht@schaltsekun.de \
--cc=duwe@suse.de \
--cc=ebiederm@xmission.com \
--cc=ebiggers@kernel.org \
--cc=fweimer@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=jack@suse.cz \
--cc=julia.lawall@inria.fr \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=marcelo.cerri@canonical.com \
--cc=matthias.peter@bsi.bund.de \
--cc=mccann@jhu.edu \
--cc=mjg59@srcf.ucam.org \
--cc=mzxreary@0pointer.de \
--cc=nhorman@redhat.com \
--cc=patrakov@gmail.com \
--cc=ptesarik@suse.cz \
--cc=rdunlap@infradead.org \
--cc=rstrode@redhat.com \
--cc=smueller@chronox.de \
--cc=tytso@mit.edu \
--cc=vcaputo@pengaru.com \
--cc=w@1wt.eu \
--cc=zachary@baishancloud.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®