* [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data
2026-04-22 21:09 [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Lothar Rubusch
@ 2026-04-22 21:09 ` Lothar Rubusch
2026-04-23 7:43 ` Ard Biesheuvel
2026-04-22 21:09 ` [PATCH v3 2/3] crypto: atmel-sha204a - fix truncated 32-byte blocking read Lothar Rubusch
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Lothar Rubusch @ 2026-04-22 21:09 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
The driver allocated memory for work_data in the non-blocking read
path but never free'd it again. After first read-out the memory pointer
seemed to be recycled and never was allocated again, due to some errors
in the logic, so that the leak was not growing.
Add kfree(work_data) in the completion callback on error. then add
kfree(work_data) after the data is consumed in the subsequent read
call. Finally ensure atomic_dec() is called only after the data has
been consumed or an error occurred to prevent race conditions.
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
drivers/crypto/atmel-sha204a.c | 43 ++++++++++++++++++++--------------
1 file changed, 26 insertions(+), 17 deletions(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index dbb39ed0cea1..19720bdd446d 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -25,13 +25,17 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;
struct hwrng *rng = areq;
- if (status)
+ if (status) {
dev_warn_ratelimited(&i2c_priv->client->dev,
"i2c transaction failed (%d)\n",
status);
+ kfree(work_data);
+ rng->priv = 0;
+ atomic_dec(&i2c_priv->tfm_count);
+ return;
+ }
rng->priv = (unsigned long)work_data;
- atomic_dec(&i2c_priv->tfm_count);
}
static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
@@ -42,31 +46,36 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
- /* keep maximum 1 asynchronous read in flight at any time */
- if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1))
- return 0;
-
+ /* Verify if data available from last run */
if (rng->priv) {
work_data = (struct atmel_i2c_work_data *)rng->priv;
max = min(sizeof(work_data->cmd.data), max);
memcpy(data, &work_data->cmd.data, max);
- rng->priv = 0;
- } else {
- work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
- if (!work_data) {
- atomic_dec(&i2c_priv->tfm_count);
- return -ENOMEM;
- }
- work_data->ctx = i2c_priv;
- work_data->client = i2c_priv->client;
- max = 0;
+ /* Now, free memory */
+ kfree(work_data);
+ rng->priv = 0;
+ atomic_dec(&i2c_priv->tfm_count);
+ return max;
}
+ /* When a request is still in-flight but not processed */
+ if (atomic_read(&i2c_priv->tfm_count) > 0)
+ return 0;
+
+ /* Start a new request */
+ work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
+ if (!work_data)
+ return -ENOMEM;
+
+ atomic_inc(&i2c_priv->tfm_count);
+ work_data->ctx = i2c_priv;
+ work_data->client = i2c_priv->client;
+
atmel_i2c_init_random_cmd(&work_data->cmd);
atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng);
- return max;
+ return 0;
}
static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data
2026-04-22 21:09 ` [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data Lothar Rubusch
@ 2026-04-23 7:43 ` Ard Biesheuvel
0 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2026-04-23 7:43 UTC (permalink / raw)
To: Lothar Rubusch, Herbert Xu, Thorsten Blum, davem, nicolas.ferre,
alexandre.belloni, claudiu.beznea, Linus Walleij
Cc: linux-crypto, linux-arm-kernel, linux-kernel
Hi Lothar,
On Wed, 22 Apr 2026, at 23:09, Lothar Rubusch wrote:
> The driver allocated memory for work_data in the non-blocking read
> path but never free'd it again. After first read-out the memory pointer
> seemed to be recycled and never was allocated again, due to some errors
> in the logic, so that the leak was not growing.
>
Why can't we just reuse the work_data, instead of alloc/freeing it every time?
> Add kfree(work_data) in the completion callback on error. then add
> kfree(work_data) after the data is consumed in the subsequent read
> call. Finally ensure atomic_dec() is called only after the data has
> been consumed or an error occurred to prevent race conditions.
>
> Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A
> random number generator")
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> drivers/crypto/atmel-sha204a.c | 43 ++++++++++++++++++++--------------
> 1 file changed, 26 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/crypto/atmel-sha204a.c
> b/drivers/crypto/atmel-sha204a.c
> index dbb39ed0cea1..19720bdd446d 100644
> --- a/drivers/crypto/atmel-sha204a.c
> +++ b/drivers/crypto/atmel-sha204a.c
> @@ -25,13 +25,17 @@ static void atmel_sha204a_rng_done(struct
> atmel_i2c_work_data *work_data,
> struct atmel_i2c_client_priv *i2c_priv = work_data->ctx;
> struct hwrng *rng = areq;
>
> - if (status)
> + if (status) {
> dev_warn_ratelimited(&i2c_priv->client->dev,
> "i2c transaction failed (%d)\n",
> status);
> + kfree(work_data);
> + rng->priv = 0;
> + atomic_dec(&i2c_priv->tfm_count);
> + return;
> + }
>
> rng->priv = (unsigned long)work_data;
> - atomic_dec(&i2c_priv->tfm_count);
> }
>
> static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void
> *data,
> @@ -42,31 +46,36 @@ static int
> atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
>
> i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
>
> - /* keep maximum 1 asynchronous read in flight at any time */
> - if (!atomic_add_unless(&i2c_priv->tfm_count, 1, 1))
> - return 0;
> -
> + /* Verify if data available from last run */
> if (rng->priv) {
> work_data = (struct atmel_i2c_work_data *)rng->priv;
> max = min(sizeof(work_data->cmd.data), max);
> memcpy(data, &work_data->cmd.data, max);
> - rng->priv = 0;
> - } else {
> - work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
> - if (!work_data) {
> - atomic_dec(&i2c_priv->tfm_count);
> - return -ENOMEM;
> - }
> - work_data->ctx = i2c_priv;
> - work_data->client = i2c_priv->client;
>
> - max = 0;
> + /* Now, free memory */
> + kfree(work_data);
> + rng->priv = 0;
> + atomic_dec(&i2c_priv->tfm_count);
> + return max;
> }
>
> + /* When a request is still in-flight but not processed */
> + if (atomic_read(&i2c_priv->tfm_count) > 0)
> + return 0;
> +
> + /* Start a new request */
> + work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
> + if (!work_data)
> + return -ENOMEM;
> +
> + atomic_inc(&i2c_priv->tfm_count);
> + work_data->ctx = i2c_priv;
> + work_data->client = i2c_priv->client;
> +
> atmel_i2c_init_random_cmd(&work_data->cmd);
> atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng);
>
> - return max;
> + return 0;
> }
>
> static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
> --
> 2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 2/3] crypto: atmel-sha204a - fix truncated 32-byte blocking read
2026-04-22 21:09 [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Lothar Rubusch
2026-04-22 21:09 ` [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data Lothar Rubusch
@ 2026-04-22 21:09 ` Lothar Rubusch
2026-04-23 7:55 ` Ard Biesheuvel
2026-04-22 21:09 ` [PATCH v3 3/3] crypto: atmel-sha204a - fix non-blocking read logic Lothar Rubusch
2026-04-23 9:25 ` [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Ard Biesheuvel
3 siblings, 1 reply; 8+ messages in thread
From: Lothar Rubusch @ 2026-04-22 21:09 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
The ATSHA204A returns a 35-byte packet consisting of a 1-byte count,
32 bytes of entropy, and a 2-byte CRC. The current blocking read
implementation was incorrectly copying data starting from the
count byte, leading to offset data and truncated entropy.
Additionally, the chip requires significant execution time to
generate random numbers, going by the datasheet. Reading the I2C bus
too early results in the chip NACK-ing or returning a partial buffer
followed by zeros.
Verification:
Tests before showed repeadetly reading only 8 bytes of entropy:
$ head -c 32 /dev/hwrng | hexdump -C
00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020
After this patch applied, the result will be as follows:
$ head -c 32 /dev/hwrng | hexdump -C
00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i|
00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.|
00000020
Fix these issues by:
Increase cmd.msecs to 30ms to provide sufficient execution time. Then
set cmd.rxsize to RANDOM_RSP_SIZE (35 bytes) to capture the entire
hardware response. Eventually, correct the memcpy() offset to index 1 of
the data buffer to skip the count byte and retrieve exactly 32 bytes of
entropy.
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
drivers/crypto/atmel-sha204a.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index 19720bdd446d..f7dc00d0f4cd 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -19,6 +19,9 @@
#include <linux/workqueue.h>
#include "atmel-i2c.h"
+#define ATMEL_RNG_BLOCK_SIZE 32
+#define ATMEL_RNG_EXEC_TIME 30
+
static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
void *areq, int status)
{
@@ -91,13 +94,15 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,
i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
atmel_i2c_init_random_cmd(&cmd);
+ cmd.msecs = ATMEL_RNG_EXEC_TIME;
+ cmd.rxsize = RANDOM_RSP_SIZE;
ret = atmel_i2c_send_receive(i2c_priv->client, &cmd);
if (ret)
return ret;
- max = min(sizeof(cmd.data), max);
- memcpy(data, cmd.data, max);
+ max = min_t(size_t, ATMEL_RNG_BLOCK_SIZE, max);
+ memcpy(data, &cmd.data[1], max);
return max;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 2/3] crypto: atmel-sha204a - fix truncated 32-byte blocking read
2026-04-22 21:09 ` [PATCH v3 2/3] crypto: atmel-sha204a - fix truncated 32-byte blocking read Lothar Rubusch
@ 2026-04-23 7:55 ` Ard Biesheuvel
0 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2026-04-23 7:55 UTC (permalink / raw)
To: Lothar Rubusch, Herbert Xu, Thorsten Blum, davem, nicolas.ferre,
alexandre.belloni, claudiu.beznea, Linus Walleij
Cc: linux-crypto, linux-arm-kernel, linux-kernel
On Wed, 22 Apr 2026, at 23:09, Lothar Rubusch wrote:
> The ATSHA204A returns a 35-byte packet consisting of a 1-byte count,
> 32 bytes of entropy, and a 2-byte CRC. The current blocking read
> implementation was incorrectly copying data starting from the
> count byte, leading to offset data and truncated entropy.
>
> Additionally, the chip requires significant execution time to
> generate random numbers, going by the datasheet. Reading the I2C bus
> too early results in the chip NACK-ing or returning a partial buffer
> followed by zeros.
>
> Verification:
> Tests before showed repeadetly reading only 8 bytes of entropy:
> $ head -c 32 /dev/hwrng | hexdump -C
> 00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........|
> 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00000020
>
> After this patch applied, the result will be as follows:
> $ head -c 32 /dev/hwrng | hexdump -C
> 00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i|
> 00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.|
> 00000020
>
> Fix these issues by:
> Increase cmd.msecs to 30ms to provide sufficient execution time. Then
> set cmd.rxsize to RANDOM_RSP_SIZE (35 bytes) to capture the entire
> hardware response. Eventually, correct the memcpy() offset to index 1 of
> the data buffer to skip the count byte and retrieve exactly 32 bytes of
> entropy.
>
> Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A
> random number generator")
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> drivers/crypto/atmel-sha204a.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
> index 19720bdd446d..f7dc00d0f4cd 100644
> --- a/drivers/crypto/atmel-sha204a.c
> +++ b/drivers/crypto/atmel-sha204a.c
> @@ -19,6 +19,9 @@
> #include <linux/workqueue.h>
> #include "atmel-i2c.h"
>
> +#define ATMEL_RNG_BLOCK_SIZE 32
> +#define ATMEL_RNG_EXEC_TIME 30
> +
> static void atmel_sha204a_rng_done(struct atmel_i2c_work_data
> *work_data,
> void *areq, int status)
> {
> @@ -91,13 +94,15 @@ static int atmel_sha204a_rng_read(struct hwrng
> *rng, void *data, size_t max,
> i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
>
> atmel_i2c_init_random_cmd(&cmd);
> + cmd.msecs = ATMEL_RNG_EXEC_TIME;
> + cmd.rxsize = RANDOM_RSP_SIZE;
>
Please fix atmel_i2c_init_random_cmd() instead if it doesn't set the right
values for these fields. But afaict, you are decreasing the execution time
here, so I struggle to see how this could explain the improved behavior.
> ret = atmel_i2c_send_receive(i2c_priv->client, &cmd);
> if (ret)
> return ret;
>
> - max = min(sizeof(cmd.data), max);
> - memcpy(data, cmd.data, max);
> + max = min_t(size_t, ATMEL_RNG_BLOCK_SIZE, max);
> + memcpy(data, &cmd.data[1], max);
>
This looks correct - better to put this in a separate patch.
> return max;
> }
> --
> 2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 3/3] crypto: atmel-sha204a - fix non-blocking read logic
2026-04-22 21:09 [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Lothar Rubusch
2026-04-22 21:09 ` [PATCH v3 1/3] crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data Lothar Rubusch
2026-04-22 21:09 ` [PATCH v3 2/3] crypto: atmel-sha204a - fix truncated 32-byte blocking read Lothar Rubusch
@ 2026-04-22 21:09 ` Lothar Rubusch
2026-04-23 7:56 ` Ard Biesheuvel
2026-04-23 9:25 ` [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Ard Biesheuvel
3 siblings, 1 reply; 8+ messages in thread
From: Lothar Rubusch @ 2026-04-22 21:09 UTC (permalink / raw)
To: herbert, thorsten.blum, davem, nicolas.ferre, alexandre.belloni,
claudiu.beznea, ardb, linusw
Cc: linux-crypto, linux-arm-kernel, linux-kernel, l.rubusch
The non-blocking path was (also) failing to provide valid entropy
due to improper buffer management and a lack of hardware execution
time.
Ensure cmd.msecs (30ms) and cmd.rxsize (35ms) are initialized before
enqueuing the background work. Fix the data offset to skip the
1-byte hardware count header when copying bits to the caller. Correctly
return 0 (busy) to the hwrng core while hardware execution is in
progress, preventing zero-filled buffers, which was the situation
before.
With this fix applied, tests will look similar to this:
$ socat -u OPEN:/dev/hwrng,nonblock - | head -c 32 | hexdump -C
00000000 23 cc 42 3c 90 b1 38 fc 54 37 35 4b 09 c5 e1 0d |#.B<..8.T75K....|
2026/03/23 14:30:18 socat[858] E read(5, 0x55be363000, 8192): Resource temporarily unavailable
00000010 73 3b af d9 02 70 76 bd 2d 59 4b 12 01 ac ae 2b |s;...pv.-YK....+|
00000020
Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
---
drivers/crypto/atmel-sha204a.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/crypto/atmel-sha204a.c b/drivers/crypto/atmel-sha204a.c
index f7dc00d0f4cd..04cbf80c1411 100644
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -33,7 +33,6 @@ static void atmel_sha204a_rng_done(struct atmel_i2c_work_data *work_data,
"i2c transaction failed (%d)\n",
status);
kfree(work_data);
- rng->priv = 0;
atomic_dec(&i2c_priv->tfm_count);
return;
}
@@ -49,20 +48,19 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
- /* Verify if data available from last run */
if (rng->priv) {
work_data = (struct atmel_i2c_work_data *)rng->priv;
- max = min(sizeof(work_data->cmd.data), max);
- memcpy(data, &work_data->cmd.data, max);
+ max = min_t(size_t, ATMEL_RNG_BLOCK_SIZE, max);
+ memcpy(data, &work_data->cmd.data[1], max);
- /* Now, free memory */
+ /* Free memory and clear the in-flight flag */
kfree(work_data);
rng->priv = 0;
atomic_dec(&i2c_priv->tfm_count);
return max;
}
- /* When a request is still in-flight but not processed */
+ /* If a request is still in-flight, return 0 (busy) */
if (atomic_read(&i2c_priv->tfm_count) > 0)
return 0;
@@ -76,8 +74,14 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
work_data->client = i2c_priv->client;
atmel_i2c_init_random_cmd(&work_data->cmd);
+
+ /* Set the execution time for the RNG command (from datasheet) */
+ work_data->cmd.msecs = ATMEL_RNG_EXEC_TIME;
+ work_data->cmd.rxsize = RANDOM_RSP_SIZE;
+
atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng);
+ /* Return 0 to indicate 'busy', data will be ready on next call */
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 3/3] crypto: atmel-sha204a - fix non-blocking read logic
2026-04-22 21:09 ` [PATCH v3 3/3] crypto: atmel-sha204a - fix non-blocking read logic Lothar Rubusch
@ 2026-04-23 7:56 ` Ard Biesheuvel
0 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2026-04-23 7:56 UTC (permalink / raw)
To: Lothar Rubusch, Herbert Xu, Thorsten Blum, davem, nicolas.ferre,
alexandre.belloni, claudiu.beznea, Linus Walleij
Cc: linux-crypto, linux-arm-kernel, linux-kernel
On Wed, 22 Apr 2026, at 23:09, Lothar Rubusch wrote:
> The non-blocking path was (also) failing to provide valid entropy
> due to improper buffer management and a lack of hardware execution
> time.
>
> Ensure cmd.msecs (30ms) and cmd.rxsize (35ms) are initialized before
> enqueuing the background work. Fix the data offset to skip the
> 1-byte hardware count header when copying bits to the caller. Correctly
> return 0 (busy) to the hwrng core while hardware execution is in
> progress, preventing zero-filled buffers, which was the situation
> before.
>
> With this fix applied, tests will look similar to this:
> $ socat -u OPEN:/dev/hwrng,nonblock - | head -c 32 | hexdump -C
> 00000000 23 cc 42 3c 90 b1 38 fc 54 37 35 4b 09 c5 e1 0d
> |#.B<..8.T75K....|
> 2026/03/23 14:30:18 socat[858] E read(5, 0x55be363000, 8192): Resource
> temporarily unavailable
> 00000010 73 3b af d9 02 70 76 bd 2d 59 4b 12 01 ac ae 2b
> |s;...pv.-YK....+|
> 00000020
>
> Fixes: da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A
> random number generator")
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> drivers/crypto/atmel-sha204a.c | 16 ++++++++++------
> 1 file changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/crypto/atmel-sha204a.c
> b/drivers/crypto/atmel-sha204a.c
> index f7dc00d0f4cd..04cbf80c1411 100644
> --- a/drivers/crypto/atmel-sha204a.c
> +++ b/drivers/crypto/atmel-sha204a.c
> @@ -33,7 +33,6 @@ static void atmel_sha204a_rng_done(struct
> atmel_i2c_work_data *work_data,
> "i2c transaction failed (%d)\n",
> status);
> kfree(work_data);
> - rng->priv = 0;
> atomic_dec(&i2c_priv->tfm_count);
> return;
> }
> @@ -49,20 +48,19 @@ static int
> atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,
>
> i2c_priv = container_of(rng, struct atmel_i2c_client_priv, hwrng);
>
> - /* Verify if data available from last run */
> if (rng->priv) {
> work_data = (struct atmel_i2c_work_data *)rng->priv;
> - max = min(sizeof(work_data->cmd.data), max);
> - memcpy(data, &work_data->cmd.data, max);
> + max = min_t(size_t, ATMEL_RNG_BLOCK_SIZE, max);
> + memcpy(data, &work_data->cmd.data[1], max);
>
Please combine this with the buffer size fix in the previous patch.
> - /* Now, free memory */
> + /* Free memory and clear the in-flight flag */
> kfree(work_data);
> rng->priv = 0;
> atomic_dec(&i2c_priv->tfm_count);
> return max;
> }
>
> - /* When a request is still in-flight but not processed */
> + /* If a request is still in-flight, return 0 (busy) */
> if (atomic_read(&i2c_priv->tfm_count) > 0)
> return 0;
>
> @@ -76,8 +74,14 @@ static int atmel_sha204a_rng_read_nonblocking(struct
> hwrng *rng, void *data,
> work_data->client = i2c_priv->client;
>
> atmel_i2c_init_random_cmd(&work_data->cmd);
> +
> + /* Set the execution time for the RNG command (from datasheet) */
> + work_data->cmd.msecs = ATMEL_RNG_EXEC_TIME;
> + work_data->cmd.rxsize = RANDOM_RSP_SIZE;
> +
Again, this is either redundant or wrong.
> atmel_i2c_enqueue(work_data, atmel_sha204a_rng_done, rng);
>
> + /* Return 0 to indicate 'busy', data will be ready on next call */
> return 0;
> }
>
> --
> 2.53.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes
2026-04-22 21:09 [PATCH v3 0/3] crypto: atmel-sha204a - multiple RNG fixes Lothar Rubusch
` (2 preceding siblings ...)
2026-04-22 21:09 ` [PATCH v3 3/3] crypto: atmel-sha204a - fix non-blocking read logic Lothar Rubusch
@ 2026-04-23 9:25 ` Ard Biesheuvel
3 siblings, 0 replies; 8+ messages in thread
From: Ard Biesheuvel @ 2026-04-23 9:25 UTC (permalink / raw)
To: Lothar Rubusch, Herbert Xu, Thorsten Blum, davem, nicolas.ferre,
alexandre.belloni, claudiu.beznea, Linus Walleij
Cc: linux-crypto, linux-arm-kernel, linux-kernel
Hi Lothar,
On Wed, 22 Apr 2026, at 23:09, Lothar Rubusch wrote:
> When testing the RNG functionality on the Atmel SHA204a hardware, I
> found the following issues: rngtest reported failures and hexdump
> reveiled only the first 8 bytes out of 32 provided actually entropy.
>
> Having a closer look into it, I found a (small) memory leak, missing
> to free work_data, miss-reading of the count field into the entropy
> fields and parts of the 32 random bytes staying 0 due to reading the
> slow i2c device.
>
> The series proposes fixes and how fixed functionality can be/was
> verified. Executing rngtest afterward showed a decent result, due
> to the i2c bus a bit slow.
>
> All setups require selecting the Atmel-sha204a as active RNG.
> $ cat /sys/class/misc/hw_random/rng_available
> 3f104000.rng 1-0064 none
>
> $ echo 1-0064 > /sys/class/misc/hw_random/rng_current
>
> $ cat /sys/class/misc/hw_random/rng_current
> 1-0064
>
> Testing RNG properties currently shows problematic results:
> $ rngtest < /dev/hwrng
> rngtest 2.6
> Copyright (c) 2004 by Henrique de Moraes Holschuh
> This is free software; see the source for copying conditions. There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>
> rngtest: starting FIPS tests...
> rngtest: bits received from input: 1040032
> rngtest: FIPS 140-2 successes: 0
> rngtest: FIPS 140-2 failures: 52
> rngtest: FIPS 140-2(2001-10-10) Monobit: 52
> rngtest: FIPS 140-2(2001-10-10) Poker: 52
> rngtest: FIPS 140-2(2001-10-10) Runs: 52
> rngtest: FIPS 140-2(2001-10-10) Long run: 52
> rngtest: FIPS 140-2(2001-10-10) Continuous run: 52
> rngtest: input channel speed: (min=7.631; avg=7.804; max=7.827)Kibits/s
> rngtest: FIPS tests speed: (min=32.273; avg=32.701; max=33.056)Mibits/s
> rngtest: Program run time: 130177956 microseconds
>
> Signed-off-by: Lothar Rubusch <l.rubusch@gmail.com>
> ---
> v2 -> v3: Removal blank line, rebased
> v1 -> v2: Removal of C++ style comment (I saw it too late, sry for that)
> ---
> Lothar Rubusch (3):
> crypto: atmel-sha204a - fix memory leak at non-blocking RNG work_data
> crypto: atmel-sha204a - fix truncated 32-byte blocking read
> crypto: atmel-sha204a - fix non-blocking read logic
>
> drivers/crypto/atmel-sha204a.c | 60 ++++++++++++++++++++++------------
> 1 file changed, 39 insertions(+), 21 deletions(-)
>
Thanks for the report and the fixes. However, I'm not sure you are entirely
on the right track here. I managed to fix the rngtest issues that you report by
making the changes below. As I already replied, I think it would be better to
propose this as a standalone patch, and backport it to stable.
The remaining changes are somewhat debatable IMO: the leak is not really a leak,
so I'd like to understand better what you are fixing here. The command field
changes seems completely misguided (unless I am missing something)
--- a/drivers/crypto/atmel-sha204a.c
+++ b/drivers/crypto/atmel-sha204a.c
@@ -47,8 +47,8 @@
if (rng->priv) {
work_data = (struct atmel_i2c_work_data *)rng->priv;
- max = min(sizeof(work_data->cmd.data), max);
- memcpy(data, &work_data->cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &work_data->cmd.data[1], max);
rng->priv = 0;
} else {
work_data = kmalloc_obj(*work_data, GFP_ATOMIC);
@@ -86,8 +86,8 @@
if (ret)
return ret;
- max = min(sizeof(cmd.data), max);
- memcpy(data, cmd.data, max);
+ max = min(RANDOM_RSP_SIZE - CMD_OVERHEAD_SIZE, max);
+ memcpy(data, &cmd.data[1], max);
return max;
}
^ permalink raw reply [flat|nested] 8+ messages in thread