Attacking the STM32 Series
The STM32 series are 32-bit microcontrollers based on the Arm Cortex-M processor and are widely used in embedded systems. Different variants are suitable for low-power as well as for high-performance operations. One of its security options is the so-called Readout Protection (RDP) . The STM32 offers three different levels:
RDP Level 0: No protection
- Full debugging is allowed
- Full access while in system bootloader
RDP Level 1: Read protection
- Access (read, erase, program) to Flash memory is forbidden while debugging
- Other memories such as the bootloader memory can be accessed via JTAG
- Access (read, erase, program) to any memory is forbidden while in system bootloader
- Everything else can be read, e.g. RAM and registers
- Reset to RDP level 0 erases whole Flash memory
RDP Level 2: Read & debug protection
- Debugging is forbidden by disabling the JTAG and SWD interfaces
- Starting system bootloader is forbidden
- Reset to RDP Level 0/1 is not possible
To read the Flash memory on RDP2 locked devices, two protection levels must be circumvented.
RDP2 Downgrade to RDP1
On boot, the RDP register value is checked. A specific value has to be set for RDP2 (0xCC) and RDP0 (0xAA), all other values default to RDP1 (however, often 0xBB or 0x55 is set). Therefore, if the read operation on the RDP register reads a wrong value (due to a voltage glitch), the device will think it's in RDP level 1. Thus, debug interfaces and the bootloader will become accessible.
RDP1 Memory Reading
The internal system bootloader is available with RDP level 1 and provides a "Read Memory" operation which reads 256 bytes from a user-supplied memory address. However, this operation is not allowed in RDP1. This is ensured by the microcontroller checking the RDP state before every read operation. If this check is tampered with (by a voltage glitch), it will be skipped and 256 bytes of memory read. By glitching the read command repeatedly, 256 byte firmware chunks can be read and reassembled into a complete firmware dump.
During the last years, much work was done on Voltage Glitching attacks, as already described in the introduction above. However, we noticed that recreating glitches can be hard, mostly due to the usage of custom hardware and often unpublished glitching parameters and setups. Therefore, we took a structured approach which can hopefully be extended in the future on other chips and boards:
We created the SECGlitcher, which is based on the well-established ChipWhisperer API, but is easier to use for default use cases such as UART or GPIO triggers.
We developed the SECGlitcher as we noted, that glitching scripts across all boards are always structured similar. So why not create a simple class that wraps all of the init commands and also gathers the results? This results in smaller, clearly structured scripts that can be easily compared across different boards and chips.
Reproduce glitches with parameters: During our glitching experiments, we were always struggling with the same question: What do we use as initial search parameters? Depending on how closely we guess the glitch duration as well as trigger offset, we can find valid glitches after minutes. However, if our estimate is way off, we will take days to discover interesting glitching ranges. Thus, we decided to include a database in the SECGlitcher, which contains valid glitch width settings that we have discovered previously for each MCU. Hence, your valid parameters shouldn't be off too far (of course this also depends on the used board and capacitance of the power rail).
Easy headless usage: The use of Jupyter notebooks as featured by the ChipWhisperer may be great for some initial experiments, however, for conducting glitching tests in an efficient and scalable manner, we needed a solution that can be conveniently controlled remotely, e.g., is able to run on a (headless) server. Therefore, the SECGlitcher class is built to be used in command-line only scripts (though we implemented some interactive elements, just in case you want to showcase some stuff).
Convenient data aggregation: The need for fault-proof and convenient data aggregation comes right after the previous feature. To prevent data loss, data can not only be printed out to the console but can also be saved as CSV file. These CSV files, created from one or multiple glitching attempts, can subsequently be aggregated and visualized by a provided helper script. With this, it is possible to show potential valid glitching parameters of multiple (partial) tries.
Easy setup: An easy setup is important to keep the entry barrier low, luckily, using the SECGlitcher class is simple: Create a new virtual environment and install the
chipwhisperer as well as some other required packages with PIP. That's it.