]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: jitterentropy - Use SHA-3 library
authorDavid Howells <dhowells@redhat.com>
Thu, 26 Feb 2026 01:00:05 +0000 (17:00 -0800)
committerEric Biggers <ebiggers@kernel.org>
Mon, 9 Mar 2026 20:27:21 +0000 (13:27 -0700)
Make the jitterentropy RNG use the SHA-3 library API instead of
crypto_shash.  This ends up being quite a bit simpler, as various
dynamic allocations and error checks become unnecessary.

Signed-off-by: David Howells <dhowells@redhat.com>
Co-developed-by: Eric Biggers <ebiggers@kernel.org>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20260226010005.43528-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
crypto/Kconfig
crypto/jitterentropy-kcapi.c
crypto/jitterentropy.c
crypto/jitterentropy.h

index c977d40f906d360017a84a16d2bb9ff51b0373c1..b8608ef6823bf511ac03134c4b1761aeaac52853 100644 (file)
@@ -1177,8 +1177,8 @@ endif     # if CRYPTO_DRBG_MENU
 
 config CRYPTO_JITTERENTROPY
        tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)"
+       select CRYPTO_LIB_SHA3
        select CRYPTO_RNG
-       select CRYPTO_SHA3
        help
          CPU Jitter RNG (Random Number Generator) from the Jitterentropy library
 
index 7c880cf34c5233b539a414599cf82793e44054ce..4ad729357441021b72de8bbfc5298b28c09873d7 100644 (file)
@@ -37,7 +37,6 @@
  * DAMAGE.
  */
 
-#include <crypto/hash.h>
 #include <crypto/sha3.h>
 #include <linux/fips.h>
 #include <linux/kernel.h>
@@ -48,8 +47,6 @@
 
 #include "jitterentropy.h"
 
-#define JENT_CONDITIONING_HASH "sha3-256"
-
 /***************************************************************************
  * Helper function
  ***************************************************************************/
@@ -101,22 +98,14 @@ void jent_get_nstime(__u64 *out)
        jent_raw_hires_entropy_store(tmp);
 }
 
-int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
-                  unsigned int addtl_len, __u64 hash_loop_cnt,
-                  unsigned int stuck)
+void jent_hash_time(struct sha3_ctx *hash_state, __u64 time, u8 *addtl,
+                   unsigned int addtl_len, __u64 hash_loop_cnt,
+                   unsigned int stuck)
 {
-       struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state;
-       SHASH_DESC_ON_STACK(desc, hash_state_desc->tfm);
+       struct sha3_ctx tmp_state; /* zeroized by sha3_final() */
        u8 intermediary[SHA3_256_DIGEST_SIZE];
        __u64 j = 0;
-       int ret;
-
-       desc->tfm = hash_state_desc->tfm;
 
-       if (sizeof(intermediary) != crypto_shash_digestsize(desc->tfm)) {
-               pr_warn_ratelimited("Unexpected digest size\n");
-               return -EINVAL;
-       }
        kmsan_unpoison_memory(intermediary, sizeof(intermediary));
 
        /*
@@ -130,24 +119,20 @@ int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
         *
         * Note, it does not matter which or how much data you inject, we are
         * interested in one Keccack1600 compression operation performed with
-        * the crypto_shash_final.
+        * the sha3_final.
         */
        for (j = 0; j < hash_loop_cnt; j++) {
-               ret = crypto_shash_init(desc) ?:
-                     crypto_shash_update(desc, intermediary,
-                                         sizeof(intermediary)) ?:
-                     crypto_shash_finup(desc, addtl, addtl_len, intermediary);
-               if (ret)
-                       goto err;
+               sha3_256_init(&tmp_state);
+               sha3_update(&tmp_state, intermediary, sizeof(intermediary));
+               sha3_update(&tmp_state, addtl, addtl_len);
+               sha3_final(&tmp_state, intermediary);
        }
 
        /*
         * Inject the data from the previous loop into the pool. This data is
         * not considered to contain any entropy, but it stirs the pool a bit.
         */
-       ret = crypto_shash_update(hash_state_desc, intermediary, sizeof(intermediary));
-       if (ret)
-               goto err;
+       sha3_update(hash_state, intermediary, sizeof(intermediary));
 
        /*
         * Insert the time stamp into the hash context representing the pool.
@@ -162,30 +147,24 @@ int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
                time = 0;
        }
 
-       ret = crypto_shash_update(hash_state_desc, (u8 *)&time, sizeof(__u64));
-
-err:
-       shash_desc_zero(desc);
+       sha3_update(hash_state, (u8 *)&time, sizeof(__u64));
        memzero_explicit(intermediary, sizeof(intermediary));
-
-       return ret;
 }
 
-int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len)
+void jent_read_random_block(struct sha3_ctx *hash_state, char *dst,
+                           unsigned int dst_len)
 {
-       struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state;
        u8 jent_block[SHA3_256_DIGEST_SIZE];
+
        /* Obtain data from entropy pool and re-initialize it */
-       int ret = crypto_shash_final(hash_state_desc, jent_block) ?:
-                 crypto_shash_init(hash_state_desc) ?:
-                 crypto_shash_update(hash_state_desc, jent_block,
-                                     sizeof(jent_block));
+       sha3_final(hash_state, jent_block);
+       sha3_256_init(hash_state);
+       sha3_update(hash_state, jent_block, sizeof(jent_block));
 
-       if (!ret && dst_len)
+       if (dst_len)
                memcpy(dst, jent_block, dst_len);
 
        memzero_explicit(jent_block, sizeof(jent_block));
-       return ret;
 }
 
 /***************************************************************************
@@ -195,8 +174,7 @@ int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len)
 struct jitterentropy {
        spinlock_t jent_lock;
        struct rand_data *entropy_collector;
-       struct crypto_shash *tfm;
-       struct shash_desc *sdesc;
+       struct sha3_ctx hash_state;
 };
 
 static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
@@ -205,15 +183,7 @@ static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
 
        spin_lock(&rng->jent_lock);
 
-       if (rng->sdesc) {
-               shash_desc_zero(rng->sdesc);
-               kfree(rng->sdesc);
-       }
-       rng->sdesc = NULL;
-
-       if (rng->tfm)
-               crypto_free_shash(rng->tfm);
-       rng->tfm = NULL;
+       memzero_explicit(&rng->hash_state, sizeof(rng->hash_state));
 
        if (rng->entropy_collector)
                jent_entropy_collector_free(rng->entropy_collector);
@@ -224,34 +194,15 @@ static void jent_kcapi_cleanup(struct crypto_tfm *tfm)
 static int jent_kcapi_init(struct crypto_tfm *tfm)
 {
        struct jitterentropy *rng = crypto_tfm_ctx(tfm);
-       struct crypto_shash *hash;
-       struct shash_desc *sdesc;
-       int size, ret = 0;
+       int ret = 0;
 
        spin_lock_init(&rng->jent_lock);
 
        /* Use SHA3-256 as conditioner */
