[PATCH v2 04/10] spl: fit: support encrypted payloads
James Hilliard
james.hilliard1 at gmail.com
Fri Jul 3 03:49:49 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 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>
---
Changes v1 -> v2:
- Drop redundant SPL_FIT select (suggested by Simon Glass)
- Explain the IMAGE_ENABLE_DECRYPT change (suggested by Simon Glass)
- Explain the host tools decrypt behavior (suggested by Simon Glass)
- Decrypt external encrypted payloads in place (suggested by Simon Glass)
- Skip self-memmove after direct decrypt (suggested by Simon Glass)
---
boot/Kconfig | 8 +++++++
boot/image-fit.c | 2 +-
common/spl/spl_fit.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 70 insertions(+), 8 deletions(-)
diff --git a/boot/Kconfig b/boot/Kconfig
index 8e468c56176..73fc570d0c8 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -155,6 +155,14 @@ 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
+ 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 a4192db5eb5..c84cbfaf4a8 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2312,7 +2312,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..e5a525f6dce 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -193,6 +193,28 @@ 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;
+}
+
/**
* 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 +247,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 +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;
}
if (fit_image_get_load(fit, node, &load_addr)) {
@@ -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 (!fit_image_get_data_position(fit, node, &offset)) {
external_data = true;
} else if (!fit_image_get_data_offset(fit, node, &offset)) {
@@ -291,11 +322,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 +363,32 @@ 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) {
+ decrypt_ptr = src;
+ } 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)) {
@@ -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);
}
--
2.53.0
More information about the U-Boot
mailing list