Verified Boot Patterns in U-Boot: What to Verify, Where Keys Live, and Failure Modes

Deep dive into U-Boot verified boot patterns covering signature scopes, key storage options, common failure modes, and practical debugging techniques for embedded Linux platforms.

Verified Boot Patterns in U-Boot: What to Verify, Where Keys Live, and Failure Modes

Verified boot in U-Boot goes beyond signing a kernel image. The practical challenge is deciding what to verify, where to store keys so they survive updates, and how to handle the failure modes that appear in real deployments. This guide covers the patterns that work in production and the anti-patterns that cause field failures.

Verification scope: what gets signed

U-Boot's FIT signature mechanism can sign individual images (kernel, DTB, initramfs) or configurations (the combination of images for a specific boot scenario). The choice has security implications.

Image-level signing

Each image node in the FIT has its own signature. This allows mixing and matching signed components. For example, you could update the device tree without re-signing the kernel.

The risk: if an attacker can combine a signed old kernel with a signed old DTB that has different security settings (debug UART enabled, for instance), they can downgrade the device's security posture without breaking any individual signature.

The configuration node ties specific images together and signs the combination. You cannot swap a kernel version without re-signing the entire configuration. This is more restrictive but more secure.

For the secure boot walkthrough, configuration-level signing is the recommended pattern.

Where keys live

The public key for verification must be accessible to U-Boot before it verifies anything. There are several storage patterns, each with trade-offs.

Embedded in U-Boot DTB (most common)

The public key is compiled directly into U-Boot's device tree blob. This is simple and reliable: the key is always available because it is part of U-Boot itself.

Limitation: updating the key requires updating U-Boot. This is acceptable if your update mechanism can update the bootloader, but some products lock down the bootloader early and never update it.

In a dedicated key partition

Store the public key in a separate flash partition that U-Boot reads during boot. This allows key rotation without reflashing U-Boot.

Risk: the key partition itself becomes a target. It must be protected against unauthorized writes (e.g., by hardware write protection or by signing the key partition with a root key embedded in ROM).

In one-time-programmable (OTP) fuses

Some SoCs provide OTP fuse banks where a hash of the public key can be permanently written. U-Boot reads the key from flash but verifies its hash against the fused value. This provides a hardware root of trust.

This is the most secure option but is irreversible. A wrong fuse write bricks the device permanently for secure boot purposes. Test thoroughly on development boards before fusing production units.

In the SoC ROM boot chain

Some SoCs (NXP i.MX, TI AM64x, STM32MP1) have ROM bootloaders that verify the first-stage bootloader using keys stored in OTP fuses. U-Boot SPL is verified by ROM; U-Boot proper is verified by SPL; the FIT image is verified by U-Boot proper. This creates a complete hardware-rooted chain of trust.

Common failure modes

1. Signature algorithm mismatch

The .its file specifies sha256,rsa4096 but the key was generated as RSA-2048. U-Boot silently fails to find a matching key and reports verification failure. Always verify the key size matches the algorithm string in both the ITS and the U-Boot key node.

2. DTB size overflow

When mkimage embeds the public key into U-Boot's DTB, the DTB grows. If the DTB partition or memory allocation is too small, the key write silently truncates. U-Boot then cannot find the key. Reserve at least 8 KB extra in the DTB allocation for RSA-4096 keys.

3. Legacy image format fallback

If CONFIG_IMAGE_FORMAT_LEGACY=y is enabled, an attacker can bypass FIT verification by presenting a legacy uImage. U-Boot will happily boot it without checking any signatures. Always disable legacy image format in secure boot configurations.

4. Missing required property

If the key node does not include required = "conf" or required = "image", signature verification is advisory only. U-Boot prints warnings but still boots unsigned images. This is the single most common secure boot misconfiguration.

5. FIT image corruption during OTA

A partially written FIT image during an OTA update produces an invalid FIT structure. U-Boot cannot parse it and may fall through to a recovery path or hang. The OTA update documentation covers atomic update patterns that prevent this scenario.

6. Clock drift affecting timestamp verification

Some U-Boot configurations include timestamp verification. If the RTC battery dies or the device has no RTC, time-based verification fails spuriously. Either use a reliable time source or avoid timestamp-based checks on embedded devices.

Debugging verified boot failures

When signature verification fails, U-Boot's default error messages are terse. Enable CONFIG_FIT_VERBOSE=y to get detailed output including:

  • Which key was attempted
  • The computed hash value
  • The expected hash value
  • Which image or configuration failed

For development, add a serial console to capture boot logs. On production devices, store verification failure logs in a persistent partition for later retrieval.

Step-by-step debug process

  1. Verify the FIT image is intact: dumpimage -l fitImage on the host should show all images and configurations with correct hash values.
  2. Verify the key is present in U-Boot DTB: fdtdump u-boot.dtb | grep -A 20 signature should show the public key data.
  3. Verify algorithm alignment: The algorithm string in the FIT configuration's signature node must match the algorithm string in the U-Boot DTB key node.
  4. Try signing and verifying on the host: mkimage -F -k /path/to/keys -K u-boot.dtb -r fitImage should succeed. If it fails on the host, it will fail on target.

Anti-rollback protection

Signing prevents tampering but not rollback. An attacker with physical access can flash an older, signed image that has known vulnerabilities. Anti-rollback protection uses a monotonic counter (typically stored in OTP fuses) that increments with each firmware version. U-Boot refuses to boot images with a counter value lower than the fused minimum.

Implementation:

  1. Include a version counter in the FIT configuration
  2. Store the minimum acceptable counter in OTP fuses
  3. After successful boot, increment the fused counter

This is irreversible by design. A failed update that increments the counter before verifying the new image can brick the device. Only increment after the new image has been fully validated.

Integration with ProteanOS

ProteanOS build workflows generate FIT images as part of the ProKit build process. The signing step is integrated into the build pipeline: keys are stored in a protected CI variable, and mkimage signs the FIT image as the final build step.

For platform bring-up, the the board bring-up documentation includes verified boot as a milestone after basic boot is working. Get unsigned boot stable first, then add verification.

Summary

Verified boot in U-Boot is straightforward to set up but has failure modes that only appear in production scenarios. Sign at the configuration level, disable legacy image format, mark keys as required, and test failure paths as thoroughly as success paths. Plan for key rotation and anti-rollback from the start—retrofitting them is significantly harder than including them in the initial design.