[PATCH 4/9] spl: fit: support encrypted payloads
James Hilliard
james.hilliard1 at gmail.com
Thu Jul 2 03:46:54 CEST 2026
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
index 8e468c56176..19bbeb9ad36 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -155,6 +155,15 @@ config FIT_CIPHER
Enable the feature of data ciphering/unciphering in the tool mkimage
and in the u-boot support of the FIT image.
+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
+ help
+ Enable unciphering of FIT image data in SPL. This allows SPL to
+ decrypt an encrypted U-Boot proper FIT image through an AES driver.
+
config FIT_VERITY
bool "dm-verity boot parameter generation from FIT metadata"
depends on FIT && OF_LIBFDT
diff --git a/boot/image-fit.c b/boot/image-fit.c
index dac8b35f338..1d1723bdae0 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2290,7 +2290,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
}
/* Decrypt data before uncompress/move */
- if (IS_ENABLED(CONFIG_FIT_CIPHER) && IMAGE_ENABLE_DECRYPT) {
+ if (!tools_build() && IMAGE_ENABLE_DECRYPT) {
puts(" Decrypting Data ... ");
if (fit_image_uncipher(fit, noffset, &buf, &size)) {
puts("Error\n");
diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c
index d89384449b3..57975a7638f 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -16,6 +16,7 @@
#include <sysinfo.h>
#include <asm/global_data.h>
#include <asm/io.h>
+#include <limits.h>
#include <linux/libfdt.h>
#include <linux/printk.h>
@@ -193,6 +194,47 @@ static int get_aligned_image_size(struct spl_load_info *info, int data_size,
return ALIGN(data_size, spl_get_bl_len(info));
}
+static int spl_fit_image_decrypt(const void *fit, int node, int cipher_node,
+ void **data, size_t *size, void *dst)
+{
+ size_t dst_size;
+ int ret;
+
+ puts(" Decrypting Data ... ");
+ ret = fit_image_decrypt_data_to(fit, node, cipher_node, *data, *size,
+ dst, &dst_size);
+ if (ret) {
+ puts("Error\n");
+ return ret;
+ }
+
+ *data = dst;
+ *size = dst_size;
+
+ puts("OK\n");
+
+ return 0;
+}
+
+static bool spl_fit_ranges_overlap(ulong addr1, size_t size1,
+ ulong addr2, size_t size2)
+{
+ ulong end1, end2;
+
+ if (!size1 || !size2)
+ return false;
+
+ end1 = addr1 + size1;
+ if (end1 < addr1)
+ end1 = ULONG_MAX;
+
+ end2 = addr2 + size2;
+ if (end2 < addr2)
+ end2 = ULONG_MAX;
+
+ return addr1 < end2 && addr2 < end1;
+}
+
/**
* load_simple_fit(): load the image described in a certain FIT node
* @info: points to information about the device to load data from
@@ -225,12 +267,15 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
const void *data;
const void *fit = ctx->fit;
bool external_data = false;
+ bool encrypted;
+ bool needs_decomp = false;
+ int cipher_node = -ENOENT;
+ int ret;
log_debug("starting\n");
if (CONFIG_IS_ENABLED(BOOTMETH_VBE) &&
xpl_get_phase(info) != IH_PHASE_NONE) {
enum image_phase_t phase;
- int ret;
ret = fit_image_get_phase(fit, node, &phase);
/* if the image is for any phase, let's use it */
@@ -256,6 +301,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;
}
if (fit_image_get_load(fit, node, &load_addr)) {
@@ -267,6 +314,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 (!fit_image_get_data_position(fit, node, &offset)) {
external_data = true;
} else if (!fit_image_get_data_offset(fit, node, &offset)) {
@@ -291,11 +342,12 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
return 0;
}
- if (spl_decompression_enabled() &&
- (image_comp == IH_COMP_GZIP || image_comp == IH_COMP_LZMA))
- src_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR, ARCH_DMA_MINALIGN), len);
+ if (needs_decomp || encrypted)
+ src_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR,
+ ARCH_DMA_MINALIGN), len);
else
- src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len);
+ src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN),
+ len);
length = len;
overhead = get_aligned_image_overhead(info, offset);
@@ -331,10 +383,38 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
puts("OK\n");
}
+ 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) {
+ if (spl_fit_ranges_overlap((ulong)load_ptr, length,
+ (ulong)src, length))
+ decrypt_ptr = map_sysmem(ALIGN((ulong)src + length,
+ ARCH_DMA_MINALIGN),
+ length);
+ else
+ decrypt_ptr = load_ptr;
+ } else {
+ decrypt_ptr = load_ptr;
+ }
+
+ ret = spl_fit_image_decrypt(fit, node, cipher_node, &src, &length,
+ decrypt_ptr);
+ if (ret)
+ return ret;
+ }
+
if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS))
board_fit_image_post_process(fit, node, &src, &length);
- load_ptr = map_sysmem(load_addr, length);
if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) {
size = length;
if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) {
--
2.53.0
More information about the U-Boot
mailing list