Securing U-Boot with FIT Signature and Key Injection on ZynqMP
Published at July 17, 2025 · 4 min read · Tags: u-boot secure-boot yocto zynq
Securing U-Boot with FIT Signature and Key Injection on ZynqMP
Published at July 17, 2025 · 4 min read · Tags: u-boot secure-boot yocto zynq
This blog post provides a comprehensive guide to implementing secure boot with U-Boot using FIT image signatures and RSA public key injection, targeting Xilinx ZynqMP platforms such as the ZCU102. It includes theory, differences between DTB embedding methods, and a practical Yocto-based implementation.
Modern U-Boot supports signed FIT images to enforce boot-time validation of kernel and other binaries. The verification is done using an RSA public key embedded in U-Boot’s DTB.
To enable this:
fitImage.itb
) using mkimage
and a private key.u-boot.dtb
using mkimage -K
.U-Boot can be built in two modes regarding the Device Tree:
Mode | CONFIG Option | Description |
---|---|---|
Embedded | CONFIG_OF_EMBED=y |
DTB is compiled directly into the U-Boot binary |
Separate | CONFIG_OF_SEPARATE=y |
DTB is loaded separately; must be deployed explicitly |
For signature injection to take effect, you must inject the key into the DTB actually used at runtime. If using OF_EMBED
, you must re-link U-Boot after modifying the DTB.
Generate keys (one-time or for dev):
openssl genpkey -algorithm RSA -out dev.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key dev.key -out dev.crt -subj "/CN=dev/"
Prepare a minimal fit.its
for key injection (not full FIT):
/dts-v1/;
/ {
description = "Key Injection Only";
#address-cells = <1>;
images {
dummy {
data = /incbin/("/dev/null");
type = "kernel";
arch = "arm";
os = "linux";
compression = "none";
hash@1 { algo = "sha256"; };
};
};
signatures {
sig1 {
algo = "sha256,rsa2048";
key-name-hint = "dev";
sign-images = "dummy";
};
};
};
Inject the public key into the DTB:
mkimage -f fit.its -k keys/ -K u-boot.dtb
⚠️ Do not pass an output image name like
fit.itb
if you’re only injecting the key!
Verify key injection:
fdtdump u-boot.dtb | grep -A20 signature
You should see the RSA modulus, exponent, and key-name-hint
.
(Optional) Create a signed FIT image:
mkimage -f full-fit.its -k keys/ -K u-boot.dtb signed.itb
do_compile:append()
to build the DTB and inject the key after DTB exists.oe_runmake
after the injection, or it will overwrite it.do_deploy:append()
, install the final u-boot.dtb
into ${DEPLOYDIR}
under a unique name (u-boot-injected.dtb
).CONFIG_OF_EMBED=y
, ensure U-Boot is rebuilt after injection so the DTB is re-linked into it.To integrate FIT signature and key injection into a Yocto build, you can append logic to your u-boot-xlnx_%.bbappend
using do_compile:prepend()
and do_deploy:append()
.
Here is a practical example of the injection logic:
do_compile:prepend() {
# Generate key if missing (in real systems: use secure storage!)
if [ ! -f "${FIT_KEY_DIR}/${FIT_KEY_NAME}.key" ]; then
mkdir -p ${FIT_KEY_DIR}
openssl genpkey -algorithm RSA -out ${FIT_KEY_DIR}/${FIT_KEY_NAME}.key -pkeyopt rsa_keygen_bits:2048
openssl req -new -x509 -key ${FIT_KEY_DIR}/${FIT_KEY_NAME}.key -out ${FIT_KEY_DIR}/${FIT_KEY_NAME}.crt -subj "/CN=dev/"
fi
bbnote "Step 1: Forcing early build of u-boot.dtb"
oe_runmake ${UBOOT_DTB_BINARY}
bbnote "Step 2: Injecting FIT public key into DTB"
touch ${TMP_NULL}
# This command embeds the public key into u-boot.dtb. It will fail if fit.its is malformed or the key is invalid.
${B}/tools/mkimage -f ${WORKDIR}/fit.its -k ${WORKDIR}/keys -K ${B}/${UBOOT_DTB_BINARY} ${WORKDIR}/fit.itb || die "mkimage key injection failed"
bbnote "Step 3: Generate boot.scr from boot.cmd"
${B}/tools/mkimage -A arm -T script -C none -n "Boot Script" -d ${WORKDIR}/boot.cmd ${WORKDIR}/boot.scr
}
In this script:
mkimage -K
boot.scr
script is generated from boot.cmd
Make sure to copy the final u-boot.dtb
to ${DEPLOYDIR}
in do_deploy:append()
if you’re using CONFIG_OF_SEPARATE=y
. For CONFIG_OF_EMBED=y
, ensure U-Boot is rebuilt after injection.
To enable FIT signature support in U-Boot, add the following to your configuration fragment or defconfig
:
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_RSA=y
CONFIG_OF_CONTROL=y
CONFIG_OF_EMBED=y # or CONFIG_OF_SEPARATE=y depending on your setup
These enable U-Boot to validate FIT signatures using embedded public keys. Ensure that your u-boot.dtb
is actually used at boot by U-Boot.
mkimage
with -K
must not include a FIT output filename if you’re only injecting a key./dev/null
as a dummy image works only without configurations {}
block.fdtdump
.This guide walks you through enabling FIT image signing in U-Boot with RSA public key verification, focusing on practical Yocto integration. It’s essential for secure embedded systems boot chains, especially in safety- and security-critical environments.