[PATCH] drivers: crypto: fsl: rng: Reinitialize job ring descriptor for each iteration

Anthony Pighin (Nokia) anthony.pighin at nokia.com
Mon Jul 14 20:01:28 CEST 2025


u-boot internals were being corrupted following an EFI callback to
get_rng(). One of the many footprints was a corruption of the EFI
protocols linked list.

A request for >16 bytes of random data is broken into smaller requests.
Those requests are fed in a loop to the CAAM RNG, which uses a job
queue ring for interaction.

However, the job queue descriptor is created only at probe time. That 
descriptor may end up needing an endian swap (LS1046A) before being fed
to the CAAM RNG. This corrupts the descriptor for the next iteration,
since it will be blindly endian swapped yet again.

Two issues arise. The number of words to endian swap is taken from the
input descriptor itself. So on the second iteration, the length has been
corrupted. This results in a corruption past the end of the descriptor:
whatever is after in memory is endian swapped too. Second, some of the
entries in the descriptor are DMA addresses. If the descriptor is still
somehow considered valid after swapping, the data at the corrupted DMA
address is now trampled.

Linux properly initializes the descriptor for each iteration. This is
what is now done with this commit.

Signed-off-by: Anthony Pighin <anthony.pighin at nokia.com>
---
 drivers/crypto/fsl/rng.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/fsl/rng.c b/drivers/crypto/fsl/rng.c
index 786a710f5fb..85544f931cb 100644
--- a/drivers/crypto/fsl/rng.c
+++ b/drivers/crypto/fsl/rng.c
@@ -23,11 +23,24 @@ struct caam_rng_priv {
        u8 data[CAAM_RNG_MAX_FIFO_STORE_SIZE] __aligned(ARCH_DMA_MINALIGN);
 };

+static int caam_init_desc(struct caam_rng_priv *priv)
+{
+       ulong size = ALIGN(CAAM_RNG_DESC_LEN, ARCH_DMA_MINALIGN);
+
+       inline_cnstr_jobdesc_rng(priv->desc, priv->data,
+                                CAAM_RNG_MAX_FIFO_STORE_SIZE);
+       flush_dcache_range((unsigned long)priv->desc,
+                          (unsigned long)priv->desc + size);
+
+       return 0;
+}
+
 static int caam_rng_read_one(struct caam_rng_priv *priv)
 {
        int size = ALIGN(CAAM_RNG_MAX_FIFO_STORE_SIZE, ARCH_DMA_MINALIGN);
        int ret;

+       caam_init_desc(priv);
        ret = run_descriptor_jr(priv->desc);
        if (ret < 0)
                return -EIO;
@@ -63,12 +76,8 @@ static int caam_rng_read(struct udevice *dev, void *data, size_t len)
 static int caam_rng_probe(struct udevice *dev)
 {
        struct caam_rng_priv *priv = dev_get_priv(dev);
-       ulong size = ALIGN(CAAM_RNG_DESC_LEN, ARCH_DMA_MINALIGN);

-       inline_cnstr_jobdesc_rng(priv->desc, priv->data,
-                                CAAM_RNG_MAX_FIFO_STORE_SIZE);
-       flush_dcache_range((unsigned long)priv->desc,
-                          (unsigned long)priv->desc + size);
+       caam_init_desc(priv);

        return 0;
 }
--
2.43.0



More information about the U-Boot mailing list