Linux cryptographic layer development
 help / color / mirror / Atom feed
* Re: [PATCH] crypto: crypto4xx - Remove insecure and unused rng_alg
From: Aleksander Jan Bajkowski @ 2026-05-30 15:05 UTC (permalink / raw)
  To: Eric Biggers, linux-crypto, Herbert Xu
  Cc: Christian Lamparter, linuxppc-dev, linux-kernel, stable
In-Reply-To: <20260529220430.34135-1-ebiggers@kernel.org>

Hi Eric,

On 30/05/2026 00:04, Eric Biggers wrote:
> Remove crypto4xx_rng, as it is insecure and unused:
>
> - It has only a 64-bit security strength, which is highly inadequate.
>    This can be seen by the fact that crypto4xx_hw_init() seeds it with
>    only 64 bits of entropy, and the fact that the original commit
>    mentions that it implements ANSI X9.17 Annex C.

In addition to a seed, the PRNG also uses ring oscillators as sources of
entropy. The entropy should be higher than 64b. This is the Rambus EIP-73d
IP core. The same IP core is built into eip93 (EIP-73a), eip97 (EIP-73d),
and eip197 (EIP-73d). You can find the documentation online. The complete
"container" is actually Rambus EIP-94, and one of its parts is EIP-73d.

>
>    Another issue was that this driver didn't implement the crypto_rng API
>    correctly, as crypto4xx_prng_generate() didn't return 0 on success.
>
> - No user of this code is known.  It's usable only theoretically via the
>    "rng" algorithm type of AF_ALG.  But userspace actually just uses the
>    actual Linux RNG (/dev/random etc) instead.  And rng_algs don't
>    contribute entropy to the actual Linux RNG either.  (This may have
>    been confused with hwrng, which does contribute entropy.)

This PRNG is also used internally for Generation IV with IPSEC offload. The
IPSEC offload implementation for eip93 was recently submitted to upstream.
I am not sure whether eip94 shares some of the logic for IPSEC offload and
it will be possible to use some of the code.

>
> Fixes: d072bfa48853 ("crypto: crypto4xx - add prng crypto support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> Acked-by: Christian Lamparter <chunkeey@gmail.com>
> ---
>   drivers/crypto/Kconfig                  |  1 -
>   drivers/crypto/amcc/crypto4xx_core.c    | 88 -------------------------
>   drivers/crypto/amcc/crypto4xx_core.h    |  4 --
>   drivers/crypto/amcc/crypto4xx_reg_def.h | 11 ----
>   4 files changed, 104 deletions(-)
>
>
> base-commit: 49e05bb00f2e8168695f7af4d694c39e1423e8a2
>
> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
> index 3449b3c9c6ad..5dab813a9f74 100644
> --- a/drivers/crypto/Kconfig
> +++ b/drivers/crypto/Kconfig
> @@ -299,11 +299,10 @@ config CRYPTO_DEV_PPC4XX
>   	select CRYPTO_AES
>   	select CRYPTO_LIB_AES
>   	select CRYPTO_CCM
>   	select CRYPTO_CTR
>   	select CRYPTO_GCM
> -	select CRYPTO_RNG
>   	select CRYPTO_SKCIPHER
>   	help
>   	  This option allows you to have support for AMCC crypto acceleration.
>   
>   config HW_RANDOM_PPC4XX
> diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
> index b7b6c97d2147..68c5ff7a85b4 100644
> --- a/drivers/crypto/amcc/crypto4xx_core.c
> +++ b/drivers/crypto/amcc/crypto4xx_core.c
> @@ -29,15 +29,13 @@
>   #include <crypto/aead.h>
>   #include <crypto/aes.h>
>   #include <crypto/ctr.h>
>   #include <crypto/gcm.h>
>   #include <crypto/sha1.h>
> -#include <crypto/rng.h>
>   #include <crypto/scatterwalk.h>
>   #include <crypto/skcipher.h>
>   #include <crypto/internal/aead.h>
> -#include <crypto/internal/rng.h>
>   #include <crypto/internal/skcipher.h>
>   #include "crypto4xx_reg_def.h"
>   #include "crypto4xx_core.h"
>   #include "crypto4xx_sa.h"
>   #include "crypto4xx_trng.h"
> @@ -983,14 +981,10 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
>   		switch (alg->alg.type) {
>   		case CRYPTO_ALG_TYPE_AEAD:
>   			rc = crypto_register_aead(&alg->alg.u.aead);
>   			break;
>   
> -		case CRYPTO_ALG_TYPE_RNG:
> -			rc = crypto_register_rng(&alg->alg.u.rng);
> -			break;
> -
>   		default:
>   			rc = crypto_register_skcipher(&alg->alg.u.cipher);
>   			break;
>   		}
>   
> @@ -1012,14 +1006,10 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)
>   		switch (alg->alg.type) {
>   		case CRYPTO_ALG_TYPE_AEAD:
>   			crypto_unregister_aead(&alg->alg.u.aead);
>   			break;
>   
> -		case CRYPTO_ALG_TYPE_RNG:
> -			crypto_unregister_rng(&alg->alg.u.rng);
> -			break;
> -
>   		default:
>   			crypto_unregister_skcipher(&alg->alg.u.cipher);
>   		}
>   		kfree(alg);
>   	}
> @@ -1074,73 +1064,10 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
>   {
>   	return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR |
>   		PPC4XX_TMO_ERR_INT);
>   }
>   
> -static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
> -				 u8 *data, unsigned int max)
> -{
> -	unsigned int i, curr = 0;
> -	u32 val[2];
> -
> -	do {
> -		/* trigger PRN generation */
> -		writel(PPC4XX_PRNG_CTRL_AUTO_EN,
> -		       dev->ce_base + CRYPTO4XX_PRNG_CTRL);
> -
> -		for (i = 0; i < 1024; i++) {
> -			/* usually 19 iterations are enough */
> -			if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
> -			     CRYPTO4XX_PRNG_STAT_BUSY))
> -				continue;
> -
> -			val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
> -			val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
> -			break;
> -		}
> -		if (i == 1024)
> -			return -ETIMEDOUT;
> -
> -		if ((max - curr) >= 8) {
> -			memcpy(data, &val, 8);
> -			data += 8;
> -			curr += 8;
> -		} else {
> -			/* copy only remaining bytes */
> -			memcpy(data, &val, max - curr);
> -			break;
> -		}
> -	} while (curr < max);
> -
> -	return curr;
> -}
> -
> -static int crypto4xx_prng_generate(struct crypto_rng *tfm,
> -				   const u8 *src, unsigned int slen,
> -				   u8 *dstn, unsigned int dlen)
> -{
> -	struct rng_alg *alg = crypto_rng_alg(tfm);
> -	struct crypto4xx_alg *amcc_alg;
> -	struct crypto4xx_device *dev;
> -	int ret;
> -
> -	amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
> -	dev = amcc_alg->dev;
> -
> -	mutex_lock(&dev->core_dev->rng_lock);
> -	ret = ppc4xx_prng_data_read(dev, dstn, dlen);
> -	mutex_unlock(&dev->core_dev->rng_lock);
> -	return ret;
> -}
> -
> -
> -static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
> -			unsigned int slen)
> -{
> -	return 0;
> -}
> -
>   /*
>    * Supported Crypto Algorithms
>    */
>   static struct crypto4xx_alg_common crypto4xx_alg[] = {
>   	/* Crypto AES modes */
> @@ -1266,22 +1193,10 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = {
>   			.cra_blocksize	= 1,
>   			.cra_ctxsize	= sizeof(struct crypto4xx_ctx),
>   			.cra_module	= THIS_MODULE,
>   		},
>   	} },
> -	{ .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
> -		.base = {
> -			.cra_name		= "stdrng",
> -			.cra_driver_name        = "crypto4xx_rng",
> -			.cra_priority		= 300,
> -			.cra_ctxsize		= 0,
> -			.cra_module		= THIS_MODULE,
> -		},
> -		.generate               = crypto4xx_prng_generate,
> -		.seed                   = crypto4xx_prng_seed,
> -		.seedsize               = 0,
> -	} },
>   };
>   
>   /*
>    * Module Initialization Routine
>    */
> @@ -1351,13 +1266,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
>   	}
>   
>   	core_dev->dev->core_dev = core_dev;
>   	core_dev->dev->is_revb = is_revb;
>   	core_dev->device = dev;
> -	rc = devm_mutex_init(&ofdev->dev, &core_dev->rng_lock);
> -	if (rc)
> -		return rc;
>   	spin_lock_init(&core_dev->lock);
>   	INIT_LIST_HEAD(&core_dev->dev->alg_list);
>   	ratelimit_default_init(&core_dev->dev->aead_ratelimit);
>   	rc = crypto4xx_build_sdr(core_dev->dev);
>   	if (rc)
> diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
> index ee36630c670f..3a028aec3f0c 100644
> --- a/drivers/crypto/amcc/crypto4xx_core.h
> +++ b/drivers/crypto/amcc/crypto4xx_core.h
> @@ -12,14 +12,12 @@
>   
>   #ifndef __CRYPTO4XX_CORE_H__
>   #define __CRYPTO4XX_CORE_H__
>   
>   #include <linux/ratelimit.h>
> -#include <linux/mutex.h>
>   #include <linux/scatterlist.h>
>   #include <crypto/internal/aead.h>
> -#include <crypto/internal/rng.h>
>   #include <crypto/internal/skcipher.h>
>   #include "crypto4xx_reg_def.h"
>   #include "crypto4xx_sa.h"
>   
>   #define PPC460SX_SDR0_SRST                      0x201
> @@ -109,11 +107,10 @@ struct crypto4xx_core_device {
>   	struct hwrng *trng;
>   	u32 int_status;
>   	u32 irq;
>   	struct tasklet_struct tasklet;
>   	spinlock_t lock;
> -	struct mutex rng_lock;
>   };
>   
>   struct crypto4xx_ctx {
>   	struct crypto4xx_device *dev;
>   	struct dynamic_sa_ctl *sa_in;
> @@ -133,11 +130,10 @@ struct crypto4xx_aead_reqctx {
>   struct crypto4xx_alg_common {
>   	u32 type;
>   	union {
>   		struct skcipher_alg cipher;
>   		struct aead_alg aead;
> -		struct rng_alg rng;
>   	} u;
>   };
>   
>   struct crypto4xx_alg {
>   	struct list_head  entry;
> diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h
> index 1038061224da..73d626308a84 100644
> --- a/drivers/crypto/amcc/crypto4xx_reg_def.h
> +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
> @@ -88,24 +88,13 @@
>   
>   #define CRYPTO4XX_DMA_CFG	        	0x000600d4
>   #define CRYPTO4XX_BYTE_ORDER_CFG 		0x000600d8
>   #define CRYPTO4XX_ENDIAN_CFG			0x000600d8
>   
> -#define CRYPTO4XX_PRNG_STAT			0x00070000
> -#define CRYPTO4XX_PRNG_STAT_BUSY		0x1
>   #define CRYPTO4XX_PRNG_CTRL			0x00070004
>   #define CRYPTO4XX_PRNG_SEED_L			0x00070008
>   #define CRYPTO4XX_PRNG_SEED_H			0x0007000c
> -
> -#define CRYPTO4XX_PRNG_RES_0			0x00070020
> -#define CRYPTO4XX_PRNG_RES_1			0x00070024
> -#define CRYPTO4XX_PRNG_RES_2			0x00070028
> -#define CRYPTO4XX_PRNG_RES_3			0x0007002C
> -
> -#define CRYPTO4XX_PRNG_LFSR_L			0x00070030
> -#define CRYPTO4XX_PRNG_LFSR_H			0x00070034
> -
>   /*
>    * Initialize CRYPTO ENGINE registers, and memory bases.
>    */
>   #define PPC4XX_PDR_POLL				0x3ff
>   #define PPC4XX_OUTPUT_THRESHOLD			2

^ permalink raw reply

* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Krzysztof Kozlowski @ 2026-05-30 10:48 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Demi Marie Obenour, Dmitry Baryshkov, Herbert Xu, David S. Miller,
	Thara Gopinath, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Russell King, linux-kernel,
	linux-crypto, linux-arm-msm, Ard Biesheuvel, devicetree,
	linux-arm-kernel
In-Reply-To: <20260524204537.GB110177@quark>

On Sun, May 24, 2026 at 03:45:37PM -0500, Eric Biggers wrote:
> On Sun, May 24, 2026 at 10:29:28PM +0200, Krzysztof Kozlowski wrote:
> > On 24/05/2026 22:12, Demi Marie Obenour wrote:
> > > On 5/24/26 12:42, Dmitry Baryshkov wrote:
> > >> On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
> > >>> From: Demi Marie Obenour <demiobenour@gmail.com>
> > >>>
> > >>> It's slower than the generic C code and causes problems.
> > >>
> > >> Which problems?
> > > 
> > > See https://lore.kernel.org/all/20260522024912.GC5937@quark/.
> > 
> > Your commit is still incomplete and other people's opinion is poor
> > reason. If you do not know what to write, ask that person to make
> > necessary changes.
> > 
> > Not mentioning that removing driver is not even necessary to achieve the
> > goal Eric was mentioning and if I understood correctly: you are removing
> > even the pieces Eric found useful.
> 
> This driver is more than an order of magnitude slower than the CPU for
> both encryption and hashing.  See:
> 
>     https://lore.kernel.org/r/20250704070322.20692-1-ebiggers@kernel.org/
>     https://lore.kernel.org/r/20250615031807.GA81869@sol/
> 
> There are many examples of it having bugs as well, for example see the
> second link above.
> 
> That's why it had to be disabled via the cra_priority system.  This
> driver was actively making Linux worse.
> 
> This isn't particularly unique to drivers/crypto/, of course.  This one
> we just have data on, so it's a bit clearer.
> 
> I've yet to see any real reason to keep this driver.
> 
> Crypto drivers need to be held to a higher standard than other device
> drivers, as well.  The onus is on those who want to keep a particular
> crypto driver to prove that it's worth keeping.

Commit doing the work should have all these explanations, including
numbers. External references are not a proper justification for commits.

Make your case, describe the findings including impact (or lack of
impact) on ongoing hw wrapped keys work and inlined encryption for other
devices (ICE).

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 4/5] dt-bindings: dma: qcom,bam-dma: Increase iommus maxItems to seven
From: Krzysztof Kozlowski @ 2026-05-30 10:39 UTC (permalink / raw)
  To: Kuldeep Singh
  Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Bjorn Andersson, Vinod Koul, Thara Gopinath,
	Konrad Dybcio, Frank Li, Andy Gross, Harshal Dev, linux-arm-msm,
	linux-crypto, devicetree, linux-kernel, dmaengine
In-Reply-To: <20260521-shikra_crypto_changse-v1-4-0154cc9cc0de@oss.qualcomm.com>

On Thu, May 21, 2026 at 06:47:11PM +0530, Kuldeep Singh wrote:
> Shikra bam dma engine support 7 iommu entries and not 6.
> Increase maxItems property for iommus to pass dtbs_check errors.

What errors? There is no Shikra in upstream so how could we have errors?

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/5] dt-bindings: crypto: qcom,inline-crypto-engine: Document Shikra ICE
From: Krzysztof Kozlowski @ 2026-05-30 10:38 UTC (permalink / raw)
  To: Kuldeep Singh
  Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Bjorn Andersson, Vinod Koul, Thara Gopinath,
	Konrad Dybcio, Frank Li, Andy Gross, Harshal Dev, linux-arm-msm,
	linux-crypto, devicetree, linux-kernel, dmaengine
In-Reply-To: <20260521-shikra_crypto_changse-v1-1-0154cc9cc0de@oss.qualcomm.com>

On Thu, May 21, 2026 at 06:47:08PM +0530, Kuldeep Singh wrote:
> Document the Inline Crypto Engine (ICE) on the Qualcomm Shikra platform.
> 
> Signed-off-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 +
>  1 file changed, 1 insertion(+)

Missing constraints for clocks.

That's also v3, not v1.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 2/2] dt-bindings: crypto: qcom,inline-crypto-engine: Document Hawi ICE
From: Krzysztof Kozlowski @ 2026-05-30 10:37 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Vinod Koul, Bjorn Andersson, linux-arm-msm,
	linux-crypto, devicetree, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260521-hawi-crypto-v1-2-9176a3b51bc0@kernel.org>

On Thu, May 21, 2026 at 12:36:21PM +0000, Manivannan Sadhasivam wrote:
> From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> 
> The Inline Crypto Engine found in Hawi SoC is compatible with the common
> baseline IP 'qcom,inline-crypto-engine'. Hence, document the compatible as
> such.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---
>  Documentation/devicetree/bindings/crypto/qcom,inline-crypto-engine.yaml | 1 +
>  1 file changed, 1 insertion(+)

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/2] dt-bindings: crypto: qcom,prng: Document Hawi TRNG
From: Krzysztof Kozlowski @ 2026-05-30 10:37 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Herbert Xu, David S. Miller, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Vinod Koul, Bjorn Andersson, linux-arm-msm,
	linux-crypto, devicetree, linux-kernel, Manivannan Sadhasivam
In-Reply-To: <20260521-hawi-crypto-v1-1-9176a3b51bc0@kernel.org>

On Thu, May 21, 2026 at 12:36:20PM +0000, Manivannan Sadhasivam wrote:
> From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> 
> Hawi SoC has the True Random Number Generator (TRNG) which is compatible
> with the baseline IP "qcom,trng". Hence, document the compatible as such.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
> ---

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH] crypto: crypto4xx - Remove insecure and unused rng_alg
From: Christian Lamparter @ 2026-05-30 10:20 UTC (permalink / raw)
  To: Eric Biggers, linux-crypto, Herbert Xu; +Cc: linuxppc-dev, linux-kernel, stable
In-Reply-To: <20260529220430.34135-1-ebiggers@kernel.org>

Hi!

On 5/30/26 12:04 AM, Eric Biggers wrote:
> Remove crypto4xx_rng, as it is insecure and unused:
> 
> - It has only a 64-bit security strength, which is highly inadequate.
>    This can be seen by the fact that crypto4xx_hw_init() seeds it with
>    only 64 bits of entropy, and the fact that the original commit
>    mentions that it implements ANSI X9.17 Annex C.