-       hash = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0);
-       if (IS_ERR(hash)) {
-               pr_err("Cannot allocate conditioning digest\n");
-               return PTR_ERR(hash);
-       }
-       rng->tfm = hash;
-
-       size = sizeof(struct shash_desc) + crypto_shash_descsize(hash);
-       sdesc = kmalloc(size, GFP_KERNEL);
-       if (!sdesc) {
-               ret = -ENOMEM;
-               goto err;
-       }
-
-       sdesc->tfm = hash;
-       crypto_shash_init(sdesc);
-       rng->sdesc = sdesc;
+       sha3_256_init(&rng->hash_state);
 
-       rng->entropy_collector =
-               jent_entropy_collector_alloc(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0,
-                                            sdesc);
+       rng->entropy_collector = jent_entropy_collector_alloc(
+               CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, &rng->hash_state);
        if (!rng->entropy_collector) {
                ret = -ENOMEM;
                goto err;
@@ -326,23 +277,16 @@ static struct rng_alg jent_alg = {
 
 static int __init jent_mod_init(void)
 {
-       SHASH_DESC_ON_STACK(desc, tfm);
-       struct crypto_shash *tfm;
+       struct sha3_ctx hash_state;
        int ret = 0;
 
        jent_testing_init();
 
-       tfm = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0);
-       if (IS_ERR(tfm)) {
-               jent_testing_exit();
-               return PTR_ERR(tfm);
-       }
+       sha3_256_init(&hash_state);
 
-       desc->tfm = tfm;
-       crypto_shash_init(desc);
-       ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, desc, NULL);
-       shash_desc_zero(desc);
-       crypto_free_shash(tfm);
+       ret = jent_entropy_init(CONFIG_CRYPTO_JITTERENTROPY_OSR, 0, &hash_state,
+                               NULL);
+       memzero_explicit(&hash_state, sizeof(hash_state));
        if (ret) {
                /* Handle permanent health test error */
                if (fips_enabled)
index 3f93cdc9a7afbbfa6effb9080dbb815a40a72d5f..d5832caa8ab3cd0c3592204c9ebfdfd6f9a21f20 100644 (file)
@@ -68,7 +68,7 @@ struct rand_data {
         * of the RNG are marked as SENSITIVE. A user must not
         * access that information while the RNG executes its loops to
         * calculate the next random value. */
-       void *hash_state;               /* SENSITIVE hash state entropy pool */
+       struct sha3_ctx *hash_state;    /* SENSITIVE hash state entropy pool */
        __u64 prev_time;                /* SENSITIVE Previous time stamp */
        __u64 last_delta;               /* SENSITIVE stuck test */
        __s64 last_delta2;              /* SENSITIVE stuck test */
@@ -417,10 +417,9 @@ static __u64 jent_loop_shuffle(unsigned int bits, unsigned int min)
  * time [in] time stamp to be injected
  * stuck [in] Is the time stamp identified as stuck?
  *
- * Output:
- * updated hash context in the entropy collector or error code
+ * Output: updated hash context in the entropy collector
  */
-static int jent_condition_data(struct rand_data *ec, __u64 time, int stuck)
+static void jent_condition_data(struct rand_data *ec, __u64 time, int stuck)
 {
 #define SHA3_HASH_LOOP (1<<3)
        struct {
@@ -435,8 +434,8 @@ static int jent_condition_data(struct rand_data *ec, __u64 time, int stuck)
                ec->apt_base
        };
 
-       return jent_hash_time(ec->hash_state, time, (u8 *)&addtl, sizeof(addtl),
-                             SHA3_HASH_LOOP, stuck);
+       jent_hash_time(ec->hash_state, time, (u8 *)&addtl, sizeof(addtl),
+                      SHA3_HASH_LOOP, stuck);
 }
 
 /*
@@ -538,8 +537,7 @@ static int jent_measure_jitter(struct rand_data *ec, __u64 *ret_current_delta)
        stuck = jent_stuck(ec, current_delta);
 
        /* Now call the next noise sources which also injects the data */
-       if (jent_condition_data(ec, current_delta, stuck))
-               stuck = 1;
+       jent_condition_data(ec, current_delta, stuck);
 
        /* return the raw entropy value */
        if (ret_current_delta)
@@ -597,7 +595,7 @@ static void jent_gen_entropy(struct rand_data *ec)
  * @return 0 when request is fulfilled or an error
  *
  * The following error codes can occur:
- *     -1      entropy_collector is NULL or the generation failed
+ *     -1      entropy_collector is NULL
  *     -2      Intermittent health failure
  *     -3      Permanent health failure
  */
@@ -640,8 +638,7 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
                }
 
                tocopy = min(DATA_SIZE_BITS / 8, len);
-               if (jent_read_random_block(ec->hash_state, p, tocopy))
-                       return -1;
+               jent_read_random_block(ec->hash_state, p, tocopy);
 
                len -= tocopy;
                p += tocopy;
@@ -656,7 +653,7 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
 
 struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
                                               unsigned int flags,
-                                              void *hash_state)
+                                              struct sha3_ctx *hash_state)
 {
        struct rand_data *entropy_collector;
 
@@ -704,8 +701,8 @@ void jent_entropy_collector_free(struct rand_data *entropy_collector)
        jent_zfree(entropy_collector);
 }
 
