Secure boot is the foundational security control for connected devices. Without it, anyone with physical access to the device can replace the firmware with malicious code, and any vulnerability in the OTA update mechanism can be exploited to push unauthorized software. With secure boot, the device will only execute firmware that has been cryptographically authorized by the manufacturer — making unauthorized firmware execution effectively impossible without the private signing key.
Implementing secure boot correctly is not trivial. It requires careful key management, a specific flash memory layout, a signing workflow integrated with the build pipeline, and hardware lockdown procedures that must be executed before devices leave the factory. This guide provides a complete, practical walkthrough.
How Secure Boot Works: The Verification Chain
Secure boot operates through a chain of trust where each stage verifies the next:
CPU Reset
→ Boot ROM executes (immutable, factory-programmed)
→ Verifies: Is the bootloader signature valid?
YES → Execute bootloader
→ Bootloader verifies: Is the application firmware signature valid?
YES → Jump to application
NO → Enter recovery/DFU mode, reject firmware
NO → Halt or enter secure recovery
The Boot ROM is the hardware root of trust — it is burned into the chip at manufacture and cannot be modified. The public key used by the Boot ROM for bootloader verification is stored in OTP (One-Time Programmable) fuses. This key was generated by the firmware signing system during the signing infrastructure setup and is programmed into each chip during manufacturing.
Key Generation and Management
The security of the entire system rests on the signing key. If the private signing key is compromised, an attacker can sign any firmware and it will execute on all deployed devices.
Key Generation
Generate the signing key pair on an air-gapped workstation or, ideally, inside a Hardware Security Module (HSM):
# Generate ECDSA P-256 key pair (recommended for MCU secure boot)
openssl ecparam -name prime256v1 -genkey -noout -out signing_key_private.pem
# Extract the public key
openssl ec -in signing_key_private.pem -pubout -out signing_key_public.pem
# Extract raw public key bytes for embedding in firmware
openssl ec -in signing_key_public.pem -pubin -outform DER | \
tail -c 64 > signing_key_public.bin
# Display as hex for OTP programming
xxd signing_key_public.bin
Key storage requirements:
- Private key: HSM (preferred), encrypted file on offline workstation (acceptable), never on build servers or source control
- Public key hash: Burned into MCU OTP fuses during manufacturing
- Backup: Encrypted backup of private key stored in geographically separate secure location
Key Rotation
Plan for key rotation before you need it. If the signing key is compromised or a cryptographic weakness is discovered in ECDSA P-256, you need a path to migrate the entire fleet to a new key. Common approaches:
- Key hierarchy: The OTP-burned key authorizes a secondary signing key, which can be rotated via a specially signed update. Only the root key requires OTP burning.
- Key revocation flag: A bit in OTP that, when set, makes the device require firmware signed by the key distributed with the next OTA update.
Flash Memory Layout for Secure Boot
A secure boot-compatible flash layout must accommodate multiple firmware images and metadata:
Flash Layout (STM32L5 example, 512 KB total):
┌─────────────────────────────────────────┐ 0x08000000
│ Bootloader (64 KB) │
│ - Contains verification code │
│ - Contains embedded public key │
│ - This region is WRITE-PROTECTED │
├─────────────────────────────────────────┤ 0x08010000
│ Firmware Slot A (192 KB) │
│ - Active firmware image │
│ - Preceded by header with signature │
├─────────────────────────────────────────┤ 0x08040000
│ Firmware Slot B (192 KB) │
│ - Pending update image │
│ - Bootloader verifies before swap │
├─────────────────────────────────────────┤ 0x08070000
│ Secure Storage (16 KB) │
│ - Device certificate │
│ - Anti-rollback counter │
│ - Configuration flags │
└─────────────────────────────────────────┘ 0x08080000
The dual-slot (A/B) layout enables atomic updates: the new firmware is written to the inactive slot, verified, then swapped on next boot. If verification fails, the active slot remains unchanged.
MCUBoot: Open-Source Secure Bootloader
MCUBoot is the most widely used open-source secure bootloader for embedded systems. It is the reference bootloader for Zephyr RTOS, Nordic nRF Connect SDK, and NXP MCUXpresso. It supports:
- ECDSA P-256 and RSA-2048 firmware signature verification
- AES-256-CTR firmware encryption (protects firmware confidentiality during OTA delivery)
- Anti-rollback using a monotonic counter stored in flash
- Dual-slot (A/B) and overwrite update modes
- Encrypted key slots for secure key storage