Yes, that "ANSI X9.17 Annex C" comes from the datasheet for the PRNG.

>    Another issue was that this driver didn't implement the crypto_rng API
>    correctly, as crypto4xx_prng_generate() didn't return 0 on success.

Oh! Hmm, I think I copied that "return amount;" from another driver that
had it implemented? But I'm not sure, this was sooo long ago. That said,
if this never worked...

> - No user of this code is known.  It's usable only theoretically via the
>    "rng" algorithm type of AF_ALG.  But userspace actually just uses the
>    actual Linux RNG (/dev/random etc) instead.  And rng_algs don't
>    contribute entropy to the actual Linux RNG either.  (This may have
>    been confused with hwrng, which does contribute entropy.)

... and it's completely redundant: Sure!

just in case, this counts for anything, but as the person that added it in the
first place:

Acked-by: Christian Lamparter <chunkeey@gmail.com>

> Fixes: d072bfa48853 ("crypto: crypto4xx - add prng crypto support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
>   drivers/crypto/Kconfig                  |  1 -
>   drivers/crypto/amcc/crypto4xx_core.c    | 88 -------------------------
>   drivers/crypto/amcc/crypto4xx_core.h    |  4 --
>   drivers/crypto/amcc/crypto4xx_reg_def.h | 11 ----
>   4 files changed, 104 deletions(-)
> 
> diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
> index 3449b3c9c6ad..5dab813a9f74 100644
> --- a/drivers/crypto/Kconfig
> +++ b/drivers/crypto/Kconfig
> @@ -299,11 +299,10 @@ config CRYPTO_DEV_PPC4XX
>   	select CRYPTO_AES
>   	select CRYPTO_LIB_AES
>   	select CRYPTO_CCM
>   	select CRYPTO_CTR
>   	select CRYPTO_GCM
> -	select CRYPTO_RNG
>   	select CRYPTO_SKCIPHER
>   	help
>   	  This option allows you to have support for AMCC crypto acceleration.
>   
>   config HW_RANDOM_PPC4XX
> diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
> index b7b6c97d2147..68c5ff7a85b4 100644
> --- a/drivers/crypto/amcc/crypto4xx_core.c
> +++ b/drivers/crypto/amcc/crypto4xx_core.c
> @@ -29,15 +29,13 @@
>   #include <crypto/aead.h>
>   #include <crypto/aes.h>
>   #include <crypto/ctr.h>
>   #include <crypto/gcm.h>
>   #include <crypto/sha1.h>
> -#include <crypto/rng.h>
>   #include <crypto/scatterwalk.h>
>   #include <crypto/skcipher.h>
>   #include <crypto/internal/aead.h>
> -#include <crypto/internal/rng.h>
>   #include <crypto/internal/skcipher.h>
>   #include "crypto4xx_reg_def.h"
>   #include "crypto4xx_core.h"
>   #include "crypto4xx_sa.h"
>   #include "crypto4xx_trng.h"
> @@ -983,14 +981,10 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
>   		switch (alg->alg.type) {
>   		case CRYPTO_ALG_TYPE_AEAD:
>   			rc = crypto_register_aead(&alg->alg.u.aead);
>   			break;
>   
> -		case CRYPTO_ALG_TYPE_RNG:
> -			rc = crypto_register_rng(&alg->alg.u.rng);
> -			break;
> -
>   		default:
>   			rc = crypto_register_skcipher(&alg->alg.u.cipher);
>   			break;
>   		}
>   
> @@ -1012,14 +1006,10 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)
>   		switch (alg->alg.type) {
>   		case CRYPTO_ALG_TYPE_AEAD:
>   			crypto_unregister_aead(&alg->alg.u.aead);
>   			break;
>   
> -		case CRYPTO_ALG_TYPE_RNG:
> -			crypto_unregister_rng(&alg->alg.u.rng);
> -			break;
> -
>   		default:
>   			crypto_unregister_skcipher(&alg->alg.u.cipher);
>   		}
>   		kfree(alg);
>   	}
> @@ -1074,73 +1064,10 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
>   {
>   	return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR |
>   		PPC4XX_TMO_ERR_INT);
>   }
>   
> -static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
> -				 u8 *data, unsigned int max)
> -{
> -	unsigned int i, curr = 0;
> -	u32 val[2];
> -
> -	do {
> -		/* trigger PRN generation */
> -		writel(PPC4XX_PRNG_CTRL_AUTO_EN,
> -		       dev->ce_base + CRYPTO4XX_PRNG_CTRL);
> -
> -		for (i = 0; i < 1024; i++) {
> -			/* usually 19 iterations are enough */
> -			if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
> -			     CRYPTO4XX_PRNG_STAT_BUSY))
> -				continue;
> -
> -			val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
> -			val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
> -			break;
> -		}
> -		if (i == 1024)
> -			return -ETIMEDOUT;
> -
> -		if ((max - curr) >= 8) {
> -			memcpy(data, &val, 8);
> -			data += 8;
> -			curr += 8;
> -		} else {
> -			/* copy only remaining bytes */
> -			memcpy(data, &val, max - curr);
> -			break;
> -		}
> -	} while (curr < max);
> -
> -	return curr;
> -}
> -
> -static int crypto4xx_prng_generate(struct crypto_rng *tfm,
> -				   const u8 *src, unsigned int slen,
> -				   u8 *dstn, unsigned int dlen)
> -{
> -	struct rng_alg *alg = crypto_rng_alg(tfm);
> -	struct crypto4xx_alg *amcc_alg;
> -	struct crypto4xx_device *dev;
> -	int ret;
> -
> -	amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
> -	dev = amcc_alg->dev;
> -
> -	mutex_lock(&dev->core_dev->rng_lock);
> -	ret = ppc4xx_prng_data_read(dev, dstn, dlen);
> -	mutex_unlock(&dev->core_dev->rng_lock);
> -	return ret;
> -}
> -
> -
> -static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
> -			unsigned int slen)
> -{
> -	return 0;
> -}
> -
>   /*
>    * Supported Crypto Algorithms
>    */
>   static struct crypto4xx_alg_common crypto4xx_alg[] = {
>   	/* Crypto AES modes */
> @@ -1266,22 +1193,10 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = {
>   			.cra_blocksize	= 1,
>   			.cra_ctxsize	= sizeof(struct crypto4xx_ctx),
>   			.cra_module	= THIS_MODULE,
>   		},
>   	} },
> -	{ .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
> -		.base = {
> -			.cra_name		= "stdrng",
> -			.cra_driver_name        = "crypto4xx_rng",
> -			.cra_priority		= 300,
> -			.cra_ctxsize		= 0,
> -			.cra_module		= THIS_MODULE,
> -		},
> -		.generate               = crypto4xx_prng_generate,
> -		.seed                   = crypto4xx_prng_seed,
> -		.seedsize               = 0,
> -	} },
>   };
>   
>   /*
>    * Module Initialization Routine
>    */
> @@ -1351,13 +1266,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
>   	}
>   
>   	core_dev->dev->core_dev = core_dev;
>   	core_dev->dev->is_revb = is_revb;
>   	core_dev->device = dev;
> -	rc = devm_mutex_init(&ofdev->dev, &core_dev->rng_lock);
> -	if (rc)
> -		return rc;
>   	spin_lock_init(&core_dev->lock);
>   	INIT_LIST_HEAD(&core_dev->dev->alg_list);
>   	ratelimit_default_init(&core_dev->dev->aead_ratelimit);
>   	rc = crypto4xx_build_sdr(core_dev->dev);
>   	if (rc)
> diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
> index ee36630c670f..3a028aec3f0c 100644
> --- a/drivers/crypto/amcc/crypto4xx_core.h
> +++ b/drivers/crypto/amcc/crypto4xx_core.h
> @@ -12,14 +12,12 @@
>   
>   #ifndef __CRYPTO4XX_CORE_H__
>   #define __CRYPTO4XX_CORE_H__
>   
>   #include <linux/ratelimit.h>
> -#include <linux/mutex.h>
>   #include <linux/scatterlist.h>
>   #include <crypto/internal/aead.h>
> -#include <crypto/internal/rng.h>
>   #include <crypto/internal/skcipher.h>
>   #include "crypto4xx_reg_def.h"
>   #include "crypto4xx_sa.h"
>   
>   #define PPC460SX_SDR0_SRST                      0x201
> @@ -109,11 +107,10 @@ struct crypto4xx_core_device {
>   	struct hwrng *trng;
>   	u32 int_status;
>   	u32 irq;
>   	struct tasklet_struct tasklet;
>   	spinlock_t lock;
> -	struct mutex rng_lock;
>   };
>   
>   struct crypto4xx_ctx {
>   	struct crypto4xx_device *dev;
>   	struct dynamic_sa_ctl *sa_in;
> @@ -133,11 +130,10 @@ struct crypto4xx_aead_reqctx {
>   struct crypto4xx_alg_common {
>   	u32 type;
>   	union {
>   		struct skcipher_alg cipher;
>   		struct aead_alg aead;
> -		struct rng_alg rng;
>   	} u;
>   };
>   
>   struct crypto4xx_alg {
>   	struct list_head  entry;
> diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h
> index 1038061224da..73d626308a84 100644
> --- a/drivers/crypto/amcc/crypto4xx_reg_def.h
> +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
> @@ -88,24 +88,13 @@
>   
>   #define CRYPTO4XX_DMA_CFG	        	0x000600d4
>   #define CRYPTO4XX_BYTE_ORDER_CFG 		0x000600d8
>   #define CRYPTO4XX_ENDIAN_CFG			0x000600d8
>   
> -#define CRYPTO4XX_PRNG_STAT			0x00070000
> -#define CRYPTO4XX_PRNG_STAT_BUSY		0x1
>   #define CRYPTO4XX_PRNG_CTRL			0x00070004
>   #define CRYPTO4XX_PRNG_SEED_L			0x00070008
>   #define CRYPTO4XX_PRNG_SEED_H			0x0007000c
> -
> -#define CRYPTO4XX_PRNG_RES_0			0x00070020
> -#define CRYPTO4XX_PRNG_RES_1			0x00070024
> -#define CRYPTO4XX_PRNG_RES_2			0x00070028
> -#define CRYPTO4XX_PRNG_RES_3			0x0007002C
> -
> -#define CRYPTO4XX_PRNG_LFSR_L			0x00070030
> -#define CRYPTO4XX_PRNG_LFSR_H			0x00070034
> -

Hmm, don't think these defines will hurt anyone? As these are part of the hardware spec.
Or do you forsee a future where AI-Agents will sent patches hallucinating that it "fixed"
the issue which readds it? I have no idea.

>   /*
>    * Initialize CRYPTO ENGINE registers, and memory bases.
>    */
>   #define PPC4XX_PDR_POLL				0x3ff
>   #define PPC4XX_OUTPUT_THRESHOLD			2


Cheers,
Christian

^ permalink raw reply

* [PATCH 4/4] hwrng: qcom - Move qcom-rng.c into drivers/char/hw_random/
From: Eric Biggers @ 2026-05-30  2:03 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
	linux-arm-msm, Olivia Mackall, Eric Biggers
In-Reply-To: <20260530020332.143058-1-ebiggers@kernel.org>

Since this file just implements a hwrng driver, move it into
drivers/char/hw_random/.  Rename the kconfig option accordingly as well.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 arch/arm/configs/multi_v7_defconfig           |  2 +-
 arch/arm/configs/qcom_defconfig               |  2 +-
 arch/arm64/configs/defconfig                  |  2 +-
 drivers/char/hw_random/Kconfig                | 11 +++++++++++
 drivers/char/hw_random/Makefile               |  1 +
 drivers/{crypto => char/hw_random}/qcom-rng.c |  0
 drivers/crypto/Kconfig                        | 11 -----------
 drivers/crypto/Makefile                       |  1 -
 drivers/gpu/drm/ci/arm64.config               |  2 +-
 9 files changed, 16 insertions(+), 16 deletions(-)
 rename drivers/{crypto => char/hw_random}/qcom-rng.c (100%)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index bcc9aabc1202..a3c612a9d423 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -404,10 +404,11 @@ CONFIG_SERIAL_DEV_BUS=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_ASPEED_KCS_IPMI_BMC=m
 CONFIG_ASPEED_BT_IPMI_BMC=m
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ST=y
+CONFIG_HW_RANDOM_QCOM=m
 CONFIG_TCG_TPM=m
 CONFIG_TCG_TIS_I2C_INFINEON=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_ARB_GPIO_CHALLENGE=m
 CONFIG_I2C_MUX_GPIO=y
@@ -1334,11 +1335,10 @@ CONFIG_CRYPTO_DEV_S5P=m
 CONFIG_CRYPTO_DEV_ATMEL_AES=m
 CONFIG_CRYPTO_DEV_ATMEL_TDES=m
 CONFIG_CRYPTO_DEV_ATMEL_SHA=m
 CONFIG_CRYPTO_DEV_MARVELL_CESA=m
 CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCOM_RNG=m
 CONFIG_CRYPTO_DEV_ROCKCHIP=m
 CONFIG_CRYPTO_DEV_STM32_HASH=m
 CONFIG_CRYPTO_DEV_STM32_CRYP=m
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig
index 29a1dea500f0..d57554971c03 100644
--- a/arch/arm/configs/qcom_defconfig
+++ b/arch/arm/configs/qcom_defconfig
@@ -115,10 +115,11 @@ CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_DEV_BUS=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_QCOM=m
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QUP=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
@@ -309,11 +310,10 @@ CONFIG_CRYPTO_USER=m
 CONFIG_CRYPTO_USER_API=m
 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_DEV_QCOM_RNG=m
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index d905a0777f93..bb930cce7233 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -548,10 +548,11 @@ CONFIG_VIRTIO_CONSOLE=y
 CONFIG_IPMI_HANDLER=m
 CONFIG_IPMI_DEVICE_INTERFACE=m
 CONFIG_IPMI_SI=m
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_HW_RANDOM_QCOM=m
 CONFIG_TCG_TPM=y
 CONFIG_TCG_TIS=m
 CONFIG_TCG_TIS_SPI=m
 CONFIG_TCG_TIS_SPI_CR50=y
 CONFIG_TCG_TIS_I2C_CR50=m
@@ -1951,11 +1952,10 @@ CONFIG_CRYPTO_AES_ARM64_BS=m
 CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
 CONFIG_CRYPTO_DEV_SUN8I_CE=m
 CONFIG_CRYPTO_DEV_FSL_CAAM=m
 CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
 CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCOM_RNG=m
 CONFIG_CRYPTO_DEV_TEGRA=m
 CONFIG_CRYPTO_DEV_XILINX_TRNG=m
 CONFIG_CRYPTO_DEV_ZYNQMP_AES=m
 CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=m
 CONFIG_CRYPTO_DEV_CCREE=m
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 492a2a61a65b..7102e03dcf0a 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -613,10 +613,21 @@ config HW_RANDOM_ROCKCHIP
 	  To compile this driver as a module, choose M here: the
 	  module will be called rockchip-rng.
 
 	  If unsure, say Y.
 
+config HW_RANDOM_QCOM
+	tristate "Qualcomm True Random Number Generator Driver"
+	depends on ARCH_QCOM || COMPILE_TEST
+	depends on HW_RANDOM
+	help
+	  This driver provides support for the True Random Number
+	  Generator hardware found on some Qualcomm SoCs.
+
+	  To compile this driver as a module, choose M here. The
+	  module will be called qcom-rng. If unsure, say N.
+
 endif # HW_RANDOM
 
 config UML_RANDOM
 	depends on UML
 	select HW_RANDOM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index b9132b3f5d21..605ba8df5a8f 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -50,5 +50,6 @@ obj-$(CONFIG_HW_RANDOM_XIPHERA) += xiphera-trng.o
 obj-$(CONFIG_HW_RANDOM_ARM_SMCCC_TRNG) += arm_smccc_trng.o
 obj-$(CONFIG_HW_RANDOM_CN10K) += cn10k-rng.o
 obj-$(CONFIG_HW_RANDOM_POLARFIRE_SOC) += mpfs-rng.o
 obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o
 obj-$(CONFIG_HW_RANDOM_JH7110) += jh7110-trng.o
+obj-$(CONFIG_HW_RANDOM_QCOM) += qcom-rng.o
diff --git a/drivers/crypto/qcom-rng.c b/drivers/char/hw_random/qcom-rng.c
similarity index 100%
rename from drivers/crypto/qcom-rng.c
rename to drivers/char/hw_random/qcom-rng.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index a12cd677467b..07f0fa3341fc 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -654,21 +654,10 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN
 
 	  Note that 192-bit keys are not supported by the hardware and are
 	  always processed by the software fallback, and all DES requests
 	  are done by the hardware.
 
-config CRYPTO_DEV_QCOM_RNG
-	tristate "Qualcomm Random Number Generator Driver"
-	depends on ARCH_QCOM || COMPILE_TEST
-	depends on HW_RANDOM
-	help
-	  This driver provides support for the Random Number
-	  Generator hardware found on Qualcomm SoCs.
-
-	  To compile this driver as a module, choose M here. The
-	  module will be called qcom-rng. If unsure, say N.
-
 config CRYPTO_DEV_IMGTEC_HASH
 	tristate "Imagination Technologies hardware hash accelerator"
 	depends on MIPS || COMPILE_TEST
 	select CRYPTO_MD5
 	select CRYPTO_SHA1
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 283bbc650b5b..a5f3d388f4d0 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -26,11 +26,10 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_DES) += omap-des.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
 obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
 obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
 obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
-obj-$(CONFIG_CRYPTO_DEV_QCOM_RNG) += qcom-rng.o
 obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
 obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
 obj-$(CONFIG_CRYPTO_DEV_SA2UL) += sa2ul.o
 obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
 obj-$(CONFIG_CRYPTO_DEV_SL3516) += gemini/
diff --git a/drivers/gpu/drm/ci/arm64.config b/drivers/gpu/drm/ci/arm64.config
index 563a69669a7b..c46125c1f80f 100644
--- a/drivers/gpu/drm/ci/arm64.config
+++ b/drivers/gpu/drm/ci/arm64.config
@@ -76,11 +76,10 @@ CONFIG_INTERCONNECT_QCOM_SDM845=y
 CONFIG_INTERCONNECT_QCOM_MSM8916=y
 CONFIG_INTERCONNECT_QCOM_MSM8996=y
 CONFIG_INTERCONNECT_QCOM_OSM_L3=y
 CONFIG_INTERCONNECT_QCOM_SC7180=y
 CONFIG_INTERCONNECT_QCOM_SM8350=y
-CONFIG_CRYPTO_DEV_QCOM_RNG=y
 CONFIG_SC_DISPCC_7180=y
 CONFIG_SC_GPUCC_7180=y
 CONFIG_SM_GPUCC_8350=y
 CONFIG_QCOM_SPMI_ADC5=y
 CONFIG_QCOM_SPMI_VADC=y
@@ -187,10 +186,11 @@ CONFIG_PWM_MEDIATEK=y
 CONFIG_DRM_MEDIATEK_HDMI=y
 CONFIG_GNSS=y
 CONFIG_GNSS_MTK_SERIAL=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MTK=y
+CONFIG_HW_RANDOM_QCOM=y
 CONFIG_MTK_DEVAPC=y
 CONFIG_PWM_MTK_DISP=y
 CONFIG_MTK_CMDQ=y
 CONFIG_REGULATOR_DA9211=y
 CONFIG_DRM_ANALOGIX_ANX7625=y
-- 
2.54.0


^ permalink raw reply related

* [PATCH 3/4] crypto: qcom-rng - Remove crypto_rng interface
From: Eric Biggers @ 2026-05-30  2:03 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
	linux-arm-msm, Olivia Mackall, Eric Biggers, stable
In-Reply-To: <20260530020332.143058-1-ebiggers@kernel.org>

qcom-rng.c exposes the same hardware through two completely separate
interfaces, crypto_rng and hwrng.  However, the implementation of this
is buggy because it permits generation operations from these interfaces
to run concurrently with each other, accessing the same registers.  That
is, qcom_rng_generate() synchronizes with itself but not with
qcom_hwrng_read().  This results in potential repetition of output from
the RNG, output of non-random values, etc.

Fortunately, there's actually no point in hardware RNG drivers
implementing the crypto_rng interface.  It's not actually used by
anything besides the "rng" algorithm type of AF_ALG, which in turn is
not actually used in practice.  Other crypto_rng hardware drivers are
likewise being phased out, leaving just the hwrng support.

Thus, remove it to simplify the code and avoid conflict (and confusion)
with the hwrng interface which is the one that actually matters.

Note that while this means the driver stops supporting "qcom,prng" and
"qcom,prng-ee", it didn't do anything useful on SoCs with those anyway.

Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 drivers/crypto/Kconfig    |   1 -
 drivers/crypto/qcom-rng.c | 175 ++------------------------------------
 2 files changed, 9 insertions(+), 167 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6ad..a12cd677467b 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -658,11 +658,10 @@ config CRYPTO_DEV_QCE_SW_MAX_LEN
 
 config CRYPTO_DEV_QCOM_RNG
 	tristate "Qualcomm Random Number Generator Driver"
 	depends on ARCH_QCOM || COMPILE_TEST
 	depends on HW_RANDOM
-	select CRYPTO_RNG
 	help
 	  This driver provides support for the Random Number
 	  Generator hardware found on Qualcomm SoCs.
 
 	  To compile this driver as a module, choose M here. The
diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index b7f3b9695dac..48b605687b28 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -1,14 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 // Copyright (c) 2017-18 Linaro Limited
 //
 // Based on msm-rng.c and downstream driver
 
-#include <crypto/internal/rng.h>
-#include <linux/acpi.h>
 #include <linux/clk.h>
-#include <linux/crypto.h>
 #include <linux/hw_random.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -30,28 +27,15 @@
 #define WORD_SZ			4
 
 #define QCOM_TRNG_QUALITY	1024
 
 struct qcom_rng {
-	struct mutex lock;
 	void __iomem *base;
 	struct clk *clk;
 	struct hwrng hwrng;
-	struct qcom_rng_match_data *match_data;
 };
 
-struct qcom_rng_ctx {
-	struct qcom_rng *rng;
-};
-
-struct qcom_rng_match_data {
-	bool skip_init;
-	bool hwrng_support;
-};
-
-static struct qcom_rng *qcom_rng_dev;
-
 static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
 {
 	unsigned int currsize = 0;
 	u32 val;
 	int ret;
@@ -77,41 +61,10 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
 	} while (currsize < max);
 
 	return currsize;
 }
 
-static int qcom_rng_generate(struct crypto_rng *tfm,
-			     const u8 *src, unsigned int slen,
-			     u8 *dstn, unsigned int dlen)
-{
-	struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm);
-	struct qcom_rng *rng = ctx->rng;
-	int ret;
-
-	ret = clk_prepare_enable(rng->clk);
-	if (ret)
-		return ret;
-
-	mutex_lock(&rng->lock);
-
-	ret = qcom_rng_read(rng, dstn, dlen);
-
-	mutex_unlock(&rng->lock);
-	clk_disable_unprepare(rng->clk);
-
-	if (ret >= 0)
-		ret = 0;
-
-	return ret;
-}
-
-static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
-			 unsigned int slen)
-{
-	return 0;
-}
-
 static int qcom_hwrng_init(struct hwrng *hwrng)
 {
 	struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
 
 	return clk_prepare_enable(qrng->clk);
@@ -129,159 +82,49 @@ static void qcom_hwrng_cleanup(struct hwrng *hwrng)
 	struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
 
 	clk_disable_unprepare(qrng->clk);
 }
 
-static int qcom_rng_enable(struct qcom_rng *rng)
-{
-	u32 val;
-	int ret;
-
-	ret = clk_prepare_enable(rng->clk);
-	if (ret)
-		return ret;
-
-	/* Enable PRNG only if it is not already enabled */
-	val = readl_relaxed(rng->base + PRNG_CONFIG);
-	if (val & PRNG_CONFIG_HW_ENABLE)
-		goto already_enabled;
-
-	val = readl_relaxed(rng->base + PRNG_LFSR_CFG);
-	val &= ~PRNG_LFSR_CFG_MASK;
-	val |= PRNG_LFSR_CFG_CLOCKS;
-	writel(val, rng->base + PRNG_LFSR_CFG);
-
-	val = readl_relaxed(rng->base + PRNG_CONFIG);
-	val |= PRNG_CONFIG_HW_ENABLE;
-	writel(val, rng->base + PRNG_CONFIG);
-
-already_enabled:
-	clk_disable_unprepare(rng->clk);
-
-	return 0;
-}
-
-static int qcom_rng_init(struct crypto_tfm *tfm)
-{
-	struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm);
-
-	ctx->rng = qcom_rng_dev;
-
-	if (!ctx->rng->match_data->skip_init)
-		return qcom_rng_enable(ctx->rng);
-
-	return 0;
-}
-
-static struct rng_alg qcom_rng_alg = {
-	.generate	= qcom_rng_generate,
-	.seed		= qcom_rng_seed,
-	.seedsize	= 0,
-	.base		= {
-		.cra_name		= "stdrng",
-		.cra_driver_name	= "qcom-rng",
-		.cra_flags		= CRYPTO_ALG_TYPE_RNG,
-		.cra_priority		= 300,
-		.cra_ctxsize		= sizeof(struct qcom_rng_ctx),
-		.cra_module		= THIS_MODULE,
-		.cra_init		= qcom_rng_init,
-	}
-};
-
 static int qcom_rng_probe(struct platform_device *pdev)
 {
 	struct qcom_rng *rng;
 	int ret;
 
 	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
 	if (!rng)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, rng);
-	mutex_init(&rng->lock);
-
 	rng->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(rng->base))
 		return PTR_ERR(rng->base);
 
 	rng->clk = devm_clk_get_optional(&pdev->dev, "core");
 	if (IS_ERR(rng->clk))
 		return PTR_ERR(rng->clk);
 
-	rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev);
-
-	qcom_rng_dev = rng;
-	ret = crypto_register_rng(&qcom_rng_alg);
-	if (ret) {
-		dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret);
-		qcom_rng_dev = NULL;
-		return ret;
-	}
-
-	if (rng->match_data->hwrng_support) {
-		rng->hwrng.name = "qcom_hwrng";
-		rng->hwrng.init = qcom_hwrng_init;
-		rng->hwrng.read = qcom_hwrng_read;
-		rng->hwrng.cleanup = qcom_hwrng_cleanup;
-		rng->hwrng.quality = QCOM_TRNG_QUALITY;
-		ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
-		if (ret) {
-			dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
-			qcom_rng_dev = NULL;
-			goto fail;
-		}
-	}
-
-	return ret;
-fail:
-	crypto_unregister_rng(&qcom_rng_alg);
+	rng->hwrng.name = "qcom_hwrng";
+	rng->hwrng.init = qcom_hwrng_init;
+	rng->hwrng.read = qcom_hwrng_read;
+	rng->hwrng.cleanup = qcom_hwrng_cleanup;
+	rng->hwrng.quality = QCOM_TRNG_QUALITY;
+	ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
+	if (ret)
+		dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
 	return ret;
 }
 
-static void qcom_rng_remove(struct platform_device *pdev)
-{
-	crypto_unregister_rng(&qcom_rng_alg);
-
-	qcom_rng_dev = NULL;
-}
-
-static struct qcom_rng_match_data qcom_prng_match_data = {
-	.skip_init = false,
-	.hwrng_support = false,
-};
-
-static struct qcom_rng_match_data qcom_prng_ee_match_data = {
-	.skip_init = true,
-	.hwrng_support = false,
-};
-
-static struct qcom_rng_match_data qcom_trng_match_data = {
-	.skip_init = true,
-	.hwrng_support = true,
-};
-
-static const struct acpi_device_id __maybe_unused qcom_rng_acpi_match[] = {
-	{ .id = "QCOM8160", .driver_data = (kernel_ulong_t)&qcom_prng_ee_match_data },
-	{}
-};
-MODULE_DEVICE_TABLE(acpi, qcom_rng_acpi_match);
-
 static const struct of_device_id __maybe_unused qcom_rng_of_match[] = {
-	{ .compatible = "qcom,prng", .data = &qcom_prng_match_data },
-	{ .compatible = "qcom,prng-ee", .data = &qcom_prng_ee_match_data },
-	{ .compatible = "qcom,trng", .data = &qcom_trng_match_data },
+	{ .compatible = "qcom,trng" },
 	{}
 };
 MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
 
 static struct platform_driver qcom_rng_driver = {
 	.probe = qcom_rng_probe,
-	.remove =  qcom_rng_remove,
 	.driver = {
 		.name = KBUILD_MODNAME,
 		.of_match_table = qcom_rng_of_match,
-		.acpi_match_table = ACPI_PTR(qcom_rng_acpi_match),
 	}
 };
 module_platform_driver(qcom_rng_driver);
 
 MODULE_ALIAS("platform:" KBUILD_MODNAME);
-- 
2.54.0


^ permalink raw reply related

* [PATCH 2/4] crypto: qcom-rng - Allow zero as a random number
From: Eric Biggers @ 2026-05-30  2:03 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
	linux-arm-msm, Olivia Mackall, Eric Biggers, stable
In-Reply-To: <20260530020332.143058-1-ebiggers@kernel.org>

Zero is a valid random number and needs to be allowed.  Otherwise the
output is distinguishable from random.

Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 drivers/crypto/qcom-rng.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index f31a7fe07ba7..b7f3b9695dac 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -63,13 +63,10 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
 					 200, 10000);
 		if (ret)
 			return ret;
 
 		val = readl_relaxed(rng->base + PRNG_DATA_OUT);
