Laser Fault Injection on a Budget: RP2350 Edition

Posted on Tue 14 January 2025 in Projects

Introduction

In August 2024, Raspberry Pi introduced the RP2350 microcontroller. This part iterates over the RP2040 and comes with numerous new features. These include security-related capabilities, such as a Secure Boot implementation.

A couple of days after this announcement, during DEFCON 2024, an interesting challenge targeted at these new features was launched: the RP2350 Hacking Challenge.

After some work and the development of a fully custom “Laser Fault Injection Platform”, I managed to beat this challenge and submitted my findings to Raspberry Pi.

This article will provide technical details about this custom platform, including manufacturing files for those interested in building their own. Additionally, I will explain how injecting a single laser-induced fault can bypass the Secure Boot feature of the RP2350.

Warning

The “Laser Fault Injection Platform” introduced in this article makes use of an infrared high-power laser source. Such a component can be hazardous; be careful if you attempt to reproduce this work.


Hacking Challenge & RP2350 Security Features

Objectives of the Challenge

The target of this challenge is a Pico 2 board, which hosts a RP2350 microcontroller. It must be configured according to the instructions provided in the challenge’s GitHub repository.

Following the instructions from the repository will:

  • Write “secret” data into one of the OTP areas of the RP2350.
  • Configure and enable the Secure Boot feature, locking the chip as much as possible. This includes disabling debug interfaces (SWD) and enabling various security features, such as glitch detectors.
  • Flash a signed firmware that primarily restricts even more access to the OTP area where the secret is stored.

The goal of the challenge is to find a way to recover the secret data, potentially bypassing the Secure Boot feature in the process.

Security Features

The Secure Boot feature is enforced by code contained in the Boot ROM of the RP2350. This code is hardened in several ways, going beyond software methods; the Boot ROM leverages hardware-specific features.

These features are primarily related to an innovative component called the “Redundancy Co-Processor.” Quoting the RP2350 Datasheet:

The redundancy coprocessor (RCP) is used in the RP2350 bootrom to provide hardware-assisted mitigation against fault injection and return-oriented programming attacks. This includes the following instructions:

  • generate and validate stack canary values based on a per-boot random seed
  • assert that certain points in the program are executed in the correct order without missing steps
  • validate booleans stored as one of two valid bit patterns in a 32-bit word
  • validate 32-bit integers stored redundantly in two words with an XOR parity mask
  • halt the processor upon reaching a software-detected panic condition

[…]

Each core’s RCP has a 64-bit seed value (Section 3.6.3.1). The RCP uses this value to generate stack canary values and to add short pseudorandom delays to RCP instructions.

Additionally, the RP2350 is capable of detecting fault injection attempts using glitch detectors. These configurable circuits respond to voltage or electromagnetic fault-injection attempts and reset the system. For this challenge, these detectors are set to their maximum sensitivity level.


Article Overview

Below is a brief, high-level summary of the article’s content.

Why choosing Laser Fault Injection

Considering that the Boot ROM of the RP2350 has been audited before the opening of the challenge, I did not attempt to find logic bugs in it and quickly considered a hardware attack, such as a fault injection attack.

However, online comments tend to show that the glitch detector system implemented in the RP2350 was rather efficient in mitigating simple voltage fault injection attacks.

Hence, I quickly decided to tackle the challenge with laser fault injection, assuming that focusing a laser beam away from the glitch detector circuits could allow for injecting faults without triggering them.

Now, the thing is, while I did have some experience with “classic” voltage fault injection attacks, I knew nothing about laser fault injections.

This challenge was then used as an opportunity to build a fully custom, cheap laser fault injection platform.

Note that while traditionally known to be expensive to implement, several “cheap” platforms aimed at injecting faults with a laser have emerged over the past few months:

Note

My mistake, after some research, I actually managed to find this presentation of the “RayV-Lite” introduced at Blackhat 2024. Their project presents various similarities with my “Laser Fault Injection Platform”, but also interesting differences. I’ll highlight some of these differences in this article and encourage you to check out their work.

Sample Preparation

The idea being LFI is reasonably simple. A focused laser beam is directed at the silicon die of the target component. Transistors are sensitive to photoelectric effects, meaning the emitted light can be enough to induce temporary faults or malfunctions. When precisely timed, these faults could be leveraged to bypass security features.

A major downside of such an attack compared to voltage or clock glitching is that the silicon die of the target has to be exposed. Of course, the circuit must still be able to operate normally after the die has been exposed.

Accessing the silicon can either be attempted from the top, or the bottom side of the packaged chip.

Simplified Top and Bottom Sides Render of a Packaged Integrated Circuit
Simplified Top and Bottom Sides Render of a Packaged Integrated Circuit

I chose to expose performed from the backside of the die. This choice has been made for two reasons:

  • Accessing the backside can be achieved with cheap mechanical tools. However, exposing the top of the die would have required chemicals I would rather not deal with, such as concentrated nitric acid.
  • Based on images available online, it seems the top of the die is fully covered by a metal layer, likely complicating fault injection.

The process I developed to expose the backside of the silicon die is detailed in the relevant sections of this article.

Die Imaging & Laser Focusing

LFI requires targeting with a focused laser beam relatively precise areas of the die. A custom, cheap Laser Fault Injection platform has been designed for this purpose.

The Laser Fault Injection Platform
The Laser Fault Injection Platform

Because the design of this platform is very budget oriented, corners had to be cut in multiple paces, resulting in various limitations. These limitations, alongside various technical details and working principles, are detailed in the corresponding sections of this article.

To enable others to reproduce my results, I will also be sharing the relevant manufacturing files and source code.

Fault Injection & Secure Boot Bypass

Being able to inject faults is just the first step in attacking the RP2350. As previously mentioned, the glitch detectors are not the only security feature that Raspberry Pi developed to protect the system.

