Easy Path to Proof
Side-channel power analysis is a method of breaking security on embedded systems, and something Colin has covered extensively in his column. This time Colin shows how you can prove some of the fundamental assumptions that underpin side-channel power analysis. He uses the open-source ChipWhisperer project with Jupyter notebooks for easy interactive evaluation.
By Colin O’Flynn
This month I thought I’d bring you an introduction to side-channel power analysis (again). I’ve covered this in past articles, but it’s been a few years and I know new readers are going to be picking up this issue of Circuit Cellar. But don’t worry—I’m doing more than just giving you a rehash of old material. My open-source ChipWhisperer project has recently had the Version 5.0 release, which uses a new interactive Python interface (using something called Jupyter notebooks). As part of this release, several new tutorials are available, and some of them cover aspects I haven’t previously shown you.
In particular, I’m going to show you how some of the fundamental assumptions around side-channel power analysis can be easily proven. It’s not something for which you have to take my word. It’s something you can test yourself, and experiment with the differences that show up for various firmware code you might be running.
Simple Power Analysis
My intro is going to push through all sorts of examples. The first thing we’ll talk about is simple power analysis (SPA). This form of power analysis commonly refers to the fact that you can see the flow of data through a system. This can be used to break code that has an execution path that depends on the secret data being processed. What sort of code might that be? We’ll take a look at a simple password check as shown in Listing 1. That might look straight-forward—but what if you could see the loop execution time? Power analysis lets us do exactly that, meaning that we could discover which character of our password was incorrect.
The code from Listing 1 also contains a trigger_high() and trigger_low() call. Those actually provide an added piece of instrumentation being used only for our demonstration. Using a resistor in the power pin, we could see how the power is varying, as in Figure 1. I’m doing that with my ChipWhisperer platform, but you could use an oscilloscope or other similar piece of gear. You can see in Figure 2 the loop has an obvious pattern, and we see four iterations through the loop.
How does that help us crack a password? We could monitor the power consumption of the device and send every possible first character of the password. When we see a change in the power trace, we know that suddenly another code path was taken. Most likely this “other code path” is in fact the loop going into the second iteration. We don’t need to be clever or look for a specific signature. We just look for “different.”
It’s hard to hide this difference. If we add a random delay afterward, we can still see the time at which the power traces changed. We can notice that at this point in time whether it seems to go into a busy-wait loop or continues processing data. If you don’t believe me, there is an exact example of this in the open-source ChipWhisperer Jupyter.
So, if you think you’re clever, you’ll implement the code as in Listing 2. This takes the same amount of time, no matter what code is executed. Let’s see how to break that.
Data Affects Power
What if I told you that the very data being processed affect the power consumption? The theory behind this is fairly simple. Internal to the device, a data bus consists of wires over a ground plane. Changing the voltage on this is equivalent to charging and discharging a capacitor. As a nice feature, most internal data-buses go to an intermediate state between valid data transmissions. These intermediate states mean that every time we send a value across the data-bus, we have to charge a certain number of data lines to the ‘1’ state. If we looked at the power consumed on the VCC rail, we would expect to see spikes related to the data being sent across a bus. If all the bits of the data-bus were going high, we would expect to see larger spikes than when only one or two lines went high. You can see our expected results in Figure 3.
But how could we test that? We could send some data to a chip, and try to find a location where, for example, we see a strong difference in the power being used that depends on the data. Since we expect our signal to be very weak, we might need to average a number of such traces over time. …
Read the full article in the March 344 issue of Circuit Cellar
(Full article word count: 2133 words; Figure count: 7 Figures.)
Don’t miss out on upcoming issues of Circuit Cellar. Subscribe today!