[PATCH v2 04/10] spl: fit: support encrypted payloads

Simon Glass sjg at chromium.org
Thu Jul 9 20:37:22 CEST 2026


Hi James,

On 2026-07-03T01:49:45, 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 in place before
> the existing copy or decompression path consumes them. Embedded encrypted
> images decrypt into the final load buffer, or into scratch memory when
> decompression is still required.
>
> Use IMAGE_ENABLE_DECRYPT in the common FIT image-load path so FIT cipher
> support is selected by phase. Keep that path disabled for host tools,
> since the target-side decrypt helper depends on the U-Boot control FDT
> and runtime crypto providers.
>
> Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
>
> boot/Kconfig         |  8 +++++++
>  boot/image-fit.c     |  2 +-
>  common/spl/spl_fit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------
>  3 files changed, 70 insertions(+), 8 deletions(-)

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -256,6 +281,8 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
>       if (spl_decompression_enabled()) {
>               fit_image_get_comp(fit, node, &image_comp);
>               debug("%s ", genimg_get_comp_name(image_comp));
> +             needs_decomp = image_comp == IH_COMP_GZIP ||
> +                            image_comp == IH_COMP_LZMA;
>       }

This also drives buffer selection for the encrypted path. If someone
later adds a new compression type here (say IH_COMP_LZ4) they will
have to remember to update this test too, otherwise decrypt lands in
the load buffer and decomp then overwrites it. Please extract a small
helper like spl_image_needs_decomp(image_comp) so both sites stay in
sync.

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -267,6 +294,10 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
>               load_addr = image_info->load_addr;
>       }
>
> +     if (CONFIG_IS_ENABLED(FIT_CIPHER))
> +             cipher_node = fdt_subnode_offset(fit, node, FIT_CIPHER_NODENAME);
> +     encrypted = cipher_node >= 0;

If SPL_FIT_CIPHER is not enabled but the FIT actually carries a cipher
subnode, this silently treats the ciphertext as plaintext and hands it
to the copy/decompress path - the hash check passes (FIT hashes are
over the ciphertext) and SPL then hands garbage to U-Boot proper.
Should we have a message in that case, or can we assume that
SPL_FIT_CIPHER must be enabled whenever we encounter a FIT that might
have ciphertext?

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

For external_data the answer is always 'decrypt_ptr = src' regardless
of needs_decomp, so this can flatten to:

    if (external_data)
        decrypt_ptr = src;
    else if (needs_decomp)
        decrypt_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR,
                                       ARCH_DMA_MINALIGN), length);
    else
        decrypt_ptr = load_ptr;

That also makes the intent easier to match against the "read into
scratch, decrypt in place" wording in the commit message.

> diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
> @@ -352,7 +406,7 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
>                       return -EIO;
>               }
>               length = loadEnd - CONFIG_SYS_LOAD_ADDR;
> -     } else {
> +     } else if (src != load_ptr) {
>               memmove(load_ptr, src, length);
>       }

Please add a one-line comment noting that 'src == load_ptr' only
happens when we decrypted straight into the load buffer, so the next
reader doesn't start 'fixing' the else-branch.

Regards,
Simon


More information about the U-Boot mailing list