Author Philippe Azalbert
Category Automotive
Tags hardware, fault injection, glitching, IDCODE, RH850, automotive, 2026
This blogpost explains how we bypassed the 16-byte password protection of the debug on several variants of the RH850 family using voltage fault injection.
Introduction
The RH850 family is a range of high-performance and high-reliability 32-bit microcontrollers for Renesas, dedicated to the automotive industry. These microcontrollers are the most common ones we have to work with in the various Electronic Control Units (ECU) we audit at Quarkslab.
Like other microcontrollers, they embed a debug access for development purposes to flash new firmware or monitor its behavior. To ensure the firmware could not be extracted or tampered with in production, the debug access can be disabled or locked using a 16-byte password.
Being able to bypass such protection could be useful in any black-box assessment, in order to retrieve the firmware and be able to reverse-engineer it and look for vulnerabilities. With the UNECE R155 regulation, it is also a common security goal we have to verify, to ensure an attacker will not be able to alter the firmware.
To enhance our audit capabilities for the automotive industry, we studied if, using fault injection, we could reliably bypass the 16-byte password protection known as IDCODE, to perform such an attack during any assessment when needed.
State-of-the-art
Two previous research studies demonstrated that fault injection attacks are effective in bypassing debug protection on two families of Renesas' microcontrollers.
The first one, by Franck Jullien focused on the RX65 series. He was able to use voltage fault injection to bypass the debug password on an RX architecture.
In 2022, Willem Melching documented in his blog how he managed to exploit a disabled debug access of an RH850/P1M-E, also using voltage fault injection.
Both articles describe Renesas' proprietary debug protocol, which supports 1-wire and 2-wire UART interfaces. When the debug access is locked using a password, the unlock sequence is the following, as described in the RX65N Group, RX651 Group User's Manual: Hardware:
- The debug probe starts an initialization sequence, sending about 10
0x00bytes on the UART interface. - If the RH850 is properly started in programming mode, with pin FLMD0 set at 1, it replies with a
0x00. - The debugger then sends a connect command
0x55awaiting response0xC1. - Several messages are then exchanged to set the expected CPU and UART speed.
- Once done, the debugger sends a SYNC command.
- Depending on the configuration, the RH850 will inform debug access is granted, password protected, or prohibited.
This implementation is interesting from a security point of view, as even with a deactivated debug access, the initialization of the debug sequence is still allowed, providing monitorable information to perform an attack.
Having several ECUs lying on our lab's shelves, we wondered if we could bypass the second debug protection of the RH850, using fault injection also.
What is fault injection ?
Fault injection is the art of generating glitches that put a microcontroller outside its expected condition of operation in order to alter its intended behavior. Some glitches generate faults that can be exploited depending on their effect.
Several methods exist to inject a glitch, the most common being:
- clock glitching;
- voltage glitching;
- alectromagnetic pulse injection;
- laser.
Common belief is that fault injection's main effect is to bypass instruction. If such a result can be observed, on the hardware level it flips one or several bits in memory or any internal bus during OTP reading, instruction fetching...
For example, let's look at a basic ARM instruction, mov r1, #0x03, which equals 0x03 0x10 0xa0 0xe3 in little-endian. For example, if a fault flips the 15th bit during the fetch phase or execution of the instruction, it becomes mov r3, #0x03 (0x03 0x30 0xa0 0xe3). Depending on the instruction logic, an unexpected value of register r1 may change the execution path, looking like an instruction skipping.
Fault injection technique used
For this study, we worked with a crowbar voltage glitch attack. Voltage glitching technique is performed by underpowering or overpowering the chip for a controlled amount of time to alter its behavior. The crowbar attack is a specific type of voltage glitch where the power supply is shorted to the ground instead of injecting a specific voltage, using a MOSFET for example.
On a very basic microcontroller, the voltage glitch can be executed on any power input pins, commonly named VCC. However many chips have one or several pins tied to the internal regulators to connect external capacitors, commonly labeled VCAP or VREG. Targeting these pins is often more effective as the attack will affect the internal regulator, providing better results. Removing capacitors connected to the VCAP and VCC improves results and requires shorter glitches but is not always mandatory, depending on the setup. Setting the input power to a lowest running voltage, like 2.3V, allowed to generate faults on several targets without the need to remove capacitors.
With such type of attack, three parameters are needed:
- a trigger;
- a delay;
- a duration.
The trigger is the most important one; it has to be reliable, as the success and the repeatability of an attack will highly depend on it. When attacking a specific feature like a password or a secure boot, we need to find a reference that can be used to start each attempt. It could be a specific message on a bus or a rising/falling edge on a pin, but it needs to be precise and deterministic.
Based on the trigger, the glitch will be injected after a certain delay that will last for a specific duration. These two parameters are often named "glitch offset" (the delay after the trigger) and "glitch width" (the duration of the glitch).
Finding a valid pair that generates a fault can be quite long. Once a fault is found, understanding the generated effect and if it can be used for an attack is called the characterization.
Reproducing known attack
Having multiple RH850-based ECUs, we first tried to reproduce Willem's research. Lacking an RH850/P1M-E-based ECU, we targeted the RH850/F1KM-S4, which is not based on the same CPU and is running with a higher clock frequency:
| RH850/P1M-E | RH850/F1KM-S4 | |
|---|---|---|
| CPU | G3M | G3KH |
| Frequency | 160 MHz | 240 MHz |
| Usage | Electronic power steering | Electrical body application |
| ASIL | ASIL-D | ASIL-B |
To find valid parameters that could generate an "instruction skip" like fault, we first worked on a Renesas RH850 development board. The RH850 F1KM-S4 has two internal regulators, AWO (Always-On area) and ISO (Isolated area), which are interesting for our voltage glitch. Looking at the datasheet, we decided to attack the ISOVCL pin, as the ISO regulator is powering the CPU subsystem and the Code Flash:
Functions of AWO and ISO voltage regulators.
We removed capacitors connected to the ISOVCL and soldered an SMA connector to this pin to connect a ChipWhisperer Husky, a device made by NewAE technology to perform voltage fault injection.
Setup with the RH850 development board, the ChipWhisperer Husky and a Rigol oscilloscope.
Before attacking the password protection, we looked for parameters that generate faults and flashed the following test script onto the board:
#include <string.h>
static char* message = "XXX%08xYYYY%08xZZZ\r\n";
char buffer[1024];
int msg_len = 0;
int result = 0;
#pragma inline_asm init_r6
static void init_r6(void) {
mov 0, r6
}
#pragma inline_asm perform_1024_add_operation
static int perform_1024_add_operation(void) {
add 1, r6
/* repeated 1022 times */
...
add 1, r6
/* returns value of r6 */
mov r6, 10
}
void main(void) {
init_r6();
/* Set trigger pin high */
PORT.P11 |= (1 << 14);
perform_1024_add_operation();
/* Set trigger pin low */
PORT.P11 &= ~(1 << 14);
/* R6 is copied to R10 after setting the trigger down, to ensure only the ADD operation is targeted */
result = read_r6();
msg_len = sprintf(buffer, message, result, result);
R_Config_UART0_Send(buffer, msg_len);
while (1) {
};
}
Aiming a single add instruction as presented by Raelize in "False injections: Tales of Physics, Misconceptions and Weird Machines" and during their trainings limits the parameter search and helps to characterize found faults.
As we inject our glitch in the middle of a series of 1024 instructions add 1, r6 and read the returned value on the UART port, it is easy to identify a fault that acts as an instruction skipping.
To perform a finer characterization, exploiting exception handlers from crashes allows for the identification of exploitable opcode mutations, as described in Fault injection - down the rabbit hole.
Switching a GPIO at the beginning and at the end of the targeted instructions provides a reliable trigger we can use for this search, greatly reducing the range of injection delays to test. After several attempts, we found different sets of parameters that faulted our microcontroller.
Results of the `ADD 1024` parameter search.
To attack the password protection of the RH850 we decided to use the byte before the checksum of the password as a trigger to be able to start injecting our fault before the last rising edge of the UART signal. The ChipWhisperer Husky having an embedded UART trigger, we didn't need an external device like a Raspberry Pico, which was used in the aforementioned research to monitor the UART traffic and to generate the trigger.
Using an oscilloscope, we checked that our trigger was working as expected and measured when the response from the RH850 was sent to estimate the delay window we needed to test. We noticed an ~80 microseconds jitter that could be related to UART handling or a random delay added to counter this kind of attack, meaning our trigger is not reliable enough.
Jitter between UART Tx (blue) and Rx (yellow).
To ensure an attack on the IDCODE is successful, our script analyzes if the response after sending the IDCODE is the expected one (0x81 0x00 0x01 0x3a 0xc5 0x03) and then tries to read the option 0x3A which returns the model of the chip of our development board (R7F701648). This approach allows us to confirm proper access to the memory when attacking a locked device, where the content of the Flash is unknown at first.
Believing (a little) in luck, and as we needed to halt this study for some weeks, we decided to inject glitches in this very wide window using a Raspberry Pi that controlled the ChipWhisperer Husky. After several days we did get one successful fault that confirmed the RH850 password protection could be bypassed. However, relying on luck is not what we aimed for. Wanting to see if we could have a reliable setup to perform such an attack, we worked on finding a better trigger than the one used.
The quest for the golden trigger
As the UART communication between the RH850 and the debugger could not be used as a trigger for the attack, we decided to conduct a side-channel analysis to have a better understanding of the behavior of the microcontroller when the password is received and checked. The easiest method is to perform a simple power analysis (SPA), monitoring the power consumption of the chip. As different instructions require more or less power depending on the various transistors used to compute them, we may guess what kind of operation is running on the microcontroller or distinguish an idle state from an active one.
Thanks to Ohm's law, you can measure current by reading the voltage on a shunt resistor as U = R*I. The ChipWhisperer Husky provides a dedicated connector to perform power measurement, with a 12-bit 200MS/s analog to digital converter.
We modified our setup to add a second SMA connector also tied to the ISOVCL pin to monitor the power consumption on the internal regulator and connected it to the ChipWhisperer Husky. We also put one probe of our oscilloscope on the ISOVCL pin and analyzed several traces.
After a few attempts, we did notice a ~4µs long pattern that sounded interesting. Comparing various traces on our oscilloscope confirmed the shape of the pattern.
Power analysis pattern providing a reliable trigger (purple).
The ChipWhisperer Husky provides a Sum of Absolute Difference (SAD) trigger that could be used in this kind of situation, allowing the use of a reference trace as a trigger. We decided to test this functionality and performed a capture when sending an invalid password and kept the trace of the pattern. However, when sending other passwords, we did not see the trigger being set on our oscilloscope. NewAE providing a SAD software to emulate the SAD implementation on the FPGA of the ChipWhisperer, we ran several computations with various traces and parameters and concluded the identified pattern is not unique enough to be used with the SAD feature.
Still confident in our power analysis approach to get a reliable trigger, we decided to explore the trigger sequencer of the ChipWhisperer Husky. After the password is sent on the UART serial the power trace seems in an idle state until the pattern is found. We decided to reuse the UART trigger as a first step then to rely on an ADC trigger that will detect one of the first spikes of our pattern. Needing a reference level for the ADC trigger, we measured the value of the highest spike on the ADC pattern and used 80% of this value.
Pattern as seen by the embedded measurement of the ChipWhisperer and identified reference level.
Same capture on the oscilloscope.
NewAE's GitHub hosts several Jupyter notebooks to understand and practice every feature, like the one for the trigger sequence of the ChipWhisperer Husky. Enabling the sequencer is simply done with the following commands:
import chipwhisperer as cw
scope = cw.scope()
reference_level = highest_spike * 0.8
scope.trigger.sequencer_enabled = True
scope.trigger.module[0] = 'UART'
scope.trigger.module[1] = 'ADC'
scope.trigger.level = reference_level
After some basic tuning, we ran this new attack campaign and managed to bypass the IDCODE protection in about one minute:
$ python3 run_IDCODE_glitch.py
Delay: 537 Width: 18, Crash: 2, Reset: 25: 0%| | 88/168000 [01:10<35:02:39, 1.33it/s]
IDCODE response: b'\x81\x00\x01\x3a\xc5\x03'
Reading option 3a: R7F701648
Glitched with delay 537 and width 18 in 88 attempts
Visualisation of the successful glitch on the oscilloscope.
Reproducibility and outcomes
After successfully bypassing the password protection on our RH850 development board, we questioned whether the power analysis trigger used was hardware-dependent or could be exploited on other PCBs. With several RH850-based ECUs available in our lab, we confirmed that the ADC trigger pattern was consistent across all devices. Although the reference level varied slightly per device due to peripheral chip consumption, we bypassed every IDCODE-locked ECU in minutes after removing ISOVCL capacitors and measuring the threshold level on a sample trace.
We also improved our attack to be able to read/write firmware on an IDCODE protected ECU, by automatically sending a command that sets the IDCODE to the default value (16-times 0xFF) when a valid glitch is observed.
Poor man version
If higher-end equipment exists to perform voltage fault injection, the ChipWhisperer Husky used in this research is considered as a professional tool. A question arose to evaluate if this attack is reproducible with DIY level device.
We were interested in the Pico Glitcher v3, a 30-50€ voltage glitching platform based on the Raspberry Pico 2. It has several inputs, including ext1 and ext2 which provide adjustable Schmitt triggers. Two potentiometers per trigger allow to set the attenuation level and the threshold the trigger will react to. The goal was to check if the target pattern could be detected by this kind of trigger.
The Pico Glitcher can be controlled by the Findus Python module and runs a MicroPython based firmware, which is easily customizable. An additional UART adapter has been used to send and receive debug commands to the RH850, the Pico Glitcher controlling the reset state of the microcontroller.
Attack setup with a Pico Glitcher.
Basic configuration of the Pico Glitcher firmware does not allow combined sequenced triggers, so we modified the StatesMachines.py file to add our own trigger logic:
@asm_pio()
def edge_trigger_threshold_rising_edge():
# block until number of edges and delay are received
pull(block)
mov(x, osr) # Read edge counter threshold
pull(block)
mov(y, osr) # Read trigger #1 delay
# count the rising edges on trigger pin
label("edge_count_loop")
# wait for rising edge on trigger pin EXT1
wait(0, pin, 1)
wait(1, pin, 1)
# decrease x and jump to the beginning of the loop
jmp(x_dec, "edge_count_loop")
# delay before monitoring the second trigger
label("delay_loop")
jmp(y_dec, "delay_loop")
# wait for rising edge on trigger pin EXT2
wait(0, pin, 0)
wait(1, pin, 0)
# tell observed trigger
irq(block, 1)
push(block)
The edge counter trigger is used first to monitor the password sent. A customizable delay was added to give control to the second trigger when the power consumption signal is stable, changes in the UART lines affecting the power consumption of the target.
However, spikes of the expected pattern being a few millivolts, we were not able to use the Schmitt triggers of the Pico Glitcher to reproduce the same attack flow as we did with the ChipWhisperer Husky.
Nonetheless, we managed to successfully bypass the IDCODE password, fine-tuning the delay of our attack to a ~5 microseconds window. If we managed to have a valid glitch within 100 attempts with the ChipWhisperer Husky and its ADC trigger, we needed around ~7.000 with the PicoGlitcher with a longer tuning phase.
qb@qb:~/Work/MCU_bypass/RH850$ python3 RH850_picoglitcher.py
[+] Version of Pico Glitcher: [1, 13, 1]
[+] Version of findus: [1, 13, 1]
Attack started at 17:26:17
7%|████▋ | 7277/100000 [1:22:32<20:30:34, 1.26it/s]
[SUCCESS] (18:48:50) Option 3a: b'R7F701649'