Joe Grand demonstrated a fault injection attack on the
Trezor One hardware wallet in order to recover the key off the device. The original post is very dramatic but shy's area from some technical details. In this post, the author publishes their research on how this attack was performed.
Fault injection is the intentional glitching of the system to produce undefined behavior. Hopefully, this benefits us, the hacker, by skipping an instruction, changes a register value or something else. There are three main types of glitching with various benefits: clock, voltage and Electromagnetic.
The target of this attack is the Trezor One hardware wallet. This is a low-cost and open source wallet built around the STM32F2. The security feature is set to RDP2, meaning that flash is locked, RAM reads are locked and the debug interface is locked. If the instruction for verifying this configuration was glitched, we could re-enable these settings.
The goal is to glitch the voltage/power of the wallet. To do this, the author decided to attack the internal voltage regulator. Since this is the internal voltage regulator, modifications to this line(VCAP_1 and VCAP_2) would directly affect kernel logic, flash memory and IO logic. These lines are accessible from the outer layer of the PCB as well.
The vulnerability being exploited was an issue with the BootROM of the STM32F2, commonly referred to as
Chip.Fail. This bug allows an attacker to inject a fault around 170 microseconds after BootROM execution in order to glitch the RDP security check. Since RDP2 is no longer in use, a debugger can be turned on to read out the SRAM of the device to get the wallets contents.
How do we practically set this up though? First, we remove capacitors connected to the VCAP lines. The capacitors will attempt to keep the voltage stable, which do not want. Hooking up an oscilloscope is required, since we need to know when the device turns on in order to launch the attack. Additionally, we need to solder to the RESET line in order to turn off the board with an unsuccessful glitch. Finally, we need to solder to the SWD port for the debugging interface.
Finally, with everything setup, we can replicate the attack! The author used the fancy ChipWhisperer to power the wallet, trigger the reset line and glitch the VCAP line. They used an STLink for the debugging portion of the project. If a glitch was unsuccessful, they simply changed the parameters and tried again. They knew if a glitch was successful or not by using the STLink SWD enumeration code.
Prior to using this on the real board, they did this on a developer STM32 board. With the ChipWhisperer, they had to perfect the width of the glitch, the timing of it and the amount of clock cycles to repeat the glitch for. After playing with these settings and letting the setup run for an entire weekend, they successfully got the SWD debugger enabled!
Overall, I love the post. One of my big hurdles for fault injection was knowing how to wire everything up on the board itself. This gives me a good idea of how to do that, which I really appreciate.