lede/target/linux/generic/backport-6.6/906-05-v6.7-crypto-jitter-use-permanent-health-test-storage.patch
Shiji Yang 71813b0d03 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>
2025-04-10 11:59:41 +08:00

243 lines
8.3 KiB
Diff

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