Photon-Emission-Guided Laser Fault Injection maakt Secure Debug op RP2350 mogelijk
- Door middel van photon-emission microscopy konden we een register lokaliseren dat verantwoordelijk is voor het inschakelen van debug-functies op de microcontroller van Raspberry Pi.
- Laserpulsen op twee nabijgelegen posities herstelden vervolgens de toegang van de debugger tot de 'Secure world' van de chip, ook al was debuggen permanent uitgeschakeld.
- Door deze toegang te gebruiken na een rescue reset, konden we een geheim uit het one-time-programmable (OTP) geheugen herstellen. De reset stopte de chip voordat de firmware de runtime-lock kon toepassen, waardoor de pagina leesbaar bleef voor Secure-toegang.
- De aanval vereist fysieke toegang, destructieve voorbereiding en laboratoriumapparatuur ter waarde van ongeveer $250.000.
Het beveiligingsmodel van de RP2350
De RP2350 is een dual-core microcontroller van Raspberry Pi: elke processor-socket kan bij het opstarten kiezen tussen een Arm Cortex-M33 of een RISC-V Hazard3 core. De hardwarematige beveiligingsfuncties omvatten:
- Secure boot: authenticeert ondertekende firmware aan de hand van public-key fingerprints die zijn geprovisioneerd in het One-Time Programmable (OTP) geheugen.
- Armv8-M TrustZone: scheidt de Secure- en Non-secure uitvoeringsstatussen.
- Permanente debug-disable instellingen.
- Glitch-detectoren: bedoeld om timing-verstoringen te detecteren die worden veroorzaakt door manipulatie van de klok of de voeding.
Raspberry Pi heeft onderzoekers actief uitgenodigd om deze beschermingen te evalueren via de RP2350 Hacking Challenges. De eerste challenge liep van augustus tot december 2024 tegen de originele chip. Nadat verschillende bevindingen waren verholpen, bracht Raspberry Pi de A4-revisie uit—de versie die wij hebben getest.
De permanente beveiligingsconfiguratie en de fingerprints van de public key voor het opstarten zijn opgeslagen in OTP-geheugen: elke bit kan één keer van 0 naar 1 worden omgezet en nooit meer terug, waardoor alles wat daar wordt geschreven voor de levensduur van de chip behouden blijft.
OTP is georganiseerd in pagina's van 128 bytes, beschermd door twee persistente (harde) lock-rijen:
- Voor pagina $n$ configureert
PAGEn_LOCK0optionele lees- en schrijfsleutels en het gedrag wanneer er geen sleutel wordt ingevoerd. PAGEnLOCK1bevat de door hardware afgedwongenLOCKSenLOCK_NSpermissies. Deze statussen kunnen verschuiven van read-write naar read-only of ontoegankelijk, maar kunnen nooit permissiever worden.
Het OTP-subsystem gebruikt redundante coderingen voor beveiligingsgerelateerde velden: kritieke vlaggen zijn "gecodeerd met een three-of-eight vote over acht opeenvolgende OTP-rijen", en OTP-lockbits zijn "triple-redundant met een majority vote", volgens het RP2350-datasheet.
Bij een OTP-reset initialiseren de persistente LOCKS en LOCKNS waarden een runtime-lock per pagina, ook wel een soft lock genoemd. Firmware kan deze lock verder aanscherpen tot de volgende OTP-reset, maar kan hem niet versoepelen. De runtime-wijziging overleeft die reset niet.
Een externe debugger communiceert met de RP2350 via de Serial Wire Debug (SWD) interface van Arm. Verzoeken bereiken eerst de Serial Wire Debug Port (SW-DP) en worden vervolgens gerouteerd naar toegangspoorten. In de gebruikte Cortex-M33 configuratie heeft elke core een memory access port (Mem-AP) die is verbonden met de systeembus; een ingeschakelde Mem-AP stelt de debugger in staat om toegestaan geheugen en randapparatuur te lezen en te schrijven. Een aparte, altijd actieve toegangspoort, de RP-AP, biedt een kleine set reset- en recovery-bedieningen.
Secure debug verwijst naar Mem-AP toegang met Secure-attributie. De debugger kan dan transacties uitvoeren met Secure memory-mapped resources die de toegangscontrollogica toestaat, en een core die in de Secure-status draait, pauzeren of inspecteren.
De permanente CRIT1.DEBUG_DISABLE vlag is bedoeld om dit pad te sluiten. Wanneer deze is ingesteld, worden de enable-signalen voor de Mem-AP's van beide cores naar nul gedreven, wat "voorkomt dat de AP's überhaupt bus-toegangen uitvoeren", en schakelt het factory-test JTAG-interface en de toegangspoort van de RISC-V debugmodule uit. De SW-DP en RP-AP reageren nog steeds, maar geen enkele core Mem-AP kan de systeembus benaderen.
Er is echter een override: het memory-mapped DEBUGEN register stelt Secure software in staat om de Mem-AP van elke core opnieuw in te schakelen en, apart daarvan, Secure-toegang daardoor toe te staan. Het datasheet vermeldt dat DEBUG_DISABLE "volledig kan worden overruled door alle bits van dit register in te stellen".
Deze kritieke override in de handhavingsketen maakte de debug-interface tot ons doelwit. Toegang krijgen tot Secure debug op een Mem-AP is een algemeen bruikbare primitieve om Secure-geheugen te lezen en schrijven, een core te pauzeren en stap-voor-stap uit te voeren, en de registers ervan te inspecteren. De vraag is of dat register door een fault (fout) kan worden ingesteld.
Experimentele opstelling
Doelconfiguratie
De RP2350 Hacking Challenge van Raspberry Pi vroeg deelnemers om een 128-bit geheim te extraheren dat in OTP1 is opgeslagen. Bij het opstarten zorgt de ondertekende challenge-firmware ervoor dat pagina 48 de verwachte persistente lock heeft, en past vervolgens een runtime-lock toe die zowel Secure als Non-secure toegang tot het geheim weigert tot de volgende OTP-reset.
We hebben deze door de leverancier gedefinieerde configuratie gereproduceerd op ons eigen revisie A4-apparaat:
- De SHA-256 fingerprint van onze public key in
BOOTKEY0geprogrammeerd. BOOTFLAGS1.KEYVALIDop0x1enBOOTFLAGS1.KEYINVALIDop0xegezet.- Secure boot ingeschakeld (
CRIT1.SECUREBOOTENABLE = 1). - Debug permanent uitgeschakeld (
CRIT1.DEBUG_DISABLE = 1). - De glitch-detectoren ingeschakeld op maximale gevoeligheid (
CRIT1.GLITCHDETECTORENABLE = 1,CRIT1.GLITCHDETECTORSENS = 3). - De persistente locks voor pagina 1 en 2 geconfigureerd volgens de challenge-configuratie.
- De persistente lock voor pagina 48 ingesteld op
PAGE48LOCK1 = 0x3c3c3c, wat Non-secure toegang weigerde (LOCKNS = INACCESSIBLE) terwijl Secure read-write toegang behouden bleef (LOCKS = READWRITE).
Omdat secure boot alleen de Cortex-M33 cores toestaat, werden voor deze experimenten beide processor-sockets op Arm ingesteld.
Voorbereiding van het monster en de testbank
Het apparaat werd aan de achterzijde gedecapsuleerd (backside decapsulation), zodat infrarood licht de transistoren bereikt via het silicium substraat in plaats van geblokkeerd te worden door de metaallagen aan de voorzijde. De chip werd vervolgens teruggesoldeerd op een daughterboard verbonden met Scaffold, het open-source platform van Ledger Donjon voor het aansturen en monitoren van apparaten onder test. Het verwijderen van het lead frame aan de achterzijde van de chip verbreekt de GND-verbinding; een koperdraad herstelt deze verbinding.
DEBUGEN: het overriden van de permanente debug-disable
DEBUGEN heeft vijf functionele bits:
| Bit | Naam | Effect |
|---|---|---|
| 0 | PROC0 | Schakelt de memory access port van core 0 in |
| 1 | PROC0_SECURE | Staat Secure-toegangen toe via de memory access port van core 0 |
| 2 | PROC1 | Schakelt de memory access port van core 1 in |
| 3 | PROC1_SECURE | Staat Secure-toegangen toe via de memory access port van core 1 |
| 8 | MISC | Schakelt aanvullende debugcomponenten in, inclusief de cross-trigger interface en de RISC-V debug access port |
Secure debug op een core vereist beide bijbehorende bits: de bit die de Mem-AP inschakelt, en de bit die Secure-toegang daardoor toestaat.
In tegenstelling tot de redundante codering die wordt gebruikt voor OTP-beveiligingsvelden, vermeldt het datasheet geen bit-redundantie, pariteit of majority vote voor DEBUGEN. We hebben daarom getest of laserpulsen de DEBUGEN-bits op het beveiligde apparaat konden instellen.
Lokalisatie via photon-emission
Die test vereist eerst dat we weten waar we moeten mikken. Het instellen van een individuele DEBUGEN-bit betekent dat we een enkele register-bit moeten raken—een speld in een hooiberg. Dit is een moeilijker target-probleem dan de instruction-skip faults die gebruikelijk zijn bij laser fault injection (LFI), waarbij het verstoren van een van de vele flip-flops in een core-pipeline hetzelfde resultaat kan geven. Een blinde scan voor één DEBUGEN-bit is onpraktisch.
Schakelende transistoren zenden zwakke nabij-infrarood fotonen uit die gecorreleerd zijn met hun activiteit. Door deze emissie te verzamelen over herhaalde uitvoeringen, kan worden onthuld waar een geselecteerde controle van status verandert. Dit maakte photon-emission microscopy (PEM) zeer geschikt voor DEBUGEN: als een memory-mapped register kan Secure software exacte bits in een loop toggelen, wat de herhaalde statuswijzigingen veroorzaakt die voor de meting nodig zijn. We gebruikten dit als eerste lokalisatiefase, en de resulterende kaart beperkte de daaropvolgende laserscan tot een gebied van enkele micrometers.
We vergeleken loops die geselecteerde DEBUGEN-bits herhaaldelijk aan- en uitzetten, waarbij alleen de doelbits verschilden. Omdat de emissie van een register zwak is ten opzichte van de ruis van de camera en gevoelig voor langzaam driftende omgevingsfactoren zoals temperatuur, onthult één enkel frame niets. Het middelen van veel frames van elke loop onderdrukte willekeurige sensorruis, en het aftrekken van de twee gemiddelde stacks elimineerde alles wat de loops gemeen hadden: statische achtergrond, sensor-offset, thermische emissie en schakelingen die niet gerelateerd waren aan de geselecteerde bits. Door de twee waarden tijdens de acquisitie af te wisselen, werd voorkomen dat langzame drift de aftrekking beïnvloedde. Wat overbleef was de emissie die de geselecteerde bits volgde.
Herhaalde vergelijkingen over verschillende bitmasks legden compacte locaties bloot die geassocieerd waren met DEBUGEN-bits 0–3 over drie regio's van het cameraveld. Deze zones tonen schakelactiviteit geassocieerd met elke DEBUGEN-bit; ze identificeren niet direct de opslagcellen. De meerdere hotspots die voor elke bit werden waargenomen, kunnen voortkomen uit het opslagelement of uit gerelateerde logica. Zonder layout-data kunnen we het onderscheid niet maken. Deze zones verminderen echter aanzienlijk de zoekruimte.
Bevinding 1 — faulting van DEBUGEN geeft Secure debug
Voor de laser fault injection (LFI) gebruikten we een gepulseerde laser op 980 nm met een maximale optische kracht van 2,97 W, bedreven op ongeveer 40% (ca. 1,2 W), met een pulsbreedte van 100 ns via een 50x objectief. Na elke puls controleerden we de debug-toegangspoorten via SWD.
Binnen het gebied dat via PEM was gevonden, voerden we een LFI-scan uit en gebruikten we de SWD-feedback om twee responsieve posities te kalibreren die enkele micrometers uit elkaar lagen. Op de ene positie schakelden pulsen de bus-toegang via de Mem-AP van core 1 in, wat erop wees dat PROC1 was ingesteld. Op de andere positie rapporteerde het Control/Status Word van de Mem-AP SDeviceEn = 1, een status-gestuurd signaal dat PROC1_SECURE waarschijnlijk was ingesteld. We controleerden beide indicatoren na elke puls.
Een puls die één bit instelde, kon de andere wissen, dus het instellen van beide vereiste een iteratieve sequentie. Ons script pulseerde de PROC1-positie totdat bus-toegang beschikbaar was, en pulseerde vervolgens de PROC1_SECURE-positie totdat SDeviceEn = 1, waarbij telkens werd teruggekeerd naar de eerste positie wanneer de bus-toegang verloren ging. Eenmaal gekalibreerd, schakelde de sequentie binnen enkele seconden Secure debug in. Interessant genoeg konden we deze sequentie niet reproduceren met een 20x objectief. Omdat de twee posities slechts enkele micrometers uit elkaar liggen, raakte die bredere spot waarschijnlijk zowel de regio die een bit instelt als de regio die hem wist.
Zodra beide bits waren ingesteld, bleven ze dat zonder verdere pulsen of software-schrijfacties. Het lezen van het Secure-only DEBUGEN register via de Mem-AP van core 1 gaf vervolgens 0xc terug; omdat DEBUGEN Secure-only is, bevestigt deze succesvolle leesactie dat de transactie Secure-attributed was.
Het inschakelen van Secure-toegang via de Mem-AP van core 1 stelt de debugger in staat om memory-mapped resources te lezen en schrijven waarvan de ACCESSCTRL-permissies de debugger als busmanager accepteren en waarvan de target-specifieke controles Secure AHB-transacties toestaan. Onafhankelijk van deze directe leesacties kan de debugger de core pauzeren en stap-voor-stap uitvoeren, en de registers ervan inspecteren of wijzigen, wat de TrustZone runtime-isolatie compromitteert via Secure-core-gemedieerde extractie. Dit zorgt er niet voor dat de boot ROM ongeauthenticeerde firmware accepteert: wanneer firmware normaal opstart, authenticeert secure boot deze nog steeds, maar kan de runtime-status niet beschermen die toegankelijk blijft voor de debugger na verificatie.
Toepassing op de Hacking Challenge-configuratie
De beschreven Secure-attributed Mem-AP toegang legt de Secure runtime-status bloot, maar de runtime-lock van pagina 48 in de challenge voorkomt nog steeds toegang tot het geheim nadat de firmware is uitgevoerd. De persistente lock van de pagina, PAGE48LOCK1 = 0x3c3c3c, weigert Non-secure leesacties maar laat LOCKS op READ_WRITE staan, waardoor deze leesbaar blijft via Secure-attributed toegang voordat de runtime-lock wordt aangescherpt.
Tijdens elke boot schrijft de firmware de meest restrictieve binaire waarde, 0b1111, naar de runtime-lock otphw->swlock[48]. Dat register maakt de pagina vervolgens ontoegankelijk voor zowel Secure als Non-secure toegang, inclusief Secure debug, en voorkomt dus dat Secure-transacties van de Mem-AP het geheim kunnen lezen.
Zoals gedocumenteerd worden software-locks "bij reset geïnitialiseerd vanuit de OTP lock-pagina's", en een schrijfactie wijzigt de status alleen "tot de volgende reset". Het resetten van het OTP-blok verwijdert 0b1111 en herstelt de waarde afgeleid van PAGE48LOCK1, waarvoor LOCKS = READ_WRITE geldt.
De resterende vraag is hoe een gelockte chip gereset kan worden zonder de firmware toe te staan de runtime-lock opnieuw toe te passen. De RP-AP blijft "altijd toegankelijk, zelfs wanneer externe debug is uitgeschakeld". Het instellen van CTRL.RESCUE_RESTART triggert een rescue reset: een volledige systeemreset die de boot ROM ook opdracht geeft om te pauzeren voordat er user-software wordt uitgevoerd.
De boot ROM controleert POWMANCHIPRESET.RESCUEFLAG vóór watchdog, flash of USB boot, wist deze, en houdt vervolgens core 0 in een interrupt-disabled wait loop en core 1 in het wait-for-vector pad. Het datasheet vermeldt geen restricties op CTRL.RESCUERESTART.
We gingen als volgt te werk:
- Rescue reset: Stel
CTRL.RESCUERESTARTin op 1, en zet deze vervolgens via de RP-AP terug naar 0. De chip reset en blijft in de boot-ROM wait paths. De ondertekende firmware wordt nooit uitgevoerd, dusswlock[48]wordt nooit aangescherpt en blijft op de permissieve waarde afgeleid vanPAGE48LOCK1(LOCKS = READ_WRITE). - Fault DEBUGEN naar 0xc: Terwijl beide cores in de boot-ROM wait paths staan, stellen we
PROC1enPROC1_SECUREin zoals hierboven beschreven; deze twee set bits produceren de waarde0xc. - Pauzeer core 1 via het Debug Halting Control and Status Register (DHCSR) over de nu Secure Mem-AP.
- Lees het geheim uit OTP-rijen
0xc08–0xc0fvia de guarded read interface.
We hebben deze sequentie uitgevoerd op het geteste apparaat en het volledige challenge-geheim hersteld.
DEBUGEN_LOCK voorkomt geen laser-geïnduceerde wijzigingen
DEBUGEN_LOCK blokkeert softwarematige schrijfacties naar de overeenkomstige DEBUGEN-bits: elke lock-bit is "Schrijf 1 om de [...] bit van DEBUGEN te locken. Kan niet worden gewist zodra deze is ingesteld". Het datasheet presenteert dit als een manier "om accidentele schrijfacties te voorkomen".
In tests waarbij de target DEBUGEN-bit op 0 stond en de lock-bit op 1, kon een puls DEBUGEN nog steeds instellen terwijl de lock op 1 bleef. Pulsen stelden ook lock-bits in, met of zonder een overeenkomstige wijziging in DEBUGEN. In succesvolle sequenties waren alle vijf de functionele lock-bits op 1 tegen de tijd dat PROC1 en PROC1_SECURE beide waren ingesteld. We zagen nooit een lock-bit terugkeren van 1 naar 0, waardoor een latere schrijfactie van DEBUGEN = 0 de uitgeschakelde status niet kan herstellen zodra de fault de overeenkomstige lock heeft ingesteld.
Limieten van softwarematige mitigaties
Zodra Secure-toegang via de Mem-AP is ingeschakeld, scheidt Secure-attributie alleen niet langer de debugger van de Secure-firmware. Deze toegang overschrijft geen harde OTP-locks of peripheral-specifieke controles. ACCESSCTRL kan directe debugger-manager transacties naar specifieke targets blokkeren, maar voorkomt op zichzelf niet dat een debugger die de Secure-core controleert, core-georigineerde toegangen veroorzaakt of geladen waarden extraheert via core-registers. Na een rescue reset keert ACCESSCTRL terug naar de standaardwaarden van de reset-tijd voordat firmware deze kan herconfigureren. ACCESSCTRL vermindert dus de directe Mem-AP blootstelling in plaats van een zelfstandige vertrouwelijkheidsgrens te vormen.
Firmware kan de post-boot blootstelling nevertheless verminderen door de debugger via ACCESSCTRL toegang tot gevoelige targets te weigeren, en vervolgens de debugger-bit in ACCESSCTRL.LOCK in te stellen zodat debugger-transacties die permissies niet kunnen heropenen. Secure firmware kan ook DEBUGEN periodiek controleren en bij een onverwachte waarde een fail-safe reset triggeren die het processor-cold reset domein wist. Deze maatregelen zijn best-effort runtime mitigaties: een ingeschakelde debugger kan de core pauzeren vóór de volgende controle, en een rescue reset stopt voordat firmware ACCESSCTRL kan configureren of de monitor kan draaien. Ze voorkomen dus niet de pre-firmware secret read die hier is gedemonstreerd.
De gedocumenteerde encrypted-boot flow van de RP2350 illustreert de pre-firmware beperking van runtime-locks en de post-boot beperking van debugger-manager filtering in twee verschillende machinetoestanden. Na een rescue reset pauzeert de boot ROM vóór decryptie: er bestaat nog geen plaintext payload, maar de decryptiesleutel kan direct leesbaar zijn als de persistente permissies van de OTP-pagina Secure-toegang toestaan en geen andere target-controle de transactie blokkeert. Na een normale encrypted boot bestaat plaintext in SRAM: directe Mem-AP leesacties hangen af van debugger-manager permissies in ACCESSCTRL, terwijl Secure-core controle core-gemedieerde extractie kan toestaan, zelfs wanneer directe leesacties worden geweigerd. Dit is een architecturale analyse, geen getest resultaat van encrypted-boot; encrypted boot beschermt externe flash nog steeds tegen offline inspectie.
Impact en vereisten voor de aanval
De gedemonstreerde sequentie biedt Secure-attributed geheugentoegang, controle over de Secure-world uitvoering, en toegang tot het challenge-geheim na het resetten van de runtime-paginalock. Het vereist de volgende middelen:
- Destructieve fysieke toegang: Backside decapsulatie wijzigt de behuizing permanent en laat de die blootliggen.
- Gespecialiseerde laboratoriumapparatuur: De volledige beschreven opstelling kost ongeveer $250.000.
- Expertise in hardwarebeveiliging: De procedure vereist monsterbereiding, die-navigatie, selectie van laserparameters, en gecoördineerde laserbesturing, positionering van de stage en SWD-meting.
Conclusie
De RP2350 codeert kritieke debug-disable vlaggen in OTP met redundante voting, maar DEBUGEN kan hun effect overriden en heeft geen equivalente bescherming in het datasheet. In onze experimenten veranderden laserpulsen DEBUGEN ondanks DEBUGEN_LOCK en konden een lock-bit instellen die voorkwam dat firmware de uitgeschakelde waarde herstelde. Apart daarvan herstelde de RP-AP rescue reset de runtime-paginalock van de challenge naar zijn persistente waarde, terwijl de uitvoering van user-firmware werd voorkomen. De software-zichtbare mechanismen voerden elk hun gedocumenteerde functie uit, maar hun interactie met de laser-fault maakte Secure debug en herstel van het challenge-geheim mogelijk.
Differentiële PEM isoleerde eerst de bit-afhankelijke DEBUGEN-activiteit, en LFI zette die ruimtelijke aanwijzing om in persistente Secure debug. De systeemles is dat beveiligingsanalyse het volledige handhavingspad moet bestrijken, van persistente OTP-configuratie tot aan mutabele control-registers en reset-gedrag, omdat systeembeveiliging afhangt van dat pad en niet van individuele mechanismen in isolatie.
Divulgatie en dankwoord
We hebben deze fault op 28 juli 2026 gemeld aan Raspberry Pi. We danken het Raspberry Pi-team voor hun betrokkenheid bij de discussies over de divulgatie en voor hun transparante aanpak van beveiligingsonderzoek.
Antoine Plin, Hardware Security Intern bij Ledger Donjon
***
Voetnoten
- https://github.com/raspberrypi/rp2350hackingchallenge De RP2350 Hacking Challenge repository, met de referentie lockdown-configuratie en firmware die we hebben gereproduceerd.
- Courk, Laser Fault Injection on a Budget: RP2350 Edition.
- De rescue check is stap 1 van het core 0 boot pad in
src/main/arm/varmbootpath.c; insrc/main/arm/arm8bootromrt0.Sgaatvarmwaitrescuenaar de interrupt-disabledvarmdeadquietWFI loop, terwijl core 1 in het wait-for-vector pad van de boot ROM blijft.
Groetjes,