linux-crypto.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] Common entropy source and DRNG management
@ 2022-01-26  7:02 Stephan Müller
  2022-01-26  7:03 ` [PATCH 1/7] crypto: DRBG - remove internal reseeding operation Stephan Müller
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:02 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The current code base of the kernel crypto API random number support
leaves the task to seed and reseed the DRNG to either the caller or
the DRNG implementation. The code in crypto/drbg.c implements its own
seeding strategy. crypto/ansi_cprng.c does not contain any seeding
operation. The implementation in arch/s390/crypto/prng.c has yet
another approach for seeding. Albeit the crypto_rng_reset() contains
a seeding logic from get_random_bytes, there is no management of
the DRNG to ensure proper reseeding or control which entropy sources
are used for pulling data from.

The task of seeding and reseeding a DRNG including the controlling
of the state of the entropy sources is security sensitive as the
strength of the data obtained from the DRNG rests in large parts on
the proper seeding. In addition, various aspects need to be considered
when (re)seeding a DRNG. This gap is filled with the Entropy Source and
DRNG Manager (ESDM) proposed by this patch set.

The ESDM consists of two managers: the manager for the DRNG(s) and
manager for the entropy sources. The DRNG manager ensures that DRNGs
are properly seeded before random numbers are obtained from them.
Similarly, the entropy source manager ensures that the available
entropy sources are properly initialized if needed, and that data
is obtained with an appropriately considered entropy rate.

Both, the DRNG and entropy source managers offer a pluggable interface
allowing to use different DRNG implementations as well as various
entropy sources. Each provided entropy source may be enabled during
compile time. The ESDM therefore provides flexibility in the future
to extend the set of entropy sources or the supported DRNGs to the
required algorithms.

The patch set consists of the following changes:

- Patch 1 removes the seeding and reseeding logic from the DRBG
  transforming it into a pure deterministic implementation.

- Patch 2 removes the special AF_ALG interface used to test
  the DRBG implementation which requires bypassing of the DRBG
  automated seeding from entropy sources. With patch 1 this is
  not needed any more.

- Patch 3 adds the ESDM with its DRNG and entropy source
  managers. It contains the support to use the kernel crypto
  API's DRNG implementations.

- Patches 4 and 5 use the existing Jitter RNG as an entropy
  source for the ESDM.

- Patch 6 provides the glue code to use the get_random_bytes
  function as entropy source to the ESDM.

- Patch 7 adds the ESDM interface to register it with the kernel
  crypto API RNG framework as "stdrng" with the highest priority.
  This way, the ESDM is used per default when using the call
  crypto_get_default_rng().

With this patch series, callers to the kernel crypto API would not
experience any difference. When using the RNG framework, the function
crypto_get_default_rng is commonly used. Instead of providing the
DRBG implementation, the ESDM is used which returns random numbers
from a properly seeded DRBG.

Stephan Mueller (7):
  crypto: DRBG - remove internal reseeding operation
  crypto: AF_ALG - remove ALG_SET_DRBG_ENTROPY interface
  crypto: Entropy Source and DRNG Manager
  crypto: move Jitter RNG header include dir
  crypto: ESDM - add Jitter RNG entropy source
  crypto: ESDM - add Kernel RNG entropy source
  crypto: ESDM - add kernel crypto API RNG interface

 crypto/Kconfig                                |  11 +-
 crypto/Makefile                               |   1 +
 crypto/af_alg.c                               |   7 -
 crypto/algif_rng.c                            |  74 +-
 crypto/drbg.c                                 | 640 ++++-------------
 crypto/esdm/Kconfig                           | 166 +++++
 crypto/esdm/Makefile                          |  15 +
 crypto/esdm/esdm_definitions.h                | 141 ++++
 crypto/esdm/esdm_drng_kcapi.c                 | 202 ++++++
 crypto/esdm/esdm_drng_kcapi.h                 |  13 +
 crypto/esdm/esdm_drng_mgr.c                   | 398 +++++++++++
 crypto/esdm/esdm_drng_mgr.h                   |  85 +++
 crypto/esdm/esdm_es_aux.c                     | 332 +++++++++
 crypto/esdm/esdm_es_aux.h                     |  44 ++
 crypto/esdm/esdm_es_jent.c                    | 128 ++++
 crypto/esdm/esdm_es_jent.h                    |  17 +
 crypto/esdm/esdm_es_krng.c                    | 120 ++++
 crypto/esdm/esdm_es_krng.h                    |  17 +
 crypto/esdm/esdm_es_mgr.c                     | 372 ++++++++++
 crypto/esdm/esdm_es_mgr.h                     |  46 ++
 crypto/esdm/esdm_es_mgr_cb.h                  |  73 ++
 crypto/esdm/esdm_interface_kcapi.c            |  91 +++
 crypto/esdm/esdm_sha.h                        |  14 +
 crypto/esdm/esdm_sha256.c                     |  72 ++
 crypto/jitterentropy-kcapi.c                  |   3 +-
 crypto/jitterentropy.c                        |   2 +-
 crypto/testmgr.c                              | 104 +--
 crypto/testmgr.h                              | 641 +-----------------
 include/crypto/drbg.h                         |  84 ---
 include/crypto/esdm.h                         | 115 ++++
 include/crypto/if_alg.h                       |   1 -
 .../crypto/internal}/jitterentropy.h          |   0
 include/crypto/internal/rng.h                 |   6 -
 include/crypto/rng.h                          |   4 -
 include/uapi/linux/if_alg.h                   |   2 +-
 35 files changed, 2615 insertions(+), 1426 deletions(-)
 create mode 100644 crypto/esdm/Kconfig
 create mode 100644 crypto/esdm/Makefile
 create mode 100644 crypto/esdm/esdm_definitions.h
 create mode 100644 crypto/esdm/esdm_drng_kcapi.c
 create mode 100644 crypto/esdm/esdm_drng_kcapi.h
 create mode 100644 crypto/esdm/esdm_drng_mgr.c
 create mode 100644 crypto/esdm/esdm_drng_mgr.h
 create mode 100644 crypto/esdm/esdm_es_aux.c
 create mode 100644 crypto/esdm/esdm_es_aux.h
 create mode 100644 crypto/esdm/esdm_es_jent.c
 create mode 100644 crypto/esdm/esdm_es_jent.h
 create mode 100644 crypto/esdm/esdm_es_krng.c
 create mode 100644 crypto/esdm/esdm_es_krng.h
 create mode 100644 crypto/esdm/esdm_es_mgr.c
 create mode 100644 crypto/esdm/esdm_es_mgr.h
 create mode 100644 crypto/esdm/esdm_es_mgr_cb.h
 create mode 100644 crypto/esdm/esdm_interface_kcapi.c
 create mode 100644 crypto/esdm/esdm_sha.h
 create mode 100644 crypto/esdm/esdm_sha256.c
 create mode 100644 include/crypto/esdm.h
 rename {crypto => include/crypto/internal}/jitterentropy.h (100%)

-- 
2.33.1





^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/7] crypto: DRBG - remove internal reseeding operation
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
@ 2022-01-26  7:03 ` Stephan Müller
  2022-01-26 12:15   ` kernel test robot
  2022-01-26  7:03 ` [PATCH 2/7] crypto: AF_ALG - remove ALG_SET_DRBG_ENTROPY interface Stephan Müller
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:03 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The DRBG's internal seeding support is completely removed. When
initializing the DRBG, it is now completely unseeded. The caller must
provide the seed data and perform the reseeding as needed using the
standard API of crypto_rng_reset.

The seeding and reseeding is a security-critical task which is provided
with a separate framework, the entropy source and DRNG manager (ESDM).
When using the ESDM, the DRBG may be integrated to offer a fully seeded
DRBG. The output of the ESDM in this case is generated from the DRBG,
but the ESDM ensures the DRBG is appropriately seeded and reseeded.

The change removes the "prediction resistance" variants of the DRBG.
Those variants would cause the DRBG to constantly reseed from the
entropy sources. As the seeding is appropriately performed by the ESDM,
the prediction resistance variants are not needed.

Due to the limitations of the kernel crypto API RNG framework, adding a
personalization string is not supported during initial seeding. In
addition, providing an additional information string during reseeding is
not supported by the DRBG. If a user wants to still apply either string,
the caller must concatenate it to the seed that is submitted to the
DRBG. Yet, using an additional information string during the
generation of random numbers is supported. The patch implies that the
DRBG fully complies with the kernel crypto API RNG framework interfaces.
All auxiliary interfaces are removed.

The change also simplifies the drbg_instantiate function: the resolution
of the coreref is now performed in the drbg_instantiate function as it
is only needed during initial seeding. Subsequent reseeding operations
flowing through this function do not need to perform this resolution.

The DRBG code now rejects the initial instantiation with an empty seed
buffer. An empty seed buffer during initial instantiation implies that
the DRBG will not be seeded and does not have any internal state based
on seed. Thus, a crypto_rng_reset(tfm, NULL, 0) immediately after an
crypto_alloc_rng() will now fail.

In addition, the patch removes FIPS 140-2 continuous test as its
more sane equivalent is handled by the ESDM by applying a proper health
test to the entropy sources that deliver entropy.

The change is validated with the NIST ACVP reference implementation. The
testing covered:

- Hash DRBG with SHA-1, SHA-256, SHA-384, SHA-512

- HMAC DRBG with SHA-1, SHA-256, SHA-384, SHA-512

- CTR DRBG with AES-128, AES-192, AES-256

- reseeding, but without additional information

- no reseeding, but with additional information

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/algif_rng.c    |   3 +-
 crypto/drbg.c         | 640 ++++++++---------------------------------
 crypto/testmgr.c      |  96 +------
 crypto/testmgr.h      | 641 +-----------------------------------------
 include/crypto/drbg.h |  84 ------
 5 files changed, 140 insertions(+), 1324 deletions(-)

diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index 407408c43730..b204f1427542 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -305,7 +305,8 @@ static int __maybe_unused rng_setentropy(void *private, sockptr_t entropy,
 			return PTR_ERR(kentropy);
 	}
 
-	crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
+	if (crypto_rng_alg(pctx->drng)->set_ent)
+		crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
 	/*
 	 * Since rng doesn't perform any memory management for the entropy
 	 * buffer, save kentropy pointer to pctx now to free it after use.
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 177983b6ae38..67d9fef1af2a 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -7,7 +7,7 @@
  *		* HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
  *		* with and without prediction resistance
  *
- * Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2014 - 2022
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,10 +43,10 @@
  *
  * DRBG Usage
  * ==========
- * The SP 800-90A DRBG allows the user to specify a personalization string
- * for initialization as well as an additional information string for each
- * random number request. The following code fragments show how a caller
- * uses the kernel crypto API to use the full functionality of the DRBG.
+ * The SP 800-90A DRBG allows the user to specify an additional information
+ * string for each random number request. The following code fragments show how
+ * a caller uses the kernel crypto API to use the full functionality of the
+ * DRBG.
  *
  * Usage without any additional data
  * ---------------------------------
@@ -55,25 +55,22 @@
  * char data[DATALEN];
  *
  * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset initializes the DRBG with the provided seed string
+ * err = crypto_rng_reset(drng, &seed, strlen(seed));
  * err = crypto_rng_get_bytes(drng, &data, DATALEN);
  * crypto_free_rng(drng);
  *
  *
  * Usage with personalization string during initialization
  * -------------------------------------------------------
- * struct crypto_rng *drng;
- * int err;
- * char data[DATALEN];
- * struct drbg_string pers;
- * char personalization[11] = "some-string";
+ * This is not supported internally. If you want to use a personalization
+ * string during seeding, concatenate it at the end of the seed.
  *
- * drbg_string_fill(&pers, personalization, strlen(personalization));
- * drng = crypto_alloc_rng(drng_name, 0, 0);
- * // The reset completely re-initializes the DRBG with the provided
- * // personalization string
- * err = crypto_rng_reset(drng, &personalization, strlen(personalization));
- * err = crypto_rng_get_bytes(drng, &data, DATALEN);
- * crypto_free_rng(drng);
+ *
+ * Usage with additional information during reseeding
+ * --------------------------------------------------
+ * This is not supported internally. If you want to use an additional
+ * string during reseeding, concatenate it at the end of the reseed.
  *
  *
  * Usage with additional information string during random number request
@@ -81,20 +78,17 @@
  * struct crypto_rng *drng;
  * int err;
  * char data[DATALEN];
+ * char addtlbuf[ADDTLLEN];
  * char addtl_string[11] = "some-string";
- * string drbg_string addtl;
  *
  * drbg_string_fill(&addtl, addtl_string, strlen(addtl_string));
  * drng = crypto_alloc_rng(drng_name, 0, 0);
+ * // The reset initializes the DRBG with the provided seed string
+ * err = crypto_rng_reset(drng, &seed, strlen(seed));
  * // The following call is a wrapper to crypto_rng_get_bytes() and returns
  * // the same error codes.
- * err = crypto_drbg_get_bytes_addtl(drng, &data, DATALEN, &addtl);
+ * err = crypto_rng_generate(drng, addtlbuf, ADDTLLEN, &data, DATALEN, &addtl);
  * crypto_free_rng(drng);
- *
- *
- * Usage with personalization and additional information strings
- * -------------------------------------------------------------
- * Just mix both scenarios above.
  */
 
 #include <crypto/drbg.h>
@@ -221,57 +215,6 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
 	}
 }
 
-/*
- * FIPS 140-2 continuous self test for the noise source
- * The test is performed on the noise source input data. Thus, the function
- * implicitly knows the size of the buffer to be equal to the security
- * strength.
- *
- * Note, this function disregards the nonce trailing the entropy data during
- * initial seeding.
- *
- * drbg->drbg_mutex must have been taken.
- *
- * @drbg DRBG handle
- * @entropy buffer of seed data to be checked
- *
- * return:
- *	0 on success
- *	-EAGAIN on when the CTRNG is not yet primed
- *	< 0 on error
- */
-static int drbg_fips_continuous_test(struct drbg_state *drbg,
-				     const unsigned char *entropy)
-{
-	unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
-	int ret = 0;
-
-	if (!IS_ENABLED(CONFIG_CRYPTO_FIPS))
-		return 0;
-
-	/* skip test if we test the overall system */
-	if (list_empty(&drbg->test_data.list))
-		return 0;
-	/* only perform test in FIPS mode */
-	if (!fips_enabled)
-		return 0;
-
-	if (!drbg->fips_primed) {
-		/* Priming of FIPS test */
-		memcpy(drbg->prev, entropy, entropylen);
-		drbg->fips_primed = true;
-		/* priming: another round is needed */
-		return -EAGAIN;
-	}
-	ret = memcmp(drbg->prev, entropy, entropylen);
-	if (!ret)
-		panic("DRBG continuous self test failed\n");
-	memcpy(drbg->prev, entropy, entropylen);
-
-	/* the test shall pass when the two values are not equal */
-	return 0;
-}
-
 /*
  * Convert an integer into a byte representation of this integer.
  * The byte representation is big-endian
@@ -298,11 +241,8 @@ static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
 
 #ifdef CONFIG_CRYPTO_DRBG_CTR
 #define CRYPTO_DRBG_CTR_STRING "CTR "
-MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes256");
 MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes256");
-MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes192");
 MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes192");
-MODULE_ALIAS_CRYPTO("drbg_pr_ctr_aes128");
 MODULE_ALIAS_CRYPTO("drbg_nopr_ctr_aes128");
 
 static void drbg_kcapi_symsetkey(struct drbg_state *drbg,
@@ -642,13 +582,9 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg);
 
 #ifdef CONFIG_CRYPTO_DRBG_HMAC
 #define CRYPTO_DRBG_HMAC_STRING "HMAC "
-MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
 MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
-MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha384");
 MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha384");
-MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha256");
 MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha256");
-MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha1");
 MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha1");
 
 /* update function of HMAC DRBG as defined in 10.1.2.2 */
@@ -762,13 +698,9 @@ static const struct drbg_state_ops drbg_hmac_ops = {
 
 #ifdef CONFIG_CRYPTO_DRBG_HASH
 #define CRYPTO_DRBG_HASH_STRING "HASH "
-MODULE_ALIAS_CRYPTO("drbg_pr_sha512");
 MODULE_ALIAS_CRYPTO("drbg_nopr_sha512");
-MODULE_ALIAS_CRYPTO("drbg_pr_sha384");
 MODULE_ALIAS_CRYPTO("drbg_nopr_sha384");
-MODULE_ALIAS_CRYPTO("drbg_pr_sha256");
 MODULE_ALIAS_CRYPTO("drbg_nopr_sha256");
-MODULE_ALIAS_CRYPTO("drbg_pr_sha1");
 MODULE_ALIAS_CRYPTO("drbg_nopr_sha1");
 
 /*
@@ -1036,221 +968,6 @@ static const struct drbg_state_ops drbg_hash_ops = {
  * Functions common for DRBG implementations
  ******************************************************************/
 
-static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
-			      int reseed, enum drbg_seed_state new_seed_state)
-{
-	int ret = drbg->d_ops->update(drbg, seed, reseed);
-
-	if (ret)
-		return ret;
-
-	drbg->seeded = new_seed_state;
-	drbg->last_seed_time = jiffies;
-	/* 10.1.1.2 / 10.1.1.3 step 5 */
-	drbg->reseed_ctr = 1;
-
-	switch (drbg->seeded) {
-	case DRBG_SEED_STATE_UNSEEDED:
-		/* Impossible, but handle it to silence compiler warnings. */
-		fallthrough;
-	case DRBG_SEED_STATE_PARTIAL:
-		/*
-		 * Require frequent reseeds until the seed source is
-		 * fully initialized.
-		 */
-		drbg->reseed_threshold = 50;
-		break;
-
-	case DRBG_SEED_STATE_FULL:
-		/*
-		 * Seed source has become fully initialized, frequent
-		 * reseeds no longer required.
-		 */
-		drbg->reseed_threshold = drbg_max_requests(drbg);
-		break;
-	}
-
-	return ret;
-}
-
-static inline int drbg_get_random_bytes(struct drbg_state *drbg,
-					unsigned char *entropy,
-					unsigned int entropylen)
-{
-	int ret;
-
-	do {
-		get_random_bytes(entropy, entropylen);
-		ret = drbg_fips_continuous_test(drbg, entropy);
-		if (ret && ret != -EAGAIN)
-			return ret;
-	} while (ret);
-
-	return 0;
-}
-
-static int drbg_seed_from_random(struct drbg_state *drbg)
-{
-	struct drbg_string data;
-	LIST_HEAD(seedlist);
-	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
-	unsigned char entropy[32];
-	int ret;
-
-	BUG_ON(!entropylen);
-	BUG_ON(entropylen > sizeof(entropy));
-
-	drbg_string_fill(&data, entropy, entropylen);
-	list_add_tail(&data.list, &seedlist);
-
-	ret = drbg_get_random_bytes(drbg, entropy, entropylen);
-	if (ret)
-		goto out;
-
-	ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
-
-out:
-	memzero_explicit(entropy, entropylen);
-	return ret;
-}
-
-static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
-{
-	unsigned long next_reseed;
-
-	/* Don't ever reseed from get_random_bytes() in test mode. */
-	if (list_empty(&drbg->test_data.list))
-		return false;
-
-	/*
-	 * Obtain fresh entropy for the nopr DRBGs after 300s have
-	 * elapsed in order to still achieve sort of partial
-	 * prediction resistance over the time domain at least. Note
-	 * that the period of 300s has been chosen to match the
-	 * CRNG_RESEED_INTERVAL of the get_random_bytes()' chacha
-	 * rngs.
-	 */
-	next_reseed = drbg->last_seed_time + 300 * HZ;
-	return time_after(jiffies, next_reseed);
-}
-
-/*
- * Seeding or reseeding of the DRBG
- *
- * @drbg: DRBG state struct
- * @pers: personalization / additional information buffer
- * @reseed: 0 for initial seed process, 1 for reseeding
- *
- * return:
- *	0 on success
- *	error value otherwise
- */
-static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
-		     bool reseed)
-{
-	int ret;
-	unsigned char entropy[((32 + 16) * 2)];
-	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
-	struct drbg_string data1;
-	LIST_HEAD(seedlist);
-	enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
-
-	/* 9.1 / 9.2 / 9.3.1 step 3 */
-	if (pers && pers->len > (drbg_max_addtl(drbg))) {
-		pr_devel("DRBG: personalization string too long %zu\n",
-			 pers->len);
-		return -EINVAL;
-	}
-
-	if (list_empty(&drbg->test_data.list)) {
-		drbg_string_fill(&data1, drbg->test_data.buf,
-				 drbg->test_data.len);
-		pr_devel("DRBG: using test entropy\n");
-	} else {
-		/*
-		 * Gather entropy equal to the security strength of the DRBG.
-		 * With a derivation function, a nonce is required in addition
-		 * to the entropy. A nonce must be at least 1/2 of the security
-		 * strength of the DRBG in size. Thus, entropy + nonce is 3/2
-		 * of the strength. The consideration of a nonce is only
-		 * applicable during initial seeding.
-		 */
-		BUG_ON(!entropylen);
-		if (!reseed)
-			entropylen = ((entropylen + 1) / 2) * 3;
-		BUG_ON((entropylen * 2) > sizeof(entropy));
-
-		/* Get seed from in-kernel /dev/urandom */
-		if (!rng_is_initialized())
-			new_seed_state = DRBG_SEED_STATE_PARTIAL;
-
-		ret = drbg_get_random_bytes(drbg, entropy, entropylen);
-		if (ret)
-			goto out;
-
-		if (!drbg->jent) {
-			drbg_string_fill(&data1, entropy, entropylen);
-			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
-				 entropylen);
-		} else {
-			/*
-			 * Get seed from Jitter RNG, failures are
-			 * fatal only in FIPS mode.
-			 */
-			ret = crypto_rng_get_bytes(drbg->jent,
-						   entropy + entropylen,
-						   entropylen);
-			if (fips_enabled && ret) {
-				pr_devel("DRBG: jent failed with %d\n", ret);
-
-				/*
-				 * Do not treat the transient failure of the
-				 * Jitter RNG as an error that needs to be
-				 * reported. The combined number of the
-				 * maximum reseed threshold times the maximum
-				 * number of Jitter RNG transient errors is
-				 * less than the reseed threshold required by
-				 * SP800-90A allowing us to treat the
-				 * transient errors as such.
-				 *
-				 * However, we mandate that at least the first
-				 * seeding operation must succeed with the
-				 * Jitter RNG.
-				 */
-				if (!reseed || ret != -EAGAIN)
-					goto out;
-			}
-
-			drbg_string_fill(&data1, entropy, entropylen * 2);
-			pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
-				 entropylen * 2);
-		}
-	}
-	list_add_tail(&data1.list, &seedlist);
-
-	/*
-	 * concatenation of entropy with personalization str / addtl input)
-	 * the variable pers is directly handed in by the caller, so check its
-	 * contents whether it is appropriate
-	 */
-	if (pers && pers->buf && 0 < pers->len) {
-		list_add_tail(&pers->list, &seedlist);
-		pr_devel("DRBG: using personalization string\n");
-	}
-
-	if (!reseed) {
-		memset(drbg->V, 0, drbg_statelen(drbg));
-		memset(drbg->C, 0, drbg_statelen(drbg));
-	}
-
-	ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
-
-out:
-	memzero_explicit(entropy, entropylen * 2);
-
-	return ret;
-}
-
 /* Free all substructures in a DRBG state without the DRBG state structure */
 static inline void drbg_dealloc_state(struct drbg_state *drbg)
 {
@@ -1267,11 +984,6 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
 	drbg->reseed_ctr = 0;
 	drbg->d_ops = NULL;
 	drbg->core = NULL;
-	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
-		kfree_sensitive(drbg->prev);
-		drbg->prev = NULL;
-		drbg->fips_primed = false;
-	}
 }
 
 /*
@@ -1314,12 +1026,14 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 		goto fini;
 	}
 	drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
+	memset(drbg->V, 0, drbg_statelen(drbg));
 	drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
 	if (!drbg->Cbuf) {
 		ret = -ENOMEM;
 		goto fini;
 	}
 	drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
+	memset(drbg->C, 0, drbg_statelen(drbg));
 	/* scratchpad is only generated for CTR and Hash */
 	if (drbg->core->flags & DRBG_HMAC)
 		sb_size = 0;
@@ -1341,16 +1055,6 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
 		drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
 	}
 
-	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
-		drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
-				     GFP_KERNEL);
-		if (!drbg->prev) {
-			ret = -ENOMEM;
-			goto fini;
-		}
-		drbg->fips_primed = false;
-	}
-
 	return 0;
 
 fini:
@@ -1419,40 +1123,18 @@ static int drbg_generate(struct drbg_state *drbg,
 	/* 9.3.1 step 5 is implicit with the chosen DRBG */
 
 	/*
-	 * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c is implemented
-	 * here. The spec is a bit convoluted here, we make it simpler.
+	 * 9.3.1 step 6 and 9 supplemented by 9.3.2 step c - the reseeding if
+	 * too much data is pulled - is not implemented here but must be
+	 * provided by the caller (e.g. the ESDM).
 	 */
-	if (drbg->reseed_threshold < drbg->reseed_ctr)
-		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
-
-	if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
-		pr_devel("DRBG: reseeding before generation (prediction "
-			 "resistance: %s, state %s)\n",
-			 drbg->pr ? "true" : "false",
-			 (drbg->seeded ==  DRBG_SEED_STATE_FULL ?
-			  "seeded" : "unseeded"));
-		/* 9.3.1 steps 7.1 through 7.3 */
-		len = drbg_seed(drbg, addtl, true);
-		if (len)
-			goto err;
-		/* 9.3.1 step 7.4 */
-		addtl = NULL;
-	} else if (rng_is_initialized() &&
-		   (drbg->seeded == DRBG_SEED_STATE_PARTIAL ||
-		    drbg_nopr_reseed_interval_elapsed(drbg))) {
-		len = drbg_seed_from_random(drbg);
-		if (len)
-			goto err;
-	}
 
 	if (addtl && 0 < addtl->len)
 		list_add_tail(&addtl->list, &addtllist);
 	/* 9.3.1 step 8 and 10 */
 	len = drbg->d_ops->generate(drbg, buf, buflen, &addtllist);
-
 	/* 10.1.1.4 step 6, 10.1.2.5 step 7, 10.2.1.5.2 step 7 */
 	drbg->reseed_ctr++;
-	if (0 >= len)
+	if (len < 0)
 		goto err;
 
 	/*
@@ -1475,14 +1157,14 @@ static int drbg_generate(struct drbg_state *drbg,
 		int err = 0;
 		pr_devel("DRBG: start to perform self test\n");
 		if (drbg->core->flags & DRBG_HMAC)
-			err = alg_test("drbg_pr_hmac_sha256",
-				       "drbg_pr_hmac_sha256", 0, 0);
+			err = alg_test("drbg_nopr_hmac_sha256",
+				       "drbg_nopr_hmac_sha256", 0, 0);
 		else if (drbg->core->flags & DRBG_CTR)
-			err = alg_test("drbg_pr_ctr_aes128",
-				       "drbg_pr_ctr_aes128", 0, 0);
+			err = alg_test("drbg_nopr_ctr_aes128",
+				       "drbg_nopr_ctr_aes128", 0, 0);
 		else
-			err = alg_test("drbg_pr_sha256",
-				       "drbg_pr_sha256", 0, 0);
+			err = alg_test("drbg_nopr_sha256",
+				       "drbg_nopr_sha256", 0, 0);
 		if (err) {
 			pr_err("DRBG: periodical self test failed\n");
 			/*
@@ -1535,96 +1217,123 @@ static int drbg_generate_long(struct drbg_state *drbg,
 	return 0;
 }
 
-static int drbg_prepare_hrng(struct drbg_state *drbg)
+/*
+ * Seeding or reseeding of the DRBG
+ *
+ * @drbg: DRBG state struct
+ * @pers: personalization / additional information buffer
+ * @reseed: 0 for initial seed process, 1 for reseeding
+ *
+ * return:
+ *	0 on success
+ *	error value otherwise
+ */
+static int drbg_seed(struct drbg_state *drbg, struct list_head *seed,
+		     int reseed)
 {
-	/* We do not need an HRNG in test mode. */
-	if (list_empty(&drbg->test_data.list))
-		return 0;
+	int ret = drbg->d_ops->update(drbg, seed, reseed);
 
-	drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
-	if (IS_ERR(drbg->jent)) {
-		const int err = PTR_ERR(drbg->jent);
+	if (ret)
+		return ret;
 
-		drbg->jent = NULL;
-		if (fips_enabled || err != -ENOENT)
-			return err;
-		pr_info("DRBG: Continuing without Jitter RNG\n");
-	}
+	/* 10.1.1.2 / 10.1.1.3 step 5 */
+	drbg->reseed_ctr = 1;
 
-	return 0;
+	return ret;
+}
+
+/*
+ * Look up the DRBG flags by given kernel crypto API cra_name
+ * The code uses the drbg_cores definition to do this
+ *
+ * @cra_name kernel crypto API cra_name
+ * @coreref reference to integer which is filled with the pointer to
+ *  the applicable core
+ */
+static inline int drbg_convert_tfm_core(const char *cra_driver_name,
+					int *coreref)
+{
+	int i = 0, len = 0;
+
+	len = strlen(cra_driver_name);
+	if (len < 10)
+		return -ENOENT;
+	len -= 10;
+
+	/* disassemble the name */
+	if (memcmp(cra_driver_name, "drbg_nopr_", 10))
+		return -ENOENT;
+
+	/* remove the first part */
+	for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
+		if (!memcmp(cra_driver_name + 10, drbg_cores[i].cra_name,
+			    len)) {
+			*coreref = i;
+			return 0;
+		}
+	}
+	return -ENOENT;
 }
 
 /*
  * DRBG instantiation function as required by SP800-90A - this function
- * sets up the DRBG handle, performs the initial seeding and all sanity
- * checks required by SP800-90A
+ * sets up the DRBG handle if needed and seeds the DRBG with entropy. If the
+ * DRBG is already instantiated, the DRBG is simply reseeded.
  *
- * @drbg memory of state -- if NULL, new memory is allocated
- * @pers Personalization string that is mixed into state, may be NULL -- note
- *	 the entropy is pulled by the DRBG internally unconditionally
- *	 as defined in SP800-90A. The additional input is mixed into
- *	 the state in addition to the pulled entropy.
- * @coreref reference to core
- * @pr prediction resistance enabled
+ * @tfm: tfm cipher handle with DRBG state (may be uninitialized)
+ * @seed: buffer with the entropy data to (re)seed the DRBG
+ * @slen: length of seed buffer
  *
  * return
  *	0 on success
  *	error value otherwise
  */
