Glitching Raspberry Pi 3B+
Can you easily perform voltage fault injection on complex embedded targets like a stock Raspberry Pi 3 Model B+? In this article, Colin demonstrates how we can use the same techniques shown in previous articles by applying them to an application built on a stock Linux install on the Raspberry Pi 3 Model B+.
Back in 2014, I recorded an example of myself performing voltage glitching against a Raspberry Pi SBC, and posted it to YouTube with the title “VCC Glitching against Raspberry Pi (Linux SoC)” [1]. I’ve continued to use that demo as a reference for how you can apply voltage glitching against a modern Linux-based system, and glitch a user application without affecting the other processes.
I was documenting that demonstration for my upcoming book (“The Hardware Hacking Handbook” from No Starch Press) [2], and as part of that my co-author (Jasper) kindly pointed out that the original Raspberry Pi B I’m using in the demo was first released in 2012, and has in fact been discontinued for several years now. This makes it much more difficult to follow along with this demonstration. Sounds like it’s time for an update.
In this article, I’m going to update my demonstration to use modern targets (and modern tools). This will show you how to perform voltage glitching against a simple application running on a Raspberry Pi 3 Model B+. And if you’re too busy right now to follow along don’t worry, because the Raspberry Pi 3 Model B+ will stay in production until at least January 2026, so hopefully this demonstration won’t go out of date as quickly in the future.
RPI 3 POWER PERTURBATIONS
The act of voltage glitching is typically one where we insert ringing or excessive voltages into the power network of the chip. This is assumed to cause timing violations within the chip, because we suddenly have a situation where voltages are far outside of what the designer intended. If we allow the violations to exist for a short time only, the device may not completely crash as you expect, but instead give incorrect results to specific instructions that are executed.
I’ve covered this topic in many previous articles, and shown you various ways of performing fault injection (glitching). With that in mind, I won’t spend too long on the why we want to glitch, but instead look toward how you can recreate this glitch even on a modern system.
As mentioned, we’ll be using a Raspberry Pi 3 Model B+ board. Let’s take a look at the power distribution network and main controller on that device. Figure 1 shows the area near the main system on a chip (SoC), with the power IC to the upper right. What does this power IC do? While we don’t have a full schematic for this board, the partial schematic we are given does provide information on the number of power rails, as shown in Figure 2.
— ADVERTISMENT—
—Advertise Here—
We can see a number of different power rails on this device. Of particular interest is VCC_CORE. This would be the core power supply rail for the SoC, which is the rail onto which we would most likely want to insert glitches. The setup for our fault insertion is shown in Figure 3. We want to use a MOSFET to short the power rail for very short durations. This ChipWhisperer-Lite from NewAE Technology has this crowbar feature built into the device itself, meaning we don’t even need any external circuitry.
Because we are trying to insert the glitch into the SoC, we want to connect our MOSFET close to the VCC_CORE connection on the SoC itself. The VCC_CORE rail likely has many decoupling capacitors on it that are designed to prevent the types of perturbations our glitching circuitry is attempting to insert, and if we insert a large spike physically far away from the SoC, the inductance and capacitance of the power distribution network may flatten our glitches.
FINDING THE RIGHT NET
Because we don’t have a full schematic (or board silkscreen information), I can’t tell which pins on the SoC are connected to the VCC_CORE power rail using just the product documentation. Instead, we simply flip the board over, as in Figure 4. Using a multi-meter, I can look for a short (0Ω) connection between some of the power islands and the VCC_CORE pin on the power distribution IC.
You can see in Figure 4 that there are three islands all connected to VCC_CORE. These are all underneath the SoC itself, so it is assumed these all go to VCC_CORE pins on the SoC. Of course, we have no documentation on that SoC, so we could have multiple different core function power pins all connected to that same VCC_CORE rail. There are multiple cores in the SoC so each core may be closer to different power pins, and there are other internal features such as the GPU which might have discrete power pins, all of that are powered from the same VCC_CORE supply.
In theory this means you might need to try each of the islands or different areas underneath the SoC to get a success. Even though they are electrically connected, you might find a perturbation inserted as close as possible to the “sensitive” power pin is the most effective. In this case I didn’t find it to be so sensitive, instead the first island I tried seemed to work well. To connect my ChipWhisperer-Lite to the net, I used a spring needle pin (pogo pin). A detail of the needle point on one of the VCC_CORE islands can be seen in Figure 5.
This needle connects to the center of the “glitch” SMA (SubMiniature version A) connector on the ChipWhisperer-Lite, which is the high-side (drain) of the MOSFET. The overall setup is shown in Figure 6, where the needle pin is seen soldered to the center pin of a SMA connector. The ChipWhisperer-Lite is simply held in a PanaVise overtop of the Raspberry Pi, with pressure keeping everything in the correct location. The ground connection is done over a jumper cable—you can imagine this jumper cable likely adds significant inductance, so you may also experiment with using a shorter ground connection as well. The jumper cable in this example simply goes from the Raspberry Pi GPIO header ground pin to a ChipWhisperer-Lite ground pin.
With this in place, let’s figure out some example code to test with, and then see how the ChipWhisperer-Lite can be driven to cause glitches.
A SIMPLE LOOP
To start with, we will boot the Raspberry Pi 3 Model B+ using a standard image. Without changing anything, we then create a file called glitch.c
with the contents of Listing 1. This program has two loops that run in a row—any sort of program flow changes will result in one or two of the loops exiting early. When this happens, the value stored in the k variable will be different than if the loops ran through fully.
#include <stdio.h>
— ADVERTISMENT—
—Advertise Here—
int main(void)
{
volatile int i,j,k,cnt;
cnt = 0;
while(1){
k = 0;
for(i = 0; i < 10000; i++){
for(j = 0; j < 10000; j++){
k++;
}
}
cnt++;
printf("%d %d %d %d\n", i, j, k, cnt);
};
}
LISTING 1 – A simple double-loop is a basic test code for fault injection.
You can compile this by running gcc glitch.c -o glitch
which will build our glitch executable. Running it with ./glitch
should print the normal correct output of 10000 10000 100000000 1
, where the last number (1
in this example) will continue to iterate for every run through the double-loop. The second to last value (100000000
) is the most likely value that will be corrupted by incorrect runs, and represents the value of k. Of course, any of the other values could be corrupted too, which is why we print them all.
Now that we have our target code, let’s decide what ChipWhisperer configuration we will use. Using the ChipWhisperer-Lite, we’ll simply enable the higher-power MOSFET crowbar, and set a width to turn “on” the crowbar for. When the MOSFET is on, this means the VCC_CORE is being shorted to ground. The example code to do this is shown in Listing 2.
import chipwhisperer as cw
scope = cw.scope()
scope.glitch.clkgen_freq = 100E6
scope.glitch.output = "enable_only"
scope.glitch.clk_src = "clkgen"
scope.io.glitch_hp = True
scope.glitch.resetDcms()
# Set glitch width here
scope.glitch.repeat = 480
# Call this to insert glitches
scope.glitch.manual_trigger()
LISTING 2 – The configuration of the ChipWhisperer-Lite allows generating a relatively long (4.8µs in this example) crowbar activation.
There isn’t much code here. To start with, a 100MHz clock is generated (the clkgen
frequency in the code), and a certain number of cycles of it (the scope.glitch.repeat
setting) are specified to short the VCC_CORE power rail via the crowbar.
Figuring out this width is critical. Initially we should find an upper bound on this width, by first confirming that we can reboot the target by shorting the VCC_CORE supply for “too long” a period. If we are unable to reset the system by shorting the VCC_CORE supply, it suggests our glitch is simply not powerful enough to overcome the power distribution network of the Raspberry Pi. Or we might have too much inductance in our connections such they cannot pull the VCC_CORE power down.
Of course, all of this can be done without the ChipWhisperer-Lite. You can find an external MOSFET similar to the one used in the ChipWhisperer-Lite, and simply drive it with a pulse generated from another source. But there are more variables here, and the open-source nature of the ChipWhisperer-Lite makes it easy for you to see what the actual hardware is doing.
Once we have our upper limit on the glitch width (based on the width that will reset the board), we simply reduce the width by turning the scope.glitch.repeat
setting down until the board no longer resets. If we run the glitch program at the same time, we should see some interesting results.
Listing 3 shows an example of me running the scope.glitch.manual_trigger()
line from Listing 2 four times during the program execution. You can see that there are several different faults in the output. Two of the glitched outputs have minor changes to the final count of 104001932
and 176245593
(the last column value index of 4 and 20 respectively in Listing 3). You’ll notice the 5th output iteration is completely wrong. Both the overall iteration counter changed incorrectly, along with the internal counts. Something went very wrong with that glitch! And the final fault doesn’t print any invalid output at all, as instead we get a Segmentation Fault
, as on the 4th fault insertion I have corrupted some critical process or memory (oops).
pi@raspberrypi:~ $ ./glitch
10000 10000 100000000 1
10000 10000 100000000 2
10000 10000 104001932 3
10000 10000 100000000 4
18 18 54598716 18
10000 10000 100000000 19
10000 10000 176245593 20
10000 10000 100000000 21
Segmentation fault
— ADVERTISMENT—
—Advertise Here—
LISTING 3 – An example of the output of the loop program from Listing 1 while inserting faults
You’ll note this is on an otherwise fully functioning system—t’s running Linux, it has a display driver up with the normal desktop running, and has all the normal background tasks. Yet our fault injection appears to primarily affect our user application rather than crashing the system. The main reason for this is that our user application is taking the majority of the CPU time, so when we randomly insert a glitch it is most likely we will hit the user application.
APPLYING GLITCHES
What sort of application can you come up with for this? While now that you can see how easily glitches can be inserted, there are all sorts of interesting applications for it. One thing you’ll have to work on is timing. If you are trying to attack some specific code block, you cannot just insert glitches at any time you want.
Most commonly you’ll have a trigger (such as the user entering a password), and count a certain time (or number of clock cycles) from the trigger until you insert the glitch. The exact timing will require some experimentation, but often you can script this such that you can let your system search for the specific timing by trying repeatedly until a success is seen.
But not all applications require careful timing. As an example, there is an attack on the RSA cryptosystem commonly referred to as the “Bellcore Attack”, which was disclosed in a paper entitled “On the Importance of Checking Cryptographic Protocols for Faults” by Boneh, DeMillo and Lipton. This paper showed that on many implementations of RSA, a single fault inserted almost anywhere in the RSA calculation makes it possible to recover the private key. You also see very time-independent faults where devices use an infinite while(1)
loop as a failure mode (for example, when a signature has failed). Sometimes breaking out of the loop with a glitch causes the system to return to a normal operating mode.
VIEWING THE VOLTAGE
I’ve avoided answering one question that you likely have: What did the glitch look like in practice? And I’ll bet many readers are confused why our glitch width was so long, here almost a 4.8µs wide glitch! Considering the Raspberry Pi runs at 1.4GHz, this is a lot of cycles of the target device. In reality our glitch isn’t actually affecting the target for the entire time—this makes more sense if you look at the glitch waveform as measured in Figure 7.
You can see that the normal operating voltage of 1.2V is slowly pulled down to around 0.96V, and on the release of the crowbar the voltage rapidly increases to 1.44V. This rapid increase means a ringing on the internal rails, where this ringing causes the interesting effects we wanted.
I know in many previous articles I’ve concentrated on small microcontrollers, but hopefully this article has convinced you that you can apply these techniques to more complex systems without much effort. The glitch generation here is identical to those I’ve used in previous articles, and the entire setup is made easier since I didn’t need any sort of external debugger or connection. I compiled my test code on the same system I performed the glitching on. Hopefully you can try to apply this to many other complicated SoC type devices and see if you get such easy success too!
RESOURCES
References:
[1] YouTube video (see below)
[2] https://nostarch.com/hardwarehacking
NewAE Technology | www.newae.com
Raspberry Pi Foundation | www.raspberrypi.org
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • MARCH 2021 #368 – Get a PDF of the issue
Sponsor this ArticleColin O’Flynn has been building and breaking electronic devices for many years. He is an assistant professor at Dalhousie University, and also CTO of NewAE Technology both based in Halifax, NS, Canada. Some of his work is posted on his website (see link above).