-		if (!val)
-			return -EINVAL;
-
 		if ((max - currsize) >= WORD_SZ) {
 			memcpy(data, &val, WORD_SZ);
 			data += WORD_SZ;
 			currsize += WORD_SZ;
 		} else {
-- 
2.54.0


^ permalink raw reply related

* [PATCH 1/4] crypto: qcom-rng - Enable clock in hwrng case
From: Eric Biggers @ 2026-05-30  2:03 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
	linux-arm-msm, Olivia Mackall, Eric Biggers, stable
In-Reply-To: <20260530020332.143058-1-ebiggers@kernel.org>

Fix qcom-rng.c to enable the clock before accessing the hardware.

Fixes: f29cd5bb64c2 ("crypto: qcom-rng - Add hw_random interface support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 drivers/crypto/qcom-rng.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c
index 150e5802e351..f31a7fe07ba7 100644
--- a/drivers/crypto/qcom-rng.c
+++ b/drivers/crypto/qcom-rng.c
@@ -111,17 +111,31 @@ static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
 			 unsigned int slen)
 {
 	return 0;
 }
 
+static int qcom_hwrng_init(struct hwrng *hwrng)
+{
+	struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
+
+	return clk_prepare_enable(qrng->clk);
+}
+
 static int qcom_hwrng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
 {
 	struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
 
 	return qcom_rng_read(qrng, data, max);
 }
 
+static void qcom_hwrng_cleanup(struct hwrng *hwrng)
+{
+	struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
+
+	clk_disable_unprepare(qrng->clk);
+}
+
 static int qcom_rng_enable(struct qcom_rng *rng)
 {
 	u32 val;
 	int ret;
 
@@ -206,11 +220,13 @@ static int qcom_rng_probe(struct platform_device *pdev)
 		return ret;
 	}
 
 	if (rng->match_data->hwrng_support) {
 		rng->hwrng.name = "qcom_hwrng";
+		rng->hwrng.init = qcom_hwrng_init;
 		rng->hwrng.read = qcom_hwrng_read;
+		rng->hwrng.cleanup = qcom_hwrng_cleanup;
 		rng->hwrng.quality = QCOM_TRNG_QUALITY;
 		ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
 		if (ret) {
 			dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
 			qcom_rng_dev = NULL;
-- 
2.54.0


^ permalink raw reply related

* [PATCH 0/4] qcom-rng fixes and cleanups
From: Eric Biggers @ 2026-05-30  2:03 UTC (permalink / raw)
  To: linux-crypto
  Cc: linux-kernel, Om Prakash Singh, Bjorn Andersson, Neil Armstrong,
	linux-arm-msm, Olivia Mackall, Eric Biggers

This series fixes several bugs in qcom-rng, including failure to enable
the clock before accessing the hardware, generating biased random
numbers, and generating duplicate or non-random numbers due to missing
locking.  To fix the latter bug, it drops the support for the
duplicative crypto_rng interface, which isn't used in practice, leaving
just hwrng which is the one that actually matters.

This series is targeting cryptodev/master

Eric Biggers (4):
  crypto: qcom-rng - Enable clock in hwrng case
  crypto: qcom-rng - Allow zero as a random number
  crypto: qcom-rng - Remove crypto_rng interface
  hwrng: qcom - Move qcom-rng.c into drivers/char/hw_random/

 arch/arm/configs/multi_v7_defconfig |   2 +-
 arch/arm/configs/qcom_defconfig     |   2 +-
 arch/arm64/configs/defconfig        |   2 +-
 drivers/char/hw_random/Kconfig      |  11 ++
 drivers/char/hw_random/Makefile     |   1 +
 drivers/char/hw_random/qcom-rng.c   | 132 +++++++++++++
 drivers/crypto/Kconfig              |  12 --
 drivers/crypto/Makefile             |   1 -
 drivers/crypto/qcom-rng.c           | 276 ----------------------------
 drivers/gpu/drm/ci/arm64.config     |   2 +-
 10 files changed, 148 insertions(+), 293 deletions(-)
 create mode 100644 drivers/char/hw_random/qcom-rng.c
 delete mode 100644 drivers/crypto/qcom-rng.c


base-commit: 5624ea54f3ba5c83d2e5503411a31a8be0278c1e
-- 
2.54.0


^ permalink raw reply

* [PATCH] crypto: loongson - Remove broken and unused loongson-rng
From: Eric Biggers @ 2026-05-29 23:32 UTC (permalink / raw)
  To: linux-crypto, Herbert Xu
  Cc: linux-kernel, loongarch, Qunqin Zhao, Huacai Chen, Yinggang Gu,
	Lee Jones, Eric Biggers, stable

The loongson-rng rng_alg has several vulnerabilities, including not
providing forward security, and a use-after-free bug due to the use of
wait_for_completion_interruptible().

Meanwhile, the rng_alg framework doesn't really have any purpose in the
first place other than to access the software algorithms crypto/drbg.c
and crypto/jitterentropy.c.  Hardware-specific rng_algs have no
in-kernel user, and unlike hwrng there's no feed into the actual Linux
RNG.  As such, there's really no point to this code.  There are of
course other rng_alg drivers that are similarly unused, but they're
similarly in the process of being phased out, e.g.
https://lore.kernel.org/r/20260529193648.18172-1-ebiggers@kernel.org and
https://lore.kernel.org/r/20260529220430.34135-1-ebiggers@kernel.org

Given that, there's no point in fixing forward these vulnerabilities,
and it makes much more sense to simply roll back the addition of this
driver.  If this platform provides TRNG (not PRNG) functionality, it
could make sense to add a hwrng driver, but it would be quite different.

Link: https://lore.kernel.org/linux-crypto/20260525145939.GC2018@quark/
Fixes: 766b2d724c8d ("crypto: loongson - add Loongson RNG driver support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 MAINTAINERS                                 |   1 -
 arch/loongarch/configs/loongson32_defconfig |   1 -
 arch/loongarch/configs/loongson64_defconfig |   1 -
 drivers/crypto/Kconfig                      |   1 -
 drivers/crypto/Makefile                     |   1 -
 drivers/crypto/loongson/Kconfig             |   6 -
 drivers/crypto/loongson/Makefile            |   1 -
 drivers/crypto/loongson/loongson-rng.c      | 209 --------------------
 8 files changed, 221 deletions(-)
 delete mode 100644 drivers/crypto/loongson/Kconfig
 delete mode 100644 drivers/crypto/loongson/Makefile
 delete mode 100644 drivers/crypto/loongson/loongson-rng.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 882214b0e7db..6c805560c77c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15068,11 +15068,10 @@ F:	drivers/pwm/pwm-loongson.c
 LOONGSON SECURITY ENGINE DRIVERS
 M:	Qunqin Zhao <zhaoqunqin@loongson.cn>
 L:	linux-crypto@vger.kernel.org
 S:	Maintained
 F:	drivers/char/tpm/tpm_loongson.c
-F:	drivers/crypto/loongson/
 F:	drivers/mfd/loongson-se.c
 F:	include/linux/mfd/loongson-se.h
 
 LOONGSON-2 SOC SERIES CLOCK DRIVER
 M:	Yinbo Zhu <zhuyinbo@loongson.cn>
diff --git a/arch/loongarch/configs/loongson32_defconfig b/arch/loongarch/configs/loongson32_defconfig
index d5ef396dffe3..82897236863f 100644
--- a/arch/loongarch/configs/loongson32_defconfig
+++ b/arch/loongarch/configs/loongson32_defconfig
@@ -1089,11 +1089,10 @@ CONFIG_CRYPTO_LZ4HC=m
 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_DEV_VIRTIO=m
-CONFIG_CRYPTO_DEV_LOONGSON_RNG=m
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_PRINTK_TIME=y
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/loongarch/configs/loongson64_defconfig b/arch/loongarch/configs/loongson64_defconfig
index cba4cdff5acd..a94e88bd7ec5 100644
--- a/arch/loongarch/configs/loongson64_defconfig
+++ b/arch/loongarch/configs/loongson64_defconfig
@@ -1122,11 +1122,10 @@ CONFIG_CRYPTO_LZ4HC=m
 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_DEV_VIRTIO=m
-CONFIG_CRYPTO_DEV_LOONGSON_RNG=m
 CONFIG_DMA_CMA=y
 CONFIG_DMA_NUMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_PRINTK_TIME=y
 CONFIG_STRIP_ASM_SYMS=y
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6ad..075ec9432789 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -844,11 +844,10 @@ config CRYPTO_DEV_CCREE
 	  Choose this if you wish to use hardware acceleration of
 	  cryptographic operations on the system REE.
 	  If unsure say Y.
 
 source "drivers/crypto/hisilicon/Kconfig"
-source "drivers/crypto/loongson/Kconfig"
 
 source "drivers/crypto/amlogic/Kconfig"
 
 config CRYPTO_DEV_SA2UL
 	tristate "Support for TI security accelerator"
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 283bbc650b5b..ad773158ae56 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -41,11 +41,10 @@ obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
 obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/
 obj-y += inside-secure/
 obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/
 obj-y += xilinx/
 obj-y += hisilicon/
-obj-y += loongson/
 obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
 obj-y += intel/
 obj-y += starfive/
 obj-y += cavium/
 obj-y += ti/
diff --git a/drivers/crypto/loongson/Kconfig b/drivers/crypto/loongson/Kconfig
deleted file mode 100644
index f4e1544ffbb4..000000000000
--- a/drivers/crypto/loongson/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config CRYPTO_DEV_LOONGSON_RNG
-	tristate "Support for Loongson RNG Driver"
-	depends on MFD_LOONGSON_SE
-	select CRYPTO_RNG
-	help
-	  Support for Loongson RNG Driver.
diff --git a/drivers/crypto/loongson/Makefile b/drivers/crypto/loongson/Makefile
deleted file mode 100644
index 1ce5ec32b553..000000000000
--- a/drivers/crypto/loongson/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_CRYPTO_DEV_LOONGSON_RNG)  += loongson-rng.o
diff --git a/drivers/crypto/loongson/loongson-rng.c b/drivers/crypto/loongson/loongson-rng.c
deleted file mode 100644
index 3a4940260f9e..000000000000
--- a/drivers/crypto/loongson/loongson-rng.c
+++ /dev/null
@@ -1,209 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2019 HiSilicon Limited. */
-/* Copyright (c) 2025 Loongson Technology Corporation Limited. */
-
-#include <linux/crypto.h>
-#include <linux/err.h>
-#include <linux/hw_random.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mfd/loongson-se.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <crypto/internal/rng.h>
-
-#define SE_SEED_SIZE 32
-
-struct loongson_rng_list {
-	struct mutex lock;
-	struct list_head list;
-	int registered;
-};
-
-struct loongson_rng {
-	u32 used;
-	struct loongson_se_engine *engine;
-	struct list_head list;
-	struct mutex lock;
-};
-
-struct loongson_rng_ctx {
-	struct loongson_rng *rng;
-};
-
-struct loongson_rng_cmd {
-	u32 cmd_id;
-	union {
-		u32 len;
-		u32 ret;
-	} u;
-	u32 seed_off;
-	u32 out_off;
-	u32 pad[4];
-};
-
-static struct loongson_rng_list rng_devices = {
-	.lock = __MUTEX_INITIALIZER(rng_devices.lock),
-	.list = LIST_HEAD_INIT(rng_devices.list),
-};
-
-static int loongson_rng_generate(struct crypto_rng *tfm, const u8 *src,
-			  unsigned int slen, u8 *dstn, unsigned int dlen)
-{
-	struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm);
-	struct loongson_rng *rng = ctx->rng;
-	struct loongson_rng_cmd *cmd = rng->engine->command;
-	int err, len;
-
-	mutex_lock(&rng->lock);
-	cmd->seed_off = 0;
-	do {
-		len = min(dlen, rng->engine->buffer_size);
-		cmd = rng->engine->command;
-		cmd->u.len = len;
-		err = loongson_se_send_engine_cmd(rng->engine);
-		if (err)
-			break;
-
-		cmd = rng->engine->command_ret;
-		if (cmd->u.ret) {
-			err = -EIO;
-			break;
-		}
-
-		memcpy(dstn, rng->engine->data_buffer, len);
-		dlen -= len;
-		dstn += len;
-	} while (dlen > 0);
-	mutex_unlock(&rng->lock);
-
-	return err;
-}
-
-static int loongson_rng_init(struct crypto_tfm *tfm)
-{
-	struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm);
-	struct loongson_rng *rng;
-	u32 min_used = U32_MAX;
-
-	mutex_lock(&rng_devices.lock);
-	list_for_each_entry(rng, &rng_devices.list, list) {
-		if (rng->used < min_used) {
-			ctx->rng = rng;
-			min_used = rng->used;
-		}
-	}
-	ctx->rng->used++;
-	mutex_unlock(&rng_devices.lock);
-
-	return 0;
-}
-
-static void loongson_rng_exit(struct crypto_tfm *tfm)
-{
-	struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm);
-
-	mutex_lock(&rng_devices.lock);
-	ctx->rng->used--;
-	mutex_unlock(&rng_devices.lock);
-}
-
-static int loongson_rng_seed(struct crypto_rng *tfm, const u8 *seed,
-			     unsigned int slen)
-{
-	struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm);
-	struct loongson_rng *rng = ctx->rng;
-	struct loongson_rng_cmd *cmd;
-	int err;
-
-	if (slen < SE_SEED_SIZE)
-		return -EINVAL;
-
-	slen = min(slen, rng->engine->buffer_size);
-
-	mutex_lock(&rng->lock);
-	cmd = rng->engine->command;
-	cmd->u.len = slen;
-	cmd->seed_off = rng->engine->buffer_off;
-	memcpy(rng->engine->data_buffer, seed, slen);
-	err = loongson_se_send_engine_cmd(rng->engine);
-	if (err)
-		goto out;
-
-	cmd = rng->engine->command_ret;
-	if (cmd->u.ret)
-		err = -EIO;
-out:
-	mutex_unlock(&rng->lock);
-
-	return err;
-}
-
-static struct rng_alg loongson_rng_alg = {
-	.generate = loongson_rng_generate,
-	.seed =	loongson_rng_seed,
-	.seedsize = SE_SEED_SIZE,
-	.base = {
-		.cra_name = "stdrng",
-		.cra_driver_name = "loongson_stdrng",
-		.cra_priority = 300,
-		.cra_ctxsize = sizeof(struct loongson_rng_ctx),
-		.cra_module = THIS_MODULE,
-		.cra_init = loongson_rng_init,
-		.cra_exit = loongson_rng_exit,
-	},
-};
-
-static int loongson_rng_probe(struct platform_device *pdev)
-{
-	struct loongson_rng_cmd *cmd;
-	struct loongson_rng *rng;
-	int ret = 0;
-
-	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
-	if (!rng)
-		return -ENOMEM;
-
-	rng->engine = loongson_se_init_engine(pdev->dev.parent, SE_ENGINE_RNG);
-	if (!rng->engine)
-		return -ENODEV;
-	cmd = rng->engine->command;
-	cmd->cmd_id = SE_CMD_RNG;
-	cmd->out_off = rng->engine->buffer_off;
-	mutex_init(&rng->lock);
-
-	mutex_lock(&rng_devices.lock);
-
-	if (!rng_devices.registered) {
-		ret = crypto_register_rng(&loongson_rng_alg);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to register crypto(%d)\n", ret);
-			goto out;
-		}
-		rng_devices.registered = 1;
-	}
-
-	list_add_tail(&rng->list, &rng_devices.list);
-out:
-	mutex_unlock(&rng_devices.lock);
-
-	return ret;
-}
-
-static struct platform_driver loongson_rng_driver = {
-	.probe		= loongson_rng_probe,
-	.driver		= {
-		.name	= "loongson-rng",
-	},
-};
-module_platform_driver(loongson_rng_driver);
-
-MODULE_ALIAS("platform:loongson-rng");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Yinggang Gu <guyinggang@loongson.cn>");
-MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@loongson.cn>");
-MODULE_DESCRIPTION("Loongson Random Number Generator driver");

base-commit: 5624ea54f3ba5c83d2e5503411a31a8be0278c1e
-- 
2.54.0


^ permalink raw reply related

* [PATCH] crypto: crypto4xx - Remove insecure and unused rng_alg
From: Eric Biggers @ 2026-05-29 22:04 UTC (permalink / raw)
  To: linux-crypto, Herbert Xu
  Cc: Christian Lamparter, linuxppc-dev, linux-kernel, Eric Biggers,
	stable

Remove crypto4xx_rng, as it is insecure and unused:

- It has only a 64-bit security strength, which is highly inadequate.
  This can be seen by the fact that crypto4xx_hw_init() seeds it with
  only 64 bits of entropy, and the fact that the original commit
  mentions that it implements ANSI X9.17 Annex C.

  Another issue was that this driver didn't implement the crypto_rng API
  correctly, as crypto4xx_prng_generate() didn't return 0 on success.

- No user of this code is known.  It's usable only theoretically via the
  "rng" algorithm type of AF_ALG.  But userspace actually just uses the
  actual Linux RNG (/dev/random etc) instead.  And rng_algs don't
  contribute entropy to the actual Linux RNG either.  (This may have
  been confused with hwrng, which does contribute entropy.)

Fixes: d072bfa48853 ("crypto: crypto4xx - add prng crypto support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 drivers/crypto/Kconfig                  |  1 -
 drivers/crypto/amcc/crypto4xx_core.c    | 88 -------------------------
 drivers/crypto/amcc/crypto4xx_core.h    |  4 --
 drivers/crypto/amcc/crypto4xx_reg_def.h | 11 ----
 4 files changed, 104 deletions(-)

diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6ad..5dab813a9f74 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -299,11 +299,10 @@ config CRYPTO_DEV_PPC4XX
 	select CRYPTO_AES
 	select CRYPTO_LIB_AES
 	select CRYPTO_CCM
 	select CRYPTO_CTR
 	select CRYPTO_GCM
-	select CRYPTO_RNG
 	select CRYPTO_SKCIPHER
 	help
 	  This option allows you to have support for AMCC crypto acceleration.
 
 config HW_RANDOM_PPC4XX
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index b7b6c97d2147..68c5ff7a85b4 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -29,15 +29,13 @@
 #include <crypto/aead.h>
 #include <crypto/aes.h>
 #include <crypto/ctr.h>
 #include <crypto/gcm.h>
 #include <crypto/sha1.h>
-#include <crypto/rng.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/skcipher.h>
 #include <crypto/internal/aead.h>
-#include <crypto/internal/rng.h>
 #include <crypto/internal/skcipher.h>
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_core.h"
 #include "crypto4xx_sa.h"
 #include "crypto4xx_trng.h"
@@ -983,14 +981,10 @@ static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
 		switch (alg->alg.type) {
 		case CRYPTO_ALG_TYPE_AEAD:
 			rc = crypto_register_aead(&alg->alg.u.aead);
 			break;
 
-		case CRYPTO_ALG_TYPE_RNG:
-			rc = crypto_register_rng(&alg->alg.u.rng);
-			break;
-
 		default:
 			rc = crypto_register_skcipher(&alg->alg.u.cipher);
 			break;
 		}
 
@@ -1012,14 +1006,10 @@ static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev)
 		switch (alg->alg.type) {
 		case CRYPTO_ALG_TYPE_AEAD:
 			crypto_unregister_aead(&alg->alg.u.aead);
 			break;
 
-		case CRYPTO_ALG_TYPE_RNG:
-			crypto_unregister_rng(&alg->alg.u.rng);
-			break;
-
 		default:
 			crypto_unregister_skcipher(&alg->alg.u.cipher);
 		}
 		kfree(alg);
 	}
@@ -1074,73 +1064,10 @@ static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
 {
 	return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR |
 		PPC4XX_TMO_ERR_INT);
 }
 
-static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
-				 u8 *data, unsigned int max)
-{
-	unsigned int i, curr = 0;
-	u32 val[2];
-
-	do {
-		/* trigger PRN generation */
-		writel(PPC4XX_PRNG_CTRL_AUTO_EN,
-		       dev->ce_base + CRYPTO4XX_PRNG_CTRL);
-
-		for (i = 0; i < 1024; i++) {
-			/* usually 19 iterations are enough */
-			if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
-			     CRYPTO4XX_PRNG_STAT_BUSY))
-				continue;
-
-			val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
-			val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
-			break;
-		}
-		if (i == 1024)
-			return -ETIMEDOUT;
-
-		if ((max - curr) >= 8) {
-			memcpy(data, &val, 8);
-			data += 8;
-			curr += 8;
-		} else {
-			/* copy only remaining bytes */
-			memcpy(data, &val, max - curr);
-			break;
-		}
-	} while (curr < max);
-
-	return curr;
-}
-
-static int crypto4xx_prng_generate(struct crypto_rng *tfm,
-				   const u8 *src, unsigned int slen,
-				   u8 *dstn, unsigned int dlen)
-{
-	struct rng_alg *alg = crypto_rng_alg(tfm);
-	struct crypto4xx_alg *amcc_alg;
-	struct crypto4xx_device *dev;
-	int ret;
-
-	amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
-	dev = amcc_alg->dev;
-
-	mutex_lock(&dev->core_dev->rng_lock);
-	ret = ppc4xx_prng_data_read(dev, dstn, dlen);
-	mutex_unlock(&dev->core_dev->rng_lock);
-	return ret;
-}
-
-
-static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
-			unsigned int slen)
-{
-	return 0;
-}
-
 /*
  * Supported Crypto Algorithms
  */
 static struct crypto4xx_alg_common crypto4xx_alg[] = {
 	/* Crypto AES modes */
@@ -1266,22 +1193,10 @@ static struct crypto4xx_alg_common crypto4xx_alg[] = {
 			.cra_blocksize	= 1,
 			.cra_ctxsize	= sizeof(struct crypto4xx_ctx),
 			.cra_module	= THIS_MODULE,
 		},
 	} },
-	{ .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
-		.base = {
-			.cra_name		= "stdrng",
-			.cra_driver_name        = "crypto4xx_rng",
-			.cra_priority		= 300,
-			.cra_ctxsize		= 0,
-			.cra_module		= THIS_MODULE,
-		},
-		.generate               = crypto4xx_prng_generate,
-		.seed                   = crypto4xx_prng_seed,
-		.seedsize               = 0,
-	} },
 };
 
 /*
  * Module Initialization Routine
  */
@@ -1351,13 +1266,10 @@ static int crypto4xx_probe(struct platform_device *ofdev)
 	}
 
 	core_dev->dev->core_dev = core_dev;
 	core_dev->dev->is_revb = is_revb;
 	core_dev->device = dev;
-	rc = devm_mutex_init(&ofdev->dev, &core_dev->rng_lock);
-	if (rc)
-		return rc;
 	spin_lock_init(&core_dev->lock);
 	INIT_LIST_HEAD(&core_dev->dev->alg_list);
 	ratelimit_default_init(&core_dev->dev->aead_ratelimit);
 	rc = crypto4xx_build_sdr(core_dev->dev);
 	if (rc)
diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h
index ee36630c670f..3a028aec3f0c 100644
--- a/drivers/crypto/amcc/crypto4xx_core.h
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -12,14 +12,12 @@
 
 #ifndef __CRYPTO4XX_CORE_H__
 #define __CRYPTO4XX_CORE_H__
 
 #include <linux/ratelimit.h>
-#include <linux/mutex.h>
 #include <linux/scatterlist.h>
 #include <crypto/internal/aead.h>
-#include <crypto/internal/rng.h>
 #include <crypto/internal/skcipher.h>
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_sa.h"
 
 #define PPC460SX_SDR0_SRST                      0x201
@@ -109,11 +107,10 @@ struct crypto4xx_core_device {
 	struct hwrng *trng;
 	u32 int_status;
 	u32 irq;
 	struct tasklet_struct tasklet;
 	spinlock_t lock;
-	struct mutex rng_lock;
 };
 
 struct crypto4xx_ctx {
 	struct crypto4xx_device *dev;
 	struct dynamic_sa_ctl *sa_in;
@@ -133,11 +130,10 @@ struct crypto4xx_aead_reqctx {
 struct crypto4xx_alg_common {
 	u32 type;
 	union {
 		struct skcipher_alg cipher;
 		struct aead_alg aead;
-		struct rng_alg rng;
 	} u;
 };
 
 struct crypto4xx_alg {
 	struct list_head  entry;
diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h
index 1038061224da..73d626308a84 100644
--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
@@ -88,24 +88,13 @@
 
 #define CRYPTO4XX_DMA_CFG	        	0x000600d4
 #define CRYPTO4XX_BYTE_ORDER_CFG 		0x000600d8
 #define CRYPTO4XX_ENDIAN_CFG			0x000600d8
 
-#define CRYPTO4XX_PRNG_STAT			0x00070000
-#define CRYPTO4XX_PRNG_STAT_BUSY		0x1
 #define CRYPTO4XX_PRNG_CTRL			0x00070004
 #define CRYPTO4XX_PRNG_SEED_L			0x00070008
 #define CRYPTO4XX_PRNG_SEED_H			0x0007000c
-
-#define CRYPTO4XX_PRNG_RES_0			0x00070020
-#define CRYPTO4XX_PRNG_RES_1			0x00070024
-#define CRYPTO4XX_PRNG_RES_2			0x00070028
-#define CRYPTO4XX_PRNG_RES_3			0x0007002C
-
-#define CRYPTO4XX_PRNG_LFSR_L			0x00070030
-#define CRYPTO4XX_PRNG_LFSR_H			0x00070034
-
 /*
  * Initialize CRYPTO ENGINE registers, and memory bases.
  */
 #define PPC4XX_PDR_POLL				0x3ff
 #define PPC4XX_OUTPUT_THRESHOLD			2

base-commit: 49e05bb00f2e8168695f7af4d694c39e1423e8a2
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH] crypto: sun4i-ss - Remove insecure and unused rng_alg
From: Eric Biggers @ 2026-05-29 20:54 UTC (permalink / raw)
  To: sashiko-reviews; +Cc: linux-sunxi, linux-crypto, Corentin Labbe
In-Reply-To: <20260529195725.5C7B91F00898@smtp.kernel.org>

On Fri, May 29, 2026 at 07:57:24PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] The debugfs directory and files created during probe are never removed on driver unbind, module unload, or probe failure, leading to a resource leak and potential Use-After-Free or page fault.
> - [High] The driver modifies a static global array (`ss_algs`) to store per-device context (`ss`), which breaks if multiple instances of the device are probed.
> - [High] Missing check on `sg_miter_next` return value leads to an infinite loop (DoS) inside a `spin_lock_bh` critical section.

Just par for the course for drivers/crypto/.

- Eric

^ permalink raw reply

* Re: [PATCH 0/2] Add hw_random Rust bindings
From: Manos Pitsidianakis @ 2026-05-29 20:35 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Herbert Xu, rust-for-linux, linux-kernel,
	linux-crypto, manos.pitsidianakis
In-Reply-To: <CANiq72mU=yQ_L_D6emvTj4c5E_ankLFvpXzkE7yTfcYfLB5T=g@mail.gmail.com>

Hi Miguel,

On Fri, 29 May 2026 23:02, Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote:
>On Fri, May 29, 2026 at 5:50 PM Manos Pitsidianakis
><manos@pitsidianak.is> wrote:
>>
>> A virtio-rng Rust driver that uses them will be submitted as a separate
>> series since it also depends on the virtio abstractions series.
>
>Please include that at least as a reference to a branch or similar,
>since in most cases the user is needed to evaluate abstractions etc.


Good point, thanks.

My WIP branch is here 
https://github.com/epilys/linux/tree/b4/rust-virtio-rng (HEAD is the 
driver that uses the abstraction in this series)

It uses atomics instead of a spinlock since we can't sleep during virtio 
driver probe. I didn't want to overcomplicate it by deferring all the 
sleeping work to a workqueue, but maybe it's a necessity until we get 
spinlocks that can disable IRQs.


>
>Thanks!
>
>Cheers,
>Miguel

^ permalink raw reply

* Re: [PATCH 0/2] Add hw_random Rust bindings
From: Miguel Ojeda @ 2026-05-29 20:02 UTC (permalink / raw)
  To: Manos Pitsidianakis
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Herbert Xu, rust-for-linux, linux-kernel,
	linux-crypto, manos.pitsidianakis
In-Reply-To: <20260529-rust-hw_random-virtio-rng-v1-0-b3153dd90311@pitsidianak.is>

On Fri, May 29, 2026 at 5:50 PM Manos Pitsidianakis
<manos@pitsidianak.is> wrote:
>
> A virtio-rng Rust driver that uses them will be submitted as a separate
> series since it also depends on the virtio abstractions series.

Please include that at least as a reference to a branch or similar,
since in most cases the user is needed to evaluate abstractions etc.

Thanks!

Cheers,
Miguel

^ permalink raw reply

* Re: [PATCH 2/2] rust: add hw_random module
From: Miguel Ojeda @ 2026-05-29 20:01 UTC (permalink / raw)
  To: Manos Pitsidianakis
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Herbert Xu, rust-for-linux, linux-kernel,
	linux-crypto, manos.pitsidianakis
In-Reply-To: <20260529-rust-hw_random-virtio-rng-v1-2-b3153dd90311@pitsidianak.is>

Hi Manos,

Some quick doc nits I noticed while managing our list...

On Fri, May 29, 2026 at 5:50 PM Manos Pitsidianakis
<manos@pitsidianak.is> wrote:
>
> +//! # Example

"Examples" is the section name we use.

> +//!# fn no_run() {
> +//!# use kernel::hw_random::*;
> +//!# use kernel::str::CString;
> +//!# use kernel::prelude::*;

Missing indentation.

> +//!     fn read(&self, data: &mut Buffer<'_>, can_wait: bool) -> Result<()> {

-> Result

> +//!         // write zeroes - in your driver, this should write actual data from your hardware.

"Write"

> +//! let name = CString::try_from(c"example_hwrng").unwrap();

Could you avoid `unwrap()`s, perhaps using `?` etc.? It is not
critical, but good practice to try to show how "real code" would be
written.

> +        from_result,          //
> +        to_result,            //
> +        VTABLE_DEFAULT_ERROR, //

Please only use the slashes in the last one:

> +    },

...but add one here, since this level doesn't have it.

> +    /// Returns `true` if the buffer has been filled.

[`true`]

> +        // SAFETY: u8 and MaybeUninit<u8> have the same layout

Please use Markdown (but no intra-doc links needed) in comments too, e.g.

  `u8` ... `MaybeUninit<u8>`

There are other instances below.

> +/// [`struct hwrng`]: srctree/include/linux/hw_random.h

Is this reference used?

> +#[vtable]
> +/// Trait for the implementation of hardware RNGs.

Attributes after documentation.

Other instances below too.

> +    /// [`hwrng_unregister`]: srctree/include/linux/hw_random.h
> +    #[inline]
> +    #[doc(alias = "hwrng_unregister")]

Is this one for the alias? How does it behave when rendered?

> +    pub fn unregister(&self) {
> +        if self
> +            .registered
> +            .compare_exchange(true, false, Ordering::SeqCst, Ordering::Acquire)
> +            .is_ok()

We are starting to add `// ORDERING: ...` comments for things like
this, so it would be nice to have them here already.

> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.

Please start comments capitalized. Other instances elsewhere too.

Cheers,
Miguel

^ permalink raw reply

* Re: [PATCH 2/2] rust: add hw_random module
From: Onur Özkan @ 2026-05-29 19:56 UTC (permalink / raw)
  To: Manos Pitsidianakis
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Herbert Xu, rust-for-linux, linux-kernel,
	linux-crypto, manos.pitsidianakis
In-Reply-To: <20260529-rust-hw_random-virtio-rng-v1-2-b3153dd90311@pitsidianak.is>

On Fri, 29 May 2026 18:50:27 +0300
Manos Pitsidianakis <manos@pitsidianak.is> wrote:

> Add abstraction for the hardware random number generator core subsystem.
> 
> The registration is guarded by an atomic boolean, because we cannot yet
> use IRQ disabling spinlocks in Rust. Once they are supported, we should
> switch to that, because it's theoretically possible to construct a data
> race. In practice I do not think it's possible, since registration
> happens once in driver probe and unregistration happens on driver
> teardown; there shouldn't be multiple threads doing their own thing in
> both cases.
> 
> Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
> ---
>  MAINTAINERS              |   8 ++
>  rust/kernel/hw_random.rs | 320 +++++++++++++++++++++++++++++++++++++++++++++++
>  rust/kernel/lib.rs       |   2 +
>  3 files changed, 330 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4f60b323c796fc0968fd67d1c7afee6802990572..a3b372ccbd07c4ae2c735ba31f2acf40472b384a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11304,6 +11304,14 @@ F:	Documentation/devicetree/bindings/rng/
>  F:	drivers/char/hw_random/
>  F:	include/linux/hw_random.h
>  
> +HARDWARE RANDOM NUMBER GENERATOR CORE [RUST]
> +M:	Manos Pitsidianakis <manos@pitsidianak.is>
> +M:	Herbert Xu <herbert@gondor.apana.org.au>
> +L:	linux-crypto@vger.kernel.org
> +L:	rust-for-linux@vger.kernel.org
> +S:	Maintained
> +F:	rust/kernel/hw_random.rs
> +
>  HARDWARE SPINLOCK CORE
>  M:	Bjorn Andersson <andersson@kernel.org>
>  R:	Baolin Wang <baolin.wang7@gmail.com>
> diff --git a/rust/kernel/hw_random.rs b/rust/kernel/hw_random.rs
> new file mode 100644
> index 0000000000000000000000000000000000000000..29fc180b4a3b4157a45c8fdb2d94bf1d9d781a3c
> --- /dev/null
> +++ b/rust/kernel/hw_random.rs
> @@ -0,0 +1,320 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Author: Manos Pitsidianakis <manos@pitsidianak.is>
> +
> +//! Hardware Random Number Generators
> +//!
> +//! This module provides an abstraction for implementing a hardware random number generator and
> +//! using it with the kernel's `hw_random` system.
> +//!
> +//! # Example
> +//!
> +//! ```no_run
> +//!# fn no_run() {
> +//!# use kernel::hw_random::*;
> +//!# use kernel::str::CString;
> +//!# use kernel::prelude::*;
> +//! #[pin_data]
> +//! struct ExampleHwRng {}
> +//!
> +//! #[vtable]
> +//! impl HwRngImpl for ExampleHwRng {
> +//!     fn read(&self, data: &mut Buffer<'_>, can_wait: bool) -> Result<()> {
> +//!         // write zeroes - in your driver, this should write actual data from your hardware.
> +//!         data.write(&[0_u8; 8]);
> +//!         Ok(())
> +//!     }
> +//! }
> +//!
> +//! let name = CString::try_from(c"example_hwrng").unwrap();
> +//! let my_rng = KBox::pin_init(
> +//!                 HwRng::new(
> +//!                     name,
> +//!                     0,
> +//!                     try_pin_init!(ExampleHwRng {})
> +//!                 ),
> +//!                 GFP_KERNEL
> +//!              ).unwrap();
> +//! // Register `my_rng`: after this succeeds, the kernel may call our `HwRngImpl` method at any
> +//! // time.
> +//! my_rng.register().unwrap();
> +//!
> +//! // ...
> +//!
> +//! my_rng.unregister();
> +//!# }
> +//!```
> +
> +use crate::{
> +    error::{
> +        from_result,          //
> +        to_result,            //
> +        VTABLE_DEFAULT_ERROR, //
> +    },
> +    prelude::*, //
> +    str::{
> +        CString, //
> +    },
> +    types::{
> +        Opaque, //
> +    },
> +};
> +
> +use core::{
> +    ffi::{
> +        c_int,    //
> +        c_ushort, //
> +        c_void,   //
> +    },
> +    mem::{
> +        MaybeUninit, //
> +    },
> +    ptr::{
> +        slice_from_raw_parts,     //
> +        slice_from_raw_parts_mut, //
> +    },
> +    sync::atomic::{
> +        AtomicBool, //
> +        Ordering,   //
> +    },
> +};
> +
> +use pin_init::pin_init_from_closure;
> +
> +/// A buffer to write random bytes in using [`Buffer::write`] that tracks how many bytes were
> +/// written.
> +///
> +/// See also [`HwRngImpl::read`].
> +pub struct Buffer<'a> {
> +    inner: &'a mut [MaybeUninit<u8>],
> +    written: usize,
> +}
> +
> +impl Buffer<'_> {
> +    /// Returns `true` if the buffer has been filled.
> +    #[inline]
> +    pub const fn is_empty(&self) -> bool {
> +        self.written == self.inner.len()
> +    }
> +
> +    /// Returns the number of bytes that can be written.
> +    #[inline]
> +    pub const fn len(&self) -> usize {

This name is quite confusing for what it actually does. `len()` is a very common
API across many types and readers would usually expect it to return the total
length of the buffer. A more explicit name like `remaining_len()` or
`writable_len()` would make it much clearer.

> +        self.inner.len() - self.written
> +    }
> +
> +    /// Writes bytes from `buf` into buffer and returns the amount of bytes written.
> +    #[inline]
> +    pub fn write(&mut self, buf: &[u8]) -> usize {
> +        let to_copy = self.len().min(buf.len());
> +        let ptr = buf.as_ptr();
> +        // SAFETY: u8 and MaybeUninit<u8> have the same layout
> +        let buf = unsafe { &*slice_from_raw_parts(ptr.cast::<MaybeUninit<u8>>(), to_copy) };
> +        self.inner[self.written..][..to_copy].copy_from_slice(buf);
> +        self.written += to_copy;
> +        to_copy
> +    }
> +}
> +
> +/// An adapter type for the registration of hardware random number generators drivers.
> +///
> +/// [`struct hwrng`]: srctree/include/linux/hw_random.h
> +#[pin_data(PinnedDrop)]
> +pub struct HwRng<T: HwRngImpl + 'static> {
> +    #[pin]
> +    registration: Opaque<bindings::hwrng>,
> +    registered: AtomicBool,
> +    #[pin]
> +    name: CString,
> +    #[pin]
> +    inner: T,
> +}
> +
> +impl<T: HwRngImpl + 'static> core::ops::Deref for HwRng<T> {
> +    type Target = T;
> +
> +    #[inline]
> +    fn deref(&self) -> &Self::Target {
> +        &self.inner
> +    }
> +}
> +
> +// SAFETY: HwRng contains a `*const u8` reference but it is opaque for us in Rust.
> +unsafe impl<T: HwRngImpl + 'static> Send for HwRng<T> {}
> +
> +// SAFETY: `HwRng` has no interior mutability from Rust, and C manages it with the rng_mutex lock.
> +unsafe impl<T: HwRngImpl + 'static> Sync for HwRng<T> {}
> +
> +#[pinned_drop]
> +impl<T: HwRngImpl> PinnedDrop for HwRng<T> {
> +    fn drop(self: Pin<&mut Self>) {
> +        self.unregister();
> +    }
> +}
> +
> +#[vtable]
> +/// Trait for the implementation of hardware RNGs.
> +pub trait HwRngImpl: Send + Sync {
> +    #[inline]
> +    /// Initialization callback, can be optionally implemented.
> +    fn init(&self) -> Result {
> +        build_error!(VTABLE_DEFAULT_ERROR)
> +    }
> +
> +    #[inline]
> +    /// Cleanup callback, can be optionally implemented.
> +    fn cleanup(&self) {
> +        build_error!(VTABLE_DEFAULT_ERROR)
> +    }
> +
> +    /// Places random bytes in `data`.
> +    fn read(&self, data: &mut Buffer<'_>, can_wait: bool) -> Result<()>;
> +}
> +
> +impl<T: HwRngImpl + 'static> HwRng<T> {
> +    /// Create a new [`HwRng`] without registering it.
> +    pub fn new(
> +        name: CString,
> +        quality: c_ushort,
> +        inner: impl PinInit<T, Error>,
> +    ) -> impl PinInit<Self, Error> {
> +        // We use pin_init_from_closure because we need to store the `slot` address as `priv` field
> +        // of `hwrng` struct.
> +
> +        // SAFETY:
> +        // - when the closure returns `Ok(())`, then it has successfully initialized all fields,
> +        // - when it returns `Err(e)`, it does not need to perform any cleanup.
> +        unsafe {
> +            pin_init_from_closure(move |slot: *mut Self| {
> +                inner.__pinned_init(&raw mut (*slot).inner)?;
> +
> +                let registration = (&raw mut (*slot).registration).cast::<bindings::hwrng>();
> +                registration.write(bindings::hwrng {
> +                    name: name.as_char_ptr(),
> +                    read: Some(Self::read_callback),
> +                    init: if <T as HwRngImpl>::HAS_INIT {
> +                        Some(Self::init_callback)
> +                    } else {
> +                        None
> +                    },
> +                    cleanup: if <T as HwRngImpl>::HAS_CLEANUP {
> +                        Some(Self::cleanup_callback)
> +                    } else {
> +                        None
> +                    },
> +                    quality,
> +                    priv_: slot as usize,
> +                    ..Default::default()
> +                });
> +
> +                let name_ptr = &raw mut (*slot).name;
> +                name_ptr.write(name);
> +
> +                let registered = &raw mut (*slot).registered;
> +                registered.write(AtomicBool::new(false));
> +
> +                // All fields of `HwRng` have been initialized
> +                Ok(())
> +            })
> +        }
> +    }
> +
> +    /// Register `self` with the `hwrng` subsystem.
> +    ///
> +    /// After this function successfully returns, the `hwrng` subsystem can start calling the
> +    /// [`HwRngImpl`] methods at any time.
> +    ///
> +    /// [`hwrng_register`]: srctree/include/linux/hw_random.h
> +    #[inline]
> +    #[doc(alias = "hwrng_register")]
> +    pub fn register(&self) -> Result {
> +        if self
> +            .registered
> +            .compare_exchange(false, true, Ordering::SeqCst, Ordering::Acquire)
> +            .is_ok()
> +        {
> +            // SAFETY: `registration` is properly initialized.
> +            if let Err(err) = to_result(unsafe {
> +                bindings::hwrng_register(self.registration.get().cast::<bindings::hwrng>())
> +            }) {
> +                self.registered.store(false, Ordering::Release);
> +                return Err(err);
> +            }
> +        }
> +        Ok(())
> +    }
> +
> +    /// Unregister `self` from `hwrng` subsystem.
> +    ///
> +    /// [`hwrng_unregister`]: srctree/include/linux/hw_random.h
> +    #[inline]
> +    #[doc(alias = "hwrng_unregister")]
> +    pub fn unregister(&self) {
> +        if self
> +            .registered
> +            .compare_exchange(true, false, Ordering::SeqCst, Ordering::Acquire)
> +            .is_ok()
> +        {
> +            // SAFETY: Since `registration` is properly initialized and registered, destroying is
> +            // safe.
> +            unsafe {
> +                bindings::hwrng_unregister(self.registration.get().cast::<bindings::hwrng>())
> +            };
> +        }
> +    }
> +}
> +
> +impl<T: HwRngImpl + 'static> HwRng<T> {
> +    extern "C" fn init_callback(ptr: *mut bindings::hwrng) -> c_int {
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        from_result(|| {
> +            inner.init()?;
> +            Ok(0)
> +        })
> +    }
> +
> +    extern "C" fn cleanup_callback(ptr: *mut bindings::hwrng) {
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        inner.cleanup();
> +    }
> +
> +    extern "C" fn read_callback(
> +        ptr: *mut bindings::hwrng,
> +        data: *mut c_void,
> +        max: usize,
> +        wait: bool,
> +    ) -> c_int {
> +        if data.is_null() || max == 0 {
> +            return 0;
> +        }
> +
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        let buf_ptr = slice_from_raw_parts_mut(data.cast::<MaybeUninit<u8>>(), max);
> +        // SAFETY: By the hw_random API contract, data points to a bytes buffer `max` bytes long.
> +        let buf_ref = unsafe { &mut *buf_ptr };
> +
> +        let mut buffer = Buffer {
> +            inner: buf_ref,
> +            written: 0,
> +        };
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        from_result(|| {
> +            inner.read(&mut buffer, wait)?;
> +            Ok(buffer.written.try_into().unwrap_or(c_int::MAX))
> +        })
> +    }
> +}
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index ea08641919c26faba97cf5dd9b67b0df55fcd698..096b6d9d57d20612864289e87a359331058fb01c 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -74,6 +74,8 @@
>  pub mod fs;
>  #[cfg(CONFIG_GPU_BUDDY = "y")]
>  pub mod gpu;
> +#[cfg(CONFIG_HW_RANDOM = "y")]
> +pub mod hw_random;
>  #[cfg(CONFIG_I2C = "y")]
>  pub mod i2c;
>  pub mod id_pool;
> 
> -- 
> 2.47.3
> 

^ permalink raw reply

* Re: [PATCH 2/2] rust: add hw_random module
From: Onur Özkan @ 2026-05-29 19:48 UTC (permalink / raw)
  To: Manos Pitsidianakis
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Herbert Xu, rust-for-linux, linux-kernel,
	linux-crypto, manos.pitsidianakis
In-Reply-To: <20260529-rust-hw_random-virtio-rng-v1-2-b3153dd90311@pitsidianak.is>

On Fri, 29 May 2026 18:50:27 +0300
Manos Pitsidianakis <manos@pitsidianak.is> wrote:

> Add abstraction for the hardware random number generator core subsystem.
> 
> The registration is guarded by an atomic boolean, because we cannot yet
> use IRQ disabling spinlocks in Rust. Once they are supported, we should
> switch to that, because it's theoretically possible to construct a data
> race. In practice I do not think it's possible, since registration
> happens once in driver probe and unregistration happens on driver
> teardown; there shouldn't be multiple threads doing their own thing in
> both cases.

hw_random/core.c seem to use Mutex, why are you not using Mutex<bool> instead of
flipping atomics which doesn't really serialize register & unregister properly?

> 
> Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
> ---
>  MAINTAINERS              |   8 ++
>  rust/kernel/hw_random.rs | 320 +++++++++++++++++++++++++++++++++++++++++++++++
>  rust/kernel/lib.rs       |   2 +
>  3 files changed, 330 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 4f60b323c796fc0968fd67d1c7afee6802990572..a3b372ccbd07c4ae2c735ba31f2acf40472b384a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -11304,6 +11304,14 @@ F:	Documentation/devicetree/bindings/rng/
>  F:	drivers/char/hw_random/
>  F:	include/linux/hw_random.h
>  
> +HARDWARE RANDOM NUMBER GENERATOR CORE [RUST]
> +M:	Manos Pitsidianakis <manos@pitsidianak.is>
> +M:	Herbert Xu <herbert@gondor.apana.org.au>
> +L:	linux-crypto@vger.kernel.org
> +L:	rust-for-linux@vger.kernel.org
> +S:	Maintained
> +F:	rust/kernel/hw_random.rs
> +
>  HARDWARE SPINLOCK CORE
>  M:	Bjorn Andersson <andersson@kernel.org>
>  R:	Baolin Wang <baolin.wang7@gmail.com>
> diff --git a/rust/kernel/hw_random.rs b/rust/kernel/hw_random.rs
> new file mode 100644
> index 0000000000000000000000000000000000000000..29fc180b4a3b4157a45c8fdb2d94bf1d9d781a3c
> --- /dev/null
> +++ b/rust/kernel/hw_random.rs
> @@ -0,0 +1,320 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Author: Manos Pitsidianakis <manos@pitsidianak.is>
> +
> +//! Hardware Random Number Generators
> +//!
> +//! This module provides an abstraction for implementing a hardware random number generator and
> +//! using it with the kernel's `hw_random` system.
> +//!
> +//! # Example
> +//!
> +//! ```no_run
> +//!# fn no_run() {
> +//!# use kernel::hw_random::*;
> +//!# use kernel::str::CString;
> +//!# use kernel::prelude::*;
> +//! #[pin_data]
> +//! struct ExampleHwRng {}
> +//!
> +//! #[vtable]
> +//! impl HwRngImpl for ExampleHwRng {
> +//!     fn read(&self, data: &mut Buffer<'_>, can_wait: bool) -> Result<()> {
> +//!         // write zeroes - in your driver, this should write actual data from your hardware.
> +//!         data.write(&[0_u8; 8]);
> +//!         Ok(())
> +//!     }
> +//! }
> +//!
> +//! let name = CString::try_from(c"example_hwrng").unwrap();
> +//! let my_rng = KBox::pin_init(
> +//!                 HwRng::new(
> +//!                     name,
> +//!                     0,
> +//!                     try_pin_init!(ExampleHwRng {})
> +//!                 ),
> +//!                 GFP_KERNEL
> +//!              ).unwrap();
> +//! // Register `my_rng`: after this succeeds, the kernel may call our `HwRngImpl` method at any
> +//! // time.
> +//! my_rng.register().unwrap();
> +//!
> +//! // ...
> +//!
> +//! my_rng.unregister();
> +//!# }
> +//!```
> +
> +use crate::{
> +    error::{
> +        from_result,          //
> +        to_result,            //
> +        VTABLE_DEFAULT_ERROR, //
> +    },
> +    prelude::*, //
> +    str::{
> +        CString, //
> +    },
> +    types::{
> +        Opaque, //
> +    },
> +};
> +
> +use core::{
> +    ffi::{
> +        c_int,    //
> +        c_ushort, //
> +        c_void,   //

You don't need to put "//" to every line. You can simply do:

	a,
	b,
	c,
	//

> +    },
> +    mem::{
> +        MaybeUninit, //
> +    },
> +    ptr::{
> +        slice_from_raw_parts,     //
> +        slice_from_raw_parts_mut, //
> +    },
> +    sync::atomic::{
> +        AtomicBool, //
> +        Ordering,   //
> +    },
> +};
> +
> +use pin_init::pin_init_from_closure;
> +
> +/// A buffer to write random bytes in using [`Buffer::write`] that tracks how many bytes were
> +/// written.
> +///
> +/// See also [`HwRngImpl::read`].
> +pub struct Buffer<'a> {
> +    inner: &'a mut [MaybeUninit<u8>],
> +    written: usize,
> +}
> +
> +impl Buffer<'_> {
> +    /// Returns `true` if the buffer has been filled.

Either the doc or function name is wrong. Looking at the function logic, this
should be called "is_full"?

> +    #[inline]
> +    pub const fn is_empty(&self) -> bool {
> +        self.written == self.inner.len()
> +    }
> +
> +    /// Returns the number of bytes that can be written.
> +    #[inline]
> +    pub const fn len(&self) -> usize {
> +        self.inner.len() - self.written
> +    }
> +
> +    /// Writes bytes from `buf` into buffer and returns the amount of bytes written.
> +    #[inline]
> +    pub fn write(&mut self, buf: &[u8]) -> usize {
> +        let to_copy = self.len().min(buf.len());
> +        let ptr = buf.as_ptr();
> +        // SAFETY: u8 and MaybeUninit<u8> have the same layout
> +        let buf = unsafe { &*slice_from_raw_parts(ptr.cast::<MaybeUninit<u8>>(), to_copy) };
> +        self.inner[self.written..][..to_copy].copy_from_slice(buf);
> +        self.written += to_copy;
> +        to_copy
> +    }
> +}
> +
> +/// An adapter type for the registration of hardware random number generators drivers.
> +///
> +/// [`struct hwrng`]: srctree/include/linux/hw_random.h
> +#[pin_data(PinnedDrop)]
> +pub struct HwRng<T: HwRngImpl + 'static> {
> +    #[pin]
> +    registration: Opaque<bindings::hwrng>,
> +    registered: AtomicBool,
> +    #[pin]
> +    name: CString,
> +    #[pin]
> +    inner: T,
> +}
> +
> +impl<T: HwRngImpl + 'static> core::ops::Deref for HwRng<T> {
> +    type Target = T;
> +
> +    #[inline]
> +    fn deref(&self) -> &Self::Target {
> +        &self.inner
> +    }
> +}
> +
> +// SAFETY: HwRng contains a `*const u8` reference but it is opaque for us in Rust.
> +unsafe impl<T: HwRngImpl + 'static> Send for HwRng<T> {}
> +
> +// SAFETY: `HwRng` has no interior mutability from Rust, and C manages it with the rng_mutex lock.
> +unsafe impl<T: HwRngImpl + 'static> Sync for HwRng<T> {}
> +
> +#[pinned_drop]
> +impl<T: HwRngImpl> PinnedDrop for HwRng<T> {
> +    fn drop(self: Pin<&mut Self>) {
> +        self.unregister();
> +    }
> +}
> +
> +#[vtable]
> +/// Trait for the implementation of hardware RNGs.

Doc-comment should come first.

> +pub trait HwRngImpl: Send + Sync {
> +    #[inline]
> +    /// Initialization callback, can be optionally implemented.
> +    fn init(&self) -> Result {
> +        build_error!(VTABLE_DEFAULT_ERROR)
> +    }
> +
> +    #[inline]
> +    /// Cleanup callback, can be optionally implemented.
> +    fn cleanup(&self) {
> +        build_error!(VTABLE_DEFAULT_ERROR)
> +    }
> +
> +    /// Places random bytes in `data`.
> +    fn read(&self, data: &mut Buffer<'_>, can_wait: bool) -> Result<()>;
> +}
> +
> +impl<T: HwRngImpl + 'static> HwRng<T> {
> +    /// Create a new [`HwRng`] without registering it.
> +    pub fn new(
> +        name: CString,
> +        quality: c_ushort,
> +        inner: impl PinInit<T, Error>,
> +    ) -> impl PinInit<Self, Error> {
> +        // We use pin_init_from_closure because we need to store the `slot` address as `priv` field
> +        // of `hwrng` struct.
> +
> +        // SAFETY:
> +        // - when the closure returns `Ok(())`, then it has successfully initialized all fields,
> +        // - when it returns `Err(e)`, it does not need to perform any cleanup.
> +        unsafe {
> +            pin_init_from_closure(move |slot: *mut Self| {
> +                inner.__pinned_init(&raw mut (*slot).inner)?;
> +
> +                let registration = (&raw mut (*slot).registration).cast::<bindings::hwrng>();
> +                registration.write(bindings::hwrng {
> +                    name: name.as_char_ptr(),
> +                    read: Some(Self::read_callback),
> +                    init: if <T as HwRngImpl>::HAS_INIT {
> +                        Some(Self::init_callback)
> +                    } else {
> +                        None
> +                    },
> +                    cleanup: if <T as HwRngImpl>::HAS_CLEANUP {
> +                        Some(Self::cleanup_callback)
> +                    } else {
> +                        None
> +                    },
> +                    quality,
> +                    priv_: slot as usize,
> +                    ..Default::default()
> +                });
> +
> +                let name_ptr = &raw mut (*slot).name;
> +                name_ptr.write(name);
> +
> +                let registered = &raw mut (*slot).registered;
> +                registered.write(AtomicBool::new(false));
> +
> +                // All fields of `HwRng` have been initialized
> +                Ok(())
> +            })
> +        }
> +    }
> +
> +    /// Register `self` with the `hwrng` subsystem.
> +    ///
> +    /// After this function successfully returns, the `hwrng` subsystem can start calling the
> +    /// [`HwRngImpl`] methods at any time.
> +    ///
> +    /// [`hwrng_register`]: srctree/include/linux/hw_random.h
> +    #[inline]
> +    #[doc(alias = "hwrng_register")]
> +    pub fn register(&self) -> Result {
> +        if self
> +            .registered
> +            .compare_exchange(false, true, Ordering::SeqCst, Ordering::Acquire)
> +            .is_ok()
> +        {
> +            // SAFETY: `registration` is properly initialized.
> +            if let Err(err) = to_result(unsafe {
> +                bindings::hwrng_register(self.registration.get().cast::<bindings::hwrng>())
> +            }) {
> +                self.registered.store(false, Ordering::Release);
> +                return Err(err);
> +            }
> +        }
> +        Ok(())
> +    }
> +
> +    /// Unregister `self` from `hwrng` subsystem.
> +    ///
> +    /// [`hwrng_unregister`]: srctree/include/linux/hw_random.h
> +    #[inline]
> +    #[doc(alias = "hwrng_unregister")]
> +    pub fn unregister(&self) {
> +        if self
> +            .registered
> +            .compare_exchange(true, false, Ordering::SeqCst, Ordering::Acquire)
> +            .is_ok()
> +        {
> +            // SAFETY: Since `registration` is properly initialized and registered, destroying is
> +            // safe.
> +            unsafe {
> +                bindings::hwrng_unregister(self.registration.get().cast::<bindings::hwrng>())
> +            };
> +        }
> +    }
> +}
> +
> +impl<T: HwRngImpl + 'static> HwRng<T> {
> +    extern "C" fn init_callback(ptr: *mut bindings::hwrng) -> c_int {
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        from_result(|| {
> +            inner.init()?;
> +            Ok(0)
> +        })
> +    }
> +
> +    extern "C" fn cleanup_callback(ptr: *mut bindings::hwrng) {
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        inner.cleanup();
> +    }
> +
> +    extern "C" fn read_callback(
> +        ptr: *mut bindings::hwrng,
> +        data: *mut c_void,
> +        max: usize,
> +        wait: bool,
> +    ) -> c_int {
> +        if data.is_null() || max == 0 {
> +            return 0;
> +        }
> +
> +        // SAFETY: we set `priv_` as the value of `*mut Self` when initializing.
> +        let priv_ = unsafe { (*ptr).priv_ };
> +        let this_ptr = priv_ as *mut Self;
> +
> +        let buf_ptr = slice_from_raw_parts_mut(data.cast::<MaybeUninit<u8>>(), max);
> +        // SAFETY: By the hw_random API contract, data points to a bytes buffer `max` bytes long.
> +        let buf_ref = unsafe { &mut *buf_ptr };
> +
> +        let mut buffer = Buffer {
> +            inner: buf_ref,
> +            written: 0,
> +        };
> +
> +        // SAFETY: we set `inner` to point to a valid `T` when initializing.
> +        let inner: &T = unsafe { &(*this_ptr).inner };
> +        from_result(|| {
> +            inner.read(&mut buffer, wait)?;
> +            Ok(buffer.written.try_into().unwrap_or(c_int::MAX))
> +        })
> +    }
> +}
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index ea08641919c26faba97cf5dd9b67b0df55fcd698..096b6d9d57d20612864289e87a359331058fb01c 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -74,6 +74,8 @@
>  pub mod fs;
>  #[cfg(CONFIG_GPU_BUDDY = "y")]
>  pub mod gpu;
> +#[cfg(CONFIG_HW_RANDOM = "y")]
> +pub mod hw_random;
>  #[cfg(CONFIG_I2C = "y")]
>  pub mod i2c;
>  pub mod id_pool;
> 
> -- 
> 2.47.3
> 

^ permalink raw reply

* Re: [PATCH v2] crypto: sun4i-ss - clamp PRNG seed length to prevent heap overflow
From: Eric Biggers @ 2026-05-29 19:41 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: Tianchu Chen, herbert, davem, wens, jernej.skrabec, samuel,
	linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <20260529173341.GA566433@google.com>

On Fri, May 29, 2026 at 05:33:41PM +0000, Eric Biggers wrote:
> On Fri, May 29, 2026 at 07:10:06PM +0200, Corentin Labbe wrote:
> > Le Fri, May 29, 2026 at 09:10:57AM -0700, Eric Biggers a écrit :
> > > On Fri, May 29, 2026 at 08:08:01AM +0000, Tianchu Chen wrote:
> > > > From: Tianchu Chen <flynnnchen@tencent.com>
> > > > 
> > > > sun4i_ss_prng_seed() copies the user-supplied seed into ss->seed
> > > > using the user-provided length with no bounds check. The crypto core
> > > > does not enforce slen <= seedsize before calling into the driver, so a
> > > > userspace caller via AF_ALG setsockopt(ALG_SET_KEY) can pass up to
> > > > sysctl_optmem_max bytes, overflowing the fixed-size buffer and
> > > > corrupting adjacent heap memory.
> > > > 
> > > > Clamp the copy length to the buffer size, matching the approach used by
> > > > loongson-rng for oversized seeds.
> > > > 
> > > > Discovered by Atuin - Automated Vulnerability Discovery Engine.
> > > > 
> > > > Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> > > > ---
> > > > v2: Silently clamp oversized seeds with min_t instead of returning
> > > >     -EINVAL (Herbert Xu).
> > > 
> > > sun4i-ss-prng.c is useless, is still broken, and should just be deleted.
> > 
> > Hello
> > 
> > useless ? clearly no, it helped a lot on devices where it is.
> 
> The only way this code is reachable is via "rng" algorithm type in
> AF_ALG, which is almost never used.  Everyone just uses the regular
> Linux RNG (/dev/random etc) instead, as they should.
> 
> In fact, anyone were to accidentally use this it would be a security
> vulnerability, seeing as sun4i_ss_prng_generate() doesn't actually fill
> in all the bytes that were requested.  It also doesn't wait for the FIFO
> to be ready when reading data from it.
> 
> Is it possible that there's a misunderstanding here and you think this
> provides entropy to the regular Linux RNG?  It doesn't.  hwrng does
> that, crypto_rng does not.
> 
> The correct fix is to mark CRYPTO_DEV_SUN8I_CE_PRNG as BROKEN or remove
> it entirely.  Doing otherwise is not responsible.