-static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
-			    int coreref, bool pr)
+static int drbg_instantiate(struct crypto_rng *tfm,
+			    const u8 *seed, unsigned int slen)
 {
+	struct drbg_state *drbg = crypto_rng_ctx(tfm);
+	struct drbg_string seeddata;
+	LIST_HEAD(seedlist);
 	int ret;
 	bool reseed = true;
 
-	pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
-		 "%s\n", coreref, pr ? "enabled" : "disabled");
+	drbg_string_fill(&seeddata, seed, slen);
+	list_add_tail(&seeddata.list, &seedlist);
+
 	mutex_lock(&drbg->drbg_mutex);
 
 	/* 9.1 step 1 is implicit with the selected DRBG type */
-
-	/*
-	 * 9.1 step 2 is implicit as caller can select prediction resistance
-	 * and the flag is copied into drbg->flags --
-	 * all DRBG types support prediction resistance
-	 */
-
+	/* 9.1 step 2 is implicit as no prediction resistance is supported */
 	/* 9.1 step 4 is implicit in  drbg_sec_strength */
 
 	if (!drbg->core) {
+		struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
+		int coreref = 0;
+
+		if (!slen) {
+			pr_warn("DRBG: initial seed missing\n");
+			return -EINVAL;
+		}
+
+		pr_devel("DRBG: Initializing DRBG core %d\n", coreref);
+		ret = drbg_convert_tfm_core(
+			crypto_tfm_alg_driver_name(tfm_base), &coreref);
+		if (ret)
+			return ret;
 		drbg->core = &drbg_cores[coreref];
-		drbg->pr = pr;
-		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
-		drbg->last_seed_time = 0;
-		drbg->reseed_threshold = drbg_max_requests(drbg);
 
 		ret = drbg_alloc_state(drbg);
 		if (ret)
 			goto unlock;
 
-		ret = drbg_prepare_hrng(drbg);
-		if (ret)
-			goto free_everything;
-
 		reseed = false;
 	}
 
-	ret = drbg_seed(drbg, pers, reseed);
-
-	if (ret && !reseed)
-		goto free_everything;
-
-	mutex_unlock(&drbg->drbg_mutex);
-	return ret;
+	ret = drbg_seed(drbg, &seedlist, reseed);
 
 unlock:
 	mutex_unlock(&drbg->drbg_mutex);
 	return ret;
-
-free_everything:
-	mutex_unlock(&drbg->drbg_mutex);
-	drbg_uninstantiate(drbg);
-	return ret;
 }
 
 /*
@@ -1638,34 +1347,12 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
  */
 static int drbg_uninstantiate(struct drbg_state *drbg)
 {
-	if (!IS_ERR_OR_NULL(drbg->jent))
-		crypto_free_rng(drbg->jent);
-	drbg->jent = NULL;
-
 	if (drbg->d_ops)
 		drbg->d_ops->crypto_fini(drbg);
 	drbg_dealloc_state(drbg);
-	/* no scrubbing of test_data -- this shall survive an uninstantiate */
 	return 0;
 }
 
-/*
- * Helper function for setting the test data in the DRBG
- *
- * @drbg DRBG state handle
- * @data test data
- * @len test data length
- */
-static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
-				   const u8 *data, unsigned int len)
-{
-	struct drbg_state *drbg = crypto_rng_ctx(tfm);
-
-	mutex_lock(&drbg->drbg_mutex);
-	drbg_string_fill(&drbg->test_data, data, len);
-	mutex_unlock(&drbg->drbg_mutex);
-}
-
 /***************************************************************
  * Kernel crypto API cipher invocations requested by DRBG
  ***************************************************************/
@@ -1884,46 +1571,6 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
  * Kernel crypto API interface to register DRBG
  ***************************************************************/
 
-/*
- * Look up the DRBG flags by given kernel crypto API cra_name
- * The code uses the drbg_cores definition to do this
- *
- * @cra_name kernel crypto API cra_name
- * @coreref reference to integer which is filled with the pointer to
- *  the applicable core
- * @pr reference for setting prediction resistance
- *
- * return: flags
- */
-static inline void drbg_convert_tfm_core(const char *cra_driver_name,
-					 int *coreref, bool *pr)
-{
-	int i = 0;
-	size_t start = 0;
-	int len = 0;
-
-	*pr = true;
-	/* disassemble the names */
-	if (!memcmp(cra_driver_name, "drbg_nopr_", 10)) {
-		start = 10;
-		*pr = false;
-	} else if (!memcmp(cra_driver_name, "drbg_pr_", 8)) {
-		start = 8;
-	} else {
-		return;
-	}
-
-	/* remove the first part */
-	len = strlen(cra_driver_name) - start;
-	for (i = 0; ARRAY_SIZE(drbg_cores) > i; i++) {
-		if (!memcmp(cra_driver_name + start, drbg_cores[i].cra_name,
-			    len)) {
-			*coreref = i;
-			return;
-		}
-	}
-}
-
 static int drbg_kcapi_init(struct crypto_tfm *tfm)
 {
 	struct drbg_state *drbg = crypto_tfm_ctx(tfm);
@@ -1970,21 +1617,7 @@ static int drbg_kcapi_random(struct crypto_rng *tfm,
 static int drbg_kcapi_seed(struct crypto_rng *tfm,
 			   const u8 *seed, unsigned int slen)
 {
-	struct drbg_state *drbg = crypto_rng_ctx(tfm);
-	struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
-	bool pr = false;
-	struct drbg_string string;
-	struct drbg_string *seed_string = NULL;
-	int coreref = 0;
-
-	drbg_convert_tfm_core(crypto_tfm_alg_driver_name(tfm_base), &coreref,
-			      &pr);
-	if (0 < slen) {
-		drbg_string_fill(&string, seed, slen);
-		seed_string = &string;
-	}
-
-	return drbg_instantiate(drbg, seed_string, coreref, pr);
+	return drbg_instantiate(tfm, seed, slen);
 }
 
 /***************************************************************
@@ -2007,9 +1640,7 @@ static inline int __init drbg_healthcheck_sanity(void)
 #define OUTBUFLEN 16
 	unsigned char buf[OUTBUFLEN];
 	struct drbg_state *drbg = NULL;
-	int ret;
 	int rc = -EFAULT;
-	bool pr = false;
 	int coreref = 0;
 	struct drbg_string addtl;
 	size_t max_addtllen, max_request_bytes;
@@ -2019,12 +1650,14 @@ static inline int __init drbg_healthcheck_sanity(void)
 		return 0;
 
 #ifdef CONFIG_CRYPTO_DRBG_CTR
-	drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref, &pr);
+	rc = drbg_convert_tfm_core("drbg_nopr_ctr_aes128", &coreref);
 #elif defined CONFIG_CRYPTO_DRBG_HASH
-	drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
+	rc = drbg_convert_tfm_core("drbg_nopr_sha256", &coreref);
 #else
-	drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref, &pr);
+	rc = drbg_convert_tfm_core("drbg_nopr_hmac_sha256", &coreref);
 #endif
+	if (rc)
+		return rc;
 
 	drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL);
 	if (!drbg)
@@ -2032,7 +1665,6 @@ static inline int __init drbg_healthcheck_sanity(void)
 
 	mutex_init(&drbg->drbg_mutex);
 	drbg->core = &drbg_cores[coreref];
-	drbg->reseed_threshold = drbg_max_requests(drbg);
 
 	/*
 	 * if the following tests fail, it is likely that there is a buffer
@@ -2052,9 +1684,6 @@ static inline int __init drbg_healthcheck_sanity(void)
 	len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
 	BUG_ON(0 < len);
 
-	/* overflow max addtllen with personalization string */
-	ret = drbg_seed(drbg, &addtl, false);
-	BUG_ON(0 == ret);
 	/* all tests passed */
 	rc = 0;
 
@@ -2065,7 +1694,7 @@ static inline int __init drbg_healthcheck_sanity(void)
 	return rc;
 }
 
-static struct rng_alg drbg_algs[22];
+static struct rng_alg drbg_algs[11];
 
 /*
  * Fill the array drbg_algs used to register the different DRBGs
@@ -2073,20 +1702,13 @@ static struct rng_alg drbg_algs[22];
  * from drbg_cores[] is used.
  */
 static inline void __init drbg_fill_array(struct rng_alg *alg,
-					  const struct drbg_core *core, int pr)
+					  const struct drbg_core *core)
 {
-	int pos = 0;
 	static int priority = 200;
 
 	memcpy(alg->base.cra_name, "stdrng", 6);
-	if (pr) {
-		memcpy(alg->base.cra_driver_name, "drbg_pr_", 8);
-		pos = 8;
-	} else {
-		memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10);
-		pos = 10;
-	}
-	memcpy(alg->base.cra_driver_name + pos, core->cra_name,
+	memcpy(alg->base.cra_driver_name, "drbg_nopr_", 10);
+	memcpy(alg->base.cra_driver_name + 10, core->cra_name,
 	       strlen(core->cra_name));
 
 	alg->base.cra_priority = priority;
@@ -2105,41 +1727,29 @@ static inline void __init drbg_fill_array(struct rng_alg *alg,
 	alg->base.cra_exit	= drbg_kcapi_cleanup;
 	alg->generate		= drbg_kcapi_random;
 	alg->seed		= drbg_kcapi_seed;
-	alg->set_ent		= drbg_kcapi_set_entropy;
 	alg->seedsize		= 0;
 }
 
 static int __init drbg_init(void)
 {
-	unsigned int i = 0; /* pointer to drbg_algs */
-	unsigned int j = 0; /* pointer to drbg_cores */
+	unsigned int i;
 	int ret;
 
 	ret = drbg_healthcheck_sanity();
 	if (ret)
 		return ret;
 
-	if (ARRAY_SIZE(drbg_cores) * 2 > ARRAY_SIZE(drbg_algs)) {
-		pr_info("DRBG: Cannot register all DRBG types"
-			"(slots needed: %zu, slots available: %zu)\n",
-			ARRAY_SIZE(drbg_cores) * 2, ARRAY_SIZE(drbg_algs));
-		return -EFAULT;
-	}
+	BUILD_BUG_ON(ARRAY_SIZE(drbg_cores) != ARRAY_SIZE(drbg_algs));
 
 	/*
-	 * each DRBG definition can be used with PR and without PR, thus
-	 * we instantiate each DRBG in drbg_cores[] twice.
-	 *
 	 * As the order of placing them into the drbg_algs array matters
 	 * (the later DRBGs receive a higher cra_priority) we register the
 	 * prediction resistance DRBGs first as the should not be too
 	 * interesting.
 	 */
-	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
-		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 1);
-	for (j = 0; ARRAY_SIZE(drbg_cores) > j; j++, i++)
-		drbg_fill_array(&drbg_algs[i], &drbg_cores[j], 0);
-	return crypto_register_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+	for (i = 0; i < ARRAY_SIZE(drbg_cores); i++)
+		drbg_fill_array(&drbg_algs[i], &drbg_cores[i]);
+	return crypto_register_rngs(drbg_algs, ARRAY_SIZE(drbg_cores));
 }
 
 static void __exit drbg_exit(void)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 5831d4bbc64f..2ce698eb14b6 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3635,13 +3635,11 @@ static int alg_test_cprng(const struct alg_test_desc *desc, const char *driver,
 }
 
 
-static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
+static int drbg_cavs_test(const struct drbg_testvec *test,
 			  const char *driver, u32 type, u32 mask)
 {
 	int ret = -EAGAIN;
 	struct crypto_rng *drng;
-	struct drbg_test_data test_data;
-	struct drbg_string addtl, pers, testentropy;
 	unsigned char *buf = kzalloc(test->expectedlen, GFP_KERNEL);
 
 	if (!buf)
@@ -3655,47 +3653,29 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
 		return -ENOMEM;
 	}
 
-	test_data.testentropy = &testentropy;
-	drbg_string_fill(&testentropy, test->entropy, test->entropylen);
-	drbg_string_fill(&pers, test->pers, test->perslen);
-	ret = crypto_drbg_reset_test(drng, &pers, &test_data);
+	ret = crypto_rng_reset(drng, test->entropy, test->entropylen);
 	if (ret) {
 		printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
 		goto outbuf;
 	}
 
-	drbg_string_fill(&addtl, test->addtla, test->addtllen);
-	if (pr) {
-		drbg_string_fill(&testentropy, test->entpra, test->entprlen);
-		ret = crypto_drbg_get_bytes_addtl_test(drng,
-			buf, test->expectedlen, &addtl,	&test_data);
-	} else {
-		ret = crypto_drbg_get_bytes_addtl(drng,
-			buf, test->expectedlen, &addtl);
-	}
+	ret = crypto_rng_generate(drng, test->addtla, test->addtllen,
+				  buf, test->expectedlen);
+
 	if (ret < 0) {
 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
 		       "driver %s\n", driver);
 		goto outbuf;
 	}
 
-	drbg_string_fill(&addtl, test->addtlb, test->addtllen);
-	if (pr) {
-		drbg_string_fill(&testentropy, test->entprb, test->entprlen);
-		ret = crypto_drbg_get_bytes_addtl_test(drng,
-			buf, test->expectedlen, &addtl, &test_data);
-	} else {
-		ret = crypto_drbg_get_bytes_addtl(drng,
-			buf, test->expectedlen, &addtl);
-	}
+	ret = crypto_rng_generate(drng, test->addtlb, test->addtllen,
+				  buf, test->expectedlen);
 	if (ret < 0) {
 		printk(KERN_ERR "alg: drbg: could not obtain random data for "
 		       "driver %s\n", driver);
 		goto outbuf;
 	}
 
-	ret = memcmp(test->expected, buf, test->expectedlen);
-
 outbuf:
 	crypto_free_rng(drng);
 	kfree_sensitive(buf);
