mirror of
https://github.com/openwrt/openwrt.git
synced 2025-04-13 22:23:38 +00:00
generic: crypto: fix jitterentropy initialization failed issue
Sync jitterentropy source code with linux-6.12 to solve the issue of jitterentropy initialization failed: [ 9.523489] jitterentropy: Initialization failed with host not compliant with requirements: 9 [ 9.661916] kmodloader: 1 module could not be probed [ 9.662377] kmodloader: - jitterentropy_rng - 0 In linux upstream commit cf27d9475f37 ("crypto: jitter - use permanent health test storage"), when FIPS crypto is disabled, the health test results are always explicitly skipped. That means it will never return error code 9 (health test failed) again. Fixes: https://github.com/openwrt/openwrt/issues/16684 Signed-off-by: Shiji Yang <yangshiji66@outlook.com> Link: https://github.com/openwrt/openwrt/pull/18399 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
parent
4e18d224c8
commit
eec11fbbb6
@ -0,0 +1,445 @@
|
||||
From 04597c8dd6c4b55e946fec50dc3b14a5d9d54501 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:11 +0200
|
||||
Subject: [PATCH] crypto: jitter - add RCT/APT support for different OSRs
|
||||
|
||||
The oversampling rate (OSR) value specifies the heuristically implied
|
||||
entropy in the recorded data - H_submitter = 1/osr. A different entropy
|
||||
estimate implies a different APT/RCT cutoff value. This change adds
|
||||
support for OSRs 1 through 15. This OSR can be selected by the caller
|
||||
of the Jitter RNG.
|
||||
|
||||
For this patch, the caller still uses one hard-coded OSR. A subsequent
|
||||
patch allows this value to be configured.
|
||||
|
||||
In addition, the power-up self test is adjusted as follows:
|
||||
|
||||
* It allows the caller to provide an oversampling rate that should be
|
||||
tested with - commonly it should be the same as used for the actual
|
||||
runtime operation. This makes the power-up testing therefore consistent
|
||||
with the runtime operation.
|
||||
|
||||
* It calls now jent_measure_jitter (i.e. collects the full entropy
|
||||
that can possibly be harvested by the Jitter RNG) instead of only
|
||||
jent_condition_data (which only returns the entropy harvested from
|
||||
the conditioning component). This should now alleviate reports where
|
||||
the Jitter RNG initialization thinks there is too little entropy.
|
||||
|
||||
* The power-up test now solely relies on the (enhanced) APT and RCT
|
||||
test that is used as a health test at runtime.
|
||||
|
||||
The code allowing the different OSRs as well as the power-up test
|
||||
changes are present in the user space version of the Jitter RNG 3.4.1
|
||||
and thus was already in production use for some time.
|
||||
|
||||
Reported-by "Ospan, Abylay" <aospan@amazon.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 4 +-
|
||||
crypto/jitterentropy.c | 233 ++++++++++++++++++-----------------
|
||||
crypto/jitterentropy.h | 3 +-
|
||||
3 files changed, 123 insertions(+), 117 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -245,7 +245,7 @@ static int jent_kcapi_init(struct crypto
|
||||
crypto_shash_init(sdesc);
|
||||
rng->sdesc = sdesc;
|
||||
|
||||
- rng->entropy_collector = jent_entropy_collector_alloc(1, 0, sdesc);
|
||||
+ rng->entropy_collector = jent_entropy_collector_alloc(0, 0, sdesc);
|
||||
if (!rng->entropy_collector) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
@@ -334,7 +334,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(desc);
|
||||
+ ret = jent_entropy_init(0, 0, desc);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -72,6 +72,8 @@ struct rand_data {
|
||||
__u64 prev_time; /* SENSITIVE Previous time stamp */
|
||||
__u64 last_delta; /* SENSITIVE stuck test */
|
||||
__s64 last_delta2; /* SENSITIVE stuck test */
|
||||
+
|
||||
+ unsigned int flags; /* Flags used to initialize */
|
||||
unsigned int osr; /* Oversample rate */
|
||||
#define JENT_MEMORY_BLOCKS 64
|
||||
#define JENT_MEMORY_BLOCKSIZE 32
|
||||
@@ -88,16 +90,9 @@ struct rand_data {
|
||||
/* Repetition Count Test */
|
||||
unsigned int rct_count; /* Number of stuck values */
|
||||
|
||||
- /* Intermittent health test failure threshold of 2^-30 */
|
||||
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 31. */
|
||||
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
|
||||
-#define JENT_RCT_CUTOFF (31 - 1) /* Taken from SP800-90B sec 4.4.1 */
|
||||
-#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
|
||||
- /* Permanent health test failure threshold of 2^-60 */
|
||||
- /* From an SP800-90B perspective, this RCT cutoff value is equal to 61. */
|
||||
- /* However, our RCT implementation starts at 1, so we subtract 1 here. */
|
||||
-#define JENT_RCT_CUTOFF_PERMANENT (61 - 1)
|
||||
-#define JENT_APT_CUTOFF_PERMANENT 355
|
||||
+ /* Adaptive Proportion Test cutoff values */
|
||||
+ unsigned int apt_cutoff; /* Intermittent health test failure */
|
||||
+ unsigned int apt_cutoff_permanent; /* Permanent health test failure */
|
||||
#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
|
||||
/* LSB of time stamp to process */
|
||||
#define JENT_APT_LSB 16
|
||||
@@ -122,6 +117,9 @@ struct rand_data {
|
||||
* zero). */
|
||||
#define JENT_ESTUCK 8 /* Too many stuck results during init. */
|
||||
#define JENT_EHEALTH 9 /* Health test failed during initialization */
|
||||
+#define JENT_ERCT 10 /* RCT failed during initialization */
|
||||
+#define JENT_EHASH 11 /* Hash self test failed */
|
||||
+#define JENT_EMEM 12 /* Can't allocate memory for initialization */
|
||||
|
||||
/*
|
||||
* The output n bits can receive more than n bits of min entropy, of course,
|
||||
@@ -148,6 +146,48 @@ struct rand_data {
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
+ * See the SP 800-90B comment #10b for the corrected cutoff for the SP 800-90B
|
||||
+ * APT.
|
||||
+ * http://www.untruth.org/~josh/sp80090b/UL%20SP800-90B-final%20comments%20v1.9%2020191212.pdf
|
||||
+ * In in the syntax of R, this is C = 2 + qbinom(1 − 2^(−30), 511, 2^(-1/osr)).
|
||||
+ * (The original formula wasn't correct because the first symbol must
|
||||
+ * necessarily have been observed, so there is no chance of observing 0 of these
|
||||
+ * symbols.)
|
||||
+ *
|
||||
+ * For the alpha < 2^-53, R cannot be used as it uses a float data type without
|
||||
+ * arbitrary precision. A SageMath script is used to calculate those cutoff
|
||||
+ * values.
|
||||
+ *
|
||||
+ * For any value above 14, this yields the maximal allowable value of 512
|
||||
+ * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that
|
||||
+ * renders the test unable to fail).
|
||||
+ */
|
||||
+static const unsigned int jent_apt_cutoff_lookup[15] = {
|
||||
+ 325, 422, 459, 477, 488, 494, 499, 502,
|
||||
+ 505, 507, 508, 509, 510, 511, 512 };
|
||||
+static const unsigned int jent_apt_cutoff_permanent_lookup[15] = {
|
||||
+ 355, 447, 479, 494, 502, 507, 510, 512,
|
||||
+ 512, 512, 512, 512, 512, 512, 512 };
|
||||
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
+
|
||||
+static void jent_apt_init(struct rand_data *ec, unsigned int osr)
|
||||
+{
|
||||
+ /*
|
||||
+ * Establish the apt_cutoff based on the presumed entropy rate of
|
||||
+ * 1/osr.
|
||||
+ */
|
||||
+ if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) {
|
||||
+ ec->apt_cutoff = jent_apt_cutoff_lookup[
|
||||
+ ARRAY_SIZE(jent_apt_cutoff_lookup) - 1];
|
||||
+ ec->apt_cutoff_permanent = jent_apt_cutoff_permanent_lookup[
|
||||
+ ARRAY_SIZE(jent_apt_cutoff_permanent_lookup) - 1];
|
||||
+ } else {
|
||||
+ ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1];
|
||||
+ ec->apt_cutoff_permanent =
|
||||
+ jent_apt_cutoff_permanent_lookup[osr - 1];
|
||||
+ }
|
||||
+}
|
||||
+/*
|
||||
* Reset the APT counter
|
||||
*
|
||||
* @ec [in] Reference to entropy collector
|
||||
@@ -187,12 +227,12 @@ static void jent_apt_insert(struct rand_
|
||||
/* APT health test failure detection */
|
||||
static int jent_apt_permanent_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->apt_count >= JENT_APT_CUTOFF_PERMANENT) ? 1 : 0;
|
||||
+ return (ec->apt_count >= ec->apt_cutoff_permanent) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int jent_apt_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->apt_count >= JENT_APT_CUTOFF) ? 1 : 0;
|
||||
+ return (ec->apt_count >= ec->apt_cutoff) ? 1 : 0;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -275,15 +315,28 @@ static int jent_stuck(struct rand_data *
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* RCT health test failure detection */
|
||||
+/*
|
||||
+ * The cutoff value is based on the following consideration:
|
||||
+ * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
+ * In addition, we require an entropy value H of 1/osr as this is the minimum
|
||||
+ * entropy required to provide full entropy.
|
||||
+ * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr deltas for
|
||||
+ * inserting them into the entropy pool which should then have (close to)
|
||||
+ * DATA_SIZE_BITS bits of entropy in the conditioned output.
|
||||
+ *
|
||||
+ * Note, ec->rct_count (which equals to value B in the pseudo code of SP800-90B
|
||||
+ * section 4.4.1) starts with zero. Hence we need to subtract one from the
|
||||
+ * cutoff value as calculated following SP800-90B. Thus
|
||||
+ * C = ceil(-log_2(alpha)/H) = 30*osr or 60*osr.
|
||||
+ */
|
||||
static int jent_rct_permanent_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->rct_count >= JENT_RCT_CUTOFF_PERMANENT) ? 1 : 0;
|
||||
+ return (ec->rct_count >= (60 * ec->osr)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int jent_rct_failure(struct rand_data *ec)
|
||||
{
|
||||
- return (ec->rct_count >= JENT_RCT_CUTOFF) ? 1 : 0;
|
||||
+ return (ec->rct_count >= (30 * ec->osr)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Report of health test failures */
|
||||
@@ -448,7 +501,7 @@ static void jent_memaccess(struct rand_d
|
||||
*
|
||||
* @return result of stuck test
|
||||
*/
|
||||
-static int jent_measure_jitter(struct rand_data *ec)
|
||||
+static int jent_measure_jitter(struct rand_data *ec, __u64 *ret_current_delta)
|
||||
{
|
||||
__u64 time = 0;
|
||||
__u64 current_delta = 0;
|
||||
@@ -472,6 +525,10 @@ static int jent_measure_jitter(struct ra
|
||||
if (jent_condition_data(ec, current_delta, stuck))
|
||||
stuck = 1;
|
||||
|
||||
+ /* return the raw entropy value */
|
||||
+ if (ret_current_delta)
|
||||
+ *ret_current_delta = current_delta;
|
||||
+
|
||||
return stuck;
|
||||
}
|
||||
|
||||
@@ -489,11 +546,11 @@ static void jent_gen_entropy(struct rand
|
||||
safety_factor = JENT_ENTROPY_SAFETY_FACTOR;
|
||||
|
||||
/* priming of the ->prev_time value */
|
||||
- jent_measure_jitter(ec);
|
||||
+ jent_measure_jitter(ec, NULL);
|
||||
|
||||
while (!jent_health_failure(ec)) {
|
||||
/* If a stuck measurement is received, repeat measurement */
|
||||
- if (jent_measure_jitter(ec))
|
||||
+ if (jent_measure_jitter(ec, NULL))
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -554,7 +611,8 @@ int jent_read_entropy(struct rand_data *
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(ec->hash_state))
|
||||
+ if (jent_entropy_init(ec->osr, ec->flags,
|
||||
+ ec->hash_state))
|
||||
return -3;
|
||||
|
||||
return -2;
|
||||
@@ -604,11 +662,15 @@ struct rand_data *jent_entropy_collector
|
||||
|
||||
/* verify and set the oversampling rate */
|
||||
if (osr == 0)
|
||||
- osr = 1; /* minimum sampling rate is 1 */
|
||||
+ osr = 1; /* H_submitter = 1 / osr */
|
||||
entropy_collector->osr = osr;
|
||||
+ entropy_collector->flags = flags;
|
||||
|
||||
entropy_collector->hash_state = hash_state;
|
||||
|
||||
+ /* Initialize the APT */
|
||||
+ jent_apt_init(entropy_collector, osr);
|
||||
+
|
||||
/* fill the data pad with non-zero values */
|
||||
jent_gen_entropy(entropy_collector);
|
||||
|
||||
@@ -622,20 +684,14 @@ void jent_entropy_collector_free(struct
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
|
||||
-int jent_entropy_init(void *hash_state)
|
||||
+int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state)
|
||||
{
|
||||
- int i;
|
||||
- __u64 delta_sum = 0;
|
||||
- __u64 old_delta = 0;
|
||||
- unsigned int nonstuck = 0;
|
||||
- int time_backwards = 0;
|
||||
- int count_mod = 0;
|
||||
- int count_stuck = 0;
|
||||
- struct rand_data ec = { 0 };
|
||||
-
|
||||
- /* Required for RCT */
|
||||
- ec.osr = 1;
|
||||
- ec.hash_state = hash_state;
|
||||
+ struct rand_data *ec;
|
||||
+ int i, time_backwards = 0, ret = 0;
|
||||
+
|
||||
+ ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
+ if (!ec)
|
||||
+ return JENT_EMEM;
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
* that we only have a few loop counts to do testing. These
|
||||
@@ -664,31 +720,28 @@ int jent_entropy_init(void *hash_state)
|
||||
#define TESTLOOPCOUNT 1024
|
||||
#define CLEARCACHE 100
|
||||
for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
|
||||
- __u64 time = 0;
|
||||
- __u64 time2 = 0;
|
||||
- __u64 delta = 0;
|
||||
- unsigned int lowdelta = 0;
|
||||
- int stuck;
|
||||
+ __u64 start_time = 0, end_time = 0, delta = 0;
|
||||
|
||||
/* Invoke core entropy collection logic */
|
||||
- jent_get_nstime(&time);
|
||||
- ec.prev_time = time;
|
||||
- jent_condition_data(&ec, time, 0);
|
||||
- jent_get_nstime(&time2);
|
||||
+ jent_measure_jitter(ec, &delta);
|
||||
+ end_time = ec->prev_time;
|
||||
+ start_time = ec->prev_time - delta;
|
||||
|
||||
/* test whether timer works */
|
||||
- if (!time || !time2)
|
||||
- return JENT_ENOTIME;
|
||||
- delta = jent_delta(time, time2);
|
||||
+ if (!start_time || !end_time) {
|
||||
+ ret = JENT_ENOTIME;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* test whether timer is fine grained enough to provide
|
||||
* delta even when called shortly after each other -- this
|
||||
* implies that we also have a high resolution timer
|
||||
*/
|
||||
- if (!delta)
|
||||
- return JENT_ECOARSETIME;
|
||||
-
|
||||
- stuck = jent_stuck(&ec, delta);
|
||||
+ if (!delta || (end_time == start_time)) {
|
||||
+ ret = JENT_ECOARSETIME;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/*
|
||||
* up to here we did not modify any variable that will be
|
||||
@@ -700,49 +753,9 @@ int jent_entropy_init(void *hash_state)
|
||||
if (i < CLEARCACHE)
|
||||
continue;
|
||||
|
||||
- if (stuck)
|
||||
- count_stuck++;
|
||||
- else {
|
||||
- nonstuck++;
|
||||
-
|
||||
- /*
|
||||
- * Ensure that the APT succeeded.
|
||||
- *
|
||||
- * With the check below that count_stuck must be less
|
||||
- * than 10% of the overall generated raw entropy values
|
||||
- * it is guaranteed that the APT is invoked at
|
||||
- * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
|
||||
- */
|
||||
- if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
|
||||
- jent_apt_reset(&ec,
|
||||
- delta & JENT_APT_WORD_MASK);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* Validate health test result */
|
||||
- if (jent_health_failure(&ec))
|
||||
- return JENT_EHEALTH;
|
||||
-
|
||||
/* test whether we have an increasing timer */
|
||||
- if (!(time2 > time))
|
||||
+ if (!(end_time > start_time))
|
||||
time_backwards++;
|
||||
-
|
||||
- /* use 32 bit value to ensure compilation on 32 bit arches */
|
||||
- lowdelta = time2 - time;
|
||||
- if (!(lowdelta % 100))
|
||||
- count_mod++;
|
||||
-
|
||||
- /*
|
||||
- * ensure that we have a varying delta timer which is necessary
|
||||
- * for the calculation of entropy -- perform this check
|
||||
- * only after the first loop is executed as we need to prime
|
||||
- * the old_data value
|
||||
- */
|
||||
- if (delta > old_delta)
|
||||
- delta_sum += (delta - old_delta);
|
||||
- else
|
||||
- delta_sum += (old_delta - delta);
|
||||
- old_delta = delta;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -752,31 +765,23 @@ int jent_entropy_init(void *hash_state)
|
||||
* should not fail. The value of 3 should cover the NTP case being
|
||||
* performed during our test run.
|
||||
*/
|
||||
- if (time_backwards > 3)
|
||||
- return JENT_ENOMONOTONIC;
|
||||
-
|
||||
- /*
|
||||
- * Variations of deltas of time must on average be larger
|
||||
- * than 1 to ensure the entropy estimation
|
||||
- * implied with 1 is preserved
|
||||
- */
|
||||
- if ((delta_sum) <= 1)
|
||||
- return JENT_EVARVAR;
|
||||
+ if (time_backwards > 3) {
|
||||
+ ret = JENT_ENOMONOTONIC;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * Ensure that we have variations in the time stamp below 10 for at
|
||||
- * least 10% of all checks -- on some platforms, the counter increments
|
||||
- * in multiples of 100, but not always
|
||||
- */
|
||||
- if ((TESTLOOPCOUNT/10 * 9) < count_mod)
|
||||
- return JENT_ECOARSETIME;
|
||||
+ /* Did we encounter a health test failure? */
|
||||
+ if (jent_rct_failure(ec)) {
|
||||
+ ret = JENT_ERCT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (jent_apt_failure(ec)) {
|
||||
+ ret = JENT_EHEALTH;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * If we have more than 90% stuck results, then this Jitter RNG is
|
||||
- * likely to not work well.
|
||||
- */
|
||||
- if ((TESTLOOPCOUNT/10 * 9) < count_stuck)
|
||||
- return JENT_ESTUCK;
|
||||
+out:
|
||||
+ jent_entropy_collector_free(ec);
|
||||
|
||||
- return 0;
|
||||
+ return ret;
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -9,7 +9,8 @@ extern int jent_hash_time(void *hash_sta
|
||||
int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len);
|
||||
|
||||
struct rand_data;
|
||||
-extern int jent_entropy_init(void *hash_state);
|
||||
+extern int jent_entropy_init(unsigned int osr, unsigned int flags,
|
||||
+ void *hash_state);
|
||||
extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
|
||||
unsigned int len);
|
||||
|
@ -0,0 +1,159 @@
|
||||
From 59bcfd788552504606e3eb774ae68052379396b6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:33 +0200
|
||||
Subject: [PATCH] crypto: jitter - Allow configuration of memory size
|
||||
|
||||
The memory size consumed by the Jitter RNG is one contributing factor in
|
||||
the amount of entropy that is gathered. As the amount of entropy
|
||||
directly correlates with the distance of the memory from the CPU, the
|
||||
caches that are possibly present on a given system have an impact on the
|
||||
collected entropy.
|
||||
|
||||
Thus, the kernel compile time should offer a means to configure the
|
||||
amount of memory used by the Jitter RNG. Although this option could be
|
||||
turned into a runtime option (e.g. a kernel command line option), it
|
||||
should remain a compile time option as otherwise adminsitrators who may
|
||||
not have performed an entropy assessment may select a value that is
|
||||
inappropriate.
|
||||
|
||||
The default value selected by the configuration is identical to the
|
||||
current Jitter RNG value. Thus, the patch should not lead to any change
|
||||
in the Jitter RNG behavior.
|
||||
|
||||
To accommodate larger memory buffers, kvzalloc / kvfree is used.
|
||||
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 43 ++++++++++++++++++++++++++++++++++++
|
||||
crypto/jitterentropy-kcapi.c | 11 +++++++++
|
||||
crypto/jitterentropy.c | 16 ++++++++------
|
||||
crypto/jitterentropy.h | 2 ++
|
||||
4 files changed, 65 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1297,6 +1297,49 @@ config CRYPTO_JITTERENTROPY
|
||||
|
||||
See https://www.chronox.de/jent/
|
||||
|
||||
+choice
|
||||
+ prompt "CPU Jitter RNG Memory Size"
|
||||
+ default CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ depends on CRYPTO_JITTERENTROPY
|
||||
+ help
|
||||
+ The Jitter RNG measures the execution time of memory accesses.
|
||||
+ Multiple consecutive memory accesses are performed. If the memory
|
||||
+ size fits into a cache (e.g. L1), only the memory access timing
|
||||
+ to that cache is measured. The closer the cache is to the CPU
|
||||
+ the less variations are measured and thus the less entropy is
|
||||
+ obtained. Thus, if the memory size fits into the L1 cache, the
|
||||
+ obtained entropy is less than if the memory size fits within
|
||||
+ L1 + L2, which in turn is less if the memory fits into
|
||||
+ L1 + L2 + L3. Thus, by selecting a different memory size,
|
||||
+ the entropy rate produced by the Jitter RNG can be modified.
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ bool "2048 Bytes (default)"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ bool "128 kBytes"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ bool "1024 kBytes"
|
||||
+
|
||||
+ config CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+ bool "8192 kBytes"
|
||||
+endchoice
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
|
||||
+ int
|
||||
+ default 64 if CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ default 512 if CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ default 4096 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
|
||||
+ int
|
||||
+ default 32 if CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
+ default 256 if CRYPTO_JITTERENTROPY_MEMSIZE_128
|
||||
+ default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
+ default 2048 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
+
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
depends on CRYPTO_JITTERENTROPY
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -54,6 +54,17 @@
|
||||
* Helper function
|
||||
***************************************************************************/
|
||||
|
||||
+void *jent_kvzalloc(unsigned int len)
|
||||
+{
|
||||
+ return kvzalloc(len, GFP_KERNEL);
|
||||
+}
|
||||
+
|
||||
+void jent_kvzfree(void *ptr, unsigned int len)
|
||||
+{
|
||||
+ memzero_explicit(ptr, len);
|
||||
+ kvfree(ptr);
|
||||
+}
|
||||
+
|
||||
void *jent_zalloc(unsigned int len)
|
||||
{
|
||||
return kzalloc(len, GFP_KERNEL);
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -75,10 +75,10 @@ struct rand_data {
|
||||
|
||||
unsigned int flags; /* Flags used to initialize */
|
||||
unsigned int osr; /* Oversample rate */
|
||||
-#define JENT_MEMORY_BLOCKS 64
|
||||
-#define JENT_MEMORY_BLOCKSIZE 32
|
||||
#define JENT_MEMORY_ACCESSLOOPS 128
|
||||
-#define JENT_MEMORY_SIZE (JENT_MEMORY_BLOCKS*JENT_MEMORY_BLOCKSIZE)
|
||||
+#define JENT_MEMORY_SIZE \
|
||||
+ (CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS * \
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE)
|
||||
unsigned char *mem; /* Memory access location with size of
|
||||
* memblocks * memblocksize */
|
||||
unsigned int memlocation; /* Pointer to byte in *mem */
|
||||
@@ -650,13 +650,15 @@ struct rand_data *jent_entropy_collector
|
||||
/* Allocate memory for adding variations based on memory
|
||||
* access
|
||||
*/
|
||||
- entropy_collector->mem = jent_zalloc(JENT_MEMORY_SIZE);
|
||||
+ entropy_collector->mem = jent_kvzalloc(JENT_MEMORY_SIZE);
|
||||
if (!entropy_collector->mem) {
|
||||
jent_zfree(entropy_collector);
|
||||
return NULL;
|
||||
}
|
||||
- entropy_collector->memblocksize = JENT_MEMORY_BLOCKSIZE;
|
||||
- entropy_collector->memblocks = JENT_MEMORY_BLOCKS;
|
||||
+ entropy_collector->memblocksize =
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE;
|
||||
+ entropy_collector->memblocks =
|
||||
+ CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS;
|
||||
entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS;
|
||||
}
|
||||
|
||||
@@ -679,7 +681,7 @@ struct rand_data *jent_entropy_collector
|
||||
|
||||
void jent_entropy_collector_free(struct rand_data *entropy_collector)
|
||||
{
|
||||
- jent_zfree(entropy_collector->mem);
|
||||
+ jent_kvzfree(entropy_collector->mem, JENT_MEMORY_SIZE);
|
||||
entropy_collector->mem = NULL;
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
+extern void *jent_kvzalloc(unsigned int len);
|
||||
+extern void jent_kvzfree(void *ptr, unsigned int len);
|
||||
extern void *jent_zalloc(unsigned int len);
|
||||
extern void jent_zfree(void *ptr);
|
||||
extern void jent_get_nstime(__u64 *out);
|
@ -0,0 +1,75 @@
|
||||
From 0baa8fab334a4d7017235b72fa8a547433572109 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 21 Sep 2023 13:48:59 +0200
|
||||
Subject: [PATCH] crypto: jitter - Allow configuration of oversampling rate
|
||||
|
||||
The oversampling rate used by the Jitter RNG allows the configuration of
|
||||
the heuristically implied entropy in one timing measurement. This
|
||||
entropy rate is (1 / OSR) bits of entropy per time stamp.
|
||||
|
||||
Considering that the Jitter RNG now support APT/RCT health tests for
|
||||
different OSRs, allow this value to be configured at compile time to
|
||||
support systems with limited amount of entropy in their timer.
|
||||
|
||||
The allowed range of OSR values complies with the APT/RCT cutoff health
|
||||
test values which range from 1 through 15.
|
||||
|
||||
The default value of the OSR selection support is left at 1 which is the
|
||||
current default. Thus, the addition of the configuration support does
|
||||
not alter the default Jitter RNG behavior.
|
||||
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 17 +++++++++++++++++
|
||||
crypto/jitterentropy-kcapi.c | 6 ++++--
|
||||
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1340,6 +1340,23 @@ config CRYPTO_JITTERENTROPY_MEMORY_BLOCK
|
||||
default 1024 if CRYPTO_JITTERENTROPY_MEMSIZE_1024
|
||||
default 2048 if CRYPTO_JITTERENTROPY_MEMSIZE_8192
|
||||
|
||||
+config CRYPTO_JITTERENTROPY_OSR
|
||||
+ int "CPU Jitter RNG Oversampling Rate"
|
||||
+ range 1 15
|
||||
+ default 1
|
||||
+ depends on CRYPTO_JITTERENTROPY
|
||||
+ help
|
||||
+ The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
+ The Jitter RNG operation requires a fixed amount of timing
|
||||
+ measurements to produce one output block of random numbers. The
|
||||
+ OSR value is multiplied with the amount of timing measurements to
|
||||
+ generate one output block. Thus, the timing measurement is oversampled
|
||||
+ by the OSR factor. The oversampling allows the Jitter RNG to operate
|
||||
+ on hardware whose timers deliver limited amount of entropy (e.g.
|
||||
+ the timer is coarse) by setting the OSR to a higher value. The
|
||||
+ trade-off, however, is that the Jitter RNG now requires more time
|
||||
+ to generate random numbers.
|
||||
+
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
depends on CRYPTO_JITTERENTROPY
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -256,7 +256,9 @@ static int jent_kcapi_init(struct crypto
|
||||
crypto_shash_init(sdesc);
|
||||
rng->sdesc = sdesc;
|
||||
|
||||
- rng->entropy_collector = jent_entropy_collector_alloc(0, 0, sdesc);
|
||||
+ rng->entropy_collector =
|
||||
+ jent_entropy_collector_alloc(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0,
|
||||
+ sdesc);
|
||||
if (!rng->entropy_collector) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
@@ -345,7 +347,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(0, 0, desc);
|
||||
+ ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
@ -0,0 +1,117 @@
|
||||
From 8405ec8e3c02df8b3720874c3e2169fef4553868 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Sat, 7 Oct 2023 09:10:43 +0200
|
||||
Subject: [PATCH] crypto: jitter - reuse allocated entropy collector
|
||||
|
||||
In case a health test error occurs during runtime, the power-up health
|
||||
tests are rerun to verify that the noise source is still good and
|
||||
that the reported health test error was an outlier. For performing this
|
||||
power-up health test, the already existing entropy collector instance
|
||||
is used instead of allocating a new one. This change has the following
|
||||
implications:
|
||||
|
||||
* The noise that is collected as part of the newly run health tests is
|
||||
inserted into the entropy collector and thus stirs the existing
|
||||
data present in there further. Thus, the entropy collected during
|
||||
the health test is not wasted. This is also allowed by SP800-90B.
|
||||
|
||||
* The power-on health test is not affected by the state of the entropy
|
||||
collector, because it resets the APT / RCT state. The remainder of
|
||||
the state is unrelated to the health test as it is only applied to
|
||||
newly obtained time stamps.
|
||||
|
||||
This change also fixes a bug report about an allocation while in an
|
||||
atomic lock (the lock is taken in jent_kcapi_random, jent_read_entropy
|
||||
is called and this can call jent_entropy_init).
|
||||
|
||||
Fixes: 04597c8dd6c4 ("jitter - add RCT/APT support for different OSRs")
|
||||
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 2 +-
|
||||
crypto/jitterentropy.c | 36 ++++++++++++++++++++++++++----------
|
||||
crypto/jitterentropy.h | 2 +-
|
||||
3 files changed, 28 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -347,7 +347,7 @@ static int __init jent_mod_init(void)
|
||||
|
||||
desc->tfm = tfm;
|
||||
crypto_shash_init(desc);
|
||||
- ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc);
|
||||
+ ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc, NULL);
|
||||
shash_desc_zero(desc);
|
||||
crypto_free_shash(tfm);
|
||||
if (ret) {
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -611,8 +611,7 @@ int jent_read_entropy(struct rand_data *
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(ec->osr, ec->flags,
|
||||
- ec->hash_state))
|
||||
+ if (jent_entropy_init(0, 0, NULL, ec))
|
||||
return -3;
|
||||
|
||||
return -2;
|
||||
@@ -686,14 +685,30 @@ void jent_entropy_collector_free(struct
|
||||
jent_zfree(entropy_collector);
|
||||
}
|
||||
|
||||
-int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state)
|
||||
+int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state,
|
||||
+ struct rand_data *p_ec)
|
||||
{
|
||||
- struct rand_data *ec;
|
||||
- int i, time_backwards = 0, ret = 0;
|
||||
+ /*
|
||||
+ * If caller provides an allocated ec, reuse it which implies that the
|
||||
+ * health test entropy data is used to further still the available
|
||||
+ * entropy pool.
|
||||
+ */
|
||||
+ struct rand_data *ec = p_ec;
|
||||
+ int i, time_backwards = 0, ret = 0, ec_free = 0;
|
||||
|
||||
- ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
- if (!ec)
|
||||
- return JENT_EMEM;
|
||||
+ if (!ec) {
|
||||
+ ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
+ if (!ec)
|
||||
+ return JENT_EMEM;
|
||||
+ ec_free = 1;
|
||||
+ } else {
|
||||
+ /* Reset the APT */
|
||||
+ jent_apt_reset(ec, 0);
|
||||
+ /* Ensure that a new APT base is obtained */
|
||||
+ ec->apt_base_set = 0;
|
||||
+ /* Reset the RCT */
|
||||
+ ec->rct_count = 0;
|
||||
+ }
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
* that we only have a few loop counts to do testing. These
|
||||
@@ -783,7 +798,8 @@ int jent_entropy_init(unsigned int osr,
|
||||
}
|
||||
|
||||
out:
|
||||
- jent_entropy_collector_free(ec);
|
||||
+ if (ec_free)
|
||||
+ jent_entropy_collector_free(ec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
--- a/crypto/jitterentropy.h
|
||||
+++ b/crypto/jitterentropy.h
|
||||
@@ -12,7 +12,7 @@ int jent_read_random_block(void *hash_st
|
||||
|
||||
struct rand_data;
|
||||
extern int jent_entropy_init(unsigned int osr, unsigned int flags,
|
||||
- void *hash_state);
|
||||
+ void *hash_state, struct rand_data *p_ec);
|
||||
extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
|
||||
unsigned int len);
|
||||
|
@ -0,0 +1,242 @@
|
||||
From cf27d9475f37fb69b5bc293e6e6d6c1d03cf7cc6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
|
||||
Date: Thu, 19 Oct 2023 09:40:42 +0200
|
||||
Subject: [PATCH] crypto: jitter - use permanent health test storage
|
||||
|
||||
The health test result in the current code is only given for the currently
|
||||
processed raw time stamp. This implies to react on the health test error,
|
||||
the result must be checked after each raw time stamp being processed. To
|
||||
avoid this constant checking requirement, any health test error is recorded
|
||||
and stored to be analyzed at a later time, if needed.
|
||||
|
||||
This change ensures that the power-up test catches any health test error.
|
||||
Without that patch, the power-up health test result is not enforced.
|
||||
|
||||
The introduced changes are already in use with the user space version of
|
||||
the Jitter RNG.
|
||||
|
||||
Fixes: 04597c8dd6c4 ("jitter - add RCT/APT support for different OSRs")
|
||||
Reported-by: Joachim Vandersmissen <git@jvdsn.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy.c | 125 ++++++++++++++++++++++++-----------------
|
||||
1 file changed, 74 insertions(+), 51 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy.c
|
||||
+++ b/crypto/jitterentropy.c
|
||||
@@ -100,6 +100,8 @@ struct rand_data {
|
||||
unsigned int apt_observations; /* Number of collected observations */
|
||||
unsigned int apt_count; /* APT counter */
|
||||
unsigned int apt_base; /* APT base reference */
|
||||
+ unsigned int health_failure; /* Record health failure */
|
||||
+
|
||||
unsigned int apt_base_set:1; /* APT base reference set? */
|
||||
};
|
||||
|
||||
@@ -121,6 +123,13 @@ struct rand_data {
|
||||
#define JENT_EHASH 11 /* Hash self test failed */
|
||||
#define JENT_EMEM 12 /* Can't allocate memory for initialization */
|
||||
|
||||
+#define JENT_RCT_FAILURE 1 /* Failure in RCT health test. */
|
||||
+#define JENT_APT_FAILURE 2 /* Failure in APT health test. */
|
||||
+#define JENT_PERMANENT_FAILURE_SHIFT 16
|
||||
+#define JENT_PERMANENT_FAILURE(x) (x << JENT_PERMANENT_FAILURE_SHIFT)
|
||||
+#define JENT_RCT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_RCT_FAILURE)
|
||||
+#define JENT_APT_FAILURE_PERMANENT JENT_PERMANENT_FAILURE(JENT_APT_FAILURE)
|
||||
+
|
||||
/*
|
||||
* The output n bits can receive more than n bits of min entropy, of course,
|
||||
* but the fixed output of the conditioning function can only asymptotically
|
||||
@@ -215,26 +224,22 @@ static void jent_apt_insert(struct rand_
|
||||
return;
|
||||
}
|
||||
|
||||
- if (delta_masked == ec->apt_base)
|
||||
+ if (delta_masked == ec->apt_base) {
|
||||
ec->apt_count++;
|
||||
|
||||
+ /* Note, ec->apt_count starts with one. */
|
||||
+ if (ec->apt_count >= ec->apt_cutoff_permanent)
|
||||
+ ec->health_failure |= JENT_APT_FAILURE_PERMANENT;
|
||||
+ else if (ec->apt_count >= ec->apt_cutoff)
|
||||
+ ec->health_failure |= JENT_APT_FAILURE;
|
||||
+ }
|
||||
+
|
||||
ec->apt_observations++;
|
||||
|
||||
if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
|
||||
jent_apt_reset(ec, delta_masked);
|
||||
}
|
||||
|
||||
-/* APT health test failure detection */
|
||||
-static int jent_apt_permanent_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->apt_count >= ec->apt_cutoff_permanent) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-static int jent_apt_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->apt_count >= ec->apt_cutoff) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
/***************************************************************************
|
||||
* Stuck Test and its use as Repetition Count Test
|
||||
*
|
||||
@@ -261,6 +266,30 @@ static void jent_rct_insert(struct rand_
|
||||
{
|
||||
if (stuck) {
|
||||
ec->rct_count++;
|
||||
+
|
||||
+ /*
|
||||
+ * The cutoff value is based on the following consideration:
|
||||
+ * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
+ * In addition, we require an entropy value H of 1/osr as this
|
||||
+ * is the minimum entropy required to provide full entropy.
|
||||
+ * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
|
||||
+ * deltas for inserting them into the entropy pool which should
|
||||
+ * then have (close to) DATA_SIZE_BITS bits of entropy in the
|
||||
+ * conditioned output.
|
||||
+ *
|
||||
+ * Note, ec->rct_count (which equals to value B in the pseudo
|
||||
+ * code of SP800-90B section 4.4.1) starts with zero. Hence
|
||||
+ * we need to subtract one from the cutoff value as calculated
|
||||
+ * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr
|
||||
+ * or 60*osr.
|
||||
+ */
|
||||
+ if ((unsigned int)ec->rct_count >= (60 * ec->osr)) {
|
||||
+ ec->rct_count = -1;
|
||||
+ ec->health_failure |= JENT_RCT_FAILURE_PERMANENT;
|
||||
+ } else if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
|
||||
+ ec->rct_count = -1;
|
||||
+ ec->health_failure |= JENT_RCT_FAILURE;
|
||||
+ }
|
||||
} else {
|
||||
/* Reset RCT */
|
||||
ec->rct_count = 0;
|
||||
@@ -316,38 +345,24 @@ static int jent_stuck(struct rand_data *
|
||||
}
|
||||
|
||||
/*
|
||||
- * The cutoff value is based on the following consideration:
|
||||
- * alpha = 2^-30 or 2^-60 as recommended in SP800-90B.
|
||||
- * In addition, we require an entropy value H of 1/osr as this is the minimum
|
||||
- * entropy required to provide full entropy.
|
||||
- * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr deltas for
|
||||
- * inserting them into the entropy pool which should then have (close to)
|
||||
- * DATA_SIZE_BITS bits of entropy in the conditioned output.
|
||||
+ * Report any health test failures
|
||||
*
|
||||
- * Note, ec->rct_count (which equals to value B in the pseudo code of SP800-90B
|
||||
- * section 4.4.1) starts with zero. Hence we need to subtract one from the
|
||||
- * cutoff value as calculated following SP800-90B. Thus
|
||||
- * C = ceil(-log_2(alpha)/H) = 30*osr or 60*osr.
|
||||
- */
|
||||
-static int jent_rct_permanent_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->rct_count >= (60 * ec->osr)) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-static int jent_rct_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return (ec->rct_count >= (30 * ec->osr)) ? 1 : 0;
|
||||
-}
|
||||
-
|
||||
-/* Report of health test failures */
|
||||
-static int jent_health_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return jent_rct_failure(ec) | jent_apt_failure(ec);
|
||||
-}
|
||||
+ * @ec [in] Reference to entropy collector
|
||||
+ *
|
||||
+ * @return a bitmask indicating which tests failed
|
||||
+ * 0 No health test failure
|
||||
+ * 1 RCT failure
|
||||
+ * 2 APT failure
|
||||
+ * 1<<JENT_PERMANENT_FAILURE_SHIFT RCT permanent failure
|
||||
+ * 2<<JENT_PERMANENT_FAILURE_SHIFT APT permanent failure
|
||||
+ */
|
||||
+static unsigned int jent_health_failure(struct rand_data *ec)
|
||||
+{
|
||||
+ /* Test is only enabled in FIPS mode */
|
||||
+ if (!fips_enabled)
|
||||
+ return 0;
|
||||
|
||||
-static int jent_permanent_health_failure(struct rand_data *ec)
|
||||
-{
|
||||
- return jent_rct_permanent_failure(ec) | jent_apt_permanent_failure(ec);
|
||||
+ return ec->health_failure;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
@@ -594,11 +609,12 @@ int jent_read_entropy(struct rand_data *
|
||||
return -1;
|
||||
|
||||
while (len > 0) {
|
||||
- unsigned int tocopy;
|
||||
+ unsigned int tocopy, health_test_result;
|
||||
|
||||
jent_gen_entropy(ec);
|
||||
|
||||
- if (jent_permanent_health_failure(ec)) {
|
||||
+ health_test_result = jent_health_failure(ec);
|
||||
+ if (health_test_result > JENT_PERMANENT_FAILURE_SHIFT) {
|
||||
/*
|
||||
* At this point, the Jitter RNG instance is considered
|
||||
* as a failed instance. There is no rerun of the
|
||||
@@ -606,13 +622,18 @@ int jent_read_entropy(struct rand_data *
|
||||
* is assumed to not further use this instance.
|
||||
*/
|
||||
return -3;
|
||||
- } else if (jent_health_failure(ec)) {
|
||||
+ } else if (health_test_result) {
|
||||
/*
|
||||
* Perform startup health tests and return permanent
|
||||
* error if it fails.
|
||||
*/
|
||||
- if (jent_entropy_init(0, 0, NULL, ec))
|
||||
+ if (jent_entropy_init(0, 0, NULL, ec)) {
|
||||
+ /* Mark the permanent error */
|
||||
+ ec->health_failure &=
|
||||
+ JENT_RCT_FAILURE_PERMANENT |
|
||||
+ JENT_APT_FAILURE_PERMANENT;
|
||||
return -3;
|
||||
+ }
|
||||
|
||||
return -2;
|
||||
}
|
||||
@@ -695,6 +716,7 @@ int jent_entropy_init(unsigned int osr,
|
||||
*/
|
||||
struct rand_data *ec = p_ec;
|
||||
int i, time_backwards = 0, ret = 0, ec_free = 0;
|
||||
+ unsigned int health_test_result;
|
||||
|
||||
if (!ec) {
|
||||
ec = jent_entropy_collector_alloc(osr, flags, hash_state);
|
||||
@@ -708,6 +730,9 @@ int jent_entropy_init(unsigned int osr,
|
||||
ec->apt_base_set = 0;
|
||||
/* Reset the RCT */
|
||||
ec->rct_count = 0;
|
||||
+ /* Reset intermittent, leave permanent health test result */
|
||||
+ ec->health_failure &= (~JENT_RCT_FAILURE);
|
||||
+ ec->health_failure &= (~JENT_APT_FAILURE);
|
||||
}
|
||||
|
||||
/* We could perform statistical tests here, but the problem is
|
||||
@@ -788,12 +813,10 @@ int jent_entropy_init(unsigned int osr,
|
||||
}
|
||||
|
||||
/* Did we encounter a health test failure? */
|
||||
- if (jent_rct_failure(ec)) {
|
||||
- ret = JENT_ERCT;
|
||||
- goto out;
|
||||
- }
|
||||
- if (jent_apt_failure(ec)) {
|
||||
- ret = JENT_EHEALTH;
|
||||
+ health_test_result = jent_health_failure(ec);
|
||||
+ if (health_test_result) {
|
||||
+ ret = (health_test_result & JENT_RCT_FAILURE) ? JENT_ERCT :
|
||||
+ JENT_EHEALTH;
|
||||
goto out;
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
From e7ed6473c2c8c4e45dd861bfa06e96189b11d8db Mon Sep 17 00:00:00 2001
|
||||
From: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Date: Mon, 6 Nov 2023 18:00:08 +0800
|
||||
Subject: [PATCH] crypto: jitterentropy - Hide esoteric Kconfig options under
|
||||
FIPS and EXPERT
|
||||
|
||||
As JITTERENTROPY is selected by default if you enable the CRYPTO
|
||||
API, any Kconfig options added there will show up for every single
|
||||
user. Hide the esoteric options under EXPERT as well as FIPS so
|
||||
that only distro makers will see them.
|
||||
|
||||
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Reviewed-by: Stephan Mueller <smueller@chronox.de>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 28 +++++++++++++++++++++++++---
|
||||
1 file changed, 25 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1297,10 +1297,12 @@ config CRYPTO_JITTERENTROPY
|
||||
|
||||
See https://www.chronox.de/jent/
|
||||
|
||||
+if CRYPTO_JITTERENTROPY
|
||||
+if CRYPTO_FIPS && EXPERT
|
||||
+
|
||||
choice
|
||||
prompt "CPU Jitter RNG Memory Size"
|
||||
default CRYPTO_JITTERENTROPY_MEMSIZE_2
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The Jitter RNG measures the execution time of memory accesses.
|
||||
Multiple consecutive memory accesses are performed. If the memory
|
||||
@@ -1344,7 +1346,6 @@ config CRYPTO_JITTERENTROPY_OSR
|
||||
int "CPU Jitter RNG Oversampling Rate"
|
||||
range 1 15
|
||||
default 1
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
The Jitter RNG operation requires a fixed amount of timing
|
||||
@@ -1359,7 +1360,6 @@ config CRYPTO_JITTERENTROPY_OSR
|
||||
|
||||
config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
bool "CPU Jitter RNG Test Interface"
|
||||
- depends on CRYPTO_JITTERENTROPY
|
||||
help
|
||||
The test interface allows a privileged process to capture
|
||||
the raw unconditioned high resolution time stamp noise that
|
||||
@@ -1377,6 +1377,28 @@ config CRYPTO_JITTERENTROPY_TESTINTERFAC
|
||||
|
||||
If unsure, select N.
|
||||
|
||||
+endif # if CRYPTO_FIPS && EXPERT
|
||||
+
|
||||
+if !(CRYPTO_FIPS && EXPERT)
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKS
|
||||
+ int
|
||||
+ default 64
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE
|
||||
+ int
|
||||
+ default 32
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_OSR
|
||||
+ int
|
||||
+ default 1
|
||||
+
|
||||
+config CRYPTO_JITTERENTROPY_TESTINTERFACE
|
||||
+ bool
|
||||
+
|
||||
+endif # if !(CRYPTO_FIPS && EXPERT)
|
||||
+endif # if CRYPTO_JITTERENTROPY
|
||||
+
|
||||
config CRYPTO_KDF800108_CTR
|
||||
tristate
|
||||
select CRYPTO_HMAC
|
@ -0,0 +1,30 @@
|
||||
From 6e61ee1ca551292d8714c35c92a019c41db79e4e Mon Sep 17 00:00:00 2001
|
||||
From: Thorsten Blum <thorsten.blum@toblux.com>
|
||||
Date: Wed, 27 Mar 2024 23:25:09 +0100
|
||||
Subject: [PATCH] crypto: jitter - Use kvfree_sensitive() to fix Coccinelle
|
||||
warning
|
||||
|
||||
Replace memzero_explicit() and kvfree() with kvfree_sensitive() to fix
|
||||
the following Coccinelle/coccicheck warning reported by
|
||||
kfree_sensitive.cocci:
|
||||
|
||||
WARNING opportunity for kfree_sensitive/kvfree_sensitive
|
||||
|
||||
Signed-off-by: Thorsten Blum <thorsten.blum@toblux.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/jitterentropy-kcapi.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/crypto/jitterentropy-kcapi.c
|
||||
+++ b/crypto/jitterentropy-kcapi.c
|
||||
@@ -61,8 +61,7 @@ void *jent_kvzalloc(unsigned int len)
|
||||
|
||||
void jent_kvzfree(void *ptr, unsigned int len)
|
||||
{
|
||||
- memzero_explicit(ptr, len);
|
||||
- kvfree(ptr);
|
||||
+ kvfree_sensitive(ptr, len);
|
||||
}
|
||||
|
||||
void *jent_zalloc(unsigned int len)
|
@ -0,0 +1,36 @@
|
||||
From 95a798d20060d2b648dd604321e347c85edfd783 Mon Sep 17 00:00:00 2001
|
||||
From: Stephan Mueller <smueller@chronox.de>
|
||||
Date: Mon, 12 Aug 2024 08:25:42 +0200
|
||||
Subject: [PATCH] crypto: jitter - set default OSR to 3
|
||||
|
||||
The user space Jitter RNG library uses the oversampling rate of 3 which
|
||||
implies that each time stamp is credited with 1/3 bit of entropy. To
|
||||
obtain 256 bits of entropy, 768 time stamps need to be sampled. The
|
||||
increase in OSR is applied based on a report where the Jitter RNG is
|
||||
used on a system exhibiting a challenging environment to collect
|
||||
entropy.
|
||||
|
||||
This OSR default value is now applied to the Linux kernel version of
|
||||
the Jitter RNG as well.
|
||||
|
||||
The increase in the OSR from 1 to 3 also implies that the Jitter RNG is
|
||||
now slower by default.
|
||||
|
||||
Reported-by: Jeff Barnes <jeffbarnes@microsoft.com>
|
||||
Signed-off-by: Stephan Mueller <smueller@chronox.com>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
crypto/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/crypto/Kconfig
|
||||
+++ b/crypto/Kconfig
|
||||
@@ -1345,7 +1345,7 @@ config CRYPTO_JITTERENTROPY_MEMORY_BLOCK
|
||||
config CRYPTO_JITTERENTROPY_OSR
|
||||
int "CPU Jitter RNG Oversampling Rate"
|
||||
range 1 15
|
||||
- default 1
|
||||
+ default 3
|
||||
help
|
||||
The Jitter RNG allows the specification of an oversampling rate (OSR).
|
||||
The Jitter RNG operation requires a fixed amount of timing
|
Loading…
x
Reference in New Issue
Block a user