Keep the production signing key off the build machine and reach it through a PKCS#11 token or an HSM, and run a separate development key that is never fused into a production part. The cost is that your continuous integration system can no longer produce a shippable image on its own. The gain is that a compromised build server does not become a compromised product line.
Secure boot key custody is the decision about where the private key that signs your firmware lives, and who can make it sign something. It is rarely decided deliberately, and usually settled when someone follows the vendor application note, runs the code signing tool against a directory of sample keys, and commits that directory so the next engineer can build. Months later the product ships, and the key that authorises every update sits in a shared repository.
The context
The hardware side is irreversible. On i.MX parts using HABv4 the public Super Root Keys form an SRK table, that table is hashed, and the hash is programmed into fuses. The Foundries.io i.MX reference states the consequence plainly: once programmed, those fuses cannot be modified. A further fuse, SEC_CONFIG[1], moves the part into the closed state, and a production device should also lock the SRK values. Other families use different names for the same arrangement, and none of them reopen a closed part.
The key also has to outlive the people and machines around it. A product with a ten-year field life needs a valid signature for ten years, while build servers get rebuilt and the engineer who made the key leaves. A key that exists only as a file on a machine has a shorter expected life than the product it authorises.
The third property is easy to miss. Secure boot key custody is one question repeated at each verification boundary, and the boundaries use different tools:
- The boot ROM verifies the first-stage loader, using the vendor key tree and Code Signing Tool.
- U-Boot verifies the FIT image holding the kernel and device tree, using a key whose public half sits in its control device tree.
- The kernel verifies loadable modules, using the key named by
CONFIG_MODULE_SIG_KEY.
Teams often protect the first key carefully and leave the other two in the build tree, which leaves a supported path to running an attacker’s kernel on a device that reports secure boot as on.
The options
Option 1: key files in the source tree
The key pair is generated once and committed with the build metadata. In Yocto you point UBOOT_SIGN_KEYDIR at a directory in a layer, or set FIT_GENERATE_KEYS = "1" (the default is “0”) so the build creates a pair when none exists.
# local.conf โ development chain
UBOOT_SIGN_ENABLE = "1"
UBOOT_SIGN_KEYDIR = "${TOPDIR}/../keys/dev"
UBOOT_SIGN_KEYNAME = "dev"
Any engineer can build, bisect a boot regression and reproduce a customer’s binary. Against that, the key is readable by anyone with repository access. Fused into shipping parts, it means the number of people who can sign your firmware equals the number who have ever had a checkout.
Option 2: key files on a restricted build server
The key stays out of version control on one machine, readable only by the release account. This is a real improvement for little work and keeps release signing automatic. Against that, the key is still an extractable file that anyone who can run a job on that machine can copy without leaving evidence.
Option 3: a PKCS#11 token or HSM the build calls
The private key is generated inside a smartcard, token or HSM and never leaves it: the build sends a hash and receives a signature. U-Boot’s mkimage supports this through an OpenSSL engine:
raghu@techveda.org:~$ export MKIMAGE_SIGN_PIN=******
raghu@techveda.org:~$ ./tools/mkimage -F -N pkcs11 -r \
-k "pkcs11:serial=000xxxxxxxxx;object=Signature%20key" \
-K u-boot.dtb fitImage
-N pkcs11 selects the engine, -k supplies the token URL, -K writes the public key into U-Boot’s control device tree, and -r marks it required, so U-Boot refuses a configuration it cannot verify.
The key is marked CKA_SENSITIVE and CKA_NEVER_EXTRACTABLE, so an attacker who compromises the build machine cannot leave with the ability to sign forever. They can still sign anything they like while access lasts, which is why this bounds the damage rather than preventing it. Against that, someone must own the token, its PIN and its backup, and a lost token with no spare key in the SRK table ends updates.
Option 4: a detached signing step after the build
The build produces an unsigned artefact and a small separate process signs it, which U-Boot supports because mkimage -F adds signatures to an existing FIT image. The component holding the key runs almost no code, and signing becomes an auditable event with a requester and an approver. Against that, it is the most work to set up.
The decision
For a product that will be closed in production, settle secure boot key custody as two key chains from the first week, and put the production key in hardware. The development chain uses option 1: keys in the repository, parts left open. Name that key dev and never fuse its hash into a part you sell. The production chain uses option 3 for the key material and option 4 for the process.
Two details matter. First, decide the key inventory before the first fuse is burnt. On i.MX the SRK table holds up to four public keys, and the SRK_REVOKE fuses cover only the first three, so a full table leaves one key that cannot be revoked as the fallback. A single-key table has no recovery path at all.
Second, U-Boot can require more than one signature. The required property on a key node accepts image or conf, and the /signature node accepts required-mode with the values any or all:
raghu@techveda.org:~$ fdtput -t s control.dtb /signature required-mode all
With any, a configuration signed by either of two required keys boots, which makes staged rotation possible: ship a release trusting old and new keys, then retire the old one. With all, both signatures are demanded, which supports two-person release control. That part of secure boot key custody is hard to change once devices ship.
The simpler options are sometimes right. If parts are never closed, the signature is a build convention rather than a control, so option 1 is proportionate and option 3 is unnecessary expense. If the team is two people and the alternative to committing a key is not shipping, commit the key, but record which fuse burn would make that permanent.
Custody protects the key; it says nothing about the correctness of the code that checks the signature. A verifier with a parsing flaw will accept an image the key never authorised, which we looked at in How U-Boot Verified Boot Was Broken by Its Own Image Parser.
The consequences of secure boot key custody
Secure boot key custody is easier to plan than to discover during a release.
Builds stop being self-contained. A signed release can no longer be reproduced from source alone, so the build documentation has to name who approves a signature. Development builds must stay reproducible or engineers cannot bisect.
The module key needs its own answer. The kernel build generates a key pair into certs/signing_key.pem when none is present, and setting CONFIG_MODULE_SIG_KEY to anything else disables that generation. It also accepts a PKCS#11 URI (RFC 7512). The kernel documentation is direct: the private key must be destroyed or moved to a secure location, not left in the source tree.
Verification is not one symbol. FIT verification needs CONFIG_FIT_SIGNATURE plus CONFIG_RSA or CONFIG_ECDSA, and U-Boot’s documentation warns that CONFIG_LEGACY_IMAGE_FORMAT must stay disabled, because it offers a path around the check.
Key takeaways
- Secure boot key custody is decided in practice by whoever produces the first signed image. Decide it before any fuse is programmed.
- Run two chains: a development key in the repository for open parts, and a production key that is never a file.
- A token or HSM converts a stolen key into temporary signing access.
- Populate the whole SRK table before it is hashed into fuses, so revocation and rotation stay possible.
Frequently asked questions
Can we move the signing key into an HSM after the product has shipped?
You can move the key material only if it is still extractable. What you cannot change is which public key the parts in the field already trust, because that hash is in fuses. Settle secure boot key custody before the first production fuse burn.
Is a signed FIT image enough on its own?
No. U-Boot verifies the FIT image only if the public key is marked required in its control device tree, and only if U-Boot itself was verified by the stage before it. If the boot ROM does not authenticate the loader, an attacker replaces the loader and its trusted key together.
What happens to the signing token when the engineer holding it leaves?
A token in one person’s drawer is a single point of failure with no backup. Either use an HSM with a documented operator model, or populate the whole SRK table so a lost key can be revoked.
Further reading
- U-Boot FIT Signature Verification โ control-FDT key storage,
required-mode, and PKCS#11 signing. - Kernel module signing facility โ
CONFIG_MODULE_SIG_KEYand protecting the private key. - Yocto Project Reference Manual: Classes โ the signing and key-generation variables.
- i.MX Secure Boot on HABv4 Supported Devices โ SRK table hashing and the fuse-programming steps.
- NXP AN4581: Secure Boot Using HABv4 โ the PKI tree, SRK revocation and the Code Signing Tool.




