🛠 Secure boot et TrustZone-M sur RP2350 : signer son firmware sans se faire avoir
Objectifs
Le RP2350 est la première puce « grand public » de Raspberry Pi avec une vraie pile sécurité : Arm TrustZone-M étendu système (périphériques, GPIO et canaux DMA individuellement assignables aux domaines Secure/Non-Secure, 8 régions SAU + 8+8 régions MPU par cœur), boot signé (SHA-256 + ECDSA secp256k1, empreinte de clé publique dans l'OTP 8 Ko, compteur anti-recul), clés de chiffrement dans l'OTP, accélérateur matériel SHA-256, TRNG, coprocesseur de redondance (RCP) et détecteur de glitchs contre l'injection de fautes (datasheet RP2350, §10, §3.6.3, §12.12–12.13). Ce tuto : comprendre la chaîne de confiance, ses deux gros compromis, et l'ordre des manipulations — parce que l'OTP est irréversible.
Matériel
- 1 × carte RP2350 de test (l'OTP est à sens unique : ne commence jamais par ta carte « de production »)
- pico-sdk 2.x + outils de signature du SDK
- Paire de clés générée hors carte, clé privée jamais stockée sur la machine de dev finale
La chaîne de confiance
- Boot ROM immuable : à chaque reset, il lit un descripteur de signature en flash ; si le secure boot est désactivé (état par défaut), il boote n'importe quoi — c'est ce qui rend le drag-and-drop UF2 possible.
- Empreinte de clé dans l'OTP : activer le secure boot = graver l'empreinte de ta clé publique dans l'OTP. Toute image non signée avec la clé privée correspondante est refusée. Il n'existe pas de « off » à l'OTP : une clé perdue = plus aucun firmware possible sur la puce.
- Anti-recul : le compteur OTP interdit de revenir en arrière (protection contre le downgrade) — prévois ta politique de version AVANT de graver.
- TrustZone-M : découpe SAU/MPU par cœur, et surtout la granularité système — tu peux mettre le contrôleur USB en Non-Secure et ta clé en Secure. Attention errata E3 sur RP2350A (QFN-60) :
GPIO_NSMASK0applique les permissions Non-Secure des PADS aux mauvaises broches (le mapping ignore le remap des pads QFN-60, datasheet Appendix D.1.1) — relis l'errata avant de concevoir un partitionnement Secure/Non-Secure sur un RP2350A.
Les deux compromis à connaître
- Secure boot ⇒ RISC-V désactivé : la vérification de signature est sur le chemin de boot Cortex-M33 ; activer SB force les cœurs Arm (datasheet §10). Tu choisis entre signature et ARCHSEL.
- La sécurité physique a un prix : le challenge de hacking DEF CON 32 ($10k→$20k pour lire l'OTP) a été remporté en janvier 2025 par 4 équipes via injection de fautes laser sur le secure boot et lecture OTP par faisceau d'ions focalisés ; Raspberry Pi a publié les mitigations E20/E21/E24/E26 (bootrom des steppings A3/A4). Achète du silicium récent et tiens compte du RCP + détecteur de glitchs dans ton threat model.
Vérification attendue
Sur la carte de test : image signée bootée, image modifiée d'un octet refusée (la LED de statut ou le code retour bootrom le signale).
Erreurs fréquentes
- Graver l'empreinte de clé sur LA carte qu'on veut garder, sans backup de clé privée : brique garantie à la perte de clé.
- Tester le secure boot sur un stepping A2 : les errata E20/E21/E24/E26 (mitigations injection de fautes) ne sont corrigés qu'en A3/A4 — le silicium compte.
- Oublier l'errata E3 (QFN-60) et croire ton partitionnement PADS correct sur RP2350A.
- Confondre secure boot (authenticité) et chiffrement (confidentialité) : le boot signé empêche le firmware non autorisé, pas la lecture de ta flash par XIP — le RP2350 ne chiffre pas le flash XIP par défaut.
- Ignorer les termes « PUF » ou broche « TRUSTED » qu'on lit dans certains blogs :
- Négliger les autres errata bootrom (E13 image invalide bloque le boot, E18 motif ECC invalide dans le champ partition OTP = boot brické) : sur A2, une écriture OTP mal formée peut tuer la puce — re-vérifie chaque mot avant d'écrire.
- Penser que TrustZone protège du physiquement connecté sans RCP ni détecteur de glitchs activés : les deux sont des périphériques à configurer, pas des magies.
Autres tutoriels pour cette carte
- 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
Exemples de code pour cette carte
clignotante.pyPythonbouton-interruption.pyPythonpwm-servo.pyPythonlecture-adc.pyPythonneopixel.pyPythonoled-i2c.pyPython