Looking into it a bit more, just removing CRYPTO_DEV_SUN4I_SS_PRNG is
clearly the way to go.  This patch does it:
https://lore.kernel.org/linux-crypto/20260529193648.18172-1-ebiggers@kernel.org

- Eric

^ permalink raw reply

* [PATCH] crypto: sun4i-ss - Remove insecure and unused rng_alg
From: Eric Biggers @ 2026-05-29 19:36 UTC (permalink / raw)
  To: linux-crypto, Herbert Xu
  Cc: linux-sunxi, linux-arm-kernel, linux-kernel, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Corentin Labbe, Eric Biggers,
	stable

Remove sun4i_ss_rng, as it is insecure and unused:

- It has multiple vulnerabilities.  sun4i_ss_prng_seed() is missing
  locking and has a buffer overflow.  sun4i_ss_prng_generate() fails to
  fill the entire buffer with cryptographic random bytes, because it
  rounds the destination length down and also doesn't actually wait for
  the hardware to be ready before pulling bytes from it.

- No user of this code is known.  It's usable only theoretically via the
  "rng" algorithm type of AF_ALG.  But userspace actually just uses the
  actual Linux RNG (/dev/random etc) instead.  And rng_algs don't
  contribute entropy to the actual Linux RNG either.  (This may have
  been confused with hwrng, which does contribute entropy.)

Fixes: b8ae5c7387ad ("crypto: sun4i-ss - support the Security System PRNG")
Cc: stable@vger.kernel.org
Cc: Corentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 arch/arm/configs/sunxi_defconfig              |  1 -
 drivers/crypto/allwinner/Kconfig              |  8 ---
 drivers/crypto/allwinner/sun4i-ss/Makefile    |  1 -
 .../crypto/allwinner/sun4i-ss/sun4i-ss-core.c | 44 ------------
 .../crypto/allwinner/sun4i-ss/sun4i-ss-prng.c | 69 -------------------
 drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h  | 20 ------
 6 files changed, 143 deletions(-)
 delete mode 100644 drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c

diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index a83d29fed175..f4b8d8f7dbef 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -168,11 +168,10 @@ CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_CRYPTO_DEV_SUN4I_SS=y
-CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG=y
 CONFIG_CRYPTO_DEV_SUN8I_CE=y
 CONFIG_CRYPTO_DEV_SUN8I_SS=y
 CONFIG_DMA_CMA=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig
index b8e75210a0e3..06ea0e9fe6f2 100644
--- a/drivers/crypto/allwinner/Kconfig
+++ b/drivers/crypto/allwinner/Kconfig
@@ -22,18 +22,10 @@ config CRYPTO_DEV_SUN4I_SS
 	  and SHA1 and MD5 hash algorithms.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called sun4i-ss.
 
-config CRYPTO_DEV_SUN4I_SS_PRNG
-	bool "Support for Allwinner Security System PRNG"
-	depends on CRYPTO_DEV_SUN4I_SS
-	select CRYPTO_RNG
-	help
-	  Select this option if you want to provide kernel-side support for
-	  the Pseudo-Random Number Generator found in the Security System.
-
 config CRYPTO_DEV_SUN4I_SS_DEBUG
 	bool "Enable sun4i-ss stats"
 	depends on CRYPTO_DEV_SUN4I_SS
 	depends on DEBUG_FS
 	help
diff --git a/drivers/crypto/allwinner/sun4i-ss/Makefile b/drivers/crypto/allwinner/sun4i-ss/Makefile
index c0a2797d3168..06a9ae81f9f8 100644
--- a/drivers/crypto/allwinner/sun4i-ss/Makefile
+++ b/drivers/crypto/allwinner/sun4i-ss/Makefile
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o
 sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o
-sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
index 813c4bc6312a..35ef0930e77f 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c
@@ -211,27 +211,10 @@ static struct sun4i_ss_alg_template ss_algs[] = {
 			.cra_init = sun4i_ss_cipher_init,
 			.cra_exit = sun4i_ss_cipher_exit,
 		}
 	}
 },
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-{
-	.type = CRYPTO_ALG_TYPE_RNG,
-	.alg.rng = {
-		.base = {
-			.cra_name		= "stdrng",
-			.cra_driver_name	= "sun4i_ss_rng",
-			.cra_priority		= 300,
-			.cra_ctxsize		= 0,
-			.cra_module		= THIS_MODULE,
-		},
-		.generate               = sun4i_ss_prng_generate,
-		.seed                   = sun4i_ss_prng_seed,
-		.seedsize               = SS_SEED_LEN / BITS_PER_BYTE,
-	}
-},
-#endif
 };
 
 static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
 {
 	unsigned int i;
@@ -245,18 +228,10 @@ static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
 				   ss_algs[i].alg.crypto.base.cra_driver_name,
 				   ss_algs[i].alg.crypto.base.cra_name,
 				   ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
 				   ss_algs[i].stat_bytes);
 			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
-				   ss_algs[i].alg.rng.base.cra_driver_name,
-				   ss_algs[i].alg.rng.base.cra_name,
-				   ss_algs[i].stat_req, ss_algs[i].stat_bytes);
-			break;
-#endif
 		case CRYPTO_ALG_TYPE_AHASH:
 			seq_printf(seq, "%s %s reqs=%lu\n",
 				   ss_algs[i].alg.hash.halg.base.cra_driver_name,
 				   ss_algs[i].alg.hash.halg.base.cra_name,
 				   ss_algs[i].stat_req);
@@ -471,19 +446,10 @@ static int sun4i_ss_probe(struct platform_device *pdev)
 				dev_err(ss->dev, "Fail to register %s\n",
 					ss_algs[i].alg.hash.halg.base.cra_name);
 				goto error_alg;
 			}
 			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			err = crypto_register_rng(&ss_algs[i].alg.rng);
-			if (err) {
-				dev_err(ss->dev, "Fail to register %s\n",
-					ss_algs[i].alg.rng.base.cra_name);
-			}
-			break;
-#endif
 		}
 	}
 
 	/* Ignore error of debugfs */
 	ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL);
@@ -499,15 +465,10 @@ static int sun4i_ss_probe(struct platform_device *pdev)
 			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
 			break;
 		case CRYPTO_ALG_TYPE_AHASH:
 			crypto_unregister_ahash(&ss_algs[i].alg.hash);
 			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			crypto_unregister_rng(&ss_algs[i].alg.rng);
-			break;
-#endif
 		}
 	}
 error_pm:
 	sun4i_ss_pm_exit(ss);
 	return err;
@@ -524,15 +485,10 @@ static void sun4i_ss_remove(struct platform_device *pdev)
 			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
 			break;
 		case CRYPTO_ALG_TYPE_AHASH:
 			crypto_unregister_ahash(&ss_algs[i].alg.hash);
 			break;
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-		case CRYPTO_ALG_TYPE_RNG:
-			crypto_unregister_rng(&ss_algs[i].alg.rng);
-			break;
-#endif
 		}
 	}
 
 	sun4i_ss_pm_exit(ss);
 }
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
deleted file mode 100644
index 491fcb7b81b4..000000000000
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-prng.c
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-#include "sun4i-ss.h"
-
-int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
-		       unsigned int slen)
-{
-	struct sun4i_ss_alg_template *algt;
-	struct rng_alg *alg = crypto_rng_alg(tfm);
-
-	algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
-	memcpy(algt->ss->seed, seed, slen);
-
-	return 0;
-}
-
-int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
-			   unsigned int slen, u8 *dst, unsigned int dlen)
-{
-	struct sun4i_ss_alg_template *algt;
-	struct rng_alg *alg = crypto_rng_alg(tfm);
-	int i, err;
-	u32 v;
-	u32 *data = (u32 *)dst;
-	const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED;
-	size_t len;
-	struct sun4i_ss_ctx *ss;
-	unsigned int todo = (dlen / 4) * 4;
-
-	algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng);
-	ss = algt->ss;
-
-	err = pm_runtime_resume_and_get(ss->dev);
-	if (err < 0)
-		return err;
-
-	if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN4I_SS_DEBUG)) {
-		algt->stat_req++;
-		algt->stat_bytes += todo;
-	}
-
-	spin_lock_bh(&ss->slock);
-
-	writel(mode, ss->base + SS_CTL);
-
-	while (todo > 0) {
-		/* write the seed */
-		for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++)
-			writel(ss->seed[i], ss->base + SS_KEY0 + i * 4);
-
-		/* Read the random data */
-		len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo);
-		readsl(ss->base + SS_TXFIFO, data, len / 4);
-		data += len / 4;
-		todo -= len;
-
-		/* Update the seed */
-		for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) {
-			v = readl(ss->base + SS_KEY0 + i * 4);
-			ss->seed[i] = v;
-		}
-	}
-
-	writel(0, ss->base + SS_CTL);
-	spin_unlock_bh(&ss->slock);
-
-	pm_runtime_put(ss->dev);
-
-	return 0;
-}
diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
index 6c5d4aa6453c..f7d1c79ac677 100644
--- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
+++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss.h
@@ -29,12 +29,10 @@
 #include <crypto/hash.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/aes.h>
 #include <crypto/internal/des.h>
-#include <crypto/internal/rng.h>
-#include <crypto/rng.h>
 
 #define SS_CTL            0x00
 #define SS_KEY0           0x04
 #define SS_KEY1           0x08
 #define SS_KEY2           0x0C
@@ -60,14 +58,10 @@
 #define SS_RXFIFO         0x200
 #define SS_TXFIFO         0x204
 
 /* SS_CTL configuration values */
 
-/* PRNG generator mode - bit 15 */
-#define SS_PRNG_ONESHOT		(0 << 15)
-#define SS_PRNG_CONTINUE	(1 << 15)
-
 /* IV mode for hash */
 #define SS_IV_ARBITRARY		(1 << 14)
 
 /* SS operation mode - bits 12-13 */
 #define SS_ECB			(0 << 12)
@@ -92,18 +86,14 @@
 #define SS_OP_AES		(0 << 4)
 #define SS_OP_DES		(1 << 4)
 #define SS_OP_3DES		(2 << 4)
 #define SS_OP_SHA1		(3 << 4)
 #define SS_OP_MD5		(4 << 4)
-#define SS_OP_PRNG		(5 << 4)
 
 /* Data end bit - bit 2 */
 #define SS_DATA_END		(1 << 2)
 
-/* PRNG start bit - bit 1 */
-#define SS_PRNG_START		(1 << 1)
-
 /* SS Enable bit - bit 0 */
 #define SS_DISABLED		(0 << 0)
 #define SS_ENABLED		(1 << 0)
 
 /* SS_FCSR configuration values */
@@ -126,13 +116,10 @@
 #define SS_RXFIFO_EMP_INT_PENDING	(1 << 10)
 #define SS_TXFIFO_AVA_INT_PENDING	(1 << 8)
 #define SS_RXFIFO_EMP_INT_ENABLE	(1 << 2)
 #define SS_TXFIFO_AVA_INT_ENABLE	(1 << 0)
 
-#define SS_SEED_LEN 192
-#define SS_DATA_LEN 160
-
 /*
  * struct ss_variant - Describe SS hardware variant
  * @sha1_in_be:		The SHA1 digest is given by SS in BE, and so need to be inverted.
  */
 struct ss_variant {
@@ -149,24 +136,20 @@ struct sun4i_ss_ctx {
 	struct device *dev;
 	struct resource *res;
 	char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
 	char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
 	spinlock_t slock; /* control the use of the device */
-#ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
-	u32 seed[SS_SEED_LEN / BITS_PER_LONG];
-#endif
 	struct dentry *dbgfs_dir;
 	struct dentry *dbgfs_stats;
 };
 
 struct sun4i_ss_alg_template {
 	u32 type;
 	u32 mode;
 	union {
 		struct skcipher_alg crypto;
 		struct ahash_alg hash;
-		struct rng_alg rng;
 	} alg;
 	struct sun4i_ss_ctx *ss;
 	unsigned long stat_req;
 	unsigned long stat_fb;
 	unsigned long stat_bytes;
@@ -229,8 +212,5 @@ int sun4i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			unsigned int keylen);
 int sun4i_ss_des_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			unsigned int keylen);
 int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			 unsigned int keylen);
-int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
-			   unsigned int slen, u8 *dst, unsigned int dlen);
-int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);

base-commit: 49e05bb00f2e8168695f7af4d694c39e1423e8a2
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH v2] crypto: sun4i-ss - clamp PRNG seed length to prevent heap overflow
From: Eric Biggers @ 2026-05-29 17:33 UTC (permalink / raw)
  To: Corentin Labbe
  Cc: Tianchu Chen, herbert, davem, wens, jernej.skrabec, samuel,
	linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <ahnIbpBLyn5z_siT@Red>

On Fri, May 29, 2026 at 07:10:06PM +0200, Corentin Labbe wrote:
> Le Fri, May 29, 2026 at 09:10:57AM -0700, Eric Biggers a écrit :
> > On Fri, May 29, 2026 at 08:08:01AM +0000, Tianchu Chen wrote:
> > > From: Tianchu Chen <flynnnchen@tencent.com>
> > > 
> > > sun4i_ss_prng_seed() copies the user-supplied seed into ss->seed
> > > using the user-provided length with no bounds check. The crypto core
> > > does not enforce slen <= seedsize before calling into the driver, so a
> > > userspace caller via AF_ALG setsockopt(ALG_SET_KEY) can pass up to
> > > sysctl_optmem_max bytes, overflowing the fixed-size buffer and
> > > corrupting adjacent heap memory.
> > > 
> > > Clamp the copy length to the buffer size, matching the approach used by
> > > loongson-rng for oversized seeds.
> > > 
> > > Discovered by Atuin - Automated Vulnerability Discovery Engine.
> > > 
> > > Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> > > ---
> > > v2: Silently clamp oversized seeds with min_t instead of returning
> > >     -EINVAL (Herbert Xu).
> > 
> > sun4i-ss-prng.c is useless, is still broken, and should just be deleted.
> 
> Hello
> 
> useless ? clearly no, it helped a lot on devices where it is.

The only way this code is reachable is via "rng" algorithm type in
AF_ALG, which is almost never used.  Everyone just uses the regular
Linux RNG (/dev/random etc) instead, as they should.

In fact, anyone were to accidentally use this it would be a security
vulnerability, seeing as sun4i_ss_prng_generate() doesn't actually fill
in all the bytes that were requested.  It also doesn't wait for the FIFO
to be ready when reading data from it.

Is it possible that there's a misunderstanding here and you think this
provides entropy to the regular Linux RNG?  It doesn't.  hwrng does
that, crypto_rng does not.

The correct fix is to mark CRYPTO_DEV_SUN8I_CE_PRNG as BROKEN or remove
it entirely.  Doing otherwise is not responsible.

- Eric

^ permalink raw reply

* Re: [PATCH v2] crypto: sun4i-ss - clamp PRNG seed length to prevent heap overflow
From: Corentin Labbe @ 2026-05-29 17:10 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Tianchu Chen, herbert, davem, wens, jernej.skrabec, samuel,
	linux-crypto, linux-arm-kernel, linux-sunxi, linux-kernel
In-Reply-To: <20260529161057.GA2706@sol>

Le Fri, May 29, 2026 at 09:10:57AM -0700, Eric Biggers a écrit :
> On Fri, May 29, 2026 at 08:08:01AM +0000, Tianchu Chen wrote:
> > From: Tianchu Chen <flynnnchen@tencent.com>
> > 
> > sun4i_ss_prng_seed() copies the user-supplied seed into ss->seed
> > using the user-provided length with no bounds check. The crypto core
> > does not enforce slen <= seedsize before calling into the driver, so a
> > userspace caller via AF_ALG setsockopt(ALG_SET_KEY) can pass up to
> > sysctl_optmem_max bytes, overflowing the fixed-size buffer and
> > corrupting adjacent heap memory.
> > 
> > Clamp the copy length to the buffer size, matching the approach used by
> > loongson-rng for oversized seeds.
> > 
> > Discovered by Atuin - Automated Vulnerability Discovery Engine.
> > 
> > Fixes: 6298e948215f ("crypto: sunxi-ss - Add Allwinner Security System crypto accelerator")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
> > ---
> > v2: Silently clamp oversized seeds with min_t instead of returning
> >     -EINVAL (Herbert Xu).
> 
> sun4i-ss-prng.c is useless, is still broken, and should just be deleted.

Hello

useless ? clearly no, it helped a lot on devices where it is.

Regards

^ permalink raw reply

* Re: [PATCH 05/29] crypto: talitos - Prepare crypto implementation file splitting
From: David Laight @ 2026-05-29 16:24 UTC (permalink / raw)
  To: Christophe Leroy (CS GROUP)
  Cc: Paul Louvel, Herbert Xu, David S. Miller, Thomas Petazzoni,
	Herve Codina, linux-crypto, linux-kernel
In-Reply-To: <22245899-e046-41f1-8707-94f172b310e9@kernel.org>

On Fri, 29 May 2026 15:21:39 +0200
"Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:

