[PATCH 9/9] crypto: allwinner: add sun8i-ce hash driver
Simon Glass
sjg at chromium.org
Thu Jul 2 22:04:36 CEST 2026
Hi James,
On 2026-07-02T01:46:51, James Hilliard <james.hilliard1 at gmail.com> wrote:
> crypto: allwinner: add sun8i-ce hash driver
>
> The Allwinner sun8i Crypto Engine includes hardware hash methods. Add a
> UCLASS_HASH child for the sun8i-ce parent so FIT hash verification can use
> the accelerator from U-Boot proper and SPL.
>
> Support MD5, SHA1, SHA256, SHA384 and SHA512 using the CE one-shot task
> interface. Build the final hash padding in the driver and bounce
> cache-unaligned input so FIT data with short or unaligned tails can be
> hashed directly.
>
> H6 and H616 use bit-sized hash task lengths. In SPL, only advertise hash
> algorithms selected for that phase so SRAM-constrained builds do not accept
> wider algorithms unless requested.
>
> Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
>
> drivers/crypto/allwinner/sun8i-ce/Kconfig | 26 ++
> drivers/crypto/allwinner/sun8i-ce/Makefile | 1 +
> drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 11 +
> drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c | 300 ++++++++++++++++++++++
> drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h | 7 +
> 5 files changed, 345 insertions(+)
> diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
> @@ -0,0 +1,300 @@
> + struct sunxi_ce_task *task = &job->task;
> + u32 total_len = src_len + pad_len;
> ...
> + task->t_dlen = ce->variant->hash_t_dlen_in_bits ?
> + total_len * 8 : total_len / sizeof(u32);
Since both H6 and H616 set hash_t_dlen_in_bits, this u32 multiply
overflows for inputs of 512 MiB or more, so t_dlen wraps and the CE
produces a wrong digest with no error. The whole input is submitted as
a single one-shot task, unlike the AES driver which chunks at 128 KiB,
so nothing else limits the size. Please can you reject over-limit
lengths in sunxi_hash_digest() with -EINVAL so this fails cleanly?
> diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
> @@ -0,0 +1,300 @@
> + if (src_len && !IS_ALIGNED((ulong)ibuf, ARCH_DMA_MINALIGN)) {
> + src_buf = memalign(ARCH_DMA_MINALIGN,
> + ALIGN(src_len, ARCH_DMA_MINALIGN));
This bounces the entire input in one allocation, so an unaligned FIT
image of a few MiB needs an equally large bounce buffer, which may
well fail in SPL where the heap is small. Since the source mapping is
DMA_TO_DEVICE and only flushes the cache, a misaligned start is not
destructive; my understanding is the hardware only needs word
alignment (the H616 word-addressed descriptors imply 4-byte
alignment). Could the bounce be limited to buffers that are not 4-byte
aligned, with the flush rounded outwards as sunxi_ce_flush() already
does? What do you think?
> diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c
> @@ -0,0 +1,300 @@
> + ret = sunxi_hash_digest(dev, algo, ibuf, ilen, obuf);
> + if (!ret && chunk_sz)
> + schedule();
The point of hash_digest_wd() is to keep the watchdog fed while a long
hash runs, but here schedule() is only called after the operation has
completed, which does not help. The wait loops in sunxi_ce_run_task()
use readl_poll_timeout() with a 3-second timeout and never call
schedule(), so a slow hash of a large image could trigger the
watchdog. I suggest feeding the watchdog inside the core polling loop
(e.g. readl_poll_sleep_timeout() with a schedule() call, or an
explicit loop) and dropping the call here.
Regards,
Simon
More information about the U-Boot
mailing list