mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
crypto: jitterentropy - Use SHA-3 library
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>
This commit is contained in:
committed by
Eric Biggers
parent
5e07ce4663
commit
ce260754bb
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
if (!ret && dst_len)
|
||||
/* Obtain data from entropy pool and re-initialize it */
|
||||
sha3_final(hash_state, jent_block);
|
||||
sha3_256_init(hash_state);
|
||||
sha3_update(hash_state, jent_block, sizeof(jent_block));
|
||||
|
||||
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;
|
||||
sha3_256_init(&rng->hash_state);
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user