Secure Boot on STM32 — A Working Example with Anti-Rollback

Option-byte configuration, dual-bank firmware layout, and the RDP-level decisions that decide whether your secure boot survives JTAG re-attachment in the field.


Start With the Threat Model, Not the Datasheet

Secure boot is one of those features where teams reach for the application note before they reach for the threat model — and end up with a configuration that looks impressive on paper but doesn't survive the actual attacker. On STM32 the toolbox is generous: RDP (Readout Protection) levels 0/1/2, PCROP, WRP, MPU, option bytes, dual-bank flash, and the embedded SFI/SBSFU framework. Without a written threat model, you'll over-spend on the parts that don't matter and under-spend on the ones that do.

We start every secure-boot engagement with a one-page document that answers four questions:

  • Who is the attacker? A casual cloner with a J-Link, a competitor with an X-ray microscope and a bench full of probes, or a state-level adversary with focused-ion-beam capability. The answer changes everything downstream.
  • What are they after? Firmware extraction (IP theft), key extraction (fleet attack), or code injection (botnet recruitment). The mitigation for each is different.
  • What does success look like for the defender? "Attack costs more than $5,000 of equipment + 40 hours" is a perfectly valid bar for most industrial IoT. "Attack requires a fab-equivalent" is what aerospace pays for.
  • What's the recovery story? If a unit is compromised in the field, can you re-key it? Brick it? Rotate to a new signing key fleet-wide?

"We've audited secure-boot setups that locked down JTAG flawlessly but left the bootloader's UART update path completely unauthenticated. The attacker walked in through the front door while we'd bricked the side window." — Pioneer Horizon firmware team

Once that document exists, the technical choices — RDP level, signature scheme, key storage — fall out naturally. Skip it and you'll either over-engineer toward RDP-2 (which is irreversible and will haunt your support team) or under-engineer to RDP-1 (which a determined attacker can downgrade).

RDP Levels and Option Bytes — The Decisions You Can't Undo

STM32's Readout Protection is the foundation, but it's a one-way ratchet on most parts: once you go to RDP-2, you cannot go back. We've watched teams brick entire production lots by enabling RDP-2 on engineering samples and then needing to debug them. Here's how we actually choose levels for production firmware on STM32L4/STM32H7 platforms.

RDP-0 — open, debug-friendly, not for production

JTAG/SWD fully open, flash readable. We use this only on bring-up benches. Any board leaving the lab in this state is a leak waiting to happen.

RDP-1 — debug locked, flash erase-on-regression

Reading flash via JTAG returns 0xFF. Switching back to RDP-0 mass-erases user flash. This is our default for industrial products where the threat model says "casual cloner with off-the-shelf tools." A determined attacker can still glitch the boot ROM and dump flash in roughly 24–48 engineering hours — public papers have documented this on multiple STM32 families.

RDP-2 — irreversible lockout

Permanent. JTAG dead forever. Bootloader patched out. The factory-programming station has exactly one shot, and any production-line glitch costs you the part. We reserve this for medical and defence builds where IP value exceeds the support cost of a higher RMA rate.

Option bytes we set alongside RDP

  • WRP on the bootloader region (sectors 0–1 typically). Prevents in-application code from overwriting itself.
  • PCROP on cryptographic constants and the public key store. Read-protected even from privileged code.
  • BOR level 3 — brown-out reset at 2.7V. Prevents partial writes during power transients that have caused field-failure rates of up to 0.4% in our pre-mitigation telemetry.
  • nBOOT_SEL = 1 and nBOOT0 = 1 — forces boot from main flash. Disables the System Memory bootloader, which is otherwise an unauthenticated entry point on many STM32 parts.

Document the option byte values in your factory programming script and version-control them next to the firmware. We've seen production runs where the firmware was correct and the option bytes were wrong — every unit shipped open.

Dual-Bank Layout and Anti-Rollback

Dual-bank flash isn't just an OTA convenience — it's the foundation of anti-rollback. The threat is straightforward: an attacker captures an old, signed firmware image with a known vulnerability, then pushes it to a fielded device. If your bootloader has no concept of "version monotonicity," the device accepts it and gets owned.

Layout we use on STM32H7

  1. Bank 1, sector 0 — immutable bootloader (~32 KB). RDP-protected, WRP-locked.
  2. Bank 1, sector 1 — boot configuration page (active-bank pointer, rollback counter, public key fingerprint).
  3. Bank 1, sectors 2–N — Slot A firmware image.
  4. Bank 2, sectors 0–N — Slot B firmware image.