MCUBoot Integration (Zephyr/Nordic nRF)
- Add MCUBoot as a secure bootloader:
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="signing_key_private.pem"
CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
- Build and sign the application:
west build -b nrf5340dk_nrf5340_cpuapp application/
# west automatically signs the image using the configured key
- Verify the signed image header:
imgtool verify --key signing_key_public.pem build/zephyr/zephyr.signed.bin
- Check anti-rollback version:
# In the application CMakeLists.txt
CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS="--version 2.0.0"
# MCUBoot refuses images with version < minimum confirmed version
STM32 Secure Boot: STM32L5/STM32H5
For STM32-based designs, ST provides hardware-based secure boot through STM32CubeProtect and the built-in Secure Boot and Secure Firmware Update (SBSFU) middleware.
The STM32L5 uses TrustZone to create a secure world where the bootloader runs with full access to flash and peripherals, and a non-secure world where the application executes with restricted access. The bootloader verifies the application’s signature before granting it execution rights.
Key steps for STM32L5 SBSFU setup:
- Configure the STM32L5 product state via STM32CubeProgrammer
- Set TZEN=1 (TrustZone enabled) in TZEN option byte
- Program the signing public key hash into HASH_REF option bytes
- Lock the bootloader flash region with SECWM (Secure Write-protection Memory)
- Set RDP (Read Protection) Level 2 to prevent bootloader extraction
Anti-Rollback Protection
Anti-rollback prevents an attacker from installing an old, vulnerable firmware version after a security patch has been deployed. Implementation uses a security counter — a monotonically increasing value in OTP or secure flash that defines the minimum acceptable firmware version:
// In bootloader: check anti-rollback before installation
bool check_anti_rollback(const image_header_t* header) {
uint32_t min_version = secure_storage_read_security_counter();
if (header->security_counter < min_version) {
// Reject: this image is older than the minimum acceptable version
LOG_ERR("Anti-rollback check failed: image counter %d < minimum %d",
header->security_counter, min_version);
return false;
}
return true;
}
// After successful install: update the minimum version counter
void commit_security_counter(uint32_t new_counter) {
// Write-once: counter can only increase
if (new_counter > secure_storage_read_security_counter()) {
secure_storage_write_security_counter(new_counter);
}
}
Hardware Lockdown Before Shipping
These steps must be executed for every device unit before it leaves the factory:
- Flash the bootloader with signature verification enabled and write-protection set on the bootloader region
- Program the public key hash into OTP fuses (or HASH_REF option bytes for STM32)
- Set read protection (STM32 RDP Level 1 or 2) to prevent flash readback
- Disable debug port (lock JTAG/SWD):
CONFIG_DISABLE_JTAG_DEBUG=yin Zephyr, or via STM32 option bytes - Verify the configuration: Use a production test to confirm that unsigned firmware is rejected and debug port is locked
These steps should be part of an automated production test script that logs results for each unit, providing an audit trail of security configuration.
For the broader IoT security context, see our IoT security best practices guide and the IoT Security Foundation guidelines. NIST SP 800-193 provides the authoritative framework for platform firmware resilience.
Conclusion
Secure boot is the cornerstone of IoT device security. Implementing it correctly requires careful attention to the full chain: key generation and storage, bootloader verification logic, flash layout, anti-rollback protection, and hardware lockdown. Each step is important; omitting any one creates an exploitable gap.
The good news: open-source bootloaders like MCUBoot and vendor-provided solutions like STM32 SBSFU handle most of the implementation complexity. The key engineering work is in integrating these tools into your build and production workflow, and in establishing the signing key management processes that protect the root of trust.
UABit’s firmware and embedded development team has implemented secure boot on STM32, Nordic nRF, and NXP platforms for products in healthcare, industrial, and consumer markets. If you need help designing or implementing a secure boot system, our security-focused embedded engineers are ready to help.
IoT & AIoT Weekly
Get the best IoT development content delivered weekly. No noise, just signal.