-int jent_entropy_init(unsigned int osr, unsigned int flags, void *hash_state,
-                     struct rand_data *p_ec)
+int jent_entropy_init(unsigned int osr, unsigned int flags,
+                     struct sha3_ctx *hash_state, struct rand_data *p_ec)
 {
        /*
         * If caller provides an allocated ec, reuse it which implies that the
index 4c5dbf2a8d8f95690d44b92a43e5308bc228bb23..5bb15cb3300098d8d88549f59ad53e02897de593 100644 (file)
@@ -1,24 +1,27 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+struct sha3_ctx;
 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);
-extern int jent_hash_time(void *hash_state, __u64 time, u8 *addtl,
-                         unsigned int addtl_len, __u64 hash_loop_cnt,
-                         unsigned int stuck);
-int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len);
+void jent_hash_time(struct sha3_ctx *hash_state, __u64 time, u8 *addtl,
+                   unsigned int addtl_len, __u64 hash_loop_cnt,
+                   unsigned int stuck);
+void jent_read_random_block(struct sha3_ctx *hash_state, char *dst,
+                           unsigned int dst_len);
 
 struct rand_data;
 extern int jent_entropy_init(unsigned int osr, unsigned int flags,
-                            void *hash_state, struct rand_data *p_ec);
+                            struct sha3_ctx *hash_state,
+                            struct rand_data *p_ec);
 extern int jent_read_entropy(struct rand_data *ec, unsigned char *data,
                             unsigned int len);
 
-extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
-                                                     unsigned int flags,
-                                                     void *hash_state);
+extern struct rand_data *
+jent_entropy_collector_alloc(unsigned int osr, unsigned int flags,
+                            struct sha3_ctx *hash_state);
 extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
 
 #ifdef CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE