Hardware Security Modules on MCUs: Secure Boot, Key Storage, and TrustZone in Practice
Introduction
For a decade the prevailing assumption in deeply embedded design was that physical access ends the security discussion. Regulation has erased that assumption: the EU Cyber Resilience Act, IEC 62443, ETSI EN 303 645, and the FDA's premarket cybersecurity guidance now make verified boot, protected keys, and update authenticity baseline requirements rather than differentiators. The result is that security primitives once confined to smartcards and dedicated HSMs (Hardware Security Modules) have migrated into mainstream Cortex-M parts costing under two dollars.
The engineering problem is that these primitives are heterogeneous, partially overlapping, and individually defeatable. A "secure" MCU is a collection of mechanisms — immutable boot ROM, OTP fuses, crypto accelerators, isolation hardware — each with a distinct threat model and a distinct failure mode. This post examines what is genuinely on offer, where each vendor draws the trust boundary, and how those boundaries are broken in practice.
The three primitives, precisely defined
Before comparing silicon, it helps to separate three commonly conflated mechanisms.
- Secure boot establishes a chain of trust: an immutable boot ROM verifies a signature (typically ECDSA-P256 or RSA-2048/3072) over the first mutable stage before executing it, and each stage verifies the next. Its job is authenticity and integrity, not confidentiality.
- Key storage protects the secrets that everything else depends on — boot verification roots, device identity keys, TLS credentials. The spectrum runs from on-die OTP/eFuse, through key-wrapping by a hardware unique key (HUK), to fully isolated secure elements where the private key never leaves the die.
- Isolation (TrustZone-M, MPU, privilege levels) partitions a running system so that compromise of non-secure firmware does not leak secure assets.
These are orthogonal. TrustZone without secure boot protects nothing, because an attacker simply replaces the secure-world image. Secure boot without protected keys is theatre, because the verification root can be read or overwritten.
ARM TrustZone-M in practice
TrustZone for Armv8-M (Cortex-M23/M33/M55/M85) differs fundamentally from the Cortex-A variant: there is no secure monitor and no world-switch via a dedicated instruction. Instead, security state is tied to the memory map. The SAU (Security Attribution Unit) and an implementation-defined IDAU partition address space into Secure, Non-Secure, and Non-Secure-Callable (NSC) regions. Transitions are implicit on branch: calling into an NSC region containing an SG (Secure Gateway) instruction switches the core to secure state.
The practical consequence is that the entire API surface between worlds is a set of veneers, and every one of them is attack surface:
// Secure-side entry veneer, compiled with -mcmse (TrustZone-M)
// Placed by the linker in a Non-Secure-Callable region.
__attribute__((cmse_nonsecure_entry))
int32_t sign_payload(uint8_t *buf, size_t len)
{
// CRITICAL: validate that the non-secure caller's pointer
// actually lies in non-secure memory before dereferencing it.
// Skipping this lets NS code read/write Secure RAM by proxy.
if (cmse_check_address_range(buf, len, CMSE_NONSECURE | CMSE_MPU_READWRITE) == NULL)
return -1; // reject forged pointer
return crypto_ecdsa_sign(buf, len); // secret key never leaves Secure world
}
The cmse_check_address_range check is the most common omission in real codebases: a secure function that trusts a caller-supplied pointer becomes a confused-deputy primitive that exfiltrates secure RAM. TrustZone-M moves the trust boundary onto the developer's discipline, not away from it.
Vendor landscape
Implementations diverge sharply in where keys live and who anchors the root of trust.
| Vendor / family | Isolation | Root of trust | Key storage | Notable use case |
|---|---|---|---|---|
| ST STM32L5/U5/H5 | TrustZone-M | Boot ROM (RSS), option bytes | OTP + OBKeys, key-wrap by HUK | Industrial, metering, IEC 62443 |
| NXP LPC55S6x, RT5xx/6xx | TrustZone-M | ROM, PRINCE on-the-fly decrypt | PUF-derived keys (SRAM PUF) | Connected appliances, edge AI |
| NXP i.MX RT1180 | TrustZone-M + EdgeLock Enclave | Dedicated security subsystem | Isolated, CAAM-class | Gateways, functional safety |
| Microchip SAM L11 | TrustZone-M | Boot ROM | Limited on-die | Cost-sensitive sensing |
| Microchip + ATECC608 | external SE | SE-anchored | Secure element, key never exported | Provisioned identity, accessory auth |
| Silicon Labs EFR32 (Secure Vault) | TrustZone-M | Secure Engine subsystem | PUF-wrapped, anti-tamper | Wireless/Matter, Zigbee, BLE |
| Espressif ESP32-S3/C-series | no TrustZone | Boot ROM, eFuse | eFuse keys + flash encryption | Consumer IoT, Wi-Fi |
| Infineon PSoC 64 / OPTIGA | TrustZone-M / external SE | TFM / OPTIGA | OPTIGA Trust M secure element | Cloud onboarding, certificate store |
| Renesas RA (Cortex-M33) | TrustZone-M + RSIP/SCE | MCUboot / FSP | Wrapped keys, SCE engine | General-purpose secure designs |
A few patterns deserve emphasis. SRAM PUF (NXP, Silicon Labs) derives a device-unique key from the random power-up state of uninitialised SRAM, conditioned with a fuzzy extractor. Nothing secret is stored at rest, which removes the "read the fuses" attack — but it adds enrollment and helper-data integrity concerns. Secure elements (ATECC608, OPTIGA, SE05x) take the opposite stance: a separate certified die (often Common Criteria EAL5+/6+) holds the private key and exposes only sign/verify/ECDH operations over I²C. This is the strongest key-confidentiality posture available to a hobbyist-grade MCU, at the cost of a second component and a bus that itself must be authenticated.
Other hardware mechanisms worth designing in
- Discrete TPM 2.0 (Infineon SLB9670, ST ST33): a standardised, certified key store and measured-boot anchor when the MCU lacks an internal secure subsystem. Heavier and slower than an SE, but interoperable with TCG tooling.
- Memory protection beyond TrustZone: even non-secure firmware should run an MPU with privileged/unprivileged split. TrustZone protects the secure asset; the MPU contains the blast radius inside the non-secure world.
- Debug lockdown and lifecycle states: JTAG/SWD must be permanently closed (ST RDP Level 2, Espressif eFuse disable, lifecycle "closed/locked" states) once provisioned. This is frequently the single largest real-world hole.
- Anti-tamper and active shields: voltage/clock/temperature monitors and tamper pins that zeroise keys on intrusion — present in Secure Vault and TPMs, absent on commodity parts.
Vulnerabilities by mechanism
Hardware security on MCUs is broken far more often by physics than by cryptography.
Fault injection / voltage and clock glitching. The dominant practical attack. A precisely timed power or clock glitch can skip the conditional branch that enforces a readout-protection level or a signature-comparison result. Numerous academic and conference results have demonstrated downgrading STM32 readout protection (RDP Level 2 → Level 1) and bypassing secure-boot signature checks across multiple vendors using sub-$1000 setups. Mitigations are defensive coding (redundant checks, random delays), but the boot ROM — being immutable — cannot be patched if it is the vulnerable stage.
Side-channel analysis (DPA/CPA/EM). Power and electromagnetic correlation attacks recover AES and ECC keys from unprotected crypto accelerators. Vendors counter with masking, constant-time implementations, and shielding (Secure Vault advertises DPA countermeasures); commodity software crypto on a bare MCU offers none.
Logical / boundary flaws. TrustZone's confused-deputy class (the missing cmse_check_address_range above), TOCTOU on shared buffers, and secure-world parsers exposed to attacker-controlled input. These require no equipment and scale infinitely once found.
Provisioning and supply chain. Keys injected at manufacturing, helper data for PUFs, and the secure-element pairing secret are all exposed during production. A contract manufacturer with debug access at provisioning time can clone identities regardless of the runtime security posture.
The unifying lesson: the strongest mechanism a part offers is irrelevant if a weaker one (open debug port, glitchable ROM, unmasked accelerator) sits on the same attack path.
Conclusion
Hardware security on MCUs is now table stakes, but it is a defence-in-depth exercise, not a checkbox. The practical decision tree:
- Use on-die TrustZone-M + secure boot + RDP/lifecycle lockdown for the common case: protecting firmware authenticity and isolating a TLS stack against remote attackers. This is sufficient when the threat model excludes a funded, physically present adversary.
- Add a certified secure element or PUF-based key store when device identity must survive cloning attempts, or when regulation (medical, automotive, payment) demands certified key confidentiality.
- Add anti-tamper, DPA-hardened crypto, and a discrete TPM/SE only when the attacker is assumed to have unlimited physical access and budget — at which point cost and BOM complexity rise sharply.
What hardware security on a commodity MCU does not do is resist a determined fault-injection adversary against an immutable, unhardened boot ROM. If your threat model includes that attacker, you need either a vendor part with explicitly glitch-hardened ROM and active anti-tamper, or a secure element that keeps the key off the application die entirely. Specify the threat model first; the silicon choice follows from it, not the reverse.