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.itbif 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 -Kboot.scr script is generated from boot.cmdMake 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.