[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