@@ -3707,16 +3687,12 @@ static int alg_test_drbg(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
 	int err = 0;
-	int pr = 0;
 	int i = 0;
 	const struct drbg_testvec *template = desc->suite.drbg.vecs;
 	unsigned int tcount = desc->suite.drbg.count;
 
-	if (0 == memcmp(driver, "drbg_pr_", 8))
-		pr = 1;
-
 	for (i = 0; i < tcount; i++) {
-		err = drbg_cavs_test(&template[i], pr, driver, type, mask);
+		err = drbg_cavs_test(&template[i], driver, type, mask);
 		if (err) {
 			printk(KERN_ERR "alg: drbg: Test %d failed for %s\n",
 			       i, driver);
@@ -4725,62 +4701,6 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.alg = "drbg_nopr_sha512",
 		.fips_allowed = 1,
 		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_ctr_aes128",
-		.test = alg_test_drbg,
-		.fips_allowed = 1,
-		.suite = {
-			.drbg = __VECS(drbg_pr_ctr_aes128_tv_template)
-		}
-	}, {
-		/* covered by drbg_pr_ctr_aes128 test */
-		.alg = "drbg_pr_ctr_aes192",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_ctr_aes256",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_hmac_sha1",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_hmac_sha256",
-		.test = alg_test_drbg,
-		.fips_allowed = 1,
-		.suite = {
-			.drbg = __VECS(drbg_pr_hmac_sha256_tv_template)
-		}
-	}, {
-		/* covered by drbg_pr_hmac_sha256 test */
-		.alg = "drbg_pr_hmac_sha384",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_hmac_sha512",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "drbg_pr_sha1",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_sha256",
-		.test = alg_test_drbg,
-		.fips_allowed = 1,
-		.suite = {
-			.drbg = __VECS(drbg_pr_sha256_tv_template)
-		}
-	}, {
-		/* covered by drbg_pr_sha256 test */
-		.alg = "drbg_pr_sha384",
-		.fips_allowed = 1,
-		.test = alg_test_null,
-	}, {
-		.alg = "drbg_pr_sha512",
-		.fips_allowed = 1,
-		.test = alg_test_null,
 	}, {
 		.alg = "ecb(aes)",
 		.test = alg_test_skcipher,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index a253d66ba1c1..99a422816377 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -134,14 +134,9 @@ struct cprng_testvec {
 struct drbg_testvec {
 	const unsigned char *entropy;
 	size_t entropylen;
-	const unsigned char *entpra;
-	const unsigned char *entprb;
-	size_t entprlen;
 	const unsigned char *addtla;
 	const unsigned char *addtlb;
 	size_t addtllen;
-	const unsigned char *pers;
-	size_t perslen;
 	const unsigned char *expected;
 	size_t expectedlen;
 };
@@ -21440,453 +21435,13 @@ static const struct cprng_testvec ansi_cprng_aes_tv_template[] = {
 	},
 };
 
-/*
- * SP800-90A DRBG Test vectors from
- * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
- *
- * Test vectors for DRBG with prediction resistance. All types of DRBGs
- * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
- * w/o personalization string, w/ and w/o additional input string).
- */
-static const struct drbg_testvec drbg_pr_sha256_tv_template[] = {
-	{
-		.entropy = (unsigned char *)
-			"\x72\x88\x4c\xcd\x6c\x85\x57\x70\xf7\x0b\x8b\x86"
-			"\xc1\xeb\xd2\x4e\x36\x14\xab\x18\xc4\x9c\xc9\xcf"
-			"\x1a\xe8\xf7\x7b\x02\x49\x73\xd7\xf1\x42\x7d\xc6"
-			"\x3f\x29\x2d\xec\xd3\x66\x51\x3f\x1d\x8d\x5b\x4e",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\x38\x9c\x91\xfa\xc2\xa3\x46\x89\x56\x08\x3f\x62"
-			"\x73\xd5\x22\xa9\x29\x63\x3a\x1d\xe5\x5d\x5e\x4f"
-			"\x67\xb0\x67\x7a\x5e\x9e\x0c\x62",
-		.entprb = (unsigned char *)
-			"\xb2\x8f\x36\xb2\xf6\x8d\x39\x13\xfa\x6c\x66\xcf"
-			"\x62\x8a\x7e\x8c\x12\x33\x71\x9c\x69\xe4\xa5\xf0"
-			"\x8c\xee\xeb\x9c\xf5\x31\x98\x31",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x52\x7b\xa3\xad\x71\x77\xa4\x49\x42\x04\x61\xc7"
-			"\xf0\xaf\xa5\xfd\xd3\xb3\x0d\x6a\x61\xba\x35\x49"
-			"\xbb\xaa\xaf\xe4\x25\x7d\xb5\x48\xaf\x5c\x18\x3d"
-			"\x33\x8d\x9d\x45\xdf\x98\xd5\x94\xa8\xda\x92\xfe"
-			"\xc4\x3c\x94\x2a\xcf\x7f\x7b\xf2\xeb\x28\xa9\xf1"
-			"\xe0\x86\x30\xa8\xfe\xf2\x48\x90\x91\x0c\x75\xb5"
-			"\x3c\x00\xf0\x4d\x09\x4f\x40\xa7\xa2\x8c\x52\xdf"
-			"\x52\xef\x17\xbf\x3d\xd1\xa2\x31\xb4\xb8\xdc\xe6"
-			"\x5b\x0d\x1f\x78\x36\xb4\xe6\x4b\xa7\x11\x25\xd5"
-			"\x94\xc6\x97\x36\xab\xf0\xe5\x31\x28\x6a\xbb\xce"
-			"\x30\x81\xa6\x8f\x27\x14\xf8\x1c",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x5d\xf2\x14\xbc\xf6\xb5\x4e\x0b\xf0\x0d\x6f\x2d"
-			"\xe2\x01\x66\x7b\xd0\xa4\x73\xa4\x21\xdd\xb0\xc0"
-			"\x51\x79\x09\xf4\xea\xa9\x08\xfa\xa6\x67\xe0\xe1"
-			"\xd1\x88\xa8\xad\xee\x69\x74\xb3\x55\x06\x9b\xf6",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xef\x48\x06\xa2\xc2\x45\xf1\x44\xfa\x34\x2c\xeb"
-			"\x8d\x78\x3c\x09\x8f\x34\x72\x20\xf2\xe7\xfd\x13"
-			"\x76\x0a\xf6\xdc\x3c\xf5\xc0\x15",
-		.entprb = (unsigned char *)
-			"\x4b\xbe\xe5\x24\xed\x6a\x2d\x0c\xdb\x73\x5e\x09"
-			"\xf9\xad\x67\x7c\x51\x47\x8b\x6b\x30\x2a\xc6\xde"
-			"\x76\xaa\x55\x04\x8b\x0a\x72\x95",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x3b\x14\x71\x99\xa1\xda\xa0\x42\xe6\xc8\x85\x32"
-			"\x70\x20\x32\x53\x9a\xbe\xd1\x1e\x15\xef\xfb\x4c"
-			"\x25\x6e\x19\x3a\xf0\xb9\xcb\xde\xf0\x3b\xc6\x18"
-			"\x4d\x85\x5a\x9b\xf1\xe3\xc2\x23\x03\x93\x08\xdb"
-			"\xa7\x07\x4b\x33\x78\x40\x4d\xeb\x24\xf5\x6e\x81"
-			"\x4a\x1b\x6e\xa3\x94\x52\x43\xb0\xaf\x2e\x21\xf4"
-			"\x42\x46\x8e\x90\xed\x34\x21\x75\xea\xda\x67\xb6"
-			"\xe4\xf6\xff\xc6\x31\x6c\x9a\x5a\xdb\xb3\x97\x13"
-			"\x09\xd3\x20\x98\x33\x2d\x6d\xd7\xb5\x6a\xa8\xa9"
-			"\x9a\x5b\xd6\x87\x52\xa1\x89\x2b\x4b\x9c\x64\x60"
-			"\x50\x47\xa3\x63\x81\x16\xaf\x19",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\xbe\x13\xdb\x2a\xe9\xa8\xfe\x09\x97\xe1\xce\x5d"
-			"\xe8\xbb\xc0\x7c\x4f\xcb\x62\x19\x3f\x0f\xd2\xad"
-			"\xa9\xd0\x1d\x59\x02\xc4\xff\x70",
-		.addtlb = (unsigned char *)
-			"\x6f\x96\x13\xe2\xa7\xf5\x6c\xfe\xdf\x66\xe3\x31"
-			"\x63\x76\xbf\x20\x27\x06\x49\xf1\xf3\x01\x77\x41"
-			"\x9f\xeb\xe4\x38\xfe\x67\x00\xcd",
-		.addtllen = 32,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\xc6\x1c\xaf\x83\xa2\x56\x38\xf9\xb0\xbc\xd9\x85"
-			"\xf5\x2e\xc4\x46\x9c\xe1\xb9\x40\x98\x70\x10\x72"
-			"\xd7\x7d\x15\x85\xa1\x83\x5a\x97\xdf\xc8\xa8\xe8"
-			"\x03\x4c\xcb\x70\x35\x8b\x90\x94\x46\x8a\x6e\xa1",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xc9\x05\xa4\xcf\x28\x80\x4b\x93\x0f\x8b\xc6\xf9"
-			"\x09\x41\x58\x74\xe9\xec\x28\xc7\x53\x0a\x73\x60"
-			"\xba\x0a\xde\x57\x5b\x4b\x9f\x29",
-		.entprb = (unsigned char *)
-			"\x4f\x31\xd2\xeb\xac\xfa\xa8\xe2\x01\x7d\xf3\xbd"
-			"\x42\xbd\x20\xa0\x30\x65\x74\xd5\x5d\xd2\xad\xa4"
-			"\xa9\xeb\x1f\x4d\xf6\xfd\xb8\x26",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\xf6\x13\x05\xcb\x83\x60\x16\x42\x49\x1d\xc6\x25"
-			"\x3b\x8c\x31\xa3\xbe\x8b\xbd\x1c\xe2\xec\x1d\xde"
-			"\xbb\xbf\xa1\xac\xa8\x9f\x50\xce\x69\xce\xef\xd5"
-			"\xd6\xf2\xef\x6a\xf7\x81\x38\xdf\xbc\xa7\x5a\xb9"
-			"\xb2\x42\x65\xab\xe4\x86\x8d\x2d\x9d\x59\x99\x2c"
-			"\x5a\x0d\x71\x55\x98\xa4\x45\xc2\x8d\xdb\x05\x5e"
-			"\x50\x21\xf7\xcd\xe8\x98\x43\xce\x57\x74\x63\x4c"
-			"\xf3\xb1\xa5\x14\x1e\x9e\x01\xeb\x54\xd9\x56\xae"
-			"\xbd\xb6\x6f\x1a\x47\x6b\x3b\x44\xe4\xa2\xe9\x3c"
-			"\x6c\x83\x12\x30\xb8\x78\x7f\x8e\x54\x82\xd4\xfe"
-			"\x90\x35\x0d\x4c\x4d\x85\xe7\x13",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\xa5\xbf\xac\x4f\x71\xa1\xbb\x67\x94\xc6\x50\xc7"
-			"\x2a\x45\x9e\x10\xa8\xed\xf7\x52\x4f\xfe\x21\x90"
-			"\xa4\x1b\xe1\xe2\x53\xcc\x61\x47",
-		.perslen = 32,
-	}, {
-		.entropy = (unsigned char *)
-			"\xb6\xc1\x8d\xdf\x99\x54\xbe\x95\x10\x48\xd9\xf6"
-			"\xd7\x48\xa8\x73\x2d\x74\xde\x1e\xde\x57\x7e\xf4"
-			"\x7b\x7b\x64\xef\x88\x7a\xa8\x10\x4b\xe1\xc1\x87"
-			"\xbb\x0b\xe1\x39\x39\x50\xaf\x68\x9c\xa2\xbf\x5e",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xdc\x81\x0a\x01\x58\xa7\x2e\xce\xee\x48\x8c\x7c"
-			"\x77\x9e\x3c\xf1\x17\x24\x7a\xbb\xab\x9f\xca\x12"
-			"\x19\xaf\x97\x2d\x5f\xf9\xff\xfc",
-		.entprb = (unsigned char *)
-			"\xaf\xfc\x4f\x98\x8b\x93\x95\xc1\xb5\x8b\x7f\x73"
-			"\x6d\xa6\xbe\x6d\x33\xeb\x2c\x82\xb1\xaf\xc1\xb6"
-			"\xb6\x05\xe2\x44\xaa\xfd\xe7\xdb",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x51\x79\xde\x1c\x0f\x58\xf3\xf4\xc9\x57\x2e\x31"
-			"\xa7\x09\xa1\x53\x64\x63\xa2\xc5\x1d\x84\x88\x65"
-			"\x01\x1b\xc6\x16\x3c\x49\x5b\x42\x8e\x53\xf5\x18"
-			"\xad\x94\x12\x0d\x4f\x55\xcc\x45\x5c\x98\x0f\x42"
-			"\x28\x2f\x47\x11\xf9\xc4\x01\x97\x6b\xa0\x94\x50"
-			"\xa9\xd1\x5e\x06\x54\x3f\xdf\xbb\xc4\x98\xee\x8b"
-			"\xba\xa9\xfa\x49\xee\x1d\xdc\xfb\x50\xf6\x51\x9f"
-			"\x6c\x4a\x9a\x6f\x63\xa2\x7d\xad\xaf\x3a\x24\xa0"
-			"\xd9\x9f\x07\xeb\x15\xee\x26\xe0\xd5\x63\x39\xda"
-			"\x3c\x59\xd6\x33\x6c\x02\xe8\x05\x71\x46\x68\x44"
-			"\x63\x4a\x68\x72\xe9\xf5\x55\xfe",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\x15\x20\x2f\xf6\x98\x28\x63\xa2\xc4\x4e\xbb\x6c"
-			"\xb2\x25\x92\x61\x79\xc9\x22\xc4\x61\x54\x96\xff"
-			"\x4a\x85\xca\x80\xfe\x0d\x1c\xd0",
-		.addtlb = (unsigned char *)
-			"\xde\x29\x8e\x03\x42\x61\xa3\x28\x5e\xc8\x80\xc2"
-			"\x6d\xbf\xad\x13\xe1\x8d\x2a\xc7\xe8\xc7\x18\x89"
-			"\x42\x58\x9e\xd6\xcc\xad\x7b\x1e",
-		.addtllen = 32,
-		.pers = (unsigned char *)
-			"\x84\xc3\x73\x9e\xce\xb3\xbc\x89\xf7\x62\xb3\xe1"
-			"\xd7\x48\x45\x8a\xa9\xcc\xe9\xed\xd5\x81\x84\x52"
-			"\x82\x4c\xdc\x19\xb8\xf8\x92\x5c",
-		.perslen = 32,
-	},
-};
-
-static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
-	{
-		.entropy = (unsigned char *)
-			"\x99\x69\xe5\x4b\x47\x03\xff\x31\x78\x5b\x87\x9a"
-			"\x7e\x5c\x0e\xae\x0d\x3e\x30\x95\x59\xe9\xfe\x96"
-			"\xb0\x67\x6d\x49\xd5\x91\xea\x4d\x07\xd2\x0d\x46"
-			"\xd0\x64\x75\x7d\x30\x23\xca\xc2\x37\x61\x27\xab",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xc6\x0f\x29\x99\x10\x0f\x73\x8c\x10\xf7\x47\x92"
-			"\x67\x6a\x3f\xc4\xa2\x62\xd1\x37\x21\x79\x80\x46"
-			"\xe2\x9a\x29\x51\x81\x56\x9f\x54",
-		.entprb = (unsigned char *)
-			"\xc1\x1d\x45\x24\xc9\x07\x1b\xd3\x09\x60\x15\xfc"
-			"\xf7\xbc\x24\xa6\x07\xf2\x2f\xa0\x65\xc9\x37\x65"
-			"\x8a\x2a\x77\xa8\x69\x90\x89\xf4",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\xab\xc0\x15\x85\x60\x94\x80\x3a\x93\x8d\xff\xd2"
-			"\x0d\xa9\x48\x43\x87\x0e\xf9\x35\xb8\x2c\xfe\xc1"
-			"\x77\x06\xb8\xf5\x51\xb8\x38\x50\x44\x23\x5d\xd4"
-			"\x4b\x59\x9f\x94\xb3\x9b\xe7\x8d\xd4\x76\xe0\xcf"
-			"\x11\x30\x9c\x99\x5a\x73\x34\xe0\xa7\x8b\x37\xbc"
-			"\x95\x86\x23\x50\x86\xfa\x3b\x63\x7b\xa9\x1c\xf8"
-			"\xfb\x65\xef\xa2\x2a\x58\x9c\x13\x75\x31\xaa\x7b"
-			"\x2d\x4e\x26\x07\xaa\xc2\x72\x92\xb0\x1c\x69\x8e"
-			"\x6e\x01\xae\x67\x9e\xb8\x7c\x01\xa8\x9c\x74\x22"
-			"\xd4\x37\x2d\x6d\x75\x4a\xba\xbb\x4b\xf8\x96\xfc"
-			"\xb1\xcd\x09\xd6\x92\xd0\x28\x3f",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\xb9\x1f\xe9\xef\xdd\x9b\x7d\x20\xb6\xec\xe0\x2f"
-			"\xdb\x76\x24\xce\x41\xc8\x3a\x4a\x12\x7f\x3e\x2f"
-			"\xae\x05\x99\xea\xb5\x06\x71\x0d\x0c\x4c\xb4\x05"
-			"\x26\xc6\xbd\xf5\x7f\x2a\x3d\xf2\xb5\x49\x7b\xda",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xef\x67\x50\x9c\xa7\x7d\xdf\xb7\x2d\x81\x01\xa4"
-			"\x62\x81\x6a\x69\x5b\xb3\x37\x45\xa7\x34\x8e\x26"
-			"\x46\xd9\x26\xa2\x19\xd4\x94\x43",
-		.entprb = (unsigned char *)
-			"\x97\x75\x53\x53\xba\xb4\xa6\xb2\x91\x60\x71\x79"
-			"\xd1\x6b\x4a\x24\x9a\x34\x66\xcc\x33\xab\x07\x98"
-			"\x51\x78\x72\xb2\x79\xfd\x2c\xff",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x9c\xdc\x63\x8a\x19\x23\x22\x66\x0c\xc5\xb9\xd7"
-			"\xfb\x2a\xb0\x31\xe3\x8a\x36\xa8\x5a\xa8\x14\xda"
-			"\x1e\xa9\xcc\xfe\xb8\x26\x44\x83\x9f\xf6\xff\xaa"
-			"\xc8\x98\xb8\x30\x35\x3b\x3d\x36\xd2\x49\xd4\x40"
-			"\x62\x0a\x65\x10\x76\x55\xef\xc0\x95\x9c\xa7\xda"
-			"\x3f\xcf\xb7\x7b\xc6\xe1\x28\x52\xfc\x0c\xe2\x37"
-			"\x0d\x83\xa7\x51\x4b\x31\x47\x3c\xe1\x3c\xae\x70"
-			"\x01\xc8\xa3\xd3\xc2\xac\x77\x9c\xd1\x68\x77\x9b"
-			"\x58\x27\x3b\xa5\x0f\xc2\x7a\x8b\x04\x65\x62\xd5"
-			"\xe8\xd6\xfe\x2a\xaf\xd3\xd3\xfe\xbd\x18\xfb\xcd"
-			"\xcd\x66\xb5\x01\x69\x66\xa0\x3c",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\x17\xc1\x56\xcb\xcc\x50\xd6\x03\x7d\x45\x76\xa3"
-			"\x75\x76\xc1\x4a\x66\x1b\x2e\xdf\xb0\x2e\x7d\x56"
-			"\x6d\x99\x3b\xc6\x58\xda\x03\xf6",
-		.addtlb = (unsigned char *)
-			"\x7c\x7b\x4a\x4b\x32\x5e\x6f\x67\x34\xf5\x21\x4c"
-			"\xf9\x96\xf9\xbf\x1c\x8c\x81\xd3\x9b\x60\x6a\x44"
-			"\xc6\x03\xa2\xfb\x13\x20\x19\xb7",
-		.addtllen = 32,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x13\x54\x96\xfc\x1b\x7d\x28\xf3\x18\xc9\xa7\x89"
-			"\xb6\xb3\xc8\x72\xac\x00\xd4\x59\x36\x25\x05\xaf"
-			"\xa5\xdb\x96\xcb\x3c\x58\x46\x87\xa5\xaa\xbf\x20"
-			"\x3b\xfe\x23\x0e\xd1\xc7\x41\x0f\x3f\xc9\xb3\x67",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\xe2\xbd\xb7\x48\x08\x06\xf3\xe1\x93\x3c\xac\x79"
-			"\xa7\x2b\x11\xda\xe3\x2e\xe1\x91\xa5\x02\x19\x57"
-			"\x20\x28\xad\xf2\x60\xd7\xcd\x45",
-		.entprb = (unsigned char *)
-			"\x8b\xd4\x69\xfc\xff\x59\x95\x95\xc6\x51\xde\x71"
-			"\x68\x5f\xfc\xf9\x4a\xab\xec\x5a\xcb\xbe\xd3\x66"
-			"\x1f\xfa\x74\xd3\xac\xa6\x74\x60",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x1f\x9e\xaf\xe4\xd2\x46\xb7\x47\x41\x4c\x65\x99"
-			"\x01\xe9\x3b\xbb\x83\x0c\x0a\xb0\xc1\x3a\xe2\xb3"
-			"\x31\x4e\xeb\x93\x73\xee\x0b\x26\xc2\x63\xa5\x75"
-			"\x45\x99\xd4\x5c\x9f\xa1\xd4\x45\x87\x6b\x20\x61"
-			"\x40\xea\x78\xa5\x32\xdf\x9e\x66\x17\xaf\xb1\x88"
-			"\x9e\x2e\x23\xdd\xc1\xda\x13\x97\x88\xa5\xb6\x5e"
-			"\x90\x14\x4e\xef\x13\xab\x5c\xd9\x2c\x97\x9e\x7c"
-			"\xd7\xf8\xce\xea\x81\xf5\xcd\x71\x15\x49\x44\xce"
-			"\x83\xb6\x05\xfb\x7d\x30\xb5\x57\x2c\x31\x4f\xfc"
-			"\xfe\x80\xb6\xc0\x13\x0c\x5b\x9b\x2e\x8f\x3d\xfc"
-			"\xc2\xa3\x0c\x11\x1b\x80\x5f\xf3",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\x64\xb6\xfc\x60\xbc\x61\x76\x23\x6d\x3f\x4a\x0f"
-			"\xe1\xb4\xd5\x20\x9e\x70\xdd\x03\x53\x6d\xbf\xce"
-			"\xcd\x56\x80\xbc\xb8\x15\xc8\xaa",
-		.perslen = 32,
-	}, {
-		.entropy = (unsigned char *)
-			"\xc7\xcc\xbc\x67\x7e\x21\x66\x1e\x27\x2b\x63\xdd"
-			"\x3a\x78\xdc\xdf\x66\x6d\x3f\x24\xae\xcf\x37\x01"
-			"\xa9\x0d\x89\x8a\xa7\xdc\x81\x58\xae\xb2\x10\x15"
-			"\x7e\x18\x44\x6d\x13\xea\xdf\x37\x85\xfe\x81\xfb",
-		.entropylen = 48,
-		.entpra = (unsigned char *)
-			"\x7b\xa1\x91\x5b\x3c\x04\xc4\x1b\x1d\x19\x2f\x1a"
-			"\x18\x81\x60\x3c\x6c\x62\x91\xb7\xe9\xf5\xcb\x96"
-			"\xbb\x81\x6a\xcc\xb5\xae\x55\xb6",
-		.entprb = (unsigned char *)
-			"\x99\x2c\xc7\x78\x7e\x3b\x88\x12\xef\xbe\xd3\xd2"
-			"\x7d\x2a\xa5\x86\xda\x8d\x58\x73\x4a\x0a\xb2\x2e"
-			"\xbb\x4c\x7e\xe3\x9a\xb6\x81\xc1",
-		.entprlen = 32,
-		.expected = (unsigned char *)
-			"\x95\x6f\x95\xfc\x3b\xb7\xfe\x3e\xd0\x4e\x1a\x14"
-			"\x6c\x34\x7f\x7b\x1d\x0d\x63\x5e\x48\x9c\x69\xe6"
-			"\x46\x07\xd2\x87\xf3\x86\x52\x3d\x98\x27\x5e\xd7"
-			"\x54\xe7\x75\x50\x4f\xfb\x4d\xfd\xac\x2f\x4b\x77"
-			"\xcf\x9e\x8e\xcc\x16\xa2\x24\xcd\x53\xde\x3e\xc5"
-			"\x55\x5d\xd5\x26\x3f\x89\xdf\xca\x8b\x4e\x1e\xb6"
-			"\x88\x78\x63\x5c\xa2\x63\x98\x4e\x6f\x25\x59\xb1"
-			"\x5f\x2b\x23\xb0\x4b\xa5\x18\x5d\xc2\x15\x74\x40"
-			"\x59\x4c\xb4\x1e\xcf\x9a\x36\xfd\x43\xe2\x03\xb8"
-			"\x59\x91\x30\x89\x2a\xc8\x5a\x43\x23\x7c\x73\x72"
-			"\xda\x3f\xad\x2b\xba\x00\x6b\xd1",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\x18\xe8\x17\xff\xef\x39\xc7\x41\x5c\x73\x03\x03"
-			"\xf6\x3d\xe8\x5f\xc8\xab\xe4\xab\x0f\xad\xe8\xd6"
-			"\x86\x88\x55\x28\xc1\x69\xdd\x76",
-		.addtlb = (unsigned char *)
-			"\xac\x07\xfc\xbe\x87\x0e\xd3\xea\x1f\x7e\xb8\xe7"
-			"\x9d\xec\xe8\xe7\xbc\xf3\x18\x25\x77\x35\x4a\xaa"
-			"\x00\x99\x2a\xdd\x0a\x00\x50\x82",
-		.addtllen = 32,
-		.pers = (unsigned char *)
-			"\xbc\x55\xab\x3c\xf6\x52\xb0\x11\x3d\x7b\x90\xb8"
-			"\x24\xc9\x26\x4e\x5a\x1e\x77\x0d\x3d\x58\x4a\xda"
-			"\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
-		.perslen = 32,
-	},
-};
-
-static const struct drbg_testvec drbg_pr_ctr_aes128_tv_template[] = {
-	{
-		.entropy = (unsigned char *)
-			"\xd1\x44\xc6\x61\x81\x6d\xca\x9d\x15\x28\x8a\x42"
-			"\x94\xd7\x28\x9c\x43\x77\x19\x29\x1a\x6d\xc3\xa2",
-		.entropylen = 24,
-		.entpra = (unsigned char *)
-			"\x96\xd8\x9e\x45\x32\xc9\xd2\x08\x7a\x6d\x97\x15"
-			"\xb4\xec\x80\xb1",
-		.entprb = (unsigned char *)
-			"\x8b\xb6\x72\xb5\x24\x0b\x98\x65\x95\x95\xe9\xc9"
-			"\x28\x07\xeb\xc2",
-		.entprlen = 16,
-		.expected = (unsigned char *)
-			"\x70\x19\xd0\x4c\x45\x78\xd6\x68\xa9\x9a\xaa\xfe"
-			"\xc1\xdf\x27\x9a\x1c\x0d\x0d\xf7\x24\x75\x46\xcc"
-			"\x77\x6b\xdf\x89\xc6\x94\xdc\x74\x50\x10\x70\x18"
-			"\x9b\xdc\x96\xb4\x89\x23\x40\x1a\xce\x09\x87\xce"
-			"\xd2\xf3\xd5\xe4\x51\x67\x74\x11\x5a\xcc\x8b\x3b"
-			"\x8a\xf1\x23\xa8",
-		.expectedlen = 64,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x8e\x83\xe0\xeb\x37\xea\x3e\x53\x5e\x17\x6e\x77"
-			"\xbd\xb1\x53\x90\xfc\xdc\xc1\x3c\x9a\x88\x22\x94",
-		.entropylen = 24,
-		.entpra = (unsigned char *)
-			"\x6a\x85\xe7\x37\xc8\xf1\x04\x31\x98\x4f\xc8\x73"
-			"\x67\xd1\x08\xf8",
-		.entprb = (unsigned char *)
-			"\xd7\xa4\x68\xe2\x12\x74\xc3\xd9\xf1\xb7\x05\xbc"
-			"\xd4\xba\x04\x58",
-		.entprlen = 16,
-		.expected = (unsigned char *)
-			"\x78\xd6\xa6\x70\xff\xd1\x82\xf5\xa2\x88\x7f\x6d"
-			"\x3d\x8c\x39\xb1\xa8\xcb\x2c\x91\xab\x14\x7e\xbc"
-			"\x95\x45\x9f\x24\xb8\x20\xac\x21\x23\xdb\x72\xd7"
-			"\x12\x8d\x48\x95\xf3\x19\x0c\x43\xc6\x19\x45\xfc"
-			"\x8b\xac\x40\x29\x73\x00\x03\x45\x5e\x12\xff\x0c"
-			"\xc1\x02\x41\x82",
-		.expectedlen = 64,
-		.addtla = (unsigned char *)
-			"\xa2\xd9\x38\xcf\x8b\x29\x67\x5b\x65\x62\x6f\xe8"
-			"\xeb\xb3\x01\x76",
-		.addtlb = (unsigned char *)
-			"\x59\x63\x1e\x81\x8a\x14\xa8\xbb\xa1\xb8\x41\x25"
-			"\xd0\x7f\xcc\x43",
-		.addtllen = 16,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x04\xd9\x49\xa6\xdc\xe8\x6e\xbb\xf1\x08\x77\x2b"
-			"\x9e\x08\xca\x92\x65\x16\xda\x99\xa2\x59\xf3\xe8",
-		.entropylen = 24,
-		.entpra = (unsigned char *)
-			"\x38\x7e\x3f\x6b\x51\x70\x7b\x20\xec\x53\xd0\x66"
-			"\xc3\x0f\xe3\xb0",
-		.entprb = (unsigned char *)
-			"\xe0\x86\xa6\xaa\x5f\x72\x2f\xad\xf7\xef\x06\xb8"
-			"\xd6\x9c\x9d\xe8",
-		.entprlen = 16,
-		.expected = (unsigned char *)
-			"\xc9\x0a\xaf\x85\x89\x71\x44\x66\x4f\x25\x0b\x2b"
-			"\xde\xd8\xfa\xff\x52\x5a\x1b\x32\x5e\x41\x7a\x10"
-			"\x1f\xef\x1e\x62\x23\xe9\x20\x30\xc9\x0d\xad\x69"
-			"\xb4\x9c\x5b\xf4\x87\x42\xd5\xae\x5e\x5e\x43\xcc"
-			"\xd9\xfd\x0b\x93\x4a\xe3\xd4\x06\x37\x36\x0f\x3f"
-			"\x72\x82\x0c\xcf",
-		.expectedlen = 64,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\xbf\xa4\x9a\x8f\x7b\xd8\xb1\x7a\x9d\xfa\x45\xed"
-			"\x21\x52\xb3\xad",
-		.perslen = 16,
-	}, {
-		.entropy = (unsigned char *)
-			"\x92\x89\x8f\x31\xfa\x1c\xff\x6d\x18\x2f\x26\x06"
-			"\x43\xdf\xf8\x18\xc2\xa4\xd9\x72\xc3\xb9\xb6\x97",
-		.entropylen = 24,
-		.entpra = (unsigned char *)
-			"\x20\x72\x8a\x06\xf8\x6f\x8d\xd4\x41\xe2\x72\xb7"
-			"\xc4\x2c\xe8\x10",
-		.entprb = (unsigned char *)
-			"\x3d\xb0\xf0\x94\xf3\x05\x50\x33\x17\x86\x3e\x22"
-			"\x08\xf7\xa5\x01",
-		.entprlen = 16,
-		.expected = (unsigned char *)
-			"\x5a\x35\x39\x87\x0f\x4d\x22\xa4\x09\x24\xee\x71"
-			"\xc9\x6f\xac\x72\x0a\xd6\xf0\x88\x82\xd0\x83\x28"
-			"\x73\xec\x3f\x93\xd8\xab\x45\x23\xf0\x7e\xac\x45"
-			"\x14\x5e\x93\x9f\xb1\xd6\x76\x43\x3d\xb6\xe8\x08"
-			"\x88\xf6\xda\x89\x08\x77\x42\xfe\x1a\xf4\x3f\xc4"
-			"\x23\xc5\x1f\x68",
-		.expectedlen = 64,
-		.addtla = (unsigned char *)
-			"\x1a\x40\xfa\xe3\xcc\x6c\x7c\xa0\xf8\xda\xba\x59"
-			"\x23\x6d\xad\x1d",
-		.addtlb = (unsigned char *)
-			"\x9f\x72\x76\x6c\xc7\x46\xe5\xed\x2e\x53\x20\x12"
-			"\xbc\x59\x31\x8c",
-		.addtllen = 16,
-		.pers = (unsigned char *)
-			"\xea\x65\xee\x60\x26\x4e\x7e\xb6\x0e\x82\x68\xc4"
-			"\x37\x3c\x5c\x0b",
-		.perslen = 16,
-	},
-};
-
 /*
  * SP800-90A DRBG Test vectors from
  * http://csrc.nist.gov/groups/STM/cavp/documents/drbg/drbgtestvectors.zip
  *
  * Test vectors for DRBG without prediction resistance. All types of DRBGs
- * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and
- * w/o personalization string, w/ and w/o additional input string).
+ * (Hash, HMAC, CTR) are tested with all permutations of use cases (w/ and w/o
+ * additional input string).
  */
 static const struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
 	{
@@ -21912,8 +21467,6 @@ static const struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
 		.addtla = NULL,
 		.addtlb = NULL,
 		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
 	}, {
 		.entropy = (unsigned char *)
 			"\x73\xd3\xfb\xa3\x94\x5f\x2b\x5f\xb9\x8f\xf6\x9c"
@@ -21943,71 +21496,7 @@ static const struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
 			"\x6f\x8c\x55\x1c\x44\xd1\xce\x6f\x28\xcc\xa4\x4d"
 			"\xa8\xc0\x85\xd1\x5a\x0c\x59\x40",
 		.addtllen = 32,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x2a\x85\xa9\x8b\xd0\xda\x83\xd6\xad\xab\x9f\xbb"
-			"\x54\x31\x15\x95\x1c\x4d\x49\x9f\x6a\x15\xf6\xe4"
-			"\x15\x50\x88\x06\x29\x0d\xed\x8d\xb9\x6f\x96\xe1"
-			"\x83\x9f\xf7\x88\xda\x84\xbf\x44\x28\xd9\x1d\xaa",
-		.entropylen = 48,
-		.expected = (unsigned char *)
-			"\x2d\x55\xde\xc9\xed\x05\x47\x07\x3d\x04\xfc\x28"
-			"\x0f\x92\xf0\x4d\xd8\x00\x32\x47\x0a\x1b\x1c\x4b"
-			"\xef\xd9\x97\xa1\x17\x67\xda\x26\x6c\xfe\x76\x46"
-			"\x6f\xbc\x6d\x82\x4e\x83\x8a\x98\x66\x6c\x01\xb6"
-			"\xe6\x64\xe0\x08\x10\x6f\xd3\x5d\x90\xe7\x0d\x72"
-			"\xa6\xa7\xe3\xbb\x98\x11\x12\x56\x23\xc2\x6d\xd1"
-			"\xc8\xa8\x7a\x39\xf3\x34\xe3\xb8\xf8\x66\x00\x77"
-			"\x7d\xcf\x3c\x3e\xfa\xc9\x0f\xaf\xe0\x24\xfa\xe9"
-			"\x84\xf9\x6a\x01\xf6\x35\xdb\x5c\xab\x2a\xef\x4e"
-			"\xac\xab\x55\xb8\x9b\xef\x98\x68\xaf\x51\xd8\x16"
-			"\xa5\x5e\xae\xf9\x1e\xd2\xdb\xe6",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\xa8\x80\xec\x98\x30\x98\x15\xd2\xc6\xc4\x68\xf1"
-			"\x3a\x1c\xbf\xce\x6a\x40\x14\xeb\x36\x99\x53\xda"
-			"\x57\x6b\xce\xa4\x1c\x66\x3d\xbc",
-		.perslen = 32,
-	}, {
-		.entropy = (unsigned char *)
-			"\x69\xed\x82\xa9\xc5\x7b\xbf\xe5\x1d\x2f\xcb\x7a"
-			"\xd3\x50\x7d\x96\xb4\xb9\x2b\x50\x77\x51\x27\x74"
-			"\x33\x74\xba\xf1\x30\xdf\x8e\xdf\x87\x1d\x87\xbc"
-			"\x96\xb2\xc3\xa7\xed\x60\x5e\x61\x4e\x51\x29\x1a",
-		.entropylen = 48,
-		.expected = (unsigned char *)
-			"\xa5\x71\x24\x31\x11\xfe\x13\xe1\xa8\x24\x12\xfb"
-			"\x37\xa1\x27\xa5\xab\x77\xa1\x9f\xae\x8f\xaf\x13"
-			"\x93\xf7\x53\x85\x91\xb6\x1b\xab\xd4\x6b\xea\xb6"
-			"\xef\xda\x4c\x90\x6e\xef\x5f\xde\xe1\xc7\x10\x36"
-			"\xd5\x67\xbd\x14\xb6\x89\x21\x0c\xc9\x92\x65\x64"
-			"\xd0\xf3\x23\xe0\x7f\xd1\xe8\x75\xc2\x85\x06\xea"
-			"\xca\xc0\xcb\x79\x2d\x29\x82\xfc\xaa\x9a\xc6\x95"
-			"\x7e\xdc\x88\x65\xba\xec\x0e\x16\x87\xec\xa3\x9e"
-			"\xd8\x8c\x80\xab\x3a\x64\xe0\xcb\x0e\x45\x98\xdd"
-			"\x7c\x6c\x6c\x26\x11\x13\xc8\xce\xa9\x47\xa6\x06"
-			"\x57\xa2\x66\xbb\x2d\x7f\xf3\xc1",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\x74\xd3\x6d\xda\xe8\xd6\x86\x5f\x63\x01\xfd\xf2"
-			"\x7d\x06\x29\x6d\x94\xd1\x66\xf0\xd2\x72\x67\x4e"
-			"\x77\xc5\x3d\x9e\x03\xe3\xa5\x78",
-		.addtlb = (unsigned char *)
-			"\xf6\xb6\x3d\xf0\x7c\x26\x04\xc5\x8b\xcd\x3e\x6a"
-			"\x9f\x9c\x3a\x2e\xdb\x47\x87\xe5\x8e\x00\x5e\x2b"
-			"\x74\x7f\xa6\xf6\x80\xcd\x9b\x21",
-		.addtllen = 32,
-		.pers = (unsigned char *)
-			"\x74\xa6\xe0\x08\xf9\x27\xee\x1d\x6e\x3c\x28\x20"
-			"\x87\xdd\xd7\x54\x31\x47\x78\x4b\xe5\x6d\xa3\x73"
-			"\xa9\x65\xb1\x10\xc1\xdc\x77\x7c",
-		.perslen = 32,
-	},
+	}
 };
 
 static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
@@ -22034,8 +21523,6 @@ static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
 		.addtla = NULL,
 		.addtlb = NULL,
 		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
 	}, {
 		.entropy = (unsigned char *)
 			"\xf9\x7a\x3c\xfd\x91\xfa\xa0\x46\xb9\xe6\x1b\x94"
@@ -22065,71 +21552,7 @@ static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
 			"\x1d\x74\x49\xfe\x75\x06\x26\x82\xe8\x9c\x57\x14"
 			"\x40\xc0\xc9\xb5\x2c\x42\xa6\xe0",
 		.addtllen = 32,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\x8d\xf0\x13\xb4\xd1\x03\x52\x30\x73\x91\x7d\xdf"
-			"\x6a\x86\x97\x93\x05\x9e\x99\x43\xfc\x86\x54\x54"
-			"\x9e\x7a\xb2\x2f\x7c\x29\xf1\x22\xda\x26\x25\xaf"
-			"\x2d\xdd\x4a\xbc\xce\x3c\xf4\xfa\x46\x59\xd8\x4e",
-		.entropylen = 48,
-		.expected = (unsigned char *)
-			"\xb9\x1c\xba\x4c\xc8\x4f\xa2\x5d\xf8\x61\x0b\x81"
-			"\xb6\x41\x40\x27\x68\xa2\x09\x72\x34\x93\x2e\x37"
-			"\xd5\x90\xb1\x15\x4c\xbd\x23\xf9\x74\x52\xe3\x10"
-			"\xe2\x91\xc4\x51\x46\x14\x7f\x0d\xa2\xd8\x17\x61"
-			"\xfe\x90\xfb\xa6\x4f\x94\x41\x9c\x0f\x66\x2b\x28"
-			"\xc1\xed\x94\xda\x48\x7b\xb7\xe7\x3e\xec\x79\x8f"
-			"\xbc\xf9\x81\xb7\x91\xd1\xbe\x4f\x17\x7a\x89\x07"
-			"\xaa\x3c\x40\x16\x43\xa5\xb6\x2b\x87\xb8\x9d\x66"
-			"\xb3\xa6\x0e\x40\xd4\xa8\xe4\xe9\xd8\x2a\xf6\xd2"
-			"\x70\x0e\x6f\x53\x5c\xdb\x51\xf7\x5c\x32\x17\x29"
-			"\x10\x37\x41\x03\x0c\xcc\x3a\x56",
-		.expectedlen = 128,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\xb5\x71\xe6\x6d\x7c\x33\x8b\xc0\x7b\x76\xad\x37"
-			"\x57\xbb\x2f\x94\x52\xbf\x7e\x07\x43\x7a\xe8\x58"
-			"\x1c\xe7\xbc\x7c\x3a\xc6\x51\xa9",
-		.perslen = 32,
-	}, {
-		.entropy = (unsigned char *)
-			"\xc2\xa5\x66\xa9\xa1\x81\x7b\x15\xc5\xc3\xb7\x78"
-			"\x17\x7a\xc8\x7c\x24\xe7\x97\xbe\x0a\x84\x5f\x11"
-			"\xc2\xfe\x39\x9d\xd3\x77\x32\xf2\xcb\x18\x94\xeb"
-			"\x2b\x97\xb3\xc5\x6e\x62\x83\x29\x51\x6f\x86\xec",
-		.entropylen = 48,
-		.expected = (unsigned char *)
-			"\xb3\xa3\x69\x8d\x77\x76\x99\xa0\xdd\x9f\xa3\xf0"
-			"\xa9\xfa\x57\x83\x2d\x3c\xef\xac\x5d\xf2\x44\x37"
-			"\xc6\xd7\x3a\x0f\xe4\x10\x40\xf1\x72\x90\x38\xae"
-			"\xf1\xe9\x26\x35\x2e\xa5\x9d\xe1\x20\xbf\xb7\xb0"
-			"\x73\x18\x3a\x34\x10\x6e\xfe\xd6\x27\x8f\xf8\xad"
-			"\x84\x4b\xa0\x44\x81\x15\xdf\xdd\xf3\x31\x9a\x82"
-			"\xde\x6b\xb1\x1d\x80\xbd\x87\x1a\x9a\xcd\x35\xc7"
-			"\x36\x45\xe1\x27\x0f\xb9\xfe\x4f\xa8\x8e\xc0\xe4"
-			"\x65\x40\x9e\xa0\xcb\xa8\x09\xfe\x2f\x45\xe0\x49"
-			"\x43\xa2\xe3\x96\xbb\xb7\xdd\x2f\x4e\x07\x95\x30"
-			"\x35\x24\xcc\x9c\xc5\xea\x54\xa1",
-		.expectedlen = 128,
-		.addtla = (unsigned char *)
-			"\x41\x3d\xd8\x3f\xe5\x68\x35\xab\xd4\x78\xcb\x96"
-			"\x93\xd6\x76\x35\x90\x1c\x40\x23\x9a\x26\x64\x62"
-			"\xd3\x13\x3b\x83\xe4\x9c\x82\x0b",
-		.addtlb = (unsigned char *)
-			"\xd5\xc4\xa7\x1f\x9d\x6d\x95\xa1\xbe\xdf\x0b\xd2"
-			"\x24\x7c\x27\x7d\x1f\x84\xa4\xe5\x7a\x4a\x88\x25"
-			"\xb8\x2a\x2d\x09\x7d\xe6\x3e\xf1",
-		.addtllen = 32,
-		.pers = (unsigned char *)
-			"\x13\xce\x4d\x8d\xd2\xdb\x97\x96\xf9\x41\x56\xc8"
-			"\xe8\xf0\x76\x9b\x0a\xa1\xc8\x2c\x13\x23\xb6\x15"
-			"\x36\x60\x3b\xca\x37\xc9\xee\x29",
-		.perslen = 32,
-	},
+	}
 };
 
 /* Test vector obtained during NIST ACVP testing */
@@ -22176,8 +21599,6 @@ static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = {
 			"\x2D\x1E\x22\x2A\xBD\x8B\x05\x6F\xA3\xFC\xBF\x16"
 			"\xED\xAA\x75\x8D\x73\x9A\xF6\xEC",
 		.addtllen = 32,
-		.pers = NULL,
-		.perslen = 0,
 	}
 };
 
@@ -22200,8 +21621,6 @@ static const struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = {
 		.addtla = NULL,
 		.addtlb = NULL,
 		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
 	},
 };
 
@@ -22224,8 +21643,6 @@ static const struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = {
 		.addtla = NULL,
 		.addtlb = NULL,
 		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
 	},
 };
 
@@ -22246,8 +21663,6 @@ static const struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
 		.addtla = NULL,
 		.addtlb = NULL,
 		.addtllen = 0,
-		.pers = NULL,
-		.perslen = 0,
 	}, {
 		.entropy = (unsigned char *)
 			"\x71\xbd\xce\x35\x42\x7d\x20\xbf\x58\xcf\x17\x74"
@@ -22268,53 +21683,7 @@ static const struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
 			"\xe3\x18\x83\xd9\x4b\x5e\xc4\xcc\xaa\x61\x2f\xbb"
 			"\x4a\x55\xd1\xc6",
 		.addtllen = 16,
-		.pers = NULL,
-		.perslen = 0,
-	}, {
-		.entropy = (unsigned char *)
-			"\xca\x4b\x1e\xfa\x75\xbd\x69\x36\x38\x73\xb8\xf9"
-			"\xdb\x4d\x35\x0e\x47\xbf\x6c\x37\x72\xfd\xf7\xa9",
-		.entropylen = 24,
-		.expected = (unsigned char *)
-			"\x59\xc3\x19\x79\x1b\xb1\xf3\x0e\xe9\x34\xae\x6e"
-			"\x8b\x1f\xad\x1f\x74\xca\x25\x45\x68\xb8\x7f\x75"
-			"\x12\xf8\xf2\xab\x4c\x23\x01\x03\x05\xe1\x70\xee"
-			"\x75\xd8\xcb\xeb\x23\x4c\x7a\x23\x6e\x12\x27\xdb"
-			"\x6f\x7a\xac\x3c\x44\xb7\x87\x4b\x65\x56\x74\x45"
-			"\x34\x30\x0c\x3d",
-		.expectedlen = 64,
-		.addtla = NULL,
-		.addtlb = NULL,
-		.addtllen = 0,
-		.pers = (unsigned char *)
-			"\xeb\xaa\x60\x2c\x4d\xbe\x33\xff\x1b\xef\xbf\x0a"
-			"\x0b\xc6\x97\x54",
-		.perslen = 16,
-	}, {
-		.entropy = (unsigned char *)
-			"\xc0\x70\x1f\x92\x50\x75\x8f\xcd\xf2\xbe\x73\x98"
-			"\x80\xdb\x66\xeb\x14\x68\xb4\xa5\x87\x9c\x2d\xa6",
-		.entropylen = 24,
-		.expected = (unsigned char *)
-			"\x97\xc0\xc0\xe5\xa0\xcc\xf2\x4f\x33\x63\x48\x8a"
-			"\xdb\x13\x0a\x35\x89\xbf\x80\x65\x62\xee\x13\x95"
-			"\x7c\x33\xd3\x7d\xf4\x07\x77\x7a\x2b\x65\x0b\x5f"
-			"\x45\x5c\x13\xf1\x90\x77\x7f\xc5\x04\x3f\xcc\x1a"
-			"\x38\xf8\xcd\x1b\xbb\xd5\x57\xd1\x4a\x4c\x2e\x8a"
-			"\x2b\x49\x1e\x5c",
-		.expectedlen = 64,
-		.addtla = (unsigned char *)
-			"\xf9\x01\xf8\x16\x7a\x1d\xff\xde\x8e\x3c\x83\xe2"
-			"\x44\x85\xe7\xfe",
-		.addtlb = (unsigned char *)
-			"\x17\x1c\x09\x38\xc2\x38\x9f\x97\x87\x60\x55\xb4"
-			"\x82\x16\x62\x7f",
-		.addtllen = 16,
-		.pers = (unsigned char *)
-			"\x80\x08\xae\xe8\xe9\x69\x40\xc5\x08\x73\xc7\x9f"
-			"\x8e\xcf\xe0\x02",
-		.perslen = 16,
-	},
+	}
 };
 
 /* Cast5 test vectors from RFC 2144 */
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index af5ad51d3eef..58787575d220 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -101,10 +101,6 @@ struct drbg_state_ops {
 
 };
 
-struct drbg_test_data {
-	struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */
-};
-
 enum drbg_seed_state {
 	DRBG_SEED_STATE_UNSEEDED,
 	DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
@@ -120,7 +116,6 @@ struct drbg_state {
 	unsigned char *Cbuf;
 	/* Number of RNG requests since last reseed -- 10.1.1.1 1c) */
 	size_t reseed_ctr;
-	size_t reseed_threshold;
 	 /* some memory the DRBG can use for its operation */
 	unsigned char *scratchpad;
 	unsigned char *scratchpadbuf;
@@ -133,15 +128,8 @@ struct drbg_state {
 	struct crypto_wait ctr_wait;		/* CTR mode async wait obj */
 	struct scatterlist sg_in, sg_out;	/* CTR mode SGLs */
 
-	enum drbg_seed_state seeded;		/* DRBG fully seeded? */
-	unsigned long last_seed_time;
-	bool pr;		/* Prediction resistance enabled? */
-	bool fips_primed;	/* Continuous test primed? */
-	unsigned char *prev;	/* FIPS 140-2 continuous test value */
-	struct crypto_rng *jent;
 	const struct drbg_state_ops *d_ops;
 	const struct drbg_core *core;
-	struct drbg_string test_data;
 };
 
 static inline __u8 drbg_statelen(struct drbg_state *drbg)
@@ -192,78 +180,6 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg)
 	return (1<<20);
 }
 
-/*
- * This is a wrapper to the kernel crypto API function of
- * crypto_rng_generate() to allow the caller to provide additional data.
- *
- * @drng DRBG handle -- see crypto_rng_get_bytes
- * @outbuf output buffer -- see crypto_rng_get_bytes
- * @outlen length of output buffer -- see crypto_rng_get_bytes
- * @addtl_input additional information string input buffer
- * @addtllen length of additional information string buffer
- *
- * return
- *	see crypto_rng_get_bytes
- */
-static inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng,
-			unsigned char *outbuf, unsigned int outlen,
-			struct drbg_string *addtl)
-{
-	return crypto_rng_generate(drng, addtl->buf, addtl->len,
-				   outbuf, outlen);
-}
-
-/*
- * TEST code
- *
- * This is a wrapper to the kernel crypto API function of
- * crypto_rng_generate() to allow the caller to provide additional data and
- * allow furnishing of test_data
- *
- * @drng DRBG handle -- see crypto_rng_get_bytes
- * @outbuf output buffer -- see crypto_rng_get_bytes
- * @outlen length of output buffer -- see crypto_rng_get_bytes
- * @addtl_input additional information string input buffer
- * @addtllen length of additional information string buffer
- * @test_data filled test data
- *
- * return
- *	see crypto_rng_get_bytes
- */
-static inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng,
-			unsigned char *outbuf, unsigned int outlen,
-			struct drbg_string *addtl,
-			struct drbg_test_data *test_data)
-{
-	crypto_rng_set_entropy(drng, test_data->testentropy->buf,
-			       test_data->testentropy->len);
-	return crypto_rng_generate(drng, addtl->buf, addtl->len,
-				   outbuf, outlen);
-}
-
-/*
- * TEST code
- *
- * This is a wrapper to the kernel crypto API function of
- * crypto_rng_reset() to allow the caller to provide test_data
- *
- * @drng DRBG handle -- see crypto_rng_reset
- * @pers personalization string input buffer
- * @perslen length of additional information string buffer
- * @test_data filled test data
- *
- * return
- *	see crypto_rng_reset
- */
-static inline int crypto_drbg_reset_test(struct crypto_rng *drng,
-					 struct drbg_string *pers,
-					 struct drbg_test_data *test_data)
-{
-	crypto_rng_set_entropy(drng, test_data->testentropy->buf,
-			       test_data->testentropy->len);
-	return crypto_rng_reset(drng, pers->buf, pers->len);
-}
-
 /* DRBG type flags */
 #define DRBG_CTR	((drbg_flag_t)1<<0)
 #define DRBG_HMAC	((drbg_flag_t)1<<1)
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/7] crypto: AF_ALG - remove ALG_SET_DRBG_ENTROPY interface
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
  2022-01-26  7:03 ` [PATCH 1/7] crypto: DRBG - remove internal reseeding operation Stephan Müller
@ 2022-01-26  7:03 ` Stephan Müller
  2022-01-26  7:04 ` [PATCH 3/7] crypto: Entropy Source and DRNG Manager Stephan Müller
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:03 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange, Elena Petrova

The ALG_SET_DRBG_ENTROPY was added to test the DRBG implementation
provided with the kernel crypto API. This interface was used to set a
"test entropy" string to bypass the DRBG-internal seeding mechanism.

Since the DRBG-internal seeding mechanism is completely removed, the
special bypass is not needed any more. The entropy string for the DRBG
can be set with the crypto_rng_reset() function that is invoked with the
ALG_SET_KEY interface.

The change enables the sendmsg implementation in AF_ALG RNG for a
general use. The sendmsg allows user space to set the input data to the
crypto_rng_generate function call.

The change still allows the full testing of the DRBG which was verified
with libkcapi version 1.5.0 covering the following aspects:

- Hash DRBG with SHA-1, SHA-256, SHA-384, SHA-512

- HMAC DRBG with SHA-1, SHA-256, SHA-384, SHA-512

- CTR DRBG with AES-128, AES-192, AES-256

- reseeding, but without additional information

- no reseeding, but with additional information

The limitation of the test is defined with algif_rng.c:MAXSIZE which
restricts the allowed output size for testing to 128 bytes.

CC: Elena Petrova <lenaptr@google.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/Kconfig                |  9 -----
 crypto/af_alg.c               |  7 ----
 crypto/algif_rng.c            | 75 +----------------------------------
 include/crypto/if_alg.h       |  1 -
 include/crypto/internal/rng.h |  6 ---
 include/crypto/rng.h          |  4 --
 include/uapi/linux/if_alg.h   |  2 +-
 7 files changed, 3 insertions(+), 101 deletions(-)

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 442765219c37..a0de01ab6f0c 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1879,15 +1879,6 @@ config CRYPTO_USER_API_RNG
 	  This option enables the user-spaces interface for random
 	  number generator algorithms.
 
-config CRYPTO_USER_API_RNG_CAVP
-	bool "Enable CAVP testing of DRBG"
-	depends on CRYPTO_USER_API_RNG && CRYPTO_DRBG
-	help
-	  This option enables extra API for CAVP testing via the user-space
-	  interface: resetting of DRBG entropy, and providing Additional Data.
-	  This should only be enabled for CAVP testing. You should say
-	  no unless you know what this is.
-
 config CRYPTO_USER_API_AEAD
 	tristate "User-space interface for AEAD cipher algorithms"
 	depends on NET
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index e1ea18536a5f..6e5222fd10e2 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -259,13 +259,6 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
 			goto unlock;
 		err = type->setauthsize(ask->private, optlen);
 		break;
-	case ALG_SET_DRBG_ENTROPY:
-		if (sock->state == SS_CONNECTED)
-			goto unlock;
-		if (!type->setentropy)
-			goto unlock;
-
-		err = type->setentropy(ask->private, optval, optlen);
 	}
 
 unlock:
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index b204f1427542..4fade9456990 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -110,16 +110,6 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
 	struct rng_ctx *ctx = ask->private;
-
-	return _rng_recvmsg(ctx->drng, msg, len, NULL, 0);
-}
-
-static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
-			    int flags)
-{
-	struct sock *sk = sock->sk;
-	struct alg_sock *ask = alg_sk(sk);
-	struct rng_ctx *ctx = ask->private;
 	int ret;
 
 	lock_sock(sock->sk);
@@ -130,7 +120,7 @@ static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 	return ret;
 }
 
-static int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
+static int rng_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 {
 	int err;
 	struct alg_sock *ask = alg_sk(sock->sk);
@@ -173,30 +163,11 @@ static struct proto_ops algif_rng_ops = {
 	.mmap		=	sock_no_mmap,
 	.bind		=	sock_no_bind,
 	.accept		=	sock_no_accept,
-	.sendmsg	=	sock_no_sendmsg,
 	.sendpage	=	sock_no_sendpage,
 
 	.release	=	af_alg_release,
 	.recvmsg	=	rng_recvmsg,
-};
-
-static struct proto_ops __maybe_unused algif_rng_test_ops = {
-	.family		=	PF_ALG,
-
-	.connect	=	sock_no_connect,
-	.socketpair	=	sock_no_socketpair,
-	.getname	=	sock_no_getname,
-	.ioctl		=	sock_no_ioctl,
-	.listen		=	sock_no_listen,
-	.shutdown	=	sock_no_shutdown,
-	.mmap		=	sock_no_mmap,
-	.bind		=	sock_no_bind,
-	.accept		=	sock_no_accept,
-	.sendpage	=	sock_no_sendpage,
-
-	.release	=	af_alg_release,
-	.recvmsg	=	rng_test_recvmsg,
-	.sendmsg	=	rng_test_sendmsg,
+	.sendmsg	=	rng_sendmsg,
 };
 
 static void *rng_bind(const char *name, u32 type, u32 mask)
@@ -225,7 +196,6 @@ static void rng_release(void *private)
 	if (unlikely(!pctx))
 		return;
 	crypto_free_rng(pctx->drng);
-	kfree_sensitive(pctx->entropy);
 	kfree_sensitive(pctx);
 }
 
@@ -264,13 +234,6 @@ static int rng_accept_parent(void *private, struct sock *sk)
 	ask->private = ctx;
 	sk->sk_destruct = rng_sock_destruct;
 
-	/*
-	 * Non NULL pctx->entropy means that CAVP test has been initiated on
-	 * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops.
-	 */
-	if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy)
-		sk->sk_socket->ops = &algif_rng_test_ops;
-
 	return 0;
 }
 
@@ -284,45 +247,11 @@ static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
 	return crypto_rng_reset(pctx->drng, seed, seedlen);
 }
 
-static int __maybe_unused rng_setentropy(void *private, sockptr_t entropy,
-					 unsigned int len)
-{
-	struct rng_parent_ctx *pctx = private;
-	u8 *kentropy = NULL;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
-	if (pctx->entropy)
-		return -EINVAL;
-
-	if (len > MAXSIZE)
-		return -EMSGSIZE;
-
-	if (len) {
-		kentropy = memdup_sockptr(entropy, len);
-		if (IS_ERR(kentropy))
-			return PTR_ERR(kentropy);
-	}
-
-	if (crypto_rng_alg(pctx->drng)->set_ent)
-		crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
-	/*
-	 * Since rng doesn't perform any memory management for the entropy
-	 * buffer, save kentropy pointer to pctx now to free it after use.
-	 */
-	pctx->entropy = kentropy;
-	return 0;
-}
-
 static const struct af_alg_type algif_type_rng = {
 	.bind		=	rng_bind,
 	.release	=	rng_release,
 	.accept		=	rng_accept_parent,
 	.setkey		=	rng_setkey,
-#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP
-	.setentropy	=	rng_setentropy,
-#endif
 	.ops		=	&algif_rng_ops,
 	.name		=	"rng",
 	.owner		=	THIS_MODULE
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index a5db86670bdf..ee6412314f8f 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -46,7 +46,6 @@ struct af_alg_type {
 	void *(*bind)(const char *name, u32 type, u32 mask);
 	void (*release)(void *private);
 	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
-	int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
 	int (*accept)(void *private, struct sock *sk);
 	int (*accept_nokey)(void *private, struct sock *sk);
 	int (*setauthsize)(void *private, unsigned int authsize);
diff --git a/include/crypto/internal/rng.h b/include/crypto/internal/rng.h
index e0711b6a597f..bf6da44f9e82 100644
--- a/include/crypto/internal/rng.h
+++ b/include/crypto/internal/rng.h
@@ -31,10 +31,4 @@ static inline void *crypto_rng_ctx(struct crypto_rng *tfm)
 	return crypto_tfm_ctx(&tfm->base);
 }
 
-static inline void crypto_rng_set_entropy(struct crypto_rng *tfm,
-					  const u8 *data, unsigned int len)
-{
-	crypto_rng_alg(tfm)->set_ent(tfm, data, len);
-}
-
 #endif
diff --git a/include/crypto/rng.h b/include/crypto/rng.h
index 17bb3673d3c1..85312ea12274 100644
--- a/include/crypto/rng.h
+++ b/include/crypto/rng.h
@@ -28,8 +28,6 @@ struct crypto_rng;
  *		up a new state, the seed must be provided by the
  *		consumer while invoking this function. The required
  *		size of the seed is defined with @seedsize .
- * @set_ent:	Set entropy that would otherwise be obtained from
- *		entropy source.  Internal use only.
  * @seedsize:	The seed size required for a random number generator
  *		initialization defined with this variable. Some
  *		random number generators does not require a seed
@@ -43,8 +41,6 @@ struct rng_alg {
 			const u8 *src, unsigned int slen,
 			u8 *dst, unsigned int dlen);
 	int (*seed)(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);
-	void (*set_ent)(struct crypto_rng *tfm, const u8 *data,
-			unsigned int len);
 
 	unsigned int seedsize;
 
diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
index dc52a11ba6d1..e8d676350c8f 100644
--- a/include/uapi/linux/if_alg.h
+++ b/include/uapi/linux/if_alg.h
@@ -51,7 +51,7 @@ struct af_alg_iv {
 #define ALG_SET_OP			3
 #define ALG_SET_AEAD_ASSOCLEN		4
 #define ALG_SET_AEAD_AUTHSIZE		5
-#define ALG_SET_DRBG_ENTROPY		6
+#define ALG_SET_DRBG_ENTROPY		6 /* Not implemented any more */
 
 /* Operations */
 #define ALG_OP_DECRYPT			0
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/7] crypto: Entropy Source and DRNG Manager
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
  2022-01-26  7:03 ` [PATCH 1/7] crypto: DRBG - remove internal reseeding operation Stephan Müller
  2022-01-26  7:03 ` [PATCH 2/7] crypto: AF_ALG - remove ALG_SET_DRBG_ENTROPY interface Stephan Müller
@ 2022-01-26  7:04 ` Stephan Müller
  2022-01-26  7:04 ` [PATCH 4/7] crypto: move Jitter RNG header include dir Stephan Müller
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:04 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The kernel crypto API contains deterministic random number generators
(DRNG) which a caller must seed and reseed. The task of seeding a DRNG
is a non-trivial task requiring the consideration of a significant
number of aspects. The Entropy Source and DRNG Manager (ESDM) fills
that gap to transparently seed and reseed DRNGs. A user of the ESDM
obtains random numbers from an appropriately seeded and initialized
DRNG. Further, the ESDM controls various entropy sources guaranteeing
that they are properly initialized and managed.

The ESDM consists of two main parts:

- The entropy source (ES) manager implemented in esdm_es_mgr.c
  controls the available entropy sources including pulling appropritate
  amount of data from them for the DRNG manager.

- The DRNG manager provided with esdm_drng_mgr.c controls the DRNG(s)
  and ensures proper seeding and reseeding.

The entropy source manager controls the entropy sources registered in
the esdm_es array. The entropy sources provide a function pointer data
structure that is used to obtain the services from it.

The ES manager triggers the initial seeding of the DRNGs during boot
time in three stages:

1. The DRNG is seeded from the entropy sources if all entropy sources
   collectively have at least 32 bits of entropy available. The goal
   of this step is to ensure that the DRNG receive some initial entropy
   as early as possible.

2. The DRNG is reseeded from the entropy sources if all entropy sources
   collectively have at least 128 bits of entropy available.

3. The DRNG is reseeded from the entropy sources if all entropy sources
   collectively have at least 256 bits of entropy available.

At the time of the reseeding steps, the DRNG requests as much entropy as
is available in order to skip certain steps and reach the seeding level
of 256 bits. This may imply that one or more of the aforementioned steps
are skipped.

In all listed steps, the DRNG is (re)seeded with a number of random bytes
from the entropy pool that is at most the amount of entropy present in
the entropy pool. This means that for example when the entropy pool
contains 128 or more bits of entropy, the DRNG is seeded with that amount
of entropy as well.

Entropy sources (ES) inform the ES manager when new entropy has been
collected using the esdm_es_add_entropy() function. That function
schedules a DRNG (re)seed with the DRNG manager. When the DRNG manager
requests entropy data, the function esdm_fill_seed_buffer fills the seed
buffer by iterating through all available ES. The output of all entropy
sources is concatenated with each other. Further, the seed buffer
contains the amount of entropy each entropy credits its data. Finally a
time stamp is added.

The ES trigger such (re)seeding events only as long as not all DRNGs
are fully seeded with 256 bits of entropy. Once that seeding level is
reached, the triggers are not further processed.

The DRNG manager initializes the initial DRNG instance during late stage
of the kernel boot process before user space is triggered. The DRNG is
seeded at the following occasions:

- when the DRNG is initialized, the available amount of entropy is used,

- during boot time until the DRNG is fully initialized, the reaching of
  the aforementioned seeding steps of 32/128/256 bits of entropy trigger
  a reseed of the DRNG.

- at runtime after the elapse of 600 seconds since the last seeding,
  the DRNG reseeding flag is raised

- at runtime when more than 2^20 generate operations were performed by
  the given DRNG since last reseeding, the reseeding flag is raised

Raising the reseeding flag implies that the DRNG is seeded in process
context the next time a caller requests random numbers.

At runtime, the DRNG manager requires at least 128 bits of entropy from
the entropy sources (or 256 bits when the FIPS mode is active to be
SP800-90C compliant). It may be possible that the entropy sources may
not deliver that amount. The DRNG is reseeded with the available amount
of entropy and continues to operate. Yet, when after 2^30 generate
requests since the last seeding with 128 bits (or 256 bits in FIPS mode)
the DRNG cannot be seeded with 128 bits (or 256 bits), the DRNG becomes
unseeded which means it will not produce random numbers until it is
fully reseeded again.

To support the DRNG manager, a DRNG implementation is provided with
esdm_drng_kcapi.c. It uses the kernel crypto API RNG framework and
allows the specification of the used DRNG with the kernel command line
option of esdm_drng_kcapi.drng_name. If no reference is given, the
default is the SP800-90A DRBG. In case the chosen DRNG requires the seed
to have a certain length, a hash is used bring the entropy buffer into
the proper size.

In addition, the DRNG manager controls the message digest implementation
offered to entropy sources when they want to perform a conditioning
operation. As entropy sources may require the conditioning operation at
any time, the default is a SHA-256 software hash implementation that
neither sleeps nor does it need any memory allocation operation.
Therefore, this hash is available even for the earliest kernel
operations.

The initial drop of the ESDM includes the entropy source of the
"auxiliary" pool. This entropy source must always be present. It is an
entropy pool that is based on the state of a message digest. Every
insertion of data is a hash update operation. In order to obtain data, a
hash final operation is performed. The purpose of this auxiliary pool is
twofold:

- Provide a general interface to inject an arbitrary amount of data from
  any external source. When providing such data, the caller may specify
  the amount of entropy it contains.

- The auxiliary pool also provides the backtracking resistance for all
  entropy sources. Once a seed buffer is filled from all entropy sources
  it is re-inserted into the auxiliary pool at the same time it is used
  for seeding the DRNG. Naturally, the insertion of the seed buffer into
  the auxiliary pool is not credited with any entropy.

If enabled during compile time with the option of
CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES, the entropy source
oversampling is activated. However, this oversampling is only enforced
if the kernel is booted with fips=1. The oversampling pulls 128 more
bits of entropy than originally requested. This implies that when 256
bits of entropy are requested for a (re)seed of a DRNG, the ES are
queried for 384 bits. This oversampling complies with SP800-90C.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/Kconfig                 |   2 +
 crypto/Makefile                |   1 +
 crypto/esdm/Kconfig            |  79 +++++++
 crypto/esdm/Makefile           |  10 +
 crypto/esdm/esdm_definitions.h | 141 ++++++++++++
 crypto/esdm/esdm_drng_kcapi.c  | 201 +++++++++++++++++
 crypto/esdm/esdm_drng_kcapi.h  |  13 ++
 crypto/esdm/esdm_drng_mgr.c    | 398 +++++++++++++++++++++++++++++++++
 crypto/esdm/esdm_drng_mgr.h    |  85 +++++++
 crypto/esdm/esdm_es_aux.c      | 332 +++++++++++++++++++++++++++
 crypto/esdm/esdm_es_aux.h      |  44 ++++
 crypto/esdm/esdm_es_mgr.c      | 364 ++++++++++++++++++++++++++++++
 crypto/esdm/esdm_es_mgr.h      |  46 ++++
 crypto/esdm/esdm_es_mgr_cb.h   |  67 ++++++
 crypto/esdm/esdm_sha.h         |  14 ++
 crypto/esdm/esdm_sha256.c      |  72 ++++++
 include/crypto/esdm.h          | 115 ++++++++++
 17 files changed, 1984 insertions(+)
 create mode 100644 crypto/esdm/Kconfig
 create mode 100644 crypto/esdm/Makefile
 create mode 100644 crypto/esdm/esdm_definitions.h
 create mode 100644 crypto/esdm/esdm_drng_kcapi.c
 create mode 100644 crypto/esdm/esdm_drng_kcapi.h
 create mode 100644 crypto/esdm/esdm_drng_mgr.c
 create mode 100644 crypto/esdm/esdm_drng_mgr.h
 create mode 100644 crypto/esdm/esdm_es_aux.c
 create mode 100644 crypto/esdm/esdm_es_aux.h
 create mode 100644 crypto/esdm/esdm_es_mgr.c
 create mode 100644 crypto/esdm/esdm_es_mgr.h
 create mode 100644 crypto/esdm/esdm_es_mgr_cb.h
 create mode 100644 crypto/esdm/esdm_sha.h
 create mode 100644 crypto/esdm/esdm_sha256.c
 create mode 100644 include/crypto/esdm.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index a0de01ab6f0c..91f5ed9aab4f 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1790,6 +1790,8 @@ config CRYPTO_ZSTD
 
 comment "Random Number Generation"
 
+source "crypto/esdm/Kconfig"
+
 config CRYPTO_ANSI_CPRNG
 	tristate "Pseudo Random Number Generation for Cryptographic modules"
 	select CRYPTO_AES
diff --git a/crypto/Makefile b/crypto/Makefile
index d76bff8d0ffd..2b9aadbb5c69 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -159,6 +159,7 @@ obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o
 obj-$(CONFIG_CRYPTO_XXHASH) += xxhash_generic.o
 obj-$(CONFIG_CRYPTO_842) += 842.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
+obj-$(CONFIG_CRYPTO_ESDM) += esdm/
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
 obj-$(CONFIG_CRYPTO_DRBG) += drbg.o
 obj-$(CONFIG_CRYPTO_JITTERENTROPY) += jitterentropy_rng.o
diff --git a/crypto/esdm/Kconfig b/crypto/esdm/Kconfig
new file mode 100644
index 000000000000..1351d4d146dc
--- /dev/null
+++ b/crypto/esdm/Kconfig
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Entropy Source and DRNG Manager configuration
+#
+
+config CRYPTO_ESDM
+	bool "ESDM Implementation"
+	default n
+	select CRYPTO_LIB_SHA256 if CRYPTO
+	help
+	  The Entropy Source and DRNG Manager (ESDM) generates entropy
+	  from different entropy sources. Each entropy source can
+	  be enabled and configured independently. The interrupt
+	  entropy source can be configured to be SP800-90B compliant.
+	  The entire ESDM can be configured to be SP800-90C compliant.
+	  Runtime-switchable cryptographic support is available.
+	  The ESDM delivers significant entropy during boot.
+
+	  The ESDM also provides compliance to SP800-90A/B/C.
+
+menu "Entropy Source and DRNG Manager Configuration"
+	depends on CRYPTO_ESDM
+
+if CRYPTO_ESDM
+
+config CRYPTO_ESDM_SHA256
+	bool
+	default y if CRYPTO_LIB_SHA256
+
+menu "Specific DRNG seeding strategies"
+
+config CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+	bool "Oversample entropy sources"
+	default n
+	help
+	  When enabling this option, the entropy sources are
+	  over-sampled with the following approach: First, the
+	  the entropy sources are requested to provide 64 bits more
+	  entropy than the size of the entropy buffer. For example,
+	  if the entropy buffer is 256 bits, 320 bits of entropy
+	  is requested to fill that buffer.
+
+	  Second, the seed operation of the deterministic RNG
+	  requests 128 bits more data from each entropy source than
+	  the security strength of the DRNG during initialization.
+	  A prerequisite for this operation is that the digest size
+	  of the used hash must be at least equally large to generate
+	  that buffer. If the prerequisite is not met, this
+	  oversampling is not applied.
+
+	  This strategy is intended to offset the asymptotic entropy
+	  increase to reach full entropy in a buffer.
+
+	  The strategy is consistent with the requirements in
+	  NIST SP800-90C and is only enforced with fips=1.
+
+	  If unsure, say N.
+
+config CRYPTO_ESDM_OVERSAMPLE_ES_BITS
+	int
+	default 0 if !CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+	default 64 if CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+
+config CRYPTO_ESDM_SEED_BUFFER_INIT_ADD_BITS
+	int
+	default 0 if !CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+	default 128 if CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+
+endmenu # "Specific DRNG seeding strategies"
+
+config CRYPTO_ESDM_DRNG_KCAPI
+	bool
+	depends on CRYPTO
+	select CRYPTO_RNG
+	default y
+
+endif # CRYPTO_ESDM
+
+endmenu # CRYPTO_ESDM
diff --git a/crypto/esdm/Makefile b/crypto/esdm/Makefile
new file mode 100644
index 000000000000..24dc7af234b6
--- /dev/null
+++ b/crypto/esdm/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the Entropy Source and DRNG Manager.
+#
+
+obj-y					+= esdm_es_mgr.o esdm_drng_mgr.o \
+					   esdm_es_aux.o
+obj-$(CONFIG_CRYPTO_ESDM_SHA256)	+= esdm_sha256.o
+
+obj-$(CONFIG_CRYPTO_ESDM_DRNG_KCAPI)	+= esdm_drng_kcapi.o
diff --git a/crypto/esdm/esdm_definitions.h b/crypto/esdm/esdm_definitions.h
new file mode 100644
index 000000000000..e4c5bf5f757c
--- /dev/null
+++ b/crypto/esdm/esdm_definitions.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_DEFINITIONS_H
+#define _ESDM_DEFINITIONS_H
+
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+#include <linux/slab.h>
+
+/*************************** General ESDM parameter ***************************/
+
+/* Security strength of ESDM -- this must match DRNG security strength */
+#define ESDM_DRNG_SECURITY_STRENGTH_BYTES 32
+#define ESDM_DRNG_SECURITY_STRENGTH_BITS (ESDM_DRNG_SECURITY_STRENGTH_BYTES * 8)
+#define ESDM_DRNG_INIT_SEED_SIZE_BITS \
+	(ESDM_DRNG_SECURITY_STRENGTH_BITS +      \
+	 CONFIG_CRYPTO_ESDM_SEED_BUFFER_INIT_ADD_BITS)
+#define ESDM_DRNG_INIT_SEED_SIZE_BYTES (ESDM_DRNG_INIT_SEED_SIZE_BITS >> 3)
+
+/*
+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is
+ * considered a safer margin.
+ *
+ * This value is allowed to be changed.
+ */
+#define ESDM_DRNG_MAX_REQSIZE		(1<<12)
+
+/*
+ * SP800-90A defines a maximum number of requests between reseeds of 2^48.
+ * The given value is considered a much safer margin, balancing requests for
+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be
+ * larger than INT_MAX because it is used in an atomic_t.
+ *
+ * This value is allowed to be changed.
+ */
+#define ESDM_DRNG_RESEED_THRESH		(1<<20)
+
+/*
+ * Maximum DRNG generation operations without reseed having full entropy
+ * This value defines the absolute maximum value of DRNG generation operations
+ * without a reseed holding full entropy. ESDM_DRNG_RESEED_THRESH is the
+ * threshold when a new reseed is attempted. But it is possible that this fails
+ * to deliver full entropy. In this case the DRNG will continue to provide data
+ * even though it was not reseeded with full entropy. To avoid in the extreme
+ * case that no reseed is performed for too long, this threshold is enforced.
+ * If that absolute low value is reached, the ESDM is marked as not operational.
+ *
+ * This value is allowed to be changed.
+ */
+#define ESDM_DRNG_MAX_WITHOUT_RESEED	(1<<30)
+
+/*
+ * Min required seed entropy is 128 bits covering the minimum entropy
+ * requirement of SP800-131A and the German BSI's TR02102.
+ *
+ * This value is allowed to be changed.
+ */
+#define ESDM_FULL_SEED_ENTROPY_BITS	ESDM_DRNG_SECURITY_STRENGTH_BITS
+#define ESDM_MIN_SEED_ENTROPY_BITS	128
+#define ESDM_INIT_ENTROPY_BITS		32
+
+/*
+ * Wakeup value
+ *
+ * This value is allowed to be changed but must not be larger than the
+ * digest size of the hash operation used update the aux_pool.
+ */
+#ifdef CONFIG_CRYPTO_ESDM_SHA256
+# define ESDM_ATOMIC_DIGEST_SIZE	SHA256_DIGEST_SIZE
+#else
+# define ESDM_ATOMIC_DIGEST_SIZE	SHA1_DIGEST_SIZE
+#endif
+#define ESDM_WRITE_WAKEUP_ENTROPY	ESDM_ATOMIC_DIGEST_SIZE
+
+/*
+ * If the switching support is configured, we must provide support up to
+ * the largest digest size. Without switching support, we know it is only
+ * the built-in digest size.
+ */
+#ifdef CONFIG_CRYPTO_ESDM_CRYPTO_SWITCH
+# define ESDM_MAX_DIGESTSIZE		64
+#else
+# define ESDM_MAX_DIGESTSIZE		ESDM_ATOMIC_DIGEST_SIZE
+#endif
+
+/*
+ * Oversampling factor of timer-based events to obtain
+ * ESDM_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a
+ * high-resolution time stamp is not available. In this case, jiffies and
+ * register contents are used to fill the entropy pool. These noise sources
+ * are much less entropic than the high-resolution timer. The entropy content
+ * is the entropy content assumed with ESDM_[IRQ|SCHED]_ENTROPY_BITS divided by
+ * ESDM_ES_OVERSAMPLING_FACTOR.
+ *
+ * This value is allowed to be changed.
+ */
+#define ESDM_ES_OVERSAMPLING_FACTOR	10
+
+/* Alignmask that is intended to be identical to CRYPTO_MINALIGN */
+#define ESDM_KCAPI_ALIGN		ARCH_KMALLOC_MINALIGN
+
+/*
+ * This definition must provide a buffer that is equal to SHASH_DESC_ON_STACK
+ * as it will be casted into a struct shash_desc.
+ */
+#define ESDM_POOL_SIZE	(sizeof(struct shash_desc) + HASH_MAX_DESCSIZE)
+
+/****************************** Helper code ***********************************/
+
+static inline u32 esdm_fast_noise_entropylevel(u32 ent_bits, u32 requested_bits)
+{
+	/* Obtain entropy statement */
+	ent_bits = ent_bits * requested_bits / ESDM_DRNG_SECURITY_STRENGTH_BITS;
+	/* Cap entropy to buffer size in bits */
+	ent_bits = min_t(u32, ent_bits, requested_bits);
+	return ent_bits;
+}
+
+/* Convert entropy in bits into nr. of events with the same entropy content. */
+static inline u32 esdm_entropy_to_data(u32 entropy_bits, u32 entropy_rate)
+{
+	return ((entropy_bits * entropy_rate) /
+		ESDM_DRNG_SECURITY_STRENGTH_BITS);
+}
+
+/* Convert number of events into entropy value. */
+static inline u32 esdm_data_to_entropy(u32 irqnum, u32 entropy_rate)
+{
+	return ((irqnum * ESDM_DRNG_SECURITY_STRENGTH_BITS) /
+		entropy_rate);
+}
+
+static inline u32 atomic_read_u32(atomic_t *v)
+{
+	return (u32)atomic_read(v);
+}
+
+#endif /* _ESDM_DEFINITIONS_H */
diff --git a/crypto/esdm/esdm_drng_kcapi.c b/crypto/esdm/esdm_drng_kcapi.c
new file mode 100644
index 000000000000..ae8d2be91b37
--- /dev/null
+++ b/crypto/esdm/esdm_drng_kcapi.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the ESDM providing the cryptographic primitives using the
+ * kernel crypto API.
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/esdm.h>
+#include <crypto/hash.h>
+#include <crypto/rng.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include "esdm_drng_kcapi.h"
+
+static char *drng_name =
+#ifdef CONFIG_CRYPTO_DRBG_CTR
+	/* CTR_DRBG with AES-256 using derivation function */
+	"drbg_nopr_ctr_aes256";
+#elif defined CONFIG_CRYPTO_DRBG_HMAC
+	/* HMAC_DRBG with SHA-512 */
+	"drbg_nopr_hmac_sha512";
+#elif defined CONFIG_CRYPTO_DRBG_HASH
+	/* Hash_DRBG with SHA-512 using derivation function */
+	"drbg_nopr_sha512";
+#else
+	NULL;
+#endif
+module_param(drng_name, charp, 0444);
+MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG");
+
+static char *seed_hash = NULL;
+module_param(seed_hash, charp, 0444);
+MODULE_PARM_DESC(seed_hash,
+		 "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG");
+
+struct esdm_drng_info {
+	struct crypto_rng *kcapi_rng;
+	struct crypto_shash *hash_tfm;
+};
+
+static int esdm_kcapi_drng_seed_helper(void *drng, const u8 *inbuf,
+				       u32 inbuflen)
+{
+	struct esdm_drng_info *esdm_drng_info = (struct esdm_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = esdm_drng_info->kcapi_rng;
+	struct crypto_shash *hash_tfm = esdm_drng_info->hash_tfm;
+	SHASH_DESC_ON_STACK(shash, hash_tfm);
+	u32 digestsize;
+	u8 digest[HASH_MAX_DIGESTSIZE] __aligned(8);
+	int ret;
+
+	if (!hash_tfm)
+		return crypto_rng_reset(kcapi_rng, inbuf, inbuflen);
+
+	shash->tfm = hash_tfm;
+	digestsize = crypto_shash_digestsize(hash_tfm);
+
+	ret = crypto_shash_digest(shash, inbuf, inbuflen, digest);
+	shash_desc_zero(shash);
+	if (ret)
+		return ret;
+
+	ret = crypto_rng_reset(kcapi_rng, digest, digestsize);
+	if (ret)
+		return ret;
+
+	memzero_explicit(digest, digestsize);
+	return 0;
+}
+
+static int esdm_kcapi_drng_generate_helper(void *drng, u8 *outbuf,
+					   u32 outbuflen)
+{
+	struct esdm_drng_info *esdm_drng_info = (struct esdm_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = esdm_drng_info->kcapi_rng;
+	int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen);
+
+	if (ret < 0)
+		return ret;
+
+	return outbuflen;
+}
+
+static void *esdm_kcapi_drng_alloc(u32 sec_strength)
+{
+	struct esdm_drng_info *esdm_drng_info;
+	struct crypto_rng *kcapi_rng;
+	u32 time = random_get_entropy();
+	int seedsize, rv;
+	void *ret =  ERR_PTR(-ENOMEM);
+
+	if (!drng_name) {
+		pr_err("DRNG name missing\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!memcmp(drng_name, "stdrng", 6) ||
+	    !memcmp(drng_name, "jitterentropy_rng", 17)) {
+		pr_err("Refusing to load the requested random number generator\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	esdm_drng_info = kzalloc(sizeof(*esdm_drng_info), GFP_KERNEL);
+	if (!esdm_drng_info)
+		return ERR_PTR(-ENOMEM);
+
+	kcapi_rng = crypto_alloc_rng(drng_name, 0, 0);
+	if (IS_ERR(kcapi_rng)) {
+		pr_err("DRNG %s cannot be allocated\n", drng_name);
+		ret = ERR_CAST(kcapi_rng);
+		goto free;
+	}
+
+	esdm_drng_info->kcapi_rng = kcapi_rng;
+
+	seedsize = crypto_rng_seedsize(kcapi_rng);
+	if (seedsize) {
+		struct crypto_shash *hash_tfm;
+
+		if (!seed_hash) {
+			switch (seedsize) {
+			case 32:
+				seed_hash = "sha256";
+				break;
+			case 48:
+				seed_hash = "sha384";
+				break;
+			case 64:
+				seed_hash = "sha512";
+				break;
+			default:
+				pr_err("Seed size %d cannot be processed\n",
+				       seedsize);
+				goto dealloc;
+			}
+		}
+
+		hash_tfm = crypto_alloc_shash(seed_hash, 0, 0);
+		if (IS_ERR(hash_tfm)) {
+			ret = ERR_CAST(hash_tfm);
+			goto dealloc;
+		}
+
+		if (seedsize != crypto_shash_digestsize(hash_tfm)) {
+			pr_err("Seed hash output size not equal to DRNG seed size\n");
+			crypto_free_shash(hash_tfm);
+			ret = ERR_PTR(-EINVAL);
+			goto dealloc;
+		}
+
+		esdm_drng_info->hash_tfm = hash_tfm;
+
+		pr_info("Seed hash %s allocated\n", seed_hash);
+	}
+
+	rv = esdm_kcapi_drng_seed_helper(esdm_drng_info, (u8 *)(&time),
+					 sizeof(time));
+	if (rv) {
+		ret = ERR_PTR(rv);
+		goto dealloc;
+	}
+
+	pr_info("Kernel crypto API DRNG %s allocated\n", drng_name);
+
+	return esdm_drng_info;
+
+dealloc:
+	crypto_free_rng(kcapi_rng);
+free:
+	kfree(esdm_drng_info);
+	return ret;
+}
+
+static void esdm_kcapi_drng_dealloc(void *drng)
+{
+	struct esdm_drng_info *esdm_drng_info = (struct esdm_drng_info *)drng;
+	struct crypto_rng *kcapi_rng = esdm_drng_info->kcapi_rng;
+
+	crypto_free_rng(kcapi_rng);
+	if (esdm_drng_info->hash_tfm)
+		crypto_free_shash(esdm_drng_info->hash_tfm);
+	kfree(esdm_drng_info);
+	pr_info("DRNG %s deallocated\n", drng_name);
+}
+
+static const char *esdm_kcapi_drng_name(void)
+{
+	return drng_name;
+}
+
+const struct esdm_drng_cb esdm_kcapi_drng_cb = {
+	.drng_name	= esdm_kcapi_drng_name,
+	.drng_alloc	= esdm_kcapi_drng_alloc,
+	.drng_dealloc	= esdm_kcapi_drng_dealloc,
+	.drng_seed	= esdm_kcapi_drng_seed_helper,
+	.drng_generate	= esdm_kcapi_drng_generate_helper,
+};
diff --git a/crypto/esdm/esdm_drng_kcapi.h b/crypto/esdm/esdm_drng_kcapi.h
new file mode 100644
index 000000000000..0950a15fdfaa
--- /dev/null
+++ b/crypto/esdm/esdm_drng_kcapi.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * ESDM kernel crypto API DRNG definition
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_KCAPI_DRNG_H
+#define _ESDM_KCAPI_DRNG_H
+
+extern const struct esdm_drng_cb esdm_kcapi_drng_cb;
+
+#endif /* _ESDM_KCAPI_DRNG_H */
diff --git a/crypto/esdm/esdm_drng_mgr.c b/crypto/esdm/esdm_drng_mgr.c
new file mode 100644
index 000000000000..53b683b7ac05
--- /dev/null
+++ b/crypto/esdm/esdm_drng_mgr.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM DRNG management
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/esdm.h>
+#include <linux/fips.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include "esdm_drng_kcapi.h"
+#include "esdm_drng_mgr.h"
+#include "esdm_es_aux.h"
+#include "esdm_es_mgr.h"
+#include "esdm_sha.h"
+
+/*
+ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note,
+ * this is enforced with the next request of random numbers from the
+ * DRNG. Setting this value to zero implies a reseeding attempt before every
+ * generated random number.
+ */
+int esdm_drng_reseed_max_time = 600;
+
+/*
+ * Is ESDM for general-purpose use (i.e. is at least the esdm_drng_init
+ * fully allocated)?
+ */
+static atomic_t esdm_avail = ATOMIC_INIT(0);
+
+/*
+ * Default hash callback that provides the crypto primitive right from the
+ * kernel start. It must not perform any memory allocation operation, but
+ * simply perform the hash calculation.
+ */
+const struct esdm_hash_cb *esdm_default_hash_cb = &esdm_sha_hash_cb;
+
+/*
+ * Default DRNG callback that provides the crypto primitive which is
+ * allocated either during late kernel boot stage. So, it is permissible for
+ * the callback to perform memory allocation operations.
+ */
+const struct esdm_drng_cb *esdm_default_drng_cb = &esdm_kcapi_drng_cb;
+
+/* DRNG for non-atomic use cases */
+static struct esdm_drng esdm_drng_init = {
+	ESDM_DRNG_STATE_INIT(esdm_drng_init, NULL, NULL, NULL,
+			     &esdm_sha_hash_cb),
+	.lock = __MUTEX_INITIALIZER(esdm_drng_init.lock),
+};
+
+static u32 max_wo_reseed = ESDM_DRNG_MAX_WITHOUT_RESEED;
+#ifdef CONFIG_CRYPTO_ESDM_RUNTIME_MAX_WO_RESEED_CONFIG
+module_param(max_wo_reseed, uint, 0444);
+MODULE_PARM_DESC(max_wo_reseed,
+		 "Maximum number of DRNG generate operation without full reseed\n");
+#endif
+
+/* Wait queue to wait until the ESDM is initialized - can freely be used */
+DECLARE_WAIT_QUEUE_HEAD(esdm_init_wait);
+
+/********************************** Helper ************************************/
+
+bool esdm_get_available(void)
+{
+	return likely(atomic_read(&esdm_avail));
+}
+
+struct esdm_drng *esdm_drng_init_instance(void)
+{
+	return &esdm_drng_init;
+}
+
+struct esdm_drng *esdm_drng_node_instance(void)
+{
+	return esdm_drng_init_instance();
+}
+
+void esdm_drng_reset(struct esdm_drng *drng)
+{
+	atomic_set(&drng->requests, ESDM_DRNG_RESEED_THRESH);
+	atomic_set(&drng->requests_since_fully_seeded, 0);
+	drng->last_seeded = jiffies;
+	drng->fully_seeded = false;
+	drng->force_reseed = true;
+	pr_debug("reset DRNG\n");
+}
+
+/* Initialize the DRNG, except the mutex lock */
+int esdm_drng_alloc_common(struct esdm_drng *drng,
+			   const struct esdm_drng_cb *drng_cb)
+{
+	if (!drng || !drng_cb)
+		return -EINVAL;
+
+	drng->drng_cb = drng_cb;
+	drng->drng = drng_cb->drng_alloc(ESDM_DRNG_SECURITY_STRENGTH_BYTES);
+	if (IS_ERR(drng->drng))
+		return PTR_ERR(drng->drng);
+
+	esdm_drng_reset(drng);
+	return 0;
+}
+
+/* Initialize the default DRNG during boot and perform its seeding */
+int esdm_drng_initalize(void)
+{
+	int ret;
+
+	if (esdm_get_available())
+		return 0;
+
+	/* Catch programming error */
+	WARN_ON(esdm_drng_init.hash_cb != esdm_default_hash_cb);
+
+	mutex_lock(&esdm_drng_init.lock);
+	if (esdm_get_available()) {
+		mutex_unlock(&esdm_drng_init.lock);
+		return 0;
+	}
+
+	ret = esdm_drng_alloc_common(&esdm_drng_init, esdm_default_drng_cb);
+	mutex_unlock(&esdm_drng_init.lock);
+	if (ret)
+		return ret;
+
+	pr_debug("ESDM for general use is available\n");
+	atomic_set(&esdm_avail, 1);
+
+	/* Seed the DRNG with any entropy available */
+	if (!esdm_pool_trylock()) {
+		pr_info("Initial DRNG initialized triggering first seeding\n");
+		esdm_drng_seed_work(NULL);
+	} else {
+		pr_info("Initial DRNG initialized without seeding\n");
+	}
+
+	return 0;
+}
+
+static int __init esdm_drng_make_available(void)
+{
+	return esdm_drng_initalize();
+}
+late_initcall(esdm_drng_make_available);
+
+bool esdm_sp80090c_compliant(void)
+{
+	if (!IS_ENABLED(CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES))
+		return false;
+
+	/* SP800-90C only requested in FIPS mode */
+	return fips_enabled;
+}
+
+/************************* Random Number Generation ***************************/
+
+/* Inject a data buffer into the DRNG - caller must hold its lock */
+void esdm_drng_inject(struct esdm_drng *drng, const u8 *inbuf, u32 inbuflen,
+		      bool fully_seeded, const char *drng_type)
+{
+	BUILD_BUG_ON(ESDM_DRNG_RESEED_THRESH > INT_MAX);
+	pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen);
+	if (drng->drng_cb->drng_seed(drng->drng, inbuf, inbuflen) < 0) {
+		pr_warn("seeding of %s DRNG failed\n", drng_type);
+		drng->force_reseed = true;
+	} else {
+		int gc = ESDM_DRNG_RESEED_THRESH - atomic_read(&drng->requests);
+
+		pr_debug("%s DRNG stats since last seeding: %lu secs; generate calls: %d\n",
+			 drng_type,
+			 (time_after(jiffies, drng->last_seeded) ?
+			  (jiffies - drng->last_seeded) : 0) / HZ, gc);
+
+		/* Count the numbers of generate ops since last fully seeded */
+		if (fully_seeded)
+			atomic_set(&drng->requests_since_fully_seeded, 0);
+		else
+			atomic_add(gc, &drng->requests_since_fully_seeded);
+
+		drng->last_seeded = jiffies;
+		atomic_set(&drng->requests, ESDM_DRNG_RESEED_THRESH);
+		drng->force_reseed = false;
+
+		if (!drng->fully_seeded) {
+			drng->fully_seeded = fully_seeded;
+			if (drng->fully_seeded)
+				pr_debug("%s DRNG fully seeded\n", drng_type);
+		}
+	}
+}
+
+/* Perform the seeding of the DRNG with data from noise source */
+static void esdm_drng_seed_es(struct esdm_drng *drng)
+{
+	struct entropy_buf seedbuf __aligned(ESDM_KCAPI_ALIGN);
+
+	esdm_fill_seed_buffer(&seedbuf,
+			      esdm_get_seed_entropy_osr(drng->fully_seeded));
+
+	mutex_lock(&drng->lock);
+	esdm_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf),
+			 esdm_fully_seeded_eb(drng->fully_seeded, &seedbuf),
+			 "regular");
+	mutex_unlock(&drng->lock);
+
+	/* Set the seeding state of the ESDM */
+	esdm_init_ops(&seedbuf);
+
+	memzero_explicit(&seedbuf, sizeof(seedbuf));
+}
+
+static void esdm_drng_seed(struct esdm_drng *drng)
+{
+	BUILD_BUG_ON(ESDM_MIN_SEED_ENTROPY_BITS >
+		     ESDM_DRNG_SECURITY_STRENGTH_BITS);
+
+	if (esdm_get_available()) {
+		/* (Re-)Seed DRNG */
+		esdm_drng_seed_es(drng);
+	} else {
+		esdm_init_ops(NULL);
+	}
+}
+
+static void _esdm_drng_seed_work(struct esdm_drng *drng, u32 node)
+{
+	pr_debug("reseed triggered by system events for DRNG on NUMA node %d\n",
+		 node);
+	esdm_drng_seed(drng);
+	if (drng->fully_seeded) {
+		/* Prevent reseed storm */
+		drng->last_seeded += node * 100 * HZ;
+	}
+}
+
+/*
+ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work()
+ */
+void esdm_drng_seed_work(struct work_struct *dummy)
+{
+	if (!esdm_drng_init.fully_seeded) {
+		_esdm_drng_seed_work(&esdm_drng_init, 0);
+		goto out;
+	}
+
+	esdm_pool_all_numa_nodes_seeded(true);
+
+out:
+	/* Allow the seeding operation to be called again */
+	esdm_pool_unlock();
+}
+
+/* Force all DRNGs to reseed before next generation */
+void esdm_drng_force_reseed(void)
+{
+	esdm_drng_init.force_reseed = esdm_drng_init.fully_seeded;
+	pr_debug("force reseed of initial DRNG\n");
+}
+EXPORT_SYMBOL(esdm_drng_force_reseed);
+
+static bool esdm_drng_must_reseed(struct esdm_drng *drng)
+{
+	return (atomic_dec_and_test(&drng->requests) ||
+		drng->force_reseed ||
+		time_after(jiffies,
+			   drng->last_seeded + esdm_drng_reseed_max_time * HZ));
+}
+
+/*
+ * esdm_drng_get() - Get random data out of the DRNG which is reseeded
+ * frequently.
+ *
+ * @drng: DRNG instance
+ * @outbuf: buffer for storing random data
+ * @outbuflen: length of outbuf
+ *
+ * Return:
+ * * < 0 in error case (DRNG generation or update failed)
+ * * >=0 returning the returned number of bytes
+ */
+int esdm_drng_get(struct esdm_drng *drng, u8 *outbuf, u32 outbuflen)
+{
+	u32 processed = 0;
+
+	if (!outbuf || !outbuflen)
+		return 0;
+
+	if (!esdm_get_available())
+		return -EOPNOTSUPP;
+
+	outbuflen = min_t(size_t, outbuflen, INT_MAX);
+
+	/* If DRNG operated without proper reseed for too long, block ESDM */
+	BUILD_BUG_ON(ESDM_DRNG_MAX_WITHOUT_RESEED < ESDM_DRNG_RESEED_THRESH);
+	if (atomic_read_u32(&drng->requests_since_fully_seeded) > max_wo_reseed)
+		esdm_unset_fully_seeded(drng);
+
+	while (outbuflen) {
+		u32 todo = min_t(u32, outbuflen, ESDM_DRNG_MAX_REQSIZE);
+		int ret;
+
+		if (esdm_drng_must_reseed(drng)) {
+			if (esdm_pool_trylock()) {
+				drng->force_reseed = true;
+			} else {
+				esdm_drng_seed(drng);
+				esdm_pool_unlock();
+			}
+		}
+
+		mutex_lock(&drng->lock);
+		ret = drng->drng_cb->drng_generate(drng->drng,
+						   outbuf + processed, todo);
+		mutex_unlock(&drng->lock);
+		if (ret <= 0) {
+			pr_warn("getting random data from DRNG failed (%d)\n",
+				ret);
+			return -EFAULT;
+		}
+		processed += ret;
+		outbuflen -= ret;
+	}
+
+	return processed;
+}
+
+int esdm_drng_get_sleep(u8 *outbuf, u32 outbuflen)
+{
+	struct esdm_drng *drng = &esdm_drng_init;
+	int ret;
+
+	might_sleep();
+
+	ret = esdm_drng_initalize();
+	if (ret)
+		return ret;
+
+	return esdm_drng_get(drng, outbuf, outbuflen);
+}
+
+/* Reset ESDM such that all existing entropy is gone */
+static void _esdm_reset(struct work_struct *work)
+{
+	mutex_lock(&esdm_drng_init.lock);
+	esdm_drng_reset(&esdm_drng_init);
+	mutex_unlock(&esdm_drng_init.lock);
+
+	esdm_set_entropy_thresh(ESDM_INIT_ENTROPY_BITS);
+
+	esdm_reset_state();
+}
+
+static DECLARE_WORK(esdm_reset_work, _esdm_reset);
+
+void esdm_reset(void)
+{
+	schedule_work(&esdm_reset_work);
+}
+
+/******************* Generic ESDM kernel output interfaces ********************/
+
+int esdm_drng_sleep_while_nonoperational(int nonblock)
+{
+	if (likely(!esdm_state_operational()))
+		return 0;
+	if (nonblock)
+		return -EAGAIN;
+	return wait_event_interruptible(esdm_init_wait,
+					esdm_state_operational());
+}
+
+int esdm_drng_sleep_while_non_min_seeded(void)
+{
+	if (likely(esdm_state_min_seeded()))
+		return 0;
+	return wait_event_interruptible(esdm_init_wait,
+					esdm_state_min_seeded());
+}
+
+void esdm_get_random_bytes_full(void *buf, int nbytes)
+{
+	esdm_drng_sleep_while_nonoperational(0);
+	esdm_drng_get_sleep((u8 *)buf, (u32)nbytes);
+}
+EXPORT_SYMBOL(esdm_get_random_bytes_full);
+
+void esdm_get_random_bytes_min(void *buf, int nbytes)
+{
+	esdm_drng_sleep_while_non_min_seeded();
+	esdm_drng_get_sleep((u8 *)buf, (u32)nbytes);
+}
+EXPORT_SYMBOL(esdm_get_random_bytes_min);
diff --git a/crypto/esdm/esdm_drng_mgr.h b/crypto/esdm/esdm_drng_mgr.h
new file mode 100644
index 000000000000..241b94b84bf7
--- /dev/null
+++ b/crypto/esdm/esdm_drng_mgr.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_DRNG_H
+#define _ESDM_DRNG_H
+
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+#include "esdm_definitions.h"
+
+extern struct wait_queue_head esdm_init_wait;
+extern int esdm_drng_reseed_max_time;
+extern struct mutex esdm_crypto_cb_update;
+extern const struct esdm_drng_cb *esdm_default_drng_cb;
+extern const struct esdm_hash_cb *esdm_default_hash_cb;
+
+/* DRNG state handle */
+struct esdm_drng {
+	void *drng;				/* DRNG handle */
+	void *hash;				/* Hash handle */
+	const struct esdm_drng_cb *drng_cb;	/* DRNG callbacks */
+	const struct esdm_hash_cb *hash_cb;	/* Hash callbacks */
+	atomic_t requests;			/* Number of DRNG requests */
+	atomic_t requests_since_fully_seeded;	/* Number DRNG requests since
+						 * last fully seeded
+						 */
+	unsigned long last_seeded;		/* Last time it was seeded */
+	bool fully_seeded;			/* Is DRNG fully seeded? */
+	bool force_reseed;			/* Force a reseed */
+
+	rwlock_t hash_lock;			/* Lock hash_cb replacement */
+	/* Lock write operations on DRNG state, DRNG replacement of drng_cb */
+	struct mutex lock;			/* Non-atomic DRNG operation */
+	spinlock_t spin_lock;			/* Atomic DRNG operation */
+};
+
+#define ESDM_DRNG_STATE_INIT(x, d, h, d_cb, h_cb) \
+	.drng				= d, \
+	.hash				= h, \
+	.drng_cb			= d_cb, \
+	.hash_cb			= h_cb, \
+	.requests			= ATOMIC_INIT(ESDM_DRNG_RESEED_THRESH),\
+	.requests_since_fully_seeded	= ATOMIC_INIT(0), \
+	.last_seeded			= 0, \
+	.fully_seeded			= false, \
+	.force_reseed			= true, \
+	.hash_lock			= __RW_LOCK_UNLOCKED(x.hash_lock)
+
+struct esdm_drng *esdm_drng_init_instance(void);
+struct esdm_drng *esdm_drng_node_instance(void);
+
+void esdm_reset(void);
+int esdm_drng_alloc_common(struct esdm_drng *drng,
+			   const struct esdm_drng_cb *crypto_cb);
+int esdm_drng_initalize(void);
+bool esdm_sp80090c_compliant(void);
+bool esdm_get_available(void);
+void esdm_drng_reset(struct esdm_drng *drng);
+void esdm_drng_inject(struct esdm_drng *drng, const u8 *inbuf, u32 inbuflen,
+		      bool fully_seeded, const char *drng_type);
+int esdm_drng_get(struct esdm_drng *drng, u8 *outbuf, u32 outbuflen);
+int esdm_drng_sleep_while_nonoperational(int nonblock);
+int esdm_drng_sleep_while_non_min_seeded(void);
+int esdm_drng_get_sleep(u8 *outbuf, u32 outbuflen);
+void esdm_drng_seed_work(struct work_struct *dummy);
+void esdm_drng_force_reseed(void);
+
+static inline u32 esdm_compress_osr(void)
+{
+	return esdm_sp80090c_compliant() ?
+	       CONFIG_CRYPTO_ESDM_OVERSAMPLE_ES_BITS : 0;
+}
+
+static inline u32 esdm_reduce_by_osr(u32 entropy_bits)
+{
+	u32 osr_bits = esdm_compress_osr();
+
+	return (entropy_bits >= osr_bits) ? (entropy_bits - osr_bits) : 0;
+}
+
+#endif /* _ESDM_DRNG_H */
diff --git a/crypto/esdm/esdm_es_aux.c b/crypto/esdm/esdm_es_aux.c
new file mode 100644
index 000000000000..9a665eaf856b
--- /dev/null
+++ b/crypto/esdm/esdm_es_aux.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM Slow Entropy Source: Auxiliary entropy pool
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/esdm.h>
+
+#include "esdm_es_aux.h"
+#include "esdm_es_mgr.h"
+
+/*
+ * This is the auxiliary pool
+ *
+ * The aux pool array is aligned to 8 bytes to comfort the kernel crypto API
+ * cipher implementations of the hash functions used to read the pool: for some
+ * accelerated implementations, we need an alignment to avoid a realignment
+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto
+ * implementations.
+ */
+struct esdm_pool {
+	u8 aux_pool[ESDM_POOL_SIZE];	/* Aux pool: digest state */
+	atomic_t aux_entropy_bits;
+	atomic_t digestsize;		/* Digest size of used hash */
+	bool initialized;		/* Aux pool initialized? */
+
+	/* Serialize read of entropy pool and update of aux pool */
+	spinlock_t lock;
+};
+
+static struct esdm_pool esdm_pool __aligned(ESDM_KCAPI_ALIGN) = {
+	.aux_entropy_bits	= ATOMIC_INIT(0),
+	.digestsize		= ATOMIC_INIT(ESDM_ATOMIC_DIGEST_SIZE),
+	.initialized		= false,
+	.lock			= __SPIN_LOCK_UNLOCKED(esdm_pool.lock)
+};
+
+/********************************** Helper ***********************************/
+
+/* Entropy in bits present in aux pool */
+static u32 esdm_aux_avail_entropy(u32 __unused)
+{
+	/* Cap available entropy with max entropy */
+	u32 avail_bits = min_t(u32, esdm_get_digestsize(),
+			       atomic_read_u32(&esdm_pool.aux_entropy_bits));
+
+	/* Consider oversampling rate due to aux pool conditioning */
+	return esdm_reduce_by_osr(avail_bits);
+}
+
+/* Set the digest size of the used hash in bytes */
+static void esdm_set_digestsize(u32 digestsize)
+{
+	struct esdm_pool *pool = &esdm_pool;
+	u32 ent_bits = atomic_xchg_relaxed(&pool->aux_entropy_bits, 0),
+	    old_digestsize = esdm_get_digestsize();
+
+	atomic_set(&esdm_pool.digestsize, digestsize);
+
+	/*
+	 * Update the write wakeup threshold which must not be larger
+	 * than the digest size of the current conditioning hash.
+	 */
+	digestsize = esdm_reduce_by_osr(digestsize << 3);
+	esdm_write_wakeup_bits = digestsize;
+
+	/*
+	 * In case the new digest is larger than the old one, cap the available
+	 * entropy to the old message digest used to process the existing data.
+	 */
+	ent_bits = min_t(u32, ent_bits, old_digestsize);
+	atomic_add(ent_bits, &pool->aux_entropy_bits);
+}
+
+static int __init esdm_init_wakeup_bits(void)
+{
+	u32 digestsize = esdm_reduce_by_osr(esdm_get_digestsize());
+
+	esdm_write_wakeup_bits = digestsize;
+	return 0;
+}
+core_initcall(esdm_init_wakeup_bits);
+
+/* Obtain the digest size provided by the used hash in bits */
+u32 esdm_get_digestsize(void)
+{
+	return atomic_read_u32(&esdm_pool.digestsize) << 3;
+}
+
+/* Set entropy content in user-space controllable aux pool */
+void esdm_pool_set_entropy(u32 entropy_bits)
+{
+	atomic_set(&esdm_pool.aux_entropy_bits, entropy_bits);
+}
+
+static void esdm_aux_reset(void)
+{
+	esdm_pool_set_entropy(0);
+}
+
+/*
+ * Replace old with new hash for auxiliary pool handling
+ *
+ * Assumption: the caller must guarantee that the new_cb is available during the
+ * entire operation (e.g. it must hold the write lock against pointer updating).
+ */
+static int
+esdm_aux_switch_hash(struct esdm_drng *drng, int __unused,
+		     const struct esdm_hash_cb *new_cb, void *new_hash,
+		     const struct esdm_hash_cb *old_cb)
+{
+	struct esdm_drng *init_drng = esdm_drng_init_instance();
+	struct esdm_pool *pool = &esdm_pool;
+	struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
+	u8 digest[ESDM_MAX_DIGESTSIZE];
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_CRYPTO_ESDM_CRYPTO_SWITCH))
+		return -EOPNOTSUPP;
+
+	if (unlikely(!pool->initialized))
+		return 0;
+
+	/* We only switch if the processed DRNG is the initial DRNG. */
+	if (init_drng != drng)
+		return 0;
+
+	/* Get the aux pool hash with old digest ... */
+	ret = old_cb->hash_final(shash, digest) ?:
+	      /* ... re-initialize the hash with the new digest ... */
+	      new_cb->hash_init(shash, new_hash) ?:
+	      /*
+	       * ... feed the old hash into the new state. We may feed
+	       * uninitialized memory into the new state, but this is
+	       * considered no issue and even good as we have some more
+	       * uncertainty here.
+	       */
+	      new_cb->hash_update(shash, digest, sizeof(digest));
+	if (!ret) {
+		esdm_set_digestsize(new_cb->hash_digestsize(new_hash));
+		pr_debug("Re-initialize aux entropy pool with hash %s\n",
+			 new_cb->hash_name());
+	}
+
+	memzero_explicit(digest, sizeof(digest));
+	return ret;
+}
+
+/* Insert data into auxiliary pool by using the hash update function. */
+static int
+esdm_aux_pool_insert_locked(const u8 *inbuf, u32 inbuflen, u32 entropy_bits)
+{
+	struct esdm_pool *pool = &esdm_pool;
+	struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
+	struct esdm_drng *drng = esdm_drng_init_instance();
+	const struct esdm_hash_cb *hash_cb;
+	unsigned long flags;
+	void *hash;
+	int ret;
+
+	entropy_bits = min_t(u32, entropy_bits, inbuflen << 3);
+
+	read_lock_irqsave(&drng->hash_lock, flags);
+	hash_cb = drng->hash_cb;
+	hash = drng->hash;
+
+	if (unlikely(!pool->initialized)) {
+		ret = hash_cb->hash_init(shash, hash);
+		if (ret)
+			goto out;
+		pool->initialized = true;
+	}
+
+	ret = hash_cb->hash_update(shash, inbuf, inbuflen);
+	if (ret)
+		goto out;
+
+	/*
+	 * Cap the available entropy to the hash output size compliant to
+	 * SP800-90B section 3.1.5.1 table 1.
+	 */
+	entropy_bits += atomic_read_u32(&pool->aux_entropy_bits);
+	atomic_set(&pool->aux_entropy_bits,
+		   min_t(u32, entropy_bits,
+			 hash_cb->hash_digestsize(hash) << 3));
+
+out:
+	read_unlock_irqrestore(&drng->hash_lock, flags);
+	return ret;
+}
+
+int esdm_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits)
+{
+	struct esdm_pool *pool = &esdm_pool;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	ret = esdm_aux_pool_insert_locked(inbuf, inbuflen, entropy_bits);
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	esdm_es_add_entropy();
+
+	return ret;
+}
+EXPORT_SYMBOL(esdm_pool_insert_aux);
+
+/************************* Get data from entropy pool *************************/
+
+/*
+ * Get auxiliary entropy pool and its entropy content for seed buffer.
+ * Caller must hold esdm_pool.pool->lock.
+ * @outbuf: buffer to store data in with size requested_bits
+ * @requested_bits: Requested amount of entropy
+ * @return: amount of entropy in outbuf in bits.
+ */
+static u32 esdm_aux_get_pool(u8 *outbuf, u32 requested_bits)
+{
+	struct esdm_pool *pool = &esdm_pool;
+	struct shash_desc *shash = (struct shash_desc *)pool->aux_pool;
+	struct esdm_drng *drng = esdm_drng_init_instance();
+	const struct esdm_hash_cb *hash_cb;
+	unsigned long flags;
+	void *hash;
+	u32 collected_ent_bits, returned_ent_bits, unused_bits = 0,
+	    digestsize, digestsize_bits, requested_bits_osr;
+	u8 aux_output[ESDM_MAX_DIGESTSIZE];
+
+	if (unlikely(!pool->initialized))
+		return 0;
+
+	read_lock_irqsave(&drng->hash_lock, flags);
+
+	hash_cb = drng->hash_cb;
+	hash = drng->hash;
+	digestsize = hash_cb->hash_digestsize(hash);
+	digestsize_bits = digestsize << 3;
+
+	/* Cap to maximum entropy that can ever be generated with given hash */
+	esdm_cap_requested(digestsize_bits, requested_bits);
+
+	/* Ensure that no more than the size of aux_pool can be requested */
+	requested_bits = min_t(u32, requested_bits, (ESDM_MAX_DIGESTSIZE << 3));
+	requested_bits_osr = requested_bits + esdm_compress_osr();
+
+	/* Cap entropy with entropy counter from aux pool and the used digest */
+	collected_ent_bits = min_t(u32, digestsize_bits,
+			       atomic_xchg_relaxed(&pool->aux_entropy_bits, 0));
+
+	/* We collected too much entropy and put the overflow back */
+	if (collected_ent_bits > requested_bits_osr) {
+		/* Amount of bits we collected too much */
+		unused_bits = collected_ent_bits - requested_bits_osr;
+		/* Put entropy back */
+		atomic_add(unused_bits, &pool->aux_entropy_bits);
+		/* Fix collected entropy */
+		collected_ent_bits = requested_bits_osr;
+	}
+
+	/* Apply oversampling: discount requested oversampling rate */
+	returned_ent_bits = esdm_reduce_by_osr(collected_ent_bits);
+
+	pr_debug("obtained %u bits by collecting %u bits of entropy from aux pool, %u bits of entropy remaining\n",
+		 returned_ent_bits, collected_ent_bits, unused_bits);
+
+	/* Get the digest for the aux pool to be returned to the caller ... */
+	if (hash_cb->hash_final(shash, aux_output) ||
+	    /*
+	     * ... and re-initialize the aux state. Do not add the aux pool
+	     * digest for backward secrecy as it will be added with the
+	     * insertion of the complete seed buffer after it has been filled.
+	     */
+	    hash_cb->hash_init(shash, hash)) {
+		returned_ent_bits = 0;
+	} else {
+		/*
+		 * Do not truncate the output size exactly to collected_ent_bits
+		 * as the aux pool may contain data that is not credited with
+		 * entropy, but we want to use them to stir the DRNG state.
+		 */
+		memcpy(outbuf, aux_output, requested_bits >> 3);
+	}
+
+	read_unlock_irqrestore(&drng->hash_lock, flags);
+	memzero_explicit(aux_output, digestsize);
+	return returned_ent_bits;
+}
+
+static void esdm_aux_get_backtrack(struct entropy_buf *eb, u32 requested_bits,
+				   bool __unused)
+{
+	struct esdm_pool *pool = &esdm_pool;
+	unsigned long flags;
+
+	/* Ensure aux pool extraction and backtracking op are atomic */
+	spin_lock_irqsave(&pool->lock, flags);
+
+	eb->e_bits[esdm_ext_es_aux] = esdm_aux_get_pool(eb->e[esdm_ext_es_aux],
+							requested_bits);
+
+	/* Mix the extracted data back into pool for backtracking resistance */
+	if (esdm_aux_pool_insert_locked((u8 *)eb,
+					sizeof(struct entropy_buf), 0))
+		pr_warn("Backtracking resistance operation failed\n");
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+static void esdm_aux_es_state(unsigned char *buf, size_t buflen)
+{
+	const struct esdm_drng *esdm_drng_init = esdm_drng_init_instance();
+
+	/* Assume the esdm_drng_init lock is taken by caller */
+	snprintf(buf, buflen,
+		 " Hash for operating entropy pool: %s\n"
+		 " Available entropy: %u\n",
+		 esdm_drng_init->hash_cb->hash_name(),
+		 esdm_aux_avail_entropy(0));
+}
+
+struct esdm_es_cb esdm_es_aux = {
+	.name			= "Auxiliary",
+	.get_ent		= esdm_aux_get_backtrack,
+	.curr_entropy		= esdm_aux_avail_entropy,
+	.max_entropy		= esdm_get_digestsize,
+	.state			= esdm_aux_es_state,
+	.reset			= esdm_aux_reset,
+	.switch_hash		= esdm_aux_switch_hash,
+};
diff --git a/crypto/esdm/esdm_es_aux.h b/crypto/esdm/esdm_es_aux.h
new file mode 100644
index 000000000000..fde7f34696b0
--- /dev/null
+++ b/crypto/esdm/esdm_es_aux.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_ES_AUX_H
+#define _ESDM_ES_AUX_H
+
+#include "esdm_drng_mgr.h"
+#include "esdm_es_mgr_cb.h"
+
+u32 esdm_get_digestsize(void);
+void esdm_pool_set_entropy(u32 entropy_bits);
+int esdm_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits);
+
+extern struct esdm_es_cb esdm_es_aux;
+
+/****************************** Helper code ***********************************/
+
+/* Obtain the security strength of the ESDM in bits */
+static inline u32 esdm_security_strength(void)
+{
+	/*
+	 * We use a hash to read the entropy in the entropy pool. According to
+	 * SP800-90B table 1, the entropy can be at most the digest size.
+	 * Considering this together with the last sentence in section 3.1.5.1.2
+	 * the security strength of a (approved) hash is equal to its output
+	 * size. On the other hand the entropy cannot be larger than the
+	 * security strength of the used DRBG.
+	 */
+	return min_t(u32, ESDM_FULL_SEED_ENTROPY_BITS, esdm_get_digestsize());
+}
+
+static inline u32 esdm_get_seed_entropy_osr(bool fully_seeded)
+{
+	u32 requested_bits = esdm_security_strength();
+
+	/* Apply oversampling during initialization according to SP800-90C */
+	if (esdm_sp80090c_compliant() && !fully_seeded)
+		requested_bits += CONFIG_CRYPTO_ESDM_SEED_BUFFER_INIT_ADD_BITS;
+	return requested_bits;
+}
+
+#endif /* _ESDM_ES_AUX_H */
diff --git a/crypto/esdm/esdm_es_mgr.c b/crypto/esdm/esdm_es_mgr.c
new file mode 100644
index 000000000000..8bdef5a934a8
--- /dev/null
+++ b/crypto/esdm/esdm_es_mgr.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM Entropy sources management
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/random.h>
+#include <linux/utsname.h>
+#include <linux/workqueue.h>
+
+#include "esdm_drng_mgr.h"
+#include "esdm_es_aux.h"
+#include "esdm_es_mgr.h"
+
+struct esdm_state {
+	bool perform_seedwork;		/* Can seed work be performed? */
+	bool esdm_operational;		/* Is DRNG operational? */
+	bool esdm_fully_seeded;		/* Is DRNG fully seeded? */
+	bool esdm_min_seeded;		/* Is DRNG minimally seeded? */
+	bool all_online_numa_node_seeded;/* All NUMA DRNGs seeded? */
+
+	/*
+	 * To ensure that external entropy providers cannot dominate the
+	 * internal noise sources but yet cannot be dominated by internal
+	 * noise sources, the following booleans are intended to allow
+	 * external to provide seed once when a DRNG reseed occurs. This
+	 * triggering of external noise source is performed even when the
+	 * entropy pool has sufficient entropy.
+	 */
+
+	atomic_t boot_entropy_thresh;	/* Reseed threshold */
+	atomic_t reseed_in_progress;	/* Flag for on executing reseed */
+	struct work_struct esdm_seed_work;	/* (re)seed work queue */
+};
+
+static struct esdm_state esdm_state = {
+	false, false, false, false, false,
+	.boot_entropy_thresh	= ATOMIC_INIT(ESDM_INIT_ENTROPY_BITS),
+	.reseed_in_progress	= ATOMIC_INIT(0),
+};
+
+/*
+ * If the entropy count falls under this number of bits, then we
+ * should wake up processes which are selecting or polling on write
+ * access to /dev/random.
+ */
+u32 esdm_write_wakeup_bits = (ESDM_WRITE_WAKEUP_ENTROPY << 3);
+
+/*
+ * The entries must be in the same order as defined by
+ * enum enum esdm_external_es
+ */
+struct esdm_es_cb *esdm_es[] = {
+	&esdm_es_aux
+};
+
+/********************************** Helper ***********************************/
+
+/*
+ * Reading of the ESDM pool is only allowed by one caller. The reading is
+ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken,
+ * the reseeding operation is in progress. The caller is not intended to wait
+ * but continue with its other operation.
+ */
+int esdm_pool_trylock(void)
+{
+	return atomic_cmpxchg(&esdm_state.reseed_in_progress, 0, 1);
+}
+
+void esdm_pool_unlock(void)
+{
+	atomic_set(&esdm_state.reseed_in_progress, 0);
+}
+
+/* Set new entropy threshold for reseeding during boot */
+void esdm_set_entropy_thresh(u32 new_entropy_bits)
+{
+	atomic_set(&esdm_state.boot_entropy_thresh, new_entropy_bits);
+}
+
+/*
+ * Reset ESDM state - the entropy counters are reset, but the data that may
+ * or may not have entropy remains in the pools as this data will not hurt.
+ */
+void esdm_reset_state(void)
+{
+	u32 i;
+
+	for_each_esdm_es(i) {
+		if (esdm_es[i]->reset)
+			esdm_es[i]->reset();
+	}
+	esdm_state.esdm_operational = false;
+	esdm_state.esdm_fully_seeded = false;
+	esdm_state.esdm_min_seeded = false;
+	esdm_state.all_online_numa_node_seeded = false;
+	pr_debug("reset ESDM\n");
+}
+
+/* Set flag that all DRNGs are fully seeded */
+void esdm_pool_all_numa_nodes_seeded(bool set)
+{
+	esdm_state.all_online_numa_node_seeded = set;
+}
+
+/* Return boolean whether ESDM reached minimally seed level */
+bool esdm_state_min_seeded(void)
+{
+	return esdm_state.esdm_min_seeded;
+}
+
+/* Return boolean whether ESDM reached fully seed level */
+bool esdm_state_fully_seeded(void)
+{
+	return esdm_state.esdm_fully_seeded;
+}
+
+/* Return boolean whether ESDM is considered fully operational */
+bool esdm_state_operational(void)
+{
+	return esdm_state.esdm_operational;
+}
+
+static void esdm_init_wakeup(void)
+{
+	wake_up_all(&esdm_init_wait);
+}
+
+static bool esdm_fully_seeded(bool fully_seeded, u32 collected_entropy)
+{
+	return (collected_entropy >= esdm_get_seed_entropy_osr(fully_seeded));
+}
+
+/* Policy to check whether entropy buffer contains full seeded entropy */
+bool esdm_fully_seeded_eb(bool fully_seeded, struct entropy_buf *eb)
+{
+	u32 i, collected_entropy = 0;
+
+	for_each_esdm_es(i)
+		collected_entropy += eb->e_bits[i];
+
+	return esdm_fully_seeded(fully_seeded, collected_entropy);
+}
+
+/* Mark one DRNG as not fully seeded */
+void esdm_unset_fully_seeded(struct esdm_drng *drng)
+{
+	drng->fully_seeded = false;
+	esdm_pool_all_numa_nodes_seeded(false);
+
+	/*
+	 * The init DRNG instance must always be fully seeded as this instance
+	 * is the fall-back if any of the per-NUMA node DRNG instances is
+	 * insufficiently seeded. Thus, we mark the entire ESDM as
+	 * non-operational if the initial DRNG becomes not fully seeded.
+	 */
+	if (drng == esdm_drng_init_instance() && esdm_state_operational()) {
+		pr_debug("ESDM set to non-operational\n");
+		esdm_state.esdm_operational = false;
+		esdm_state.esdm_fully_seeded = false;
+
+		/* If sufficient entropy is available, reseed now. */
+		esdm_es_add_entropy();
+	}
+}
+
+/* Policy to enable ESDM operational mode */
+static void esdm_set_operational(void)
+{
+	/*
+	 * ESDM is operational if the initial DRNG is fully seeded. This state
+	 * can only occur if either the external entropy sources provided
+	 * sufficient entropy, or the SP800-90B startup test completed for
+	 * the internal ES to supply also entropy data.
+	 */
+	if (esdm_state.esdm_fully_seeded) {
+		esdm_state.esdm_operational = true;
+		esdm_init_wakeup();
+		pr_info("ESDM fully operational\n");
+	}
+}
+
+static u32 esdm_avail_entropy_thresh(void)
+{
+	u32 ent_thresh = esdm_security_strength();
+
+	/*
+	 * Apply oversampling during initialization according to SP800-90C as
+	 * we request a larger buffer from the ES.
+	 */
+	if (esdm_sp80090c_compliant() &&
+	    !esdm_state.all_online_numa_node_seeded)
+		ent_thresh += CONFIG_CRYPTO_ESDM_SEED_BUFFER_INIT_ADD_BITS;
+
+	return ent_thresh;
+}
+
+/* Available entropy in the entire ESDM considering all entropy sources */
+u32 esdm_avail_entropy(void)
+{
+	u32 i, ent = 0, ent_thresh = esdm_avail_entropy_thresh();
+
+	BUILD_BUG_ON(ARRAY_SIZE(esdm_es) != esdm_ext_es_last);
+	for_each_esdm_es(i)
+		ent += esdm_es[i]->curr_entropy(ent_thresh);
+	return ent;
+}
+
+/*
+ * esdm_init_ops() - Set seed stages of ESDM
+ *
+ * Set the slow noise source reseed trigger threshold. The initial threshold
+ * is set to the minimum data size that can be read from the pool: a word. Upon
+ * reaching this value, the next seed threshold of 128 bits is set followed
+ * by 256 bits.
+ *
+ * @eb: buffer containing the size of entropy currently injected into DRNG - if
+ *	NULL, the function obtains the available entropy from the ES.
+ */
+void esdm_init_ops(struct entropy_buf *eb)
+{
+	struct esdm_state *state = &esdm_state;
+	u32 i, requested_bits, seed_bits = 0;
+
+	if (state->esdm_operational)
+		return;
+
+	requested_bits = esdm_get_seed_entropy_osr(
+					state->all_online_numa_node_seeded);
+
+	if (eb) {
+		for_each_esdm_es(i)
+			seed_bits += eb->e_bits[i];
+	} else {
+		u32 ent_thresh = esdm_avail_entropy_thresh();
+
+		for_each_esdm_es(i)
+			seed_bits += esdm_es[i]->curr_entropy(ent_thresh);
+	}
+
+	/* DRNG is seeded with full security strength */
+	if (state->esdm_fully_seeded) {
+		esdm_set_operational();
+		esdm_set_entropy_thresh(requested_bits);
+	} else if (esdm_fully_seeded(state->all_online_numa_node_seeded,
+				     seed_bits)) {
+		state->esdm_fully_seeded = true;
+		esdm_set_operational();
+		state->esdm_min_seeded = true;
+		pr_info("ESDM fully seeded with %u bits of entropy\n",
+			seed_bits);
+		esdm_set_entropy_thresh(requested_bits);
+	} else if (!state->esdm_min_seeded) {
+
+		/* DRNG is seeded with at least 128 bits of entropy */
+		if (seed_bits >= ESDM_MIN_SEED_ENTROPY_BITS) {
+			state->esdm_min_seeded = true;
+			pr_info("ESDM minimally seeded with %u bits of entropy\n",
+				seed_bits);
+			esdm_set_entropy_thresh(requested_bits);
+			esdm_init_wakeup();
+
+		/* DRNG is seeded with at least ESDM_INIT_ENTROPY_BITS bits */
+		} else if (seed_bits >= ESDM_INIT_ENTROPY_BITS) {
+			pr_info("ESDM initial entropy level %u bits of entropy\n",
+				seed_bits);
+			esdm_set_entropy_thresh(ESDM_MIN_SEED_ENTROPY_BITS);
+		}
+	}
+}
+
+int __init esdm_rand_initialize(void)
+{
+	struct seed {
+		ktime_t time;
+		unsigned long data[(ESDM_MAX_DIGESTSIZE /
+				    sizeof(unsigned long))];
+		struct new_utsname utsname;
+	} seed __aligned(ESDM_KCAPI_ALIGN);
+	unsigned int i;
+
+	BUILD_BUG_ON(ESDM_MAX_DIGESTSIZE % sizeof(unsigned long));
+
+	seed.time = ktime_get_real();
+
+	for (i = 0; i < ARRAY_SIZE(seed.data); i++) {
+		if (!arch_get_random_seed_long(&(seed.data[i])) &&
+		    !arch_get_random_long(&seed.data[i]))
+			seed.data[i] = random_get_entropy();
+	}
+	memcpy(&seed.utsname, utsname(), sizeof(*(utsname())));
+
+	esdm_pool_insert_aux((u8 *)&seed, sizeof(seed), 0);
+	memzero_explicit(&seed, sizeof(seed));
+
+	/* Initialize the seed work queue */
+	INIT_WORK(&esdm_state.esdm_seed_work, esdm_drng_seed_work);
+	esdm_state.perform_seedwork = true;
+
+	return 0;
+}
+
+early_initcall(esdm_rand_initialize);
+
+/* Interface requesting a reseed of the DRNG */
+void esdm_es_add_entropy(void)
+{
+	/*
+	 * Once all DRNGs are fully seeded, the system-triggered arrival of
+	 * entropy will not cause any reseeding any more.
+	 */
+	if (likely(esdm_state.all_online_numa_node_seeded))
+		return;
+
+	/* Only trigger the DRNG reseed if we have collected entropy. */
+	if (esdm_avail_entropy() <
+	    atomic_read_u32(&esdm_state.boot_entropy_thresh))
+		return;
+
+	/* Ensure that the seeding only occurs once at any given time. */
+	if (esdm_pool_trylock())
+		return;
+
+	/* Seed the DRNG with any available noise. */
+	if (esdm_state.perform_seedwork)
+		schedule_work(&esdm_state.esdm_seed_work);
+	else
+		esdm_drng_seed_work(NULL);
+}
+
+/* Fill the seed buffer with data from the noise sources */
+void esdm_fill_seed_buffer(struct entropy_buf *eb, u32 requested_bits)
+{
+	struct esdm_state *state = &esdm_state;
+	u32 i, req_ent = esdm_sp80090c_compliant() ?
+			  esdm_security_strength() : ESDM_MIN_SEED_ENTROPY_BITS;
+
+	/* Guarantee that requested bits is a multiple of bytes */
+	BUILD_BUG_ON(ESDM_DRNG_SECURITY_STRENGTH_BITS % 8);
+
+	/* always reseed the DRNG with the current time stamp */
+	eb->now = random_get_entropy();
+
+	/*
+	 * Require at least 128 bits of entropy for any reseed. If the ESDM is
+	 * operated SP800-90C compliant we want to comply with SP800-90A section
+	 * 9.2 mandating that DRNG is reseeded with the security strength.
+	 */
+	if (state->esdm_fully_seeded && (esdm_avail_entropy() < req_ent)) {
+		for_each_esdm_es(i)
+			eb->e_bits[i] = 0;
+
+		return;
+	}
+
+	/* Concatenate the output of the entropy sources. */
+	for_each_esdm_es(i) {
+		esdm_es[i]->get_ent(eb, requested_bits,
+				    state->esdm_fully_seeded);
+	}
+}
diff --git a/crypto/esdm/esdm_es_mgr.h b/crypto/esdm/esdm_es_mgr.h
new file mode 100644
index 000000000000..e1b73fe618d1
--- /dev/null
+++ b/crypto/esdm/esdm_es_mgr.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_ES_MGR_H
+#define _ESDM_ES_MGR_H
+
+#include "esdm_es_mgr_cb.h"
+
+/*************************** General ESDM parameter ***************************/
+
+#define ESDM_DRNG_BLOCKSIZE 64		/* Maximum of DRNG block sizes */
+
+/* Helper to concatenate a macro with an integer type */
+#define ESDM_PASTER(x, y) x ## y
+#define ESDM_UINT32_C(x) ESDM_PASTER(x, U)
+
+/************************* Entropy sources management *************************/
+
+extern struct esdm_es_cb *esdm_es[];
+
+#define for_each_esdm_es(ctr)		\
+	for ((ctr) = 0; (ctr) < esdm_ext_es_last; (ctr)++)
+
+bool esdm_state_min_seeded(void);
+int esdm_rand_initialize(void);
+bool esdm_state_operational(void);
+
+extern u32 esdm_write_wakeup_bits;
+void esdm_set_entropy_thresh(u32 new);
+u32 esdm_avail_entropy(void);
+void esdm_reset_state(void);
+
+bool esdm_state_fully_seeded(void);
+
+int esdm_pool_trylock(void);
+void esdm_pool_unlock(void);
+void esdm_pool_all_numa_nodes_seeded(bool set);
+
+bool esdm_fully_seeded_eb(bool fully_seeded, struct entropy_buf *eb);
+void esdm_unset_fully_seeded(struct esdm_drng *drng);
+void esdm_fill_seed_buffer(struct entropy_buf *eb, u32 requested_bits);
+void esdm_init_ops(struct entropy_buf *eb);
+
+#endif /* _ESDM_ES_MGR_H */
diff --git a/crypto/esdm/esdm_es_mgr_cb.h b/crypto/esdm/esdm_es_mgr_cb.h
new file mode 100644
index 000000000000..41b39983196f
--- /dev/null
+++ b/crypto/esdm/esdm_es_mgr_cb.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ *
+ * Definition of an entropy source.
+ */
+
+#ifndef _ESDM_ES_MGR_CB_H
+#define _ESDM_ES_MGR_CB_H
+
+#include <crypto/esdm.h>
+
+#include "esdm_definitions.h"
+#include "esdm_drng_mgr.h"
+
+enum esdm_external_es {
+	esdm_ext_es_aux,			/* MUST BE LAST ES! */
+	esdm_ext_es_last			/* MUST be the last entry */
+};
+
+struct entropy_buf {
+	u8 e[esdm_ext_es_last][ESDM_DRNG_INIT_SEED_SIZE_BYTES];
+	u32 now, e_bits[esdm_ext_es_last];
+};
+
+/*
+ * struct esdm_es_cb - callback defining an entropy source
+ * @name: Name of the entropy source.
+ * @get_ent: Fetch entropy into the entropy_buf. The ES shall only deliver
+ *	     data if its internal initialization is complete, including any
+ *	     SP800-90B startup testing or similar.
+ * @curr_entropy: Return amount of currently available entropy.
+ * @max_entropy: Maximum amount of entropy the entropy source is able to
+ *		 maintain.
+ * @state: Buffer with human-readable ES state.
+ * @reset: Reset entropy source (drop all entropy and reinitialize).
+ *	   This callback may be NULL.
+ * @switch_hash: callback to switch from an old hash callback definition to
+ *		 a new one. This callback may be NULL.
+ */
+struct esdm_es_cb {
+	const char *name;
+	void (*get_ent)(struct entropy_buf *eb, u32 requested_bits,
+			bool fully_seeded);
+	u32 (*curr_entropy)(u32 requested_bits);
+	u32 (*max_entropy)(void);
+	void (*state)(unsigned char *buf, size_t buflen);
+	void (*reset)(void);
+	int (*switch_hash)(struct esdm_drng *drng, int node,
+			   const struct esdm_hash_cb *new_cb, void *new_hash,
+			   const struct esdm_hash_cb *old_cb);
+};
+
+/* Allow entropy sources to tell the ES manager that new entropy is there */
+void esdm_es_add_entropy(void);
+
+/* Cap to maximum entropy that can ever be generated with given hash */
+#define esdm_cap_requested(__digestsize_bits, __requested_bits)		\
+	do {								\
+		if (__digestsize_bits < __requested_bits) {		\
+			pr_debug("Cannot satisfy requested entropy %u due to insufficient hash size %u\n",\
+				 __requested_bits, __digestsize_bits);	\
+			__requested_bits = __digestsize_bits;		\
+		}							\
+	} while (0)
+
+#endif /* _ESDM_ES_MGR_CB_H */
diff --git a/crypto/esdm/esdm_sha.h b/crypto/esdm/esdm_sha.h
new file mode 100644
index 000000000000..c71662881b8d
--- /dev/null
+++ b/crypto/esdm/esdm_sha.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * ESDM SHA definition usable in atomic contexts right from the start of the
+ * kernel.
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_SHA_H
+#define _ESDM_SHA_H
+
+extern const struct esdm_hash_cb esdm_sha_hash_cb;
+
+#endif /* _ESDM_SHA_H */
diff --git a/crypto/esdm/esdm_sha256.c b/crypto/esdm/esdm_sha256.c
new file mode 100644
index 000000000000..030c503d09c5
--- /dev/null
+++ b/crypto/esdm/esdm_sha256.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * Backend for the ESDM providing the SHA-256 implementation that can be used
+ * without the kernel crypto API available including during early boot and in
+ * atomic contexts.
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <crypto/esdm.h>
+#include <crypto/sha2.h>
+
+#include "esdm_sha.h"
+
+static u32 esdm_sha256_hash_digestsize(void *hash)
+{
+	return SHA256_DIGEST_SIZE;
+}
+
+static int esdm_sha256_hash_init(struct shash_desc *shash, void *hash)
+{
+	/*
+	 * We do not need a TFM - we only need sufficient space for
+	 * struct sha256_state on the stack.
+	 */
+	sha256_init(shash_desc_ctx(shash));
+	return 0;
+}
+
+static int esdm_sha256_hash_update(struct shash_desc *shash,
+				   const u8 *inbuf, u32 inbuflen)
+{
+	sha256_update(shash_desc_ctx(shash), inbuf, inbuflen);
+	return 0;
+}
+
+static int esdm_sha256_hash_final(struct shash_desc *shash, u8 *digest)
+{
+	sha256_final(shash_desc_ctx(shash), digest);
+	return 0;
+}
+
+static const char *esdm_sha256_hash_name(void)
+{
+	return "SHA-256";
+}
+
+static void esdm_sha256_hash_desc_zero(struct shash_desc *shash)
+{
+	memzero_explicit(shash_desc_ctx(shash), sizeof(struct sha256_state));
+}
+
+static void *esdm_sha256_hash_alloc(void)
+{
+	pr_info("Hash %s allocated\n", esdm_sha256_hash_name());
+	return NULL;
+}
+
+static void esdm_sha256_hash_dealloc(void *hash) { }
+
+const struct esdm_hash_cb esdm_sha_hash_cb = {
+	.hash_name		= esdm_sha256_hash_name,
+	.hash_alloc		= esdm_sha256_hash_alloc,
+	.hash_dealloc		= esdm_sha256_hash_dealloc,
+	.hash_digestsize	= esdm_sha256_hash_digestsize,
+	.hash_init		= esdm_sha256_hash_init,
+	.hash_update		= esdm_sha256_hash_update,
+	.hash_final		= esdm_sha256_hash_final,
+	.hash_desc_zero		= esdm_sha256_hash_desc_zero,
+};
diff --git a/include/crypto/esdm.h b/include/crypto/esdm.h
new file mode 100644
index 000000000000..95a12ea0356e
--- /dev/null
+++ b/include/crypto/esdm.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_H
+#define _ESDM_H
+
+#include <crypto/hash.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+
+/*
+ * struct esdm_drng_cb - cryptographic callback functions defining a DRNG
+ * @drng_name		Name of DRNG
+ * @drng_alloc:		Allocate DRNG -- the provided integer should be used for
+ *			sanity checks.
+ *			return: allocated data structure or PTR_ERR on error
+ * @drng_dealloc:	Deallocate DRNG
+ * @drng_seed:		Seed the DRNG with data of arbitrary length drng: is
+ *			pointer to data structure allocated with drng_alloc
+ *			return: >= 0 on success, < 0 on error
+ * @drng_generate:	Generate random numbers from the DRNG with arbitrary
+ *			length
+ */
+struct esdm_drng_cb {
+	const char *(*drng_name)(void);
+	void *(*drng_alloc)(u32 sec_strength);
+	void (*drng_dealloc)(void *drng);
+	int (*drng_seed)(void *drng, const u8 *inbuf, u32 inbuflen);
+	int (*drng_generate)(void *drng, u8 *outbuf, u32 outbuflen);
+};
+
+/*
+ * struct esdm_hash_cb - cryptographic callback functions defining a hash
+ * @hash_name		Name of Hash used for reading entropy pool arbitrary
+ *			length
+ * @hash_alloc:		Allocate the hash for reading the entropy pool
+ *			return: allocated data structure (NULL is success too)
+ *				or ERR_PTR on error
+ * @hash_dealloc:	Deallocate Hash
+ * @hash_digestsize:	Return the digestsize for the used hash to read out
+ *			entropy pool
+ *			hash: is pointer to data structure allocated with
+ *			      hash_alloc
+ *			return: size of digest of hash in bytes
+ * @hash_init:		Initialize hash
+ *			hash: is pointer to data structure allocated with
+ *			      hash_alloc
+ *			return: 0 on success, < 0 on error
+ * @hash_update:	Update hash operation
+ *			hash: is pointer to data structure allocated with
+ *			      hash_alloc
+ *			return: 0 on success, < 0 on error
+ * @hash_final		Final hash operation
+ *			hash: is pointer to data structure allocated with
+ *			      hash_alloc
+ *			return: 0 on success, < 0 on error
+ * @hash_desc_zero	Zeroization of hash state buffer
+ *
+ * Assumptions:
+ *
+ * 1. Hash operation will not sleep
+ * 2. The hash' volatile state information is provided with *shash by caller.
+ */
+struct esdm_hash_cb {
+	const char *(*hash_name)(void);
+	void *(*hash_alloc)(void);
+	void (*hash_dealloc)(void *hash);
+	u32 (*hash_digestsize)(void *hash);
+	int (*hash_init)(struct shash_desc *shash, void *hash);
+	int (*hash_update)(struct shash_desc *shash, const u8 *inbuf,
+			   u32 inbuflen);
+	int (*hash_final)(struct shash_desc *shash, u8 *digest);
+	void (*hash_desc_zero)(struct shash_desc *shash);
+};
+
+/*
+ * esdm_get_random_bytes_full() - Provider of cryptographic strong
+ * random numbers for kernel-internal usage from a fully initialized ESDM.
+ *
+ * This function will always return random numbers from a fully seeded and
+ * fully initialized ESDM.
+ *
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. It provides access to the full functionality of ESDM
+ * including the switchable DRNG support, that may support other DRNGs such
+ * as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+#ifdef CONFIG_CRYPTO_ESDM
+void esdm_get_random_bytes_full(void *buf, int nbytes);
+#endif
+
+/*
+ * esdm_get_random_bytes_min() - Provider of cryptographic strong
+ * random numbers for kernel-internal usage from at least a minimally seeded
+ * ESDM, which is not necessarily fully initialized yet (e.g. SP800-90C
+ * oversampling applied in FIPS mode is not applied yet).
+ *
+ * This function is appropriate only for non-atomic use cases as this
+ * function may sleep. It provides access to the full functionality of ESDM
+ * including the switchable DRNG support, that may support other DRNGs such
+ * as the SP800-90A DRBG.
+ *
+ * @buf: buffer to store the random bytes
+ * @nbytes: size of the buffer
+ */
+#ifdef CONFIG_CRYPTO_ESDM
+void esdm_get_random_bytes_min(void *buf, int nbytes);
+#endif
+
+#endif /* _ESDM_H */
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/7] crypto: move Jitter RNG header include dir
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
                   ` (2 preceding siblings ...)
  2022-01-26  7:04 ` [PATCH 3/7] crypto: Entropy Source and DRNG Manager Stephan Müller
@ 2022-01-26  7:04 ` Stephan Müller
  2022-01-26  7:04 ` [PATCH 5/7] crypto: ESDM - add Jitter RNG entropy source Stephan Müller
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:04 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

To support the ESDM operation which uses the Jitter RNG separately
from the kernel crypto API, the header file must be accessible to
the ESDM code.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/jitterentropy-kcapi.c                        | 3 +--
 crypto/jitterentropy.c                              | 2 +-
 {crypto => include/crypto/internal}/jitterentropy.h | 0
 3 files changed, 2 insertions(+), 3 deletions(-)
 rename {crypto => include/crypto/internal}/jitterentropy.h (100%)

diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index 2d115bec15ae..40bc51f32432 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -41,10 +41,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <crypto/internal/jitterentropy.h>
 #include <crypto/internal/rng.h>
 
-#include "jitterentropy.h"
-
 /***************************************************************************
  * Helper function
  ***************************************************************************/
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 93bff3213823..81b80a4d3d3a 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -133,7 +133,7 @@ struct rand_data {
 #define JENT_ENTROPY_SAFETY_FACTOR	64
 
 #include <linux/fips.h>
-#include "jitterentropy.h"
+#include <crypto/internal/jitterentropy.h>
 
 /***************************************************************************
  * Adaptive Proportion Test
diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h
similarity index 100%
rename from crypto/jitterentropy.h
rename to include/crypto/internal/jitterentropy.h
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/7] crypto: ESDM - add Jitter RNG entropy source
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
                   ` (3 preceding siblings ...)
  2022-01-26  7:04 ` [PATCH 4/7] crypto: move Jitter RNG header include dir Stephan Müller
@ 2022-01-26  7:04 ` Stephan Müller
  2022-01-26  7:05 ` [PATCH 6/7] crypto: ESDM - add Kernel " Stephan Müller
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:04 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The Jitter RNG entropy source provided as part of the kernel crypto API
is used as a separate entropy source for the ESDM. It can be enabled at
compile time together with its implied entropy rate.

The entropy rate states how many bits of entropy are present in 256 bits
of data from that entropy source. If a different amount of data is
pulled from the entropy source, the entropy ratio is scaled accordingly.

In FIPS mode, the amount of entropy is set to 256 bits considering that
this entropy source is provided with an entropy analysis demonstrating
its compliance with SP800-90B and thus allowing to claim full strength.

When the entropy ratio is set to zero, the Jitter RNG provides data but
without claiming any entropy for it.

In addition, the patch offers the compile time option to allow setting
the entropy rate with the kernel command line using the parameter of
esdm_es_jent.jent_entropy.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/esdm/Kconfig          |  45 ++++++++++++
 crypto/esdm/Makefile         |   2 +
 crypto/esdm/esdm_es_jent.c   | 128 +++++++++++++++++++++++++++++++++++
 crypto/esdm/esdm_es_jent.h   |  17 +++++
 crypto/esdm/esdm_es_mgr.c    |   4 ++
 crypto/esdm/esdm_es_mgr_cb.h |   3 +
 6 files changed, 199 insertions(+)
 create mode 100644 crypto/esdm/esdm_es_jent.c
 create mode 100644 crypto/esdm/esdm_es_jent.h

diff --git a/crypto/esdm/Kconfig b/crypto/esdm/Kconfig
index 1351d4d146dc..eeef71546bc3 100644
--- a/crypto/esdm/Kconfig
+++ b/crypto/esdm/Kconfig
@@ -68,6 +68,51 @@ config CRYPTO_ESDM_SEED_BUFFER_INIT_ADD_BITS
 
 endmenu # "Specific DRNG seeding strategies"
 
+menu "Entropy Source Configuration"
+
+config CRYPTO_ESDM_RUNTIME_ES_CONFIG
+	bool "Enable runtime configuration of entropy sources"
+	help
+	  When enabling this option, the ESDM provides the mechanism
+	  allowing to alter the entropy rate of each entropy source
+	  during boot time and runtime.
+
+	  Each entropy source allows its entropy rate changed with
+	  a kernel command line option. When not providing any
+	  option, the default specified during kernel compilation
+	  is applied.
+
+comment "Jitter RNG Entropy Source"
+
+config CRYPTO_ESDM_JENT
+	bool "Enable Jitter RNG as ESDM Seed Source"
+	depends on CRYPTO
+	select CRYPTO_JITTERENTROPY
+	help
+	  The Linux RNG may use the Jitter RNG as entropy source. Enabling
+	  this option enables the use of the Jitter RNG. Its default
+	  entropy level is 16 bits of entropy per 256 data bits delivered
+	  by the Jitter RNG. This entropy level can be changed at boot
+	  time or at runtime with the esdm_base.jitterrng configuration
+	  variable.
+
+config CRYPTO_ESDM_JENT_ENTROPY_RATE
+	int "Jitter RNG Entropy Source Entropy Rate"
+	depends on CRYPTO_ESDM_JENT
+	range 0 256
+	default 16
+	help
+	  The option defines the amount of entropy the ESDM applies to 256
+	  bits of data obtained from the Jitter RNG entropy source. The
+	  ESDM enforces the limit that this value must be in the range
+	  between 0 and 256.
+
+	  When configuring this value to 0, the Jitter RNG entropy source
+	  will provide 256 bits of data without being credited to contain
+	  entropy.
+
+endmenu # "Entropy Source Configuration"
+
 config CRYPTO_ESDM_DRNG_KCAPI
 	bool
 	depends on CRYPTO
diff --git a/crypto/esdm/Makefile b/crypto/esdm/Makefile
index 24dc7af234b6..99a86ce3e3af 100644
--- a/crypto/esdm/Makefile
+++ b/crypto/esdm/Makefile
@@ -8,3 +8,5 @@ obj-y					+= esdm_es_mgr.o esdm_drng_mgr.o \
 obj-$(CONFIG_CRYPTO_ESDM_SHA256)	+= esdm_sha256.o
 
 obj-$(CONFIG_CRYPTO_ESDM_DRNG_KCAPI)	+= esdm_drng_kcapi.o
+
+obj-$(CONFIG_CRYPTO_ESDM_JENT)		+= esdm_es_jent.o
diff --git a/crypto/esdm/esdm_es_jent.c b/crypto/esdm/esdm_es_jent.c
new file mode 100644
index 000000000000..8cbd649e8f42
--- /dev/null
+++ b/crypto/esdm/esdm_es_jent.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM Fast Entropy Source: Jitter RNG
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <crypto/internal/jitterentropy.h>
+
+#include "esdm_definitions.h"
+#include "esdm_es_aux.h"
+#include "esdm_es_jent.h"
+
+/*
+ * Estimated entropy of data is a 16th of ESDM_DRNG_SECURITY_STRENGTH_BITS.
+ * Albeit a full entropy assessment is provided for the noise source indicating
+ * that it provides high entropy rates and considering that it deactivates
+ * when it detects insufficient hardware, the chosen under estimation of
+ * entropy is considered to be acceptable to all reviewers.
+ */
+static u32 jent_entropy = CONFIG_CRYPTO_ESDM_JENT_ENTROPY_RATE;
+#ifdef CONFIG_CRYPTO_ESDM_RUNTIME_ES_CONFIG
+module_param(jent_entropy, uint, 0644);
+MODULE_PARM_DESC(jent_entropy, "Entropy in bits of 256 data bits from Jitter RNG noise source");
+#endif
+
+static bool esdm_jent_initialized = false;
+static struct rand_data *esdm_jent_state;
+
+static int __init esdm_jent_initialize(void)
+{
+	/* Initialize the Jitter RNG after the clocksources are initialized. */
+	if (jent_entropy_init() ||
+	    (esdm_jent_state = jent_entropy_collector_alloc(1, 0)) == NULL) {
+		jent_entropy = 0;
+		pr_info("Jitter RNG unusable on current system\n");
+		return 0;
+	}
+	esdm_jent_initialized = true;
+	pr_debug("Jitter RNG working on current system\n");
+
+	/* In FIPS mode, the Jitter RNG is defined to have full of entropy */
+	if (fips_enabled)
+		jent_entropy = ESDM_DRNG_SECURITY_STRENGTH_BITS;
+
+	esdm_drng_force_reseed();
+	if (jent_entropy)
+		esdm_es_add_entropy();
+
+	return 0;
+}
+device_initcall(esdm_jent_initialize);
+
+static u32 esdm_jent_entropylevel(u32 requested_bits)
+{
+	return esdm_fast_noise_entropylevel(esdm_jent_initialized ?
+					    jent_entropy : 0, requested_bits);
+}
+
+static u32 esdm_jent_poolsize(void)
+{
+	return esdm_jent_entropylevel(esdm_security_strength());
+}
+
+
+/*
+ * esdm_get_jent() - Get Jitter RNG entropy
+ *
+ * @eb: entropy buffer to store entropy
+ * @requested_bits: requested entropy in bits
+ */
+static void esdm_jent_get(struct entropy_buf *eb, u32 requested_bits,
+			  bool __unused)
+{
+	int ret;
+	u32 ent_bits = esdm_jent_entropylevel(requested_bits);
+	unsigned long flags;
+	static DEFINE_SPINLOCK(esdm_jent_lock);
+
+	spin_lock_irqsave(&esdm_jent_lock, flags);
+
+	if (!esdm_jent_initialized) {
+		spin_unlock_irqrestore(&esdm_jent_lock, flags);
+		goto err;
+	}
+
+	ret = jent_read_entropy(esdm_jent_state, eb->e[esdm_ext_es_jitter],
+				requested_bits >> 3);
+	spin_unlock_irqrestore(&esdm_jent_lock, flags);
+
+	if (ret) {
+		pr_debug("Jitter RNG failed with %d\n", ret);
+		goto err;
+	}
+
+	pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n",
+		 ent_bits);
+
+	eb->e_bits[esdm_ext_es_jitter] = ent_bits;
+	return;
+
+err:
+	eb->e_bits[esdm_ext_es_jitter] = 0;
+}
+
+static void esdm_jent_es_state(unsigned char *buf, size_t buflen)
+{
+	snprintf(buf, buflen,
+		 " Available entropy: %u\n"
+		 " Enabled: %s\n",
+		 esdm_jent_poolsize(),
+		 esdm_jent_initialized ? "true" : "false");
+}
+
+struct esdm_es_cb esdm_es_jent = {
+	.name			= "JitterRNG",
+	.get_ent		= esdm_jent_get,
+	.curr_entropy		= esdm_jent_entropylevel,
+	.max_entropy		= esdm_jent_poolsize,
+	.state			= esdm_jent_es_state,
+	.reset			= NULL,
+	.switch_hash		= NULL,
+};
diff --git a/crypto/esdm/esdm_es_jent.h b/crypto/esdm/esdm_es_jent.h
new file mode 100644
index 000000000000..d6a48f267018
--- /dev/null
+++ b/crypto/esdm/esdm_es_jent.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_ES_JENT_H
+#define _ESDM_ES_JENT_H
+
+#include "esdm_es_mgr_cb.h"
+
+#ifdef CONFIG_CRYPTO_ESDM_JENT
+
+extern struct esdm_es_cb esdm_es_jent;
+
+#endif /* CONFIG_CRYPTO_ESDM_JENT */
+
+#endif /* _ESDM_ES_JENT_H */
diff --git a/crypto/esdm/esdm_es_mgr.c b/crypto/esdm/esdm_es_mgr.c
index 8bdef5a934a8..b7b1a4151137 100644
--- a/crypto/esdm/esdm_es_mgr.c
+++ b/crypto/esdm/esdm_es_mgr.c
@@ -13,6 +13,7 @@
 
 #include "esdm_drng_mgr.h"
 #include "esdm_es_aux.h"
+#include "esdm_es_jent.h"
 #include "esdm_es_mgr.h"
 
 struct esdm_state {
@@ -54,6 +55,9 @@ u32 esdm_write_wakeup_bits = (ESDM_WRITE_WAKEUP_ENTROPY << 3);
  * enum enum esdm_external_es
  */
 struct esdm_es_cb *esdm_es[] = {
+#ifdef CONFIG_CRYPTO_ESDM_JENT
+	&esdm_es_jent,
+#endif
 	&esdm_es_aux
 };
 
diff --git a/crypto/esdm/esdm_es_mgr_cb.h b/crypto/esdm/esdm_es_mgr_cb.h
index 41b39983196f..18f0e4317691 100644
--- a/crypto/esdm/esdm_es_mgr_cb.h
+++ b/crypto/esdm/esdm_es_mgr_cb.h
@@ -14,6 +14,9 @@
 #include "esdm_drng_mgr.h"
 
 enum esdm_external_es {
+#ifdef CONFIG_CRYPTO_ESDM_JENT
+	esdm_ext_es_jitter,			/* Jitter RNG */
+#endif
 	esdm_ext_es_aux,			/* MUST BE LAST ES! */
 	esdm_ext_es_last			/* MUST be the last entry */
 };
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/7] crypto: ESDM - add Kernel RNG entropy source
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
                   ` (4 preceding siblings ...)
  2022-01-26  7:04 ` [PATCH 5/7] crypto: ESDM - add Jitter RNG entropy source Stephan Müller
@ 2022-01-26  7:05 ` Stephan Müller
  2022-01-26  7:05 ` [PATCH 7/7] crypto: ESDM - add kernel crypto API RNG interface Stephan Müller
  2022-01-26 22:49 ` [PATCH 0/7] Common entropy source and DRNG management Eric Biggers
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:05 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The Kernel RNG entropy source is used as a separate entropy source for
the ESDM. It can be enabled at compile time together with its implied
entropy rate. If the FIPS mode is enabled, the entropy rate is
automatically set to 0 since the entropy source is not SP800-90B
compliant and thus must be considered to deliver no entropy.

As long as the Kernel RNG is not fully initialized, the entropy rate is
also forced to 0.

The entropy rate states how many bits of entropy are present in 256 bits
of data from that entropy source. If a different amount of data is
pulled from the entropy source, the entropy ratio is scaled accordingly.

When the entropy ratio is set to zero, the Kernel RNG provides data but
without claiming any entropy for it.

When the compile time switch for enabling runtime setting of the entropy
rate is enabled (CONFIG_CRYPTO_ESDM_RUNTIME_ES_CONFIG), the entropy rate
can be configured at the kernel command line with the option
esdm_es_random.krng_entropy. If this option is not set, the default
value set during compile time is used.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/esdm/Kconfig          |  28 ++++++++
 crypto/esdm/Makefile         |   1 +
 crypto/esdm/esdm_es_krng.c   | 120 +++++++++++++++++++++++++++++++++++
 crypto/esdm/esdm_es_krng.h   |  17 +++++
 crypto/esdm/esdm_es_mgr.c    |   4 ++
 crypto/esdm/esdm_es_mgr_cb.h |   3 +
 6 files changed, 173 insertions(+)
 create mode 100644 crypto/esdm/esdm_es_krng.c
 create mode 100644 crypto/esdm/esdm_es_krng.h

diff --git a/crypto/esdm/Kconfig b/crypto/esdm/Kconfig
index eeef71546bc3..43e11484e95c 100644
--- a/crypto/esdm/Kconfig
+++ b/crypto/esdm/Kconfig
@@ -111,6 +111,34 @@ config CRYPTO_ESDM_JENT_ENTROPY_RATE
 	  will provide 256 bits of data without being credited to contain
 	  entropy.
 
+comment "Kernel RNG Entropy Source"
+
+config CRYPTO_ESDM_KERNEL_RNG
+	bool "Enable Kernel RNG as ESDM Seed Source"
+	help
+	  The Linux RNG may use the kernel RNG (random.c) as entropy
+	  source.
+
+config CRYPTO_ESDM_KERNEL_RNG_ENTROPY_RATE
+	int "Kernel RNG Entropy Source Entropy Rate"
+	depends on CRYPTO_ESDM_KERNEL_RNG
+	range 0 256
+	default 256
+	help
+	  The option defines the amount of entropy the ESDM applies to 256
+	  bits of data obtained from the kernel RNG entropy source. The
+	  ESDM enforces the limit that this value must be in the range
+	  between 0 and 256.
+
+	  When configuring this value to 0, the kernel RNG entropy source
+	  will provide 256 bits of data without being credited to contain
+	  entropy.
+
+	  Note: This value is set to 0 automatically when booting the
+	  kernel in FIPS mode (with fips=1 kernel command line option).
+	  This is due to the fact that random.c is not SP800-90B
+	  compliant.
+
 endmenu # "Entropy Source Configuration"
 
 config CRYPTO_ESDM_DRNG_KCAPI
diff --git a/crypto/esdm/Makefile b/crypto/esdm/Makefile
index 99a86ce3e3af..404436de0aa2 100644
--- a/crypto/esdm/Makefile
+++ b/crypto/esdm/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_CRYPTO_ESDM_SHA256)	+= esdm_sha256.o
 
 obj-$(CONFIG_CRYPTO_ESDM_DRNG_KCAPI)	+= esdm_drng_kcapi.o
 
+obj-$(CONFIG_CRYPTO_ESDM_KERNEL_RNG)	+= esdm_es_krng.o
 obj-$(CONFIG_CRYPTO_ESDM_JENT)		+= esdm_es_jent.o
diff --git a/crypto/esdm/esdm_es_krng.c b/crypto/esdm/esdm_es_krng.c
new file mode 100644
index 000000000000..d536a9139276
--- /dev/null
+++ b/crypto/esdm/esdm_es_krng.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM Fast Entropy Source: Linux kernel RNG (random.c)
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fips.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/types.h>
+
+#include "esdm_es_aux.h"
+#include "esdm_es_krng.h"
+
+static u32 krng_entropy = CONFIG_CRYPTO_ESDM_KERNEL_RNG_ENTROPY_RATE;
+#ifdef CONFIG_CRYPTO_ESDM_RUNTIME_ES_CONFIG
+module_param(krng_entropy, uint, 0644);
+MODULE_PARM_DESC(krng_entropy, "Entropy in bits of 256 data bits from the kernel RNG noise source");
+#endif
+
+static atomic_t esdm_krng_initial_rate = ATOMIC_INIT(0);
+
+static struct random_ready_callback esdm_krng_ready = {
+	.owner = THIS_MODULE,
+	.func = NULL,
+};
+
+static u32 esdm_krng_fips_entropylevel(u32 entropylevel)
+{
+	return fips_enabled ? 0 : entropylevel;
+}
+
+static void esdm_krng_adjust_entropy(struct random_ready_callback *rdy)
+{
+	u32 entropylevel;
+
+	krng_entropy = atomic_read_u32(&esdm_krng_initial_rate);
+
+	entropylevel = esdm_krng_fips_entropylevel(krng_entropy);
+	pr_debug("Kernel RNG is fully seeded, setting entropy rate to %u bits of entropy\n",
+		 entropylevel);
+	esdm_drng_force_reseed();
+	if (entropylevel)
+		esdm_es_add_entropy();
+}
+
+static u32 esdm_krng_entropylevel(u32 requested_bits)
+{
+	if (esdm_krng_ready.func == NULL) {
+		int err;
+
+		esdm_krng_ready.func = esdm_krng_adjust_entropy;
+
+		err = add_random_ready_callback(&esdm_krng_ready);
+		switch (err) {
+		case 0:
+			atomic_set(&esdm_krng_initial_rate, krng_entropy);
+			krng_entropy = 0;
+			pr_debug("Kernel RNG is not yet seeded, setting entropy rate to 0 bits of entropy\n");
+			break;
+
+		case -EALREADY:
+			pr_debug("Kernel RNG is fully seeded, setting entropy rate to %u bits of entropy\n",
+				 esdm_krng_fips_entropylevel(krng_entropy));
+			break;
+		default:
+			esdm_krng_ready.func = NULL;
+			return 0;
+		}
+	}
+
+	return esdm_fast_noise_entropylevel(
+		esdm_krng_fips_entropylevel(krng_entropy), requested_bits);
+}
+
+static u32 esdm_krng_poolsize(void)
+{
+	return esdm_krng_entropylevel(esdm_security_strength());
+}
+
+/*
+ * esdm_krng_get() - Get kernel RNG entropy
+ *
+ * @eb: entropy buffer to store entropy
+ * @requested_bits: requested entropy in bits
+ */
+static void esdm_krng_get(struct entropy_buf *eb, u32 requested_bits,
+			  bool __unused)
+{
+	u32 ent_bits = esdm_krng_entropylevel(requested_bits);
+
+	get_random_bytes(eb->e[esdm_ext_es_krng], requested_bits >> 3);
+
+	pr_debug("obtained %u bits of entropy from kernel RNG noise source\n",
+		 ent_bits);
+
+	eb->e_bits[esdm_ext_es_krng] = ent_bits;
+}
+
+static void esdm_krng_es_state(unsigned char *buf, size_t buflen)
+{
+	snprintf(buf, buflen,
+		 " Available entropy: %u\n"
+		 " Entropy Rate per 256 data bits: %u\n",
+		 esdm_krng_poolsize(),
+		 esdm_krng_entropylevel(256));
+}
+
+struct esdm_es_cb esdm_es_krng = {
+	.name			= "KernelRNG",
+	.get_ent		= esdm_krng_get,
+	.curr_entropy		= esdm_krng_entropylevel,
+	.max_entropy		= esdm_krng_poolsize,
+	.state			= esdm_krng_es_state,
+	.reset			= NULL,
+	.switch_hash		= NULL,
+};
diff --git a/crypto/esdm/esdm_es_krng.h b/crypto/esdm/esdm_es_krng.h
new file mode 100644
index 000000000000..b164594bfe79
--- /dev/null
+++ b/crypto/esdm/esdm_es_krng.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#ifndef _ESDM_ES_RANDOM_H
+#define _ESDM_ES_RANDOM_H
+
+#include "esdm_es_mgr_cb.h"
+
+#ifdef CONFIG_CRYPTO_ESDM_KERNEL_RNG
+
+extern struct esdm_es_cb esdm_es_krng;
+
+#endif /* CONFIG_CRYPTO_ESDM_KERNEL_RNG */
+
+#endif /* _ESDM_ES_RANDOM_H */
diff --git a/crypto/esdm/esdm_es_mgr.c b/crypto/esdm/esdm_es_mgr.c
index b7b1a4151137..0a65aafac8d2 100644
--- a/crypto/esdm/esdm_es_mgr.c
+++ b/crypto/esdm/esdm_es_mgr.c
@@ -14,6 +14,7 @@
 #include "esdm_drng_mgr.h"
 #include "esdm_es_aux.h"
 #include "esdm_es_jent.h"
