* [PATCH 01/38] crypto: drbg - Fix returning success on failure in CTR_DRBG
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 02/38] crypto: drbg - Fix misaligned writes in CTR_DRBG and HASH_DRBG Eric Biggers
` (36 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers,
stable
drbg_ctr_generate() sometimes returns success when it fails, leaving the
output buffer uninitialized. Fix it.
Fixes: cde001e4c3c3 ("crypto: rng - RNGs must return 0 in success case")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 9204e6edb426..e4eb78ed222b 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -375,11 +375,11 @@ static int drbg_ctr_generate(struct drbg_state *drbg,
/* 10.2.1.5.2 step 2 */
if (addtl && !list_empty(addtl)) {
ret = drbg_ctr_update(drbg, addtl, 2);
if (ret)
- return 0;
+ return ret;
}
/* 10.2.1.5.2 step 4.1 */
ret = drbg_kcapi_sym_ctr(drbg, NULL, 0, buf, len);
if (ret)
base-commit: c1f49dea2b8f335813d3b348fd39117fb8efb428
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 02/38] crypto: drbg - Fix misaligned writes in CTR_DRBG and HASH_DRBG
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
2026-04-20 6:33 ` [PATCH 01/38] crypto: drbg - Fix returning success on failure in CTR_DRBG Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 03/38] crypto: drbg - Fix ineffective sanity check Eric Biggers
` (35 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers,
stable
drbg_cpu_to_be32() is being used to do a plain write to a byte array,
which doesn't have any alignment guarantee. This can cause a misaligned
write. Replace it with the correct function, put_unaligned_be32().
Fixes: 72f3e00dd67e ("crypto: drbg - replace int2byte with cpu_to_be")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/df_sp80090a.c | 7 ++++---
crypto/drbg.c | 3 ++-
include/crypto/internal/drbg.h | 18 ------------------
3 files changed, 6 insertions(+), 22 deletions(-)
diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c
index b8134be6f7ad..f4bb7be016e8 100644
--- a/crypto/df_sp80090a.c
+++ b/crypto/df_sp80090a.c
@@ -8,10 +8,11 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/unaligned.h>
#include <crypto/aes.h>
#include <crypto/df_sp80090a.h>
#include <crypto/internal/drbg.h>
static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval,
@@ -139,14 +140,14 @@ int crypto_drbg_ctr_df(struct aes_enckey *aeskey,
return -EINVAL;
/* 10.4.2 step 2 -- calculate the entire length of all input data */
list_for_each_entry(seed, seedlist, list)
inputlen += seed->len;
- drbg_cpu_to_be32(inputlen, &L_N[0]);
+ put_unaligned_be32(inputlen, &L_N[0]);
/* 10.4.2 step 3 */
- drbg_cpu_to_be32(bytes_to_return, &L_N[4]);
+ put_unaligned_be32(bytes_to_return, &L_N[4]);
/* 10.4.2 step 5: length is L_N, input_string, one byte, padding */
padlen = (inputlen + sizeof(L_N) + 1) % (blocklen_bytes);
/* wrap the padlen appropriately */
if (padlen)
@@ -173,11 +174,11 @@ int crypto_drbg_ctr_df(struct aes_enckey *aeskey,
/*
* 10.4.2 step 9.1 - the padding is implicit as the buffer
* holds zeros after allocation -- even the increment of i
* is irrelevant as the increment remains within length of i
*/
- drbg_cpu_to_be32(i, iv);
+ put_unaligned_be32(i, iv);
/* 10.4.2 step 9.2 -- BCC and concatenation with temp */
drbg_ctr_bcc(aeskey, temp + templen, K, &bcc_list,
blocklen_bytes, keylen);
/* 10.4.2 step 9.3 */
i++;
diff --git a/crypto/drbg.c b/crypto/drbg.c
index e4eb78ed222b..de4c69032155 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -101,10 +101,11 @@
#include <crypto/df_sp80090a.h>
#include <crypto/internal/cipher.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/string_choices.h>
+#include <linux/unaligned.h>
/***************************************************************
* Backend cipher definitions available to DRBG
***************************************************************/
@@ -599,11 +600,11 @@ static int drbg_hash_df(struct drbg_state *drbg,
unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
struct drbg_string data;
/* 10.4.1 step 3 */
input[0] = 1;
- drbg_cpu_to_be32((outlen * 8), &input[1]);
+ put_unaligned_be32(outlen * 8, &input[1]);
/* 10.4.1 step 4.1 -- concatenation of data for input into hash */
drbg_string_fill(&data, input, 5);
list_add(&data.list, entropylist);
diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h
index 371e52dcee6c..b4e5ef0be602 100644
--- a/include/crypto/internal/drbg.h
+++ b/include/crypto/internal/drbg.h
@@ -7,28 +7,10 @@
*/
#ifndef _INTERNAL_DRBG_H
#define _INTERNAL_DRBG_H
-/*
- * Convert an integer into a byte representation of this integer.
- * The byte representation is big-endian
- *
- * @val value to be converted
- * @buf buffer holding the converted integer -- caller must ensure that
- * buffer size is at least 32 bit
- */
-static inline void drbg_cpu_to_be32(__u32 val, unsigned char *buf)
-{
- struct s {
- __be32 conv;
- };
- struct s *conversion = (struct s *)buf;
-
- conversion->conv = cpu_to_be32(val);
-}
-
/*
* Concatenation Helper and string operation helper
*
* SP800-90A requires the concatenation of different data. To avoid copying
* buffers around or allocate additional memory, the following data structure
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 03/38] crypto: drbg - Fix ineffective sanity check
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
2026-04-20 6:33 ` [PATCH 01/38] crypto: drbg - Fix returning success on failure in CTR_DRBG Eric Biggers
2026-04-20 6:33 ` [PATCH 02/38] crypto: drbg - Fix misaligned writes in CTR_DRBG and HASH_DRBG Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 04/38] crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels Eric Biggers
` (34 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers,
stable
Fix drbg_healthcheck_sanity() to correctly check the return value of
drbg_generate(). drbg_generate() returns 0 on success, or a negative
errno value on failure. drbg_healthcheck_sanity() incorrectly assumed
that it returned a positive value on success.
This didn't make the sanity check fail, but it made it ineffective.
Fixes: cde001e4c3c3 ("crypto: rng - RNGs must return 0 in success case")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index de4c69032155..f23b431bd490 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1735,11 +1735,10 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
* Note 2: There is no sensible way of testing the reseed counter
* enforcement, so skip it.
*/
static inline int __init drbg_healthcheck_sanity(void)
{
- int len = 0;
#define OUTBUFLEN 16
unsigned char buf[OUTBUFLEN];
struct drbg_state *drbg = NULL;
int ret;
int rc = -EFAULT;
@@ -1780,15 +1779,15 @@ static inline int __init drbg_healthcheck_sanity(void)
max_addtllen = drbg_max_addtl(drbg);
max_request_bytes = drbg_max_request_bytes(drbg);
drbg_string_fill(&addtl, buf, max_addtllen + 1);
/* overflow addtllen with additional info string */
- len = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
- BUG_ON(0 < len);
+ ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ BUG_ON(ret == 0);
/* overflow max_bits */
- len = drbg_generate(drbg, buf, (max_request_bytes + 1), NULL);
- BUG_ON(0 < len);
+ ret = drbg_generate(drbg, buf, max_request_bytes + 1, NULL);
+ BUG_ON(ret == 0);
/* overflow max addtllen with personalization string */
ret = drbg_seed(drbg, &addtl, false);
BUG_ON(0 == ret);
/* all tests passed */
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 04/38] crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (2 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 03/38] crypto: drbg - Fix ineffective sanity check Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 05/38] crypto: drbg - Fix the fips_enabled priority boost Eric Biggers
` (33 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers,
stable
On 64-bit kernels, drbg_max_addtl() returns 2**35 bytes. That's too
large, for two reasons:
1. SP800-90A says the maximum limit is 2**35 *bits*, not 2**35 bytes.
So the implemented limit has confused bits and bytes.
2. When drbg_kcapi_hash() calls crypto_shash_update() on the additional
information string, the length is implicitly cast to 'unsigned int'.
That truncates the additional information string to U32_MAX bytes.
Fix the maximum additional information string length to always be
U32_MAX - 1, causing an error to be returned for any longer lengths.
Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/drbg.h | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 2d42518cbdce..c11eaf757ed0 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -146,23 +146,19 @@ static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
{
/* SP800-90A requires the limit 2**19 bits, but we return bytes */
return (1 << 16);
}
+/*
+ * SP800-90A allows implementations to support additional info / personalization
+ * strings of up to 2**35 bits. Implementations can have a smaller maximum. We
+ * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a
+ * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement.
+ */
static inline size_t drbg_max_addtl(struct drbg_state *drbg)
{
- /* SP800-90A requires 2**35 bytes additional info str / pers str */
-#if (__BITS_PER_LONG == 32)
- /*
- * SP800-90A allows smaller maximum numbers to be returned -- we
- * return SIZE_MAX - 1 to allow the verification of the enforcement
- * of this value in drbg_healthcheck_sanity.
- */
- return (SIZE_MAX - 1);
-#else
- return (1UL<<35);
-#endif
+ return U32_MAX - 1;
}
static inline size_t drbg_max_requests(struct drbg_state *drbg)
{
/* SP800-90A requires 2**48 maximum requests before reseeding */
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 05/38] crypto: drbg - Fix the fips_enabled priority boost
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (3 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 04/38] crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 06/38] crypto: drbg - Remove always-enabled symbol CRYPTO_DRBG_HMAC Eric Biggers
` (32 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers,
stable
When fips_enabled=1, it seems to have been intended for one of the
algorithms defined in crypto/drbg.c to be the highest priority "stdrng"
algorithm, so that it is what is used by "stdrng" users.
However, the code only boosts the priority to 400, which is less than
the priority 500 used in drivers/crypto/caam/caamprng.c. Thus, the CAAM
RNG could be used instead.
Fix this by boosting the priority by 2000 instead of 200.
Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index f23b431bd490..e3065fb9541b 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1830,11 +1830,11 @@ static inline void __init drbg_fill_array(struct rng_alg *alg,
* If FIPS mode enabled, the selected DRBG shall have the
* highest cra_priority over other stdrng instances to ensure
* it is selected.
*/
if (fips_enabled)
- alg->base.cra_priority += 200;
+ alg->base.cra_priority += 2000;
alg->base.cra_ctxsize = sizeof(struct drbg_state);
alg->base.cra_module = THIS_MODULE;
alg->base.cra_init = drbg_kcapi_init;
alg->base.cra_exit = drbg_kcapi_cleanup;
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 06/38] crypto: drbg - Remove always-enabled symbol CRYPTO_DRBG_HMAC
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (4 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 05/38] crypto: drbg - Fix the fips_enabled priority boost Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 07/38] crypto: drbg - Remove broken commented-out code Eric Biggers
` (31 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
The kconfig symbol CRYPTO_DRBG_HMAC is always enabled when
CRYPTO_DRBG_MENU is enabled, and all checks for CRYPTO_DRBG_HMAC are in
code conditional on CRYPTO_DRBG_MENU. Thus, the only purpose of the
CRYPTO_DRBG_HMAC symbol is to select CRYPTO_HMAC and CRYPTO_SHA512.
Move those two selections to CRYPTO_DRBG_MENU, remove the checks for
CRYPTO_DRBG_HMAC, and remove the CRYPTO_DRBG_HMAC symbol itself.
Note that this also fixes an issue where CRYPTO_HMAC and CRYPTO_SHA512
were unnecessarily being forced to built-in when CRYPTO_DRBG=m.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 10 +++-------
crypto/drbg.c | 15 ---------------
2 files changed, 3 insertions(+), 22 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 103d1f58cb7c..34da01c153d6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1120,16 +1120,10 @@ menuconfig CRYPTO_DRBG_MENU
In the following submenu, one or more of the DRBG types must be selected.
if CRYPTO_DRBG_MENU
-config CRYPTO_DRBG_HMAC
- bool
- default y
- select CRYPTO_HMAC
- select CRYPTO_SHA512
-
config CRYPTO_DRBG_HASH
bool "Hash_DRBG"
select CRYPTO_SHA256
help
Hash_DRBG variant as defined in NIST SP800-90A.
@@ -1145,12 +1139,14 @@ config CRYPTO_DRBG_CTR
This uses the AES cipher algorithm with the counter block mode.
config CRYPTO_DRBG
tristate
default CRYPTO_DRBG_MENU
- select CRYPTO_RNG
+ select CRYPTO_HMAC
select CRYPTO_JITTERENTROPY
+ select CRYPTO_RNG
+ select CRYPTO_SHA512
endif # if CRYPTO_DRBG_MENU
config CRYPTO_JITTERENTROPY
tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)"
diff --git a/crypto/drbg.c b/crypto/drbg.c
index e3065fb9541b..f6bff275c31b 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -159,11 +159,10 @@ static const struct drbg_core drbg_cores[] = {
.blocklen_bytes = 32,
.cra_name = "sha256",
.backend_cra_name = "sha256",
},
#endif /* CONFIG_CRYPTO_DRBG_HASH */
-#ifdef CONFIG_CRYPTO_DRBG_HMAC
{
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 48, /* block length of cipher */
.blocklen_bytes = 48,
.cra_name = "hmac_sha384",
@@ -179,11 +178,10 @@ static const struct drbg_core drbg_cores[] = {
.statelen = 64, /* block length of cipher */
.blocklen_bytes = 64,
.cra_name = "hmac_sha512",
.backend_cra_name = "hmac(sha512)",
},
-#endif /* CONFIG_CRYPTO_DRBG_HMAC */
};
static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
@@ -404,20 +402,17 @@ static const struct drbg_state_ops drbg_ctr_ops = {
/******************************************************************
* HMAC DRBG callback functions
******************************************************************/
-#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
const struct list_head *in);
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
const unsigned char *key);
static int drbg_init_hash_kernel(struct drbg_state *drbg);
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
-#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
-#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");
@@ -525,11 +520,10 @@ static const struct drbg_state_ops drbg_hmac_ops = {
.update = drbg_hmac_update,
.generate = drbg_hmac_generate,
.crypto_init = drbg_init_hash_kernel,
.crypto_fini = drbg_fini_hash_kernel,
};
-#endif /* CONFIG_CRYPTO_DRBG_HMAC */
/******************************************************************
* Hash DRBG callback functions
******************************************************************/
@@ -1044,15 +1038,13 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
{
int ret = -ENOMEM;
unsigned int sb_size = 0;
switch (drbg->core->flags & DRBG_TYPE_MASK) {
-#ifdef CONFIG_CRYPTO_DRBG_HMAC
case DRBG_HMAC:
drbg->d_ops = &drbg_hmac_ops;
break;
-#endif /* CONFIG_CRYPTO_DRBG_HMAC */
#ifdef CONFIG_CRYPTO_DRBG_HASH
case DRBG_HASH:
drbg->d_ops = &drbg_hash_ops;
break;
#endif /* CONFIG_CRYPTO_DRBG_HASH */
@@ -1429,11 +1421,10 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
/***************************************************************
* Kernel crypto API cipher invocations requested by DRBG
***************************************************************/
-#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
struct sdesc {
struct shash_desc shash;
};
static int drbg_init_hash_kernel(struct drbg_state *drbg)
@@ -1489,11 +1480,10 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
crypto_shash_init(&sdesc->shash);
list_for_each_entry(input, in, list)
crypto_shash_update(&sdesc->shash, input->buf, input->len);
return crypto_shash_final(&sdesc->shash, outval);
}
-#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
#ifdef CONFIG_CRYPTO_DRBG_CTR
static int drbg_fini_sym_kernel(struct drbg_state *drbg)
{
struct aes_enckey *aeskey = drbg->priv_data;
@@ -1755,13 +1745,11 @@ static inline int __init drbg_healthcheck_sanity(void)
drbg_convert_tfm_core("drbg_nopr_ctr_aes256", &coreref, &pr);
#endif
#ifdef CONFIG_CRYPTO_DRBG_HASH
drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
#endif
-#ifdef CONFIG_CRYPTO_DRBG_HMAC
drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr);
-#endif
drbg = kzalloc_obj(struct drbg_state);
if (!drbg)
return -ENOMEM;
@@ -1885,13 +1873,10 @@ static void __exit drbg_exit(void)
module_init(drbg_init);
module_exit(drbg_exit);
#ifndef CRYPTO_DRBG_HASH_STRING
#define CRYPTO_DRBG_HASH_STRING ""
#endif
-#ifndef CRYPTO_DRBG_HMAC_STRING
-#define CRYPTO_DRBG_HMAC_STRING ""
-#endif
#ifndef CRYPTO_DRBG_CTR_STRING
#define CRYPTO_DRBG_CTR_STRING ""
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 07/38] crypto: drbg - Remove broken commented-out code
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (5 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 06/38] crypto: drbg - Remove always-enabled symbol CRYPTO_DRBG_HMAC Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 08/38] crypto: drbg - Remove unhelpful helper functions Eric Biggers
` (30 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
This commented-out code doesn't compile. Even if it did, it wouldn't
actually do what it was apparently intended to do, seeing as the "test"
for "drbg_pr_hmac_sha512" and "drbg_pr_ctr_aes256" is alg_test_null().
Just delete it to avoid keeping broken code around, and so that there
isn't any perceived need to try to update it as the DRBG code is
refactored.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 29 -----------------------------
1 file changed, 29 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index f6bff275c31b..bb8ddc090307 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1217,40 +1217,11 @@ static int drbg_generate(struct drbg_state *drbg,
* were successfully and the following are not. If the initial would
* pass and the following would not, the kernel integrity is violated.
* In this case, the entire kernel operation is questionable and it
* is unlikely that the integrity violation only affects the
* correct operation of the DRBG.
- *
- * Albeit the following code is commented out, it is provided in
- * case somebody has a need to implement the test of 11.3.3.
*/
-#if 0
- if (drbg->reseed_ctr && !(drbg->reseed_ctr % 4096)) {
- int err = 0;
- pr_devel("DRBG: start to perform self test\n");
- if (drbg->core->flags & DRBG_HMAC)
- err = alg_test("drbg_pr_hmac_sha512",
- "drbg_pr_hmac_sha512", 0, 0);
- else if (drbg->core->flags & DRBG_CTR)
- err = alg_test("drbg_pr_ctr_aes256",
- "drbg_pr_ctr_aes256", 0, 0);
- else
- err = alg_test("drbg_pr_sha256",
- "drbg_pr_sha256", 0, 0);
- if (err) {
- pr_err("DRBG: periodical self test failed\n");
- /*
- * uninstantiate implies that from now on, only errors
- * are returned when reusing this DRBG cipher handle
- */
- drbg_uninstantiate(drbg);
- return 0;
- } else {
- pr_devel("DRBG: self test successful\n");
- }
- }
-#endif
/*
* All operations were successful, return 0 as mandated by
* the kernel crypto API interface.
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 08/38] crypto: drbg - Remove unhelpful helper functions
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (6 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 07/38] crypto: drbg - Remove broken commented-out code Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 09/38] crypto: drbg - Remove obsolete FIPS 140-2 continuous test Eric Biggers
` (29 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Fold the contents of the inline functions crypto_drbg_get_bytes_addtl(),
crypto_drbg_get_bytes_addtl_test(), and crypto_drbg_reset_test() into
their only caller in drbg_cavs_test(). It ends up being much simpler.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 15 +++------
crypto/testmgr.c | 34 ++++++-------------
include/crypto/drbg.h | 76 -------------------------------------------
3 files changed, 15 insertions(+), 110 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index bb8ddc090307..83cb6c1bbac0 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -53,44 +53,39 @@
* struct crypto_rng *drng;
* int err;
* char data[DATALEN];
*
* drng = crypto_alloc_rng(drng_name, 0, 0);
- * err = crypto_rng_get_bytes(drng, &data, DATALEN);
+ * 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";
*
- * 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);
+ * err = crypto_rng_reset(drng, personalization, strlen(personalization));
+ * err = crypto_rng_get_bytes(drng, data, DATALEN);
* crypto_free_rng(drng);
*
*
* Usage with additional information string during random number request
* ---------------------------------------------------------------------
* struct crypto_rng *drng;
* int err;
* char data[DATALEN];
* 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 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, addtl_string, strlen(addtl_string),
+ data, DATALEN);
* crypto_free_rng(drng);
*
*
* Usage with personalization and additional information strings
* -------------------------------------------------------------
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 4d86efae65b2..35ff2b50e3c2 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3485,12 +3485,10 @@ static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
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)
return -ENOMEM;
@@ -3502,43 +3500,31 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
"%s\n", driver);
return PTR_ERR(drng);
}
- 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);
+ crypto_rng_set_entropy(drng, test->entropy, test->entropylen);
+ ret = crypto_rng_reset(drng, test->pers, test->perslen);
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);
- }
+ if (pr)
+ crypto_rng_set_entropy(drng, test->entpra, test->entprlen);
+ 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);
- }
+ if (pr)
+ crypto_rng_set_entropy(drng, test->entprb, test->entprlen);
+ 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;
}
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index c11eaf757ed0..486aa793688e 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -76,14 +76,10 @@ struct drbg_state_ops {
int (*crypto_init)(struct drbg_state *drbg);
int (*crypto_fini)(struct drbg_state *drbg);
};
-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() */
DRBG_SEED_STATE_FULL,
};
@@ -163,82 +159,10 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg)
{
/* SP800-90A requires 2**48 maximum requests before reseeding */
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)
#define DRBG_HASH ((drbg_flag_t)1<<2)
#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 09/38] crypto: drbg - Remove obsolete FIPS 140-2 continuous test
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (7 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 08/38] crypto: drbg - Remove unhelpful helper functions Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 10/38] crypto: drbg - Fold include/crypto/drbg.h into crypto/drbg.c Eric Biggers
` (28 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
FIPS 140-2 required that a continuous test for repeated outputs be done
on both "Approved RNGs" and "Non-Approved RNGs".
That's apparently why crypto/drbg.c does such a test on the bytes it
pulls from get_random_bytes(), despite get_random_bytes() being a
"Non-Approved RNG" that is credited with zero entropy for FIPS purposes.
(From FIPS's point of view, the "Approved RNG" is jitterentropy.)
FIPS 140-3 "modernized" the continuous RNG test requirements. They're
now a bit more sophisticated, requiring both an "Adaptive Proportion
Test" and a "Repetition Count Test".
At the same time, FIPS 140-3 doesn't require continuous RNG tests on
"Non-Approved RNGs" if a "vetted conditioning component" is used. The
SP800-90A DRBGs are exactly such a vetted conditioning component, by
their design. (In the case of HASH_DRBG and CTR_DRBG, the derivation
function does have to be implemented. But the kernel does that.)
In other words: from FIPS 140-3's point of view, get_random_bytes()
still produces zero entropy, but the way the DRBG combines those bytes
with the jitterentropy bytes preserves all the "approved" entropy from
jitterentropy. Thus no test for get_random_bytes() is required.
Seeing as FIPS 140-2 certificates stopped being issued in 2021 in favor
of FIPS 140-3, this means this code is obsolete. Remove it.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 78 ++-----------------------------------------
include/crypto/drbg.h | 2 --
2 files changed, 2 insertions(+), 78 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 83cb6c1bbac0..66d7739469c6 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -203,59 +203,10 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
default:
return 32;
}
}
-/*
- * 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:
- * %true on success
- * %false when the CTRNG is not yet primed
- */
-static bool drbg_fips_continuous_test(struct drbg_state *drbg,
- const unsigned char *entropy)
- __must_hold(&drbg->drbg_mutex)
-{
- unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
-
- if (!IS_ENABLED(CONFIG_CRYPTO_FIPS))
- return true;
-
- /* skip test if we test the overall system */
- if (list_empty(&drbg->test_data.list))
- return true;
- /* only perform test in FIPS mode */
- if (!fips_enabled)
- return true;
-
- if (!drbg->fips_primed) {
- /* Priming of FIPS test */
- memcpy(drbg->prev, entropy, entropylen);
- drbg->fips_primed = true;
- /* priming: another round is needed */
- return false;
- }
- if (!memcmp(drbg->prev, entropy, entropylen))
- panic("DRBG continuous self test failed\n");
- memcpy(drbg->prev, entropy, entropylen);
-
- /* the test shall pass when the two values are not equal */
- return true;
-}
-
/******************************************************************
* CTR DRBG callback functions
******************************************************************/
#ifdef CONFIG_CRYPTO_DRBG_CTR
@@ -831,20 +782,10 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
}
return ret;
}
-static inline void drbg_get_random_bytes(struct drbg_state *drbg,
- unsigned char *entropy,
- unsigned int entropylen)
- __must_hold(&drbg->drbg_mutex)
-{
- do
- get_random_bytes(entropy, entropylen);
- while (!drbg_fips_continuous_test(drbg, entropy));
-}
-
static int drbg_seed_from_random(struct drbg_state *drbg)
__must_hold(&drbg->drbg_mutex)
{
struct drbg_string data;
LIST_HEAD(seedlist);
@@ -856,11 +797,11 @@ static int drbg_seed_from_random(struct drbg_state *drbg)
BUG_ON(entropylen > sizeof(entropy));
drbg_string_fill(&data, entropy, entropylen);
list_add_tail(&data.list, &seedlist);
- drbg_get_random_bytes(drbg, entropy, entropylen);
+ get_random_bytes(entropy, entropylen);
ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
memzero_explicit(entropy, entropylen);
return ret;
@@ -935,11 +876,11 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
/* Get seed from in-kernel /dev/urandom */
if (!rng_is_initialized())
new_seed_state = DRBG_SEED_STATE_PARTIAL;
- drbg_get_random_bytes(drbg, entropy, entropylen);
+ get_random_bytes(entropy, entropylen);
if (!drbg->jent) {
drbg_string_fill(&data1, entropy, entropylen);
pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
entropylen);
@@ -1016,15 +957,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
kfree_sensitive(drbg->scratchpadbuf);
drbg->scratchpadbuf = NULL;
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;
- }
}
/*
* Allocate all sub-structures for a DRBG state.
* The DRBG state structure must already be allocated.
@@ -1086,20 +1022,10 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
goto fini;
}
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:
drbg->d_ops->crypto_fini(drbg);
err:
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
index 486aa793688e..4fafc69a8ee6 100644
--- a/include/crypto/drbg.h
+++ b/include/crypto/drbg.h
@@ -107,12 +107,10 @@ struct drbg_state {
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;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 10/38] crypto: drbg - Fold include/crypto/drbg.h into crypto/drbg.c
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (8 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 09/38] crypto: drbg - Remove obsolete FIPS 140-2 continuous test Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 11/38] crypto: drbg - Remove import of crypto_cipher functions Eric Biggers
` (27 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
include/crypto/drbg.h no longer contains anything that is used
externally to crypto/drbg.c. Therefore, fold it into crypto/drbg.c.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 132 ++++++++++++-
crypto/testmgr.c | 3 +-
include/crypto/drbg.h | 181 ------------------
.../crypto/chacha20-s390/test-cipher.c | 1 -
4 files changed, 132 insertions(+), 185 deletions(-)
delete mode 100644 include/crypto/drbg.h
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 66d7739469c6..fd1d75addaf7 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -90,18 +90,148 @@
* Usage with personalization and additional information strings
* -------------------------------------------------------------
* Just mix both scenarios above.
*/
-#include <crypto/drbg.h>
#include <crypto/df_sp80090a.h>
#include <crypto/internal/cipher.h>
+#include <crypto/internal/drbg.h>
+#include <crypto/internal/rng.h>
+#include <crypto/hash.h>
+#include <crypto/skcipher.h>
+#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
+struct drbg_state;
+typedef uint32_t drbg_flag_t;
+
+struct drbg_core {
+ drbg_flag_t flags; /* flags for the cipher */
+ __u8 statelen; /* maximum state length */
+ __u8 blocklen_bytes; /* block size of output in bytes */
+ char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
+ /* kernel crypto API backend cipher name */
+ char backend_cra_name[CRYPTO_MAX_ALG_NAME];
+};
+
+struct drbg_state_ops {
+ int (*update)(struct drbg_state *drbg, struct list_head *seed,
+ int reseed);
+ int (*generate)(struct drbg_state *drbg,
+ unsigned char *buf, unsigned int buflen,
+ struct list_head *addtl);
+ int (*crypto_init)(struct drbg_state *drbg);
+ int (*crypto_fini)(struct drbg_state *drbg);
+
+};
+
+enum drbg_seed_state {
+ DRBG_SEED_STATE_UNSEEDED,
+ DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
+ DRBG_SEED_STATE_FULL,
+};
+
+struct drbg_state {
+ struct mutex drbg_mutex; /* lock around DRBG */
+ unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *Vbuf;
+ /* hash: static value 10.1.1.1 1b) hmac / ctr: key */
+ unsigned char *C;
+ 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;
+ void *priv_data; /* Cipher handle */
+
+ struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */
+ struct skcipher_request *ctr_req; /* CTR mode request handle */
+ __u8 *outscratchpadbuf; /* CTR mode output scratchpad */
+ __u8 *outscratchpad; /* CTR mode aligned outbuf */
+ 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? */
+ 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)
+{
+ if (drbg && drbg->core)
+ return drbg->core->statelen;
+ return 0;
+}
+
+static inline __u8 drbg_blocklen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return drbg->core->blocklen_bytes;
+ return 0;
+}
+
+static inline __u8 drbg_keylen(struct drbg_state *drbg)
+{
+ if (drbg && drbg->core)
+ return (drbg->core->statelen - drbg->core->blocklen_bytes);
+ return 0;
+}
+
+static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
+{
+ /* SP800-90A requires the limit 2**19 bits, but we return bytes */
+ return (1 << 16);
+}
+
+/*
+ * SP800-90A allows implementations to support additional info / personalization
+ * strings of up to 2**35 bits. Implementations can have a smaller maximum. We
+ * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a
+ * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement.
+ */
+static inline size_t drbg_max_addtl(struct drbg_state *drbg)
+{
+ return U32_MAX - 1;
+}
+
+static inline size_t drbg_max_requests(struct drbg_state *drbg)
+{
+ /* SP800-90A requires 2**48 maximum requests before reseeding */
+ return (1<<20);
+}
+
+/* DRBG type flags */
+#define DRBG_CTR ((drbg_flag_t)1<<0)
+#define DRBG_HMAC ((drbg_flag_t)1<<1)
+#define DRBG_HASH ((drbg_flag_t)1<<2)
+#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
+/* DRBG strength flags */
+#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
+#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
+#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
+#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
+ DRBG_STRENGTH256)
+
+enum drbg_prefixes {
+ DRBG_PREFIX0 = 0x00,
+ DRBG_PREFIX1,
+ DRBG_PREFIX2,
+ DRBG_PREFIX3
+};
+
/***************************************************************
* Backend cipher definitions available to DRBG
***************************************************************/
/*
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 35ff2b50e3c2..480368a41cc0 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -26,17 +26,16 @@
#include <linux/prandom.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uio.h>
-#include <crypto/rng.h>
-#include <crypto/drbg.h>
#include <crypto/akcipher.h>
#include <crypto/kpp.h>
#include <crypto/acompress.h>
#include <crypto/sig.h>
#include <crypto/internal/cipher.h>
+#include <crypto/internal/rng.h>
#include <crypto/internal/simd.h>
#include "internal.h"
MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h
deleted file mode 100644
index 4fafc69a8ee6..000000000000
--- a/include/crypto/drbg.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * DRBG based on NIST SP800-90A
- *
- * Copyright Stephan Mueller <smueller@chronox.de>, 2014
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, and the entire permission notice in its entirety,
- * including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU General Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions. (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-#ifndef _DRBG_H
-#define _DRBG_H
-
-
-#include <linux/random.h>
-#include <linux/scatterlist.h>
-#include <crypto/hash.h>
-#include <crypto/skcipher.h>
-#include <linux/module.h>
-#include <linux/crypto.h>
-#include <linux/slab.h>
-#include <crypto/internal/drbg.h>
-#include <crypto/internal/rng.h>
-#include <crypto/rng.h>
-#include <linux/fips.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/workqueue.h>
-
-struct drbg_state;
-typedef uint32_t drbg_flag_t;
-
-struct drbg_core {
- drbg_flag_t flags; /* flags for the cipher */
- __u8 statelen; /* maximum state length */
- __u8 blocklen_bytes; /* block size of output in bytes */
- char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
- /* kernel crypto API backend cipher name */
- char backend_cra_name[CRYPTO_MAX_ALG_NAME];
-};
-
-struct drbg_state_ops {
- int (*update)(struct drbg_state *drbg, struct list_head *seed,
- int reseed);
- int (*generate)(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
- struct list_head *addtl);
- int (*crypto_init)(struct drbg_state *drbg);
- int (*crypto_fini)(struct drbg_state *drbg);
-
-};
-
-enum drbg_seed_state {
- DRBG_SEED_STATE_UNSEEDED,
- DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
- DRBG_SEED_STATE_FULL,
-};
-
-struct drbg_state {
- struct mutex drbg_mutex; /* lock around DRBG */
- unsigned char *V; /* internal state 10.1.1.1 1a) */
- unsigned char *Vbuf;
- /* hash: static value 10.1.1.1 1b) hmac / ctr: key */
- unsigned char *C;
- 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;
- void *priv_data; /* Cipher handle */
-
- struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */
- struct skcipher_request *ctr_req; /* CTR mode request handle */
- __u8 *outscratchpadbuf; /* CTR mode output scratchpad */
- __u8 *outscratchpad; /* CTR mode aligned outbuf */
- 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? */
- 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)
-{
- if (drbg && drbg->core)
- return drbg->core->statelen;
- return 0;
-}
-
-static inline __u8 drbg_blocklen(struct drbg_state *drbg)
-{
- if (drbg && drbg->core)
- return drbg->core->blocklen_bytes;
- return 0;
-}
-
-static inline __u8 drbg_keylen(struct drbg_state *drbg)
-{
- if (drbg && drbg->core)
- return (drbg->core->statelen - drbg->core->blocklen_bytes);
- return 0;
-}
-
-static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
-{
- /* SP800-90A requires the limit 2**19 bits, but we return bytes */
- return (1 << 16);
-}
-
-/*
- * SP800-90A allows implementations to support additional info / personalization
- * strings of up to 2**35 bits. Implementations can have a smaller maximum. We
- * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a
- * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement.
- */
-static inline size_t drbg_max_addtl(struct drbg_state *drbg)
-{
- return U32_MAX - 1;
-}
-
-static inline size_t drbg_max_requests(struct drbg_state *drbg)
-{
- /* SP800-90A requires 2**48 maximum requests before reseeding */
- return (1<<20);
-}
-
-/* DRBG type flags */
-#define DRBG_CTR ((drbg_flag_t)1<<0)
-#define DRBG_HMAC ((drbg_flag_t)1<<1)
-#define DRBG_HASH ((drbg_flag_t)1<<2)
-#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
-/* DRBG strength flags */
-#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
-#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
-#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
-#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
- DRBG_STRENGTH256)
-
-enum drbg_prefixes {
- DRBG_PREFIX0 = 0x00,
- DRBG_PREFIX1,
- DRBG_PREFIX2,
- DRBG_PREFIX3
-};
-
-#endif /* _DRBG_H */
diff --git a/tools/testing/crypto/chacha20-s390/test-cipher.c b/tools/testing/crypto/chacha20-s390/test-cipher.c
index 827507844e8f..9f61454ed077 100644
--- a/tools/testing/crypto/chacha20-s390/test-cipher.c
+++ b/tools/testing/crypto/chacha20-s390/test-cipher.c
@@ -9,11 +9,10 @@
#include <asm/smp.h>
#include <crypto/skcipher.h>
#include <crypto/akcipher.h>
#include <crypto/acompress.h>
#include <crypto/rng.h>
-#include <crypto/drbg.h>
#include <crypto/kpp.h>
#include <crypto/internal/simd.h>
#include <crypto/chacha.h>
#include <crypto/aead.h>
#include <crypto/hash.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 11/38] crypto: drbg - Remove import of crypto_cipher functions
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (9 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 10/38] crypto: drbg - Fold include/crypto/drbg.h into crypto/drbg.c Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG Eric Biggers
` (26 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
The inclusion of <crypto/internal/cipher.h> and the import of the
internal crypto namespace became unnecessary in commit ba0570bdf1d9
("crypto: drbg - Replace AES cipher calls with library calls").
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index fd1d75addaf7..9dedc6186b42 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -91,11 +91,10 @@
* -------------------------------------------------------------
* Just mix both scenarios above.
*/
#include <crypto/df_sp80090a.h>
-#include <crypto/internal/cipher.h>
#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
#include <crypto/hash.h>
#include <crypto/skcipher.h>
#include <linux/fips.h>
@@ -1906,6 +1905,5 @@ MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
"using following cores: "
CRYPTO_DRBG_HASH_STRING
CRYPTO_DRBG_HMAC_STRING
CRYPTO_DRBG_CTR_STRING);
MODULE_ALIAS_CRYPTO("stdrng");
-MODULE_IMPORT_NS("CRYPTO_INTERNAL");
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (10 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 11/38] crypto: drbg - Remove import of crypto_cipher functions Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 8:07 ` Geert Uytterhoeven
2026-04-20 14:40 ` Stephan Mueller
2026-04-20 6:33 ` [PATCH 13/38] crypto: drbg - Remove support for HASH_DRBG Eric Biggers
` (25 subsequent siblings)
37 siblings, 2 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Remove the support for CTR_DRBG. It's likely unused code, seeing as
HMAC_DRBG is always enabled and prioritized over it unless
NETLINK_CRYPTO is used to change the algorithm priorities.
There's also no compelling reason to support more than one of
[HMAC_DRBG, HASH_DRBG, CTR_DRBG]. By definition, callers cannot tell
any difference in their outputs. And all are FIPS-certifiable, which is
the only point of the kernel's NIST DRBGs anyway.
Switching to CTR_DRBG doesn't seem all that compelling, either. While
it's often the fastest NIST DRBG, it has several disadvantages:
- CTR_DRBG uses AES. Some platforms don't have AES acceleration at all,
causing a fallback to the table-based AES code which is very slow and
can be vulnerable to cache-timing attacks. In contrast, HMAC_DRBG
uses primitives that are consistently constant-time.
- CTR_DRBG is usually considered to be somewhat less cryptographically
robust than HMAC_DRBG. Granted, HMAC_DRBG isn't all that great
either, e.g. given the negative result from Woodage & Shumow (2018)
(https://eprint.iacr.org/2018/349.pdf), but that can be worked around.
- CTR_DRBG is more complex than HMAC_DRBG, risking bugs. Indeed, while
reviewing the CTR_DRBG code, I found two bugs, including one where it
can return success while leaving the output buffer uninitialized.
- The kernel's implementation of CTR_DRBG uses an "ctr(aes)"
crypto_skcipher and relies on it returning the next counter value.
That's fragile, and indeed historically many "ctr(aes)"
crypto_skcipher implementations haven't done that. E.g. see
commit 511306b2d075 ("crypto: arm/aes-ce - update IV after partial final CTR block"),
commit fa5fd3afc7e6 ("crypto: arm64/aes-blk - update IV after partial final CTR block"),
commit 371731ec2179 ("crypto: atmel-aes - Fix saving of IV for CTR mode"),
commit 25baaf8e2c93 ("crypto: crypto4xx - fix ctr-aes missing output IV"),
commit 334d37c9e263 ("crypto: caam - update IV using HW support"),
commit 0a4491d3febe ("crypto: chelsio - count incomplete block in IV"),
commit e8e3c1ca57d4 ("crypto: s5p - update iv after AES-CBC op end").
I.e., there were many years where the kernel's CTR_DRBG code (if it
were to have actually been used) repeated outputs on some platforms.
AES-CTR also uses a 128-bit counter, which creates overflow edge cases
that are sometimes gotten wrong. E.g. see commit 009b30ac7444
("crypto: vmx - CTR: always increment IV as quadword").
So, while switching to CTR_DRBG for performance reasons isn't completely
out of the question (notably BoringSSL uses it), it would take quite a
bit more work to create a solid implementation of it in the kernel,
including a more solid implementation of AES-CTR itself (in lib/crypto/,
with a scalar bit-sliced fallback, etc). Since HMAC_DRBG has always
been the default NIST DRBG variant in the kernel and is in a better
state, let's just standardize on it for now.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/m68k/configs/amiga_defconfig | 1 -
arch/m68k/configs/apollo_defconfig | 1 -
arch/m68k/configs/atari_defconfig | 1 -
arch/m68k/configs/bvme6000_defconfig | 1 -
arch/m68k/configs/hp300_defconfig | 1 -
arch/m68k/configs/mac_defconfig | 1 -
arch/m68k/configs/multi_defconfig | 1 -
arch/m68k/configs/mvme147_defconfig | 1 -
arch/m68k/configs/mvme16x_defconfig | 1 -
arch/m68k/configs/q40_defconfig | 1 -
arch/m68k/configs/sun3_defconfig | 1 -
arch/m68k/configs/sun3x_defconfig | 1 -
arch/mips/configs/decstation_64_defconfig | 1 -
arch/mips/configs/decstation_defconfig | 1 -
arch/mips/configs/decstation_r4k_defconfig | 1 -
crypto/Kconfig | 8 -
crypto/drbg.c | 332 +--------------------
crypto/testmgr.c | 37 ---
crypto/testmgr.h | 252 ----------------
include/crypto/internal/drbg.h | 3 +
20 files changed, 9 insertions(+), 638 deletions(-)
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 47e48c18e55c..a8ca9023caf3 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -549,11 +549,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 161586d611ab..5c6610d9e80a 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -504,11 +504,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index c13c6deeac22..4d080f6f3ddf 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -526,11 +526,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index d4f3f94b61ff..c61fc9d13d30 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -496,11 +496,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 58288f83349d..2bc20cfdfcf6 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -506,11 +506,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index abb369fd1f55..e03877efc7e6 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -525,11 +525,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index cb8de979700f..d613bfedee8a 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -612,11 +612,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 176540bd5074..fe343a8f69f5 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -496,11 +496,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 8b2e5cf4d2f2..c5803f67f30b 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -497,11 +497,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index d48f3cf5285b..619518c30e0b 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -515,11 +515,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 0b96428f25d4..530fa722e3b2 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -494,11 +494,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 6140e18244a1..f282e05bc8f9 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -494,11 +494,10 @@ CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig
index 7c43352fac6b..6712143a2842 100644
--- a/arch/mips/configs/decstation_64_defconfig
+++ b/arch/mips/configs/decstation_64_defconfig
@@ -198,9 +198,8 @@ CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
# CONFIG_CRYPTO_HW is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index aee10274f048..1a31bbb99839 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -193,10 +193,9 @@ CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
# CONFIG_CRYPTO_HW is not set
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig
index a1698049aa7a..8ff71ca43bfb 100644
--- a/arch/mips/configs/decstation_r4k_defconfig
+++ b/arch/mips/configs/decstation_r4k_defconfig
@@ -193,10 +193,9 @@ CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_DRBG_HASH=y
-CONFIG_CRYPTO_DRBG_CTR=y
# CONFIG_CRYPTO_HW is not set
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 34da01c153d6..b16a1aa95c46 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1128,18 +1128,10 @@ config CRYPTO_DRBG_HASH
help
Hash_DRBG variant as defined in NIST SP800-90A.
This uses the SHA-1, SHA-256, SHA-384, or SHA-512 hash algorithms.
-config CRYPTO_DRBG_CTR
- bool "CTR_DRBG"
- select CRYPTO_DF80090A
- help
- CTR_DRBG variant as defined in NIST SP800-90A.
-
- This uses the AES cipher algorithm with the counter block mode.
-
config CRYPTO_DRBG
tristate
default CRYPTO_DRBG_MENU
select CRYPTO_HMAC
select CRYPTO_JITTERENTROPY
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 9dedc6186b42..b29090bb59bc 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1,10 +1,9 @@
/*
* DRBG: Deterministic Random Bits Generator
* Based on NIST Recommended DRBG from NIST SP800-90A with the following
* properties:
- * * CTR DRBG with DF with AES-128, AES-192, AES-256 cores
* * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
* * 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
@@ -90,21 +89,18 @@
* Usage with personalization and additional information strings
* -------------------------------------------------------------
* Just mix both scenarios above.
*/
-#include <crypto/df_sp80090a.h>
#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
#include <crypto/hash.h>
-#include <crypto/skcipher.h>
#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/scatterlist.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
struct drbg_state;
typedef uint32_t drbg_flag_t;
@@ -137,28 +133,21 @@ enum drbg_seed_state {
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
unsigned char *V; /* internal state 10.1.1.1 1a) */
unsigned char *Vbuf;
- /* hash: static value 10.1.1.1 1b) hmac / ctr: key */
+ /* hash: static value 10.1.1.1 1b) hmac: key */
unsigned char *C;
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;
void *priv_data; /* Cipher handle */
- struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */
- struct skcipher_request *ctr_req; /* CTR mode request handle */
- __u8 *outscratchpadbuf; /* CTR mode output scratchpad */
- __u8 *outscratchpad; /* CTR mode aligned outbuf */
- 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? */
struct crypto_rng *jent;
const struct drbg_state_ops *d_ops;
@@ -178,17 +167,10 @@ static inline __u8 drbg_blocklen(struct drbg_state *drbg)
if (drbg && drbg->core)
return drbg->core->blocklen_bytes;
return 0;
}
-static inline __u8 drbg_keylen(struct drbg_state *drbg)
-{
- if (drbg && drbg->core)
- return (drbg->core->statelen - drbg->core->blocklen_bytes);
- return 0;
-}
-
static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
{
/* SP800-90A requires the limit 2**19 bits, but we return bytes */
return (1 << 16);
}
@@ -209,14 +191,13 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg)
/* SP800-90A requires 2**48 maximum requests before reseeding */
return (1<<20);
}
/* DRBG type flags */
-#define DRBG_CTR ((drbg_flag_t)1<<0)
#define DRBG_HMAC ((drbg_flag_t)1<<1)
#define DRBG_HASH ((drbg_flag_t)1<<2)
-#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH)
+#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_HASH)
/* DRBG strength flags */
#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
@@ -236,36 +217,13 @@ enum drbg_prefixes {
/*
* The order of the DRBG definitions here matter: every DRBG is registered
* as stdrng. Each DRBG receives an increasing cra_priority values the later
* they are defined in this array (see drbg_fill_array).
*
- * HMAC DRBGs are favored over Hash DRBGs over CTR DRBGs, and the
- * HMAC-SHA512 / SHA256 / AES 256 over other ciphers. Thus, the
- * favored DRBGs are the latest entries in this array.
+ * Thus, the favored DRBGs are the latest entries in this array.
*/
static const struct drbg_core drbg_cores[] = {
-#ifdef CONFIG_CRYPTO_DRBG_CTR
- {
- .flags = DRBG_CTR | DRBG_STRENGTH128,
- .statelen = 32, /* 256 bits as defined in 10.2.1 */
- .blocklen_bytes = 16,
- .cra_name = "ctr_aes128",
- .backend_cra_name = "aes",
- }, {
- .flags = DRBG_CTR | DRBG_STRENGTH192,
- .statelen = 40, /* 320 bits as defined in 10.2.1 */
- .blocklen_bytes = 16,
- .cra_name = "ctr_aes192",
- .backend_cra_name = "aes",
- }, {
- .flags = DRBG_CTR | DRBG_STRENGTH256,
- .statelen = 48, /* 384 bits as defined in 10.2.1 */
- .blocklen_bytes = 16,
- .cra_name = "ctr_aes256",
- .backend_cra_name = "aes",
- },
-#endif /* CONFIG_CRYPTO_DRBG_CTR */
#ifdef CONFIG_CRYPTO_DRBG_HASH
{
.flags = DRBG_HASH | DRBG_STRENGTH256,
.statelen = 111, /* 888 bits */
.blocklen_bytes = 48,
@@ -332,151 +290,10 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
default:
return 32;
}
}
-/******************************************************************
- * CTR DRBG callback functions
- ******************************************************************/
-
-#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 int drbg_init_sym_kernel(struct drbg_state *drbg);
-static int drbg_fini_sym_kernel(struct drbg_state *drbg);
-static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
- u8 *inbuf, u32 inbuflen,
- u8 *outbuf, u32 outlen);
-#define DRBG_OUTSCRATCHLEN 256
-
-static int drbg_ctr_df(struct drbg_state *drbg,
- unsigned char *df_data, size_t bytes_to_return,
- struct list_head *seedlist)
-{
- return crypto_drbg_ctr_df(drbg->priv_data, df_data, drbg_statelen(drbg),
- seedlist, drbg_blocklen(drbg), drbg_statelen(drbg));
-}
-
-/*
- * update function of CTR DRBG as defined in 10.2.1.2
- *
- * The reseed variable has an enhanced meaning compared to the update
- * functions of the other DRBGs as follows:
- * 0 => initial seed from initialization
- * 1 => reseed via drbg_seed
- * 2 => first invocation from drbg_ctr_update when addtl is present. In
- * this case, the df_data scratchpad is not deleted so that it is
- * available for another calls to prevent calling the DF function
- * again.
- * 3 => second invocation from drbg_ctr_update. When the update function
- * was called with addtl, the df_data memory already contains the
- * DFed addtl information and we do not need to call DF again.
- */
-static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed,
- int reseed)
-{
- int ret = -EFAULT;
- /* 10.2.1.2 step 1 */
- unsigned char *temp = drbg->scratchpad;
- unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) +
- drbg_blocklen(drbg);
-
- if (3 > reseed)
- memset(df_data, 0, drbg_statelen(drbg));
-
- if (!reseed) {
- /*
- * The DRBG uses the CTR mode of the underlying AES cipher. The
- * CTR mode increments the counter value after the AES operation
- * but SP800-90A requires that the counter is incremented before
- * the AES operation. Hence, we increment it at the time we set
- * it by one.
- */
- crypto_inc(drbg->V, drbg_blocklen(drbg));
-
- ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C,
- drbg_keylen(drbg));
- if (ret)
- goto out;
- }
-
- /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */
- if (seed) {
- ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed);
- if (ret)
- goto out;
- }
-
- ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg),
- temp, drbg_statelen(drbg));
- if (ret)
- return ret;
-
- /* 10.2.1.2 step 5 */
- ret = crypto_skcipher_setkey(drbg->ctr_handle, temp,
- drbg_keylen(drbg));
- if (ret)
- goto out;
- /* 10.2.1.2 step 6 */
- memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg));
- /* See above: increment counter by one to compensate timing of CTR op */
- crypto_inc(drbg->V, drbg_blocklen(drbg));
- ret = 0;
-
-out:
- memset(temp, 0, drbg_statelen(drbg) + drbg_blocklen(drbg));
- if (2 != reseed)
- memset(df_data, 0, drbg_statelen(drbg));
- return ret;
-}
-
-/*
- * scratchpad use: drbg_ctr_update is called independently from
- * drbg_ctr_extract_bytes. Therefore, the scratchpad is reused
- */
-/* Generate function of CTR DRBG as defined in 10.2.1.5.2 */
-static int drbg_ctr_generate(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
- struct list_head *addtl)
-{
- int ret;
- int len = min_t(int, buflen, INT_MAX);
-
- /* 10.2.1.5.2 step 2 */
- if (addtl && !list_empty(addtl)) {
- ret = drbg_ctr_update(drbg, addtl, 2);
- if (ret)
- return ret;
- }
-
- /* 10.2.1.5.2 step 4.1 */
- ret = drbg_kcapi_sym_ctr(drbg, NULL, 0, buf, len);
- if (ret)
- return ret;
-
- /* 10.2.1.5.2 step 6 */
- ret = drbg_ctr_update(drbg, NULL, 3);
- if (ret)
- len = ret;
-
- return len;
-}
-
-static const struct drbg_state_ops drbg_ctr_ops = {
- .update = drbg_ctr_update,
- .generate = drbg_ctr_generate,
- .crypto_init = drbg_init_sym_kernel,
- .crypto_fini = drbg_fini_sym_kernel,
-};
-#endif /* CONFIG_CRYPTO_DRBG_CTR */
-
/******************************************************************
* HMAC DRBG callback functions
******************************************************************/
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
@@ -1106,15 +923,10 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
#ifdef CONFIG_CRYPTO_DRBG_HASH
case DRBG_HASH:
drbg->d_ops = &drbg_hash_ops;
break;
#endif /* CONFIG_CRYPTO_DRBG_HASH */
-#ifdef CONFIG_CRYPTO_DRBG_CTR
- case DRBG_CTR:
- drbg->d_ops = &drbg_ctr_ops;
- break;
-#endif /* CONFIG_CRYPTO_DRBG_CTR */
default:
ret = -EOPNOTSUPP;
goto err;
}
@@ -1132,17 +944,13 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
if (!drbg->Cbuf) {
ret = -ENOMEM;
goto fini;
}
drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
- /* scratchpad is only generated for CTR and Hash */
+ /* scratchpad is only generated for Hash */
if (drbg->core->flags & DRBG_HMAC)
sb_size = 0;
- else if (drbg->core->flags & DRBG_CTR)
- sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg) + /* temp */
- crypto_drbg_ctr_df_datalen(drbg_statelen(drbg),
- drbg_blocklen(drbg));
else
sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
if (0 < sb_size) {
drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL);
@@ -1251,11 +1059,11 @@ static int drbg_generate(struct drbg_state *drbg,
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 */
+ /* 10.1.1.4 step 6, 10.1.2.5 step 7 */
drbg->reseed_ctr++;
if (0 >= len)
goto err;
/*
@@ -1502,131 +1310,10 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
list_for_each_entry(input, in, list)
crypto_shash_update(&sdesc->shash, input->buf, input->len);
return crypto_shash_final(&sdesc->shash, outval);
}
-#ifdef CONFIG_CRYPTO_DRBG_CTR
-static int drbg_fini_sym_kernel(struct drbg_state *drbg)
-{
- struct aes_enckey *aeskey = drbg->priv_data;
-
- kfree(aeskey);
- drbg->priv_data = NULL;
-
- if (drbg->ctr_handle)
- crypto_free_skcipher(drbg->ctr_handle);
- drbg->ctr_handle = NULL;
-
- if (drbg->ctr_req)
- skcipher_request_free(drbg->ctr_req);
- drbg->ctr_req = NULL;
-
- kfree(drbg->outscratchpadbuf);
- drbg->outscratchpadbuf = NULL;
-
- return 0;
-}
-
-static int drbg_init_sym_kernel(struct drbg_state *drbg)
-{
- struct aes_enckey *aeskey;
- struct crypto_skcipher *sk_tfm;
- struct skcipher_request *req;
- unsigned int alignmask;
- char ctr_name[CRYPTO_MAX_ALG_NAME];
-
- aeskey = kzalloc_obj(*aeskey);
- if (!aeskey)
- return -ENOMEM;
- drbg->priv_data = aeskey;
-
- if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
- drbg->core->backend_cra_name) >= CRYPTO_MAX_ALG_NAME) {
- drbg_fini_sym_kernel(drbg);
- return -EINVAL;
- }
- sk_tfm = crypto_alloc_skcipher(ctr_name, 0, 0);
- if (IS_ERR(sk_tfm)) {
- pr_info("DRBG: could not allocate CTR cipher TFM handle: %s\n",
- ctr_name);
- drbg_fini_sym_kernel(drbg);
- return PTR_ERR(sk_tfm);
- }
- drbg->ctr_handle = sk_tfm;
- crypto_init_wait(&drbg->ctr_wait);
-
- req = skcipher_request_alloc(sk_tfm, GFP_KERNEL);
- if (!req) {
- pr_info("DRBG: could not allocate request queue\n");
- drbg_fini_sym_kernel(drbg);
- return -ENOMEM;
- }
- drbg->ctr_req = req;
- skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
- CRYPTO_TFM_REQ_MAY_SLEEP,
- crypto_req_done, &drbg->ctr_wait);
-
- alignmask = crypto_skcipher_alignmask(sk_tfm);
- drbg->outscratchpadbuf = kmalloc(DRBG_OUTSCRATCHLEN + alignmask,
- GFP_KERNEL);
- if (!drbg->outscratchpadbuf) {
- drbg_fini_sym_kernel(drbg);
- return -ENOMEM;
- }
- drbg->outscratchpad = (u8 *)PTR_ALIGN(drbg->outscratchpadbuf,
- alignmask + 1);
-
- sg_init_table(&drbg->sg_in, 1);
- sg_init_one(&drbg->sg_out, drbg->outscratchpad, DRBG_OUTSCRATCHLEN);
-
- return alignmask;
-}
-
-static int drbg_kcapi_sym_ctr(struct drbg_state *drbg,
- u8 *inbuf, u32 inlen,
- u8 *outbuf, u32 outlen)
-{
- struct scatterlist *sg_in = &drbg->sg_in, *sg_out = &drbg->sg_out;
- u32 scratchpad_use = min_t(u32, outlen, DRBG_OUTSCRATCHLEN);
- int ret;
-
- if (inbuf) {
- /* Use caller-provided input buffer */
- sg_set_buf(sg_in, inbuf, inlen);
- } else {
- /* Use scratchpad for in-place operation */
- inlen = scratchpad_use;
- memset(drbg->outscratchpad, 0, scratchpad_use);
- sg_set_buf(sg_in, drbg->outscratchpad, scratchpad_use);
- }
-
- while (outlen) {
- u32 cryptlen = min3(inlen, outlen, (u32)DRBG_OUTSCRATCHLEN);
-
- /* Output buffer may not be valid for SGL, use scratchpad */
- skcipher_request_set_crypt(drbg->ctr_req, sg_in, sg_out,
- cryptlen, drbg->V);
- ret = crypto_wait_req(crypto_skcipher_encrypt(drbg->ctr_req),
- &drbg->ctr_wait);
- if (ret)
- goto out;
-
- crypto_init_wait(&drbg->ctr_wait);
-
- memcpy(outbuf, drbg->outscratchpad, cryptlen);
- memzero_explicit(drbg->outscratchpad, cryptlen);
-
- outlen -= cryptlen;
- outbuf += cryptlen;
- }
- ret = 0;
-
-out:
- return ret;
-}
-#endif /* CONFIG_CRYPTO_DRBG_CTR */
-
/***************************************************************
* Kernel crypto API interface to register DRBG
***************************************************************/
/*
@@ -1760,13 +1447,10 @@ static inline int __init drbg_healthcheck_sanity(void)
/* only perform test in FIPS mode */
if (!fips_enabled)
return 0;
-#ifdef CONFIG_CRYPTO_DRBG_CTR
- drbg_convert_tfm_core("drbg_nopr_ctr_aes256", &coreref, &pr);
-#endif
#ifdef CONFIG_CRYPTO_DRBG_HASH
drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
#endif
drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr);
@@ -1894,16 +1578,12 @@ static void __exit drbg_exit(void)
module_init(drbg_init);
module_exit(drbg_exit);
#ifndef CRYPTO_DRBG_HASH_STRING
#define CRYPTO_DRBG_HASH_STRING ""
#endif
-#ifndef CRYPTO_DRBG_CTR_STRING
-#define CRYPTO_DRBG_CTR_STRING ""
-#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
"using following cores: "
CRYPTO_DRBG_HASH_STRING
- CRYPTO_DRBG_HMAC_STRING
- CRYPTO_DRBG_CTR_STRING);
+ CRYPTO_DRBG_HMAC_STRING);
MODULE_ALIAS_CRYPTO("stdrng");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 480368a41cc0..dbc1e1fb4bd0 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4636,31 +4636,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.kpp = __VECS(dh_tv_template)
}
}, {
.alg = "digest_null",
.test = alg_test_null,
- }, {
- .alg = "drbg_nopr_ctr_aes128",
- .test = alg_test_drbg,
- .fips_allowed = 1,
- .suite = {
- .drbg = __VECS(drbg_nopr_ctr_aes128_tv_template)
- }
- }, {
- .alg = "drbg_nopr_ctr_aes192",
- .test = alg_test_drbg,
- .fips_allowed = 1,
- .suite = {
- .drbg = __VECS(drbg_nopr_ctr_aes192_tv_template)
- }
- }, {
- .alg = "drbg_nopr_ctr_aes256",
- .test = alg_test_drbg,
- .fips_allowed = 1,
- .suite = {
- .drbg = __VECS(drbg_nopr_ctr_aes256_tv_template)
- }
}, {
.alg = "drbg_nopr_hmac_sha256",
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
@@ -4695,26 +4674,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.fips_allowed = 1
}, {
.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_sha256",
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 9b4d7e11c9fd..a86275b61b6a 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -23744,126 +23744,10 @@ static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
"\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
@@ -24161,146 +24045,10 @@ static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = {
.pers = NULL,
.perslen = 0,
}
};
-static const struct drbg_testvec drbg_nopr_ctr_aes192_tv_template[] = {
- {
- .entropy = (unsigned char *)
- "\xc3\x5c\x2f\xa2\xa8\x9d\x52\xa1\x1f\xa3\x2a\xa9"
- "\x6c\x95\xb8\xf1\xc9\xa8\xf9\xcb\x24\x5a\x8b\x40"
- "\xf3\xa6\xe5\xa7\xfb\xd9\xd3\xc6\x8e\x27\x7b\xa9"
- "\xac\x9b\xbb\x00",
- .entropylen = 40,
- .expected = (unsigned char *)
- "\x8c\x2e\x72\xab\xfd\x9b\xb8\x28\x4d\xb7\x9e\x17"
- "\xa4\x3a\x31\x46\xcd\x76\x94\xe3\x52\x49\xfc\x33"
- "\x83\x91\x4a\x71\x17\xf4\x13\x68\xe6\xd4\xf1\x48"
- "\xff\x49\xbf\x29\x07\x6b\x50\x15\xc5\x9f\x45\x79"
- "\x45\x66\x2e\x3d\x35\x03\x84\x3f\x4a\xa5\xa3\xdf"
- "\x9a\x9d\xf1\x0d",
- .expectedlen = 64,
- .addtla = NULL,
- .addtlb = NULL,
- .addtllen = 0,
- .pers = NULL,
- .perslen = 0,
- },
-};
-
-static const struct drbg_testvec drbg_nopr_ctr_aes256_tv_template[] = {
- {
- .entropy = (unsigned char *)
- "\x36\x40\x19\x40\xfa\x8b\x1f\xba\x91\xa1\x66\x1f"
- "\x21\x1d\x78\xa0\xb9\x38\x9a\x74\xe5\xbc\xcf\xec"
- "\xe8\xd7\x66\xaf\x1a\x6d\x3b\x14\x49\x6f\x25\xb0"
- "\xf1\x30\x1b\x4f\x50\x1b\xe3\x03\x80\xa1\x37\xeb",
- .entropylen = 48,
- .expected = (unsigned char *)
- "\x58\x62\xeb\x38\xbd\x55\x8d\xd9\x78\xa6\x96\xe6"
- "\xdf\x16\x47\x82\xdd\xd8\x87\xe7\xe9\xa6\xc9\xf3"
- "\xf1\xfb\xaf\xb7\x89\x41\xb5\x35\xa6\x49\x12\xdf"
- "\xd2\x24\xc6\xdc\x74\x54\xe5\x25\x0b\x3d\x97\x16"
- "\x5e\x16\x26\x0c\x2f\xaf\x1c\xc7\x73\x5c\xb7\x5f"
- "\xb4\xf0\x7e\x1d",
- .expectedlen = 64,
- .addtla = NULL,
- .addtlb = NULL,
- .addtllen = 0,
- .pers = NULL,
- .perslen = 0,
- },
-};
-
-static const struct drbg_testvec drbg_nopr_ctr_aes128_tv_template[] = {
- {
- .entropy = (unsigned char *)
- "\x87\xe1\xc5\x32\x99\x7f\x57\xa3\x5c\x28\x6d\xe8"
- "\x64\xbf\xf2\x64\xa3\x9e\x98\xdb\x6c\x10\x78\x7f",
- .entropylen = 24,
- .expected = (unsigned char *)
- "\x2c\x14\x7e\x24\x11\x9a\xd8\xd4\xb2\xed\x61\xc1"
- "\x53\xd0\x50\xc9\x24\xff\x59\x75\x15\xf1\x17\x3a"
- "\x3d\xf4\x4b\x2c\x84\x28\xef\x89\x0e\xb9\xde\xf3"
- "\xe4\x78\x04\xb2\xfd\x9b\x35\x7f\xe1\x3f\x8a\x3e"
- "\x10\xc8\x67\x0a\xf9\xdf\x2d\x6c\x96\xfb\xb2\xb8"
- "\xcb\x2d\xd6\xb0",
- .expectedlen = 64,
- .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"
- "\xce\x72\xd8\x33\x34\x50\x2d\x8f\x5b\x14\xc4\xdd",
- .entropylen = 24,
- .expected = (unsigned char *)
- "\x97\x33\xe8\x20\x12\xe2\x7b\xa1\x46\x8f\xf2\x34"
- "\xb3\xc9\xb6\x6b\x20\xb2\x4f\xee\x27\xd8\x0b\x21"
- "\x8c\xff\x63\x73\x69\x29\xfb\xf3\x85\xcd\x88\x8e"
- "\x43\x2c\x71\x8b\xa2\x55\xd2\x0f\x1d\x7f\xe3\xe1"
- "\x2a\xa3\xe9\x2c\x25\x89\xc7\x14\x52\x99\x56\xcc"
- "\xc3\xdf\xb3\x81",
- .expectedlen = 64,
- .addtla = (unsigned char *)
- "\x66\xef\x42\xd6\x9a\x8c\x3d\x6d\x4a\x9e\x95\xa6"
- "\x91\x4d\x81\x56",
- .addtlb = (unsigned char *)
- "\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 */
static const struct cipher_testvec cast5_tv_template[] = {
{
.key = "\x01\x23\x45\x67\x12\x34\x56\x78"
"\x23\x45\x67\x89\x34\x56\x78\x9a",
diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h
index b4e5ef0be602..5d4174cc6a53 100644
--- a/include/crypto/internal/drbg.h
+++ b/include/crypto/internal/drbg.h
@@ -7,10 +7,13 @@
*/
#ifndef _INTERNAL_DRBG_H
#define _INTERNAL_DRBG_H
+#include <linux/list.h>
+#include <linux/types.h>
+
/*
* Concatenation Helper and string operation helper
*
* SP800-90A requires the concatenation of different data. To avoid copying
* buffers around or allocate additional memory, the following data structure
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 6:33 ` [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG Eric Biggers
@ 2026-04-20 8:07 ` Geert Uytterhoeven
2026-04-20 14:40 ` Stephan Mueller
1 sibling, 0 replies; 50+ messages in thread
From: Geert Uytterhoeven @ 2026-04-20 8:07 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, Herbert Xu, linux-kernel, Stephan Mueller,
Jason A . Donenfeld
On Mon, 20 Apr 2026 at 08:41, Eric Biggers <ebiggers@kernel.org> wrote:
> Remove the support for CTR_DRBG. It's likely unused code, seeing as
> HMAC_DRBG is always enabled and prioritized over it unless
> NETLINK_CRYPTO is used to change the algorithm priorities.
>
> There's also no compelling reason to support more than one of
> [HMAC_DRBG, HASH_DRBG, CTR_DRBG]. By definition, callers cannot tell
> any difference in their outputs. And all are FIPS-certifiable, which is
> the only point of the kernel's NIST DRBGs anyway.
>
> Switching to CTR_DRBG doesn't seem all that compelling, either. While
> it's often the fastest NIST DRBG, it has several disadvantages:
>
> - CTR_DRBG uses AES. Some platforms don't have AES acceleration at all,
> causing a fallback to the table-based AES code which is very slow and
> can be vulnerable to cache-timing attacks. In contrast, HMAC_DRBG
> uses primitives that are consistently constant-time.
>
> - CTR_DRBG is usually considered to be somewhat less cryptographically
> robust than HMAC_DRBG. Granted, HMAC_DRBG isn't all that great
> either, e.g. given the negative result from Woodage & Shumow (2018)
> (https://eprint.iacr.org/2018/349.pdf), but that can be worked around.
>
> - CTR_DRBG is more complex than HMAC_DRBG, risking bugs. Indeed, while
> reviewing the CTR_DRBG code, I found two bugs, including one where it
> can return success while leaving the output buffer uninitialized.
>
> - The kernel's implementation of CTR_DRBG uses an "ctr(aes)"
> crypto_skcipher and relies on it returning the next counter value.
> That's fragile, and indeed historically many "ctr(aes)"
> crypto_skcipher implementations haven't done that. E.g. see
> commit 511306b2d075 ("crypto: arm/aes-ce - update IV after partial final CTR block"),
> commit fa5fd3afc7e6 ("crypto: arm64/aes-blk - update IV after partial final CTR block"),
> commit 371731ec2179 ("crypto: atmel-aes - Fix saving of IV for CTR mode"),
> commit 25baaf8e2c93 ("crypto: crypto4xx - fix ctr-aes missing output IV"),
> commit 334d37c9e263 ("crypto: caam - update IV using HW support"),
> commit 0a4491d3febe ("crypto: chelsio - count incomplete block in IV"),
> commit e8e3c1ca57d4 ("crypto: s5p - update iv after AES-CBC op end").
>
> I.e., there were many years where the kernel's CTR_DRBG code (if it
> were to have actually been used) repeated outputs on some platforms.
>
> AES-CTR also uses a 128-bit counter, which creates overflow edge cases
> that are sometimes gotten wrong. E.g. see commit 009b30ac7444
> ("crypto: vmx - CTR: always increment IV as quadword").
>
> So, while switching to CTR_DRBG for performance reasons isn't completely
> out of the question (notably BoringSSL uses it), it would take quite a
> bit more work to create a solid implementation of it in the kernel,
> including a more solid implementation of AES-CTR itself (in lib/crypto/,
> with a scalar bit-sliced fallback, etc). Since HMAC_DRBG has always
> been the default NIST DRBG variant in the kernel and is in a better
> state, let's just standardize on it for now.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> arch/m68k/configs/amiga_defconfig | 1 -
> arch/m68k/configs/apollo_defconfig | 1 -
> arch/m68k/configs/atari_defconfig | 1 -
> arch/m68k/configs/bvme6000_defconfig | 1 -
> arch/m68k/configs/hp300_defconfig | 1 -
> arch/m68k/configs/mac_defconfig | 1 -
> arch/m68k/configs/multi_defconfig | 1 -
> arch/m68k/configs/mvme147_defconfig | 1 -
> arch/m68k/configs/mvme16x_defconfig | 1 -
> arch/m68k/configs/q40_defconfig | 1 -
> arch/m68k/configs/sun3_defconfig | 1 -
> arch/m68k/configs/sun3x_defconfig | 1 -
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> # m68k
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 6:33 ` [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG Eric Biggers
2026-04-20 8:07 ` Geert Uytterhoeven
@ 2026-04-20 14:40 ` Stephan Mueller
2026-04-20 17:47 ` Eric Biggers
1 sibling, 1 reply; 50+ messages in thread
From: Stephan Mueller @ 2026-04-20 14:40 UTC (permalink / raw)
To: linux-crypto, Herbert Xu, Eric Biggers
Cc: linux-kernel, Jason A . Donenfeld, Eric Biggers
Am Montag, 20. April 2026, 08:33:56 Mitteleuropäische Sommerzeit schrieb Eric
Biggers:
Hi Eric,
> Remove the support for CTR_DRBG. It's likely unused code, seeing as
> HMAC_DRBG is always enabled and prioritized over it unless
> NETLINK_CRYPTO is used to change the algorithm priorities.
Just as an FYI: the CTR DRBG implementation is used, because it provides
massive superior performance. The CTR DRBG implementation is lined up to use
the AES-CTR mode directly. If you have an accelerated implementation like AES-
NI or ARM-CE, your performance increase is significant.
For example, on my M4 development system, the generation of 1GB of data from
the CTR DRBG takes 90ms whereas the HMAC DRBG takes more than 4 seconds.
The default of HMAC DRBG, however, was used since it has a simple logic and
smaller code.
Ciao
Stephan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 14:40 ` Stephan Mueller
@ 2026-04-20 17:47 ` Eric Biggers
2026-04-20 19:54 ` Stephan Mueller
0 siblings, 1 reply; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 17:47 UTC (permalink / raw)
To: Stephan Mueller
Cc: linux-crypto, Herbert Xu, linux-kernel, Jason A . Donenfeld
On Mon, Apr 20, 2026 at 04:40:18PM +0200, Stephan Mueller wrote:
> Am Montag, 20. April 2026, 08:33:56 Mitteleuropäische Sommerzeit schrieb Eric
> Biggers:
>
> Hi Eric,
>
> > Remove the support for CTR_DRBG. It's likely unused code, seeing as
> > HMAC_DRBG is always enabled and prioritized over it unless
> > NETLINK_CRYPTO is used to change the algorithm priorities.
>
> Just as an FYI: the CTR DRBG implementation is used, because it provides
> massive superior performance. The CTR DRBG implementation is lined up to use
> the AES-CTR mode directly. If you have an accelerated implementation like AES-
> NI or ARM-CE, your performance increase is significant.
>
> For example, on my M4 development system, the generation of 1GB of data from
> the CTR DRBG takes 90ms whereas the HMAC DRBG takes more than 4 seconds.
>
> The default of HMAC DRBG, however, was used since it has a simple logic and
> smaller code.
I guess I have to ask: by "it is used", do you mean that it's used by a
significant number of users, or is it more of a personal thing where you
happen to be personally using it? Note that the only way to select it
is directly by driver name (which has no in-kernel users), by running a
custom userspace program that uses NETLINK_CRYPTO to modify the
algorithm priorities. I'm sure you know how to do the NETLINK_CRYPTO
thing, but this very much seems like an idiosyncratic expert-level
configuration that isn't really used in practice, similar to some other
things that you've added like CONFIG_CRYPTO_JITTERENTROPY_MEMSIZE_*.
And even if it's being used, does it really need to be? Do you really
need more than 250 MB/s of "FIPS-approved" random numbers, and from the
kernel (not a userspace library)?
I also don't think we actually have much choice, given that we don't
currently have a reliably correct implementation of CTR_DRBG anyway, and
that takes priority over everything else. As I explained in detail in
this patch, this just hasn't been something that's ever been done. It
sometimes returns success on failure, it sometimes isn't constant-time,
and it used to repeat output on some platforms (and maybe even still
does). Not particularly great properties for a RNG.
While a reliable implementation of CTR_DRBG is possible (BoringSSL does
it, for example), the reality is it would take quite a bit more work.
- Eric
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 17:47 ` Eric Biggers
@ 2026-04-20 19:54 ` Stephan Mueller
2026-04-20 20:56 ` Eric Biggers
0 siblings, 1 reply; 50+ messages in thread
From: Stephan Mueller @ 2026-04-20 19:54 UTC (permalink / raw)
To: Eric Biggers; +Cc: linux-crypto, Herbert Xu, linux-kernel, Jason A . Donenfeld
Am Montag, 20. April 2026, 19:47:13 Mitteleuropäische Sommerzeit schrieb Eric
Biggers:
Hi Eric,
> On Mon, Apr 20, 2026 at 04:40:18PM +0200, Stephan Mueller wrote:
> > Am Montag, 20. April 2026, 08:33:56 Mitteleuropäische Sommerzeit schrieb
> > Eric Biggers:
> >
> > Hi Eric,
> >
> > > Remove the support for CTR_DRBG. It's likely unused code, seeing as
> > > HMAC_DRBG is always enabled and prioritized over it unless
> > > NETLINK_CRYPTO is used to change the algorithm priorities.
> >
> > Just as an FYI: the CTR DRBG implementation is used, because it provides
> > massive superior performance. The CTR DRBG implementation is lined up to
> > use the AES-CTR mode directly. If you have an accelerated implementation
> > like AES- NI or ARM-CE, your performance increase is significant.
> >
> > For example, on my M4 development system, the generation of 1GB of data
> > from the CTR DRBG takes 90ms whereas the HMAC DRBG takes more than 4
> > seconds.
> >
> > The default of HMAC DRBG, however, was used since it has a simple logic
> > and
> > smaller code.
>
> I guess I have to ask: by "it is used", do you mean that it's used by a
> significant number of users, or is it more of a personal thing where you
> happen to be personally using it?
I see it being used by vendors that I work with. I neither have concrete
numbers or do I know how many machines are covered by it.
For any personal operations, I use the XDRBG anyway that would be separately
implemented and provided.
> Note that the only way to select it
The selection would always be done during compile time for those vendors.
> is directly by driver name (which has no in-kernel users), by running a
> custom userspace program that uses NETLINK_CRYPTO to modify the
> algorithm priorities. I'm sure you know how to do the NETLINK_CRYPTO
> thing, but this very much seems like an idiosyncratic expert-level
> configuration that isn't really used in practice, similar to some other
> things that you've added like CONFIG_CRYPTO_JITTERENTROPY_MEMSIZE_*.
>
> And even if it's being used, does it really need to be? Do you really
> need more than 250 MB/s of "FIPS-approved" random numbers, and from the
> kernel (not a userspace library)?
The performance also implies that for a given number of bits, it uses less CPU
cycles.
Ciao
Stephan
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 19:54 ` Stephan Mueller
@ 2026-04-20 20:56 ` Eric Biggers
2026-04-20 20:58 ` Stephan Mueller
0 siblings, 1 reply; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 20:56 UTC (permalink / raw)
To: Stephan Mueller
Cc: linux-crypto, Herbert Xu, linux-kernel, Jason A . Donenfeld
On Mon, Apr 20, 2026 at 09:54:48PM +0200, Stephan Mueller wrote:
> > Note that the only way to select it
>
> The selection would always be done during compile time for those vendors.
Again, even if someone were to want to do that for some reason, the
status quo is that it's not supported. That is, currently you can set
CONFIG_CRYPTO_DRBG_CTR=y, but "stdrng" is still HMAC_DRBG regardless.
- Eric
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG
2026-04-20 20:56 ` Eric Biggers
@ 2026-04-20 20:58 ` Stephan Mueller
0 siblings, 0 replies; 50+ messages in thread
From: Stephan Mueller @ 2026-04-20 20:58 UTC (permalink / raw)
To: Eric Biggers; +Cc: linux-crypto, Herbert Xu, linux-kernel, Jason A . Donenfeld
Am Montag, 20. April 2026, 22:56:07 Mitteleuropäische Sommerzeit schrieb Eric
Biggers:
Hi Eric,
> On Mon, Apr 20, 2026 at 09:54:48PM +0200, Stephan Mueller wrote:
> > > Note that the only way to select it
> >
> > The selection would always be done during compile time for those vendors.
>
> Again, even if someone were to want to do that for some reason, the
> status quo is that it's not supported. That is, currently you can set
> CONFIG_CRYPTO_DRBG_CTR=y, but "stdrng" is still HMAC_DRBG regardless.
Changes to the priorities were applied to their kernels.
>
> - Eric
Ciao
Stephan
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 13/38] crypto: drbg - Remove support for HASH_DRBG
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (11 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 12/38] crypto: drbg - Remove support for CTR_DRBG Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 14/38] crypto: drbg - Flatten the DRBG menu Eric Biggers
` (24 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Remove the support for HASH_DRBG. It's likely unused code, seeing as
HMAC_DRBG is always enabled and prioritized over it unless
NETLINK_CRYPTO is used to change the algorithm priorities.
There's also no compelling reason to support more than one of
[HMAC_DRBG, HASH_DRBG, CTR_DRBG]. By definition, callers cannot tell
any difference in their outputs. And all are FIPS-certifiable, which is
the only point of the kernel's NIST DRBGs anyway.
Switching to HASH_DRBG doesn't seem all that compelling, either. For
one, it's more complex than HMAC_DRBG.
Thus, let's just drop HASH_DRBG support and focus on HMAC_DRBG.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
Documentation/crypto/api-samples.rst | 2 +-
Documentation/crypto/userspace-if.rst | 2 +-
arch/m68k/configs/amiga_defconfig | 1 -
arch/m68k/configs/apollo_defconfig | 1 -
arch/m68k/configs/atari_defconfig | 1 -
arch/m68k/configs/bvme6000_defconfig | 1 -
arch/m68k/configs/hp300_defconfig | 1 -
arch/m68k/configs/mac_defconfig | 1 -
arch/m68k/configs/multi_defconfig | 1 -
arch/m68k/configs/mvme147_defconfig | 1 -
arch/m68k/configs/mvme16x_defconfig | 1 -
arch/m68k/configs/q40_defconfig | 1 -
arch/m68k/configs/sun3_defconfig | 1 -
arch/m68k/configs/sun3x_defconfig | 1 -
arch/mips/configs/decstation_64_defconfig | 1 -
arch/mips/configs/decstation_defconfig | 1 -
arch/mips/configs/decstation_r4k_defconfig | 1 -
crypto/Kconfig | 8 -
crypto/drbg.c | 348 +--------------------
crypto/testmgr.c | 32 --
crypto/testmgr.h | 296 ------------------
21 files changed, 8 insertions(+), 695 deletions(-)
diff --git a/Documentation/crypto/api-samples.rst b/Documentation/crypto/api-samples.rst
index e923f17bc2bd..388bb7d7a460 100644
--- a/Documentation/crypto/api-samples.rst
+++ b/Documentation/crypto/api-samples.rst
@@ -157,11 +157,11 @@ Code Example For Random Number Generator Usage
static int get_random_numbers(u8 *buf, unsigned int len)
{
struct crypto_rng *rng = NULL;
- char *drbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */
+ char *drbg = "stdrng";
int ret;
if (!buf || !len) {
pr_debug("No output buffer provided\n");
return -EINVAL;
diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst
index 021759198fe7..a3b13ff83cb3 100644
--- a/Documentation/crypto/userspace-if.rst
+++ b/Documentation/crypto/userspace-if.rst
@@ -295,11 +295,11 @@ follows:
::
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "rng", /* this selects the random number generator */
- .salg_name = "drbg_nopr_sha256" /* this is the RNG name */
+ .salg_name = "stdrng" /* this is the RNG name */
};
Depending on the RNG type, the RNG must be seeded. The seed is provided
using the setsockopt interface to set the key. The SP800-90A DRBGs do
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index a8ca9023caf3..a886494c5a30 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -548,11 +548,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 5c6610d9e80a..14c6298b1175 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -503,11 +503,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 4d080f6f3ddf..86a5c69b3655 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -525,11 +525,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index c61fc9d13d30..b3828dc6ee25 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -495,11 +495,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 2bc20cfdfcf6..6b890c6bcf35 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -505,11 +505,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index e03877efc7e6..1a7694486c08 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -524,11 +524,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index d613bfedee8a..468f0dab58ad 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -611,11 +611,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index fe343a8f69f5..ef6e94e5abcd 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -495,11 +495,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index c5803f67f30b..cdb8cb030c33 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -496,11 +496,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 619518c30e0b..a6af67707e9e 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -514,11 +514,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 530fa722e3b2..1d8233ebb454 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -493,11 +493,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index f282e05bc8f9..8366a1d850b0 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -493,11 +493,10 @@ CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
CONFIG_CRYPTO_ZSTD=m
-CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/configs/decstation_64_defconfig b/arch/mips/configs/decstation_64_defconfig
index 6712143a2842..509515cf4751 100644
--- a/arch/mips/configs/decstation_64_defconfig
+++ b/arch/mips/configs/decstation_64_defconfig
@@ -197,9 +197,8 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-CONFIG_CRYPTO_DRBG_HASH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index 1a31bbb99839..3a17c080292f 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -192,10 +192,9 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-CONFIG_CRYPTO_DRBG_HASH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/arch/mips/configs/decstation_r4k_defconfig b/arch/mips/configs/decstation_r4k_defconfig
index 8ff71ca43bfb..7f5823663702 100644
--- a/arch/mips/configs/decstation_r4k_defconfig
+++ b/arch/mips/configs/decstation_r4k_defconfig
@@ -192,10 +192,9 @@ CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-CONFIG_CRYPTO_DRBG_HASH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_FTRACE is not set
diff --git a/crypto/Kconfig b/crypto/Kconfig
index b16a1aa95c46..14519474a67b 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1120,18 +1120,10 @@ menuconfig CRYPTO_DRBG_MENU
In the following submenu, one or more of the DRBG types must be selected.
if CRYPTO_DRBG_MENU
-config CRYPTO_DRBG_HASH
- bool "Hash_DRBG"
- select CRYPTO_SHA256
- help
- Hash_DRBG variant as defined in NIST SP800-90A.
-
- This uses the SHA-1, SHA-256, SHA-384, or SHA-512 hash algorithms.
-
config CRYPTO_DRBG
tristate
default CRYPTO_DRBG_MENU
select CRYPTO_HMAC
select CRYPTO_JITTERENTROPY
diff --git a/crypto/drbg.c b/crypto/drbg.c
index b29090bb59bc..6301eb2e304c 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1,10 +1,9 @@
/*
* DRBG: Deterministic Random Bits Generator
* Based on NIST Recommended DRBG from NIST SP800-90A with the following
* properties:
- * * Hash DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
* * 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
*
@@ -131,21 +130,17 @@ enum drbg_seed_state {
DRBG_SEED_STATE_FULL,
};
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
- unsigned char *V; /* internal state 10.1.1.1 1a) */
+ unsigned char *V; /* internal state -- 10.1.2.1 1a */
unsigned char *Vbuf;
- /* hash: static value 10.1.1.1 1b) hmac: key */
- unsigned char *C;
+ unsigned char *C; /* current key -- 10.1.2.1 1b */
unsigned char *Cbuf;
- /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */
+ /* Number of RNG requests since last reseed -- 10.1.2.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;
void *priv_data; /* Cipher handle */
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
bool pr; /* Prediction resistance enabled? */
@@ -192,24 +187,21 @@ static inline size_t drbg_max_requests(struct drbg_state *drbg)
return (1<<20);
}
/* DRBG type flags */
#define DRBG_HMAC ((drbg_flag_t)1<<1)
-#define DRBG_HASH ((drbg_flag_t)1<<2)
-#define DRBG_TYPE_MASK (DRBG_HMAC | DRBG_HASH)
+#define DRBG_TYPE_MASK DRBG_HMAC
/* DRBG strength flags */
#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
DRBG_STRENGTH256)
enum drbg_prefixes {
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
- DRBG_PREFIX2,
- DRBG_PREFIX3
};
/***************************************************************
* Backend cipher definitions available to DRBG
***************************************************************/
@@ -220,31 +212,10 @@ enum drbg_prefixes {
* they are defined in this array (see drbg_fill_array).
*
* Thus, the favored DRBGs are the latest entries in this array.
*/
static const struct drbg_core drbg_cores[] = {
-#ifdef CONFIG_CRYPTO_DRBG_HASH
- {
- .flags = DRBG_HASH | DRBG_STRENGTH256,
- .statelen = 111, /* 888 bits */
- .blocklen_bytes = 48,
- .cra_name = "sha384",
- .backend_cra_name = "sha384",
- }, {
- .flags = DRBG_HASH | DRBG_STRENGTH256,
- .statelen = 111, /* 888 bits */
- .blocklen_bytes = 64,
- .cra_name = "sha512",
- .backend_cra_name = "sha512",
- }, {
- .flags = DRBG_HASH | DRBG_STRENGTH256,
- .statelen = 55, /* 440 bits */
- .blocklen_bytes = 32,
- .cra_name = "sha256",
- .backend_cra_name = "sha256",
- },
-#endif /* CONFIG_CRYPTO_DRBG_HASH */
{
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 48, /* block length of cipher */
.blocklen_bytes = 48,
.cra_name = "hmac_sha384",
@@ -301,11 +272,10 @@ static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
const unsigned char *key);
static int drbg_init_hash_kernel(struct drbg_state *drbg);
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
-#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");
@@ -413,284 +383,10 @@ static const struct drbg_state_ops drbg_hmac_ops = {
.generate = drbg_hmac_generate,
.crypto_init = drbg_init_hash_kernel,
.crypto_fini = drbg_fini_hash_kernel,
};
-/******************************************************************
- * Hash DRBG callback functions
- ******************************************************************/
-
-#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");
-
-/*
- * Increment buffer
- *
- * @dst buffer to increment
- * @add value to add
- */
-static inline void drbg_add_buf(unsigned char *dst, size_t dstlen,
- const unsigned char *add, size_t addlen)
-{
- /* implied: dstlen > addlen */
- unsigned char *dstptr;
- const unsigned char *addptr;
- unsigned int remainder = 0;
- size_t len = addlen;
-
- dstptr = dst + (dstlen-1);
- addptr = add + (addlen-1);
- while (len) {
- remainder += *dstptr + *addptr;
- *dstptr = remainder & 0xff;
- remainder >>= 8;
- len--; dstptr--; addptr--;
- }
- len = dstlen - addlen;
- while (len && remainder > 0) {
- remainder = *dstptr + 1;
- *dstptr = remainder & 0xff;
- remainder >>= 8;
- len--; dstptr--;
- }
-}
-
-/*
- * scratchpad usage: as drbg_hash_update and drbg_hash_df are used
- * interlinked, the scratchpad is used as follows:
- * drbg_hash_update
- * start: drbg->scratchpad
- * length: drbg_statelen(drbg)
- * drbg_hash_df:
- * start: drbg->scratchpad + drbg_statelen(drbg)
- * length: drbg_blocklen(drbg)
- *
- * drbg_hash_process_addtl uses the scratchpad, but fully completes
- * before either of the functions mentioned before are invoked. Therefore,
- * drbg_hash_process_addtl does not need to be specifically considered.
- */
-
-/* Derivation Function for Hash DRBG as defined in 10.4.1 */
-static int drbg_hash_df(struct drbg_state *drbg,
- unsigned char *outval, size_t outlen,
- struct list_head *entropylist)
-{
- int ret = 0;
- size_t len = 0;
- unsigned char input[5];
- unsigned char *tmp = drbg->scratchpad + drbg_statelen(drbg);
- struct drbg_string data;
-
- /* 10.4.1 step 3 */
- input[0] = 1;
- put_unaligned_be32(outlen * 8, &input[1]);
-
- /* 10.4.1 step 4.1 -- concatenation of data for input into hash */
- drbg_string_fill(&data, input, 5);
- list_add(&data.list, entropylist);
-
- /* 10.4.1 step 4 */
- while (len < outlen) {
- short blocklen = 0;
- /* 10.4.1 step 4.1 */
- ret = drbg_kcapi_hash(drbg, tmp, entropylist);
- if (ret)
- goto out;
- /* 10.4.1 step 4.2 */
- input[0]++;
- blocklen = (drbg_blocklen(drbg) < (outlen - len)) ?
- drbg_blocklen(drbg) : (outlen - len);
- memcpy(outval + len, tmp, blocklen);
- len += blocklen;
- }
-
-out:
- memset(tmp, 0, drbg_blocklen(drbg));
- return ret;
-}
-
-/* update function for Hash DRBG as defined in 10.1.1.2 / 10.1.1.3 */
-static int drbg_hash_update(struct drbg_state *drbg, struct list_head *seed,
- int reseed)
-{
- int ret = 0;
- struct drbg_string data1, data2;
- LIST_HEAD(datalist);
- LIST_HEAD(datalist2);
- unsigned char *V = drbg->scratchpad;
- unsigned char prefix = DRBG_PREFIX1;
-
- if (!seed)
- return -EINVAL;
-
- if (reseed) {
- /* 10.1.1.3 step 1 */
- memcpy(V, drbg->V, drbg_statelen(drbg));
- drbg_string_fill(&data1, &prefix, 1);
- list_add_tail(&data1.list, &datalist);
- drbg_string_fill(&data2, V, drbg_statelen(drbg));
- list_add_tail(&data2.list, &datalist);
- }
- list_splice_tail(seed, &datalist);
-
- /* 10.1.1.2 / 10.1.1.3 step 2 and 3 */
- ret = drbg_hash_df(drbg, drbg->V, drbg_statelen(drbg), &datalist);
- if (ret)
- goto out;
-
- /* 10.1.1.2 / 10.1.1.3 step 4 */
- prefix = DRBG_PREFIX0;
- drbg_string_fill(&data1, &prefix, 1);
- list_add_tail(&data1.list, &datalist2);
- drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
- list_add_tail(&data2.list, &datalist2);
- /* 10.1.1.2 / 10.1.1.3 step 4 */
- ret = drbg_hash_df(drbg, drbg->C, drbg_statelen(drbg), &datalist2);
-
-out:
- memset(drbg->scratchpad, 0, drbg_statelen(drbg));
- return ret;
-}
-
-/* processing of additional information string for Hash DRBG */
-static int drbg_hash_process_addtl(struct drbg_state *drbg,
- struct list_head *addtl)
-{
- int ret = 0;
- struct drbg_string data1, data2;
- LIST_HEAD(datalist);
- unsigned char prefix = DRBG_PREFIX2;
-
- /* 10.1.1.4 step 2 */
- if (!addtl || list_empty(addtl))
- return 0;
-
- /* 10.1.1.4 step 2a */
- drbg_string_fill(&data1, &prefix, 1);
- drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
- list_add_tail(&data1.list, &datalist);
- list_add_tail(&data2.list, &datalist);
- list_splice_tail(addtl, &datalist);
- ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
- if (ret)
- goto out;
-
- /* 10.1.1.4 step 2b */
- drbg_add_buf(drbg->V, drbg_statelen(drbg),
- drbg->scratchpad, drbg_blocklen(drbg));
-
-out:
- memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
- return ret;
-}
-
-/* Hashgen defined in 10.1.1.4 */
-static int drbg_hash_hashgen(struct drbg_state *drbg,
- unsigned char *buf,
- unsigned int buflen)
-{
- int len = 0;
- int ret = 0;
- unsigned char *src = drbg->scratchpad;
- unsigned char *dst = drbg->scratchpad + drbg_statelen(drbg);
- struct drbg_string data;
- LIST_HEAD(datalist);
-
- /* 10.1.1.4 step hashgen 2 */
- memcpy(src, drbg->V, drbg_statelen(drbg));
-
- drbg_string_fill(&data, src, drbg_statelen(drbg));
- list_add_tail(&data.list, &datalist);
- while (len < buflen) {
- unsigned int outlen = 0;
- /* 10.1.1.4 step hashgen 4.1 */
- ret = drbg_kcapi_hash(drbg, dst, &datalist);
- if (ret) {
- len = ret;
- goto out;
- }
- outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
- drbg_blocklen(drbg) : (buflen - len);
- /* 10.1.1.4 step hashgen 4.2 */
- memcpy(buf + len, dst, outlen);
- len += outlen;
- /* 10.1.1.4 hashgen step 4.3 */
- if (len < buflen)
- crypto_inc(src, drbg_statelen(drbg));
- }
-
-out:
- memset(drbg->scratchpad, 0,
- (drbg_statelen(drbg) + drbg_blocklen(drbg)));
- return len;
-}
-
-/* generate function for Hash DRBG as defined in 10.1.1.4 */
-static int drbg_hash_generate(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
- struct list_head *addtl)
-{
- int len = 0;
- int ret = 0;
- union {
- unsigned char req[8];
- __be64 req_int;
- } u;
- unsigned char prefix = DRBG_PREFIX3;
- struct drbg_string data1, data2;
- LIST_HEAD(datalist);
-
- /* 10.1.1.4 step 2 */
- ret = drbg_hash_process_addtl(drbg, addtl);
- if (ret)
- return ret;
- /* 10.1.1.4 step 3 */
- len = drbg_hash_hashgen(drbg, buf, buflen);
-
- /* this is the value H as documented in 10.1.1.4 */
- /* 10.1.1.4 step 4 */
- drbg_string_fill(&data1, &prefix, 1);
- list_add_tail(&data1.list, &datalist);
- drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
- list_add_tail(&data2.list, &datalist);
- ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
- if (ret) {
- len = ret;
- goto out;
- }
-
- /* 10.1.1.4 step 5 */
- drbg_add_buf(drbg->V, drbg_statelen(drbg),
- drbg->scratchpad, drbg_blocklen(drbg));
- drbg_add_buf(drbg->V, drbg_statelen(drbg),
- drbg->C, drbg_statelen(drbg));
- u.req_int = cpu_to_be64(drbg->reseed_ctr);
- drbg_add_buf(drbg->V, drbg_statelen(drbg), u.req, 8);
-
-out:
- memset(drbg->scratchpad, 0, drbg_blocklen(drbg));
- return len;
-}
-
-/*
- * scratchpad usage: as update and generate are used isolated, both
- * can use the scratchpad
- */
-static const struct drbg_state_ops drbg_hash_ops = {
- .update = drbg_hash_update,
- .generate = drbg_hash_generate,
- .crypto_init = drbg_init_hash_kernel,
- .crypto_fini = drbg_fini_hash_kernel,
-};
-#endif /* CONFIG_CRYPTO_DRBG_HASH */
-
/******************************************************************
* Functions common for DRBG implementations
******************************************************************/
static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
@@ -701,11 +397,10 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
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. */
@@ -898,12 +593,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
drbg->Vbuf = NULL;
drbg->V = NULL;
kfree_sensitive(drbg->Cbuf);
drbg->Cbuf = NULL;
drbg->C = NULL;
- kfree_sensitive(drbg->scratchpadbuf);
- drbg->scratchpadbuf = NULL;
drbg->reseed_ctr = 0;
drbg->d_ops = NULL;
drbg->core = NULL;
}
@@ -912,21 +605,15 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
* The DRBG state structure must already be allocated.
*/
static inline int drbg_alloc_state(struct drbg_state *drbg)
{
int ret = -ENOMEM;
- unsigned int sb_size = 0;
switch (drbg->core->flags & DRBG_TYPE_MASK) {
case DRBG_HMAC:
drbg->d_ops = &drbg_hmac_ops;
break;
-#ifdef CONFIG_CRYPTO_DRBG_HASH
- case DRBG_HASH:
- drbg->d_ops = &drbg_hash_ops;
- break;
-#endif /* CONFIG_CRYPTO_DRBG_HASH */
default:
ret = -EOPNOTSUPP;
goto err;
}
@@ -944,24 +631,10 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
if (!drbg->Cbuf) {
ret = -ENOMEM;
goto fini;
}
drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
- /* scratchpad is only generated for Hash */
- if (drbg->core->flags & DRBG_HMAC)
- sb_size = 0;
- else
- sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg);
-
- if (0 < sb_size) {
- drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL);
- if (!drbg->scratchpadbuf) {
- ret = -ENOMEM;
- goto fini;
- }
- drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1);
- }
return 0;
fini:
drbg->d_ops->crypto_fini(drbg);
@@ -1059,11 +732,11 @@ static int drbg_generate(struct drbg_state *drbg,
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.1.2.5 step 7 */
drbg->reseed_ctr++;
if (0 >= len)
goto err;
/*
@@ -1447,13 +1120,10 @@ static inline int __init drbg_healthcheck_sanity(void)
/* only perform test in FIPS mode */
if (!fips_enabled)
return 0;
-#ifdef CONFIG_CRYPTO_DRBG_HASH
- drbg_convert_tfm_core("drbg_nopr_sha256", &coreref, &pr);
-#endif
drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr);
drbg = kzalloc_obj(struct drbg_state);
if (!drbg)
return -ENOMEM;
@@ -1575,15 +1245,9 @@ static void __exit drbg_exit(void)
crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
}
module_init(drbg_init);
module_exit(drbg_exit);
-#ifndef CRYPTO_DRBG_HASH_STRING
-#define CRYPTO_DRBG_HASH_STRING ""
-#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
-MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
- "using following cores: "
- CRYPTO_DRBG_HASH_STRING
- CRYPTO_DRBG_HMAC_STRING);
+MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG)");
MODULE_ALIAS_CRYPTO("stdrng");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index dbc1e1fb4bd0..fdc5051b73c5 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4658,26 +4658,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
.drbg = __VECS(drbg_nopr_hmac_sha512_tv_template)
}
- }, {
- .alg = "drbg_nopr_sha256",
- .test = alg_test_drbg,
- .fips_allowed = 1,
- .suite = {
- .drbg = __VECS(drbg_nopr_sha256_tv_template)
- }
- }, {
- /* covered by drbg_nopr_sha256 test */
- .alg = "drbg_nopr_sha384",
- .test = alg_test_null,
- .fips_allowed = 1
- }, {
- .alg = "drbg_nopr_sha512",
- .fips_allowed = 1,
- .test = alg_test_null,
}, {
.alg = "drbg_pr_hmac_sha256",
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
@@ -4690,26 +4674,10 @@ static const struct alg_test_desc alg_test_descs[] = {
.fips_allowed = 1
}, {
.alg = "drbg_pr_hmac_sha512",
.test = alg_test_null,
.fips_allowed = 1,
- }, {
- .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",
- .test = alg_test_null,
- .fips_allowed = 1
- }, {
- .alg = "drbg_pr_sha512",
- .fips_allowed = 1,
- .test = alg_test_null,
}, {
.alg = "ecb(aes)",
.generic_driver = "ecb(aes-lib)",
.test = alg_test_skcipher,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index a86275b61b6a..d44a4c1e7313 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -23420,176 +23420,10 @@ static const struct aead_testvec aegis128_tv_template[] = {
"\x78\x93\xec\xfc\xf4\xff\xe1\x2d",
.clen = 24,
},
};
-/*
- * 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"
@@ -23744,140 +23578,10 @@ static const struct drbg_testvec drbg_pr_hmac_sha256_tv_template[] = {
"\xd1\x81\xe9\xf8\xeb\x30\x8f\x6f",
.perslen = 32,
},
};
-/*
- * 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).
- */
-static const struct drbg_testvec drbg_nopr_sha256_tv_template[] = {
- {
- .entropy = (unsigned char *)
- "\xa6\x5a\xd0\xf3\x45\xdb\x4e\x0e\xff\xe8\x75\xc3"
- "\xa2\xe7\x1f\x42\xc7\x12\x9d\x62\x0f\xf5\xc1\x19"
- "\xa9\xef\x55\xf0\x51\x85\xe0\xfb\x85\x81\xf9\x31"
- "\x75\x17\x27\x6e\x06\xe9\x60\x7d\xdb\xcb\xcc\x2e",
- .entropylen = 48,
- .expected = (unsigned char *)
- "\xd3\xe1\x60\xc3\x5b\x99\xf3\x40\xb2\x62\x82\x64"
- "\xd1\x75\x10\x60\xe0\x04\x5d\xa3\x83\xff\x57\xa5"
- "\x7d\x73\xa6\x73\xd2\xb8\xd8\x0d\xaa\xf6\xa6\xc3"
- "\x5a\x91\xbb\x45\x79\xd7\x3f\xd0\xc8\xfe\xd1\x11"
- "\xb0\x39\x13\x06\x82\x8a\xdf\xed\x52\x8f\x01\x81"
- "\x21\xb3\xfe\xbd\xc3\x43\xe7\x97\xb8\x7d\xbb\x63"
- "\xdb\x13\x33\xde\xd9\xd1\xec\xe1\x77\xcf\xa6\xb7"
- "\x1f\xe8\xab\x1d\xa4\x66\x24\xed\x64\x15\xe5\x1c"
- "\xcd\xe2\xc7\xca\x86\xe2\x83\x99\x0e\xea\xeb\x91"
- "\x12\x04\x15\x52\x8b\x22\x95\x91\x02\x81\xb0\x2d"
- "\xd4\x31\xf4\xc9\xf7\x04\x27\xdf",
- .expectedlen = 128,
- .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"
- "\x8a\x93\x17\xae\x19\xc3\x4c\xc3\xd6\xca\xa3\x2d"
- "\x16\xfc\x42\xd2\x2d\xd5\x6f\x56\xcc\x1d\x30\xff"
- "\x9e\x06\x3e\x09\xce\x58\xe6\x9a\x35\xb3\xa6\x56",
- .entropylen = 48,
- .expected = (unsigned char *)
- "\x71\x7b\x93\x46\x1a\x40\xaa\x35\xa4\xaa\xc5\xe7"
- "\x6d\x5b\x5b\x8a\xa0\xdf\x39\x7d\xae\x71\x58\x5b"
- "\x3c\x7c\xb4\xf0\x89\xfa\x4a\x8c\xa9\x5c\x54\xc0"
- "\x40\xdf\xbc\xce\x26\x81\x34\xf8\xba\x7d\x1c\xe8"
- "\xad\x21\xe0\x74\xcf\x48\x84\x30\x1f\xa1\xd5\x4f"
- "\x81\x42\x2f\xf4\xdb\x0b\x23\xf8\x73\x27\xb8\x1d"
- "\x42\xf8\x44\x58\xd8\x5b\x29\x27\x0a\xf8\x69\x59"
- "\xb5\x78\x44\xeb\x9e\xe0\x68\x6f\x42\x9a\xb0\x5b"
- "\xe0\x4e\xcb\x6a\xaa\xe2\xd2\xd5\x33\x25\x3e\xe0"
- "\x6c\xc7\x6a\x07\xa5\x03\x83\x9f\xe2\x8b\xd1\x1c"
- "\x70\xa8\x07\x59\x97\xeb\xf6\xbe",
- .expectedlen = 128,
- .addtla = (unsigned char *)
- "\xf4\xd5\x98\x3d\xa8\xfc\xfa\x37\xb7\x54\x67\x73"
- "\xc7\xc3\xdd\x47\x34\x71\x02\x5d\xc1\xa0\xd3\x10"
- "\xc1\x8b\xbd\xf5\x66\x34\x6f\xdd",
- .addtlb = (unsigned char *)
- "\xf7\x9e\x6a\x56\x0e\x73\xe9\xd9\x7a\xd1\x69\xe0"
- "\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[] = {
{
.entropy = (unsigned char *)
"\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
"\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 14/38] crypto: drbg - Flatten the DRBG menu
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (12 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 13/38] crypto: drbg - Remove support for HASH_DRBG Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 6:33 ` [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512 Eric Biggers
` (23 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Now that the menuconfig CRYPTO_DRBG_MENU has no options in it other than
the hidden symbol CRYPTO_DRBG, remove it and move CRYPTO_DRBG to its
parent menu. Give CRYPTO_DRBG an appropriate prompt and help text.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 14519474a67b..1abb3d356458 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1111,28 +1111,21 @@ config CRYPTO_ZSTD
endmenu
menu "Random number generation"
-menuconfig CRYPTO_DRBG_MENU
- tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)"
- help
- DRBG (Deterministic Random Bit Generator) (NIST SP800-90A)
-
- In the following submenu, one or more of the DRBG types must be selected.
-
-if CRYPTO_DRBG_MENU
-
config CRYPTO_DRBG
- tristate
- default CRYPTO_DRBG_MENU
+ tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)"
select CRYPTO_HMAC
select CRYPTO_JITTERENTROPY
select CRYPTO_RNG
select CRYPTO_SHA512
+ help
+ DRBG (Deterministic Random Bit Generator) (NIST SP800-90A)
-endif # if CRYPTO_DRBG_MENU
+ Enable this only if you need it for a FIPS 140 certification.
+ It's otherwise redundant with the kernel's regular RNG.
config CRYPTO_JITTERENTROPY
tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)"
select CRYPTO_LIB_SHA3
select CRYPTO_RNG
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (13 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 14/38] crypto: drbg - Flatten the DRBG menu Eric Biggers
@ 2026-04-20 6:33 ` Eric Biggers
2026-04-20 16:04 ` Joachim Vandersmissen
2026-04-20 6:34 ` [PATCH 16/38] crypto: testmgr - Update test for drbg_nopr_hmac_sha512 Eric Biggers
` (22 subsequent siblings)
37 siblings, 1 reply; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:33 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Add a test for drbg_pr_hmac_sha512, which previously didn't have a test.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/testmgr.c | 5 +-
crypto/testmgr.h | 199 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index fdc5051b73c5..5a984b3b9a9b 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4672,12 +4672,15 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "drbg_pr_hmac_sha384",
.test = alg_test_null,
.fips_allowed = 1
}, {
.alg = "drbg_pr_hmac_sha512",
- .test = alg_test_null,
+ .test = alg_test_drbg,
.fips_allowed = 1,
+ .suite = {
+ .drbg = __VECS(drbg_pr_hmac_sha512_tv_template)
+ }
}, {
.alg = "ecb(aes)",
.generic_driver = "ecb(aes-lib)",
.test = alg_test_skcipher,
.fips_allowed = 1,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index d44a4c1e7313..77935a457313 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -23700,10 +23700,209 @@ static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
"\x36\x60\x3b\xca\x37\xc9\xee\x29",
.perslen = 32,
},
};
+static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = {
+ /*
+ * Borrowed from the first applicable test vector from ACVP:
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L1161
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L271
+ */
+ {
+ /* .entropy = ACVP entropyInput || nonce */
+ .entropy = "\x9B\xE9\xB2\x87\xA3\x9A\x08\x44\x1D\x67\x82\x20"
+ "\xC9\x53\xFB\xEB\xA4\xB9\x0F\x44\x0B\x98\x33\x18"
+ "\xAC\x6E\x25\x4A\x85\x83\x2D\x26\x21\x9F\x93\x64"
+ "\xC8\x5A\x5F\x72\xDB\x88\x45\x96\x71\x41\xF4\xBF"
+ "\x6E\xA7\x98\x00\x9D\xD1\x0C\x2E\x4D\x7A\xE2\x03"
+ "\x0D\xE3\xCD\x62\xFE\xF3\x62\xBD\x12\x69\x92\x3D"
+ "\xBA\xAC\x15\x17\xC7\x80\x93\x8E\x72\x32\x2D\x52"
+ "\xE5\x2C\x19\x84\x5C\xA5\xCE\x5B\x98\x19\x1F\xF1"
+ "\x9F\x0C\x17\x04\xD0\x66\xF1\x9B\xFA\x7E\x2C\xB6"
+ "\x55\x68\xD4\x1B\xD6\x7A\x1D\x2C\xD4\x6D\x6E\x15"
+ "\xF7\x32\x23\x04\x05\x8C\xBB\xE6\x63\x6B\x80\x9B"
+ "\x9C\x69\x09\x8F\x5F\x02\xBF\x53\x42\x11\xB7\x80"
+ "\xAA\xD4\xE8\x54\x00\x83\x5C\x20\xA8\xB3\x6E\xD9"
+ "\xF5\x51\x9E\xB9\xD1\x6E\xC7\x0C\xE9\x7F\xF0\xBF"
+ "\xCE\x1D\xB0\x31\x8D\x16\xC9\x65\x0C\x18\x55\xA4"
+ "\x46\x8D\x54\x2B\x78\x69\x1B\x8C\x29\xD7\xAC\x0F"
+ "\x34\x4D\x69\x0B\x76\xC3\x98\x00\x78\x2F\xE2\x54"
+ "\xAF\xD5\x8A\xC3\x40\x97\xB1\xA2\x60\xD3\x07\x3B"
+ "\x7A\x3E\xD0\x82\x80\x68\xEE\xB0\x72\x5F\x07\x17"
+ "\xD9\x0A\xFC\xBD\xBA\xB6\x77\x4E\xC9\xCE\x6A\x48"
+ "\xEB\x9C\xF5\x18\x88\x1E\x6E\x3B\x65\x43\x16\x73"
+ "\x80\x53\xB7\xF0\x7E\xAB\x23\x19\x1E\x75\x60\x36"
+ "\xAF\x39\xC0\xCF\x0F\x6D\x7F\x90\xB2\x50\xD5\x37"
+ "\x58\x6D\x5C\x95\x78\x25\x8D\x3A\x40\xAB\xF6\x7B"
+ "\x85\x86\xBB\x48\x5E\x1C\x99\xC1\xD3\x4E\x85\xE5"
+ "\xB4\xE7\x61\xF3\x7D\x56\x1F\x77\xCF\x3C\x76\x3A"
+ "\xF4\x82\x36\xB7\x37\x33\x84\x34\xBA\x0E\xE2\xE1"
+ "\xAF\x0C\xD2\xAE\x97\x5C\x80\xD4\xD2\xFD\x37\x71"
+ "\xC8\x70\x04\x29\x8B\x44\xB9\xD7\xC9\x8F\xE7\x99"
+ "\x94\x9E\xFC\x49\x66\x24\xCB\x8B\x41\x40\x66\xC5"
+ "\xA4\x00\xD5\x3F\x68\xDD\xB5\xA5\x62\x96\x7C\xAC"
+ "\x63\x58\x95\x85\x99\x24\x21\x15\xD2\x76\xAF\x6D",
+ .entropylen = 384,
+ .pers = "\xDD\x07\x10\x10\x17\x34\xD5\xBD\x43\xAF\x03\x79\xE4"
+ "\x64\x2C\x58\x06\xEA\xE0\x39\xDA\x42\x96\x16\x0B\xF9"
+ "\xB8\xCE\x57\x7D\x53\x67\xBF\xF8\x0C\x40\x02\xB2\x77"
+ "\x16\xD5\x23\x75\x9F\x6A\x42\x0E\xE8\xCC\xD0\x9F\x40"
+ "\x64\xE9\x3B\xE9\x48\x13\xC3\x8E\x4B\xAB\xE1\xB9\x4F"
+ "\x6D\xBB\xF2\x4C\xF8\x29\xA5\x2B\x44\x23\x15\x2C\xDE"
+ "\x2A\xCF\x88\x04\x7A\x38\x37\xA2\xD5\x7B\xEA\x59\x39"
+ "\x2C\x58\xA2\x5B\xF9\x39\xA2\x7E\x94\x11\x97\xEC\x47"
+ "\x08\xD6\xE2\x39\x65\x26\x43\x81\x3F\x1B\x31\xA6\xA4"
+ "\x1A\x5C\xCD\x02\xCC\x89\x38\x3F\x32\x7C\x0E\x7E\x88"
+ "\x3B\x6F\x60\x69\xEA\xBA\xAA\x1F\x53\x93\x70\xD7\x48"
+ "\x74\x91\x79\x5E\xD4\xB0\xD9\x82\x74\x12\xDE\xFE\xFB"
+ "\x51\x96\x66\x5C\x6A\x53\x11\xAD\x9A\xD4\xFA\x9D\xF0"
+ "\xE2\x7F\x26\x8F\x6F\xAC\x00\xC8\xDB\xCF\xA5\x8E\xE6"
+ "\x61\x8F\x36\xD6\x44\x5B\x07\xDA\x9C\x2A\x46\xE3\x03"
+ "\x1C\xD8\x11\x4F\x61\x1F\xEC\xBA\x12\x68\xB9\x4B\x57"
+ "\x39\x05\xD6\xEE\xC1\xAC\x3F\x6D\x6F\xE9\xBF\xEA\x36"
+ "\x1A\x8A\xAA\xF4\xE8\xE0\xDB\xC6\xE5\x06\x9F\xC9\x91"
+ "\x52\xCD\x53\xD0\x78\xF6\xC1\x7B\x75\x91\x85\x91\x13"
+ "\x26\xBE\xC9\x02\xDE\xB0\x19\xF2\x71",
+ .perslen = 256,
+
+ .entpra = "\xDB\xBA\x25\xC7\x02\x0D\x3D\x95\x9C\xEB\xF5\x42"
+ "\x52\x3A\x6B\xDA\xE8\xAF\xE9\x3D\x76\x2A\x9E\xB5"
+ "\xD7\xE7\x5D\xC9\xB8\x1F\x3A\xC2\x91\x95\x9D\xFD"
+ "\xE5\x48\x5F\x63\xD8\x84\x44\x82\x6A\x71\xF9\xDD"
+ "\xAF\x4B\xE2\x28\xB4\x30\xCF\x78\xB7\x0B\x0F\x61"
+ "\x71\x16\x1A\xE0\x6D\x5F\xB4\x4B\x17\x1A\x26\xCA"
+ "\xD8\x9D\x6D\x46\xA3\x56\xC0\xE7\x49\xCF\xE0\xD2"
+ "\xFF\xA8\x22\x45\xE0\xB4\x18\x0B\x13\x37\x01\x46"
+ "\xCB\xE7\xD8\x2A\x59\x43\xAD\x90\x1E\xE1\xD0\xD7"
+ "\x76\xB0\x2D\xCF\x17\x23\x99\x73\x5D\xE5\xC7\x46"
+ "\x8A\x0D\x8E\xC4\xAB\x45\xAC\xA8\x74\xE4\xF7\xD0"
+ "\x26\xD7\x0A\xE2\x43\x3D\xB8\xC7\xEE\xAD\x53\x6F"
+ "\x78\xC3\x51\xC0\xE0\x76\x2A\xC2\xB7\xFE\x02\x64"
+ "\x25\xF0\xCE\xD7\xA9\xBF\x85\xCA\x20\xA6\x93\x68"
+ "\xE3\x79\xE9\x88\xA8\x7F\x45\x8D\x71\xB4\xB4\x79"
+ "\x1C\x56\x68\xF9\xAE\x18\x76\xB9\x3F\xEE\x5B\x2C"
+ "\xC6\x61\x47\x34\x3B\xC5\x24\x2D\x3C\x6D\x16\x48"
+ "\x70\xD9\xDB\x2E\xB8\x42\x52\x81\x1C\x94\x39\xF0"
+ "\xF4\xC0\x8F\x44\xD3\xCF\xD5\xF9\xC1\x59\x61\x83"
+ "\xAE\xFD\xD0\xC4\x35\xD1\x0E\x55\x46\x5C\xBA\x3D"
+ "\x5C\x4A\x89\x15\xE8\x1D\x86\x28\xE5\xF5\x31\x0B"
+ "\x89\x59\xFE\x4A\xC3\x5D\xA5\x2A\x16\x37\x78\x41"
+ "\x58\x3A\x9E\xA3\xBD\x1F\xE6\x25\xCC\x18\x9E\xD2"
+ "\x1A\x99\x56\x66\x83\x78\xBB\x27\x3E\x28\xFE\xD4"
+ "\x74\xCB\x75\x2D\x82\x86\x55\xFB\x1C\xA4\xAF\x3F"
+ "\x84\x0A\xA0\xA1\x1C\x70\x34\x87\x2E\x73\x15\x38"
+ "\x8A\x27\xB1\x6C\x33\x95\xE5\x07",
+ .entprb = "\x38\xF2\xC4\x8F\x4B\x9C\x2F\x03\x67\x8C\x8A\x47"
+ "\xE1\xF2\x18\xC5\xB8\x4C\x05\x77\x77\x15\xA8\x94"
+ "\x1F\x1F\x45\x6D\xD0\xEF\x60\x67\x63\x12\x5D\x38"
+ "\x89\x22\x76\xF5\xF2\xC4\xE1\x15\x26\x7E\x8F\x52"
+ "\x79\x1E\x96\x71\xCD\xE7\x32\x95\x2B\x4E\xB2\xC2"
+ "\x92\x21\xC7\x48\xA2\xB1\xC5\x71\x44\x91\xE4\x4F"
+ "\xBE\xD3\x5E\xA9\xAB\xD3\xE2\xD1\xE2\xD8\x8F\x98"
+ "\x38\x03\x18\x29\x84\xA2\xCA\x6E\x72\x34\xC9\x51"
+ "\x6D\x8C\xE8\x09\x50\x71\x2A\x08\xB7\xCF\x74\xE6"
+ "\x11\xB6\x38\xF5\xBC\x24\xF7\x5B\x73\x34\xD5\x8B"
+ "\xBB\x15\xE3\x6F\x9A\x9B\x1E\x32\xB9\x6F\x5F\xE3"
+ "\xC9\x9F\xF6\xD9\x33\x03\xCD\x0D\x8E\xD4\x3F\x67"
+ "\x11\x65\x0A\x90\x67\x83\xC1\xCC\x70\xB1\xA9\x46"
+ "\x4B\x5E\x0B\x84\xDC\x02\xBA\x50\x1D\x4A\x5B\xC7"
+ "\xB4\x5E\xDF\x35\x01\x45\x3D\x64\x5C\x2E\xCD\xA6"
+ "\x20\xFB\x35\x74\xC0\x7C\x2D\x24\x66\xAB\x38\x12"
+ "\x38\xCE\x52\xCB\x38\x9B\x95\xDE\x0C\x2A\x8C\x9D"
+ "\xF7\x81\x48\x9E\xD6\x10\xF1\x83\x71\x44\x53\x2F"
+ "\xCE\xF3\xEC\xB3\x29\x67\xF1\x41\xFC\xD6\xB6\x49"
+ "\xE3\x13\x74\x4D\xB2\x3E\xEA\x73\x2B\x03\x68\xAC"
+ "\x2F\x57\x8C\x58\xEC\x34\xE9\xEF\x18\x36\xDE\xAD"
+ "\xE9\x48\x1D\xF7\x9E\xB7\xA1\x60\x2E\x78\xF5\x62"
+ "\x68\xDD\xB8\x5B\x33\x6B\x66\xAD\xA1\xD5\xFB\x46"
+ "\x5E\x8F\xF8\x9D\x37\xE5\xC2\xD8\x76\xDC\x2B\x6A"
+ "\x99\x1E\xDF\x91\xB1\x0A\x81\x2A\x9D\xEB\xE7\xE4"
+ "\xD1\x21\xD4\xDA\x0E\x55\x8A\x14\xB2\xB6\x15\x7D"
+ "\x48\x52\x6A\xB0\xA2\x92\x4D\x50",
+ .entprlen = 320,
+ .addtla = "\xC2\x89\x7C\x07\x46\x74\x02\x2C\xEA\xAD\xFD\x74"
+ "\x0C\x40\xEF\xA2\x95\x64\x6B\xC4\x2D\xED\xF4\x16"
+ "\x26\x25\x06\xB3\x36\x6B\xD8\x9A\x5F\xF4\x25\xC1"
+ "\xC3\x69\x3F\x7A\x19\xB7\x02\xA6\xCC\x3B\xA2\x4E"
+ "\x05\xA1\x1C\x7B\x2D\xAD\x44\xE7\x4A\x40\x71\x85"
+ "\xEF\x1C\xE4\xEC\x54\xCA\xB0\xAF\x8F\xF5\x43\xB1"
+ "\xE0\x99\x71\x71\xD4\x3E\x56\x97\xAA\xF5\xD0\x1A"
+ "\x58\x2D\x65\x0F\xA4\xB4\xB6\x07\x1B\x1F\x13\x8B"
+ "\x29\xD6\xE5\x23\xD3\x4D\x43\xD6\xBC\x74\xA8\x92"
+ "\xBD\xE9\x9B\x01\x47\x8C\xA5\x02\xA8\x0D\xC3\x3A"
+ "\xED\x83\xFD\xD2\xCB\xFF\x25\x89\x2C\x2F\x5B\x70"
+ "\x3F\x9E\x24\x50\xF8\x78\x28\x1B\x67\x52\x92\xA2"
+ "\x87\x81\x07\x40\xA9\x40\xBA\x84\x47\x25\xC1\xF7"
+ "\x9E\x3B\x4E\xE4\x8F\x10\xE5\x50\x8B\x22\x83\x4F"
+ "\xCD\x4E\x42\x63\x92\x0A\x5F\xAF\x7A\x9B\x0E\x1A"
+ "\xE3\xB4\x99\x11\x7F\xE6\x93\xC3\xED\xF1\x9F\x3A",
+ .addtlb = "\x1E\x75\xB6\x70\x60\xFD\xE6\xD1\xC7\xA5\x74\xCF"
+ "\xA7\x50\x17\xAE\xDD\xC4\x6E\xC4\xE0\x15\xF0\x3B"
+ "\xF7\x1C\x46\x45\xEE\x60\x66\x48\x1D\x2C\x36\xCC"
+ "\x95\x3E\xB7\xEB\x1B\xFF\x8C\xC0\x78\x6D\x56\x3A"
+ "\xC7\x24\x18\x9E\x7C\xA1\x60\x54\x41\x4B\xAF\x18"
+ "\xE8\x02\xD1\x54\x65\xEC\x3D\xFD\x8B\xDF\xD2\xF5"
+ "\x62\xEA\x66\x41\x6A\x32\x87\xA6\x34\x2F\x48\xBF"
+ "\xB5\xCC\x35\x5A\x2A\xC1\xAB\x68\x34\x1A\xD6\x82"
+ "\x40\xF7\xF2\x00\x14\x8B\x69\x0F\xE4\xCD\x6B\xB1"
+ "\xFC\x8B\x16\xEC\xB4\xE3\x33\xBF\x84\x12\x4B\x58"
+ "\xED\x51\x88\xF5\xEF\xB6\xC3\xCE\x9B\x63\xCC\x80"
+ "\x1F\x3C\x8A\x67\xEE\xCD\xD2\x01\x25\x22\xAC\xB3"
+ "\xB6\x9B\x1F\xF8\xE8\x71\xE6\x0D\x78\x11\x3C\x9E"
+ "\xF2\x57\xDC\xB6\xCF\x90\xD3\xA8\x3E\xCD\x88\xD4"
+ "\xDC\x1C\x31\x6B\x1F\xC3\x6A\x29\xF0\x7B\x4C\xCC"
+ "\x6D\x92\x5E\x6F\x0C\x0B\x4D\xA7\x10\x66\x84\x1F",
+ .addtllen = 192,
+
+ .expected = "\xAA\x76\x91\xAE\x99\xCD\x8D\x83\x49\x9D\xC5\x51"
+ "\xA5\x95\xC6\x9D\xAD\x4B\x40\x2B\x5F\x8C\x30\x5D"
+ "\x1E\x89\x58\xD1\x8A\x86\xF9\x61\x2C\x45\x41\x8E"
+ "\xC5\xC6\x0E\x33\x7C\xFE\x91\x71\xC9\x53\x76\xD6"
+ "\xC2\x8D\x05\x09\xB8\x2A\x2B\x9B\x36\x1D\x31\xD7"
+ "\x50\x45\xB1\x08\x58\xC4\x99\x25\xEA\x2F\x18\xDB"
+ "\x34\x8A\x02\xD8\x38\xDD\x7B\x9E\x0E\xEF\x9C\x45"
+ "\xC7\x4F\x7E\x36\x3A\x90\x8B\x41\x51\x4A\x1B\xE9"
+ "\x8A\x61\xE9\xB5\x4E\xA5\xE2\xBD\x16\x59\x61\x0F"
+ "\x9C\x5A\x63\xA7\x87\x79\x5C\x0A\x16\xDF\x6D\x88"
+ "\x11\x25\x56\x8B\x5D\xA6\xF8\x4F\xB9\x01\x19\xAE"
+ "\x57\x3B\xC4\x06\xBB\xE7\xCB\xAF\xB3\x8D\xE2\x40"
+ "\xED\x42\x29\xB3\x0D\x64\x20\xF2\x66\x58\xB1\xDD"
+ "\x59\xB1\x39\x7C\xD9\xB2\x34\x08\x53\x9B\x3A\xB7"
+ "\x18\x35\xD0\x90\x7F\xB5\x30\xF2\x27\xA0\x90\x63"
+ "\x6F\xF2\x72\x49\xBF\xD0\xAE\x4A\xF4\xCA\xB3\x1A"
+ "\xAE\x7F\x93\xF3\xB9\x84\x99\x09\x50\xB9\xA0\x43"
+ "\x4F\x83\x33\x92\xA5\xC7\x25\x44\x6A\x74\xF4\xFA"
+ "\xBA\x60\x43\x13\x97\x53\x99\x98\xA3\x05\x02\xC1"
+ "\x03\xDF\x53\x76\x9E\x74\xE7\xA0\xB5\xD7\xA7\x87"
+ "\x1E\x00\x1D\x29\x47\x8F\x65\x4E\x0F\x76\xCA\xA9"
+ "\x2A\xC5\x05\x4F\xA6\xFE\x96\xC6\x81\xC0\x55\xFC"
+ "\x92\x89\xA6\x81\xF0\x37\xF1\x41\xA6\x88\x0B\x01"
+ "\xE0\xA5\x78\x4C\xF4\x61\xA7\x91\xD8\x4B\xE9\x2C"
+ "\xF0\x68\xEE\x46\x41\xD2\x74\xE5\x5F\x6F\x1F\xE6"
+ "\xBE\x5C\xB1\x3C\x60\x1A\xAA\xB9\x88\x3C\xB9\x1C"
+ "\xCD\x67\x78\x1F\x45\x18\xE7\x8B\xBD\xE4\x24\xDA"
+ "\xA8\x26\xD1\x03\xF1\xC7\x6B\x28\x62\xAB\x5C\xAB"
+ "\x98\xCA\xFB\xCB\x0B\x2D\x01\xD9\xC1\xA6\xFA\x91"
+ "\x71\x3D\x9B\x3B\x60\xEB\xD7\xA2\x61\xC1\x92\x60"
+ "\xB1\x02\x44\x0C\x97\x70\x77\x83\xF9\x35\xEA\x24"
+ "\x85\xF8\x0A\x32\xA2\xC7\x05\x40\x90\x83\x4F\x87"
+ "\x57\x66\xB5\xDE\xEE\xFF\x8B\x01\xBC\x96\xB0\xC5"
+ "\x29\xB6\xC1\xF0\x11\x31\x51\x11\xB0\xC2\x0F\x08"
+ "\xCF\x09\x69\x74\xE1\x0D\x6C\x0A\x10\xD0\x73\xF0"
+ "\x8E\xDC\x5F\xB1\xBD\x47\x8A\xA7\x90\xB3\x08\x86"
+ "\xD2\xE4\x58\xE5\x68\x33\x67\x3B\x37\xF1\x28\x28"
+ "\x59\x91\xB5\x5F\x8D\x84\x54\xCE\x18\x76\xE3\x5C"
+ "\x55\x37\x8E\x10\x34\x9B\x6E\x1F\x73\x88\x31\xBF"
+ "\x0D\x5C\xED\x7A\xBC\xF2\xCE\x7A\x2E\x2E\xE7\x04"
+ "\xE7\xF2\x8F\x33\xCC\x06\x77\x96\xBB\xA8\x65\x03"
+ "\x26\x79\xC0\xF0\x52\x3B\xD4\xF2\x5D\x00\xE4\x80"
+ "\x7F\x78\xC0\x45\x29\x55\xCA\x63",
+ .expectedlen = 512,
+ }
+};
+
/* Test vector obtained during NIST ACVP testing */
static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = {
{
.entropy = (unsigned char *)
"\xDF\xB0\xF2\x18\xF0\x78\x07\x01\x29\xA4\x29\x26"
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512
2026-04-20 6:33 ` [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512 Eric Biggers
@ 2026-04-20 16:04 ` Joachim Vandersmissen
2026-04-20 17:06 ` Eric Biggers
0 siblings, 1 reply; 50+ messages in thread
From: Joachim Vandersmissen @ 2026-04-20 16:04 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld
Hi Eric,
Was there any particular reason for adding this test? I don't think
there's any _explicit_ requirement for having tests for both non-PR and
PR DRBG variants.
In fact, as part of this very comprehensive cleanup, maybe the PR
variants of the DRBGs should be removed as well? Is anyone actually
using those? PR variants are (were) registered before the non-PR
variants, so non-PR was always used by default.
Kind regards,
Joachim
On 4/20/26 1:33 AM, Eric Biggers wrote:
> Add a test for drbg_pr_hmac_sha512, which previously didn't have a test.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> crypto/testmgr.c | 5 +-
> crypto/testmgr.h | 199 +++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 203 insertions(+), 1 deletion(-)
>
> diff --git a/crypto/testmgr.c b/crypto/testmgr.c
> index fdc5051b73c5..5a984b3b9a9b 100644
> --- a/crypto/testmgr.c
> +++ b/crypto/testmgr.c
> @@ -4672,12 +4672,15 @@ static const struct alg_test_desc alg_test_descs[] = {
> .alg = "drbg_pr_hmac_sha384",
> .test = alg_test_null,
> .fips_allowed = 1
> }, {
> .alg = "drbg_pr_hmac_sha512",
> - .test = alg_test_null,
> + .test = alg_test_drbg,
> .fips_allowed = 1,
> + .suite = {
> + .drbg = __VECS(drbg_pr_hmac_sha512_tv_template)
> + }
> }, {
> .alg = "ecb(aes)",
> .generic_driver = "ecb(aes-lib)",
> .test = alg_test_skcipher,
> .fips_allowed = 1,
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index d44a4c1e7313..77935a457313 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -23700,10 +23700,209 @@ static const struct drbg_testvec drbg_nopr_hmac_sha256_tv_template[] = {
> "\x36\x60\x3b\xca\x37\xc9\xee\x29",
> .perslen = 32,
> },
> };
>
> +static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = {
> + /*
> + * Borrowed from the first applicable test vector from ACVP:
> + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L1161
> + * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L271
> + */
> + {
> + /* .entropy = ACVP entropyInput || nonce */
> + .entropy = "\x9B\xE9\xB2\x87\xA3\x9A\x08\x44\x1D\x67\x82\x20"
> + "\xC9\x53\xFB\xEB\xA4\xB9\x0F\x44\x0B\x98\x33\x18"
> + "\xAC\x6E\x25\x4A\x85\x83\x2D\x26\x21\x9F\x93\x64"
> + "\xC8\x5A\x5F\x72\xDB\x88\x45\x96\x71\x41\xF4\xBF"
> + "\x6E\xA7\x98\x00\x9D\xD1\x0C\x2E\x4D\x7A\xE2\x03"
> + "\x0D\xE3\xCD\x62\xFE\xF3\x62\xBD\x12\x69\x92\x3D"
> + "\xBA\xAC\x15\x17\xC7\x80\x93\x8E\x72\x32\x2D\x52"
> + "\xE5\x2C\x19\x84\x5C\xA5\xCE\x5B\x98\x19\x1F\xF1"
> + "\x9F\x0C\x17\x04\xD0\x66\xF1\x9B\xFA\x7E\x2C\xB6"
> + "\x55\x68\xD4\x1B\xD6\x7A\x1D\x2C\xD4\x6D\x6E\x15"
> + "\xF7\x32\x23\x04\x05\x8C\xBB\xE6\x63\x6B\x80\x9B"
> + "\x9C\x69\x09\x8F\x5F\x02\xBF\x53\x42\x11\xB7\x80"
> + "\xAA\xD4\xE8\x54\x00\x83\x5C\x20\xA8\xB3\x6E\xD9"
> + "\xF5\x51\x9E\xB9\xD1\x6E\xC7\x0C\xE9\x7F\xF0\xBF"
> + "\xCE\x1D\xB0\x31\x8D\x16\xC9\x65\x0C\x18\x55\xA4"
> + "\x46\x8D\x54\x2B\x78\x69\x1B\x8C\x29\xD7\xAC\x0F"
> + "\x34\x4D\x69\x0B\x76\xC3\x98\x00\x78\x2F\xE2\x54"
> + "\xAF\xD5\x8A\xC3\x40\x97\xB1\xA2\x60\xD3\x07\x3B"
> + "\x7A\x3E\xD0\x82\x80\x68\xEE\xB0\x72\x5F\x07\x17"
> + "\xD9\x0A\xFC\xBD\xBA\xB6\x77\x4E\xC9\xCE\x6A\x48"
> + "\xEB\x9C\xF5\x18\x88\x1E\x6E\x3B\x65\x43\x16\x73"
> + "\x80\x53\xB7\xF0\x7E\xAB\x23\x19\x1E\x75\x60\x36"
> + "\xAF\x39\xC0\xCF\x0F\x6D\x7F\x90\xB2\x50\xD5\x37"
> + "\x58\x6D\x5C\x95\x78\x25\x8D\x3A\x40\xAB\xF6\x7B"
> + "\x85\x86\xBB\x48\x5E\x1C\x99\xC1\xD3\x4E\x85\xE5"
> + "\xB4\xE7\x61\xF3\x7D\x56\x1F\x77\xCF\x3C\x76\x3A"
> + "\xF4\x82\x36\xB7\x37\x33\x84\x34\xBA\x0E\xE2\xE1"
> + "\xAF\x0C\xD2\xAE\x97\x5C\x80\xD4\xD2\xFD\x37\x71"
> + "\xC8\x70\x04\x29\x8B\x44\xB9\xD7\xC9\x8F\xE7\x99"
> + "\x94\x9E\xFC\x49\x66\x24\xCB\x8B\x41\x40\x66\xC5"
> + "\xA4\x00\xD5\x3F\x68\xDD\xB5\xA5\x62\x96\x7C\xAC"
> + "\x63\x58\x95\x85\x99\x24\x21\x15\xD2\x76\xAF\x6D",
> + .entropylen = 384,
> + .pers = "\xDD\x07\x10\x10\x17\x34\xD5\xBD\x43\xAF\x03\x79\xE4"
> + "\x64\x2C\x58\x06\xEA\xE0\x39\xDA\x42\x96\x16\x0B\xF9"
> + "\xB8\xCE\x57\x7D\x53\x67\xBF\xF8\x0C\x40\x02\xB2\x77"
> + "\x16\xD5\x23\x75\x9F\x6A\x42\x0E\xE8\xCC\xD0\x9F\x40"
> + "\x64\xE9\x3B\xE9\x48\x13\xC3\x8E\x4B\xAB\xE1\xB9\x4F"
> + "\x6D\xBB\xF2\x4C\xF8\x29\xA5\x2B\x44\x23\x15\x2C\xDE"
> + "\x2A\xCF\x88\x04\x7A\x38\x37\xA2\xD5\x7B\xEA\x59\x39"
> + "\x2C\x58\xA2\x5B\xF9\x39\xA2\x7E\x94\x11\x97\xEC\x47"
> + "\x08\xD6\xE2\x39\x65\x26\x43\x81\x3F\x1B\x31\xA6\xA4"
> + "\x1A\x5C\xCD\x02\xCC\x89\x38\x3F\x32\x7C\x0E\x7E\x88"
> + "\x3B\x6F\x60\x69\xEA\xBA\xAA\x1F\x53\x93\x70\xD7\x48"
> + "\x74\x91\x79\x5E\xD4\xB0\xD9\x82\x74\x12\xDE\xFE\xFB"
> + "\x51\x96\x66\x5C\x6A\x53\x11\xAD\x9A\xD4\xFA\x9D\xF0"
> + "\xE2\x7F\x26\x8F\x6F\xAC\x00\xC8\xDB\xCF\xA5\x8E\xE6"
> + "\x61\x8F\x36\xD6\x44\x5B\x07\xDA\x9C\x2A\x46\xE3\x03"
> + "\x1C\xD8\x11\x4F\x61\x1F\xEC\xBA\x12\x68\xB9\x4B\x57"
> + "\x39\x05\xD6\xEE\xC1\xAC\x3F\x6D\x6F\xE9\xBF\xEA\x36"
> + "\x1A\x8A\xAA\xF4\xE8\xE0\xDB\xC6\xE5\x06\x9F\xC9\x91"
> + "\x52\xCD\x53\xD0\x78\xF6\xC1\x7B\x75\x91\x85\x91\x13"
> + "\x26\xBE\xC9\x02\xDE\xB0\x19\xF2\x71",
> + .perslen = 256,
> +
> + .entpra = "\xDB\xBA\x25\xC7\x02\x0D\x3D\x95\x9C\xEB\xF5\x42"
> + "\x52\x3A\x6B\xDA\xE8\xAF\xE9\x3D\x76\x2A\x9E\xB5"
> + "\xD7\xE7\x5D\xC9\xB8\x1F\x3A\xC2\x91\x95\x9D\xFD"
> + "\xE5\x48\x5F\x63\xD8\x84\x44\x82\x6A\x71\xF9\xDD"
> + "\xAF\x4B\xE2\x28\xB4\x30\xCF\x78\xB7\x0B\x0F\x61"
> + "\x71\x16\x1A\xE0\x6D\x5F\xB4\x4B\x17\x1A\x26\xCA"
> + "\xD8\x9D\x6D\x46\xA3\x56\xC0\xE7\x49\xCF\xE0\xD2"
> + "\xFF\xA8\x22\x45\xE0\xB4\x18\x0B\x13\x37\x01\x46"
> + "\xCB\xE7\xD8\x2A\x59\x43\xAD\x90\x1E\xE1\xD0\xD7"
> + "\x76\xB0\x2D\xCF\x17\x23\x99\x73\x5D\xE5\xC7\x46"
> + "\x8A\x0D\x8E\xC4\xAB\x45\xAC\xA8\x74\xE4\xF7\xD0"
> + "\x26\xD7\x0A\xE2\x43\x3D\xB8\xC7\xEE\xAD\x53\x6F"
> + "\x78\xC3\x51\xC0\xE0\x76\x2A\xC2\xB7\xFE\x02\x64"
> + "\x25\xF0\xCE\xD7\xA9\xBF\x85\xCA\x20\xA6\x93\x68"
> + "\xE3\x79\xE9\x88\xA8\x7F\x45\x8D\x71\xB4\xB4\x79"
> + "\x1C\x56\x68\xF9\xAE\x18\x76\xB9\x3F\xEE\x5B\x2C"
> + "\xC6\x61\x47\x34\x3B\xC5\x24\x2D\x3C\x6D\x16\x48"
> + "\x70\xD9\xDB\x2E\xB8\x42\x52\x81\x1C\x94\x39\xF0"
> + "\xF4\xC0\x8F\x44\xD3\xCF\xD5\xF9\xC1\x59\x61\x83"
> + "\xAE\xFD\xD0\xC4\x35\xD1\x0E\x55\x46\x5C\xBA\x3D"
> + "\x5C\x4A\x89\x15\xE8\x1D\x86\x28\xE5\xF5\x31\x0B"
> + "\x89\x59\xFE\x4A\xC3\x5D\xA5\x2A\x16\x37\x78\x41"
> + "\x58\x3A\x9E\xA3\xBD\x1F\xE6\x25\xCC\x18\x9E\xD2"
> + "\x1A\x99\x56\x66\x83\x78\xBB\x27\x3E\x28\xFE\xD4"
> + "\x74\xCB\x75\x2D\x82\x86\x55\xFB\x1C\xA4\xAF\x3F"
> + "\x84\x0A\xA0\xA1\x1C\x70\x34\x87\x2E\x73\x15\x38"
> + "\x8A\x27\xB1\x6C\x33\x95\xE5\x07",
> + .entprb = "\x38\xF2\xC4\x8F\x4B\x9C\x2F\x03\x67\x8C\x8A\x47"
> + "\xE1\xF2\x18\xC5\xB8\x4C\x05\x77\x77\x15\xA8\x94"
> + "\x1F\x1F\x45\x6D\xD0\xEF\x60\x67\x63\x12\x5D\x38"
> + "\x89\x22\x76\xF5\xF2\xC4\xE1\x15\x26\x7E\x8F\x52"
> + "\x79\x1E\x96\x71\xCD\xE7\x32\x95\x2B\x4E\xB2\xC2"
> + "\x92\x21\xC7\x48\xA2\xB1\xC5\x71\x44\x91\xE4\x4F"
> + "\xBE\xD3\x5E\xA9\xAB\xD3\xE2\xD1\xE2\xD8\x8F\x98"
> + "\x38\x03\x18\x29\x84\xA2\xCA\x6E\x72\x34\xC9\x51"
> + "\x6D\x8C\xE8\x09\x50\x71\x2A\x08\xB7\xCF\x74\xE6"
> + "\x11\xB6\x38\xF5\xBC\x24\xF7\x5B\x73\x34\xD5\x8B"
> + "\xBB\x15\xE3\x6F\x9A\x9B\x1E\x32\xB9\x6F\x5F\xE3"
> + "\xC9\x9F\xF6\xD9\x33\x03\xCD\x0D\x8E\xD4\x3F\x67"
> + "\x11\x65\x0A\x90\x67\x83\xC1\xCC\x70\xB1\xA9\x46"
> + "\x4B\x5E\x0B\x84\xDC\x02\xBA\x50\x1D\x4A\x5B\xC7"
> + "\xB4\x5E\xDF\x35\x01\x45\x3D\x64\x5C\x2E\xCD\xA6"
> + "\x20\xFB\x35\x74\xC0\x7C\x2D\x24\x66\xAB\x38\x12"
> + "\x38\xCE\x52\xCB\x38\x9B\x95\xDE\x0C\x2A\x8C\x9D"
> + "\xF7\x81\x48\x9E\xD6\x10\xF1\x83\x71\x44\x53\x2F"
> + "\xCE\xF3\xEC\xB3\x29\x67\xF1\x41\xFC\xD6\xB6\x49"
> + "\xE3\x13\x74\x4D\xB2\x3E\xEA\x73\x2B\x03\x68\xAC"
> + "\x2F\x57\x8C\x58\xEC\x34\xE9\xEF\x18\x36\xDE\xAD"
> + "\xE9\x48\x1D\xF7\x9E\xB7\xA1\x60\x2E\x78\xF5\x62"
> + "\x68\xDD\xB8\x5B\x33\x6B\x66\xAD\xA1\xD5\xFB\x46"
> + "\x5E\x8F\xF8\x9D\x37\xE5\xC2\xD8\x76\xDC\x2B\x6A"
> + "\x99\x1E\xDF\x91\xB1\x0A\x81\x2A\x9D\xEB\xE7\xE4"
> + "\xD1\x21\xD4\xDA\x0E\x55\x8A\x14\xB2\xB6\x15\x7D"
> + "\x48\x52\x6A\xB0\xA2\x92\x4D\x50",
> + .entprlen = 320,
> + .addtla = "\xC2\x89\x7C\x07\x46\x74\x02\x2C\xEA\xAD\xFD\x74"
> + "\x0C\x40\xEF\xA2\x95\x64\x6B\xC4\x2D\xED\xF4\x16"
> + "\x26\x25\x06\xB3\x36\x6B\xD8\x9A\x5F\xF4\x25\xC1"
> + "\xC3\x69\x3F\x7A\x19\xB7\x02\xA6\xCC\x3B\xA2\x4E"
> + "\x05\xA1\x1C\x7B\x2D\xAD\x44\xE7\x4A\x40\x71\x85"
> + "\xEF\x1C\xE4\xEC\x54\xCA\xB0\xAF\x8F\xF5\x43\xB1"
> + "\xE0\x99\x71\x71\xD4\x3E\x56\x97\xAA\xF5\xD0\x1A"
> + "\x58\x2D\x65\x0F\xA4\xB4\xB6\x07\x1B\x1F\x13\x8B"
> + "\x29\xD6\xE5\x23\xD3\x4D\x43\xD6\xBC\x74\xA8\x92"
> + "\xBD\xE9\x9B\x01\x47\x8C\xA5\x02\xA8\x0D\xC3\x3A"
> + "\xED\x83\xFD\xD2\xCB\xFF\x25\x89\x2C\x2F\x5B\x70"
> + "\x3F\x9E\x24\x50\xF8\x78\x28\x1B\x67\x52\x92\xA2"
> + "\x87\x81\x07\x40\xA9\x40\xBA\x84\x47\x25\xC1\xF7"
> + "\x9E\x3B\x4E\xE4\x8F\x10\xE5\x50\x8B\x22\x83\x4F"
> + "\xCD\x4E\x42\x63\x92\x0A\x5F\xAF\x7A\x9B\x0E\x1A"
> + "\xE3\xB4\x99\x11\x7F\xE6\x93\xC3\xED\xF1\x9F\x3A",
> + .addtlb = "\x1E\x75\xB6\x70\x60\xFD\xE6\xD1\xC7\xA5\x74\xCF"
> + "\xA7\x50\x17\xAE\xDD\xC4\x6E\xC4\xE0\x15\xF0\x3B"
> + "\xF7\x1C\x46\x45\xEE\x60\x66\x48\x1D\x2C\x36\xCC"
> + "\x95\x3E\xB7\xEB\x1B\xFF\x8C\xC0\x78\x6D\x56\x3A"
> + "\xC7\x24\x18\x9E\x7C\xA1\x60\x54\x41\x4B\xAF\x18"
> + "\xE8\x02\xD1\x54\x65\xEC\x3D\xFD\x8B\xDF\xD2\xF5"
> + "\x62\xEA\x66\x41\x6A\x32\x87\xA6\x34\x2F\x48\xBF"
> + "\xB5\xCC\x35\x5A\x2A\xC1\xAB\x68\x34\x1A\xD6\x82"
> + "\x40\xF7\xF2\x00\x14\x8B\x69\x0F\xE4\xCD\x6B\xB1"
> + "\xFC\x8B\x16\xEC\xB4\xE3\x33\xBF\x84\x12\x4B\x58"
> + "\xED\x51\x88\xF5\xEF\xB6\xC3\xCE\x9B\x63\xCC\x80"
> + "\x1F\x3C\x8A\x67\xEE\xCD\xD2\x01\x25\x22\xAC\xB3"
> + "\xB6\x9B\x1F\xF8\xE8\x71\xE6\x0D\x78\x11\x3C\x9E"
> + "\xF2\x57\xDC\xB6\xCF\x90\xD3\xA8\x3E\xCD\x88\xD4"
> + "\xDC\x1C\x31\x6B\x1F\xC3\x6A\x29\xF0\x7B\x4C\xCC"
> + "\x6D\x92\x5E\x6F\x0C\x0B\x4D\xA7\x10\x66\x84\x1F",
> + .addtllen = 192,
> +
> + .expected = "\xAA\x76\x91\xAE\x99\xCD\x8D\x83\x49\x9D\xC5\x51"
> + "\xA5\x95\xC6\x9D\xAD\x4B\x40\x2B\x5F\x8C\x30\x5D"
> + "\x1E\x89\x58\xD1\x8A\x86\xF9\x61\x2C\x45\x41\x8E"
> + "\xC5\xC6\x0E\x33\x7C\xFE\x91\x71\xC9\x53\x76\xD6"
> + "\xC2\x8D\x05\x09\xB8\x2A\x2B\x9B\x36\x1D\x31\xD7"
> + "\x50\x45\xB1\x08\x58\xC4\x99\x25\xEA\x2F\x18\xDB"
> + "\x34\x8A\x02\xD8\x38\xDD\x7B\x9E\x0E\xEF\x9C\x45"
> + "\xC7\x4F\x7E\x36\x3A\x90\x8B\x41\x51\x4A\x1B\xE9"
> + "\x8A\x61\xE9\xB5\x4E\xA5\xE2\xBD\x16\x59\x61\x0F"
> + "\x9C\x5A\x63\xA7\x87\x79\x5C\x0A\x16\xDF\x6D\x88"
> + "\x11\x25\x56\x8B\x5D\xA6\xF8\x4F\xB9\x01\x19\xAE"
> + "\x57\x3B\xC4\x06\xBB\xE7\xCB\xAF\xB3\x8D\xE2\x40"
> + "\xED\x42\x29\xB3\x0D\x64\x20\xF2\x66\x58\xB1\xDD"
> + "\x59\xB1\x39\x7C\xD9\xB2\x34\x08\x53\x9B\x3A\xB7"
> + "\x18\x35\xD0\x90\x7F\xB5\x30\xF2\x27\xA0\x90\x63"
> + "\x6F\xF2\x72\x49\xBF\xD0\xAE\x4A\xF4\xCA\xB3\x1A"
> + "\xAE\x7F\x93\xF3\xB9\x84\x99\x09\x50\xB9\xA0\x43"
> + "\x4F\x83\x33\x92\xA5\xC7\x25\x44\x6A\x74\xF4\xFA"
> + "\xBA\x60\x43\x13\x97\x53\x99\x98\xA3\x05\x02\xC1"
> + "\x03\xDF\x53\x76\x9E\x74\xE7\xA0\xB5\xD7\xA7\x87"
> + "\x1E\x00\x1D\x29\x47\x8F\x65\x4E\x0F\x76\xCA\xA9"
> + "\x2A\xC5\x05\x4F\xA6\xFE\x96\xC6\x81\xC0\x55\xFC"
> + "\x92\x89\xA6\x81\xF0\x37\xF1\x41\xA6\x88\x0B\x01"
> + "\xE0\xA5\x78\x4C\xF4\x61\xA7\x91\xD8\x4B\xE9\x2C"
> + "\xF0\x68\xEE\x46\x41\xD2\x74\xE5\x5F\x6F\x1F\xE6"
> + "\xBE\x5C\xB1\x3C\x60\x1A\xAA\xB9\x88\x3C\xB9\x1C"
> + "\xCD\x67\x78\x1F\x45\x18\xE7\x8B\xBD\xE4\x24\xDA"
> + "\xA8\x26\xD1\x03\xF1\xC7\x6B\x28\x62\xAB\x5C\xAB"
> + "\x98\xCA\xFB\xCB\x0B\x2D\x01\xD9\xC1\xA6\xFA\x91"
> + "\x71\x3D\x9B\x3B\x60\xEB\xD7\xA2\x61\xC1\x92\x60"
> + "\xB1\x02\x44\x0C\x97\x70\x77\x83\xF9\x35\xEA\x24"
> + "\x85\xF8\x0A\x32\xA2\xC7\x05\x40\x90\x83\x4F\x87"
> + "\x57\x66\xB5\xDE\xEE\xFF\x8B\x01\xBC\x96\xB0\xC5"
> + "\x29\xB6\xC1\xF0\x11\x31\x51\x11\xB0\xC2\x0F\x08"
> + "\xCF\x09\x69\x74\xE1\x0D\x6C\x0A\x10\xD0\x73\xF0"
> + "\x8E\xDC\x5F\xB1\xBD\x47\x8A\xA7\x90\xB3\x08\x86"
> + "\xD2\xE4\x58\xE5\x68\x33\x67\x3B\x37\xF1\x28\x28"
> + "\x59\x91\xB5\x5F\x8D\x84\x54\xCE\x18\x76\xE3\x5C"
> + "\x55\x37\x8E\x10\x34\x9B\x6E\x1F\x73\x88\x31\xBF"
> + "\x0D\x5C\xED\x7A\xBC\xF2\xCE\x7A\x2E\x2E\xE7\x04"
> + "\xE7\xF2\x8F\x33\xCC\x06\x77\x96\xBB\xA8\x65\x03"
> + "\x26\x79\xC0\xF0\x52\x3B\xD4\xF2\x5D\x00\xE4\x80"
> + "\x7F\x78\xC0\x45\x29\x55\xCA\x63",
> + .expectedlen = 512,
> + }
> +};
> +
> /* Test vector obtained during NIST ACVP testing */
> static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = {
> {
> .entropy = (unsigned char *)
> "\xDF\xB0\xF2\x18\xF0\x78\x07\x01\x29\xA4\x29\x26"
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512
2026-04-20 16:04 ` Joachim Vandersmissen
@ 2026-04-20 17:06 ` Eric Biggers
0 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 17:06 UTC (permalink / raw)
To: Joachim Vandersmissen
Cc: linux-crypto, Herbert Xu, linux-kernel, Stephan Mueller,
Jason A . Donenfeld
On Mon, Apr 20, 2026 at 11:04:51AM -0500, Joachim Vandersmissen wrote:
> Hi Eric,
>
> Was there any particular reason for adding this test? I don't think there's
> any _explicit_ requirement for having tests for both non-PR and PR DRBG
> variants.
Well, *if* predictionResistance=true continues to supported, then this
test is needed, considering that drbg_pr_hmac_sha256 and its test was
removed. Code always should be tested. (Also, considering FIPS, the
guidance I've gotten from a FIPS lab in the past is that
predictionResistance=true has to be tested if it's supported.)
> In fact, as part of this very comprehensive cleanup, maybe the PR variants
> of the DRBGs should be removed as well? Is anyone actually using those? PR
> variants are (were) registered before the non-PR variants, so non-PR was
> always used by default.
But yes, I think you're right that we should just go ahead and remove
support for predictionResistance=true too. I was a bit on the fence
about removing something that's "more" secure and also has a relatively
straightforward implementation. But since it's not the default, it
doesn't make much sense to use it, this test would have to be added, and
it's not required for FIPS certifications either (in fact it seems to
just make them a bit harder), it does seem like the right choice.
- Eric
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 16/38] crypto: testmgr - Update test for drbg_nopr_hmac_sha512
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (14 preceding siblings ...)
2026-04-20 6:33 ` [PATCH 15/38] crypto: testmgr - Add test for drbg_pr_hmac_sha512 Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 17/38] crypto: drbg - Remove support for HMAC-SHA256 and HMAC-SHA384 Eric Biggers
` (21 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Synchronize the drbg_nopr_hmac_sha512 test vector with the first test
vector from the latest ACVP json files, so that both of the DRBG test
vectors are pulled from a consistent source.
Note that the new test vector has a nonempty personalization string.
That should be helpful as well: Some FIPS labs require this, due to
their interpretation of SP800-90A 11.3.2 which says that a
"representative" value of the personalization string must be tested.
It also now does an explicit reseed, which makes it clearer that the
requirement to test "Reseed" is met, without having to interpret the
additional input processing as covering that.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/testmgr.c | 13 ++-
crypto/testmgr.h | 249 ++++++++++++++++++++++++++++++++++++++---------
2 files changed, 215 insertions(+), 47 deletions(-)
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 5a984b3b9a9b..ad4c2e66b812 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -3502,14 +3502,25 @@ static int drbg_cavs_test(const struct drbg_testvec *test, int pr,
}
crypto_rng_set_entropy(drng, test->entropy, test->entropylen);
ret = crypto_rng_reset(drng, test->pers, test->perslen);
if (ret) {
- printk(KERN_ERR "alg: drbg: Failed to reset rng\n");
+ printk(KERN_ERR "alg: drbg: Failed to instantiate rng\n");
goto outbuf;
}
+ if (test->ent_reseed_len) {
+ crypto_rng_set_entropy(drng, test->ent_reseed,
+ test->ent_reseed_len);
+ ret = crypto_rng_reset(drng, test->addtl_reseed,
+ test->addtl_reseed_len);
+ if (ret) {
+ printk(KERN_ERR "alg: drbg: Failed to reseed rng\n");
+ goto outbuf;
+ }
+ }
+
if (pr)
crypto_rng_set_entropy(drng, test->entpra, test->entprlen);
ret = crypto_rng_generate(drng, test->addtla, test->addtllen,
buf, test->expectedlen);
if (ret < 0) {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 77935a457313..fc70ca86d61f 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -118,20 +118,31 @@ struct aead_testvec {
int setauthsize_error;
int crypt_error;
};
struct drbg_testvec {
+ /* Instantiate */
const unsigned char *entropy;
size_t entropylen;
+ const unsigned char *pers;
+ size_t perslen;
+
+ /* Reseed (optional) */
+ const unsigned char *ent_reseed;
+ size_t ent_reseed_len;
+ const unsigned char *addtl_reseed;
+ size_t addtl_reseed_len;
+
+ /* Generate (twice) */
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;
+
+ /* Expected output from last call to Generate */
const unsigned char *expected;
size_t expectedlen;
};
struct akcipher_testvec {
@@ -23899,56 +23910,202 @@ static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = {
"\x7F\x78\xC0\x45\x29\x55\xCA\x63",
.expectedlen = 512,
}
};
-/* Test vector obtained during NIST ACVP testing */
static const struct drbg_testvec drbg_nopr_hmac_sha512_tv_template[] = {
+ /*
+ * Borrowed from the first applicable test vector from ACVP:
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L4596
+ * https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L986
+ */
{
- .entropy = (unsigned char *)
- "\xDF\xB0\xF2\x18\xF0\x78\x07\x01\x29\xA4\x29\x26"
- "\x2F\x8A\x34\xCB\x37\xEF\xEE\x41\xE6\x96\xF7\xFF"
- "\x61\x47\xD3\xED\x41\x97\xEF\x64\x0C\x48\x56\x5A"
- "\xE6\x40\x6E\x4A\x3B\x9E\x7F\xAC\x08\xEC\x25\xAE"
- "\x0B\x51\x0E\x2C\x44\x2E\xBD\xDB\x57\xD0\x4A\x6D"
- "\x80\x3E\x37\x0F",
- .entropylen = 64,
- .expected = (unsigned char *)
- "\x48\xc6\xa8\xdb\x09\xae\xde\x5d\x8c\x77\xf3\x52"
- "\x92\x71\xa7\xb9\x6d\x53\x6d\xa3\x73\xe3\x55\xb8"
- "\x39\xd6\x44\x2b\xee\xcb\xe1\x32\x15\x30\xbe\x4e"
- "\x9b\x1e\x06\xd1\x6b\xbf\xd5\x3e\xea\x7c\xf5\xaa"
- "\x4b\x05\xb5\xd3\xa7\xb2\xc4\xfe\xe7\x1b\xda\x11"
- "\x43\x98\x03\x70\x90\xbf\x6e\x43\x9b\xe4\x14\xef"
- "\x71\xa3\x2a\xef\x9f\x0d\xb9\xe3\x52\xf2\x89\xc9"
- "\x66\x9a\x60\x60\x99\x60\x62\x4c\xd6\x45\x52\x54"
- "\xe6\x32\xb2\x1b\xd4\x48\xb5\xa6\xf9\xba\xd3\xff"
- "\x29\xc5\x21\xe0\x91\x31\xe0\x38\x8c\x93\x0f\x3c"
- "\x30\x7b\x53\xa3\xc0\x7f\x2d\xc1\x39\xec\x69\x0e"
- "\xf2\x4a\x3c\x65\xcc\xed\x07\x2a\xf2\x33\x83\xdb"
- "\x10\x74\x96\x40\xa7\xc5\x1b\xde\x81\xca\x0b\x8f"
- "\x1e\x0a\x1a\x7a\xbf\x3c\x4a\xb8\x8c\xaf\x7b\x80"
- "\xb7\xdc\x5d\x0f\xef\x1b\x97\x6e\x3d\x17\x23\x5a"
- "\x31\xb9\x19\xcf\x5a\xc5\x00\x2a\xb6\xf3\x99\x34"
- "\x65\xee\xe9\x1c\x55\xa0\x3b\x07\x60\xc9\xc4\xe4"
- "\xf7\x57\x5c\x34\x9f\xc6\x31\x30\x3f\x23\xb2\x89"
- "\xc0\xe7\x50\xf3\xde\x59\xd1\x0e\xb3\x0f\x78\xcc"
- "\x7e\x54\x5e\x61\xf6\x86\x3d\xb3\x11\x94\x36\x3e"
- "\x61\x5c\x48\x99\xf6\x7b\x02\x9a\xdc\x6a\x28\xe6"
- "\xd1\xa7\xd1\xa3",
- .expectedlen = 256,
- .addtla = (unsigned char *)
- "\x6B\x0F\x4A\x48\x0B\x12\x85\xE4\x72\x23\x7F\x7F"
- "\x94\x7C\x24\x69\x14\x9F\xDC\x72\xA6\x33\xAD\x3C"
- "\x8C\x72\xC1\x88\x49\x59\x82\xC5",
- .addtlb = (unsigned char *)
- "\xC4\xAF\x36\x3D\xB8\x5D\x9D\xFA\x92\xF5\xC3\x3C"
- "\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,
+ /* .entropy = ACVP entropyInput || nonce */
+ .entropy = "\x47\x28\x33\x05\x82\xE8\xA7\x58\x05\xBD\x07\x9E"
+ "\xDB\x59\x87\x08\x3B\x82\x40\x70\xA1\xB7\x33\x4F"
+ "\x0F\x53\xBE\xF6\x98\x75\xFA\x21\x00\x04\xBC\x58"
+ "\x9B\xB1\xB3\xBC\x2A\xF6\xA4\x2A\xE1\xB3\x65\x24"
+ "\xA8\xEE\x56\x70\x5E\x28\x06\x04\x80\xCE\xB7\x36"
+ "\xA4\xD1\x4E\xAA\xE7\xE8\x51\x40\x7D\x30\xF7\x91"
+ "\xF2\x9E\x98\xA7\xBB\xB3\x1D\xC6\x8A\x62\xC7\xE7"
+ "\x1F\xE1\x0A\x52\x45\x39\x88\x92\x43\xA6\x5B\xC3"
+ "\x9D\x60\xDE\xFE\x79\xEF\x87\x6F\xD5\x76\x51\x69"
+ "\x7B\x4C\x3D\x08\x60\xFA\xDC\x00\x94\xEC\x0A\xC5"
+ "\xE7\xCB\x30\x05\x9F\xCC\x07\x44\x07\x14\xF4\xF9"
+ "\xBC\x7D\xC0\x66\x63\x5B\xD3\x2A\xA7\xF2\x1D\x75"
+ "\x3F\x28\x5F\x4A\xEB\x63\xD7\x92\x5A\x9A\x7C\x3A"
+ "\x56\xEA\xCB\xA9\xA0\xF9\x5B\x99\xC2\x7D\x31\xBF"
+ "\x44\xC7\x64\x6B\x7E\x64\x60\x64\x05\x86\xF0\x6B"
+ "\x76\xA7\x3E\x63\xAD\xB6\x76\xED\x3D\x05\x2E\xC7"
+ "\xC7\x52\x8F\x07\x56\x23\xFC\x2F\x93\xD5\xF2\x29"
+ "\xC6\x84\x48\xD1\x88\xB9\x3F\x84\xB2\x93\xFC\x2F"
+ "\x00\xB1\xBC\xBE\xAC\xC4\x94\x36\xF1\x2B\xF0\xC7"
+ "\x36\xE8\x1D\x45\x0A\xA2\xFE\x72\xD7\x3E\x15\x6A"
+ "\x74\x23\xB2\xD1\x3C\x20\xF2\xB7\x19\xC5\xF0\x74"
+ "\x69\x06\xD1\x92\x47\xC9\x68\xDC\xEE\xBC\xF4\x3A"
+ "\x8B\x7C\xA4\xA4\x4A\x15\xF4\xF0\x26\x26\xC5\x7D"
+ "\x57\xDC\x00\x59\x07\xDF\x84\x2A\x23\xA9\xC1\xAF"
+ "\x47\x49\x88\xCC\x2F\x3B\x90\x39\xA0\x09\xAE\x3C"
+ "\x79\xF9\x97\x9D\xEF\x13\x1D\x2B\xB6\x18\xDB\xCF"
+ "\x95\x98\x17\x7F\xF6\x95\x44\x3A\x40\x90\x63\x16"
+ "\x70\x38\x22\xC5\xD8\xE4\x57\xA0\x8E\x51\x6B\xED"
+ "\x03\x18\xC6\x74\xFA\xCA\xF2\xD5\xB2\x5A\x0C\x02"
+ "\x48\x9F\x70\x0B\x1C\x0A\xD1\xD6\x4F\x3F\x70\x3C"
+ "\x1A\x62\x29\x63\xD0\x92\x76\x30\x7C\xB9\x54\xEC"
+ "\xF6\x92\xA3\x11\x66\xB2\x56\xE0\x75\x3D\x27\x01",
+ .entropylen = 384,
+ .pers = "\x03\x75\x33\x7B\x6B\xE5\x14\xAF\x0E\x43\x33\xCC\xD3"
+ "\xF4\xF0\x8B\x8A\xCC\xFE\x95\xC1\x20\xB9\x56\x3D\x2C"
+ "\x34\xC7\xA1\x4C\xBC\xDC\x0A\x8D\xBE\x68\x28\x89\x2A"
+ "\x92\x10\x05\x4E\xF9\xE2\x51\xF7\x4F\xF4\x48\x76\xC9"
+ "\xCE\xA8\x6D\xC1\xDE\x5C\x05\x95\x77\x24\xB4\x5D\x3D"
+ "\x16\x1D\xCB\x43\xE5\xD3\x01\x96\xCC\x3E\x2E\xE1\x97"
+ "\xB3\x42\xC2\xAB\xEC\x56\xA9\xF9\xF2\x28\x59\x01\x4E"
+ "\xFC\x8A\xC0\x5E\x4E\x33\x30\x91\x96\x93\xBA\xFA\xE1"
+ "\x9F\x20\xC3\xC1\xD1\xC6\xC3\x2C\x59\x8F\x56\xD5\x73"
+ "\xE8\x8D\xCF\xAC\xB1\x85\x3E\xC7\x73\x21\x59\x8D\x0F"
+ "\xF4\xA4\xC4\x0C\xD2\x18\x81\x5F\x3E\x37\xC9\x9F\xD9"
+ "\xDE\x3F\x15\x6F\xAC\x1A\xEC\x5E\x28\xD5\x56\xA2\x65"
+ "\xD2\x7C\x41\xDE\x57\x8C\x60\xAB\xA5\x03\x42\xC8\x3C"
+ "\x70\xC2\xD1\x11\x62\x25\x4E\x17\x58\xBB\x08\x51\x79"
+ "\xE6\xED\xBA\x9A\xA7\x07\xD5\x0E\x89\x43\x31\x4F\x99"
+ "\xEE\xED\xF1\x36\xFA\x1E\xC0\x25\x01\xDA\x19\xC2\x7D"
+ "\x5D\x78\x74\x5C\xC0\x72\x2E\xF1\x7B\x4E\x9C\xDB\xFE"
+ "\x60\x89\x62\x71\x9C\xEA\xD3\xDF\x82\xC7\x8B\xB4\x7B"
+ "\x7B\x7F\x6A\x62\x3C\x57\x76\xA5\x67\x5F\x70\xFB\xE0"
+ "\x1B\x23\x79\x71\xB5\x7C\xEA\x76\x99",
+ .perslen = 256,
+
+ .ent_reseed = "\xE0\x5B\x69\xC5\xF9\xD4\x5A\x1F\xC1\x71\x0C"
+ "\x37\x6F\xFE\x31\xE0\xEF\x3E\x9B\xD5\x46\x43"
+ "\xA2\x15\xFA\x86\x75\x1C\x95\x9F\xE6\xD6\x41"
+ "\x50\x36\x0F\x67\x68\x4A\x72\x32\x85\xB0\xCB"
+ "\xA4\x0D\x1F\xA2\x43\xCA\x30\xF1\x42\xF8\xC4"
+ "\x17\x6A\xD1\x2D\x43\x46\x8C\xA5\x72\x3C\xB1"
+ "\x44\x8E\xA1\x75\xAA\x20\x30\xDD\xCD\x0B\x5A"
+ "\x0D\xE6\x28\xCA\xBC\xA9\x3B\x11\x23\x88\x85"
+ "\xDF\xD8\x84\x11\x89\x7A\x4F\x00\x90\x0B\xD8"
+ "\x8A\x35\xE9\x5F\xEC\x05\x42\x15\xCA\x7E\xA3"
+ "\xEF\xEF\xE3\xB7\xBE\x96\x8C\x36\x7D\x15\x3C"
+ "\x7A\x78\x00\x61\xAF\x62\x45\xA7\x4B\xAE\x4A"
+ "\xFD\xC9\xE0\x89\x53\x36\x71\x8F\x38\xC4\x00"
+ "\x57\xD9\xE6\xC1\xEC\xBF\xF7\x4B\x3F\x55\xD6"
+ "\x54\x15\x72\xB2\x23\x76\xD1\x4E\x8E\x7E\xFB"
+ "\xC8\xD6\xA4\xA4\x7E\x8E\xD8\x76\xD3\xEB\x90"
+ "\x90\xEB\xB3\x84\x26\x34\x93\x36\xCA\xA9\x12"
+ "\xD3\x6D\x84\x07\xE1\x0E\xE7\x63\x24\x54\x90"
+ "\x42\x8C\x6B\xE7\x21\x53\x2D\x16\xE9\x68\xA9"
+ "\xC2\x9A\x7A\x93\x31\x5E\x35\x72\xE2\x0F\x3D"
+ "\x55\x41\x8C\xC5\xD1\xBB\xEE\x5F\x3C\x95\x52"
+ "\x2A\x65\x47\xB6\x84\x6A\x05\x19\xD9\xE7\x68"
+ "\x15\xFA\x49\xD9\x9D\xFD\x47\x9F\xB9\xA6\xBB"
+ "\xA8\xD4\x22\x6C\x8B\x59\x47\xEF\xD1\xD0\xBF"
+ "\xBC\xE4\x53\x31\x2F\xA5\xD4\x2C\x89\xCA\xE5"
+ "\x29\x64\xF8\x51\x2A\x02\xDE\x31\x0D\x54\x0E"
+ "\x0E\xB8\x78\xE6\x2A\x3E\x31\xA2\xA4\xCD\x91"
+ "\x79\xF2\x9B\x04\xA0\xDB\x78\xAC\x0D\xB5\xCA"
+ "\x60\x4C\x08\x96\xCA\x8A\xE9\x93\x9F\x62\x38"
+ "\xAE",
+ .ent_reseed_len = 320,
+ .addtl_reseed = "\xD5\x46\x71\x38\x46\xE0\xC1\x27\x2C\xF1\x07"
+ "\xDD\x29\x73\xD7\xF4\x5A\x3A\xE0\x99\x98\x0A"
+ "\xEB\xA5\x9E\x2E\x49\x21\x7B\x18\xC0\xD8\x3D"
+ "\xEE\x49\xF9\x52\x7C\x55\x5E\x5E\x06\xC2\x7E"
+ "\x34\x3A\xA5\xB7\x78\x21\xC1\xB8\x8B\x4E\x07"
+ "\x1F\x3F\xC4\xB4\x9B\x3F\x20\x2D\xEE\x70\x3B"
+ "\x18\xCF\x2B\x50\x15\x1B\xF3\x6C\xE7\x9F\x2A"
+ "\x2B\x69\x53\xCA\x88\x41\xA9\x07\x31\x14\x55"
+ "\xBD\x75\x49\x68\x98\x48\xCA\x46\xA5\xEC\xAA"
+ "\x9D\x8E\x6F\x40\xBA\xCA\xC8\xE9\x9F\xA4\xC5"
+ "\x94\x89\x2C\x4D\xE4\x0A\x66\xD3\xDB\x1A\xD9"
+ "\xA7\x3F\x6B\x0A\xE0\xE4\xDC\x0B\x8B\x64\xBF"
+ "\xB4\x95\xA1\xAE\x92\xA8\x7C\xE2\x4B\xED\xFD"
+ "\xFD\xE0\x54\x48\x7C\x25\xD6\xD1\x0A\xAB\x5E"
+ "\x33\x2F\x1D\xD3\x62\x47\xAB\x35\x8C\xA1\xC2"
+ "\x75\xDD\x75\xCA\x09\xE1\x38\xDE\x87\x79\x0C"
+ "\xD7\x5D\x3E\x6D\x28\x8F\x12\x98\x2C\x26\x34"
+ "\x91\x0B\x6B\xB7\x73",
+ .addtl_reseed_len = 192,
+
+ .addtla = "\xC8\xE1\x03\x59\xEA\x9F\xD3\x1F\xCC\xCB\x5A\x3E"
+ "\x23\xDB\x47\x75\x1B\x3A\x6C\x0B\xED\xE6\xC0\xB6"
+ "\x4B\x82\x53\x5B\x6D\xEE\x2B\x97\x0F\x59\x07\xA4"
+ "\xFE\xE2\x26\x4F\xFF\xF7\x46\xAF\x62\xC4\x42\xE8"
+ "\x06\xFA\x1F\xAA\x66\xF3\xA4\xCF\x85\x02\x3C\x11"
+ "\xEF\xD2\x16\x13\x7A\xBD\x03\x66\xC3\x4D\x6F\x3A"
+ "\xE5\xD3\xFF\x92\xB6\x45\xB8\x88\x94\x42\x2E\x84"
+ "\x02\xA5\x54\x12\xBF\xCB\xF1\x6E\x1C\x0C\x23\xFE"
+ "\x8A\xFD\xF5\x1A\x4C\xD6\x2A\x34\x7F\x21\x50\xBB"
+ "\x06\x64\x9A\x77\x70\x59\x1D\x12\xD1\xA0\x10\x70"
+ "\xD7\x4F\x3C\xEE\x82\xEF\x5B\x35\x8F\x05\xF6\x51"
+ "\xBC\x28\xE1\xB1\x54\xFF\x25\x12\x16\x2C\x62\xFC"
+ "\xB9\x74\x5E\x78\x41\xB2\x04\x80\x4E\xB1\x43\x2E"
+ "\x88\x7F\x34\xA4\x33\x66\xE8\x68\x60\x54\xEB\xCE"
+ "\xD1\x5F\xC4\xD6\x21\x5E\x22\x1A\x7E\xC5\x6D\xB7"
+ "\x93\x8F\x9C\x77\x6E\x56\xA5\xA8\xF7\xB2\x10\x19",
+ .addtlb = "\xB8\x1E\x9E\xE2\xB3\xE4\x04\x43\x51\x7B\x96\x32"
+ "\xAC\x95\xF2\x1E\x5E\x7A\xBF\x68\xE3\x7A\xCE\xE5"
+ "\x2B\x3B\xB0\x34\x7F\xE1\xB5\x37\x3C\x5B\xD2\x6B"
+ "\x17\xF6\x18\xAF\x7C\x01\xA5\x84\xFE\x07\x0B\x46"
+ "\xCC\x96\x61\xAB\xCD\x81\x95\x8A\x8A\xB6\xD8\xCC"
+ "\x94\x80\x45\xF6\xFF\x95\x3A\xB8\xDC\xBF\xB4\xBF"
+ "\x26\x8C\xE9\x79\x05\x58\x9C\x03\x08\x45\xB5\xC4"
+ "\xD8\xB4\xCD\x76\x13\xAE\x2B\xCC\xB5\x3E\x3C\x65"
+ "\x7A\xAA\xDC\x9B\x0B\x13\x8B\x82\x5A\x39\x60\x9A"
+ "\xF7\xA8\x38\xB5\x83\x8E\x0B\xD1\xE6\xBF\xA1\xDC"
+ "\x30\x45\xCC\x67\x41\x0F\xF9\x86\x27\xE0\x22\x3E"
+ "\x0D\x1F\x92\x13\x16\x9B\x84\x79\x91\xFE\xBC\xDF"
+ "\x15\x6C\xDC\xAE\xC5\x64\x46\x9C\xE8\xEA\xBB\x9D"
+ "\x27\xA2\x1E\xDF\xB2\xF2\x98\xB4\x88\x4E\x22\x5F"
+ "\x3C\xD0\x35\x2C\x5C\x89\xC7\xEC\xE3\xF3\x09\x60"
+ "\xEF\xAC\x78\xBF\x94\xAA\x8C\x30\x7F\xCF\xE4\x4B",
+ .addtllen = 192,
+
+ .expected = "\x93\xFF\x4F\x4A\xA7\xE0\xFC\x3B\xCF\xCE\x57\xCD"
+ "\xFD\xE9\x94\x6D\x0D\x45\x7E\xA3\x98\xBB\xE6\x54"
+ "\x36\xF9\x92\xE6\xBB\xC5\x93\x16\x69\x35\x01\xF0"
+ "\x5A\xE2\x43\xFC\x73\x7C\xA3\x5C\x5B\x49\x72\x69"
+ "\x6A\xC4\xB6\xD4\xB2\x48\x27\x72\xCA\xE3\xF3\xB8"
+ "\xD6\x95\x9F\x39\xC8\xD7\x72\xAF\xC2\x7C\x75\xE5"
+ "\xA4\xF7\x52\x4F\xDF\x80\x75\xCA\x4B\xFA\x75\x9A"
+ "\x7A\x8D\x48\x94\x30\x1C\x82\x5E\xD6\x3F\xF1\x78"
+ "\x84\xAA\x8D\x8B\x4F\x6A\x20\x12\xA2\x65\xC5\x02"
+ "\x32\xA1\xE4\x6B\x86\x2F\xCF\x92\xCD\x01\x55\xF7"
+ "\xB8\xAB\xC3\x2C\x42\xC3\xFD\x9B\x59\x2D\x47\x8E"
+ "\xB6\x8D\xE7\x04\x2E\x67\xD9\x07\x14\xA3\xF2\x74"
+ "\x79\x9C\xAB\xC6\xD6\x52\x3E\x91\x81\xA4\x3C\x9A"
+ "\x3E\x10\x1E\xD0\x28\xBC\x1C\x50\xF0\xB6\xEC\x01"
+ "\xE5\x40\x16\x08\xB5\x58\xE0\xC4\xC2\x9A\xBB\x13"
+ "\xAB\x10\x4B\x07\x24\x09\xEB\xF9\x5E\xAA\x3E\x3A"
+ "\x25\x34\x5B\x97\x92\xF9\x46\x8A\x8E\x5A\x06\x9C"
+ "\x2B\x1C\x8E\x47\x19\xC3\x3B\x14\x8A\xC1\xEB\xF7"
+ "\xB0\xA2\x05\xE0\x70\x12\x88\x21\xFF\xC0\x35\x6D"
+ "\xE9\x08\x7E\x11\x6E\xD7\x16\x48\x24\x43\xAF\x33"
+ "\xA3\x48\x44\x91\xC5\x32\x1D\x87\xF6\x9B\x10\x1C"
+ "\xA4\x7A\x74\x23\xB3\xFC\xB9\x87\x08\xE6\x9A\xEF"
+ "\xD5\x93\x82\x17\xD4\x78\xDA\x46\x34\xC2\x61\x8C"
+ "\xB7\x53\x89\xC4\x8A\xD8\xA0\x2E\xCE\xCA\x24\x16"
+ "\xF0\x18\x7F\xC3\x12\x3F\xD0\xB1\xEF\x37\x99\xA8"
+ "\x04\x1F\x76\x50\x81\x08\xCD\x4D\x43\xEF\x64\xB6"
+ "\x03\x57\xB7\x5F\xDD\xF6\xBA\x34\xE2\x88\xE7\x1F"
+ "\x62\xA5\xA4\x05\xEB\x1A\xFE\x0B\xFE\x74\x7D\x64"
+ "\x29\x83\xE8\x0B\x97\x7D\x94\x5B\xF9\x3C\x8E\xC8"
+ "\x6B\xCD\xAD\x63\x32\x6E\x00\xBF\x8E\x57\xF2\x32"
+ "\x88\x53\x17\x40\xE3\xF8\xF8\xD9\xFD\xCD\x76\x84"
+ "\xC6\xFD\xB1\x10\x40\xED\x75\xDD\xBD\x78\x8B\x0A"
+ "\x61\x1E\xCC\xC4\x4F\x95\xF1\x2F\x8F\x5A\xF0\x12"
+ "\x00\xCE\x75\xB8\xE9\xAB\x63\xC0\x7A\xF6\x9A\x47"
+ "\xD2\x3C\xB0\xAD\xAF\x03\xDF\x25\xDD\x0C\x0F\xB6"
+ "\x29\x09\x0F\x28\x5E\xA8\x67\xBB\xC9\x78\xBE\x12"
+ "\xD8\xD6\xD0\x98\x82\x29\xA3\x82\xFB\x8E\x1C\x79"
+ "\x28\x52\x22\x73\x3C\x6F\xB5\x33\xFF\x40\x26\x4C"
+ "\x30\xE4\xE0\x39\x59\x72\x65\x79\x9F\xB7\x89\x87"
+ "\x64\xAC\x45\x11\x0D\xDD\xC0\x44\x5E\x0D\xDF\xDB"
+ "\x91\x42\x5F\x52\x7F\xBB\x66\xEE\x32\x90\x8F\x6F"
+ "\xF8\xB9\xFE\xEA\x42\xFB\x60\x2B\xE3\xD9\xB2\xD1"
+ "\x74\x37\x14\xC6\xDA\x68\xE6\x09",
+ .expectedlen = 512,
}
};
/* Cast5 test vectors from RFC 2144 */
static const struct cipher_testvec cast5_tv_template[] = {
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 17/38] crypto: drbg - Remove support for HMAC-SHA256 and HMAC-SHA384
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (15 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 16/38] crypto: testmgr - Update test for drbg_nopr_hmac_sha512 Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 18/38] crypto: drbg - Simplify algorithm registration Eric Biggers
` (20 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Remove support for the HMAC-SHA256 and HMAC-SHA384 variants of
HMAC_DRBG, leaving only the HMAC-SHA512 variant of HMAC_DRBG.
HMAC-SHA512 is already the default. The default did used to be
HMAC-SHA256, but several years ago it was upgraded to HMAC-SHA512 "to
support compliance with SP800-90B and SP800-90C". Given that the point
of crypto/drbg.c is compliance with those standards, and there's also no
technical reason to prefer HMAC-SHA384 in this situation even if
acceptable, there's really no point in offering anything else.
Note: now that only HMAC-SHA512 remains, a lot of unnecessary
abstractions can be removed. A later commit will do that. This commit
just straightforwardly removes the HMAC-SHA256 and HMAC-SHA384 code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 22 +---
crypto/testmgr.c | 27 -----
crypto/testmgr.h | 280 -----------------------------------------------
3 files changed, 2 insertions(+), 327 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 6301eb2e304c..81bccacd3595 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1,11 +1,9 @@
/*
* DRBG: Deterministic Random Bits Generator
- * Based on NIST Recommended DRBG from NIST SP800-90A with the following
- * properties:
- * * HMAC DRBG with DF with SHA-1, SHA-256, SHA-384, SHA-512 cores
- * * with and without prediction resistance
+ * Implementation of the HMAC SHA-512 DRBG from NIST SP800-90A,
+ * both with and without prediction resistance
*
* Copyright Stephan Mueller <smueller@chronox.de>, 2014
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -213,22 +211,10 @@ enum drbg_prefixes {
*
* Thus, the favored DRBGs are the latest entries in this array.
*/
static const struct drbg_core drbg_cores[] = {
{
- .flags = DRBG_HMAC | DRBG_STRENGTH256,
- .statelen = 48, /* block length of cipher */
- .blocklen_bytes = 48,
- .cra_name = "hmac_sha384",
- .backend_cra_name = "hmac(sha384)",
- }, {
- .flags = DRBG_HMAC | DRBG_STRENGTH256,
- .statelen = 32, /* block length of cipher */
- .blocklen_bytes = 32,
- .cra_name = "hmac_sha256",
- .backend_cra_name = "hmac(sha256)",
- }, {
.flags = DRBG_HMAC | DRBG_STRENGTH256,
.statelen = 64, /* block length of cipher */
.blocklen_bytes = 64,
.cra_name = "hmac_sha512",
.backend_cra_name = "hmac(sha512)",
@@ -274,14 +260,10 @@ static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
static int drbg_init_hash_kernel(struct drbg_state *drbg);
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
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");
/* update function of HMAC DRBG as defined in 10.1.2.2 */
static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
int reseed)
{
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index ad4c2e66b812..4199b7d3e9fb 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4647,44 +4647,17 @@ static const struct alg_test_desc alg_test_descs[] = {
.kpp = __VECS(dh_tv_template)
}
}, {
.alg = "digest_null",
.test = alg_test_null,
- }, {
- .alg = "drbg_nopr_hmac_sha256",
- .test = alg_test_drbg,
- .fips_allowed = 1,
- .suite = {
- .drbg = __VECS(drbg_nopr_hmac_sha256_tv_template)
- }
- }, {
- /*
- * There is no need to specifically test the DRBG with every
- * backend cipher -- covered by drbg_nopr_hmac_sha512 test
- */
- .alg = "drbg_nopr_hmac_sha384",
- .test = alg_test_null,
- .fips_allowed = 1
}, {
.alg = "drbg_nopr_hmac_sha512",
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
.drbg = __VECS(drbg_nopr_hmac_sha512_tv_template)
}
- }, {
- .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",
- .test = alg_test_null,
- .fips_allowed = 1
}, {
.alg = "drbg_pr_hmac_sha512",
.test = alg_test_drbg,
.fips_allowed = 1,
.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index fc70ca86d61f..c47203f73fd1 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -23431,290 +23431,10 @@ static const struct aead_testvec aegis128_tv_template[] = {
"\x78\x93\xec\xfc\xf4\xff\xe1\x2d",
.clen = 24,
},
};
-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_nopr_hmac_sha256_tv_template[] = {
- {
- .entropy = (unsigned char *)
- "\xca\x85\x19\x11\x34\x93\x84\xbf\xfe\x89\xde\x1c"
- "\xbd\xc4\x6e\x68\x31\xe4\x4d\x34\xa4\xfb\x93\x5e"
- "\xe2\x85\xdd\x14\xb7\x1a\x74\x88\x65\x9b\xa9\x6c"
- "\x60\x1d\xc6\x9f\xc9\x02\x94\x08\x05\xec\x0c\xa8",
- .entropylen = 48,
- .expected = (unsigned char *)
- "\xe5\x28\xe9\xab\xf2\xde\xce\x54\xd4\x7c\x7e\x75"
- "\xe5\xfe\x30\x21\x49\xf8\x17\xea\x9f\xb4\xbe\xe6"
- "\xf4\x19\x96\x97\xd0\x4d\x5b\x89\xd5\x4f\xbb\x97"
- "\x8a\x15\xb5\xc4\x43\xc9\xec\x21\x03\x6d\x24\x60"
- "\xb6\xf7\x3e\xba\xd0\xdc\x2a\xba\x6e\x62\x4a\xbf"
- "\x07\x74\x5b\xc1\x07\x69\x4b\xb7\x54\x7b\xb0\x99"
- "\x5f\x70\xde\x25\xd6\xb2\x9e\x2d\x30\x11\xbb\x19"
- "\xd2\x76\x76\xc0\x71\x62\xc8\xb5\xcc\xde\x06\x68"
- "\x96\x1d\xf8\x68\x03\x48\x2c\xb3\x7e\xd6\xd5\xc0"
- "\xbb\x8d\x50\xcf\x1f\x50\xd4\x76\xaa\x04\x58\xbd"
- "\xab\xa8\x06\xf4\x8b\xe9\xdc\xb8",
- .expectedlen = 128,
- .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"
- "\x93\xd4\x36\xc4\x93\x1f\x60\x4b\x22\xf1\x08\x15"
- "\x21\xb3\x41\x91\x51\xe8\xff\x06\x11\xf3\xa7\xd4"
- "\x35\x95\x35\x7d\x58\x12\x0b\xd1\xe2\xdd\x8a\xed",
- .entropylen = 48,
- .expected = (unsigned char *)
- "\xc6\x87\x1c\xff\x08\x24\xfe\x55\xea\x76\x89\xa5"
- "\x22\x29\x88\x67\x30\x45\x0e\x5d\x36\x2d\xa5\xbf"
- "\x59\x0d\xcf\x9a\xcd\x67\xfe\xd4\xcb\x32\x10\x7d"
- "\xf5\xd0\x39\x69\xa6\x6b\x1f\x64\x94\xfd\xf5\xd6"
- "\x3d\x5b\x4d\x0d\x34\xea\x73\x99\xa0\x7d\x01\x16"
- "\x12\x6d\x0d\x51\x8c\x7c\x55\xba\x46\xe1\x2f\x62"
- "\xef\xc8\xfe\x28\xa5\x1c\x9d\x42\x8e\x6d\x37\x1d"
- "\x73\x97\xab\x31\x9f\xc7\x3d\xed\x47\x22\xe5\xb4"
- "\xf3\x00\x04\x03\x2a\x61\x28\xdf\x5e\x74\x97\xec"
- "\xf8\x2c\xa7\xb0\xa5\x0e\x86\x7e\xf6\x72\x8a\x4f"
- "\x50\x9a\x8c\x85\x90\x87\x03\x9c",
- .expectedlen = 128,
- .addtla = (unsigned char *)
- "\x51\x72\x89\xaf\xe4\x44\xa0\xfe\x5e\xd1\xa4\x1d"
- "\xbb\xb5\xeb\x17\x15\x00\x79\xbd\xd3\x1e\x29\xcf"
- "\x2f\xf3\x00\x34\xd8\x26\x8e\x3b",
- .addtlb = (unsigned char *)
- "\x88\x02\x8d\x29\xef\x80\xb4\xe6\xf0\xfe\x12\xf9"
- "\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,
- },
-};
-
static const struct drbg_testvec drbg_pr_hmac_sha512_tv_template[] = {
/*
* Borrowed from the first applicable test vector from ACVP:
* https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/prompt.json#L1161
* https://github.com/usnistgov/ACVP-Server/blob/v1.1.0.33/gen-val/json-files/hmacDRBG-1.0/expectedResults.json#L271
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 18/38] crypto: drbg - Simplify algorithm registration
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (16 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 17/38] crypto: drbg - Remove support for HMAC-SHA256 and HMAC-SHA384 Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 19/38] crypto: drbg - De-virtualize drbg_state_ops Eric Biggers
` (19 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Now that "drbg_pr_hmac_sha512" and "drbg_nopr_hmac_sha512" are the only
crypto_rng algorithms left in crypto/drbg.c, simplify the algorithm
registration logic to register these more directly without relying on
the drbg_cores[] array (which will be removed).
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 100 ++++++++++++++++++--------------------------------
1 file changed, 35 insertions(+), 65 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 81bccacd3595..4a778d0d1fc4 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1143,90 +1143,60 @@ static inline int __init drbg_healthcheck_sanity(void)
kfree(drbg);
return rc;
}
-static struct rng_alg drbg_algs[22];
-
-/*
- * Fill the array drbg_algs used to register the different DRBGs
- * with the kernel crypto API. To fill the array, the information
- * from drbg_cores[] is used.
- */
-static inline void __init drbg_fill_array(struct rng_alg *alg,
- const struct drbg_core *core, int pr)
-{
- 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,
- strlen(core->cra_name));
-
- alg->base.cra_priority = priority;
- priority++;
- /*
- * If FIPS mode enabled, the selected DRBG shall have the
- * highest cra_priority over other stdrng instances to ensure
- * it is selected.
- */
- if (fips_enabled)
- alg->base.cra_priority += 2000;
-
- alg->base.cra_ctxsize = sizeof(struct drbg_state);
- alg->base.cra_module = THIS_MODULE;
- alg->base.cra_init = drbg_kcapi_init;
- 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 struct rng_alg drbg_algs[] = {
+ {
+ .base.cra_name = "stdrng",
+ .base.cra_driver_name = "drbg_pr_hmac_sha512",
+ .base.cra_priority = 200,
+ .base.cra_ctxsize = sizeof(struct drbg_state),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = drbg_kcapi_init,
+ .set_ent = drbg_kcapi_set_entropy,
+ .seed = drbg_kcapi_seed,
+ .generate = drbg_kcapi_random,
+ .base.cra_exit = drbg_kcapi_cleanup,
+ },
+ {
+ .base.cra_name = "stdrng",
+ .base.cra_driver_name = "drbg_nopr_hmac_sha512",
+ .base.cra_priority = 201,
+ .base.cra_ctxsize = sizeof(struct drbg_state),
+ .base.cra_module = THIS_MODULE,
+ .base.cra_init = drbg_kcapi_init,
+ .set_ent = drbg_kcapi_set_entropy,
+ .seed = drbg_kcapi_seed,
+ .generate = drbg_kcapi_random,
+ .base.cra_exit = drbg_kcapi_cleanup,
+ },
+};
static int __init drbg_init(void)
{
- unsigned int i = 0; /* pointer to drbg_algs */
- unsigned int j = 0; /* pointer to drbg_cores */
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;
- }
-
/*
- * 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.
+ * In FIPS mode, boost the algorithm priorities to ensure that when
+ * users request "stdrng", they really get an algorithm from here.
*/
- 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));
+ if (fips_enabled) {
+ for (size_t i = 0; i < ARRAY_SIZE(drbg_algs); i++)
+ drbg_algs[i].base.cra_priority += 2000;
+ }
+
+ return crypto_register_rngs(drbg_algs, ARRAY_SIZE(drbg_algs));
}
static void __exit drbg_exit(void)
{
- crypto_unregister_rngs(drbg_algs, (ARRAY_SIZE(drbg_cores) * 2));
+ crypto_unregister_rngs(drbg_algs, ARRAY_SIZE(drbg_algs));
}
module_init(drbg_init);
module_exit(drbg_exit);
MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 19/38] crypto: drbg - De-virtualize drbg_state_ops
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (17 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 18/38] crypto: drbg - Simplify algorithm registration Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 20/38] crypto: drbg - Move fixed values into constants Eric Biggers
` (18 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Now that there's only one set of state operations, use direct calls to
those operations.
No change in behavior. In particular, drbg_alloc_state() doesn't change
behavior, because the only remaining drbg_core uses HMAC_DRBG.
drbg_uninstantiate() doesn't change behavior, because a NULL d_ops
implied NULL priv_data which makes a drbg_fini_hash_kernel() a no-op.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 50 ++++++--------------------------------------------
1 file changed, 6 insertions(+), 44 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 4a778d0d1fc4..04c798d7a8b6 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -109,21 +109,10 @@ struct drbg_core {
char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
/* kernel crypto API backend cipher name */
char backend_cra_name[CRYPTO_MAX_ALG_NAME];
};
-struct drbg_state_ops {
- int (*update)(struct drbg_state *drbg, struct list_head *seed,
- int reseed);
- int (*generate)(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
- struct list_head *addtl);
- int (*crypto_init)(struct drbg_state *drbg);
- int (*crypto_fini)(struct drbg_state *drbg);
-
-};
-
enum drbg_seed_state {
DRBG_SEED_STATE_UNSEEDED,
DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
DRBG_SEED_STATE_FULL,
};
@@ -141,11 +130,10 @@ struct drbg_state {
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
bool pr; /* Prediction resistance enabled? */
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)
@@ -248,11 +236,11 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
return 32;
}
}
/******************************************************************
- * HMAC DRBG callback functions
+ * HMAC DRBG functions
******************************************************************/
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
const struct list_head *in);
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
@@ -358,25 +346,14 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
return ret;
return len;
}
-static const struct drbg_state_ops drbg_hmac_ops = {
- .update = drbg_hmac_update,
- .generate = drbg_hmac_generate,
- .crypto_init = drbg_init_hash_kernel,
- .crypto_fini = drbg_fini_hash_kernel,
-};
-
-/******************************************************************
- * 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);
+ int ret = drbg_hmac_update(drbg, seed, reseed);
if (ret)
return ret;
drbg->seeded = new_seed_state;
@@ -576,11 +553,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
drbg->V = NULL;
kfree_sensitive(drbg->Cbuf);
drbg->Cbuf = NULL;
drbg->C = NULL;
drbg->reseed_ctr = 0;
- drbg->d_ops = NULL;
drbg->core = NULL;
}
/*
* Allocate all sub-structures for a DRBG state.
@@ -588,20 +564,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
*/
static inline int drbg_alloc_state(struct drbg_state *drbg)
{
int ret = -ENOMEM;
- switch (drbg->core->flags & DRBG_TYPE_MASK) {
- case DRBG_HMAC:
- drbg->d_ops = &drbg_hmac_ops;
- break;
- default:
- ret = -EOPNOTSUPP;
- goto err;
- }
-
- ret = drbg->d_ops->crypto_init(drbg);
+ ret = drbg_init_hash_kernel(drbg);
if (ret < 0)
goto err;
drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
if (!drbg->Vbuf) {
@@ -617,20 +584,16 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
return 0;
fini:
- drbg->d_ops->crypto_fini(drbg);
+ drbg_fini_hash_kernel(drbg);
err:
drbg_dealloc_state(drbg);
return ret;
}
-/*************************************************************************
- * DRBG interface functions
- *************************************************************************/
-
/*
* DRBG generate function as required by SP800-90A - this function
* generates random numbers
*
* @drbg DRBG state handle
@@ -712,11 +675,11 @@ static int drbg_generate(struct drbg_state *drbg,
}
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);
+ len = drbg_hmac_generate(drbg, buf, buflen, &addtllist);
/* 10.1.2.5 step 7 */
drbg->reseed_ctr++;
if (0 >= len)
goto err;
@@ -877,12 +840,11 @@ 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_fini_hash_kernel(drbg);
drbg_dealloc_state(drbg);
/* no scrubbing of test_data -- this shall survive an uninstantiate */
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 20/38] crypto: drbg - Move fixed values into constants
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (18 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 19/38] crypto: drbg - De-virtualize drbg_state_ops Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 16:06 ` Joachim Vandersmissen
2026-04-20 6:34 ` [PATCH 21/38] crypto: drbg - Embed V and C into struct drbg_state Eric Biggers
` (17 subsequent siblings)
37 siblings, 1 reply; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Since only one drbg_core remains, the state length, block length, and
security strength are now fixed values. Moreover, the maximum request
length, maximum additional data length, and maximum number of requests
were all already fixed values.
Simplify the code by just using #defines for all these fixed values.
In drbg_seed_from_random(), take advantage of the constant to define the
array size. Remove assertions that are no longer useful.
In the case of drbg_blocklen() and drbg_statelen(), replace these with a
single value DRBG_STATE_LEN, as for HMAC_DRBG they are the same thing.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 183 +++++++++++++++++---------------------------------
1 file changed, 61 insertions(+), 122 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 04c798d7a8b6..34a7cbdda1f1 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -89,25 +89,22 @@
*/
#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
#include <crypto/hash.h>
+#include <crypto/sha2.h>
#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
struct drbg_state;
-typedef uint32_t drbg_flag_t;
struct drbg_core {
- drbg_flag_t flags; /* flags for the cipher */
- __u8 statelen; /* maximum state length */
- __u8 blocklen_bytes; /* block size of output in bytes */
char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
/* kernel crypto API backend cipher name */
char backend_cra_name[CRYPTO_MAX_ALG_NAME];
};
@@ -115,10 +112,36 @@ enum drbg_seed_state {
DRBG_SEED_STATE_UNSEEDED,
DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
DRBG_SEED_STATE_FULL,
};
+/* State length in bytes */
+#define DRBG_STATE_LEN SHA512_DIGEST_SIZE
+
+/* Security strength in bytes */
+#define DRBG_SEC_STRENGTH (SHA512_DIGEST_SIZE / 2)
+
+/*
+ * Maximum number of requests before reseeding is forced.
+ * SP800-90A allows this to be up to 2**48. We use a lower value.
+ */
+#define DRBG_MAX_REQUESTS (1 << 20)
+
+/*
+ * Maximum number of random bytes that can be requested at once.
+ * SP800-90A allows up to 2**19 bits, which is 2**16 bytes.
+ */
+#define DRBG_MAX_REQUEST_BYTES (1 << 16)
+
+/*
+ * Maximum length of additional info and personalization strings, in bytes.
+ * SP800-90A allows up to 2**35 bits, i.e. 2**32 bytes. We use 2**32 - 2 bytes
+ * so that the value never quite completely fills the range of a size_t,
+ * allowing the health check to verify that larger values are rejected.
+ */
+#define DRBG_MAX_ADDTL (U32_MAX - 1)
+
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
unsigned char *V; /* internal state -- 10.1.2.1 1a */
unsigned char *Vbuf;
unsigned char *C; /* current key -- 10.1.2.1 1b */
@@ -134,57 +157,10 @@ struct drbg_state {
struct crypto_rng *jent;
const struct drbg_core *core;
struct drbg_string test_data;
};
-static inline __u8 drbg_statelen(struct drbg_state *drbg)
-{
- if (drbg && drbg->core)
- return drbg->core->statelen;
- return 0;
-}
-
-static inline __u8 drbg_blocklen(struct drbg_state *drbg)
-{
- if (drbg && drbg->core)
- return drbg->core->blocklen_bytes;
- return 0;
-}
-
-static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
-{
- /* SP800-90A requires the limit 2**19 bits, but we return bytes */
- return (1 << 16);
-}
-
-/*
- * SP800-90A allows implementations to support additional info / personalization
- * strings of up to 2**35 bits. Implementations can have a smaller maximum. We
- * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a
- * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement.
- */
-static inline size_t drbg_max_addtl(struct drbg_state *drbg)
-{
- return U32_MAX - 1;
-}
-
-static inline size_t drbg_max_requests(struct drbg_state *drbg)
-{
- /* SP800-90A requires 2**48 maximum requests before reseeding */
- return (1<<20);
-}
-
-/* DRBG type flags */
-#define DRBG_HMAC ((drbg_flag_t)1<<1)
-#define DRBG_TYPE_MASK DRBG_HMAC
-/* DRBG strength flags */
-#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
-#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
-#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
-#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
- DRBG_STRENGTH256)
-
enum drbg_prefixes {
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
};
@@ -199,46 +175,17 @@ enum drbg_prefixes {
*
* Thus, the favored DRBGs are the latest entries in this array.
*/
static const struct drbg_core drbg_cores[] = {
{
- .flags = DRBG_HMAC | DRBG_STRENGTH256,
- .statelen = 64, /* block length of cipher */
- .blocklen_bytes = 64,
.cra_name = "hmac_sha512",
.backend_cra_name = "hmac(sha512)",
},
};
static int drbg_uninstantiate(struct drbg_state *drbg);
-/******************************************************************
- * Generic helper functions
- ******************************************************************/
-
-/*
- * Return strength of DRBG according to SP800-90A section 8.4
- *
- * @flags DRBG flags reference
- *
- * Return: normalized strength in *bytes* value or 32 as default
- * to counter programming errors
- */
-static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
-{
- switch (flags & DRBG_STRENGTH_MASK) {
- case DRBG_STRENGTH128:
- return 16;
- case DRBG_STRENGTH192:
- return 24;
- case DRBG_STRENGTH256:
- return 32;
- default:
- return 32;
- }
-}
-
/******************************************************************
* HMAC DRBG functions
******************************************************************/
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
@@ -261,24 +208,24 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
LIST_HEAD(seedlist);
LIST_HEAD(vdatalist);
if (!reseed) {
/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
- memset(drbg->V, 1, drbg_statelen(drbg));
+ memset(drbg->V, 1, DRBG_STATE_LEN);
drbg_kcapi_hmacsetkey(drbg, drbg->C);
}
- drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&seed1, drbg->V, DRBG_STATE_LEN);
list_add_tail(&seed1.list, &seedlist);
/* buffer of seed2 will be filled in for loop below with one byte */
drbg_string_fill(&seed2, NULL, 1);
list_add_tail(&seed2.list, &seedlist);
/* input data of seed is allowed to be NULL at this point */
if (seed)
list_splice_tail(seed, &seedlist);
- drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&vdata, drbg->V, DRBG_STATE_LEN);
list_add_tail(&vdata.list, &vdatalist);
for (i = 2; 0 < i; i--) {
/* first round uses 0x0, second 0x1 */
unsigned char prefix = DRBG_PREFIX0;
if (1 == i)
@@ -319,20 +266,20 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
ret = drbg_hmac_update(drbg, addtl, 1);
if (ret)
return ret;
}
- drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
+ drbg_string_fill(&data, drbg->V, DRBG_STATE_LEN);
list_add_tail(&data.list, &datalist);
while (len < buflen) {
unsigned int outlen = 0;
/* 10.1.2.5 step 4.1 */
ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
if (ret)
return ret;
- outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
- drbg_blocklen(drbg) : (buflen - len);
+ outlen = (DRBG_STATE_LEN < (buflen - len)) ?
+ DRBG_STATE_LEN : (buflen - len);
/* 10.1.2.5 step 4.2 */
memcpy(buf + len, drbg->V, outlen);
len += outlen;
}
@@ -375,11 +322,11 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
case DRBG_SEED_STATE_FULL:
/*
* Seed source has become fully initialized, frequent
* reseeds no longer required.
*/
- drbg->reseed_threshold = drbg_max_requests(drbg);
+ drbg->reseed_threshold = DRBG_MAX_REQUESTS;
break;
}
return ret;
}
@@ -387,25 +334,21 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
static int drbg_seed_from_random(struct drbg_state *drbg)
__must_hold(&drbg->drbg_mutex)
{
struct drbg_string data;
LIST_HEAD(seedlist);
- unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
- unsigned char entropy[32];
+ unsigned char entropy[DRBG_SEC_STRENGTH];
int ret;
- BUG_ON(!entropylen);
- BUG_ON(entropylen > sizeof(entropy));
-
- drbg_string_fill(&data, entropy, entropylen);
+ drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH);
list_add_tail(&data.list, &seedlist);
- get_random_bytes(entropy, entropylen);
+ get_random_bytes(entropy, DRBG_SEC_STRENGTH);
ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
- memzero_explicit(entropy, entropylen);
+ memzero_explicit(entropy, DRBG_SEC_STRENGTH);
return ret;
}
static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
{
@@ -442,17 +385,17 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
bool reseed)
__must_hold(&drbg->drbg_mutex)
{
int ret;
unsigned char entropy[((32 + 16) * 2)];
- unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
+ unsigned int entropylen;
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))) {
+ if (pers && pers->len > DRBG_MAX_ADDTL) {
pr_devel("DRBG: personalization string too long %zu\n",
pers->len);
return -EINVAL;
}
@@ -467,13 +410,14 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
* 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;
+ entropylen = ((DRBG_SEC_STRENGTH + 1) / 2) * 3;
+ else
+ entropylen = DRBG_SEC_STRENGTH;
BUG_ON((entropylen * 2) > sizeof(entropy));
/* Get seed from in-kernel /dev/urandom */
if (!rng_is_initialized())
new_seed_state = DRBG_SEED_STATE_PARTIAL;
@@ -529,18 +473,18 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
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));
+ memset(drbg->V, 0, DRBG_STATE_LEN);
+ memset(drbg->C, 0, DRBG_STATE_LEN);
}
ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
out:
- memzero_explicit(entropy, entropylen * 2);
+ memzero_explicit(entropy, sizeof(entropy));
return ret;
}
/* Free all substructures in a DRBG state without the DRBG state structure */
@@ -568,17 +512,17 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
ret = drbg_init_hash_kernel(drbg);
if (ret < 0)
goto err;
- drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
+ drbg->Vbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
if (!drbg->Vbuf) {
ret = -ENOMEM;
goto fini;
}
drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
- drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
+ drbg->Cbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
if (!drbg->Cbuf) {
ret = -ENOMEM;
goto fini;
}
drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
@@ -628,24 +572,23 @@ static int drbg_generate(struct drbg_state *drbg,
pr_devel("DRBG: wrong format of additional information\n");
return -EINVAL;
}
/* 9.3.1 step 2 */
- len = -EINVAL;
- if (buflen > (drbg_max_request_bytes(drbg))) {
+ if (buflen > DRBG_MAX_REQUEST_BYTES) {
pr_devel("DRBG: requested random numbers too large %u\n",
buflen);
- goto err;
+ return -EINVAL;
}
/* 9.3.1 step 3 is implicit with the chosen DRBG */
/* 9.3.1 step 4 */
- if (addtl && addtl->len > (drbg_max_addtl(drbg))) {
+ if (addtl && addtl->len > DRBG_MAX_ADDTL) {
pr_devel("DRBG: additional information string too long %zu\n",
addtl->len);
- goto err;
+ return -EINVAL;
}
/* 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
@@ -721,12 +664,12 @@ static int drbg_generate_long(struct drbg_state *drbg,
unsigned int len = 0;
unsigned int slice = 0;
do {
int err = 0;
unsigned int chunk = 0;
- slice = ((buflen - len) / drbg_max_request_bytes(drbg));
- chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
+ slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES;
+ chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len);
mutex_lock(&drbg->drbg_mutex);
err = drbg_generate(drbg, buf + len, chunk, addtl);
mutex_unlock(&drbg->drbg_mutex);
if (0 > err)
return err;
@@ -783,22 +726,21 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
/* 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 4 is implicit in drbg_sec_strength */
+ /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
if (!drbg->core) {
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);
+ drbg->reseed_threshold = DRBG_MAX_REQUESTS;
ret = drbg_alloc_state(drbg);
if (ret)
goto unlock;
@@ -882,11 +824,11 @@ static int drbg_init_hash_kernel(struct drbg_state *drbg)
if (IS_ERR(tfm)) {
pr_info("DRBG: could not allocate digest TFM handle: %s\n",
drbg->core->backend_cra_name);
return PTR_ERR(tfm);
}
- BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
+ BUG_ON(DRBG_STATE_LEN != crypto_shash_digestsize(tfm));
sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
GFP_KERNEL);
if (!sdesc) {
crypto_free_shash(tfm);
return -ENOMEM;
@@ -912,11 +854,11 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg)
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
const unsigned char *key)
{
struct sdesc *sdesc = drbg->priv_data;
- crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
+ crypto_shash_setkey(sdesc->shash.tfm, key, DRBG_STATE_LEN);
}
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
const struct list_head *in)
{
@@ -1058,11 +1000,10 @@ static inline int __init drbg_healthcheck_sanity(void)
int ret;
int rc = -EFAULT;
bool pr = false;
int coreref = 0;
struct drbg_string addtl;
- size_t max_addtllen, max_request_bytes;
/* only perform test in FIPS mode */
if (!fips_enabled)
return 0;
@@ -1072,28 +1013,26 @@ static inline int __init drbg_healthcheck_sanity(void)
if (!drbg)
return -ENOMEM;
guard(mutex_init)(&drbg->drbg_mutex);
drbg->core = &drbg_cores[coreref];
- drbg->reseed_threshold = drbg_max_requests(drbg);
+ drbg->reseed_threshold = DRBG_MAX_REQUESTS;
/*
* if the following tests fail, it is likely that there is a buffer
* overflow as buf is much smaller than the requested or provided
* string lengths -- in case the error handling does not succeed
* we may get an OOPS. And we want to get an OOPS as this is a
* grave bug.
*/
- max_addtllen = drbg_max_addtl(drbg);
- max_request_bytes = drbg_max_request_bytes(drbg);
- drbg_string_fill(&addtl, buf, max_addtllen + 1);
+ drbg_string_fill(&addtl, buf, DRBG_MAX_ADDTL + 1);
/* overflow addtllen with additional info string */
ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
BUG_ON(ret == 0);
/* overflow max_bits */
- ret = drbg_generate(drbg, buf, max_request_bytes + 1, NULL);
+ ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL);
BUG_ON(ret == 0);
/* overflow max addtllen with personalization string */
ret = drbg_seed(drbg, &addtl, false);
BUG_ON(0 == ret);
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 20/38] crypto: drbg - Move fixed values into constants
2026-04-20 6:34 ` [PATCH 20/38] crypto: drbg - Move fixed values into constants Eric Biggers
@ 2026-04-20 16:06 ` Joachim Vandersmissen
0 siblings, 0 replies; 50+ messages in thread
From: Joachim Vandersmissen @ 2026-04-20 16:06 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld
Hi Eric,
If possible, I suggest using "DRBG_MAX_ADDTL_BYTES" for consistency with
DRBG_MAX_REQUEST_BYTES and avoiding any possible confusion in the future.
Kind regards,
Joachim
On 4/20/26 1:34 AM, Eric Biggers wrote:
> Since only one drbg_core remains, the state length, block length, and
> security strength are now fixed values. Moreover, the maximum request
> length, maximum additional data length, and maximum number of requests
> were all already fixed values.
>
> Simplify the code by just using #defines for all these fixed values.
>
> In drbg_seed_from_random(), take advantage of the constant to define the
> array size. Remove assertions that are no longer useful.
>
> In the case of drbg_blocklen() and drbg_statelen(), replace these with a
> single value DRBG_STATE_LEN, as for HMAC_DRBG they are the same thing.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> crypto/drbg.c | 183 +++++++++++++++++---------------------------------
> 1 file changed, 61 insertions(+), 122 deletions(-)
>
> diff --git a/crypto/drbg.c b/crypto/drbg.c
> index 04c798d7a8b6..34a7cbdda1f1 100644
> --- a/crypto/drbg.c
> +++ b/crypto/drbg.c
> @@ -89,25 +89,22 @@
> */
>
> #include <crypto/internal/drbg.h>
> #include <crypto/internal/rng.h>
> #include <crypto/hash.h>
> +#include <crypto/sha2.h>
> #include <linux/fips.h>
> #include <linux/kernel.h>
> #include <linux/jiffies.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/string_choices.h>
> #include <linux/unaligned.h>
>
> struct drbg_state;
> -typedef uint32_t drbg_flag_t;
>
> struct drbg_core {
> - drbg_flag_t flags; /* flags for the cipher */
> - __u8 statelen; /* maximum state length */
> - __u8 blocklen_bytes; /* block size of output in bytes */
> char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
> /* kernel crypto API backend cipher name */
> char backend_cra_name[CRYPTO_MAX_ALG_NAME];
> };
>
> @@ -115,10 +112,36 @@ enum drbg_seed_state {
> DRBG_SEED_STATE_UNSEEDED,
> DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
> DRBG_SEED_STATE_FULL,
> };
>
> +/* State length in bytes */
> +#define DRBG_STATE_LEN SHA512_DIGEST_SIZE
> +
> +/* Security strength in bytes */
> +#define DRBG_SEC_STRENGTH (SHA512_DIGEST_SIZE / 2)
> +
> +/*
> + * Maximum number of requests before reseeding is forced.
> + * SP800-90A allows this to be up to 2**48. We use a lower value.
> + */
> +#define DRBG_MAX_REQUESTS (1 << 20)
> +
> +/*
> + * Maximum number of random bytes that can be requested at once.
> + * SP800-90A allows up to 2**19 bits, which is 2**16 bytes.
> + */
> +#define DRBG_MAX_REQUEST_BYTES (1 << 16)
> +
> +/*
> + * Maximum length of additional info and personalization strings, in bytes.
> + * SP800-90A allows up to 2**35 bits, i.e. 2**32 bytes. We use 2**32 - 2 bytes
> + * so that the value never quite completely fills the range of a size_t,
> + * allowing the health check to verify that larger values are rejected.
> + */
> +#define DRBG_MAX_ADDTL (U32_MAX - 1)
> +
> struct drbg_state {
> struct mutex drbg_mutex; /* lock around DRBG */
> unsigned char *V; /* internal state -- 10.1.2.1 1a */
> unsigned char *Vbuf;
> unsigned char *C; /* current key -- 10.1.2.1 1b */
> @@ -134,57 +157,10 @@ struct drbg_state {
> struct crypto_rng *jent;
> const struct drbg_core *core;
> struct drbg_string test_data;
> };
>
> -static inline __u8 drbg_statelen(struct drbg_state *drbg)
> -{
> - if (drbg && drbg->core)
> - return drbg->core->statelen;
> - return 0;
> -}
> -
> -static inline __u8 drbg_blocklen(struct drbg_state *drbg)
> -{
> - if (drbg && drbg->core)
> - return drbg->core->blocklen_bytes;
> - return 0;
> -}
> -
> -static inline size_t drbg_max_request_bytes(struct drbg_state *drbg)
> -{
> - /* SP800-90A requires the limit 2**19 bits, but we return bytes */
> - return (1 << 16);
> -}
> -
> -/*
> - * SP800-90A allows implementations to support additional info / personalization
> - * strings of up to 2**35 bits. Implementations can have a smaller maximum. We
> - * use 2**35 - 16 bits == U32_MAX - 1 bytes so that the max + 1 always fits in a
> - * size_t, allowing drbg_healthcheck_sanity() to verify its enforcement.
> - */
> -static inline size_t drbg_max_addtl(struct drbg_state *drbg)
> -{
> - return U32_MAX - 1;
> -}
> -
> -static inline size_t drbg_max_requests(struct drbg_state *drbg)
> -{
> - /* SP800-90A requires 2**48 maximum requests before reseeding */
> - return (1<<20);
> -}
> -
> -/* DRBG type flags */
> -#define DRBG_HMAC ((drbg_flag_t)1<<1)
> -#define DRBG_TYPE_MASK DRBG_HMAC
> -/* DRBG strength flags */
> -#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3)
> -#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4)
> -#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5)
> -#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \
> - DRBG_STRENGTH256)
> -
> enum drbg_prefixes {
> DRBG_PREFIX0 = 0x00,
> DRBG_PREFIX1,
> };
>
> @@ -199,46 +175,17 @@ enum drbg_prefixes {
> *
> * Thus, the favored DRBGs are the latest entries in this array.
> */
> static const struct drbg_core drbg_cores[] = {
> {
> - .flags = DRBG_HMAC | DRBG_STRENGTH256,
> - .statelen = 64, /* block length of cipher */
> - .blocklen_bytes = 64,
> .cra_name = "hmac_sha512",
> .backend_cra_name = "hmac(sha512)",
> },
> };
>
> static int drbg_uninstantiate(struct drbg_state *drbg);
>
> -/******************************************************************
> - * Generic helper functions
> - ******************************************************************/
> -
> -/*
> - * Return strength of DRBG according to SP800-90A section 8.4
> - *
> - * @flags DRBG flags reference
> - *
> - * Return: normalized strength in *bytes* value or 32 as default
> - * to counter programming errors
> - */
> -static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
> -{
> - switch (flags & DRBG_STRENGTH_MASK) {
> - case DRBG_STRENGTH128:
> - return 16;
> - case DRBG_STRENGTH192:
> - return 24;
> - case DRBG_STRENGTH256:
> - return 32;
> - default:
> - return 32;
> - }
> -}
> -
> /******************************************************************
> * HMAC DRBG functions
> ******************************************************************/
>
> static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
> @@ -261,24 +208,24 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
> LIST_HEAD(seedlist);
> LIST_HEAD(vdatalist);
>
> if (!reseed) {
> /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
> - memset(drbg->V, 1, drbg_statelen(drbg));
> + memset(drbg->V, 1, DRBG_STATE_LEN);
> drbg_kcapi_hmacsetkey(drbg, drbg->C);
> }
>
> - drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
> + drbg_string_fill(&seed1, drbg->V, DRBG_STATE_LEN);
> list_add_tail(&seed1.list, &seedlist);
> /* buffer of seed2 will be filled in for loop below with one byte */
> drbg_string_fill(&seed2, NULL, 1);
> list_add_tail(&seed2.list, &seedlist);
> /* input data of seed is allowed to be NULL at this point */
> if (seed)
> list_splice_tail(seed, &seedlist);
>
> - drbg_string_fill(&vdata, drbg->V, drbg_statelen(drbg));
> + drbg_string_fill(&vdata, drbg->V, DRBG_STATE_LEN);
> list_add_tail(&vdata.list, &vdatalist);
> for (i = 2; 0 < i; i--) {
> /* first round uses 0x0, second 0x1 */
> unsigned char prefix = DRBG_PREFIX0;
> if (1 == i)
> @@ -319,20 +266,20 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
> ret = drbg_hmac_update(drbg, addtl, 1);
> if (ret)
> return ret;
> }
>
> - drbg_string_fill(&data, drbg->V, drbg_statelen(drbg));
> + drbg_string_fill(&data, drbg->V, DRBG_STATE_LEN);
> list_add_tail(&data.list, &datalist);
> while (len < buflen) {
> unsigned int outlen = 0;
> /* 10.1.2.5 step 4.1 */
> ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
> if (ret)
> return ret;
> - outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
> - drbg_blocklen(drbg) : (buflen - len);
> + outlen = (DRBG_STATE_LEN < (buflen - len)) ?
> + DRBG_STATE_LEN : (buflen - len);
>
> /* 10.1.2.5 step 4.2 */
> memcpy(buf + len, drbg->V, outlen);
> len += outlen;
> }
> @@ -375,11 +322,11 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
> case DRBG_SEED_STATE_FULL:
> /*
> * Seed source has become fully initialized, frequent
> * reseeds no longer required.
> */
> - drbg->reseed_threshold = drbg_max_requests(drbg);
> + drbg->reseed_threshold = DRBG_MAX_REQUESTS;
> break;
> }
>
> return ret;
> }
> @@ -387,25 +334,21 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
> static int drbg_seed_from_random(struct drbg_state *drbg)
> __must_hold(&drbg->drbg_mutex)
> {
> struct drbg_string data;
> LIST_HEAD(seedlist);
> - unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
> - unsigned char entropy[32];
> + unsigned char entropy[DRBG_SEC_STRENGTH];
> int ret;
>
> - BUG_ON(!entropylen);
> - BUG_ON(entropylen > sizeof(entropy));
> -
> - drbg_string_fill(&data, entropy, entropylen);
> + drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH);
> list_add_tail(&data.list, &seedlist);
>
> - get_random_bytes(entropy, entropylen);
> + get_random_bytes(entropy, DRBG_SEC_STRENGTH);
>
> ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
>
> - memzero_explicit(entropy, entropylen);
> + memzero_explicit(entropy, DRBG_SEC_STRENGTH);
> return ret;
> }
>
> static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
> {
> @@ -442,17 +385,17 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
> bool reseed)
> __must_hold(&drbg->drbg_mutex)
> {
> int ret;
> unsigned char entropy[((32 + 16) * 2)];
> - unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
> + unsigned int entropylen;
> 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))) {
> + if (pers && pers->len > DRBG_MAX_ADDTL) {
> pr_devel("DRBG: personalization string too long %zu\n",
> pers->len);
> return -EINVAL;
> }
>
> @@ -467,13 +410,14 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
> * 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;
> + entropylen = ((DRBG_SEC_STRENGTH + 1) / 2) * 3;
> + else
> + entropylen = DRBG_SEC_STRENGTH;
> BUG_ON((entropylen * 2) > sizeof(entropy));
>
> /* Get seed from in-kernel /dev/urandom */
> if (!rng_is_initialized())
> new_seed_state = DRBG_SEED_STATE_PARTIAL;
> @@ -529,18 +473,18 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
> 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));
> + memset(drbg->V, 0, DRBG_STATE_LEN);
> + memset(drbg->C, 0, DRBG_STATE_LEN);
> }
>
> ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
>
> out:
> - memzero_explicit(entropy, entropylen * 2);
> + memzero_explicit(entropy, sizeof(entropy));
>
> return ret;
> }
>
> /* Free all substructures in a DRBG state without the DRBG state structure */
> @@ -568,17 +512,17 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
>
> ret = drbg_init_hash_kernel(drbg);
> if (ret < 0)
> goto err;
>
> - drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
> + drbg->Vbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
> if (!drbg->Vbuf) {
> ret = -ENOMEM;
> goto fini;
> }
> drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
> - drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL);
> + drbg->Cbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
> if (!drbg->Cbuf) {
> ret = -ENOMEM;
> goto fini;
> }
> drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
> @@ -628,24 +572,23 @@ static int drbg_generate(struct drbg_state *drbg,
> pr_devel("DRBG: wrong format of additional information\n");
> return -EINVAL;
> }
>
> /* 9.3.1 step 2 */
> - len = -EINVAL;
> - if (buflen > (drbg_max_request_bytes(drbg))) {
> + if (buflen > DRBG_MAX_REQUEST_BYTES) {
> pr_devel("DRBG: requested random numbers too large %u\n",
> buflen);
> - goto err;
> + return -EINVAL;
> }
>
> /* 9.3.1 step 3 is implicit with the chosen DRBG */
>
> /* 9.3.1 step 4 */
> - if (addtl && addtl->len > (drbg_max_addtl(drbg))) {
> + if (addtl && addtl->len > DRBG_MAX_ADDTL) {
> pr_devel("DRBG: additional information string too long %zu\n",
> addtl->len);
> - goto err;
> + return -EINVAL;
> }
> /* 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
> @@ -721,12 +664,12 @@ static int drbg_generate_long(struct drbg_state *drbg,
> unsigned int len = 0;
> unsigned int slice = 0;
> do {
> int err = 0;
> unsigned int chunk = 0;
> - slice = ((buflen - len) / drbg_max_request_bytes(drbg));
> - chunk = slice ? drbg_max_request_bytes(drbg) : (buflen - len);
> + slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES;
> + chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len);
> mutex_lock(&drbg->drbg_mutex);
> err = drbg_generate(drbg, buf + len, chunk, addtl);
> mutex_unlock(&drbg->drbg_mutex);
> if (0 > err)
> return err;
> @@ -783,22 +726,21 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
>
> /* 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 4 is implicit in drbg_sec_strength */
> + /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
>
> if (!drbg->core) {
> 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);
> + drbg->reseed_threshold = DRBG_MAX_REQUESTS;
>
> ret = drbg_alloc_state(drbg);
> if (ret)
> goto unlock;
>
> @@ -882,11 +824,11 @@ static int drbg_init_hash_kernel(struct drbg_state *drbg)
> if (IS_ERR(tfm)) {
> pr_info("DRBG: could not allocate digest TFM handle: %s\n",
> drbg->core->backend_cra_name);
> return PTR_ERR(tfm);
> }
> - BUG_ON(drbg_blocklen(drbg) != crypto_shash_digestsize(tfm));
> + BUG_ON(DRBG_STATE_LEN != crypto_shash_digestsize(tfm));
> sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
> GFP_KERNEL);
> if (!sdesc) {
> crypto_free_shash(tfm);
> return -ENOMEM;
> @@ -912,11 +854,11 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg)
> static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
> const unsigned char *key)
> {
> struct sdesc *sdesc = drbg->priv_data;
>
> - crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
> + crypto_shash_setkey(sdesc->shash.tfm, key, DRBG_STATE_LEN);
> }
>
> static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
> const struct list_head *in)
> {
> @@ -1058,11 +1000,10 @@ static inline int __init drbg_healthcheck_sanity(void)
> int ret;
> int rc = -EFAULT;
> bool pr = false;
> int coreref = 0;
> struct drbg_string addtl;
> - size_t max_addtllen, max_request_bytes;
>
> /* only perform test in FIPS mode */
> if (!fips_enabled)
> return 0;
>
> @@ -1072,28 +1013,26 @@ static inline int __init drbg_healthcheck_sanity(void)
> if (!drbg)
> return -ENOMEM;
>
> guard(mutex_init)(&drbg->drbg_mutex);
> drbg->core = &drbg_cores[coreref];
> - drbg->reseed_threshold = drbg_max_requests(drbg);
> + drbg->reseed_threshold = DRBG_MAX_REQUESTS;
>
> /*
> * if the following tests fail, it is likely that there is a buffer
> * overflow as buf is much smaller than the requested or provided
> * string lengths -- in case the error handling does not succeed
> * we may get an OOPS. And we want to get an OOPS as this is a
> * grave bug.
> */
>
> - max_addtllen = drbg_max_addtl(drbg);
> - max_request_bytes = drbg_max_request_bytes(drbg);
> - drbg_string_fill(&addtl, buf, max_addtllen + 1);
> + drbg_string_fill(&addtl, buf, DRBG_MAX_ADDTL + 1);
> /* overflow addtllen with additional info string */
> ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
> BUG_ON(ret == 0);
> /* overflow max_bits */
> - ret = drbg_generate(drbg, buf, max_request_bytes + 1, NULL);
> + ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL);
> BUG_ON(ret == 0);
>
> /* overflow max addtllen with personalization string */
> ret = drbg_seed(drbg, &addtl, false);
> BUG_ON(0 == ret);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 21/38] crypto: drbg - Embed V and C into struct drbg_state
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (19 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 20/38] crypto: drbg - Move fixed values into constants Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 22/38] crypto: drbg - Use HMAC-SHA512 library API Eric Biggers
` (16 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Now that the sizes of V and C are known at compile time, embed them into
struct drbg_state rather than using separate allocations.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 30 ++++--------------------------
1 file changed, 4 insertions(+), 26 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 34a7cbdda1f1..e62bde7aab43 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -140,14 +140,12 @@ enum drbg_seed_state {
*/
#define DRBG_MAX_ADDTL (U32_MAX - 1)
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
- unsigned char *V; /* internal state -- 10.1.2.1 1a */
- unsigned char *Vbuf;
- unsigned char *C; /* current key -- 10.1.2.1 1b */
- unsigned char *Cbuf;
+ u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */
+ u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */
/* Number of RNG requests since last reseed -- 10.1.2.1 1c */
size_t reseed_ctr;
size_t reseed_threshold;
void *priv_data; /* Cipher handle */
@@ -490,16 +488,12 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
/* Free all substructures in a DRBG state without the DRBG state structure */
static inline void drbg_dealloc_state(struct drbg_state *drbg)
{
if (!drbg)
return;
- kfree_sensitive(drbg->Vbuf);
- drbg->Vbuf = NULL;
- drbg->V = NULL;
- kfree_sensitive(drbg->Cbuf);
- drbg->Cbuf = NULL;
- drbg->C = NULL;
+ memzero_explicit(drbg->V, sizeof(drbg->V));
+ memzero_explicit(drbg->C, sizeof(drbg->C));
drbg->reseed_ctr = 0;
drbg->core = NULL;
}
/*
@@ -511,28 +505,12 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
int ret = -ENOMEM;
ret = drbg_init_hash_kernel(drbg);
if (ret < 0)
goto err;
-
- drbg->Vbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
- if (!drbg->Vbuf) {
- ret = -ENOMEM;
- goto fini;
- }
- drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1);
- drbg->Cbuf = kmalloc(DRBG_STATE_LEN + ret, GFP_KERNEL);
- if (!drbg->Cbuf) {
- ret = -ENOMEM;
- goto fini;
- }
- drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1);
-
return 0;
-fini:
- drbg_fini_hash_kernel(drbg);
err:
drbg_dealloc_state(drbg);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 22/38] crypto: drbg - Use HMAC-SHA512 library API
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (20 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 21/38] crypto: drbg - Embed V and C into struct drbg_state Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 23/38] crypto: drbg - Remove drbg_core Eric Biggers
` (15 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Since the HMAC algorithm is now fixed at HMAC-SHA512, just use the
HMAC-SHA512 library API. This is simpler and more efficient.
Remove error-handling code that is no longer needed.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 3 +-
crypto/drbg.c | 213 ++++++++++---------------------------------------
2 files changed, 41 insertions(+), 175 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1abb3d356458..608b2c739193 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1113,14 +1113,13 @@ endmenu
menu "Random number generation"
config CRYPTO_DRBG
tristate "NIST SP800-90A DRBG (Deterministic Random Bit Generator)"
- select CRYPTO_HMAC
select CRYPTO_JITTERENTROPY
+ select CRYPTO_LIB_SHA512
select CRYPTO_RNG
- select CRYPTO_SHA512
help
DRBG (Deterministic Random Bit Generator) (NIST SP800-90A)
Enable this only if you need it for a FIPS 140 certification.
It's otherwise redundant with the kernel's regular RNG.
diff --git a/crypto/drbg.c b/crypto/drbg.c
index e62bde7aab43..4f326385cf36 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -2,10 +2,11 @@
* DRBG: Deterministic Random Bits Generator
* Implementation of the HMAC SHA-512 DRBG from NIST SP800-90A,
* both with and without prediction resistance
*
* Copyright Stephan Mueller <smueller@chronox.de>, 2014
+ * Copyright 2026 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
@@ -88,11 +89,10 @@
* Just mix both scenarios above.
*/
#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
-#include <crypto/hash.h>
#include <crypto/sha2.h>
#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/module.h>
@@ -141,16 +141,15 @@ enum drbg_seed_state {
#define DRBG_MAX_ADDTL (U32_MAX - 1)
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */
+ struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */
u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */
/* Number of RNG requests since last reseed -- 10.1.2.1 1c */
size_t reseed_ctr;
size_t reseed_threshold;
- void *priv_data; /* Cipher handle */
-
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
bool pr; /* Prediction resistance enabled? */
struct crypto_rng *jent;
const struct drbg_core *core;
@@ -184,124 +183,90 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
* HMAC DRBG functions
******************************************************************/
-static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
- const struct list_head *in);
-static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
- const unsigned char *key);
-static int drbg_init_hash_kernel(struct drbg_state *drbg);
-static int drbg_fini_hash_kernel(struct drbg_state *drbg);
-
MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
/* update function of HMAC DRBG as defined in 10.1.2.2 */
-static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
- int reseed)
+static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
+ int reseed)
{
- int ret = -EFAULT;
int i = 0;
- struct drbg_string seed1, seed2, vdata;
- LIST_HEAD(seedlist);
- LIST_HEAD(vdatalist);
+ struct hmac_sha512_ctx hmac_ctx;
if (!reseed) {
/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
memset(drbg->V, 1, DRBG_STATE_LEN);
- drbg_kcapi_hmacsetkey(drbg, drbg->C);
+ hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
}
- drbg_string_fill(&seed1, drbg->V, DRBG_STATE_LEN);
- list_add_tail(&seed1.list, &seedlist);
- /* buffer of seed2 will be filled in for loop below with one byte */
- drbg_string_fill(&seed2, NULL, 1);
- list_add_tail(&seed2.list, &seedlist);
- /* input data of seed is allowed to be NULL at this point */
- if (seed)
- list_splice_tail(seed, &seedlist);
-
- drbg_string_fill(&vdata, drbg->V, DRBG_STATE_LEN);
- list_add_tail(&vdata.list, &vdatalist);
for (i = 2; 0 < i; i--) {
/* first round uses 0x0, second 0x1 */
unsigned char prefix = DRBG_PREFIX0;
if (1 == i)
prefix = DRBG_PREFIX1;
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
- seed2.buf = &prefix;
- ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
- if (ret)
- return ret;
- drbg_kcapi_hmacsetkey(drbg, drbg->C);
+ hmac_sha512_init(&hmac_ctx, &drbg->key);
+ hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN);
+ hmac_sha512_update(&hmac_ctx, &prefix, 1);
+ if (seed) {
+ struct drbg_string *input;
+
+ list_for_each_entry(input, seed, list)
+ hmac_sha512_update(&hmac_ctx, input->buf,
+ input->len);
+ }
+ hmac_sha512_final(&hmac_ctx, drbg->C);
+ hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
- ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
- if (ret)
- return ret;
+ hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
/* 10.1.2.2 step 3 */
if (!seed)
- return ret;
+ break;
}
-
- return 0;
}
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
-static int drbg_hmac_generate(struct drbg_state *drbg,
- unsigned char *buf,
- unsigned int buflen,
- struct list_head *addtl)
+static void drbg_hmac_generate(struct drbg_state *drbg,
+ unsigned char *buf,
+ unsigned int buflen,
+ struct list_head *addtl)
{
int len = 0;
- int ret = 0;
- struct drbg_string data;
- LIST_HEAD(datalist);
/* 10.1.2.5 step 2 */
- if (addtl && !list_empty(addtl)) {
- ret = drbg_hmac_update(drbg, addtl, 1);
- if (ret)
- return ret;
- }
+ if (addtl && !list_empty(addtl))
+ drbg_hmac_update(drbg, addtl, 1);
- drbg_string_fill(&data, drbg->V, DRBG_STATE_LEN);
- list_add_tail(&data.list, &datalist);
while (len < buflen) {
unsigned int outlen = 0;
+
/* 10.1.2.5 step 4.1 */
- ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
- if (ret)
- return ret;
+ hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
outlen = (DRBG_STATE_LEN < (buflen - len)) ?
DRBG_STATE_LEN : (buflen - len);
/* 10.1.2.5 step 4.2 */
memcpy(buf + len, drbg->V, outlen);
len += outlen;
}
/* 10.1.2.5 step 6 */
if (addtl && !list_empty(addtl))
- ret = drbg_hmac_update(drbg, addtl, 1);
+ drbg_hmac_update(drbg, addtl, 1);
else
- ret = drbg_hmac_update(drbg, NULL, 1);
- if (ret)
- return ret;
-
- return len;
+ drbg_hmac_update(drbg, NULL, 1);
}
-static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
- int reseed, enum drbg_seed_state new_seed_state)
+static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
+ int reseed, enum drbg_seed_state new_seed_state)
{
- int ret = drbg_hmac_update(drbg, seed, reseed);
-
- if (ret)
- return ret;
+ drbg_hmac_update(drbg, seed, reseed);
drbg->seeded = new_seed_state;
drbg->last_seed_time = jiffies;
drbg->reseed_ctr = 1;
@@ -323,31 +288,27 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
* reseeds no longer required.
*/
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
break;
}
-
- return ret;
}
-static int drbg_seed_from_random(struct drbg_state *drbg)
+static void drbg_seed_from_random(struct drbg_state *drbg)
__must_hold(&drbg->drbg_mutex)
{
struct drbg_string data;
LIST_HEAD(seedlist);
unsigned char entropy[DRBG_SEC_STRENGTH];
- int ret;
drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH);
list_add_tail(&data.list, &seedlist);
get_random_bytes(entropy, DRBG_SEC_STRENGTH);
- ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
+ __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
memzero_explicit(entropy, DRBG_SEC_STRENGTH);
- return ret;
}
static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
{
unsigned long next_reseed;
@@ -475,12 +436,12 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
if (!reseed) {
memset(drbg->V, 0, DRBG_STATE_LEN);
memset(drbg->C, 0, DRBG_STATE_LEN);
}
- ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
-
+ __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
+ ret = 0;
out:
memzero_explicit(entropy, sizeof(entropy));
return ret;
}
@@ -488,34 +449,17 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
/* Free all substructures in a DRBG state without the DRBG state structure */
static inline void drbg_dealloc_state(struct drbg_state *drbg)
{
if (!drbg)
return;
+ memzero_explicit(&drbg->key, sizeof(drbg->key));
memzero_explicit(drbg->V, sizeof(drbg->V));
memzero_explicit(drbg->C, sizeof(drbg->C));
drbg->reseed_ctr = 0;
drbg->core = NULL;
}
-/*
- * Allocate all sub-structures for a DRBG state.
- * The DRBG state structure must already be allocated.
- */
-static inline int drbg_alloc_state(struct drbg_state *drbg)
-{
- int ret = -ENOMEM;
-
- ret = drbg_init_hash_kernel(drbg);
- if (ret < 0)
- goto err;
- return 0;
-
-err:
- drbg_dealloc_state(drbg);
- return ret;
-}
-
/*
* DRBG generate function as required by SP800-90A - this function
* generates random numbers
*
* @drbg DRBG state handle
@@ -588,24 +532,20 @@ static int drbg_generate(struct drbg_state *drbg,
/* 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;
+ drbg_seed_from_random(drbg);
}
if (addtl && 0 < addtl->len)
list_add_tail(&addtl->list, &addtllist);
/* 9.3.1 step 8 and 10 */
- len = drbg_hmac_generate(drbg, buf, buflen, &addtllist);
+ drbg_hmac_generate(drbg, buf, buflen, &addtllist);
/* 10.1.2.5 step 7 */
drbg->reseed_ctr++;
- if (0 >= len)
- goto err;
/*
* Section 11.3.3 requires to re-perform self tests after some
* generated random numbers. The chosen value after which self
* test is performed is arbitrary, but it should be reasonable.
@@ -716,14 +656,10 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
drbg->pr = pr;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
drbg->last_seed_time = 0;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
- ret = drbg_alloc_state(drbg);
- if (ret)
- goto unlock;
-
ret = drbg_prepare_hrng(drbg);
if (ret)
goto free_everything;
reseed = false;
@@ -735,14 +671,10 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
goto free_everything;
mutex_unlock(&drbg->drbg_mutex);
return ret;
-unlock:
- mutex_unlock(&drbg->drbg_mutex);
- return ret;
-
free_everything:
mutex_unlock(&drbg->drbg_mutex);
drbg_uninstantiate(drbg);
return ret;
}
@@ -760,11 +692,10 @@ static int drbg_uninstantiate(struct drbg_state *drbg)
{
if (!IS_ERR_OR_NULL(drbg->jent))
crypto_free_rng(drbg->jent);
drbg->jent = NULL;
- drbg_fini_hash_kernel(drbg);
drbg_dealloc_state(drbg);
/* no scrubbing of test_data -- this shall survive an uninstantiate */
return 0;
}
@@ -783,74 +714,10 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *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
- ***************************************************************/
-
-struct sdesc {
- struct shash_desc shash;
-};
-
-static int drbg_init_hash_kernel(struct drbg_state *drbg)
-{
- struct sdesc *sdesc;
- struct crypto_shash *tfm;
-
- tfm = crypto_alloc_shash(drbg->core->backend_cra_name, 0, 0);
- if (IS_ERR(tfm)) {
- pr_info("DRBG: could not allocate digest TFM handle: %s\n",
- drbg->core->backend_cra_name);
- return PTR_ERR(tfm);
- }
- BUG_ON(DRBG_STATE_LEN != crypto_shash_digestsize(tfm));
- sdesc = kzalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),
- GFP_KERNEL);
- if (!sdesc) {
- crypto_free_shash(tfm);
- return -ENOMEM;
- }
-
- sdesc->shash.tfm = tfm;
- drbg->priv_data = sdesc;
-
- return 0;
-}
-
-static int drbg_fini_hash_kernel(struct drbg_state *drbg)
-{
- struct sdesc *sdesc = drbg->priv_data;
- if (sdesc) {
- crypto_free_shash(sdesc->shash.tfm);
- kfree_sensitive(sdesc);
- }
- drbg->priv_data = NULL;
- return 0;
-}
-
-static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
- const unsigned char *key)
-{
- struct sdesc *sdesc = drbg->priv_data;
-
- crypto_shash_setkey(sdesc->shash.tfm, key, DRBG_STATE_LEN);
-}
-
-static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
- const struct list_head *in)
-{
- struct sdesc *sdesc = drbg->priv_data;
- struct drbg_string *input = NULL;
-
- crypto_shash_init(&sdesc->shash);
- list_for_each_entry(input, in, list)
- crypto_shash_update(&sdesc->shash, input->buf, input->len);
- return crypto_shash_final(&sdesc->shash, outval);
-}
-
/***************************************************************
* Kernel crypto API interface to register DRBG
***************************************************************/
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 23/38] crypto: drbg - Remove drbg_core
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (21 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 22/38] crypto: drbg - Use HMAC-SHA512 library API Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 24/38] crypto: drbg - Install separate seed functions for pr and nopr Eric Biggers
` (14 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Now that none of the information in struct drbg_core is used, remove it.
The null-ity of the pointer drbg_state::core was used to keep track of
whether the DRBG has been instantiated. Replace it with a boolean.
No functional change.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 99 +++++++--------------------------------------------
1 file changed, 13 insertions(+), 86 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 4f326385cf36..161070b10f85 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -98,18 +98,10 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
-struct drbg_state;
-
-struct drbg_core {
- char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */
- /* kernel crypto API backend cipher name */
- char backend_cra_name[CRYPTO_MAX_ALG_NAME];
-};
-
enum drbg_seed_state {
DRBG_SEED_STATE_UNSEEDED,
DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
DRBG_SEED_STATE_FULL,
};
@@ -148,39 +140,21 @@ struct drbg_state {
/* Number of RNG requests since last reseed -- 10.1.2.1 1c */
size_t reseed_ctr;
size_t reseed_threshold;
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
+ bool instantiated;
bool pr; /* Prediction resistance enabled? */
struct crypto_rng *jent;
- const struct drbg_core *core;
struct drbg_string test_data;
};
enum drbg_prefixes {
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
};
-/***************************************************************
- * Backend cipher definitions available to DRBG
- ***************************************************************/
-
-/*
- * The order of the DRBG definitions here matter: every DRBG is registered
- * as stdrng. Each DRBG receives an increasing cra_priority values the later
- * they are defined in this array (see drbg_fill_array).
- *
- * Thus, the favored DRBGs are the latest entries in this array.
- */
-static const struct drbg_core drbg_cores[] = {
- {
- .cra_name = "hmac_sha512",
- .backend_cra_name = "hmac(sha512)",
- },
-};
-
static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
* HMAC DRBG functions
******************************************************************/
@@ -453,11 +427,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
return;
memzero_explicit(&drbg->key, sizeof(drbg->key));
memzero_explicit(drbg->V, sizeof(drbg->V));
memzero_explicit(drbg->C, sizeof(drbg->C));
drbg->reseed_ctr = 0;
- drbg->core = NULL;
+ drbg->instantiated = false;
}
/*
* DRBG generate function as required by SP800-90A - this function
* generates random numbers
@@ -480,12 +454,12 @@ static int drbg_generate(struct drbg_state *drbg,
__must_hold(&drbg->drbg_mutex)
{
int len = 0;
LIST_HEAD(addtllist);
- if (!drbg->core) {
- pr_devel("DRBG: not yet seeded\n");
+ if (!drbg->instantiated) {
+ pr_devel("DRBG: not yet instantiated\n");
return -EINVAL;
}
if (0 == buflen || !buf) {
pr_devel("DRBG: no output buffer provided\n");
return -EINVAL;
@@ -623,25 +597,24 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
* @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
*
* return
* 0 on success
* error value otherwise
*/
static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
- int coreref, bool pr)
+ bool pr)
{
int ret;
bool reseed = true;
- pr_devel("DRBG: Initializing DRBG core %d with prediction resistance "
- "%s\n", coreref, str_enabled_disabled(pr));
+ pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n",
+ str_enabled_disabled(pr));
mutex_lock(&drbg->drbg_mutex);
/* 9.1 step 1 is implicit with the selected DRBG type */
/*
@@ -649,12 +622,12 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
* all DRBG types support prediction resistance
*/
/* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
- if (!drbg->core) {
- drbg->core = &drbg_cores[coreref];
+ if (!drbg->instantiated) {
+ drbg->instantiated = true;
drbg->pr = pr;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
drbg->last_seed_time = 0;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
@@ -718,50 +691,10 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
/***************************************************************
* 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);
mutex_init(&drbg->drbg_mutex);
@@ -806,23 +739,21 @@ 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;
+ bool pr = memcmp(crypto_tfm_alg_driver_name(tfm_base),
+ "drbg_nopr_", 10) != 0;
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(drbg, seed_string, pr);
}
/***************************************************************
* Kernel module: code to load the module
***************************************************************/
@@ -842,26 +773,22 @@ 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;
/* only perform test in FIPS mode */
if (!fips_enabled)
return 0;
- drbg_convert_tfm_core("drbg_nopr_hmac_sha512", &coreref, &pr);
-
drbg = kzalloc_obj(struct drbg_state);
if (!drbg)
return -ENOMEM;
guard(mutex_init)(&drbg->drbg_mutex);
- drbg->core = &drbg_cores[coreref];
+ drbg->instantiated = true;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
/*
* if the following tests fail, it is likely that there is a buffer
* overflow as buf is much smaller than the requested or provided
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 24/38] crypto: drbg - Install separate seed functions for pr and nopr
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (22 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 23/38] crypto: drbg - Remove drbg_core Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 25/38] crypto: drbg - Move module aliases to end of file Eric Biggers
` (13 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Set rng_alg::seed to different functions for the prediction-resistant
and non-prediction-resistant algorithms, so that the function does not
need to parse the algorithm name to figure out which algorithm it is.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 161070b10f85..c29f4ca93d1b 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -731,20 +731,15 @@ static int drbg_kcapi_random(struct crypto_rng *tfm,
}
return drbg_generate_long(drbg, dst, dlen, addtl);
}
-/*
- * Seed the DRBG invoked by the kernel crypto API
- */
+/* Seed (i.e. instantiate) or re-seed the DRBG. */
static int drbg_kcapi_seed(struct crypto_rng *tfm,
- const u8 *seed, unsigned int slen)
+ const u8 *seed, unsigned int slen, bool pr)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
- struct crypto_tfm *tfm_base = crypto_rng_tfm(tfm);
- bool pr = memcmp(crypto_tfm_alg_driver_name(tfm_base),
- "drbg_nopr_", 10) != 0;
struct drbg_string string;
struct drbg_string *seed_string = NULL;
if (0 < slen) {
drbg_string_fill(&string, seed, slen);
@@ -752,10 +747,22 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
}
return drbg_instantiate(drbg, seed_string, pr);
}
+static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen)
+{
+ return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true);
+}
+
+static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen)
+{
+ return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false);
+}
+
/***************************************************************
* Kernel module: code to load the module
***************************************************************/
/*
@@ -825,11 +832,11 @@ static struct rng_alg drbg_algs[] = {
.base.cra_priority = 200,
.base.cra_ctxsize = sizeof(struct drbg_state),
.base.cra_module = THIS_MODULE,
.base.cra_init = drbg_kcapi_init,
.set_ent = drbg_kcapi_set_entropy,
- .seed = drbg_kcapi_seed,
+ .seed = drbg_kcapi_seed_pr,
.generate = drbg_kcapi_random,
.base.cra_exit = drbg_kcapi_cleanup,
},
{
.base.cra_name = "stdrng",
@@ -837,11 +844,11 @@ static struct rng_alg drbg_algs[] = {
.base.cra_priority = 201,
.base.cra_ctxsize = sizeof(struct drbg_state),
.base.cra_module = THIS_MODULE,
.base.cra_init = drbg_kcapi_init,
.set_ent = drbg_kcapi_set_entropy,
- .seed = drbg_kcapi_seed,
+ .seed = drbg_kcapi_seed_nopr,
.generate = drbg_kcapi_random,
.base.cra_exit = drbg_kcapi_cleanup,
},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 25/38] crypto: drbg - Move module aliases to end of file
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (23 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 24/38] crypto: drbg - Install separate seed functions for pr and nopr Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 26/38] crypto: drbg - Consolidate "instantiate" logic and remove drbg_state::C Eric Biggers
` (12 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Move the MODULE_ALIAS_CRYPTO lines in the middle of the file to the end
so that they are in the usual place and next to the other one.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index c29f4ca93d1b..439581d7bb83 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -157,13 +157,10 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
* HMAC DRBG functions
******************************************************************/
-MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
-MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
-
/* update function of HMAC DRBG as defined in 10.1.2.2 */
static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
int reseed)
{
int i = 0;
@@ -881,5 +878,7 @@ module_init(drbg_init);
module_exit(drbg_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG)");
MODULE_ALIAS_CRYPTO("stdrng");
+MODULE_ALIAS_CRYPTO("drbg_pr_hmac_sha512");
+MODULE_ALIAS_CRYPTO("drbg_nopr_hmac_sha512");
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 26/38] crypto: drbg - Consolidate "instantiate" logic and remove drbg_state::C
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (24 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 25/38] crypto: drbg - Move module aliases to end of file Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 27/38] crypto: drbg - Eliminate use of 'drbg_string' and lists Eric Biggers
` (11 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Currently some of the steps of "Instantiate the DRBG" occur in a
convoluted way in different places in the call stack:
drbg_instantiate()
=> drbg_seed(reseed=0) sets the raw HMAC key drbg_state::C to its
correct initial value, and it sets the state value
drbg_state::V to an *incorrect* initial value.
=> drbg_hmac_update(reseed=0) overwrites drbg_state::V with the
correct initial value, then prepares the hmac_sha512_key
drbg_state::key from the initial raw HMAC key drbg_state::C.
Later, each time the HMAC key is updated, drbg_hmac_update() also uses
drbg_state::C to temporarily store the new raw key.
Simplify all of this by:
- Making drbg_instantiate() set the correct initial values of
drbg_state::V and drbg_state::key.
- Converting drbg_hmac_update() to generate the raw key in a
temporary on-stack array instead of drbg_state::C.
- Removing drbg_state::C.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 38 +++++++++++++++-----------------------
1 file changed, 15 insertions(+), 23 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 439581d7bb83..7e3ab2f811b6 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -134,11 +134,10 @@ enum drbg_seed_state {
struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */
struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */
- u8 C[DRBG_STATE_LEN]; /* current key -- 10.1.2.1 1b */
/* Number of RNG requests since last reseed -- 10.1.2.1 1c */
size_t reseed_ctr;
size_t reseed_threshold;
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
@@ -158,21 +157,15 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
* HMAC DRBG functions
******************************************************************/
/* update function of HMAC DRBG as defined in 10.1.2.2 */
-static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
- int reseed)
+static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed)
{
int i = 0;
struct hmac_sha512_ctx hmac_ctx;
-
- if (!reseed) {
- /* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
- memset(drbg->V, 1, DRBG_STATE_LEN);
- hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
- }
+ u8 new_key[DRBG_STATE_LEN];
for (i = 2; 0 < i; i--) {
/* first round uses 0x0, second 0x1 */
unsigned char prefix = DRBG_PREFIX0;
if (1 == i)
@@ -186,20 +179,21 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
list_for_each_entry(input, seed, list)
hmac_sha512_update(&hmac_ctx, input->buf,
input->len);
}
- hmac_sha512_final(&hmac_ctx, drbg->C);
- hmac_sha512_preparekey(&drbg->key, drbg->C, DRBG_STATE_LEN);
+ hmac_sha512_final(&hmac_ctx, new_key);
+ hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN);
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
/* 10.1.2.2 step 3 */
if (!seed)
break;
}
+ memzero_explicit(new_key, sizeof(new_key));
}
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
static void drbg_hmac_generate(struct drbg_state *drbg,
unsigned char *buf,
@@ -208,11 +202,11 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
{
int len = 0;
/* 10.1.2.5 step 2 */
if (addtl && !list_empty(addtl))
- drbg_hmac_update(drbg, addtl, 1);
+ drbg_hmac_update(drbg, addtl);
while (len < buflen) {
unsigned int outlen = 0;
/* 10.1.2.5 step 4.1 */
@@ -225,19 +219,19 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
len += outlen;
}
/* 10.1.2.5 step 6 */
if (addtl && !list_empty(addtl))
- drbg_hmac_update(drbg, addtl, 1);
+ drbg_hmac_update(drbg, addtl);
else
- drbg_hmac_update(drbg, NULL, 1);
+ drbg_hmac_update(drbg, NULL);
}
static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
- int reseed, enum drbg_seed_state new_seed_state)
+ enum drbg_seed_state new_seed_state)
{
- drbg_hmac_update(drbg, seed, reseed);
+ drbg_hmac_update(drbg, seed);
drbg->seeded = new_seed_state;
drbg->last_seed_time = jiffies;
drbg->reseed_ctr = 1;
@@ -273,11 +267,11 @@ static void drbg_seed_from_random(struct drbg_state *drbg)
drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH);
list_add_tail(&data.list, &seedlist);
get_random_bytes(entropy, DRBG_SEC_STRENGTH);
- __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
+ __drbg_seed(drbg, &seedlist, DRBG_SEED_STATE_FULL);
memzero_explicit(entropy, DRBG_SEC_STRENGTH);
}
static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
@@ -402,16 +396,12 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
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_STATE_LEN);
- memset(drbg->C, 0, DRBG_STATE_LEN);
- }
- __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
+ __drbg_seed(drbg, &seedlist, new_seed_state);
ret = 0;
out:
memzero_explicit(entropy, sizeof(entropy));
return ret;
@@ -422,11 +412,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
{
if (!drbg)
return;
memzero_explicit(&drbg->key, sizeof(drbg->key));
memzero_explicit(drbg->V, sizeof(drbg->V));
- memzero_explicit(drbg->C, sizeof(drbg->C));
drbg->reseed_ctr = 0;
drbg->instantiated = false;
}
/*
@@ -603,10 +592,11 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
* error value otherwise
*/
static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
bool pr)
{
+ static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */
int ret;
bool reseed = true;
pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n",
str_enabled_disabled(pr));
@@ -625,10 +615,12 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
drbg->instantiated = true;
drbg->pr = pr;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
drbg->last_seed_time = 0;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
+ memset(drbg->V, 1, DRBG_STATE_LEN);
+ hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
ret = drbg_prepare_hrng(drbg);
if (ret)
goto free_everything;
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 27/38] crypto: drbg - Eliminate use of 'drbg_string' and lists
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (25 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 26/38] crypto: drbg - Consolidate "instantiate" logic and remove drbg_state::C Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 28/38] crypto: drbg - Simplify drbg_generate_long() and fold into caller Eric Biggers
` (10 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Use straightforward (buffer, len) parameters instead of struct
drbg_string or lists of strings. This simplifies the code considerably.
For now struct drbg_string is still used in crypto_drbg_ctr_df(), so
move its definition to crypto/df_sp80090a.h.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/df_sp80090a.c | 1 -
crypto/drbg.c | 179 +++++++++++-----------------
drivers/crypto/xilinx/xilinx-trng.c | 1 -
include/crypto/df_sp80090a.h | 25 ++++
include/crypto/internal/drbg.h | 39 ------
5 files changed, 94 insertions(+), 151 deletions(-)
delete mode 100644 include/crypto/internal/drbg.h
diff --git a/crypto/df_sp80090a.c b/crypto/df_sp80090a.c
index f4bb7be016e8..90e1973ee40c 100644
--- a/crypto/df_sp80090a.c
+++ b/crypto/df_sp80090a.c
@@ -11,11 +11,10 @@
#include <linux/module.h>
#include <linux/string.h>
#include <linux/unaligned.h>
#include <crypto/aes.h>
#include <crypto/df_sp80090a.h>
-#include <crypto/internal/drbg.h>
static void drbg_kcapi_sym(struct aes_enckey *aeskey, unsigned char *outval,
const struct drbg_string *in, u8 blocklen_bytes)
{
/* there is only component in *in */
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 7e3ab2f811b6..b0cd8da51b26 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -87,11 +87,10 @@
* Usage with personalization and additional information strings
* -------------------------------------------------------------
* Just mix both scenarios above.
*/
-#include <crypto/internal/drbg.h>
#include <crypto/internal/rng.h>
#include <crypto/sha2.h>
#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
@@ -142,11 +141,12 @@ struct drbg_state {
enum drbg_seed_state seeded; /* DRBG fully seeded? */
unsigned long last_seed_time;
bool instantiated;
bool pr; /* Prediction resistance enabled? */
struct crypto_rng *jent;
- struct drbg_string test_data;
+ const u8 *test_entropy;
+ size_t test_entropylen;
};
enum drbg_prefixes {
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
@@ -157,11 +157,13 @@ static int drbg_uninstantiate(struct drbg_state *drbg);
/******************************************************************
* HMAC DRBG functions
******************************************************************/
/* update function of HMAC DRBG as defined in 10.1.2.2 */
-static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed)
+static void drbg_hmac_update(struct drbg_state *drbg,
+ const u8 *data1, size_t data1_len,
+ const u8 *data2, size_t data2_len)
{
int i = 0;
struct hmac_sha512_ctx hmac_ctx;
u8 new_key[DRBG_STATE_LEN];
@@ -172,41 +174,36 @@ static void drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed)
prefix = DRBG_PREFIX1;
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
hmac_sha512_init(&hmac_ctx, &drbg->key);
hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN);
hmac_sha512_update(&hmac_ctx, &prefix, 1);
- if (seed) {
- struct drbg_string *input;
-
- list_for_each_entry(input, seed, list)
- hmac_sha512_update(&hmac_ctx, input->buf,
- input->len);
- }
+ hmac_sha512_update(&hmac_ctx, data1, data1_len);
+ hmac_sha512_update(&hmac_ctx, data2, data2_len);
hmac_sha512_final(&hmac_ctx, new_key);
hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN);
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
/* 10.1.2.2 step 3 */
- if (!seed)
+ if (data1_len == 0 && data2_len == 0)
break;
}
memzero_explicit(new_key, sizeof(new_key));
}
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
static void drbg_hmac_generate(struct drbg_state *drbg,
unsigned char *buf,
unsigned int buflen,
- struct list_head *addtl)
+ const u8 *addtl, size_t addtl_len)
{
int len = 0;
/* 10.1.2.5 step 2 */
- if (addtl && !list_empty(addtl))
- drbg_hmac_update(drbg, addtl);
+ if (addtl_len)
+ drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0);
while (len < buflen) {
unsigned int outlen = 0;
/* 10.1.2.5 step 4.1 */
@@ -218,20 +215,19 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
memcpy(buf + len, drbg->V, outlen);
len += outlen;
}
/* 10.1.2.5 step 6 */
- if (addtl && !list_empty(addtl))
- drbg_hmac_update(drbg, addtl);
- else
- drbg_hmac_update(drbg, NULL);
+ drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0);
}
-static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
+static inline void __drbg_seed(struct drbg_state *drbg,
+ const u8 *seed1, size_t seed1_len,
+ const u8 *seed2, size_t seed2_len,
enum drbg_seed_state new_seed_state)
{
- drbg_hmac_update(drbg, seed);
+ drbg_hmac_update(drbg, seed1, seed1_len, seed2, seed2_len);
drbg->seeded = new_seed_state;
drbg->last_seed_time = jiffies;
drbg->reseed_ctr = 1;
@@ -258,30 +254,26 @@ static inline void __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
}
static void drbg_seed_from_random(struct drbg_state *drbg)
__must_hold(&drbg->drbg_mutex)
{
- struct drbg_string data;
- LIST_HEAD(seedlist);
- unsigned char entropy[DRBG_SEC_STRENGTH];
-
- drbg_string_fill(&data, entropy, DRBG_SEC_STRENGTH);
- list_add_tail(&data.list, &seedlist);
+ u8 entropy[DRBG_SEC_STRENGTH];
get_random_bytes(entropy, DRBG_SEC_STRENGTH);
- __drbg_seed(drbg, &seedlist, DRBG_SEED_STATE_FULL);
+ __drbg_seed(drbg, entropy, DRBG_SEC_STRENGTH, NULL, 0,
+ DRBG_SEED_STATE_FULL);
memzero_explicit(entropy, DRBG_SEC_STRENGTH);
}
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))
+ if (drbg->test_entropylen)
return false;
/*
* Obtain fresh entropy for the nopr DRBGs after 300s have
* elapsed in order to still achieve sort of partial
@@ -297,70 +289,70 @@ static bool drbg_nopr_reseed_interval_elapsed(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
+ * @pers_len: length of @pers in bytes
+ * @reseed: false for initial seeding (instantiation), true for reseeding
*
* return:
* 0 on success
* error value otherwise
*/
-static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
+static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
bool reseed)
__must_hold(&drbg->drbg_mutex)
{
int ret;
- unsigned char entropy[((32 + 16) * 2)];
- unsigned int entropylen;
- struct drbg_string data1;
- LIST_HEAD(seedlist);
+ u8 entropy_buf[(32 + 16) * 2];
+ size_t entropylen;
+ const u8 *entropy;
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) {
+ if (pers_len > DRBG_MAX_ADDTL) {
pr_devel("DRBG: personalization string too long %zu\n",
- pers->len);
+ pers_len);
return -EINVAL;
}
- if (list_empty(&drbg->test_data.list)) {
- drbg_string_fill(&data1, drbg->test_data.buf,
- drbg->test_data.len);
+ if (drbg->test_entropylen) {
+ entropy = drbg->test_entropy;
+ entropylen = drbg->test_entropylen;
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.
*/
+ entropy = entropy_buf;
if (!reseed)
entropylen = ((DRBG_SEC_STRENGTH + 1) / 2) * 3;
else
entropylen = DRBG_SEC_STRENGTH;
- BUG_ON((entropylen * 2) > sizeof(entropy));
+ BUG_ON(entropylen * 2 > sizeof(entropy_buf));
/* Get seed from in-kernel /dev/urandom */
if (!rng_is_initialized())
new_seed_state = DRBG_SEED_STATE_PARTIAL;
- get_random_bytes(entropy, entropylen);
+ get_random_bytes(entropy_buf, entropylen);
if (!drbg->jent) {
- drbg_string_fill(&data1, entropy, entropylen);
- pr_devel("DRBG: (re)seeding with %u bytes of entropy\n",
+ pr_devel("DRBG: (re)seeding with %zu 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,
+ &entropy_buf[entropylen],
entropylen);
if (fips_enabled && ret) {
pr_devel("DRBG: jent failed with %d\n", ret);
/*
@@ -379,32 +371,23 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
*/
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);
+ entropylen *= 2;
+ pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
+ entropylen);
}
}
- 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);
+ if (pers_len)
pr_devel("DRBG: using personalization string\n");
- }
-
- __drbg_seed(drbg, &seedlist, new_seed_state);
+ __drbg_seed(drbg, entropy, entropylen, pers, pers_len, new_seed_state);
ret = 0;
out:
- memzero_explicit(entropy, sizeof(entropy));
+ memzero_explicit(entropy_buf, sizeof(entropy_buf));
return ret;
}
/* Free all substructures in a DRBG state without the DRBG state structure */
@@ -425,34 +408,31 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
* @drbg DRBG state handle
* @buf Buffer where to store the random numbers -- the buffer must already
* be pre-allocated by caller
* @buflen Length of output buffer - this value defines the number of random
* bytes pulled from DRBG
- * @addtl Additional input 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.
+ * @addtl Optional additional input that is mixed into state
+ * @addtl_len Length of @addtl in bytes, may be 0
*
* return: 0 when all bytes are generated; < 0 in case of an error
*/
static int drbg_generate(struct drbg_state *drbg,
unsigned char *buf, unsigned int buflen,
- struct drbg_string *addtl)
+ const u8 *addtl, size_t addtl_len)
__must_hold(&drbg->drbg_mutex)
{
int len = 0;
- LIST_HEAD(addtllist);
if (!drbg->instantiated) {
pr_devel("DRBG: not yet instantiated\n");
return -EINVAL;
}
if (0 == buflen || !buf) {
pr_devel("DRBG: no output buffer provided\n");
return -EINVAL;
}
- if (addtl && NULL == addtl->buf && 0 < addtl->len) {
+ if (addtl == NULL && addtl_len != 0) {
pr_devel("DRBG: wrong format of additional information\n");
return -EINVAL;
}
/* 9.3.1 step 2 */
@@ -463,13 +443,13 @@ static int drbg_generate(struct drbg_state *drbg,
}
/* 9.3.1 step 3 is implicit with the chosen DRBG */
/* 9.3.1 step 4 */
- if (addtl && addtl->len > DRBG_MAX_ADDTL) {
+ if (addtl_len > DRBG_MAX_ADDTL) {
pr_devel("DRBG: additional information string too long %zu\n",
- addtl->len);
+ addtl_len);
return -EINVAL;
}
/* 9.3.1 step 5 is implicit with the chosen DRBG */
/*
@@ -484,25 +464,24 @@ static int drbg_generate(struct drbg_state *drbg,
"resistance: %s, state %s)\n",
str_true_false(drbg->pr),
(drbg->seeded == DRBG_SEED_STATE_FULL ?
"seeded" : "unseeded"));
/* 9.3.1 steps 7.1 through 7.3 */
- len = drbg_seed(drbg, addtl, true);
+ len = drbg_seed(drbg, addtl, addtl_len, true);
if (len)
goto err;
/* 9.3.1 step 7.4 */
addtl = NULL;
+ addtl_len = 0;
} else if (rng_is_initialized() &&
(drbg->seeded == DRBG_SEED_STATE_PARTIAL ||
drbg_nopr_reseed_interval_elapsed(drbg))) {
drbg_seed_from_random(drbg);
}
- if (addtl && 0 < addtl->len)
- list_add_tail(&addtl->list, &addtllist);
/* 9.3.1 step 8 and 10 */
- drbg_hmac_generate(drbg, buf, buflen, &addtllist);
+ drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len);
/* 10.1.2.5 step 7 */
drbg->reseed_ctr++;
/*
@@ -535,21 +514,21 @@ static int drbg_generate(struct drbg_state *drbg,
* Return codes: see drbg_generate -- if one drbg_generate request fails,
* the entire drbg_generate_long request fails
*/
static int drbg_generate_long(struct drbg_state *drbg,
unsigned char *buf, unsigned int buflen,
- struct drbg_string *addtl)
+ const u8 *addtl, size_t addtl_len)
{
unsigned int len = 0;
unsigned int slice = 0;
do {
int err = 0;
unsigned int chunk = 0;
slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES;
chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len);
mutex_lock(&drbg->drbg_mutex);
- err = drbg_generate(drbg, buf + len, chunk, addtl);
+ err = drbg_generate(drbg, buf + len, chunk, addtl, addtl_len);
mutex_unlock(&drbg->drbg_mutex);
if (0 > err)
return err;
len += chunk;
} while (slice > 0 && (len < buflen));
@@ -557,11 +536,11 @@ static int drbg_generate_long(struct drbg_state *drbg,
}
static int drbg_prepare_hrng(struct drbg_state *drbg)
{
/* We do not need an HRNG in test mode. */
- if (list_empty(&drbg->test_data.list))
+ if (drbg->test_entropylen != 0)
return 0;
drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
if (IS_ERR(drbg->jent)) {
const int err = PTR_ERR(drbg->jent);
@@ -579,22 +558,20 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
* 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
*
* @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.
+ * @pers Optional personalization string that is mixed into state
+ * @pers_len Length of personalization string in bytes, may be 0
* @pr prediction resistance enabled
*
* return
* 0 on success
* error value otherwise
*/
-static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
- bool pr)
+static int drbg_instantiate(struct drbg_state *drbg,
+ const u8 *pers, size_t pers_len, bool pr)
{
static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */
int ret;
bool reseed = true;
@@ -625,11 +602,11 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers,
goto free_everything;
reseed = false;
}
- ret = drbg_seed(drbg, pers, reseed);
+ ret = drbg_seed(drbg, pers, pers_len, reseed);
if (ret && !reseed)
goto free_everything;
mutex_unlock(&drbg->drbg_mutex);
@@ -672,11 +649,12 @@ 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);
+ drbg->test_entropy = data;
+ drbg->test_entropylen = len;
mutex_unlock(&drbg->drbg_mutex);
}
/***************************************************************
* Kernel crypto API interface to register DRBG
@@ -708,36 +686,21 @@ static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
static int drbg_kcapi_random(struct crypto_rng *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
- struct drbg_string *addtl = NULL;
- struct drbg_string string;
-
- if (slen) {
- /* linked list variable is now local to allow modification */
- drbg_string_fill(&string, src, slen);
- addtl = &string;
- }
- return drbg_generate_long(drbg, dst, dlen, addtl);
+ return drbg_generate_long(drbg, dst, dlen, src, slen);
}
/* Seed (i.e. instantiate) or re-seed the DRBG. */
static int drbg_kcapi_seed(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen, bool pr)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
- struct drbg_string string;
- struct drbg_string *seed_string = NULL;
- if (0 < slen) {
- drbg_string_fill(&string, seed, slen);
- seed_string = &string;
- }
-
- return drbg_instantiate(drbg, seed_string, pr);
+ return drbg_instantiate(drbg, seed, slen, pr);
}
static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen)
{
@@ -765,15 +728,13 @@ static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm,
* enforcement, so skip it.
*/
static inline int __init drbg_healthcheck_sanity(void)
{
#define OUTBUFLEN 16
- unsigned char buf[OUTBUFLEN];
+ u8 buf[OUTBUFLEN];
struct drbg_state *drbg = NULL;
int ret;
- int rc = -EFAULT;
- struct drbg_string addtl;
/* only perform test in FIPS mode */
if (!fips_enabled)
return 0;
@@ -791,29 +752,27 @@ static inline int __init drbg_healthcheck_sanity(void)
* string lengths -- in case the error handling does not succeed
* we may get an OOPS. And we want to get an OOPS as this is a
* grave bug.
*/
- drbg_string_fill(&addtl, buf, DRBG_MAX_ADDTL + 1);
/* overflow addtllen with additional info string */
- ret = drbg_generate(drbg, buf, OUTBUFLEN, &addtl);
+ ret = drbg_generate(drbg, buf, OUTBUFLEN, buf, DRBG_MAX_ADDTL + 1);
BUG_ON(ret == 0);
/* overflow max_bits */
- ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL);
+ ret = drbg_generate(drbg, buf, DRBG_MAX_REQUEST_BYTES + 1, NULL, 0);
BUG_ON(ret == 0);
/* overflow max addtllen with personalization string */
- ret = drbg_seed(drbg, &addtl, false);
- BUG_ON(0 == ret);
+ ret = drbg_seed(drbg, buf, DRBG_MAX_ADDTL + 1, false);
+ BUG_ON(ret == 0);
/* all tests passed */
- rc = 0;
pr_devel("DRBG: Sanity tests for failure code paths successfully "
"completed\n");
kfree(drbg);
- return rc;
+ return 0;
}
static struct rng_alg drbg_algs[] = {
{
.base.cra_name = "stdrng",
diff --git a/drivers/crypto/xilinx/xilinx-trng.c b/drivers/crypto/xilinx/xilinx-trng.c
index 5276ac2d82bb..43a4832f07e7 100644
--- a/drivers/crypto/xilinx/xilinx-trng.c
+++ b/drivers/crypto/xilinx/xilinx-trng.c
@@ -17,11 +17,10 @@
#include <linux/mutex.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <crypto/aes.h>
#include <crypto/df_sp80090a.h>
-#include <crypto/internal/drbg.h>
#include <crypto/internal/cipher.h>
#include <crypto/internal/rng.h>
/* TRNG Registers Offsets */
#define TRNG_STATUS_OFFSET 0x4U
diff --git a/include/crypto/df_sp80090a.h b/include/crypto/df_sp80090a.h
index cb5d6fe15d40..e594fb718eb8 100644
--- a/include/crypto/df_sp80090a.h
+++ b/include/crypto/df_sp80090a.h
@@ -7,10 +7,35 @@
#ifndef _CRYPTO_DF80090A_H
#define _CRYPTO_DF80090A_H
#include <crypto/internal/cipher.h>
#include <crypto/aes.h>
+#include <linux/list.h>
+
+/*
+ * Concatenation Helper and string operation helper
+ *
+ * SP800-90A requires the concatenation of different data. To avoid copying
+ * buffers around or allocate additional memory, the following data structure
+ * is used to point to the original memory with its size. In addition, it
+ * is used to build a linked list. The linked list defines the concatenation
+ * of individual buffers. The order of memory block referenced in that
+ * linked list determines the order of concatenation.
+ */
+struct drbg_string {
+ const unsigned char *buf;
+ size_t len;
+ struct list_head list;
+};
+
+static inline void drbg_string_fill(struct drbg_string *string,
+ const unsigned char *buf, size_t len)
+{
+ string->buf = buf;
+ string->len = len;
+ INIT_LIST_HEAD(&string->list);
+}
static inline int crypto_drbg_ctr_df_datalen(u8 statelen, u8 blocklen)
{
return statelen + /* df_data */
blocklen + /* pad */
diff --git a/include/crypto/internal/drbg.h b/include/crypto/internal/drbg.h
deleted file mode 100644
index 5d4174cc6a53..000000000000
--- a/include/crypto/internal/drbg.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-/*
- * NIST SP800-90A DRBG derivation function
- *
- * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
- */
-
-#ifndef _INTERNAL_DRBG_H
-#define _INTERNAL_DRBG_H
-
-#include <linux/list.h>
-#include <linux/types.h>
-
-/*
- * Concatenation Helper and string operation helper
- *
- * SP800-90A requires the concatenation of different data. To avoid copying
- * buffers around or allocate additional memory, the following data structure
- * is used to point to the original memory with its size. In addition, it
- * is used to build a linked list. The linked list defines the concatenation
- * of individual buffers. The order of memory block referenced in that
- * linked list determines the order of concatenation.
- */
-struct drbg_string {
- const unsigned char *buf;
- size_t len;
- struct list_head list;
-};
-
-static inline void drbg_string_fill(struct drbg_string *string,
- const unsigned char *buf, size_t len)
-{
- string->buf = buf;
- string->len = len;
- INIT_LIST_HEAD(&string->list);
-}
-
-#endif //_INTERNAL_DRBG_H
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 28/38] crypto: drbg - Simplify drbg_generate_long() and fold into caller
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (26 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 27/38] crypto: drbg - Eliminate use of 'drbg_string' and lists Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 29/38] crypto: drbg - Put rng_alg methods in logical order Eric Biggers
` (9 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Simplify drbg_generate_long() to use a more straightforward loop, and
then fold it into its only caller. No functional change.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 48 +++++++++++++++++-------------------------------
1 file changed, 17 insertions(+), 31 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index b0cd8da51b26..9ff1a0e1b129 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -504,39 +504,10 @@ static int drbg_generate(struct drbg_state *drbg,
len = 0;
err:
return len;
}
-/*
- * Wrapper around drbg_generate which can pull arbitrary long strings
- * from the DRBG without hitting the maximum request limitation.
- *
- * Parameters: see drbg_generate
- * Return codes: see drbg_generate -- if one drbg_generate request fails,
- * the entire drbg_generate_long request fails
- */
-static int drbg_generate_long(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
- const u8 *addtl, size_t addtl_len)
-{
- unsigned int len = 0;
- unsigned int slice = 0;
- do {
- int err = 0;
- unsigned int chunk = 0;
- slice = (buflen - len) / DRBG_MAX_REQUEST_BYTES;
- chunk = slice ? DRBG_MAX_REQUEST_BYTES : (buflen - len);
- mutex_lock(&drbg->drbg_mutex);
- err = drbg_generate(drbg, buf + len, chunk, addtl, addtl_len);
- mutex_unlock(&drbg->drbg_mutex);
- if (0 > err)
- return err;
- len += chunk;
- } while (slice > 0 && (len < buflen));
- return 0;
-}
-
static int drbg_prepare_hrng(struct drbg_state *drbg)
{
/* We do not need an HRNG in test mode. */
if (drbg->test_entropylen != 0)
return 0;
@@ -674,11 +645,10 @@ static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
drbg_uninstantiate(crypto_tfm_ctx(tfm));
}
/*
* Generate random numbers invoked by the kernel crypto API:
- * The API of the kernel crypto API is extended as follows:
*
* src is additional input supplied to the RNG.
* slen is the length of src.
* dst is the output buffer where random data is to be stored.
* dlen is the length of dst.
@@ -687,11 +657,27 @@ static int drbg_kcapi_random(struct crypto_rng *tfm,
const u8 *src, unsigned int slen,
u8 *dst, unsigned int dlen)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
- return drbg_generate_long(drbg, dst, dlen, src, slen);
+ /*
+ * Break the request into multiple requests if needed, to avoid
+ * exceeding the maximum request length of the core algorithm.
+ */
+ do {
+ unsigned int n = min(dlen, DRBG_MAX_REQUEST_BYTES);
+ int err;
+
+ mutex_lock(&drbg->drbg_mutex);
+ err = drbg_generate(drbg, dst, n, src, slen);
+ mutex_unlock(&drbg->drbg_mutex);
+ if (err < 0)
+ return err;
+ dst += n;
+ dlen -= n;
+ } while (dlen);
+ return 0;
}
/* Seed (i.e. instantiate) or re-seed the DRBG. */
static int drbg_kcapi_seed(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen, bool pr)
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 29/38] crypto: drbg - Put rng_alg methods in logical order
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (27 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 28/38] crypto: drbg - Simplify drbg_generate_long() and fold into caller Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 30/38] crypto: drbg - Fold drbg_instantiate() into drbg_kcapi_seed() Eric Biggers
` (8 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Put the DRBG implementation of the rng_alg methods in the order in which
they're called (cra_init => set_ent => seed => generate => cra_exit) so
that it's easier to understand the flow.
Also rename drbg_kcapi_random to drbg_kcapi_generate, and
drbg_kcapi_cleanup to drbg_kcapi_exit, so they match the method names.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 82 ++++++++++++++++++++++-----------------------------
1 file changed, 36 insertions(+), 46 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 9ff1a0e1b129..ef9c3e9fdf6e 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -607,17 +607,24 @@ static int drbg_uninstantiate(struct drbg_state *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
- */
+/***************************************************************
+ * Kernel crypto API interface to DRBG
+ ***************************************************************/
+
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+
+ mutex_init(&drbg->drbg_mutex);
+
+ return 0;
+}
+
+/* Set test entropy in the DRBG. */
static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
const u8 *data, unsigned int len)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
@@ -625,39 +632,42 @@ static void drbg_kcapi_set_entropy(struct crypto_rng *tfm,
drbg->test_entropy = data;
drbg->test_entropylen = len;
mutex_unlock(&drbg->drbg_mutex);
}
-/***************************************************************
- * Kernel crypto API interface to register DRBG
- ***************************************************************/
-
-static int drbg_kcapi_init(struct crypto_tfm *tfm)
+/* Seed (i.e. instantiate) or re-seed the DRBG. */
+static int drbg_kcapi_seed(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen, bool pr)
{
- struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
- mutex_init(&drbg->drbg_mutex);
+ return drbg_instantiate(drbg, seed, slen, pr);
+}
- return 0;
+static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen)
+{
+ return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true);
}
-static void drbg_kcapi_cleanup(struct crypto_tfm *tfm)
+static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm,
+ const u8 *seed, unsigned int slen)
{
- drbg_uninstantiate(crypto_tfm_ctx(tfm));
+ return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false);
}
/*
* Generate random numbers invoked by the kernel crypto API:
*
* src is additional input supplied to the RNG.
* slen is the length of src.
* dst is the output buffer where random data is to be stored.
* dlen is the length of dst.
*/
-static int drbg_kcapi_random(struct crypto_rng *tfm,
- const u8 *src, unsigned int slen,
- u8 *dst, unsigned int dlen)
+static int drbg_kcapi_generate(struct crypto_rng *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
{
struct drbg_state *drbg = crypto_rng_ctx(tfm);
/*
* Break the request into multiple requests if needed, to avoid
@@ -676,35 +686,15 @@ static int drbg_kcapi_random(struct crypto_rng *tfm,
dlen -= n;
} while (dlen);
return 0;
}
-/* Seed (i.e. instantiate) or re-seed the DRBG. */
-static int drbg_kcapi_seed(struct crypto_rng *tfm,
- const u8 *seed, unsigned int slen, bool pr)
+static void drbg_kcapi_exit(struct crypto_tfm *tfm)
{
- struct drbg_state *drbg = crypto_rng_ctx(tfm);
-
- return drbg_instantiate(drbg, seed, slen, pr);
-}
-
-static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
- const u8 *seed, unsigned int slen)
-{
- return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true);
-}
-
-static int drbg_kcapi_seed_nopr(struct crypto_rng *tfm,
- const u8 *seed, unsigned int slen)
-{
- return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ false);
+ drbg_uninstantiate(crypto_tfm_ctx(tfm));
}
-/***************************************************************
- * Kernel module: code to load the module
- ***************************************************************/
-
/*
* Tests as defined in 11.3.2 in addition to the cipher tests: testing
* of the error handling.
*
* Note: testing of failing seed source as defined in 11.3.2 is not applicable
@@ -767,24 +757,24 @@ static struct rng_alg drbg_algs[] = {
.base.cra_ctxsize = sizeof(struct drbg_state),
.base.cra_module = THIS_MODULE,
.base.cra_init = drbg_kcapi_init,
.set_ent = drbg_kcapi_set_entropy,
.seed = drbg_kcapi_seed_pr,
- .generate = drbg_kcapi_random,
- .base.cra_exit = drbg_kcapi_cleanup,
+ .generate = drbg_kcapi_generate,
+ .base.cra_exit = drbg_kcapi_exit,
},
{
.base.cra_name = "stdrng",
.base.cra_driver_name = "drbg_nopr_hmac_sha512",
.base.cra_priority = 201,
.base.cra_ctxsize = sizeof(struct drbg_state),
.base.cra_module = THIS_MODULE,
.base.cra_init = drbg_kcapi_init,
.set_ent = drbg_kcapi_set_entropy,
.seed = drbg_kcapi_seed_nopr,
- .generate = drbg_kcapi_random,
- .base.cra_exit = drbg_kcapi_cleanup,
+ .generate = drbg_kcapi_generate,
+ .base.cra_exit = drbg_kcapi_exit,
},
};
static int __init drbg_init(void)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 30/38] crypto: drbg - Fold drbg_instantiate() into drbg_kcapi_seed()
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (28 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 29/38] crypto: drbg - Put rng_alg methods in logical order Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 31/38] crypto: drbg - Separate "reseed" case in drbg_kcapi_seed() Eric Biggers
` (7 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Fold drbg_instantiate() into its only caller.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 107 ++++++++++++++++++++------------------------------
1 file changed, 43 insertions(+), 64 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index ef9c3e9fdf6e..763c14e3786c 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -524,27 +524,60 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
return 0;
}
/*
- * 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
+ * DRBG uninstantiate function as required by SP800-90A - this function
+ * frees all buffers and the DRBG handle
*
- * @drbg memory of state -- if NULL, new memory is allocated
- * @pers Optional personalization string that is mixed into state
- * @pers_len Length of personalization string in bytes, may be 0
- * @pr prediction resistance enabled
+ * @drbg DRBG state handle
*
* return
* 0 on success
- * error value otherwise
*/
-static int drbg_instantiate(struct drbg_state *drbg,
- const u8 *pers, size_t pers_len, bool pr)
+static int drbg_uninstantiate(struct drbg_state *drbg)
+{
+ if (!IS_ERR_OR_NULL(drbg->jent))
+ crypto_free_rng(drbg->jent);
+ drbg->jent = NULL;
+
+ drbg_dealloc_state(drbg);
+ /* no scrubbing of test_data -- this shall survive an uninstantiate */
+ return 0;
+}
+
+/***************************************************************
+ * Kernel crypto API interface to DRBG
+ ***************************************************************/
+
+static int drbg_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+
+ mutex_init(&drbg->drbg_mutex);
+
+ return 0;
+}
+
+/* Set test entropy in the DRBG. */
+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->test_entropy = data;
+ drbg->test_entropylen = len;
+ mutex_unlock(&drbg->drbg_mutex);
+}
+
+/* Seed (i.e. instantiate) or re-seed the DRBG. */
+static int drbg_kcapi_seed(struct crypto_rng *tfm,
+ const u8 *pers, size_t pers_len, bool pr)
{
static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */
+ struct drbg_state *drbg = crypto_rng_ctx(tfm);
int ret;
bool reseed = true;
pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n",
str_enabled_disabled(pr));
@@ -587,64 +620,10 @@ static int drbg_instantiate(struct drbg_state *drbg,
mutex_unlock(&drbg->drbg_mutex);
drbg_uninstantiate(drbg);
return ret;
}
-/*
- * DRBG uninstantiate function as required by SP800-90A - this function
- * frees all buffers and the DRBG handle
- *
- * @drbg DRBG state handle
- *
- * return
- * 0 on success
- */
-static int drbg_uninstantiate(struct drbg_state *drbg)
-{
- if (!IS_ERR_OR_NULL(drbg->jent))
- crypto_free_rng(drbg->jent);
- drbg->jent = NULL;
-
- drbg_dealloc_state(drbg);
- /* no scrubbing of test_data -- this shall survive an uninstantiate */
- return 0;
-}
-
-/***************************************************************
- * Kernel crypto API interface to DRBG
- ***************************************************************/
-
-static int drbg_kcapi_init(struct crypto_tfm *tfm)
-{
- struct drbg_state *drbg = crypto_tfm_ctx(tfm);
-
- mutex_init(&drbg->drbg_mutex);
-
- return 0;
-}
-
-/* Set test entropy in the DRBG. */
-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->test_entropy = data;
- drbg->test_entropylen = len;
- mutex_unlock(&drbg->drbg_mutex);
-}
-
-/* Seed (i.e. instantiate) or re-seed the DRBG. */
-static int drbg_kcapi_seed(struct crypto_rng *tfm,
- const u8 *seed, unsigned int slen, bool pr)
-{
- struct drbg_state *drbg = crypto_rng_ctx(tfm);
-
- return drbg_instantiate(drbg, seed, slen, pr);
-}
-
static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen)
{
return drbg_kcapi_seed(tfm, seed, slen, /* pr= */ true);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 31/38] crypto: drbg - Separate "reseed" case in drbg_kcapi_seed()
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (29 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 30/38] crypto: drbg - Fold drbg_instantiate() into drbg_kcapi_seed() Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 32/38] crypto: drbg - Fold drbg_prepare_hrng() into drbg_kcapi_seed() Eric Biggers
` (6 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Clearly separate the code for the "reseed" and "instantiate" cases,
since what they need to do is quite different.
Note that the mutex guard makes the mutex start being held during the
call to drbg_uninstantiate(), which is fine.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 38 ++++++++++++++++----------------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 763c14e3786c..a9d586107ebe 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -575,51 +575,45 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
const u8 *pers, size_t pers_len, bool pr)
{
static const u8 initial_key[DRBG_STATE_LEN]; /* all zeroes */
struct drbg_state *drbg = crypto_rng_ctx(tfm);
int ret;
- bool reseed = true;
pr_devel("DRBG: Initializing DRBG with prediction resistance %s\n",
str_enabled_disabled(pr));
- mutex_lock(&drbg->drbg_mutex);
+ guard(mutex)(&drbg->drbg_mutex);
+
+ if (drbg->instantiated)
+ return drbg_seed(drbg, pers, pers_len, /* reseed= */ true);
/* 9.1 step 1 is implicit with the selected DRBG type */
/*
* 9.1 step 2 is implicit as caller can select prediction resistance
* all DRBG types support prediction resistance
*/
/* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
- if (!drbg->instantiated) {
- drbg->instantiated = true;
- drbg->pr = pr;
- drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
- drbg->last_seed_time = 0;
- drbg->reseed_threshold = DRBG_MAX_REQUESTS;
- memset(drbg->V, 1, DRBG_STATE_LEN);
- hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
-
- ret = drbg_prepare_hrng(drbg);
- if (ret)
- goto free_everything;
-
- reseed = false;
- }
-
- ret = drbg_seed(drbg, pers, pers_len, reseed);
+ drbg->instantiated = true;
+ drbg->pr = pr;
+ drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
+ drbg->last_seed_time = 0;
+ drbg->reseed_threshold = DRBG_MAX_REQUESTS;
+ memset(drbg->V, 1, DRBG_STATE_LEN);
+ hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
- if (ret && !reseed)
+ ret = drbg_prepare_hrng(drbg);
+ if (ret)
+ goto free_everything;
+ ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false);
+ if (ret)
goto free_everything;
- mutex_unlock(&drbg->drbg_mutex);
return ret;
free_everything:
- mutex_unlock(&drbg->drbg_mutex);
drbg_uninstantiate(drbg);
return ret;
}
static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 32/38] crypto: drbg - Fold drbg_prepare_hrng() into drbg_kcapi_seed()
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (30 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 31/38] crypto: drbg - Separate "reseed" case in drbg_kcapi_seed() Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 33/38] crypto: drbg - Simplify "uninstantiate" logic Eric Biggers
` (5 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Fold drbg_prepare_hrng() into its only caller.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 34 ++++++++++++----------------------
1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index a9d586107ebe..45d97f3ba4ef 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -504,29 +504,10 @@ static int drbg_generate(struct drbg_state *drbg,
len = 0;
err:
return len;
}
-static int drbg_prepare_hrng(struct drbg_state *drbg)
-{
- /* We do not need an HRNG in test mode. */
- if (drbg->test_entropylen != 0)
- return 0;
-
- drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
- if (IS_ERR(drbg->jent)) {
- const int err = PTR_ERR(drbg->jent);
-
- drbg->jent = NULL;
- if (fips_enabled)
- return err;
- pr_info("DRBG: Continuing without Jitter RNG\n");
- }
-
- return 0;
-}
-
/*
* DRBG uninstantiate function as required by SP800-90A - this function
* frees all buffers and the DRBG handle
*
* @drbg DRBG state handle
@@ -600,13 +581,22 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
drbg->last_seed_time = 0;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
memset(drbg->V, 1, DRBG_STATE_LEN);
hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
- ret = drbg_prepare_hrng(drbg);
- if (ret)
- goto free_everything;
+ /* Allocate jitterentropy_rng if not in test mode. */
+ if (drbg->test_entropylen == 0) {
+ drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
+ if (IS_ERR(drbg->jent)) {
+ ret = PTR_ERR(drbg->jent);
+ drbg->jent = NULL;
+ if (fips_enabled)
+ goto free_everything;
+ pr_info("DRBG: Continuing without Jitter RNG\n");
+ }
+ }
+
ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false);
if (ret)
goto free_everything;
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 33/38] crypto: drbg - Simplify "uninstantiate" logic
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (31 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 32/38] crypto: drbg - Fold drbg_prepare_hrng() into drbg_kcapi_seed() Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 34/38] crypto: drbg - Include get_random_bytes() output in additional input Eric Biggers
` (4 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
drbg_kcapi_seed() calls drbg_uninstantiate() only to free drbg->jent and
set drbg->instantiated = false. However, the latter is necessary only
because drbg_kcapi_seed() sets drbg->instantiated = true too early. Fix
that, then just inline the freeing of drbg->jent.
Then, simplify the actual "uninstantiate" in drbg_kcapi_exit(). Just
free drbg->jent (note that this is a no-op on error and null pointers),
then memzero_explicit() the entire drbg_state.
Note that in reality the memzero_explicit() is redundant, since the
crypto_rng API zeroizes the memory anyway. But the way SP800-90A is
worded, it's easy to imagine that someone assessing conformance with it
would be looking for code in drbg.c that says it does an "Uninstantiate"
and does the zeroization. So it's probably worth keeping it somewhat
explicit, even though that means double zeroization in practice.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 57 ++++++++++++---------------------------------------
1 file changed, 13 insertions(+), 44 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 45d97f3ba4ef..b2af481aef01 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -150,12 +150,10 @@ struct drbg_state {
enum drbg_prefixes {
DRBG_PREFIX0 = 0x00,
DRBG_PREFIX1,
};
-static int drbg_uninstantiate(struct drbg_state *drbg);
-
/******************************************************************
* HMAC DRBG functions
******************************************************************/
/* update function of HMAC DRBG as defined in 10.1.2.2 */
@@ -388,21 +386,10 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
memzero_explicit(entropy_buf, sizeof(entropy_buf));
return ret;
}
-/* Free all substructures in a DRBG state without the DRBG state structure */
-static inline void drbg_dealloc_state(struct drbg_state *drbg)
-{
- if (!drbg)
- return;
- memzero_explicit(&drbg->key, sizeof(drbg->key));
- memzero_explicit(drbg->V, sizeof(drbg->V));
- drbg->reseed_ctr = 0;
- drbg->instantiated = false;
-}
-
/*
* DRBG generate function as required by SP800-90A - this function
* generates random numbers
*
* @drbg DRBG state handle
@@ -504,30 +491,10 @@ static int drbg_generate(struct drbg_state *drbg,
len = 0;
err:
return len;
}
-/*
- * DRBG uninstantiate function as required by SP800-90A - this function
- * frees all buffers and the DRBG handle
- *
- * @drbg DRBG state handle
- *
- * return
- * 0 on success
- */
-static int drbg_uninstantiate(struct drbg_state *drbg)
-{
- if (!IS_ERR_OR_NULL(drbg->jent))
- crypto_free_rng(drbg->jent);
- drbg->jent = NULL;
-
- drbg_dealloc_state(drbg);
- /* no scrubbing of test_data -- this shall survive an uninstantiate */
- return 0;
-}
-
/***************************************************************
* Kernel crypto API interface to DRBG
***************************************************************/
static int drbg_kcapi_init(struct crypto_tfm *tfm)
@@ -573,11 +540,10 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
* all DRBG types support prediction resistance
*/
/* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
- drbg->instantiated = true;
drbg->pr = pr;
drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
drbg->last_seed_time = 0;
drbg->reseed_threshold = DRBG_MAX_REQUESTS;
memset(drbg->V, 1, DRBG_STATE_LEN);
@@ -588,24 +554,23 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
if (IS_ERR(drbg->jent)) {
ret = PTR_ERR(drbg->jent);
drbg->jent = NULL;
if (fips_enabled)
- goto free_everything;
+ return ret;
pr_info("DRBG: Continuing without Jitter RNG\n");
}
}
ret = drbg_seed(drbg, pers, pers_len, /* reseed= */ false);
- if (ret)
- goto free_everything;
-
- return ret;
-
-free_everything:
- drbg_uninstantiate(drbg);
- return ret;
+ if (ret) {
+ crypto_free_rng(drbg->jent);
+ drbg->jent = NULL;
+ return ret;
+ }
+ drbg->instantiated = true;
+ return 0;
}
static int drbg_kcapi_seed_pr(struct crypto_rng *tfm,
const u8 *seed, unsigned int slen)
{
@@ -649,13 +614,17 @@ static int drbg_kcapi_generate(struct crypto_rng *tfm,
dlen -= n;
} while (dlen);
return 0;
}
+/* Uninstantiate the DRBG. */
static void drbg_kcapi_exit(struct crypto_tfm *tfm)
{
- drbg_uninstantiate(crypto_tfm_ctx(tfm));
+ struct drbg_state *drbg = crypto_tfm_ctx(tfm);
+
+ crypto_free_rng(drbg->jent);
+ memzero_explicit(drbg, sizeof(*drbg));
}
/*
* Tests as defined in 11.3.2 in addition to the cipher tests: testing
* of the error handling.
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 34/38] crypto: drbg - Include get_random_bytes() output in additional input
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (32 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 33/38] crypto: drbg - Simplify "uninstantiate" logic Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 35/38] crypto: drbg - Change DRBG_MAX_REQUESTS to 4096 Eric Biggers
` (3 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Woodage & Shumow (2018) (https://eprint.iacr.org/2018/349.pdf) showed
that contrary to the claims made by NIST in SP800-90A, HMAC_DRBG doesn't
satisfy the formal definition of forward secrecy (i.e. "backtracking
resistance") when it's called with an empty additional input string.
The actual attack seems pretty benign, as it doesn't actually give the
attacker any previous RNG output, but rather just allows them to test
whether their guess of the previous block of RNG output is correct.
Regardless, it's an annoying design flaw, and it's yet another example
of why NIST's DRBGs aren't all that great.
Meanwhile, the kernel's HMAC_DRBG code also tries to reseed itself
automatically after random.c has reseeded itself. But the
implementation is buggy, as it just checks whether 300 seconds have
elapsed, rather than looking at the actual generation counter.
Let's just follow the example of BoringSSL and use the conservative
approach of always including 32 bytes of "regular" random data in the
additional input string. This fixes both issues described above.
This does reduce performance. But this should be tolerable, since:
- Due to earlier changes, the kernel code that was previously using
drbg.c regardless of FIPS mode is now using it only in FIPS mode.
- The additional input string is processed only once per request. So
if a lot of bytes are generated at once, the cost is amortized.
- The NIST DRBGs are notoriously slow anyway.
Note that this fix should have no impact (either positive or negative)
on FIPS 140 certifiability. From FIPS's point of view the code added by
this commit simply doesn't matter: it adds zero entropy to something
that doesn't need to contain entropy.
Fixes: 541af946fe13 ("crypto: drbg - SP800-90A Deterministic Random Bit Generator")
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index b2af481aef01..cda79d601f4f 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -191,17 +191,36 @@ static void drbg_hmac_update(struct drbg_state *drbg,
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
static void drbg_hmac_generate(struct drbg_state *drbg,
unsigned char *buf,
unsigned int buflen,
- const u8 *addtl, size_t addtl_len)
+ const u8 *addtl1, size_t addtl1_len)
{
int len = 0;
+ u8 addtl2[32];
+ size_t addtl2_len = 0;
+
+ /*
+ * Append some bytes from get_random_bytes() to the additional input
+ * string, except when in test mode (as it would break the tests).
+ * Using a nonempty additional input string works around the forward
+ * secrecy bug in HMAC_DRBG described by Woodage & Shumow (2018)
+ * (https://eprint.iacr.org/2018/349.pdf). Filling the string with
+ * get_random_bytes() rather than a fixed value is safer still, and in
+ * particular makes random.c reseeds be immediately reflected.
+ *
+ * Note that there's no need to pull bytes from jitterentropy here too,
+ * since FIPS doesn't require any entropy in the additional input.
+ */
+ if (drbg->test_entropylen == 0) {
+ get_random_bytes(addtl2, sizeof(addtl2));
+ addtl2_len = sizeof(addtl2);
+ }
/* 10.1.2.5 step 2 */
- if (addtl_len)
- drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0);
+ if (addtl1_len || addtl2_len)
+ drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
while (len < buflen) {
unsigned int outlen = 0;
/* 10.1.2.5 step 4.1 */
@@ -213,11 +232,13 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
memcpy(buf + len, drbg->V, outlen);
len += outlen;
}
/* 10.1.2.5 step 6 */
- drbg_hmac_update(drbg, addtl, addtl_len, NULL, 0);
+ drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
+
+ memzero_explicit(addtl2, sizeof(addtl2));
}
static inline void __drbg_seed(struct drbg_state *drbg,
const u8 *seed1, size_t seed1_len,
const u8 *seed2, size_t seed2_len,
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 35/38] crypto: drbg - Change DRBG_MAX_REQUESTS to 4096
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (33 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 34/38] crypto: drbg - Include get_random_bytes() output in additional input Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state Eric Biggers
` (2 subsequent siblings)
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
Currently a formal reseed happens only after each 1048576 requests.
That's quite a high number. Let's follow the example of BoringSSL and
use a more conservative value of 4096.
Note that in practice this makes little difference, now that we're
including 32 bytes from get_random_bytes() in the additional input on
every request anyway, which is a de facto reseed.
But for the same reason, we might as well decrease the actual reseed
interval to something more reasonable.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index cda79d601f4f..7fd076ddc105 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -113,11 +113,11 @@ enum drbg_seed_state {
/*
* Maximum number of requests before reseeding is forced.
* SP800-90A allows this to be up to 2**48. We use a lower value.
*/
-#define DRBG_MAX_REQUESTS (1 << 20)
+#define DRBG_MAX_REQUESTS 4096
/*
* Maximum number of random bytes that can be requested at once.
* SP800-90A allows up to 2**19 bits, which is 2**16 bytes.
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (34 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 35/38] crypto: drbg - Change DRBG_MAX_REQUESTS to 4096 Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 16:48 ` Joachim Vandersmissen
2026-04-20 6:34 ` [PATCH 37/38] crypto: drbg - Clean up generation code Eric Biggers
2026-04-20 6:34 ` [PATCH 38/38] crypto: drbg - Clean up loop in drbg_hmac_update() Eric Biggers
37 siblings, 1 reply; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
We're now incorporating 32 bytes from get_random_bytes() in the
additional input string on every request. The additional input string
is processed with a call to drbg_hmac_update(), which is exactly how the
seed is processed. Thus, in reality this is as good as a reseed.
From the perspective of FIPS 140-3, it isn't as good as a reseed. But
it doesn't actually matter, because from FIPS's point of view
get_random_bytes() provides zero entropy anyway.
Thus, neither the reseed with more get_random_bytes() every 300s, nor
the logic that reseeds more frequently before rng_is_initialized(), is
actually needed anymore. Remove it to simplify the code significantly.
(Technically the use of get_random_bytes() in drbg_seed() itself could
be removed too. But it's safer to keep it there for now.)
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 107 +++++---------------------------------------------
1 file changed, 9 insertions(+), 98 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 7fd076ddc105..bab766026177 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -91,22 +91,15 @@
#include <crypto/internal/rng.h>
#include <crypto/sha2.h>
#include <linux/fips.h>
#include <linux/kernel.h>
-#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/string_choices.h>
#include <linux/unaligned.h>
-enum drbg_seed_state {
- DRBG_SEED_STATE_UNSEEDED,
- DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
- DRBG_SEED_STATE_FULL,
-};
-
/* State length in bytes */
#define DRBG_STATE_LEN SHA512_DIGEST_SIZE
/* Security strength in bytes */
#define DRBG_SEC_STRENGTH (SHA512_DIGEST_SIZE / 2)
@@ -135,13 +128,10 @@ struct drbg_state {
struct mutex drbg_mutex; /* lock around DRBG */
u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */
struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */
/* Number of RNG requests since last reseed -- 10.1.2.1 1c */
size_t reseed_ctr;
- size_t reseed_threshold;
- enum drbg_seed_state seeded; /* DRBG fully seeded? */
- unsigned long last_seed_time;
bool instantiated;
bool pr; /* Prediction resistance enabled? */
struct crypto_rng *jent;
const u8 *test_entropy;
size_t test_entropylen;
@@ -237,76 +227,10 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
memzero_explicit(addtl2, sizeof(addtl2));
}
-static inline void __drbg_seed(struct drbg_state *drbg,
- const u8 *seed1, size_t seed1_len,
- const u8 *seed2, size_t seed2_len,
- enum drbg_seed_state new_seed_state)
-{
- drbg_hmac_update(drbg, seed1, seed1_len, seed2, seed2_len);
-
- drbg->seeded = new_seed_state;
- drbg->last_seed_time = jiffies;
- 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;
- break;
- }
-}
-
-static void drbg_seed_from_random(struct drbg_state *drbg)
- __must_hold(&drbg->drbg_mutex)
-{
- u8 entropy[DRBG_SEC_STRENGTH];
-
- get_random_bytes(entropy, DRBG_SEC_STRENGTH);
-
- __drbg_seed(drbg, entropy, DRBG_SEC_STRENGTH, NULL, 0,
- DRBG_SEED_STATE_FULL);
-
- memzero_explicit(entropy, DRBG_SEC_STRENGTH);
-}
-
-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 (drbg->test_entropylen)
- 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
@@ -323,11 +247,10 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
{
int ret;
u8 entropy_buf[(32 + 16) * 2];
size_t entropylen;
const u8 *entropy;
- enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
/* 9.1 / 9.2 / 9.3.1 step 3 */
if (pers_len > DRBG_MAX_ADDTL) {
pr_devel("DRBG: personalization string too long %zu\n",
pers_len);
@@ -353,13 +276,10 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
else
entropylen = DRBG_SEC_STRENGTH;
BUG_ON(entropylen * 2 > sizeof(entropy_buf));
/* Get seed from in-kernel /dev/urandom */
- if (!rng_is_initialized())
- new_seed_state = DRBG_SEED_STATE_PARTIAL;
-
get_random_bytes(entropy_buf, entropylen);
if (!drbg->jent) {
pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
entropylen);
@@ -399,11 +319,12 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
}
if (pers_len)
pr_devel("DRBG: using personalization string\n");
- __drbg_seed(drbg, entropy, entropylen, pers, pers_len, new_seed_state);
+ drbg_hmac_update(drbg, entropy, entropylen, pers, pers_len);
+ drbg->reseed_ctr = 1;
ret = 0;
out:
memzero_explicit(entropy_buf, sizeof(entropy_buf));
return ret;
@@ -461,31 +382,25 @@ 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.
+ *
+ * We no longer try to detect when random.c has reseeded itself and call
+ * drbg_seed() then too, since drbg_hmac_generate() adds bytes from
+ * random.c to the additional input, which is a de facto reseed anyway.
*/
- 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",
- str_true_false(drbg->pr),
- (drbg->seeded == DRBG_SEED_STATE_FULL ?
- "seeded" : "unseeded"));
+ if (drbg->pr || drbg->reseed_ctr > DRBG_MAX_REQUESTS) {
+ pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n",
+ str_true_false(drbg->pr));
/* 9.3.1 steps 7.1 through 7.3 */
len = drbg_seed(drbg, addtl, addtl_len, true);
if (len)
goto err;
/* 9.3.1 step 7.4 */
addtl = NULL;
addtl_len = 0;
- } else if (rng_is_initialized() &&
- (drbg->seeded == DRBG_SEED_STATE_PARTIAL ||
- drbg_nopr_reseed_interval_elapsed(drbg))) {
- drbg_seed_from_random(drbg);
}
/* 9.3.1 step 8 and 10 */
drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len);
@@ -562,13 +477,10 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
*/
/* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
drbg->pr = pr;
- drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
- drbg->last_seed_time = 0;
- drbg->reseed_threshold = DRBG_MAX_REQUESTS;
memset(drbg->V, 1, DRBG_STATE_LEN);
hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
/* Allocate jitterentropy_rng if not in test mode. */
if (drbg->test_entropylen == 0) {
@@ -671,11 +583,10 @@ static inline int __init drbg_healthcheck_sanity(void)
if (!drbg)
return -ENOMEM;
guard(mutex_init)(&drbg->drbg_mutex);
drbg->instantiated = true;
- drbg->reseed_threshold = DRBG_MAX_REQUESTS;
/*
* if the following tests fail, it is likely that there is a buffer
* overflow as buf is much smaller than the requested or provided
* string lengths -- in case the error handling does not succeed
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* Re: [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state
2026-04-20 6:34 ` [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state Eric Biggers
@ 2026-04-20 16:48 ` Joachim Vandersmissen
2026-04-20 17:25 ` Eric Biggers
0 siblings, 1 reply; 50+ messages in thread
From: Joachim Vandersmissen @ 2026-04-20 16:48 UTC (permalink / raw)
To: Eric Biggers, linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld
Hi Eric,
On 4/20/26 1:34 AM, Eric Biggers wrote:
> We're now incorporating 32 bytes from get_random_bytes() in the
> additional input string on every request. The additional input string
> is processed with a call to drbg_hmac_update(), which is exactly how the
> seed is processed. Thus, in reality this is as good as a reseed.
>
> From the perspective of FIPS 140-3, it isn't as good as a reseed. But
> it doesn't actually matter, because from FIPS's point of view
> get_random_bytes() provides zero entropy anyway.
>
> Thus, neither the reseed with more get_random_bytes() every 300s, nor
> the logic that reseeds more frequently before rng_is_initialized(), is
> actually needed anymore. Remove it to simplify the code significantly.
>
> (Technically the use of get_random_bytes() in drbg_seed() itself could
> be removed too. But it's safer to keep it there for now.)
It's fair to say that the additional input is as good as a reseed (if
FIPS is not considered), but then is there any reason to keep
get_random_bytes() in drbg_seed()? You say it could be removed but it's
safer to keep it there for now? In what way is it safer? The additional
input is mixed into the HMAC_DRBG state prior to generating random bits,
so should already provide sufficient assurance that the generated bits
incorporate the output of get_random_bytes()?
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
> crypto/drbg.c | 107 +++++---------------------------------------------
> 1 file changed, 9 insertions(+), 98 deletions(-)
>
> diff --git a/crypto/drbg.c b/crypto/drbg.c
> index 7fd076ddc105..bab766026177 100644
> --- a/crypto/drbg.c
> +++ b/crypto/drbg.c
> @@ -91,22 +91,15 @@
>
> #include <crypto/internal/rng.h>
> #include <crypto/sha2.h>
> #include <linux/fips.h>
> #include <linux/kernel.h>
> -#include <linux/jiffies.h>
> #include <linux/module.h>
> #include <linux/mutex.h>
> #include <linux/string_choices.h>
> #include <linux/unaligned.h>
>
> -enum drbg_seed_state {
> - DRBG_SEED_STATE_UNSEEDED,
> - DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */
> - DRBG_SEED_STATE_FULL,
> -};
> -
> /* State length in bytes */
> #define DRBG_STATE_LEN SHA512_DIGEST_SIZE
>
> /* Security strength in bytes */
> #define DRBG_SEC_STRENGTH (SHA512_DIGEST_SIZE / 2)
> @@ -135,13 +128,10 @@ struct drbg_state {
> struct mutex drbg_mutex; /* lock around DRBG */
> u8 V[DRBG_STATE_LEN]; /* internal state -- 10.1.2.1 1a */
> struct hmac_sha512_key key; /* current key -- 10.1.2.1 1b */
> /* Number of RNG requests since last reseed -- 10.1.2.1 1c */
> size_t reseed_ctr;
> - size_t reseed_threshold;
> - enum drbg_seed_state seeded; /* DRBG fully seeded? */
> - unsigned long last_seed_time;
> bool instantiated;
> bool pr; /* Prediction resistance enabled? */
> struct crypto_rng *jent;
> const u8 *test_entropy;
> size_t test_entropylen;
> @@ -237,76 +227,10 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
> drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
>
> memzero_explicit(addtl2, sizeof(addtl2));
> }
>
> -static inline void __drbg_seed(struct drbg_state *drbg,
> - const u8 *seed1, size_t seed1_len,
> - const u8 *seed2, size_t seed2_len,
> - enum drbg_seed_state new_seed_state)
> -{
> - drbg_hmac_update(drbg, seed1, seed1_len, seed2, seed2_len);
> -
> - drbg->seeded = new_seed_state;
> - drbg->last_seed_time = jiffies;
> - 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;
> - break;
> - }
> -}
> -
> -static void drbg_seed_from_random(struct drbg_state *drbg)
> - __must_hold(&drbg->drbg_mutex)
> -{
> - u8 entropy[DRBG_SEC_STRENGTH];
> -
> - get_random_bytes(entropy, DRBG_SEC_STRENGTH);
> -
> - __drbg_seed(drbg, entropy, DRBG_SEC_STRENGTH, NULL, 0,
> - DRBG_SEED_STATE_FULL);
> -
> - memzero_explicit(entropy, DRBG_SEC_STRENGTH);
> -}
> -
> -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 (drbg->test_entropylen)
> - 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
> @@ -323,11 +247,10 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
> {
> int ret;
> u8 entropy_buf[(32 + 16) * 2];
> size_t entropylen;
> const u8 *entropy;
> - enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
>
> /* 9.1 / 9.2 / 9.3.1 step 3 */
> if (pers_len > DRBG_MAX_ADDTL) {
> pr_devel("DRBG: personalization string too long %zu\n",
> pers_len);
> @@ -353,13 +276,10 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
> else
> entropylen = DRBG_SEC_STRENGTH;
> BUG_ON(entropylen * 2 > sizeof(entropy_buf));
>
> /* Get seed from in-kernel /dev/urandom */
> - if (!rng_is_initialized())
> - new_seed_state = DRBG_SEED_STATE_PARTIAL;
> -
> get_random_bytes(entropy_buf, entropylen);
>
> if (!drbg->jent) {
> pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
> entropylen);
> @@ -399,11 +319,12 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
> }
>
> if (pers_len)
> pr_devel("DRBG: using personalization string\n");
>
> - __drbg_seed(drbg, entropy, entropylen, pers, pers_len, new_seed_state);
> + drbg_hmac_update(drbg, entropy, entropylen, pers, pers_len);
> + drbg->reseed_ctr = 1;
> ret = 0;
> out:
> memzero_explicit(entropy_buf, sizeof(entropy_buf));
>
> return ret;
> @@ -461,31 +382,25 @@ 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.
> + *
> + * We no longer try to detect when random.c has reseeded itself and call
> + * drbg_seed() then too, since drbg_hmac_generate() adds bytes from
> + * random.c to the additional input, which is a de facto reseed anyway.
> */
> - 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",
> - str_true_false(drbg->pr),
> - (drbg->seeded == DRBG_SEED_STATE_FULL ?
> - "seeded" : "unseeded"));
> + if (drbg->pr || drbg->reseed_ctr > DRBG_MAX_REQUESTS) {
> + pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n",
> + str_true_false(drbg->pr));
> /* 9.3.1 steps 7.1 through 7.3 */
> len = drbg_seed(drbg, addtl, addtl_len, true);
> if (len)
> goto err;
> /* 9.3.1 step 7.4 */
> addtl = NULL;
> addtl_len = 0;
> - } else if (rng_is_initialized() &&
> - (drbg->seeded == DRBG_SEED_STATE_PARTIAL ||
> - drbg_nopr_reseed_interval_elapsed(drbg))) {
> - drbg_seed_from_random(drbg);
> }
>
> /* 9.3.1 step 8 and 10 */
> drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len);
>
> @@ -562,13 +477,10 @@ static int drbg_kcapi_seed(struct crypto_rng *tfm,
> */
>
> /* 9.1 step 4 is implicit in DRBG_SEC_STRENGTH */
>
> drbg->pr = pr;
> - drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
> - drbg->last_seed_time = 0;
> - drbg->reseed_threshold = DRBG_MAX_REQUESTS;
> memset(drbg->V, 1, DRBG_STATE_LEN);
> hmac_sha512_preparekey(&drbg->key, initial_key, DRBG_STATE_LEN);
>
> /* Allocate jitterentropy_rng if not in test mode. */
> if (drbg->test_entropylen == 0) {
> @@ -671,11 +583,10 @@ static inline int __init drbg_healthcheck_sanity(void)
> if (!drbg)
> return -ENOMEM;
>
> guard(mutex_init)(&drbg->drbg_mutex);
> drbg->instantiated = true;
> - drbg->reseed_threshold = DRBG_MAX_REQUESTS;
>
> /*
> * if the following tests fail, it is likely that there is a buffer
> * overflow as buf is much smaller than the requested or provided
> * string lengths -- in case the error handling does not succeed
^ permalink raw reply [flat|nested] 50+ messages in thread* Re: [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state
2026-04-20 16:48 ` Joachim Vandersmissen
@ 2026-04-20 17:25 ` Eric Biggers
0 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 17:25 UTC (permalink / raw)
To: Joachim Vandersmissen
Cc: linux-crypto, Herbert Xu, linux-kernel, Stephan Mueller,
Jason A . Donenfeld
On Mon, Apr 20, 2026 at 11:48:47AM -0500, Joachim Vandersmissen wrote:
> Hi Eric,
>
> On 4/20/26 1:34 AM, Eric Biggers wrote:
> > We're now incorporating 32 bytes from get_random_bytes() in the
> > additional input string on every request. The additional input string
> > is processed with a call to drbg_hmac_update(), which is exactly how the
> > seed is processed. Thus, in reality this is as good as a reseed.
> >
> > From the perspective of FIPS 140-3, it isn't as good as a reseed. But
> > it doesn't actually matter, because from FIPS's point of view
> > get_random_bytes() provides zero entropy anyway.
> >
> > Thus, neither the reseed with more get_random_bytes() every 300s, nor
> > the logic that reseeds more frequently before rng_is_initialized(), is
> > actually needed anymore. Remove it to simplify the code significantly.
> >
> > (Technically the use of get_random_bytes() in drbg_seed() itself could
> > be removed too. But it's safer to keep it there for now.)
> It's fair to say that the additional input is as good as a reseed (if FIPS
> is not considered), but then is there any reason to keep get_random_bytes()
> in drbg_seed()? You say it could be removed but it's safer to keep it there
> for now? In what way is it safer? The additional input is mixed into the
> HMAC_DRBG state prior to generating random bits, so should already provide
> sufficient assurance that the generated bits incorporate the output of
> get_random_bytes()?
I do agree that patch 34 makes the get_random_bytes() in drbg_seed()
redundant too. I'm just not yet sure that removing it would strike the
right balance between defense in depth and eliminating redundancy.
Keeping it there also keeps it very clear that whenever jitterentropy
entropy is used, we're also using an equal number of bytes from
get_random_bytes() alongside it. (Remember, not everyone "trusts"
jitterentropy. People auditing this code might *really* want to see the
get_random_bytes().) The additional input does achieve the
get_random_bytes() integration anyway, just it's a bit more subtle.
- Eric
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 37/38] crypto: drbg - Clean up generation code
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (35 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 36/38] crypto: drbg - Remove redundant reseeding based on random.c state Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
2026-04-20 6:34 ` [PATCH 38/38] crypto: drbg - Clean up loop in drbg_hmac_update() Eric Biggers
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
A few miscellaneous cleanups to make the code a bit more readable:
- Replace (buf, buflen) with (out, outlen)
- Update (out, outlen) as we go along
- Use size_t for lengths
- Use min()
- Adjust some comments and log messages
- Rename a variable named 'len' to 'err', since it isn't a length
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 53 ++++++++++++++++++---------------------------------
1 file changed, 19 insertions(+), 34 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index bab766026177..b54c807930af 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -178,16 +178,13 @@ static void drbg_hmac_update(struct drbg_state *drbg,
}
memzero_explicit(new_key, sizeof(new_key));
}
/* generate function of HMAC DRBG as defined in 10.1.2.5 */
-static void drbg_hmac_generate(struct drbg_state *drbg,
- unsigned char *buf,
- unsigned int buflen,
+static void drbg_hmac_generate(struct drbg_state *drbg, u8 *out, size_t outlen,
const u8 *addtl1, size_t addtl1_len)
{
- int len = 0;
u8 addtl2[32];
size_t addtl2_len = 0;
/*
* Append some bytes from get_random_bytes() to the additional input
@@ -208,21 +205,20 @@ static void drbg_hmac_generate(struct drbg_state *drbg,
/* 10.1.2.5 step 2 */
if (addtl1_len || addtl2_len)
drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
- while (len < buflen) {
- unsigned int outlen = 0;
+ while (outlen) {
+ size_t n = min(DRBG_STATE_LEN, outlen);
/* 10.1.2.5 step 4.1 */
hmac_sha512(&drbg->key, drbg->V, DRBG_STATE_LEN, drbg->V);
- outlen = (DRBG_STATE_LEN < (buflen - len)) ?
- DRBG_STATE_LEN : (buflen - len);
/* 10.1.2.5 step 4.2 */
- memcpy(buf + len, drbg->V, outlen);
- len += outlen;
+ memcpy(out, drbg->V, n);
+ out += n;
+ outlen -= n;
}
/* 10.1.2.5 step 6 */
drbg_hmac_update(drbg, addtl1, addtl1_len, addtl2, addtl2_len);
@@ -329,47 +325,42 @@ static int drbg_seed(struct drbg_state *drbg, const u8 *pers, size_t pers_len,
return ret;
}
/*
- * DRBG generate function as required by SP800-90A - this function
- * generates random numbers
+ * Generate random bytes from an SP800-90A DRBG.
*
* @drbg DRBG state handle
- * @buf Buffer where to store the random numbers -- the buffer must already
- * be pre-allocated by caller
- * @buflen Length of output buffer - this value defines the number of random
- * bytes pulled from DRBG
+ * @out Buffer where to store the random bytes
+ * @outlen Number of random bytes to generate
* @addtl Optional additional input that is mixed into state
* @addtl_len Length of @addtl in bytes, may be 0
*
* return: 0 when all bytes are generated; < 0 in case of an error
*/
-static int drbg_generate(struct drbg_state *drbg,
- unsigned char *buf, unsigned int buflen,
+static int drbg_generate(struct drbg_state *drbg, u8 *out, size_t outlen,
const u8 *addtl, size_t addtl_len)
__must_hold(&drbg->drbg_mutex)
{
- int len = 0;
+ int err;
if (!drbg->instantiated) {
pr_devel("DRBG: not yet instantiated\n");
return -EINVAL;
}
- if (0 == buflen || !buf) {
+ if (out == NULL || outlen == 0) {
pr_devel("DRBG: no output buffer provided\n");
return -EINVAL;
}
if (addtl == NULL && addtl_len != 0) {
pr_devel("DRBG: wrong format of additional information\n");
return -EINVAL;
}
/* 9.3.1 step 2 */
- if (buflen > DRBG_MAX_REQUEST_BYTES) {
- pr_devel("DRBG: requested random numbers too large %u\n",
- buflen);
+ if (outlen > DRBG_MAX_REQUEST_BYTES) {
+ pr_devel("DRBG: request length is too long %zu\n", outlen);
return -EINVAL;
}
/* 9.3.1 step 3 is implicit with the chosen DRBG */
@@ -391,20 +382,20 @@ static int drbg_generate(struct drbg_state *drbg,
*/
if (drbg->pr || drbg->reseed_ctr > DRBG_MAX_REQUESTS) {
pr_devel("DRBG: reseeding before generation (prediction resistance: %s)\n",
str_true_false(drbg->pr));
/* 9.3.1 steps 7.1 through 7.3 */
- len = drbg_seed(drbg, addtl, addtl_len, true);
- if (len)
- goto err;
+ err = drbg_seed(drbg, addtl, addtl_len, true);
+ if (err)
+ return err;
/* 9.3.1 step 7.4 */
addtl = NULL;
addtl_len = 0;
}
/* 9.3.1 step 8 and 10 */
- drbg_hmac_generate(drbg, buf, buflen, addtl, addtl_len);
+ drbg_hmac_generate(drbg, out, outlen, addtl, addtl_len);
/* 10.1.2.5 step 7 */
drbg->reseed_ctr++;
/*
@@ -418,17 +409,11 @@ static int drbg_generate(struct drbg_state *drbg,
* In this case, the entire kernel operation is questionable and it
* is unlikely that the integrity violation only affects the
* correct operation of the DRBG.
*/
- /*
- * All operations were successful, return 0 as mandated by
- * the kernel crypto API interface.
- */
- len = 0;
-err:
- return len;
+ return 0;
}
/***************************************************************
* Kernel crypto API interface to DRBG
***************************************************************/
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread* [PATCH 38/38] crypto: drbg - Clean up loop in drbg_hmac_update()
2026-04-20 6:33 [PATCH 00/38] Fix and simplify the NIST DRBG implementation Eric Biggers
` (36 preceding siblings ...)
2026-04-20 6:34 ` [PATCH 37/38] crypto: drbg - Clean up generation code Eric Biggers
@ 2026-04-20 6:34 ` Eric Biggers
37 siblings, 0 replies; 50+ messages in thread
From: Eric Biggers @ 2026-04-20 6:34 UTC (permalink / raw)
To: linux-crypto, Herbert Xu
Cc: linux-kernel, Stephan Mueller, Jason A . Donenfeld, Eric Biggers
This loop is a bit hard to read, with the loop counter that's used in
the HMAC being separate from the actual loop counter, which counts
backwards for some reason. Just replace it with a regular loop.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/drbg.c | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/crypto/drbg.c b/crypto/drbg.c
index b54c807930af..ad7b9577479e 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -135,37 +135,27 @@ struct drbg_state {
struct crypto_rng *jent;
const u8 *test_entropy;
size_t test_entropylen;
};
-enum drbg_prefixes {
- DRBG_PREFIX0 = 0x00,
- DRBG_PREFIX1,
-};
-
/******************************************************************
* HMAC DRBG functions
******************************************************************/
/* update function of HMAC DRBG as defined in 10.1.2.2 */
static void drbg_hmac_update(struct drbg_state *drbg,
const u8 *data1, size_t data1_len,
const u8 *data2, size_t data2_len)
{
- int i = 0;
struct hmac_sha512_ctx hmac_ctx;
u8 new_key[DRBG_STATE_LEN];
- for (i = 2; 0 < i; i--) {
- /* first round uses 0x0, second 0x1 */
- unsigned char prefix = DRBG_PREFIX0;
- if (1 == i)
- prefix = DRBG_PREFIX1;
+ for (u8 i = 0; i < 2; i++) {
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
hmac_sha512_init(&hmac_ctx, &drbg->key);
hmac_sha512_update(&hmac_ctx, drbg->V, DRBG_STATE_LEN);
- hmac_sha512_update(&hmac_ctx, &prefix, 1);
+ hmac_sha512_update(&hmac_ctx, &i, 1);
hmac_sha512_update(&hmac_ctx, data1, data1_len);
hmac_sha512_update(&hmac_ctx, data2, data2_len);
hmac_sha512_final(&hmac_ctx, new_key);
hmac_sha512_preparekey(&drbg->key, new_key, DRBG_STATE_LEN);
--
2.53.0
^ permalink raw reply related [flat|nested] 50+ messages in thread