* [PATCH 01/38] crypto: drbg - Fix returning success on failure in CTR_DRBG
[not found] <20260420063422.324906-1-ebiggers@kernel.org>
@ 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
` (3 subsequent siblings)
4 siblings, 0 replies; 5+ 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] 5+ messages in thread* [PATCH 02/38] crypto: drbg - Fix misaligned writes in CTR_DRBG and HASH_DRBG
[not found] <20260420063422.324906-1-ebiggers@kernel.org>
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
` (2 subsequent siblings)
4 siblings, 0 replies; 5+ 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] 5+ messages in thread* [PATCH 03/38] crypto: drbg - Fix ineffective sanity check
[not found] <20260420063422.324906-1-ebiggers@kernel.org>
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
2026-04-20 6:33 ` [PATCH 05/38] crypto: drbg - Fix the fips_enabled priority boost Eric Biggers
4 siblings, 0 replies; 5+ 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] 5+ messages in thread* [PATCH 04/38] crypto: drbg - Fix drbg_max_addtl() on 64-bit kernels
[not found] <20260420063422.324906-1-ebiggers@kernel.org>
` (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
4 siblings, 0 replies; 5+ 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] 5+ messages in thread* [PATCH 05/38] crypto: drbg - Fix the fips_enabled priority boost
[not found] <20260420063422.324906-1-ebiggers@kernel.org>
` (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
4 siblings, 0 replies; 5+ 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] 5+ messages in thread