+#include "esdm_es_krng.h"
 #include "esdm_es_mgr.h"
 
 struct esdm_state {
@@ -57,6 +58,9 @@ u32 esdm_write_wakeup_bits = (ESDM_WRITE_WAKEUP_ENTROPY << 3);
 struct esdm_es_cb *esdm_es[] = {
 #ifdef CONFIG_CRYPTO_ESDM_JENT
 	&esdm_es_jent,
+#endif
+#ifdef CONFIG_CRYPTO_ESDM_KERNEL_RNG
+	&esdm_es_krng,
 #endif
 	&esdm_es_aux
 };
diff --git a/crypto/esdm/esdm_es_mgr_cb.h b/crypto/esdm/esdm_es_mgr_cb.h
index 18f0e4317691..a94ad28f7d0f 100644
--- a/crypto/esdm/esdm_es_mgr_cb.h
+++ b/crypto/esdm/esdm_es_mgr_cb.h
@@ -16,6 +16,9 @@
 enum esdm_external_es {
 #ifdef CONFIG_CRYPTO_ESDM_JENT
 	esdm_ext_es_jitter,			/* Jitter RNG */
+#endif
+#ifdef CONFIG_CRYPTO_ESDM_KERNEL_RNG
+	esdm_ext_es_krng,			/* random.c */
 #endif
 	esdm_ext_es_aux,			/* MUST BE LAST ES! */
 	esdm_ext_es_last			/* MUST be the last entry */
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/7] crypto: ESDM - add kernel crypto API RNG interface
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
                   ` (5 preceding siblings ...)
  2022-01-26  7:05 ` [PATCH 6/7] crypto: ESDM - add Kernel " Stephan Müller
@ 2022-01-26  7:05 ` Stephan Müller
  2022-01-26 22:49 ` [PATCH 0/7] Common entropy source and DRNG management Eric Biggers
  7 siblings, 0 replies; 15+ messages in thread
From: Stephan Müller @ 2022-01-26  7:05 UTC (permalink / raw)
  To: herbert; +Cc: linux-crypto, simo, Nicolai Stange

The ESDM export interfaces that allow obtaining random numbers from a
fully seeded DRNG as specified in crypto/esdm.h. By using the interface
function esdm_get_random_bytes_full, the ESDM is registered as a random
number generator with the kernel crypto API's RNG framework. This
registered RNG provides random numbers from an always appropriately
seeded and initialized DRNG.

When a caller performs a crypto_rng_reset() call on the ESDM, the ESDM
injects the provided data into the auxiliary pool and flags a reseed.
This reseed is performed by the immediate subsequent DRNG generation
operation.

The RNG registered by the ESDM with the kernel crypto API is accessible
via the name "esdm". In addition, the ESDM is registered as "stdrng"
with the highest priority which implies that the kernel crypto API call
of crypto_get_default_rng accesses the ESDM.

The ESDM is marked as fips_allowed = 1 in the testmgr because it
complies with the FIPS 140 rules as follows:

- SP800-90A: The ESDM uses the kernel crypto API's DRBG and thus
  provides access to a fully seeded and SP800-90A DRBG.

- SP800-90B: The ESDM manages entropy sources via its plugins. Currently
  there is no internal entropy source provided which means that the used
  entropy sources must provide their own SP800-90B analysis. For the
  Jitter RNG, a separate SP800-90B analysis is provided. The ESDM only
  ensures that the Jitter RNG is appropriately initialized before it is
  used as an entropy source. The kernel RNG (random.c) entropy source on
  the other hand is not SP800-90B compliant. Thus, in FIPS mode, the
  ESDM credits its data with zero bits of entropy.

- SP800-90C: The ESDM follows the current draft of SP800-90C when
  compiled with the option CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES.
  The DRBG is initially seeded with at least 384 bits of entropy before
  it is marked as fully seeded (and thus produces random numbers via the
  esdm_get_random_bytes_full call. Subsequent reseeds are performed with
  at least 256 bits of entropy. The conditioning operation performed in
  the auxiliary pool requires 64 more bits of entropy to be fed into the
  conditioner function provide the respective entropy output (e.g. 256
  bits of entropy are fed into the SHA-256 conditioner resulting in the
  output of 192 bits of entropy provided by the entropy source to the
  ESDM). With the given entropy sources, the ESDM follows the RBG2(NP)
  construction method.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
 crypto/esdm/Kconfig                | 14 +++++
 crypto/esdm/Makefile               |  2 +
 crypto/esdm/esdm_drng_kcapi.c      |  1 +
 crypto/esdm/esdm_interface_kcapi.c | 91 ++++++++++++++++++++++++++++++
 crypto/testmgr.c                   |  8 +++
 5 files changed, 116 insertions(+)
 create mode 100644 crypto/esdm/esdm_interface_kcapi.c

diff --git a/crypto/esdm/Kconfig b/crypto/esdm/Kconfig
index 43e11484e95c..3636c1c79602 100644
--- a/crypto/esdm/Kconfig
+++ b/crypto/esdm/Kconfig
@@ -27,6 +27,20 @@ config CRYPTO_ESDM_SHA256
 	bool
 	default y if CRYPTO_LIB_SHA256
 
+menu "ESDM Interfaces"
+
+config CRYPTO_ESDM_KCAPI_IF
+	tristate "Interface with Kernel Crypto API"
+	depends on CRYPTO_RNG
+	help
+	  The ESDM can be registered with the kernel crypto API's
+	  random number generator framework. This offers a random
+	  number generator with the name "esdm" and a priority that
+	  is intended to be higher than the existing RNG
+	  implementations.
+
+endmenu # "ESDM Interfaces"
+
 menu "Specific DRNG seeding strategies"
 
 config CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
diff --git a/crypto/esdm/Makefile b/crypto/esdm/Makefile
index 404436de0aa2..0bf8d65dd5fa 100644
--- a/crypto/esdm/Makefile
+++ b/crypto/esdm/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_CRYPTO_ESDM_DRNG_KCAPI)	+= esdm_drng_kcapi.o
 
 obj-$(CONFIG_CRYPTO_ESDM_KERNEL_RNG)	+= esdm_es_krng.o
 obj-$(CONFIG_CRYPTO_ESDM_JENT)		+= esdm_es_jent.o
+
+obj-$(CONFIG_CRYPTO_ESDM_KCAPI_IF)	+= esdm_interface_kcapi.o
diff --git a/crypto/esdm/esdm_drng_kcapi.c b/crypto/esdm/esdm_drng_kcapi.c
index ae8d2be91b37..03135337196b 100644
--- a/crypto/esdm/esdm_drng_kcapi.c
+++ b/crypto/esdm/esdm_drng_kcapi.c
@@ -99,6 +99,7 @@ static void *esdm_kcapi_drng_alloc(u32 sec_strength)
 	}
 
 	if (!memcmp(drng_name, "stdrng", 6) ||
+	    !memcmp(drng_name, "esdm", 4) ||
 	    !memcmp(drng_name, "jitterentropy_rng", 17)) {
 		pr_err("Refusing to load the requested random number generator\n");
 		return ERR_PTR(-EINVAL);
diff --git a/crypto/esdm/esdm_interface_kcapi.c b/crypto/esdm/esdm_interface_kcapi.c
new file mode 100644
index 000000000000..f2968d83c991
--- /dev/null
+++ b/crypto/esdm/esdm_interface_kcapi.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+/*
+ * ESDM interface with the RNG framework of the kernel crypto API
+ *
+ * Copyright (C) 2022, Stephan Mueller <smueller@chronox.de>
+ */
+
+#include <crypto/esdm.h>
+#include <linux/module.h>
+#include <crypto/internal/rng.h>
+
+#include "esdm_drng_mgr.h"
+#include "esdm_es_aux.h"
+
+static int esdm_kcapi_if_init(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static void esdm_kcapi_if_cleanup(struct crypto_tfm *tfm) { }
+
+static int esdm_kcapi_if_reseed(const u8 *src, unsigned int slen)
+{
+	int ret;
+
+	if (!slen)
+		return 0;
+
+	/* Insert caller-provided data without crediting entropy */
+	ret = esdm_pool_insert_aux((u8 *)src, slen, 0);
+	if (ret)
+		return ret;
+
+	/* Make sure the new data is immediately available to DRNG */
+	esdm_drng_force_reseed();
+
+	return 0;
+}
+
+static int esdm_kcapi_if_random(struct crypto_rng *tfm,
+				const u8 *src, unsigned int slen,
+				u8 *rdata, unsigned int dlen)
+{
+	int ret = esdm_kcapi_if_reseed(src, slen);
+
+	if (!ret)
+		esdm_get_random_bytes_full(rdata, dlen);
+
+	return ret;
+}
+
+static int esdm_kcapi_if_reset(struct crypto_rng *tfm,
+			       const u8 *seed, unsigned int slen)
+{
+	return esdm_kcapi_if_reseed(seed, slen);
+}
+
+static struct rng_alg esdm_alg = {
+	.generate		= esdm_kcapi_if_random,
+	.seed			= esdm_kcapi_if_reset,
+	.seedsize		= 0,
+	.base			= {
+		.cra_name               = "stdrng",
+		.cra_driver_name        = "esdm",
+		.cra_priority           = 500,
+		.cra_ctxsize            = 0,
+		.cra_module             = THIS_MODULE,
+		.cra_init               = esdm_kcapi_if_init,
+		.cra_exit               = esdm_kcapi_if_cleanup,
+
+	}
+};
+
+static int __init esdm_kcapi_if_mod_init(void)
+{
+	return crypto_register_rng(&esdm_alg);
+}
+
+static void __exit esdm_kcapi_if_mod_exit(void)
+{
+	crypto_unregister_rng(&esdm_alg);
+}
+
+module_init(esdm_kcapi_if_mod_init);
+module_exit(esdm_kcapi_if_mod_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
+MODULE_DESCRIPTION("Entropy Source and DRNG Manager kernel crypto API RNG framework interface");
+MODULE_ALIAS_CRYPTO("esdm");
+MODULE_ALIAS_CRYPTO("stdrng");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 2ce698eb14b6..0865105f9377 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4878,6 +4878,14 @@ static const struct alg_test_desc alg_test_descs[] = {
 		.suite = {
 			.akcipher = __VECS(ecrdsa_tv_template)
 		}
+	}, {
+		.alg = "esdm",
+		.test = alg_test_null,
+#ifdef CONFIG_CRYPTO_ESDM_OVERSAMPLE_ENTROPY_SOURCES
+		.fips_allowed = 1,
+#else
+		.fips_allowed = 0,
+#endif
 	}, {
 		.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
 		.test = alg_test_aead,
-- 
2.33.1





^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] crypto: DRBG - remove internal reseeding operation
  2022-01-26  7:03 ` [PATCH 1/7] crypto: DRBG - remove internal reseeding operation Stephan Müller
@ 2022-01-26 12:15   ` kernel test robot
  2022-01-26 13:44     ` Stephan Mueller
  0 siblings, 1 reply; 15+ messages in thread
From: kernel test robot @ 2022-01-26 12:15 UTC (permalink / raw)
  To: Stephan Müller, herbert
  Cc: llvm, kbuild-all, linux-crypto, simo, Nicolai Stange

Hi "Stephan,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on herbert-cryptodev-2.6/master]
[also build test ERROR on herbert-crypto-2.6/master linus/master v5.17-rc1 next-20220125]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Stephan-M-ller/Common-entropy-source-and-DRNG-management/20220126-150911
base:   https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: hexagon-buildonly-randconfig-r003-20220124 (https://download.01.org/0day-ci/archive/20220126/202201262050.xFgnR1Kx-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 2a1b7aa016c0f4b5598806205bdfbab1ea2d92c4)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/14ec08bbd20e04299353eb31a9d43d4ac9af2b22
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Stephan-M-ller/Common-entropy-source-and-DRNG-management/20220126-150911
        git checkout 14ec08bbd20e04299353eb31a9d43d4ac9af2b22
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   crypto/drbg.c:204:30: warning: unused function 'drbg_sec_strength' [-Wunused-function]
   static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
                                ^
>> crypto/drbg.c:1742:2: error: call to __compiletime_assert_223 declared with 'error' attribute: BUILD_BUG_ON failed: ARRAY_SIZE(drbg_cores) != ARRAY_SIZE(drbg_algs)
           BUILD_BUG_ON(ARRAY_SIZE(drbg_cores) != ARRAY_SIZE(drbg_algs));
           ^
   include/linux/build_bug.h:50:2: note: expanded from macro 'BUILD_BUG_ON'
           BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
           ^
   include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG'
   #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                       ^
   include/linux/compiler_types.h:335:2: note: expanded from macro 'compiletime_assert'
           _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
           ^
   include/linux/compiler_types.h:323:2: note: expanded from macro '_compiletime_assert'
           __compiletime_assert(condition, msg, prefix, suffix)
           ^
   include/linux/compiler_types.h:316:4: note: expanded from macro '__compiletime_assert'
                           prefix ## suffix();                             \
                           ^
   <scratch space>:63:1: note: expanded from here
   __compiletime_assert_223
   ^
   1 warning and 1 error generated.


vim +/error +1742 crypto/drbg.c

  1732	
  1733	static int __init drbg_init(void)
  1734	{
  1735		unsigned int i;
  1736		int ret;
  1737	
  1738		ret = drbg_healthcheck_sanity();
  1739		if (ret)
  1740			return ret;
  1741	
> 1742		BUILD_BUG_ON(ARRAY_SIZE(drbg_cores) != ARRAY_SIZE(drbg_algs));
  1743	
  1744		/*
  1745		 * As the order of placing them into the drbg_algs array matters
  1746		 * (the later DRBGs receive a higher cra_priority) we register the
  1747		 * prediction resistance DRBGs first as the should not be too
  1748		 * interesting.
  1749		 */
  1750		for (i = 0; i < ARRAY_SIZE(drbg_cores); i++)
  1751			drbg_fill_array(&drbg_algs[i], &drbg_cores[i]);
  1752		return crypto_register_rngs(drbg_algs, ARRAY_SIZE(drbg_cores));
  1753	}
  1754	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/7] crypto: DRBG - remove internal reseeding operation
  2022-01-26 12:15   ` kernel test robot
@ 2022-01-26 13:44     ` Stephan Mueller
  0 siblings, 0 replies; 15+ messages in thread
From: Stephan Mueller @ 2022-01-26 13:44 UTC (permalink / raw)
  To: herbert, kernel test robot
  Cc: llvm, kbuild-all, linux-crypto, simo, Nicolai Stange

Am Mittwoch, 26. Januar 2022, 13:15:04 CET schrieb kernel test robot:

Hi,

>    crypto/drbg.c:204:30: warning: unused function 'drbg_sec_strength'
> [-Wunused-function] static inline unsigned short
> drbg_sec_strength(drbg_flag_t flags) ^

It is interesting that Sparse did not complain about this. Anyhow, this 
function is not needed and will be removed.
> 
> >> crypto/drbg.c:1742:2: error: call to __compiletime_assert_223 declared
> >> with 'error' attribute: BUILD_BUG_ON failed: ARRAY_SIZE(drbg_cores) !=
> >> ARRAY_SIZE(drbg_algs)
>            BUILD_BUG_ON(ARRAY_SIZE(drbg_cores) != ARRAY_SIZE(drbg_algs));


Correct, it should be > instead of != :-)

This will be fixed in the new code base

Thanks!

Ciao
Stephan



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] Common entropy source and DRNG management
  2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
                   ` (6 preceding siblings ...)
  2022-01-26  7:05 ` [PATCH 7/7] crypto: ESDM - add kernel crypto API RNG interface Stephan Müller
@ 2022-01-26 22:49 ` Eric Biggers
  2022-01-28 15:37   ` Stephan Mueller
  7 siblings, 1 reply; 15+ messages in thread
From: Eric Biggers @ 2022-01-26 22:49 UTC (permalink / raw)
  To: Stephan Müller; +Cc: herbert, linux-crypto, simo, Nicolai Stange

On Wed, Jan 26, 2022 at 08:02:54AM +0100, Stephan Müller wrote:
> The current code base of the kernel crypto API random number support
> leaves the task to seed and reseed the DRNG to either the caller or
> the DRNG implementation. The code in crypto/drbg.c implements its own
> seeding strategy. crypto/ansi_cprng.c does not contain any seeding
> operation. The implementation in arch/s390/crypto/prng.c has yet
> another approach for seeding. Albeit the crypto_rng_reset() contains
> a seeding logic from get_random_bytes, there is no management of
> the DRNG to ensure proper reseeding or control which entropy sources
> are used for pulling data from.

ansi_cprng looks like unused code that should be removed, as does the s390 prng.

With that being the case, what is the purpose of this patchset?

- Eric

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] Common entropy source and DRNG management
  2022-01-26 22:49 ` [PATCH 0/7] Common entropy source and DRNG management Eric Biggers
@ 2022-01-28 15:37   ` Stephan Mueller
  2022-01-28 18:51     ` Eric Biggers
  0 siblings, 1 reply; 15+ messages in thread
From: Stephan Mueller @ 2022-01-28 15:37 UTC (permalink / raw)
  To: Eric Biggers; +Cc: herbert, linux-crypto, simo, Nicolai Stange

Am Mittwoch, 26. Januar 2022, 23:49:03 CET schrieb Eric Biggers:

Hi Eric,

> On Wed, Jan 26, 2022 at 08:02:54AM +0100, Stephan Müller wrote:
> > The current code base of the kernel crypto API random number support
> > leaves the task to seed and reseed the DRNG to either the caller or
> > the DRNG implementation. The code in crypto/drbg.c implements its own
> > seeding strategy. crypto/ansi_cprng.c does not contain any seeding
> > operation. The implementation in arch/s390/crypto/prng.c has yet
> > another approach for seeding. Albeit the crypto_rng_reset() contains
> > a seeding logic from get_random_bytes, there is no management of
> > the DRNG to ensure proper reseeding or control which entropy sources
> > are used for pulling data from.
> 
> ansi_cprng looks like unused code that should be removed, as does the s390
> prng.
> 
> With that being the case, what is the purpose of this patchset?

I would agree that ansi_csprng could be eliminated at this stage. However, the 
S390 DRBG code base provides access to the CPACF DRBG implemented in the IBM Z 
processors. That implementation must be seeded from software. See the function 
invocation of cpacf_klmd or cpacf_kmc in the prng.c file.

The extraction of the entropy source and DRNG management into its own 
component separates out the security sensitive implementation currently found 
in multiple locations following the strategy found in the crypto API where 
each moving part is separated and encapsulated.

The current implementation of the ESDM allows an easy addition of new entropy 
sources which are properly encapsulated in self-contained code allowing self-
contained entropy analyses to be performed for each. These entropy sources 
would provide their seed data completely separate from other entropy sources 
to the DRNG preventing any mutual entanglement and thus challenges in the 
entropy assessment. I have additional entropy sources already available that I 
would like to contribute at a later stage. These entropy sources can be 
enabled, disabled or its entropy rate set as needed by vendors depending on 
their entropy source analysis. Proper default values would be used for the 
common case where a vendor does not want to perform its own analysis or a 
distro which want to provide a common kernel binary for many users.

The conditioning hash that is available to the entropy sources is currently 
fixed to a SHA-256 software implementation. To support conveying more entropy 
through the conditioning hash, I would like to contribute an extension that 
allows the use of the kernel crypto API's set of message digest 
implementations to be used. This would not only allow using larger message 
digests, but also hashes other than SHA.

Depending on use cases, it is possible that different initial seeding 
strategies are required to be considered for the DRNG. The initial patch set 
provides the oversampling of entropy sources and of the initial seed string in 
addition to the conventional approach of providing at least as much entropy as 
the security strength of the DRNG. There is a different seeding strategy in 
the pipeline that is considered by other cryptographers for which I would like 
to contribute the respective patch.

NUMA-awareness is another aspect that should be considered. The DRNG manager 
is prepared to instantiate one DRNG per node. The respective handler code, 
however, is not part of the initial code drop.

In addition to the different DRNG implementations discussed before, there is 
the possibility to add an implementation to support atomic operations. The 
current DRBG does not guarantee to be suitable for such use cases.

Ciao
Stephan



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] Common entropy source and DRNG management
  2022-01-28 15:37   ` Stephan Mueller
@ 2022-01-28 18:51     ` Eric Biggers
  2022-02-05  3:50       ` Herbert Xu
  0 siblings, 1 reply; 15+ messages in thread
From: Eric Biggers @ 2022-01-28 18:51 UTC (permalink / raw)
  To: Stephan Mueller; +Cc: herbert, linux-crypto, simo, Nicolai Stange

On Fri, Jan 28, 2022 at 04:37:26PM +0100, Stephan Mueller wrote:
> Am Mittwoch, 26. Januar 2022, 23:49:03 CET schrieb Eric Biggers:
> 
> Hi Eric,
> 
> > On Wed, Jan 26, 2022 at 08:02:54AM +0100, Stephan Müller wrote:
> > > The current code base of the kernel crypto API random number support
> > > leaves the task to seed and reseed the DRNG to either the caller or
> > > the DRNG implementation. The code in crypto/drbg.c implements its own
> > > seeding strategy. crypto/ansi_cprng.c does not contain any seeding
> > > operation. The implementation in arch/s390/crypto/prng.c has yet
> > > another approach for seeding. Albeit the crypto_rng_reset() contains
> > > a seeding logic from get_random_bytes, there is no management of
> > > the DRNG to ensure proper reseeding or control which entropy sources
> > > are used for pulling data from.
> > 
> > ansi_cprng looks like unused code that should be removed, as does the s390
> > prng.
> > 
> > With that being the case, what is the purpose of this patchset?
> 
> I would agree that ansi_csprng could be eliminated at this stage. However, the 
> S390 DRBG code base provides access to the CPACF DRBG implemented in the IBM Z 
> processors. That implementation must be seeded from software. See the function 
> invocation of cpacf_klmd or cpacf_kmc in the prng.c file.

We should still just get rid of that, since equivalent functionality is
available in software, is better tested, and isn't performance-critical.

> The extraction of the entropy source and DRNG management into its own 
> component separates out the security sensitive implementation currently found 
> in multiple locations following the strategy found in the crypto API where 
> each moving part is separated and encapsulated.
> 
> The current implementation of the ESDM allows an easy addition of new entropy 
> sources which are properly encapsulated in self-contained code allowing self-
> contained entropy analyses to be performed for each. These entropy sources 
> would provide their seed data completely separate from other entropy sources 
> to the DRNG preventing any mutual entanglement and thus challenges in the 
> entropy assessment. I have additional entropy sources already available that I 
> would like to contribute at a later stage. These entropy sources can be 
> enabled, disabled or its entropy rate set as needed by vendors depending on 
> their entropy source analysis. Proper default values would be used for the 
> common case where a vendor does not want to perform its own analysis or a 
> distro which want to provide a common kernel binary for many users.

What is the actual point of this?  The NIST DRBGs are already seeded from
random.c, which is sufficient by itself but doesn't play well with
certifications, and from Jitterentropy which the certification side is happy
with.  And the NIST DRBGs are only present for certification purposes anyway;
all real users use random.c instead.  So what problem still needs to be solved?

> 
> The conditioning hash that is available to the entropy sources is currently 
> fixed to a SHA-256 software implementation. To support conveying more entropy 
> through the conditioning hash, I would like to contribute an extension that 
> allows the use of the kernel crypto API's set of message digest 
> implementations to be used. This would not only allow using larger message 
> digests, but also hashes other than SHA.

This doesn't need to be configurable, and shouldn't be; just choose an
appropriate hash.

> Depending on use cases, it is possible that different initial seeding 
> strategies are required to be considered for the DRNG. The initial patch set 
> provides the oversampling of entropy sources and of the initial seed string in 
> addition to the conventional approach of providing at least as much entropy as 
> the security strength of the DRNG. There is a different seeding strategy in 
> the pipeline that is considered by other cryptographers for which I would like 
> to contribute the respective patch.

It would be better to standardize on one way of doing it so that people can't
choose the wrong way.

> NUMA-awareness is another aspect that should be considered. The DRNG manager 
> is prepared to instantiate one DRNG per node. The respective handler code, 
> however, is not part of the initial code drop.

random.c is already NUMA-optimized.

> In addition to the different DRNG implementations discussed before, there is 
> the possibility to add an implementation to support atomic operations. The 
> current DRBG does not guarantee to be suitable for such use cases.

random.c already supports atomic operations.

- Eric

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] Common entropy source and DRNG management
  2022-01-28 18:51     ` Eric Biggers
@ 2022-02-05  3:50       ` Herbert Xu
  2022-02-06 16:02         ` Stephan Mueller
  0 siblings, 1 reply; 15+ messages in thread
From: Herbert Xu @ 2022-02-05  3:50 UTC (permalink / raw)
  To: Eric Biggers; +Cc: Stephan Mueller, linux-crypto, simo, Nicolai Stange

On Fri, Jan 28, 2022 at 10:51:00AM -0800, Eric Biggers wrote:
>
> > The extraction of the entropy source and DRNG management into its own 
> > component separates out the security sensitive implementation currently found 
> > in multiple locations following the strategy found in the crypto API where 
> > each moving part is separated and encapsulated.
> > 
> > The current implementation of the ESDM allows an easy addition of new entropy 
> > sources which are properly encapsulated in self-contained code allowing self-
> > contained entropy analyses to be performed for each. These entropy sources 
> > would provide their seed data completely separate from other entropy sources 
> > to the DRNG preventing any mutual entanglement and thus challenges in the 
> > entropy assessment. I have additional entropy sources already available that I 
> > would like to contribute at a later stage. These entropy sources can be 
> > enabled, disabled or its entropy rate set as needed by vendors depending on 
> > their entropy source analysis. Proper default values would be used for the 
> > common case where a vendor does not want to perform its own analysis or a 
> > distro which want to provide a common kernel binary for many users.
> 
> What is the actual point of this?  The NIST DRBGs are already seeded from
> random.c, which is sufficient by itself but doesn't play well with
> certifications, and from Jitterentropy which the certification side is happy
> with.  And the NIST DRBGs are only present for certification purposes anyway;
> all real users use random.c instead.  So what problem still needs to be solved?

Indeed.  Stephan, could you please explain exactly what additional
seeding sources are needed over the current jitter+/dev/random sources
(and why).  Or even better, add those seeding sources that we must have
in your patch series so that they can be evaluated together.

As it stands this patch series seems to be adding a lot of code without
any uses.

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/7] Common entropy source and DRNG management
  2022-02-05  3:50       ` Herbert Xu
@ 2022-02-06 16:02         ` Stephan Mueller
  0 siblings, 0 replies; 15+ messages in thread
From: Stephan Mueller @ 2022-02-06 16:02 UTC (permalink / raw)
  To: Eric Biggers, Herbert Xu; +Cc: linux-crypto, simo, Nicolai Stange

Am Samstag, 5. Februar 2022, 04:50:48 CET schrieb Herbert Xu:

Hi Herbert,

> On Fri, Jan 28, 2022 at 10:51:00AM -0800, Eric Biggers wrote:
> > > The extraction of the entropy source and DRNG management into its own
> > > component separates out the security sensitive implementation currently
> > > found in multiple locations following the strategy found in the crypto
> > > API where each moving part is separated and encapsulated.
> > > 
> > > The current implementation of the ESDM allows an easy addition of new
> > > entropy sources which are properly encapsulated in self-contained code
> > > allowing self- contained entropy analyses to be performed for each.
> > > These entropy sources would provide their seed data completely separate
> > > from other entropy sources to the DRNG preventing any mutual
> > > entanglement and thus challenges in the entropy assessment. I have
> > > additional entropy sources already available that I would like to
> > > contribute at a later stage. These entropy sources can be enabled,
> > > disabled or its entropy rate set as needed by vendors depending on
> > > their entropy source analysis. Proper default values would be used for
> > > the common case where a vendor does not want to perform its own
> > > analysis or a distro which want to provide a common kernel binary for
> > > many users.> 
> > What is the actual point of this?  The NIST DRBGs are already seeded from
> > random.c, which is sufficient by itself but doesn't play well with
> > certifications, and from Jitterentropy which the certification side is
> > happy with.  And the NIST DRBGs are only present for certification
> > purposes anyway; all real users use random.c instead.  So what problem
> > still needs to be solved?
> Indeed.  Stephan, could you please explain exactly what additional
> seeding sources are needed over the current jitter+/dev/random sources
> (and why).  Or even better, add those seeding sources that we must have
> in your patch series so that they can be evaluated together.
> 
> As it stands this patch series seems to be adding a lot of code without
> any uses.

Thank you for the clarification. I will provide that information.
> 
> Thanks,


Ciao
Stephan



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-02-06 16:08 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-26  7:02 [PATCH 0/7] Common entropy source and DRNG management Stephan Müller
2022-01-26  7:03 ` [PATCH 1/7] crypto: DRBG - remove internal reseeding operation Stephan Müller
2022-01-26 12:15   ` kernel test robot
2022-01-26 13:44     ` Stephan Mueller
2022-01-26  7:03 ` [PATCH 2/7] crypto: AF_ALG - remove ALG_SET_DRBG_ENTROPY interface Stephan Müller
2022-01-26  7:04 ` [PATCH 3/7] crypto: Entropy Source and DRNG Manager Stephan Müller
2022-01-26  7:04 ` [PATCH 4/7] crypto: move Jitter RNG header include dir Stephan Müller
2022-01-26  7:04 ` [PATCH 5/7] crypto: ESDM - add Jitter RNG entropy source Stephan Müller
2022-01-26  7:05 ` [PATCH 6/7] crypto: ESDM - add Kernel " Stephan Müller
2022-01-26  7:05 ` [PATCH 7/7] crypto: ESDM - add kernel crypto API RNG interface Stephan Müller
2022-01-26 22:49 ` [PATCH 0/7] Common entropy source and DRNG management Eric Biggers
2022-01-28 15:37   ` Stephan Mueller
2022-01-28 18:51     ` Eric Biggers
2022-02-05  3:50       ` Herbert Xu
2022-02-06 16:02         ` Stephan Mueller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).