[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