From: James Hilliard <james.hilliard1@gmail.com>
To: Svyatoslav Ryhel <clamor95@gmail.com>,
Ion Agorria <ion@agorria.com>,
u-boot@lists.denx.de, Aspeed BMC SW team <BMC-SW@aspeedtech.com>,
Joel Stanley <joel@jms.id.au>
Cc: Chen-Yu Tsai <wens@kernel.org>,
Samuel Holland <samuel@sholland.org>,
Tom Rini <trini@konsulko.com>, Simon Glass <sjg@chromium.org>,
Thierry Reding <treding@nvidia.com>,
Quentin Schulz <quentin.schulz@cherry.de>,
Marek Vasut <marek.vasut+renesas@mailbox.org>,
Rasmus Villemoes <ravi@prevas.dk>,
Aristo Chen <aristo.chen@canonical.com>,
Anton Ivanov <anton@binarly.io>,
Daniel Golle <daniel@makrotopia.org>,
Francois Berder <fberder@outlook.fr>,
Peng Fan <peng.fan@nxp.com>,
Neil Armstrong <neil.armstrong@linaro.org>,
Randolph Sapp <rs@ti.com>, Jonas Karlman <jonas@kwiboo.se>,
Wolfgang Wallner <wolfgang.wallner@at.abb.com>,
Alexey Charkov <alchark@gmail.com>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Heiko Schocher <hs@nabladev.com>,
"Kory Maincent (TI.com)" <kory.maincent@bootlin.com>,
Anshul Dalal <anshuld@ti.com>, Johan Jonker <jbx6244@gmail.com>,
Francesco Valla <francesco@valla.it>,
Heinrich Schuchardt <xypron.glpk@gmx.de>,
Michael Walle <mwalle@kernel.org>,
Andre Przywara <andre.przywara@arm.com>,
Lukasz Majewski <lukma@denx.de>,
Richard Genoud <richard.genoud@bootlin.com>,
Michael Trimarchi <michael@amarulasolutions.com>,
E Shattow <e@freeshell.de>,
Enric Balletbo i Serra <eballetbo@kernel.org>,
Mattijs Korpershoek <mkorpershoek@kernel.org>,
Lucas Dietrich <ld.adecy@gmail.com>,
David Lechner <dlechner@baylibre.com>,
Julien Stephan <jstephan@baylibre.com>,
Kuan-Wei Chiu <visitorckw@gmail.com>,
Bastien Curutchet <bastien.curutchet@bootlin.com>,
Raymond Mao <raymond.mao@riscstar.com>,
Ryan Chen <ryan_chen@aspeedtech.com>,
Chia-Wei Wang <chiawei_wang@aspeedtech.com>,
"Lucien.Jheng" <lucienzx159@gmail.com>,
Mateusz Furdyna <mateusz.furdyna@nokia.com>,
Dinesh Maniyam <dinesh.maniyam@altera.com>,
Heiko Stuebner <heiko@sntech.de>,
James Hilliard <james.hilliard1@gmail.com>
Subject: [PATCH v4 09/14] spl: fit: support encrypted payloads
Date: Mon, 13 Jul 2026 00:43:06 -0600 [thread overview]
Message-ID: <20260713-submit-ce-series-v2-v4-9-ff7edc705b8a@gmail.com> (raw)
In-Reply-To: <20260713-submit-ce-series-v2-v4-0-ff7edc705b8a@gmail.com>
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.
Defer mapping the final destination until the board post-processing hook
has finalized the source and length. The direct embedded-decrypt path maps
early because the hardware needs its destination, but tracks and extends
that mapping if post-processing grows the payload. Map decompression output
for CONFIG_SYS_BOOTM_LEN rather than the compressed input length.
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.
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Changes v3 -> v4:
- Map the final destination after board post-processing determines size
- Size decompression mappings for the maximum output
- Require SPL_OF_CONTROL and clarify the SPL_FIT_CIPHER help text
Changes v2 -> v3:
- Use a shared helper for SPL decompression buffer decisions
(suggested by Simon Glass)
- Reject encrypted SPL FIT payloads when SPL_FIT_CIPHER is disabled
(suggested by Simon Glass)
- Flatten decrypt buffer selection (suggested by Simon Glass)
- Comment the no-copy path after direct decrypt (suggested by Simon Glass)
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 | 9 ++++++
boot/image-fit.c | 2 +-
common/spl/spl_fit.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 91 insertions(+), 9 deletions(-)
diff --git a/boot/Kconfig b/boot/Kconfig
index 8e468c56176..2e12a72a97b 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 decrypting data in SPL FIT images"
+ depends on SPL_LOAD_FIT
+ depends on SPL_DM_AES
+ depends on SPL_OF_CONTROL
+ help
+ Enable decrypting 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 6b55316dd37..437f6ab6381 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -2306,7 +2306,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..961e3338d16 100644
--- a/common/spl/spl_fit.c
+++ b/common/spl/spl_fit.c
@@ -193,6 +193,34 @@ 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_image_needs_decomp(uint8_t image_comp)
+{
+ return (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) ||
+ (IS_ENABLED(CONFIG_SPL_LZMA) && image_comp == IH_COMP_LZMA);
+}
+
/**
* load_simple_fit(): load the image described in a certain FIT node
* @info: points to information about the device to load data from
@@ -218,19 +246,23 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
int len;
ulong size;
ulong load_addr;
- void *load_ptr;
+ void *load_ptr = NULL;
+ size_t load_map_len = 0;
void *src;
ulong overhead;
uint8_t image_comp = -1, type = -1;
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 +288,7 @@ 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 = spl_image_needs_decomp(image_comp);
}
if (fit_image_get_load(fit, node, &load_addr)) {
@@ -267,6 +300,14 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
load_addr = image_info->load_addr;
}
+ cipher_node = fdt_subnode_offset(fit, node, FIT_CIPHER_NODENAME);
+ if (cipher_node >= 0 && !CONFIG_IS_ENABLED(FIT_CIPHER)) {
+ printf("Can't load %s: encrypted image without SPL_FIT_CIPHER\n",
+ fit_get_name(fit, node, NULL));
+ return -ENOSYS;
+ }
+ 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 +332,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 +373,40 @@ static int load_simple_fit(struct spl_load_info *info, ulong fit_offset,
puts("OK\n");
}
+ if (encrypted) {
+ void *decrypt_ptr;
+
+ if (external_data) {
+ decrypt_ptr = src;
+ } else if (needs_decomp) {
+ decrypt_ptr = map_sysmem(ALIGN(CONFIG_SYS_LOAD_ADDR,
+ ARCH_DMA_MINALIGN),
+ length);
+ } else {
+ load_map_len = length;
+ load_ptr = map_sysmem(load_addr, load_map_len);
+ 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);
+ size = needs_decomp ? CONFIG_SYS_BOOTM_LEN : length;
+ if (!load_ptr || size > load_map_len) {
+ void *old_load_ptr = load_ptr;
+
+ load_ptr = map_sysmem(load_addr, size);
+ load_map_len = size;
+ if (src == old_load_ptr)
+ src = load_ptr;
+ }
+
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 +424,8 @@ 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) {
+ /* Direct decrypt of an embedded image can already be in place. */
memmove(load_ptr, src, length);
}
--
2.53.0
next prev parent reply other threads:[~2026-07-13 13:22 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-13 6:42 [PATCH v4 00/14] crypto: allwinner: enable sun8i-ce FIT crypto James Hilliard
2026-07-13 6:42 ` [PATCH v4 01/14] cmd: aes: fix DM operation handling James Hilliard
2026-07-13 6:42 ` [PATCH v4 02/14] crypto: hash: use DM providers from hash command James Hilliard
2026-07-13 6:43 ` [PATCH v4 03/14] crypto: aes: allow DM AES in SPL James Hilliard
2026-07-13 6:43 ` [PATCH v4 04/14] crypto: hash: allow DM hash " James Hilliard
2026-07-13 6:43 ` [PATCH v4 05/14] boot: image: try all DM hash providers James Hilliard
2026-07-13 6:43 ` [PATCH v4 06/14] crypto: aes: fix software key-size handling James Hilliard
2026-07-13 6:43 ` [PATCH v4 07/14] crypto: aes: add software-key provider dispatch James Hilliard
2026-07-13 6:43 ` [PATCH v4 08/14] boot: image: add FIT decrypt-to-buffer helper James Hilliard
2026-07-13 6:43 ` James Hilliard [this message]
2026-07-13 6:43 ` [PATCH v4 10/14] clk: sunxi: add H6/H616 CE gates and reset James Hilliard
2026-07-13 6:43 ` [PATCH v4 11/14] lib: ecdsa: support additional curve sizes James Hilliard
2026-07-13 6:43 ` [PATCH v4 12/14] crypto: allwinner: add sun8i-ce AES driver James Hilliard
2026-07-13 6:43 ` [PATCH v4 13/14] crypto: allwinner: add sun8i-ce ECDSA verifier James Hilliard
2026-07-13 6:43 ` [PATCH v4 14/14] crypto: allwinner: add sun8i-ce hash driver James Hilliard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260713-submit-ce-series-v2-v4-9-ff7edc705b8a@gmail.com \
--to=james.hilliard1@gmail.com \
--cc=BMC-SW@aspeedtech.com \
--cc=alchark@gmail.com \
--cc=andre.przywara@arm.com \
--cc=anshuld@ti.com \
--cc=anton@binarly.io \
--cc=aristo.chen@canonical.com \
--cc=bastien.curutchet@bootlin.com \
--cc=chiawei_wang@aspeedtech.com \
--cc=clamor95@gmail.com \
--cc=daniel@makrotopia.org \
--cc=dinesh.maniyam@altera.com \
--cc=dlechner@baylibre.com \
--cc=e@freeshell.de \
--cc=eballetbo@kernel.org \
--cc=fberder@outlook.fr \
--cc=francesco@valla.it \
--cc=heiko@sntech.de \
--cc=hs@nabladev.com \
--cc=ilias.apalodimas@linaro.org \
--cc=ion@agorria.com \
--cc=jbx6244@gmail.com \
--cc=joel@jms.id.au \
--cc=jonas@kwiboo.se \
--cc=jstephan@baylibre.com \
--cc=kory.maincent@bootlin.com \
--cc=ld.adecy@gmail.com \
--cc=lucienzx159@gmail.com \
--cc=lukma@denx.de \
--cc=marek.vasut+renesas@mailbox.org \
--cc=mateusz.furdyna@nokia.com \
--cc=michael@amarulasolutions.com \
--cc=mkorpershoek@kernel.org \
--cc=mwalle@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=peng.fan@nxp.com \
--cc=quentin.schulz@cherry.de \
--cc=ravi@prevas.dk \
--cc=raymond.mao@riscstar.com \
--cc=richard.genoud@bootlin.com \
--cc=rs@ti.com \
--cc=ryan_chen@aspeedtech.com \
--cc=samuel@sholland.org \
--cc=sjg@chromium.org \
--cc=treding@nvidia.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=visitorckw@gmail.com \
--cc=wens@kernel.org \
--cc=wolfgang.wallner@at.abb.com \
--cc=xypron.glpk@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox