🛠 Secure boot et TrustZone-M sur RP2350 : signer son firmware sans se faire avoir
Objectives
The RP2350 is Raspberry Pi's first "mainstream" chip with a real security stack: extended system Arm TrustZone-M (peripherals, GPIO, and individual DMA channels assignable to Secure/Non-Secure domains, 8 SAU regions + 8+8 MPU regions per core), signed boot (SHA-256 + ECDSA secp256k1, public key fingerprint in 8 KB OTP, anti-rollback counter), encryption keys in OTP, hardware SHA-256 accelerator, TRNG, Redundancy Coprocessor (RCP), and glitch detector against fault injection (RP2350 datasheet, §10, §3.6.3, §12.12–12.13). This tutorial covers understanding the chain of trust, its two major trade-offs, and the order of operations — because OTP is irreversible.
Hardware
- 1 × RP2350 test board (OTP is one-way: never start with your "production" board)
- pico-sdk 2.x + SDK signing tools
- Key pair generated off-board, private key never stored on the final dev machine
The Chain of Trust
- Immutable Boot ROM: on each reset, it reads a signature descriptor in flash; if secure boot is disabled (default state), it boots anything — this is what makes drag-and-drop UF2 possible.
- Key fingerprint in OTP: enabling secure boot = burning your public key fingerprint into OTP. Any image not signed with the corresponding private key is rejected. There is no "off" switch for OTP: a lost key = no more firmware possible on the chip.
- Anti-rollback: the OTP counter prevents reverting to older versions (downgrade protection) — plan your versioning policy BEFORE burning.
- TrustZone-M: SAU/MPU partitioning per core, and especially system granularity — you can put the USB controller in Non-Secure and your key in Secure. Beware of errata E3 on RP2350A (QFN-60):
GPIO_NSMASK0applies Non-Secure permissions from PADS to the wrong pins (the mapping ignores the QFN-60 pad remap, datasheet Appendix D.1.1) — re-read the errata before designing a Secure/Non-Secure partitioning on an RP2350A.
The Two Trade-offs to Know
- Secure boot ⇒ RISC-V disabled: signature verification is on the Cortex-M33 boot path; enabling SB forces Arm cores (datasheet §10). You choose between signing and ARCHSEL.
- Physical security has a price: the DEF CON 32 hacking challenge ($10k→$20k to read OTP) was won in January 2025 by 4 teams via laser fault injection on secure boot and focused ion beam OTP reading; Raspberry Pi published mitigations E20/E21/E24/E26 (bootrom for A3/A4 steppings). Buy recent silicon and account for RCP + glitch detector in your threat model.
Expected Verification
On the test board: signed image boots, image modified by one byte is rejected (status LED or bootrom return code signals this).
Common Mistakes
- Burning the key fingerprint on the board you want to keep, without a private key backup: guaranteed brick upon key loss.
- Testing secure boot on an A2 stepping: errata E20/E21/E24/E26 (fault injection mitigations) are only fixed in A3/A4 — silicon matters.
- Forgetting errata E3 (QFN-60) and believing your PADS partitioning is correct on RP2350A.
- Confusing secure boot (authenticity) with encryption (confidentiality): signed boot prevents unauthorized firmware, not reading your flash via XIP — the RP2350 does not encrypt XIP flash by default.
- Ignoring terms like "PUF" or "TRUSTED" pin found in some blogs:
- Neglecting other bootrom errata (E13 invalid image blocks boot, E18 invalid ECC pattern in OTP partition field = bricked boot): on A2, a malformed OTP write can kill the chip — double-check every word before writing.
- Thinking TrustZone protects against physically connected attacks without RCP or glitch detector enabled: both are peripherals to configure, not magic.
Other tutorials for this board
- Flasher MicroPython sur une carte RP2350 générique et faire clignoter la première LED
- Console série sur RP2350 : USB CDC natif et UART0 de secours
- Lire l'ADC 12 bits et le capteur de température interne du RP2350
- Exploiter les 3 blocs PIO et 12 machines d'état du RP2350 (avec IRQ dédiées)
- Pico SDK 2.x sur une carte RP2350 générique : CMake, board header et PICO_BOARD
- Basculer les cœurs de Arm Cortex-M33 à Hazard3 RISC-V avec ARCHSEL
Code examples for this board
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython