[PATCH 4/9] spl: fit: support encrypted payloads

Simon Glass sjg at chromium.org
Thu Jul 2 22:02:59 CEST 2026


Hi James,

On 2026-07-02T01:46:51, James Hilliard <james.hilliard1 at gmail.com> wrote:
> spl: fit: support encrypted payloads
>
> Add SPL_FIT_CIPHER and decrypt FIT image data before post-processing,
> decompression or moving it to the final load address.
>
> SPL cannot always allocate a new output buffer while loading FIT images, so
> use the caller-provided decrypt-to-buffer helper. External encrypted images
> are read into scratch memory first, then decrypted either in-place for
> compressed payloads or into a non-overlapping buffer for direct loads.
> Embedded encrypted images decrypt into the final load buffer or a scratch
> buffer when decompression is still required.
>
> Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
>
> boot/Kconfig         |  9 +++++
>  boot/image-fit.c     |  2 +-
>  common/spl/spl_fit.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++----
>  3 files changed, 96 insertions(+), 7 deletions(-)

> diff --git a/boot/Kconfig b/boot/Kconfig
> @@ -155,6 +155,15 @@ config FIT_CIPHER
> +config SPL_FIT_CIPHER
> +     bool "Enable ciphering data in SPL FIT images"
> +     depends on SPL_LOAD_FIT
> +     depends on SPL_DM_AES
> +     select SPL_FIT

The 'select SPL_FIT' looks redundant, since SPL_LOAD_FIT already selects it.

> diff --git a/boot/image-fit.c b/boot/image-fit.c
> @@ -2290,7 +2290,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
> -     if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) {
> +     if (!tools_build() && IMAGE_ENABLE_DECRYPT) {

This bit is not mentioned in the commit message and does two things:
it makes the check phase-aware (IMAGE_ENABLE_DECRYPT is
CONFIG_IS_ENABLED(FIT_CIPHER), so SPL now uses SPL_FIT_CIPHER here)
and it disables the path for tools builds, where the old condition was
true with CONFIG_FIT_CIPHER but image_aes_decrypt() is a no-op that
leaves buf unset. Please can you explain both in the commit message,
particularly the tools-build behaviour change? Normally we want the tools
to have all available functionality.

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -331,10 +383,38 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
> +             } else if (external_data) {
> +                     if (spl_fit_ranges_overlap((ulong)load_ptr, length,
> +                                                (ulong)src, length))
> +                             decrypt_ptr = map_sysmem(ALIGN((ulong)src + length,
> +                                                            ARCH_DMA_MINALIGN),
> +                                                      length);

This writes the decrypted image just past the buffer that was read,
with no check on what lives there - it could be the FIT itself or
another image, depending on the memory layout. Since the compressed
path already relies on in-place decryption (decrypt_ptr = src), you
could decrypt in place here too and let the existing memmove() handle
the overlapping copy, avoiding the out-of-buffer write and letting you
drop spl_fit_ranges_overlap() entirely. If decrypting directly to
load_ptr matters for DMA performance, please at least add a comment
explaining the assumption that the memory after the buffer is free.
What do you think?

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -331,10 +383,38 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
> +             } else {
> +                     decrypt_ptr = load_ptr;
> +             }
> +
> +             ret = spl_fit_image_decrypt(fit, node, cipher_node, &src, &length,
> +                                         decrypt_ptr);

When the image is decrypted straight into load_ptr (this branch and
the non-overlapping external case), src becomes load_ptr, so the
memmove() at the end copies the image onto itself - U-Boot's memmove()
does not short-circuit dest == src. That is an extra full-image copy
on every encrypted uncompressed load, the main use case here. Perhaps
skip the memmove() when src == load_ptr ?

Regards,
Simon


More information about the U-Boot mailing list