It is also necessary to identify a weakness in the Boot ROM of the component, where the Secure Boot feature is implemented. The specific sequence of instructions I targeted will be discussed in the relevant sections of this article.


Sample Preparation

This section describes the initial steps required to execute the attack. The backside of the die of the target RP2350 must be carefully exposed, ensuring that the chip’s functionality remains intact.

Die Exposure

The target RP2350 first has to be desoldered from the Pico 2 board. This can be achieved with a simple hot air reflow station.

Next, a cheap (€30) dremel-like tool, advertised as an “Engraving Tool” (Amazon Part Number: UKH062_FR), has been used to carefully remove material around the ground pad.

The tool used to expose the die
The tool used to expose the die

After enough material has been removed, the metallic ground pad can be taken off, exposing a layer of what looks like silver (heat-conductive?) paste. This paste can easily be scratched out, revealing the backside of the die.

Exposed Backside after Mechanical Grinding
Exposed Backside after Mechanical Grinding

Main Carrier Board

The prepared sample can then be soldered on a custom PCB, designed to integrate with the Laser Fault Injection Platform.

RP2350 Backside Carrier Board
RP2350 Backside Carrier Board

A hole in the middle exposes the backside of the RP2350 die.

Backside view of the board, the die is visible
Backside view of the board, the die is visible

The board doesn’t include anything more, apart from a small LDO used to power the core. Power and control signals are routed away to an FFC connector.


        flowchart LR
            B{{FFC Connector}} <-->|UART| A(RP2350)
            A <-->|SWD| B
            A <-->|USB| B
            A <-->|QSPI| B
            A <-->|Control Signals| B
            B .->|3V3| A
            B .->|3V3| C((LDO))
            C .->|1V1|A

Main Carrier Board Architecture Diagram

This PCB can be hand-assembled, and the total unit BOM cost for small quantities is estimated at less than €10.

Interactive 3D Render & Design Files
Interactive 3D Render & Design Files

I/O Board

The Main Carrier Board detailed above connects to the I/O Board through a FFC cable.

I/O Board and Main Carrier Board, placed in a 3D-printed holder
I/O Board and Main Carrier Board, placed in a 3D-printed holder

The assembly of these two boards is designed to integrate with the Laser Fault Injection Platform.

I/O Board and Main Carrier Board, placed in the Laser Fault Injection Platform
I/O Board and Main Carrier Board, placed in the Laser Fault Injection Platform

The I/O Board breaks out the various control signals over:

  • A USB connector
  • Pin headers that are connected to a FPGA board, later used to implement the attack’s logic
  • A few test points used for SWD debugging (seldom used, especially considering SWD needs to be disabled for this challenge)


        flowchart TB
            A((LDO)) .->|3V3| B((Power Switch))
            C{{USB Connector}} .->|5V| A
            C <-->|USB| D{{FFC Connector}}
            B .->|3V3| D
            E{{Pin Headers}} -->|Enable| B
            D <-->|Control Signals| E
            D <-->|QSPI| E
            D <-->|UART| E
            D <-->|SWD| F(Test Points)
            D <-->|QSPI| G(QSPI Flash #0)
            D <-->|QSPI| H(QSPI Flash #1)

I/O Board Architecture Diagram

Additionally, two QSPI flashes are mounted to the board. The “active” flash, i.e. the one connected to the ~CS line of the RP2350, can be selected from the FPGA. This means the “active” flash can be swapped between each request from the RP2350 to the external memory.

This feature, detailed in the following diagram, is instrumental for the attack described in this article.


        flowchart LR
            A(RP2350) -->|CS| B(FPGA)
            B -->|CS#0| C(QSPI Flash #0)
            B -->|CS#1| D(QSPI Flash #1)

Dual Flash System

Here again, the board can be hand-assembled. The total unit BOM cost for small quantities is estimated to be less than €15.

Interactive 3D Render & Design Files
Interactive 3D Render & Design Files

Ground Connection Repair

An obvious issue with removing the ground pad to access the die is that the only ground connection to the integrated circuit is destroyed.

The RP2350 has a PGND pin connected to its internal DC/DC converter, but it doesn’t seem to have a low-impedance internal connection to ground. Instead, a method to restore a sufficient ground connection has been implemented.

It’s a bit challenging to see, but specks of exposed copper (or gold?), as well as “holes” where severed bond wires likely passed, are visible. Slightly scratching these areas can sometimes reveal more conductive material.

Visible metal specks near the exposed die
Visible metal specks near the exposed die

Magnified views of areas 1 and 2 are shown below.

Note

Note that these magnified images have been captured thanks to the imaging capabilities of the Laser Fault Injection Platform. This results in unusual colors, as the camera sensor of the platform lacks an IR filter.

Magnified view of Area 1
Magnified view of Area 1

Magnified view of Area 2
Magnified view of Area 2

Applying conductive epoxy between these small exposed metal bits and purposefully arranged copper pads located on the Carrier Board was, thankfully, enough to restore a sufficient ground connection.

View of the applied epoxy glue, after curing
View of the applied epoxy glue, after curing

The reference for the product I used is MG CHEMICALS 9410. It’s a one-part, temperature-activated epoxy. I used a hot air station at 150°C150°C for about 10 minutes to cure it.

Limitations

This process is, of course, a bit risky. While I’ve gotten better at it after a few attempts, I don’t think I can claim a 100% success rate.

Additionally, the ground connection restored thanks to the conductive epoxy is far from perfect. For instance, I’m usually not able to run such a modified RP2350 at high clock speeds, as it results in higher current being drawn.

Finally, I found that some I/O pads can sometimes stop working, or are facing signal integrity issues. I’m not sure all ground bond wires are internally connected on the die; I may not restore a good enough connection for all of them.

However, the target of the attack is the Boot ROM. The hardware is configured very conservatively by this ROM: clock speeds are low, etc. In this context, the “ground connection repair” method appears to be good enough.

To overcome these issues, it may be possible to mill only the very center of the ground pad, exposing the die while keeping the bond wires intact. This would likely require access to a CNC milling machine and fine bits, which I currently do not have.


Laser Fault Injection Platform

Platform Overview

As explained above, a custom fault injection platform has been designed for this project. While this hardware setup may not compete with more professional systems in terms of repeatability, it is likely an order of magnitude cheaper.

The Platform, fitted with the custom RP2350 Electronics
The Platform, fitted with the custom RP2350 Electronics

The platform can be divided into two subsystems, each of which will be detailed separately:

  • A positioning stage, used to precisely displace the die of the target RP2350 for observation and laser focusing.
  • An optical subsystem, utilized for visualizing this die and focusing high-power laser pulses onto it.

Interactive 3D Render
Interactive 3D Render

Positioning Stage

The positioning stage is based on the OpenFlexure Delta Stage (McDermott et al., 2022). OpenFlexure projects are impressive, and I would not have achieved much without them. High-precision mechanical positioning is made possible with simple 3D printed parts and affordable stepper motors.

Note

The “RayV-Lite” system is also based on an OpenFlexure project, but not on the Delta Stage I selected here.

Minor modifications have been made to the official OpenFlexure Delta Stage:

  • The base of the stage was raised to accommodate the custom optical subsystem.
  • Heat-set threaded inserts have been added in various locations to support the custom electronics introduced in the previous sections of this article.

Interactive 3D Render & Design Files
Interactive 3D Render & Design Files

Optical Subsystem

The optical subsystem is utilized for visualizing the die and focusing high-power laser pulses onto it. This subsystem is inspired from the reflection illumination subsystem from the OpenFlexure project. However, unlike the positioning stage, significant modifications have been implemented.

Interactive 3D Render & Design Files
Interactive 3D Render & Design Files

The Necessity of Using Infrared Light

One of the downsides of attacking the die from its backside is that infrared light has to be used. Indeed, silicon is almost fully opaque to visible light, preventing both visualization and fault injection.

Instead, infrared light with a wavelength of 1064nm1064nm is utilized. This wavelength is traditionally employed for backside fault injection and can also, as demonstrated in Infra-Red, In Situ (IRIS) Inspection of Silicon (bunnieHuang, 2023), be used for visualization of the die’s features.

Optical Components

The 3D render available below is extracted from the complete Laser Fault Injection Platform 3D Render. Only the components relevant to the imaging and laser focusing features are displayed and annotated.

Optical Components
Optical Components

The following items are visible. Refer to the Optical Assembly page for exact part numbers or sourcing details.

  1. The Laser Driver Board - This custom PCB is used to drive a laser diode, emitting short but powerful pulses of light. This piece of hardware will be detailed later in this article.
  2. Objective Lens - This is an off-the-shelf microscope objective lens. I wanted an infinity-corrected one to make focusing the laser beam easier. Unfortunately, these are typically more costly than finite-corrected ones. I obtained one for about €90 from AliExpress.
  3. Oblique Illumination System - This is a simple 1064nm1064 \text{nm} LED, used for imaging the die. During my tests, I noticed that illuminating the sample from its side, with a rather narrow angle, resulted in the best image contrast.
  4. Imaging Camera - This is a Raspberry Pi Camera v2 “NoIR”. As it does not have an IR filter, it remains a bit sensitive to the wavelength of interest.

Removing even more objects, including the 3D-printed parts that are holding things together, the following new optical elements become visible.

Optical Components, Without 3D-printer Parts
Optical Components, Without 3D-printer Parts
  1. Laser Diode - A 1064nm1064 \text{nm} laser diode. This tiny component was by far the most challenging part to source. I negotiated five pieces on Alibaba for about €300.
  2. Adjustable Collimating Lens - A screwable lens used to collimate the output of the laser diode. It can be purchased in bulk for a low price on AliExpress.
  3. Beam Splitter - This piece of glass is specially coated to reflect a fraction of the incoming light while transmitting the other part. Purchased for a reasonable price on AliExpress.
  4. Tube Lens - Once again, purchased for a reasonable price on AliExpress.

As explained, most of these components are off-the-shelf and have been sourced cheaply from Aliexpress. However, there is still a cost: these parts are often poorly specified or designed primarily for traditional microscopy applications, where only visible light is considered. As a result, I suspect that some infrared laser light is wasted and that the imaging may suffer from chromatic aberrations.

Optical Paths

Imaging

The path followed by the light to ensure the “Imaging” feature of the assembly is highlighted below.

Path followed by the light leaving the oblique imaging LED
Path followed by the light leaving the oblique imaging LED

The sample is first illuminated by the 1064nm1064 \text{nm} Oblique Illumination LED. This wavelength passes through the silicon and reflects off the features of the die.

Note

While not as powerful as the laser, this LED still seems to interact with the circuit in some way.

In particular, I noticed that it was sometimes impossible for the system to boot when the die was illuminated by the LED. I suspect that analog circuits, which may be more sensitive than digital ones, are affected.

To avoid this problem, the LED is only turned on to image the die and align the laser beam. It is turned off during the attack process.

Next, this light passes through the infinity-corrected lens before being imaged back to the camera sensor thanks to the tube lens.

In between, the light goes through the beam splitter. A fraction of the light will be transmitted and continue in the same direction. The reflected fraction of the light is lost.

The selected beam splitter has the following properties:

  • Reflection coefficient: 90%
  • Transmission coefficient: 10%

This prioritizes the light coming from the laser beam, whose path is detailed below.

Laser Focusing

The path followed by the light to implement the “Laser Focusing” feature of the assembly is highlighted below.

Path followed by the light leaving the laser diode
Path followed by the light leaving the laser diode

A pulse of light is emitted from the laser diode. This light is diverging and is collimated with the Adjustable Collimating Lens.

Most (90%) of the collimated light is reflected by the beam splitter and sent through the objective lens, where it is focused on the target sample.

Imaging Results

Below are a couple of slightly processed images of the die obtained from the setup.

Imaging Result Example 1
Imaging Result Example 1

Imaging Result Example 2
Imaging Result Example 2

Additionally, you will find a zoomable stitched view of the entire die.

Note

The quality of the stitching is obviously very poor; the processing tool I used struggles with the low-contrast images I provided.

For completeness, the following video demonstrates what is visible in real-time through the OpenFlexure web-based interface.

While these images may definitely not match the quality produced by a professional setup, they are sufficient to align a laser beam with specific features of the die.

The limiting factor may be the CMOS camera sensor, which is only marginally sensitive to 1064nm1064nm. Unfortunately, cameras that are sensitive to these wavelengths tend to be quite expensive.

For a much better view of the backside of the die, check-out the one shared by @LennertWo.

Laser Focusing Results

The properties of the focused beam aren’t great, and the resulting spot is rather large and elliptical. That’s not ideal, as the goal is to achieve a high-power density to inject a fault.

An example of the resulting spot is available below. Note that here, the laser was pulsed at a reduced power to avoid blinding the camera sensor.

Focused laser beam, as seen from the camera sensor
Focused laser beam, as seen from the camera sensor

This problem has been mitigated by increasing the power supplied to the laser diode from the Laser Driver Board.

Multiple factors can explain the poor shape of the laser spot:

  • The lenses I used are only specified for visible light.
  • The focusing method is simple and possibly a bit naive; I’m no optical expert.
  • Most importantly, the laser diode I used is a high-power one; the emitting element is large, and the light coming out of it is very diverging, with large differences between the fast and slow axes.

Laser Driving

Warning

This is where things can get dangerous. Although the custom board described here produces only very short pulses, working with a high-power laser can be hazardous, particularly when the emitted light falls outside the visible spectrum.

Be careful if you attempt to reproduce this work.

Laser fault injection requires short, high-power light pulses to be transmitted. A custom board has been designed for this purpose.

Laser Driver Board, Top View
Laser Driver Board, Top View

Most of the electronics are located on the top side of the board, with a laser diode installed on the bottom side.

Laser Driver Board, Bottom View
Laser Driver Board, Bottom View

While designing such a board was not overly complicated, finding a suitable laser diode turned out to be more challenging.

Laser Driver Board, installed in the Fault Injection Platform
Laser Driver Board, installed in the Fault Injection Platform


Note

As visible in the pictures of the boards, a section of the circuit has been reworked. This has been done to adjust the laser pulse parameters, as detailed below. The shared schematics have been updated to reflect this rework.

Interactive 3D Render & Design Files
Interactive 3D Render & Design Files

Board Architecture

The architecture of the Laser Driver Board is outlined below.


        flowchart TB
            A{{USB Connector}} <--> B(USB to I2C Bridge)
            B -->|Configure| C(Digital Potentiometer)
            B -->|Trigger| E
            C .-> D(High Voltage Power Supply Circuit)
            D .-> E(Pulse Generator Circuit)
            E .-> F(Laser Diode)
            G{{Pin Header}} -->|Trigger| E
            F -->|Current Sense| H{{SMA Connector}}

Laser Driver Board Architecture

The board is powered and configured from a USB port. The host computer connected to this port can be used to:

  • Configure the output level of a high-voltage (up to 75V75V) power supply. This high supply is needed for the pulse generator circuit to operate.
  • Manually send laser pulses.

However, because USB cannot be used for anything time-critical, laser pulses can also be generated from a simple pin header connector. This connector is interfaced with a FPGA board during the attack.

An SMA connector can be used to monitor the shape and intensity of the current pulses passing through the laser diode.

Pulse Generation Principle

A simplified schematic of the pulse generation circuit is outlined below.

Simplified Pulse Generator Circuit
Simplified Pulse Generator Circuit

The capacitor C is first charged from the high-voltage power supply. To trigger a current pulse through the laser diode, the switching element SW is closed.

The current response is close to the one observed with a typical RLC circuit. The value of R is chosen to ensure the response of the circuit is critically damped.

C and L can be fine-tuned to change the duration of the pulse, while the high-voltage level can be used to set the peak current.

Unfortunately, this means that changing the pulse duration is only possible by soldering new components onto the board. I had to perform this rework several times, gradually increasing the peak current until faults were successfully injected.

The values that have been used to successfully exploit the RP2350 are:

  • R=1.4ΩR = 1.4 \Omega
  • L=33nHL = 33 \text{nH}
  • C=60nFC = 60 \text{nF}

Note that the selected resistor must be able to handle high current pulses. After having destroyed several parts, I ended up using Vishay’s CMB 0207 family.

The selected RLC values result in the following theoretical current pulses.

In practice, the pulses generated by the hardware are reasonably close to these theoretical curves.

Voltage Measured from the SMA Connector of the Laser Driver Board
Voltage Measured from the SMA Connector of the Laser Driver Board

Unfortunately, in part because the optical components (lenses, beam splitter) I used are not specified for infrared light, I’m not sure how these current curves translate to the actual optical power received on the die surface.

Finally, note that the switching element SW is implemented with a fancy GaN FET. This choice was initially made to experiment with ultra-short pulses. However, it turns out that this wasn’t particularly useful. The BOM cost could be reduced by opting for a simpler MOSFET instead.

Despite this, the price of this BOM for small quantities does not exceed €30, excluding the cost of the laser diode.

Laser Diode Sourcing

Finding a suitable laser diode was challenging. It turns out high-power 1064nm1064 \text{nm} laser diodes are difficult to find and expensive!

After a few unsuccessful attempts (i.e. not enough power to inject a fault without damaging the diode first) with low-power parts (below 300mW300 \text{mW}), I contacted a manufacturer on Alibaba and was able to order, for about €300, five pieces of a part rated for 3W3 \text{W}. The datasheet for this part is available here.

This datasheet clearly states that the maximum operating current is 3.8A3.8 \text{A}. Based on the current curves shared above, it’s very obvious the part is used well above its rating.

While I anticipated encountering catastrophic optical damage issues, even after several thousand pulses, I don’t think I have harmed these diodes yet! This might be due to the short duration of the current pulses.

This surprising result matches the observation of Continuous wave laser diodes enable fast optoacoustic imaging (Stylogiannis et al., 2018):

We investigated whether continuous wave (CW) laser diodes, which are available in visible and near-infrared regions, can be good optoacoustic light sources when overdriven with a peak current >40-fold higher than the CW absolute maximum.

Note

A major difference between my work and that of the team behind the “RayV-Lite” system is that they used a widely available laser diode marketed as a “green” one.

That’s a clever choice, as it seems that, because of the way green light is actually generated, such diodes typically emit a significant amount of power at 1064nm1064 \text{nm}. (Galang et al., 2010)


Fault Injection Results

Identification of Sensitive Areas

After developing the Laser Fault Injection Platform, it was time to actually attempt to inject faults into a RP2350.

I first began studying the effect of laser pulses on a dummy firmware, similar to the one proposed by Hextree.io in their RP2350 Security Playground Demo.

I slowly scanned various areas of the die, varying laser power, focus, and other parameters. However, I did not attempt to comprehensively characterize the behavior of the system over the entire die surface area for the following reasons:

  • It’s a slow process; in the interest of time, I stopped as soon after I was able to disturb the ARM core execution flow without triggering the Glitch Detectors.
  • I hit a couple of areas that resulted in a full crash of the system and high power consumption. Considering that preparing samples is a bit tedious, I would rather not damage parts this way.

The sensitive surfaces I exploited are roughly located within the area highlighted below. Because the positioning repeatability of the Laser Fault Injection Platform isn’t perfect, while attempting to exploit the chip, I typically moved the beam slowly around these locations.

Rough location of the area that is usually targeted to inject faults
Rough location of the area that is usually targeted to inject faults

I found that depending on where the code is running from (SRAM, Flash, or ROM), or possibly based on the type of instructions being executed, it appears that slightly different locations had to be targeted to obtain interesting results.

Targeting for Secure Boot Bypass

The exact beam location used for the first Secure Boot bypass I achieved is displayed below. Here, the laser is pulsed at a low power to avoid blinding the camera.

Laser beam position that led to the first Secure Boot bypass
Laser beam position that led to the first Secure Boot bypass

Secure Boot Feature Bypass

Constraints

Thanks to the Laser Fault Injection Platform, injecting faults without triggering the glitch detectors is now possible! However, this alone is not enough to bypass the Secure Boot feature implemented in the Boot ROM of the RP2350. Indeed, as highlighted earlier, the Boot ROM is hardened and uses various features to resist faults. Trivial methods, such as glitching a conditional branch choosing between a valid or invalid signature, aren’t directly possible.

Furthermore, when searching for a way to bypass the Secure Boot feature, the following constraints must be considered:

  • With my custom hardware, I can only hope to inject a single fault at a time; complicated schemes with multiple glitches in a row aren’t possible. The limiting factor is the Laser Driver Board: the capacitor bank needs a bit of time to be recharged after each pulse.
  • The laser pulse should be triggered following an observable external event, such as the activity of the QSPI bus.
  • Random delays can be introduced by some instructions executed by the redundancy co-processor. Ideally, to target specific instructions, few to none of these special instructions should be executed between the trigger event and the fault injection.

Boot ROM Analysis Method

The source code of the Boot ROM of the RP2350 is publicly available. That’s really nice, and it makes high-level analysis of the Secure Boot way easier! Kudos to Raspberry Pi!

However, to study the possible impact of fault injections, I found it much easier to reflect directly against the actual ARM assembly code. Hence, after a quick read of the source code, I spent most of my time in Ghidra, looking at the content of the Boot ROM ELF file, also shared by Raspberry Pi.

In doing so, I managed to find a way to bypass the Secure Boot that addressed the previously listed constraints:

  • Things could work out with a single instruction “skip” (though “skip” may be a misnomer, “mutation” is maybe a better word).
  • The instruction to target closely follows an observable QSPI transfer.
  • At worst, a single random delay co-processor instruction is executed between the trigger and the instruction to target.

High-Level Idea

Let’s consider the s_varm_crit_ram_trash_verify_block function. This function is at the core of the Secure Boot implementation. A very stripped-down version of its implementation is available below.

// Start computing a hash
sb_sha256_init(&sha);

// Load the data from the flash to the RAM
s_varm_crit_mem_copy_by_words((uint32_t *)to_storage_addr,
                              resolve_ram_or_absolute_flash_addr(
                                  from_storage_addr),
                              (size + 3u) & ~3u);

// Feed the hash engine with the data, obtained from RAM
uint32_t *src = resolve_ram_or_absolute_flash_addr(to_storage_addr);
sb_sha256_update_32(&sha, src, size & ~3u);

// Include block data (containing source address, dest address and size)
// to the SHA-256 hash
sb_sha256_update_32(&sha, block_data, parsed_block->hash_def_block_words_included * 4);

// Finalize the hash
sb_sha256_finish(&sha, signature_workspace->hash.bytes);

// Do the complicated & well protected signature validation
sig_matches_image_keyx = s_arm8_verify_signature_secp256k1(signature_workspace->sig_context_buffer,
                                                           &public_key[0],
                                                           &signature_workspace->hash,
                                                           &signature[0]);

This code implements a very usual signature verification scheme: the firmware to validate is reduced down to a hash, which is fed to the signature verification algorithm.


        flowchart TD
            A[(Firmware Data in Flash)] --> B("`Memory Copy
            _s_varm_crit_mem_copy_by_words_`")
            B --> C[(Firmware Data in RAM)]
            C --> D("`SHA-256
            _sb_sha256_update_32_`")
            D --> E("`ECDSA Signature Verification
            _s_arm8_verify_signature_secp256k1_`")
            F[[Public Key]] --> E
            E -->|Signature Valid| R(Execute Firmware Data from RAM)
            E -->|Signature Invalid| S(Failure)

Nominal Firmware Verification Process

The idea is to inject a fault after the call to s_varm_crit_mem_copy_by_words and before the call to sb_sha256_update_32. This could result in the SHA-256 hash being computed against different data than the one that was previously loaded into RAM.


        flowchart TD
            A[(Firmware Data in Flash)] --> B("`Memory Copy
            _s_varm_crit_mem_copy_by_words_`")
            B --> C[(Firmware Data in RAM)]
            C --x Z@{ shape: bolt }
            Z --> D("`SHA-256
            _sb_sha256_update_32_`")
            D --> E("`ECDSA Signature Verification
            _s_arm8_verify_signature_secp256k1_`")
            F[[Public Key]] --> E
            E -->|Signature Valid| R(Execute Firmware Data from RAM)
            E -->|Signature Invalid| S(Failure)
            X[(Unexpected Data)] --> Z
            style X fill:#f9f,stroke:#333
            style Z fill:#f9f,stroke:#333

Glitched Firmware Verification Process

If the “unexpected data” used to compute the SHA-256 hash can match the one corresponding to a valid firmware, the signature verification will succeed, no matter the data loaded into RAM.

Fault Injection Scenarios

This section explores the impact of possibly interesting faults against various instructions located between the call to s_varm_crit_mem_copy_by_words and the call to sb_sha256_update_32.

Scenario #1 - Single Instruction “Skip”

Note

“Skip” is possibly a misnomer. In practice, the targeted instruction here could be mutated. However, for this specific scenario, the exact result of the mutation doesn’t matter too much.

The C code listed above translates to the following assembly pieces.

s_varm_crit_mem_copy_by_words is first called.

00001d5c: 1a 00              movs          r2,r3
00001d5e: 20 00              movs          r0,r4
00001d60: 0d 93              str           r3,[sp,#local_24]
00001d62: 01 f0 82 fb        bl            varm_to_s_native_crit_mem_copy_by_words_impl
00001d66: 0d 9b              ldr           r3,[sp,#local_24]
00001d68: 43 ec 70 07        mcrr          p7,0x7,r0,r3,cr0
00001d6c: ac e7              b             LAB_00001cc8

The implementation of the function, listed below, increments R1 until the target size has been reached.

0000346c: 19 fe 3a c7        mrc2          p7,0x0,r12,cr9,cr10,0x1
00003470: 10 b5              push          {r4,lr}
00003472: 03 46              mov           r3,r0
00003474: 22 b1              cbz           r2,LAB_00003480
00003476: 1a 44              add           r2,r3
    LAB_00003478:
00003478: 10 c9              ldmia         r1!,{r4}
0000347a: 10 c0              stmia         r0!,{r4}
0000347c: 90 42              cmp           r0,r2
0000347e: fb d3              bcc           LAB_00003478
    LAB_00003480:
00003480: c0 1a              subs          r0,r0,r3
00003482: 09 fe 3a c7        mcr2          p7,0x0,r12,cr9,cr10,0x1
00003486: 10 bd              pop           {r4,pc}

Next, after the function returns, R1 is kept untouched until the call to sb_sha256_update_32.

00001d02: 32 00              movs          r2,r6 // size
00001d04: 21 00              movs          r1,r4 // src
00001d06: 0f a8              add           r0,sp,#0x3c // sha context
00001d08: 02 f0 49 fb        bl            sb_sha256_update_32

If the instruction at 0x00001d04 can be “skipped”, the following will in effect be executed:

r1 = resolve_ram_or_absolute_flash_addr(from_storage_addr) + size;
sb_sha256_update_32(&sha, r1, size);

The data referenced by R1 is located in the memory-mapped area corresponding to the flash data. This specific area performs uncached reads, meaning that data will be retrieved directly from the external QSPI bus. An attacker can manipulate this data.

This is where the “dual flash” feature embedded in the custom I/O Board becomes useful, as it simplifies the process of pushing arbitrary values over the bus. If necessary, two reads from the same address can yield different data.

Scenario #2 - Register Value Corruption

During my tests, I observed that injecting faults between s_varm_crit_mem_copy_by_words and sb_sha256_update_32 often resulted in data being pulled from the flash starting from offset 0.

I don’t have a clear explanation, such as a simple instruction skip, regarding why this happens.

It could, for instance, mean that when the following is executed:

00001d02: 32 00              movs          r2,r6 // size
00001d04: 21 00              movs          r1,r4 // src
00001d06: 0f a8              add           r0,sp,#0x3c // sha context
00001d08: 02 f0 49 fb        bl            sb_sha256_update_32

The value of R4 points to the beginning of the memory-mapped area corresponding to the flash data.

Anyway, this means that once again, the call to sb_sha256_update_32 can use data under the control of an attacker instead of the data already loaded into RAM.

Scenario #3 - Instruction Mutation

The instructions corresponding to s_varm_crit_mem_copy_by_words are available below.

0000346c: 19 fe 3a c7        mrc2          p7,0x0,r12,cr9,cr10,0x1
00003470: 10 b5              push          {r4,lr}
00003472: 03 46              mov           r3,r0
00003474: 22 b1              cbz           r2,LAB_00003480
00003476: 1a 44              add           r2,r3
    LAB_00003478:
00003478: 10 c9              ldmia         r1!,{r4}
0000347a: 10 c0              stmia         r0!,{r4}
0000347c: 90 42              cmp           r0,r2
0000347e: fb d3              bcc           LAB_00003478
    LAB_00003480:
00003480: c0 1a              subs          r0,r0,r3
00003482: 09 fe 3a c7        mcr2          p7,0x0,r12,cr9,cr10,0x1
00003486: 10 bd              pop           {r4,pc}

If a fault can be injected at 0x00003486, it’s possible for the pop {r4,pc} instruction to be altered, possibly resulting in the value of R4 not being restored.

Before pop {r4,pc}, R4 corresponds to the last word copied from the flash memory to RAM, a value under the control of the attacker. This value could, for instance, be set to an address contained in the memory-mapped flash area.

R4 is subsequently used when calling sb_sha256_update_32.

00001d02: 32 00              movs          r2,r6 // size
00001d04: 21 00              movs          r1,r4 // src
00001d06: 0f a8              add           r0,sp,#0x3c // sha context
00001d08: 02 f0 49 fb        bl            sb_sha256_update_32

Once again, sb_sha256_update_32 could be forced to run against data pulled from the QSPI bus.

Attack Process

Software Architecture

Various software components have been developed to implement the logic of the attack and control the electronics.

Browse the code on GitHub
Browse the code on GitHub

FPGA

To synchronize the laser pulse with the execution of the Boot ROM, the activity of the QSPI is monitored by the gateware of an FPGA Board connected to the I/O Board.

The choice of the FPGA platform isn’t super critical as the RP2350 is clocked at a conservatively low speed when the Boot ROM is running. I chose to use a Glasgow Interface Explorer tool.

The Glasgow Interface Explorer
The Glasgow Interface Explorer

It embeds an iCE40 FPGA compatible with open source tools. Finally, it integrates well with Amaranth HDL, which I find more convenient to develop with than more common HDL languages like Verilog or VHDL.

The gateware written for this project is responsible for:

  • Basic I/O Control:
    • Turning the power supply of the target RP2350 on and off.
    • Controlling the RUN and BOOTSEL signals.
  • Trigger Timing: Monitoring the QSPI bus in real time.
  • Attack Orchestration:
    • Dynamically selecting the active QSPI Flash memory.
    • Pulsing the laser.

Laser Driver Board

The Laser Driver Board communicates with the host computer through a USB-to-I2C bridge component.

No firmware running on the board needed to be written, and the host computer can be directly used to configure the high-voltage power supply for the laser diode pulser circuit.

Positioning Stage Control

The Positioning Stage is controlled by software running on a Raspberry Pi single-board computer.

The X, Y, and Z coordinates of the moving platform can be programmatically set using a web-based API.

In the context of this attack, this API is leveraged to slowly scan over the sensitive areas while pulsing the laser.

Laser Pulse Synchronization

The last QSPI read corresponding to the call of s_varm_crit_mem_copy_by_words can be detected with little uncertainty by the FPGA gateware. From this point, before calling sb_sha256_update_32, the following instructions are executed.

00003478: 10 c9              ldmia         r1!,{r4}
0000347a: 10 c0              stmia         r0!,{r4}
0000347c: 90 42              cmp           r0,r2
0000347e: fb d3              bcc           LAB_00003478
00003480: c0 1a              subs          r0,r0,r3
00003482: 09 fe 3a c7        mcr2          p7,0x0,r12,cr9,cr10,0x1
00003486: 10 bd              pop           {r4,pc}

00001d66: 0d 9b              ldr           r3,[sp,#local_24]
00001d68: 43 ec 70 07        mcrr          p7,0x7,r0,r3,cr0
00001d6c: ac e7              b             LAB_00001cc8

00001cc8: 0b 9b              ldr           r3,[sp,#local_2c]
00001cca: 00 2b              cmp           r3,#0x0
00001ccc: b3 d0              beq           LAB_00001c36
00001cce: 03 9b              ldr           r3,[sp,#local_4c]
00001cd0: 73 b1              cbz           r3,LAB_00001cf0
00001cf0: 23 0e              lsrs          r3,r4,#0x18
00001cf2: 10 2b              cmp           r3,#0x10
00001cf4: 02 d8              bhi           LAB_00001cfc

00001cfc: 03 23              movs          r3,#0x3
00001cfe: 3e 00              movs          r6,r7
00001d00: 9e 43              bics          r6,r3
00001d02: 32 00              movs          r2,r6
00001d04: 21 00              movs          r1,r4
00001d06: 0f a8              add           r0,sp,#0x3c
00001d08: 02 f0 49 fb        bl            sb_sha256_update_32

A redundancy co-processor instruction is executed at 0x00001d68, introducing a random delay of up to 127 system clock cycles. As a result, it becomes impractical to consistently time a laser pulse to target a specific instruction following 0x00001d68.

However, this instruction is the only one that introduces a random delay. The software designed for the attack allows for about 20 attempts per second, which is sufficient to inject interesting faults in a reasonable amount of time.

Flash Memory Organization

Before starting the attack, the two QSPI flashes of the I/O Board are organized as follows:

The first flash, whose content will be loaded to RAM, contains a copy of the valid, signed firmware, including a signature block, patched as follows:

  • A small shellcode is written at the reset handler offset. This shellcode is designed to jump to arbitrary firmware located further in the flash memory at address XIP_BASE + 0x10000. XIP_BASE corresponds to the beginning of the memory-mapped flash data, while 0x10000 is an arbitrary offset.
  • The last word of the data loaded to RAM is set to XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE + 0x7000. 0x7000 is an arbitrary offset that will be used later, while XIP_NOCACHE_NOALLOC_NOTRANSLATE_BASE also returns flash data.

The second flash, whose content is expected to be read after a fault has been injected, contains three copies of the unmodified firmware. Computing the SHA-256 hash against one of these images will result in a valid hash. The copies, ensuring all the fault injection scenarios that have previously been outlined, are located at:

  • Flash offset 0x0, to support the Scenario #2.
  • The offset corresponding to the size of the data copied to RAM, to support the Scenario #1.
  • Flash offset 0x7000, to support the Scenario #3.

Finally, an arbitrary firmware is copied at offset 0x10000. This firmware will run if the shellcode, previously loaded to RAM, is executed.

Attack Loop

During the attack, the following process is repeated in a loop.

  • The first flash is selected.
  • The RP2350 is powered on.
  • QSPI bus reads are monitored until the last byte corresponding to the call to s_varm_crit_mem_copy_by_words has been read.
  • The second flash is selected.
  • After an arbitrary delay, the laser is pulsed.
  • QSPI bus reads are monitored again to verify if the data pulled from the flash corresponds to a successful bypass.
  • In case of failure, the RP2350 is powered off, and a new attempt will be made.


        flowchart TD
            A[Select First Flash] --> B[Power On RP2350]
            B --> C[Monitor QSPI Reads]
            C --> D[Select Second Flash]
            D --> E[Arbitrary Delay]
            E --> F[Pulse Laser]
            F --> G[Monitor QSPI Reads]
            G -->|Failure| H[Power Off RP2350]
            H --> A
            G -->|Success| I[Arbitrary Firmware Execution]

Attack Loop

Results

When targeting sensitive die areas, injecting faults that result in data being pulled from the QSPI bus at one of the expected addresses during the execution of sb_sha256_update_32 is quite common.

However, a major issue was that faults were often impacting the system a bit too hard, corrupting for instance the register corresponding to the size parameter of sb_sha256_update_32.

Another issue regards the positioning stage. Apart from some backlash in the gearing system, it seems the position drifts a bit over time and possibly temperature, making consistently hitting the exact sample spot complicated.

These reduced the success rate of the attack significantly. I only have been able to see the first Secure Boot bypass after more than 16 hours of tweaking the laser pulse parameters and position. However, following this fine-tuning, I only had to wait for about 20 minutes for a new success to appear.

My monitor displays the secret value hidden in the RP2350 after the first successful bypass
My monitor displays the secret value hidden in the RP2350 after the first successful bypass

The bypass enables the execution of arbitrary firmware, which can then access secrets stored in the OTP area of the RP2350. This was the objective of Raspberry Pi’s Hacking Challenge.

Possible Improvements

Several elements could be improved to increase the success rate of the attack:

  • The laser pulse duration could be fine-tuned. Due to the simple design of the Laser Driver Board, adjusting the pulse duration requires modifying the values of physical components. This process can be cumbersome, so I haven’t thoroughly explored the impact of pulse duration.
  • The laser spot size resulting from the Optical Subsystem is relatively large compared to what is typically used in similar attacks. A smaller spot size would likely lead to better-controlled and more repeatable faults.
  • The FPGA gateware could be enhanced. Instead of using two physical QSPI flashes, the FPGA could be utilized to emulate one, and dynamically supply the correct data, regardless of the flash address requested after the fault. However, this possibly goes a bit beyond the capabilities of the FPGA I used.

Conclusion

Laser fault injection can be performed on a budget! Although it requires a lot of trial and error, and sourcing a suitable laser source can be tedious, a functional setup can indeed be achieved.

Due to significant compromises, the performance of such a system is not optimal, but interesting results can still be obtained: injecting faults in the RP2350 without triggering its glitch detectors becomes possible.

This alone is not enough to bypass the Secure Boot feature of the RP2350. However, a small but critical section of the Boot ROM has been found to be less hardened and protected by the redundancy co-processor. Injecting a fault at this point, while supplying a compatible payload over the QSPI bus, can essentially defeat the Secure Boot.

While way simpler methods have now been made public, this work still addresses Raspberry Pi’s RP2350 Hacking Challenge.

Additionally, note that it may also be possible to exploit the section of the Boot ROM I targeted without even resorting to LFI. There are some reports of carefully performed EMFI attacks able to bypass the glitch detectors.

The glitch detector is pretty good at detecting EMFI attempts, but it was possible to glitch CPU operations without triggering it with a small coil and a low power glitch

Still, I regret nothing; lasers are fun to play with!

Disclosure

Following my first successful bypass, I immediately contacted Raspberry Pi. For transparency, the documents I shared with them are available here.

Communication with the team was smooth and enjoyable. They acknowledged that the “break-in” was valid and confirmed that the next Boot ROM of the RP2350 would include more hardening around the specific area of the code I targeted.


Bibliography

Andrew 'bunnie' Huang. Infra-red, in-situ (iris) inspection of silicon. 2023. URL: https://arxiv.org/abs/2303.07406, arXiv:2303.07406.

Jemellie Galang, Allesandro Restelli, Edward W. Hagley, and Charles W. Clark. A green laser pointer hazard. 2010. URL: https://arxiv.org/abs/1008.1452, arXiv:1008.1452.

Samuel McDermott, Filip Ayazi, Joel Collins, Joe Knapper, Julian Stirling, Richard Bowman, and Pietro Cicuta. Multi-modal microscopy imaging with the openflexure delta stage. Opt. Express, 30(15):26377–26395, Jul 2022. URL: https://opg.optica.org/oe/abstract.cfm?URI=oe-30-15-26377, doi:10.1364/OE.450211.

Antonios Stylogiannis, Ludwig Prade, Andreas Buehler, Juan Aguirre, George Sergiadis, and Vasilis Ntziachristos. Continuous wave laser diodes enable fast optoacoustic imaging. Photoacoustics, 9:31–38, 2018. URL: https://www.sciencedirect.com/science/article/pii/S2213597917300356, doi:https://doi.org/10.1016/j.pacs.2017.12.002.