> Hi Paul,
> 
> Le 28/05/2026 à 11:08, Paul Louvel a écrit :
> > Remove the static qualifier on multiple function that will be called
> > inside each crypto implementation file.
> > Add them to the main driver header file.  
> 
> I didn't have time to look at the generated text yet but I'm a bit 
> sceptic with this change, or more than the change itself, about its 
> purpose. And even more when I see patches 24 and 25.
> 
> Most functions here are small helpers. To be shared between several C 
> files they deserve becoming static inlines in talitos.h, not global 
> functions.
> 
> Indeed, most of the time is_sec1 is known at build time because in most 
> cases has_ftr_sec1() will constant fold into true or false during build. 
> This is because it is very unlikely that someone build a kernel to run 
> on both MPC 82xx and MPC 83xx at the same time. Therefore it is really 
> unlikely that this in built with both CRYPTO_DEV_TALITOS1 and 
> CRYPTO_DEV_TALITOS2 at the same time.
> 
> I can understand for a function like talitos_submit() but not for 
> functions like to_talitos_ptr() or to_talitos_ptr_ext_set() whose 
> purpose is really to get inlined into the caller.

I also spotted a couple of indirect calls being added.
They will be slower than you might think.
If there are only two options it is better to use an 'if'.

-- David

> 
> Christophe
> 
> 
> > 
> > Add the common structures too.
> > 
> > Signed-off-by: Paul Louvel <paul.louvel@bootlin.com>
> > ---
> >   drivers/crypto/talitos/talitos.c | 123 ++++++++++++++-------------------------
> >   drivers/crypto/talitos/talitos.h |  91 +++++++++++++++++++++++++++++
> >   2 files changed, 135 insertions(+), 79 deletions(-)
> > 
> > diff --git a/drivers/crypto/talitos/talitos.c b/drivers/crypto/talitos/talitos.c
> > index f5feff8f7d3d..3fc1069062da 100644
> > --- a/drivers/crypto/talitos/talitos.c
> > +++ b/drivers/crypto/talitos/talitos.c
> > @@ -40,8 +40,8 @@
> >   
> >   #include "talitos.h"
> >   
> > -static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> > -			   unsigned int len, bool is_sec1)
> > +void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> > +		    unsigned int len, bool is_sec1)
> >   {
> >   	ptr->ptr = cpu_to_be32(lower_32_bits(dma_addr));
> >   	if (is_sec1) {
> > @@ -52,8 +52,8 @@ static void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> >   	}
> >   }
> >   
> > -static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> > -			     struct talitos_ptr *src_ptr, bool is_sec1)
> > +void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> > +		      struct talitos_ptr *src_ptr, bool is_sec1)
> >   {
> >   	dst_ptr->ptr = src_ptr->ptr;
> >   	if (is_sec1) {
> > @@ -64,8 +64,8 @@ static void copy_talitos_ptr(struct talitos_ptr *dst_ptr,
> >   	}
> >   }
> >   
> > -static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
> > -					   bool is_sec1)
> > +unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
> > +				    bool is_sec1)
> >   {
> >   	if (is_sec1)
> >   		return be16_to_cpu(ptr->len1);
> > @@ -73,14 +73,14 @@ static unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr,
> >   		return be16_to_cpu(ptr->len);
> >   }
> >   
> > -static void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
> > -				   bool is_sec1)
> > +void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val,
> > +			    bool is_sec1)
> >   {
> >   	if (!is_sec1)
> >   		ptr->j_extent = val;
> >   }
> >   
> > -static void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
> > +void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1)
> >   {
> >   	if (!is_sec1)
> >   		ptr->j_extent |= val;
> > @@ -102,15 +102,15 @@ static void __map_single_talitos_ptr(struct device *dev,
> >   	to_talitos_ptr(ptr, dma_addr, len, is_sec1);
> >   }
> >   
> > -static void map_single_talitos_ptr(struct device *dev,
> > -				   struct talitos_ptr *ptr,
> > -				   unsigned int len, void *data,
> > -				   enum dma_data_direction dir)
> > +void map_single_talitos_ptr(struct device *dev,
> > +			    struct talitos_ptr *ptr,
> > +			    unsigned int len, void *data,
> > +			    enum dma_data_direction dir)
> >   {
> >   	__map_single_talitos_ptr(dev, ptr, len, data, dir, 0);
> >   }
> >   
> > -static void map_single_talitos_ptr_nosync(struct device *dev,
> > +void map_single_talitos_ptr_nosync(struct device *dev,
> >   					  struct talitos_ptr *ptr,
> >   					  unsigned int len, void *data,
> >   					  enum dma_data_direction dir)
> > @@ -122,9 +122,9 @@ static void map_single_talitos_ptr_nosync(struct device *dev,
> >   /*
> >    * unmap bus single (contiguous) h/w descriptor pointer
> >    */
> > -static void unmap_single_talitos_ptr(struct device *dev,
> > -				     struct talitos_ptr *ptr,
> > -				     enum dma_data_direction dir)
> > +void unmap_single_talitos_ptr(struct device *dev,
> > +			      struct talitos_ptr *ptr,
> > +			      enum dma_data_direction dir)
> >   {
> >   	struct talitos_private *priv = dev_get_drvdata(dev);
> >   	bool is_sec1 = has_ftr_sec1(priv);
> > @@ -303,11 +303,11 @@ static void dma_map_request(struct device *dev, struct talitos_request *request,
> >    * callback must check err and feedback in descriptor header
> >    * for device processing status.
> >    */
> > -static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> > -			  void (*callback)(struct device *dev,
> > -					   struct talitos_desc *desc,
> > -					   void *context, int error),
> > -			  void *context)
> > +int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> > +		   void (*callback)(struct device *dev,
> > +				    struct talitos_desc *desc,
> > +				    void *context, int error),
> > +		   void *context)
> >   {
> >   	struct talitos_private *priv = dev_get_drvdata(dev);
> >   	struct talitos_request *request;
> > @@ -830,24 +830,6 @@ DEF_TALITOS2_INTERRUPT(ch1_3, TALITOS2_ISR_CH_1_3_DONE, TALITOS2_ISR_CH_1_3_ERR,
> >    * HMAC_SNOOP_NO_AFEA (HSNA) instead of type IPSEC_ESP
> >    */
> >   #define TALITOS_CRA_PRIORITY_AEAD_HSNA	(TALITOS_CRA_PRIORITY - 1)
> > -#ifdef CONFIG_CRYPTO_DEV_TALITOS2
> > -#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
> > -#else
> > -#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
> > -#endif
> > -#define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
> > -
> > -struct talitos_ctx {
> > -	struct device *dev;
> > -	int ch;
> > -	__be32 desc_hdr_template;
> > -	u8 key[TALITOS_MAX_KEY_SIZE];
> > -	u8 iv[TALITOS_MAX_IV_LENGTH];
> > -	dma_addr_t dma_key;
> > -	unsigned int keylen;
> > -	unsigned int enckeylen;
> > -	unsigned int authkeylen;
> > -};
> >   
> >   #define HASH_MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
> >   #define TALITOS_MDEU_MAX_CONTEXT_SIZE	TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512
> > @@ -939,7 +921,7 @@ static int aead_des3_setkey(struct crypto_aead *authenc,
> >   	return err;
> >   }
> >   
> > -static void talitos_sg_unmap(struct device *dev,
> > +void talitos_sg_unmap(struct device *dev,
> >   			     struct talitos_edesc *edesc,
> >   			     struct scatterlist *src,
> >   			     struct scatterlist *dst,
> > @@ -1124,7 +1106,7 @@ static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
> >   	return count;
> >   }
> >   
> > -static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
> > +int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
> >   			      unsigned int len, struct talitos_edesc *edesc,
> >   			      struct talitos_ptr *ptr, int sg_count,
> >   			      unsigned int offset, int tbl_off, int elen,
> > @@ -1161,7 +1143,7 @@ static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
> >   	return sg_count;
> >   }
> >   
> > -static int talitos_sg_map(struct device *dev, struct scatterlist *src,
> > +int talitos_sg_map(struct device *dev, struct scatterlist *src,
> >   			  unsigned int len, struct talitos_edesc *edesc,
> >   			  struct talitos_ptr *ptr, int sg_count,
> >   			  unsigned int offset, int tbl_off)
> > @@ -1299,17 +1281,17 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
> >   /*
> >    * allocate and map the extended descriptor
> >    */
> > -static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
> > -						 struct scatterlist *src,
> > -						 struct scatterlist *dst,
> > -						 u8 *iv,
> > -						 unsigned int assoclen,
> > -						 unsigned int cryptlen,
> > -						 unsigned int authsize,
> > -						 unsigned int ivsize,
> > -						 int icv_stashing,
> > -						 u32 cryptoflags,
> > -						 bool encrypt)
> > +struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
> > +					  struct scatterlist *src,
> > +					  struct scatterlist *dst,
> > +					  u8 *iv,
> > +					  unsigned int assoclen,
> > +					  unsigned int cryptlen,
> > +					  unsigned int authsize,
> > +					  unsigned int ivsize,
> > +					  int icv_stashing,
> > +					  u32 cryptoflags,
> > +					  bool encrypt)
> >   {
> >   	struct talitos_edesc *edesc;
> >   	int src_nents, dst_nents, alloc_len, dma_len, src_len, dst_len;
> > @@ -2172,18 +2154,6 @@ static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
> >   	return 0;
> >   }
> >   
> > -
> > -struct talitos_alg_template {
> > -	u32 type;
> > -	u32 priority;
> > -	union {
> > -		struct skcipher_alg skcipher;
> > -		struct ahash_alg hash;
> > -		struct aead_alg aead;
> > -	} alg;
> > -	__be32 desc_hdr_template;
> > -};
> > -
> >   static struct talitos_alg_template driver_algs[] = {
> >   	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
> >   	{	.type = CRYPTO_ALG_TYPE_AEAD,
> > @@ -2998,14 +2968,8 @@ static struct talitos_alg_template driver_algs[] = {
> >   	}
> >   };
> >   
> > -struct talitos_crypto_alg {
> > -	struct list_head entry;
> > -	struct device *dev;
> > -	struct talitos_alg_template algt;
> > -};
> > -
> > -static int talitos_init_common(struct talitos_ctx *ctx,
> > -			       struct talitos_crypto_alg *talitos_alg)
> > +int talitos_init_common(struct talitos_ctx *ctx,
> > +			struct talitos_crypto_alg *talitos_alg)
> >   {
> >   	struct talitos_private *priv;
> >   
> > @@ -3066,7 +3030,7 @@ static int talitos_cra_init_ahash(struct crypto_tfm *tfm)
> >   	return talitos_init_common(ctx, talitos_alg);
> >   }
> >   
> > -static void talitos_cra_exit(struct crypto_tfm *tfm)
> > +void talitos_cra_exit(struct crypto_tfm *tfm)
> >   {
> >   	struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
> >   	struct device *dev = ctx->dev;
> > @@ -3080,7 +3044,7 @@ static void talitos_cra_exit(struct crypto_tfm *tfm)
> >    * type and primary/secondary execution units required match the hw
> >    * capabilities description provided in the device tree node.
> >    */
> > -static int hw_supports(struct device *dev, __be32 desc_hdr_template)
> > +int talitos_hw_supports(struct device *dev, __be32 desc_hdr_template)
> >   {
> >   	struct talitos_private *priv = dev_get_drvdata(dev);
> >   	int ret;
> > @@ -3117,7 +3081,7 @@ static void talitos_remove(struct platform_device *ofdev)
> >   		list_del(&t_alg->entry);
> >   	}
> >   
> > -	if (hw_supports(dev, DESC_HDR_SEL0_RNG))
> > +	if (talitos_hw_supports(dev, DESC_HDR_SEL0_RNG))
> >   		talitos_unregister_rng(dev);
> >   
> >   	for (i = 0; i < 2; i++)
> > @@ -3426,7 +3390,7 @@ static int talitos_probe(struct platform_device *ofdev)
> >   	}
> >   
> >   	/* register the RNG, if available */
> > -	if (hw_supports(dev, DESC_HDR_SEL0_RNG)) {
> > +	if (talitos_hw_supports(dev, DESC_HDR_SEL0_RNG)) {
> >   		err = talitos_register_rng(dev);
> >   		if (err) {
> >   			dev_err(dev, "failed to register hwrng: %d\n", err);
> > @@ -3437,7 +3401,8 @@ static int talitos_probe(struct platform_device *ofdev)
> >   
> >   	/* register crypto algorithms the device supports */
> >   	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
> > -		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
> > +		if (talitos_hw_supports(dev,
> > +					driver_algs[i].desc_hdr_template)) {
> >   			struct talitos_crypto_alg *t_alg;
> >   			struct crypto_alg *alg = NULL;
> >   
> > diff --git a/drivers/crypto/talitos/talitos.h b/drivers/crypto/talitos/talitos.h
> > index fa8c71b1f90f..1f81d336dae8 100644
> > --- a/drivers/crypto/talitos/talitos.h
> > +++ b/drivers/crypto/talitos/talitos.h
> > @@ -5,7 +5,13 @@
> >    * Copyright (c) 2006-2011 Freescale Semiconductor, Inc.
> >    */
> >   
> > +#include <crypto/aes.h>
> > +#include <crypto/internal/aead.h>
> > +#include <crypto/internal/hash.h>
> > +#include <crypto/internal/skcipher.h>
> > +#include <crypto/sha2.h>
> >   #include <linux/device.h>
> > +#include <linux/dma-mapping.h>
> >   #include <linux/hw_random.h>
> >   #include <linux/interrupt.h>
> >   #include <linux/scatterlist.h>
> > @@ -19,6 +25,13 @@
> >   #define PRIMARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 28) & 0xf)
> >   #define SECONDARY_EU(desc_hdr) ((be32_to_cpu(desc_hdr) >> 16) & 0xf)
> >   
> > +#ifdef CONFIG_CRYPTO_DEV_TALITOS2
> > +#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA512_BLOCK_SIZE)
> > +#else
> > +#define TALITOS_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + SHA256_BLOCK_SIZE)
> > +#endif
> > +#define TALITOS_MAX_IV_LENGTH		16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
> > +
> >   /* descriptor pointer entry */
> >   struct talitos_ptr {
> >   	union {
> > @@ -174,6 +187,35 @@ struct talitos_private {
> >   
> >   };
> >   
> > +struct talitos_ctx {
> > +	struct device *dev;
> > +	int ch;
> > +	__be32 desc_hdr_template;
> > +	u8 key[TALITOS_MAX_KEY_SIZE];
> > +	u8 iv[TALITOS_MAX_IV_LENGTH];
> > +	dma_addr_t dma_key;
> > +	unsigned int keylen;
> > +	unsigned int enckeylen;
> > +	unsigned int authkeylen;
> > +};
> > +
> > +struct talitos_alg_template {
> > +	u32 type;
> > +	u32 priority;
> > +	union {
> > +		struct skcipher_alg skcipher;
> > +		struct ahash_alg hash;
> > +		struct aead_alg aead;
> > +	} alg;
> > +	__be32 desc_hdr_template;
> > +};
> > +
> > +struct talitos_crypto_alg {
> > +	struct list_head entry;
> > +	struct device *dev;
> > +	struct talitos_alg_template algt;
> > +};
> > +
> >   /* .features flag */
> >   #define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
> >   #define TALITOS_FTR_HW_AUTH_CHECK 0x00000002
> > @@ -432,6 +474,55 @@ static inline bool has_ftr_sec1(struct talitos_private *priv)
> >   #define DESC_PTR_LNKTBL_RET			0x02
> >   #define DESC_PTR_LNKTBL_NEXT			0x01
> >   
> > +void to_talitos_ptr(struct talitos_ptr *ptr, dma_addr_t dma_addr,
> > +		    unsigned int len, bool is_sec1);
> > +void copy_talitos_ptr(struct talitos_ptr *dst_ptr, struct talitos_ptr *src_ptr,
> > +		      bool is_sec1);
> > +unsigned short from_talitos_ptr_len(struct talitos_ptr *ptr, bool is_sec1);
> > +void to_talitos_ptr_ext_set(struct talitos_ptr *ptr, u8 val, bool is_sec1);
> > +void to_talitos_ptr_ext_or(struct talitos_ptr *ptr, u8 val, bool is_sec1);
> > +
> > +void map_single_talitos_ptr(struct device *dev, struct talitos_ptr *ptr,
> > +			    unsigned int len, void *data,
> > +			    enum dma_data_direction dir);
> > +void map_single_talitos_ptr_nosync(struct device *dev, struct talitos_ptr *ptr,
> > +				   unsigned int len, void *data,
> > +				   enum dma_data_direction dir);
> > +void unmap_single_talitos_ptr(struct device *dev, struct talitos_ptr *ptr,
> > +			      enum dma_data_direction dir);
> > +
> > +int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
> > +		   void (*callback)(struct device *dev,
> > +				    struct talitos_desc *desc, void *context,
> > +				    int error),
> > +		   void *context);
> > +
> > +void talitos_sg_unmap(struct device *dev, struct talitos_edesc *edesc,
> > +		      struct scatterlist *src, struct scatterlist *dst,
> > +		      unsigned int len, unsigned int offset);
> > +int talitos_sg_map_ext(struct device *dev, struct scatterlist *src,
> > +		       unsigned int len, struct talitos_edesc *edesc,
> > +		       struct talitos_ptr *ptr, int sg_count,
> > +		       unsigned int offset, int tbl_off, int elen, bool force,
> > +		       int align);
> > +int talitos_sg_map(struct device *dev, struct scatterlist *src,
> > +		   unsigned int len, struct talitos_edesc *edesc,
> > +		   struct talitos_ptr *ptr, int sg_count, unsigned int offset,
> > +		   int tbl_off);
> > +
> > +struct talitos_edesc *
> > +talitos_edesc_alloc(struct device *dev, struct scatterlist *src,
> > +		    struct scatterlist *dst, u8 *iv, unsigned int assoclen,
> > +		    unsigned int cryptlen, unsigned int authsize,
> > +		    unsigned int ivsize, int icv_stashing, u32 cryptoflags,
> > +		    bool encrypt);
> > +
> > +int talitos_hw_supports(struct device *dev, __be32 desc_hdr_template);
> > +
> > +int talitos_init_common(struct talitos_ctx *ctx,
> > +			struct talitos_crypto_alg *talitos_alg);
> > +void talitos_cra_exit(struct crypto_tfm *tfm);
> > +
> >   /* Hardware RNG */
> >   
> >   int talitos_register_rng(struct device *dev);
> >   
> 
> 


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox