Secure boot means the chip only runs firmware you signed. On the NXP i.MX RT10xx this is HAB (High Assurance Boot, version 4): the boot ROM checks a signature on your image against a hash of your public keys that is burned into the chip’s fuses.

The concept is simple. Production is not, because almost every step is one-way. A fuse bit can go from 0 to 1, never back. Burn the wrong value, or burn the right values in the wrong order, and a board on the line becomes scrap. For a product team, the order of the steps matters more than any single step.

In this article I give the checklist I use, in the order that keeps every step recoverable for as long as possible, with the reason behind each one.

HAB is not a switch. It is a ratchet with three positions, and it only turns one way.

The checklist at a glance

The whole flow on one page. Green steps can be repeated; red steps burn fuses.

The first four steps can be repeated as often as you like. That is where all the testing belongs.

0. Draw the trust boundary first

Decide who is allowed to hold secrets before you generate a single key. My split: the contract manufacturer (EMS) assembles and tests boards with an unsigned test image and no keys. Boards leave the EMS open, with no secrets on them. Signing, fusing and device identity happen in-house.

That one decision keeps the private keys inside one building and makes every later step auditable.

1. Keys: only a hash goes into the chip

HAB uses a small tree of keys. The SRK (Super Root Key) sits at the top. It certifies a CSF key, which signs the command sequence, and an IMG key, which signs the image. The chip stores only a hash of the SRK public keys, in the SRK_HASH fuses.

With NXP’s SPSDK the key tree is one command. Without -ca you only get SRKs, which is not enough to sign:

bash
nxpcrypto pki-tree hab -k rsa2048 -o keys -ca

Two rules matter more than the tool:

  1. The private keys never live on a laptop that leaves the building. An HSM is the right home.
  2. Choose the key size for the product’s lifetime, not the tutorial. HABv4 supports RSA from 1024 to 4096 bits. Most examples, including mine above, use RSA-2048. NXP’s AN13023 notes that BSI guidance does not accept RSA-2048 for new designs, while RSA-3072 is fine. If your product goes through that kind of review, decide before you fuse anything.

2. Sign the image

In SPSDK 2.0 (October 2023) the old tool names changed: elftosb became nxpimage, and nxpkeygen/nxpcertgen became nxpcrypto. Old tutorials fail quietly because of it.

bash
nxpimage hab get-template -f mimxrt1060 -o hab_template.yaml
nxpimage hab export -c hab_template.yaml -o signed_image.bin

The family flag is mimxrt1060, not mimxrt1062

-f mimxrt1062 is rejected. The family string mimxrt1060 covers the RT1060, RT1062 and RT1064.

HAB signs a digest of the image. It does not encrypt it. Encryption is a separate step (step 5).

3. Boot the signed image on an open part

This is the step that prevents the most common production brick. Before any fuse is burned, erase the flash, program the final signed image, and boot it on a part that is still open.

In the open configuration HAB checks the signature but only logs a failure and boots anyway. That makes it the perfect test bench: you see every problem in the HAB event log, and the board still works. Do not move on until the log is clean.

4. Burn the SRK hash and check again

Now burn SRK_HASH, reboot, and check the HAB log a second time, this time against the fused hash. The part is still open, so a mistake here still boots. It just means this chip can never be closed with your keys.

One-way from here

eFuse bits only go from 0 to 1. Every step from here on cannot be undone. Script the fuse values, review them, and burn them from a tool, never by hand.

5. Encrypted XIP: decide early

Signing proves who wrote the firmware. Anyone with a flash programmer can still read it. If the code itself is worth protecting, the i.MX RT106x can run encrypted code straight from flash with its BEE (Bus Encryption Engine): AES-128, two regions, decrypted on the fly while executing. Other RT10xx parts use OTFAD instead, and the RT1010 has neither.

The fuses involved are BOOT_CFG1[1], which enables encrypted XIP, and the key-select fuses BEE_KEY0_SEL / BEE_KEY1_SEL. These pick either a key derived from the chip-unique OTPMK or a key you burn yourself into SW_GP2.

Where BEE’s key blocks live in flash, and what each key choice costs you.

BEE on the RT106x is decrypt-only

The engine only decrypts. With the chip-unique key, nobody outside the chip can produce new ciphertext for that region, which makes it effectively write-once and kills over-the-air updates. A key of your own in SW_GP2 restores updates but costs per-device secrecy. My answer is a hybrid: the chip-unique key for the bootloader, your own key for the application.

One more trade-off: encrypted XIP does not work together with flash remapping. If you use MCUboot, that rules out its swap-by-remap mode and leaves overwrite-only updates, without a rollback slot.

6. Close the part

Burning SEC_CONFIG[1] closes the part. From then on, an image that fails authentication does not run: the boot ROM drops into the serial downloader instead.

My policy: the first batch stays open with the SRK fused, so it can still be recovered. Volume units are closed only after the full end-of-line test has passed on them.

Two details are easy to miss:

  • Closing does not disable the USB serial downloader (SDP). A separate fuse, SDP_DISABLE, does that. I leave SDP enabled on purpose, as a recovery path.
  • On a closed part the boot ROM enables the MPU. A debug or flash tool that worked before may need to disable it first.

7. Lock the debug port and the fuses, last

An open JTAG port bypasses everything above. The i.MX RT1060 Security Reference Manual describes three modes in the JTAG_SMODE fuses: enabled, Secure JTAG (challenge-response), or no debug. SJC_DISABLE gives the strongest protection. The manual also requires the KTE fuse to be burned, or the JTAG mode does not take effect.

The very last step is the lock fuses (BOOT_CFG_LOCK, SJC_RESP_LOCK, the GP locks and others), which stop anyone from burning more bits later. And never burn a reserved fuse.

Where this step comes from

Steps 0–6 are from my own production flow. The debug-lock details in step 7 come from NXP’s Security Reference Manual and application notes, not from my bench. Check them against the manual for your exact part before you burn anything.

Who checks what at runtime

A common question once MCUboot is in the picture: does HAB verify every application update? No. HAB verifies the bootloader at every reset. The bootloader then verifies the application with its own signature (ECDSA P-256 in my setup). That means two sets of signing keys, and both belong behind the same trust boundary from step 0.

Two signing key sets, one trust boundary.

Summary

  1. The order is the safety net. Everything reversible (keys, signing, testing on an open part) happens before anything one-way.
  2. Signing is not encryption. HAB proves origin. BEE hides the code, and on the RT106x it comes with a decrypt-only catch for updates.
  3. Close late and in stages. First batch open with the SRK fused, volume units closed after their full test, debug and fuse locks last.

Sources

  • NXP AN12681, HABv4 secure boot on i.MX RT10xx.
  • NXP, i.MX RT1060 Security Reference Manual: security configurations, fuse map, BEE, Secure JTAG.
  • NXP AN12852, on-the-fly decryption on i.MX RT.
  • NXP AN13023, crypto algorithm recommendations (the RSA key-size note).
  • SPSDK documentation: nxpcrypto and nxpimage hab.

💬 Questions, corrections, or your own war story? Leave a comment below.