The bootloader on cold boot: reads the active-bank pointer, validates the slot's signature against the public key, compares the image's version counter against the on-chip rollback counter, and only then jumps. If signature or version check fails, it falls back to the other slot and marks the failing slot for re-fetch.

The anti-rollback counter — store it carefully

The rollback counter cannot live in regular flash. A power-glitch during the write will leave it half-updated, and an attacker who can manipulate VCC can corrupt it deliberately. Options we've shipped:

  • OTP fuse bits on STM32H7 (32 fuses available) — irreversible increment, perfect semantically, but you have to be very careful in the field-update logic. One off-by-one and you've burned a fuse you can't get back.
  • External secure element (ATECC608A or NXP A71CH) — supports a monotonic counter primitive and survives glitching. Adds ~$0.40 BOM cost. This is our default for high-volume programmes.
  • Mirrored counter in two flash pages with a CRC and a "valid" sentinel — software-only, no extra BOM. Acceptable for low-threat models but vulnerable to determined glitching.

For a deeper look at how the OTA pipeline keeps the rollback counter consistent across power loss, see our robust OTA article — anti-rollback and OTA atomicity are the same problem viewed from two angles.

Signing Workflow and Key Management

The signature scheme is the easy part. ECDSA-P256 with SHA-256 is our default — fast on Cortex-M (under 40 ms for verify on STM32H7 with the crypto accelerator), well-supported, FIPS-aligned. RSA-2048 is fine if your team has existing infrastructure; it's just slower to verify (~150 ms) and uses more flash for the verification code.

What teams get wrong is the key management around the signature, not the signature itself. Here are the rules we hold to on every programme:

Production private keys live in an HSM, period

We use a YubiHSM-2 or AWS CloudHSM-backed signing pipeline. The private key never exists in plaintext on any developer laptop. CI builds upload the unsigned firmware to a signing service; the service signs and returns a binary blob. Developer workstation compromise leaks code, not keys.

Use a different key for dev, staging, and production

The dev key is checked into a private repo and used by every engineer. The staging key is HSM-backed but accessible to QA. The production key requires a two-person review on every signing operation. Each key has its own public-key fingerprint baked into a different bootloader build — so a leaked dev key cannot sign anything that runs on a customer device.

Plan for key rotation before you need it

The bootloader carries one production public key. If that key's private half ever leaks, every fielded device is permanently compromised unless you've planned ahead. Two patterns we use:

  • Multi-key bootloader — three production keys baked in, any of which is acceptable. Compromise key 1, rotate to key 2 in the next OTA, retire key 1 in the OTA after that.
  • Key-rotation manifest — the bootloader accepts a special signed manifest that adds a new authorised public key. The compromised key signs its own retirement before its compromise window closes.

Both have trade-offs in flash footprint and complexity. Pick one before tape-out, not after the first leak.

Validating the Secure-Boot Chain Before Production

Secure boot is hard to test in a way that resembles how it'll be attacked. A unit test that confirms "the bootloader rejects an unsigned image" doesn't tell you whether a power-glitch at the right instruction can skip the verification check. Real validation requires adversarial testing.

The test matrix we run before any production lock

  1. Tampered signature — flip one byte of the signature, verify the bootloader rejects and falls back. Run on 50 randomly tampered positions.
  2. Tampered firmware body — flip one byte mid-image, verify rejection. Important to confirm the hash covers the full image, not just the header.
  3. Downgrade attack — sign and present an older firmware version. Verify the rollback counter rejects it.
  4. Wrong-key signature — sign with the dev key, verify production bootloader rejects.
  5. Truncated image — chop the last 1 KB. Verify rejection.
  6. Power-glitch during verification — VCC glitching at 5, 10, 15, 20 ms after reset using a ChipWhisperer or similar. We've found three exploitable glitch windows on different STM32 families this way over the past four years.
  7. JTAG re-attach after RDP — confirm that triggering JTAG after RDP-1 actually mass-erases user flash and the recovery path is sane.
  8. Bootloader UART/USB recovery — confirm the recovery interface either is disabled in production option bytes or requires a separately signed recovery image.

One last thing — exit your factory with the firmware already in production state

The single most common failure mode we see isn't a cryptographic break — it's a unit that ships from the factory in RDP-0 because the test station ran out of memory and the operator skipped the last step. Make the RDP-lock step part of the final boundary scan, and reject any unit whose final RDP read doesn't return the expected value.

If you're staring at a half-finished secure-boot design and want a second pair of eyes before you flip RDP-2 on the line, send us the bootloader source — we'll review and red-team it within a working week.

Chat on WhatsApp