Glitching the KeepKey hardware wallet
KeepKey is a hardware wallet based on STM32F205 MCU which is used to protect private keys of multiple cryptocurrencies. The signing operations are protected by the PIN implemented on the device and no one without PIN, even with physical access to the device, is supposed to be able to use the device. Fault attacks rely on the weakness of hardware and allow an attacker, who got access to the device (stolen device) to bypass the security features. In this article we show an attack on unmodified KeepKey hardware wallet, which uses electro-magnetic fault injection.
Identifying the target
The KeepKey hardware wallet is an open source hardware wallet which is implemented on the STM32F205 MCU. There are 22 input commands which can be sent to the device, some of them:
- fsm_msgPing() – sends back the received message
- fsm_msgResetDevice() – initializes the device with new PIN
- fsm_msgChangePin() – verifies the PIN and allows authenticated user to enter a new PIN or remove the PIN check.
Since the source code is available it can be seen that the fault injection attacks were considered and some countermeasures are implemented. In particular, there is a check on the clock glitching:
Fig. 1. – Fault injection countermeasures in the source code
Although there are some countermeasures most of the code is not protected against FI.
Fault injection setup
Due to the fact that USB is used for both communication and powering the device EMFI was used since it is increases the chances of successful glitching.
Since there is no arbitrary code execution on the device, the simplest user command was chosen to test if fault injection has any effect on the executing code.
Fig. 2 – Ping command implementation
First, an attempt to glitch memcpy was executed with a glitch right after the USB packet sent to the device as shown on the power trace below.
Fig. 3 – Power trace of the USB D+ communication wire, showing the communication packets with the device.
The full coarse scan on the chip resulted in a number of glitches as well as shown the areas most susceptible to fault injection. The results of the full scan can be seen below:
Fig. 4 – The full scan of the device’s chip using EMFI.
The green dots represent the expected behavior, in this case a message “HelloWorld” was sent to the device and received back. The yellow dots mean that the device muted and no message was returned at all. Finally, the red dots mean that something else was returned by the device but not the expected string. The red dots are the successful glitches. The table below shows the responses received in case of successful glitches.
A number of glitches corrupted the length of the message, others, as it seems, modified the value of the counter in the loop, some glitches corrupted one or multiple bytes to zero and finally some of them, marked bold, corrupted one bit in the value of the byte. One of the glitches resulted in the message “Settings Applied” to be printed, which most likely resulted in the executing code of the another FSM command which printed the message.
Additionally, there were a few glitches which affected the output on the screen:
Since there is a large number of commands which can be sent and glitched, an attacker need one with a simple if-check which can be skipped.
The code above shows such a check in fsm_msgResetDevice(). The command sent by an attacker to an initialized (stolen) device should return “Device is already initialized…” message. A successful glitch bypassing the check allows an attacker to set a new pin in RAM. A subsequent command fsm_msgChangePin() can be used to commit the pin to the flash.
The fault injection attack on the hardware wallet is as follows:
- An attacker gets physical access to the device (lost\stolen device)
- Fault injection is introduced when the fsm_msgResetDevice() is processed
- A successful glitch allows to skip the check of the device to be initialized
- A new PIN is set to the RAM pin storage; the seed is intact.
- The PIN is removed or updated using fsm_msgChangePin() command
- The PIN is updated to a one selected by the user and the seed is kept the same, allowing the attacker to authorize operations on the device.
Using the fault injection parameters identified for the ping command a smaller parameter scan resulted in a successful glitch after 705 attempts.
Success rate of the fault injection with optimized parameters is 1.2% meaning that on average it takes 82 attempts to get a successful glitch. With attempt rate of 0.3 attempts per second on average it takes less than 5 minutes to get a successful glitch and change pin on an initialized device to a PIN chosen by an attacker and fully compromise security of the device. Only one device was used during all the tests and no damage was done to the device by glitching after millions of attempts.
Fig. 5 – The initialization of the wallet (on the left), and the wallet after glitching on the right
- General purpose MCUs are not designed to be fault injection resistant.
- Implemented countermeasures against clock glitching cannot prevent other kinds of faults.
- Large number of available commands gives an attacker a lot of ways to break the device.
As general purpose microcontrollers attempt to provide more and more security-related functionality, increasing number of secure devices use such chips as they provide much more flexibility than traditional secure solutions, e.g. smart cards and secure elements. Although hardened hardware is a must for a secure device, the software running on the chip plays a great role in the overall resistance of the device to hardware attacks. Similar to software hardening techniques, such as integrity protection, stack overflow detection, address randomization, etc., there are a number of software countermeasures which can increase robustness of a platform to hardware attacks. Such countermeasures include integrity checks on the security sensitive values, execution randomization to lower reproducibility, control flow integrity and more. And in the same way as with other security mechanisms it is important to detect attack attempts and respond accordingly.
The secure architecture is not just hardware, or software, or even combination of the two. Secure device development also requires security focused development, architecture and code review, and thorough testing of the implemented security mechanisms. One of the ways to increase security of software is through third party review, either by means of third party security lab or, in case of open source projects, with the help of community, and there are a lot of examples proving this methods can continuously increase security. Unfortunately, hardware attacks are more difficult to tackle in the same way, as the issues are not just bugs in the implementation, but weakness in the hardware and software implementation and more structured approach is needed, focused on the architecture as a whole on a higher level and the way it is implemented.
If you are interested in evaluating your secure device, contact Riscure at firstname.lastname@example.org. Also see our previous blog post that focuses on software evaluation of another cryptowallet solution.
This research was also presented at OffensiveCon 2019 in February 2019. You can watch the video of this talk below. Click here to download the slides from this presentation.