Secure Boot with U-Boot FIT Signatures: A Practical Chain-of-Trust Walkthrough

Step-by-step guide to implementing secure boot using U-Boot FIT image signatures, from key generation through verified boot to failure handling on embedded Linux targets.

Secure Boot with U-Boot FIT Signatures: A Practical Chain-of-Trust Walkthrough

Secure boot ensures that only authenticated software runs on your hardware. In embedded Linux systems using U-Boot, the Flattened Image Tree (FIT) format provides a structured way to bundle kernel, device tree, and initramfs images with cryptographic signatures. This walkthrough covers the practical steps from key generation through to a working verified boot chain.

What the chain of trust looks like

A complete chain of trust for an embedded Linux device typically has three or four stages:

  1. ROM bootloader (in silicon) → verifies the secondary bootloader
  2. Secondary bootloader (SPL/TPL) → verifies U-Boot proper
  3. U-Boot → verifies the FIT image (kernel + DTB + optional initramfs)
  4. Kernel → verifies the root filesystem (via dm-verity or IMA)

This guide focuses on stage 3: U-Boot verifying a signed FIT image. For root filesystem verification, see the the dm-verity documentation.

FIT image structure

A FIT image is a single binary containing multiple components described by an embedded device tree structure. A typical signed FIT image includes:

/images/
    kernel@1   → compressed kernel binary
    fdt@1      → device tree blob
    ramdisk@1  → initramfs (optional)
/configurations/
    conf@1     → ties kernel + fdt + ramdisk together
               → carries the RSA signature

The configuration node is what gets signed. This means the signature covers the specific combination of kernel, device tree, and initramfs. Swapping any component invalidates the signature.

Key generation

Generate an RSA key pair. U-Boot supports RSA-2048, RSA-3072, and RSA-4096. Use RSA-4096 for new designs unless performance constraints dictate otherwise.

# Generate private key
openssl genpkey -algorithm RSA -out sign-key.pem \
  -pkeyopt rsa_keygen_bits:4096

# Extract public key in DER format
openssl rsa -in sign-key.pem -pubout -outform DER -out sign-key-pub.der

The private key signs images during the build. The public key is embedded in U-Boot itself (or in the SPL that verifies U-Boot). Protect the private key; if it leaks, an attacker can sign arbitrary images.

Embedding the public key in U-Boot

U-Boot stores the public key in its control device tree (the DTB compiled into U-Boot or loaded alongside it). The mkimage tool handles this during the signing step.

First, create a device tree source snippet for the key:

/ {
    signature {
        key-dev {
            required = "conf";
            algo = "sha256,rsa4096";
            key-name-hint = "sign-key";
        };
    };
};

During the FIT signing step, mkimage writes the public key into the U-Boot DTB automatically.

Creating and signing a FIT image

Write a FIT image description (.its file):

/dts-v1/;

/ {
    description = "Signed kernel image";
    #address-cells = <1>;

    images {
        kernel@1 {
            description = "Linux kernel";
            data = /incbin/("Image.gz");
            type = "kernel";
            arch = "arm64";
            os = "linux";
            compression = "gzip";
            load = <0x40480000>;
            entry = <0x40480000>;
            hash@1 {
                algo = "sha256";
            };
        };
        fdt@1 {
            description = "Device tree";
            data = /incbin/("target.dtb");
            type = "flat_dt";
            arch = "arm64";
            compression = "none";
            hash@1 {
                algo = "sha256";
            };
        };
    };

    configurations {
        default = "conf@1";
        conf@1 {
            description = "Boot configuration";
            kernel = "kernel@1";
            fdt = "fdt@1";
            signature@1 {
                algo = "sha256,rsa4096";
                key-name-hint = "sign-key";
                sign-images = "kernel", "fdt";
            };
        };
    };
};

Sign the image:

mkimage -f image.its -k /path/to/keys -K u-boot.dtb -r fitImage

The -K flag tells mkimage where to find sign-key.pem. The -r flag marks the key as "required" in the U-Boot DTB, meaning U-Boot will refuse to boot unsigned or incorrectly signed configurations.

Configuring U-Boot for verified boot

Enable these options in your U-Boot defconfig:

CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_RSA=y
CONFIG_FIT_VERBOSE=y
CONFIG_IMAGE_FORMAT_LEGACY=n

Disabling IMAGE_FORMAT_LEGACY is important. If legacy image format is enabled, an attacker can bypass FIT signature verification by providing a legacy (unsigned) image instead.

Boot flow with verification

When U-Boot boots a signed FIT image:

  1. U-Boot parses the FIT structure
  2. For each configuration, U-Boot checks if a signature node exists
  3. U-Boot computes the hash of the referenced images (kernel, DTB, etc.)
  4. U-Boot verifies the signature against the embedded public key
  5. If verification succeeds, boot proceeds. If it fails, U-Boot halts or falls back (depending on configuration)

Failure modes and handling

What happens when verification fails matters as much as the verification itself.

Hard failure (recommended for production): U-Boot prints an error and halts. The device does not boot. This is the most secure option but requires a recovery mechanism (see below).

Soft failure (development only): U-Boot prints a warning but continues booting. This is useful during development but must never ship in production firmware.

Configure failure behaviour through the required property in the key node. When set to "conf", verification failure prevents boot.

Recovery mechanisms

A device that refuses to boot due to a failed signature check needs a recovery path:

  • Dual-bank (A/B) boot: Maintain two image slots. If the primary fails verification, boot the secondary. The OTA update documentation covers A/B update schemes.
  • Recovery partition: A minimal, separately-signed recovery image that can download and flash a new primary image.
  • Serial/USB recovery: U-Boot's USB DFU or serial boot modes can load a new image. These should be disabled or authenticated in production.

Key rotation

Plan for key rotation from the start. Embed a "next key" slot in your U-Boot DTB. When you need to rotate keys:

  1. Sign a transition image with the old key
  2. The transition image contains U-Boot with the new public key embedded
  3. Subsequent images are signed with the new key

Without a key rotation mechanism, a compromised key means replacing U-Boot itself, which may require physical access.

Testing the chain

Test both the happy path and the failure path:

# Happy path: correctly signed image boots
# (build and sign normally, verify it boots)

# Failure path: tampered image is rejected
# Modify one byte in the kernel portion of the FIT image
dd if=/dev/urandom of=fitImage bs=1 count=1 seek=65536 conv=notrunc
# Attempt to boot — U-Boot should reject it

For teams working within the ProteanOS ecosystem, the the verified boot patterns documentation covers additional U-Boot verification scenarios including key storage locations and common failure modes across different SoC families.

The the board bring-up documentation includes secure boot as a bring-up milestone for new hardware platforms.

Summary

FIT image signing with U-Boot provides a practical, well-tested mechanism for embedded secure boot. The key steps are: generate keys, embed the public key in U-Boot, sign FIT images during the build, and configure U-Boot to require valid signatures. Test failure modes thoroughly and plan key rotation before your first production shipment.