Voltage glitching, also called fault injection, is the process of dumping the energy on a microcontroller's power rail very briefly - Just enough to cause a glitch, where it skips an instruction, rather than causing a brown-out-induced reset.
I first learned about the technique in connection with the Chip Whisperer, which is an FPGA-based board with all the bells and whistles. It's quite expensive, and like any other situation where you add an FPGA, very complicated. Naturally, that has elevated it to a level above what mere mortals can perform in the limited free time we have.
Voltage glitching, also called fault injection, is the process of dumping the energy on a microcontroller's power rail very briefly - Just enough to cause a glitch, where it skips an instruction, rather than causing a brown-out-induced reset.
I first learned about the technique in connection with the Chip Whisperer, which is an FPGA-based board with all the bells and whistles. It's quite expensive, and like any other situation where you add an FPGA, very complicated. Naturally, that has elevated it to a level above what mere mortals can perform in the limited free time we have.
After knowing about this, and having it in the back of my mind for several years, I finally have a good use-case that can justify spending some time on this. I have a pile of generic STM8-based devices, and while I have written some of my own alternative firmware, I'd love to be able to dump the original flash to revert them back to factory code.
The function of the device doesn't matter, that's not the point of this exercise.
Some quick searching for options leads to this recent write-up, which is sparse on details, but serves as excellent inspiration that this task is very doable.
A few architecture notes:
The STM8 has a Read Out Protection bit in the configuration area of its flash memory. When the programmer attempts to read out the flash memory, the bootloader first checks this bit, and if it's cleared, it starts reading out the flash to the programmer. If it's set, it just reads out zeroes. Write capability is never blocked - That is, you can still write a zero to that ROP, and then the microcontroller will be "unlocked", but it does clear the program memory, too.
One of the pins on STM8s is called VCAP, and it's attached to the internal voltage regulator. The CPU runs on this voltage rail, not the actual voltage that is provided to the IC's power pins. The pin is intended to be connected to a decoupling capacitor, and that provides an perfect spot to inject my glitches. Most microcontrollers also have something called Brown-Out Resets: When the input voltage rails sags too low, the peripheral triggers, and resets the microcontroller. Obviously, this is something we want to avoid, and using the VCAP pin should help with that.
In terms of glitching, there are two important considerations:
The glitch must start at the same time or during the cycle in which the CPU is trying to read the ROP bit, and the glitch must not last long enough to trigger the BOR or to make any other important instructions fail. It's not easy to know these exact timings, so any reasonable values must be tried, essentially brute forcing the process.
Now, the logical way to do this would be to use an external microcontroller to wait for the programmer to reset the system, wait a set period of time, and then trigger the output transistor to glitch the voltage rail. That's boring! You know what else can do that? That's right, a pair of 555s.
Here are two 555s set up as monostable pulse generators. The input is the RST line on the STM8 programmer. The first 555 then sets the delay. The second 555 sets the length of the output pulse. Both of these timings are controller by a different potentiometer. These then go to a MOSFET that dumps the energy stored in the internal voltage regulator cap.
After building it with larger-than-designed time values and testing it to prove that the waveform looks as expected, we solve the next hurdle:
To figure out decent ranges for the potentiometers, my STM8 board runs at 8MHz, which means that each clock cycle takes 125ns. The STM8 requires at least 2 clock cycles for each instructions (one for retrieval and one for execution), and more for instructions with multiple bytes or arguments. So, ballparking, we need a pulse that's anywhere from 0.2us to 1.2us or so.
One problem with a typical 555 is that it can only generate pulses as small as 10us. Fortunately, I have a pair of high speed versions up my sleeve, the These have a...
I am curious how you arrived at your delay number. According to my scope outs, sduino's stm8flash waits a whopping 16.6 *milliseconds* after dropping the reset line to initiate SWIM, and also resets the micro THREE TIMES for reasons?!? It also leaves the reset line low.
The ST Visual Studio doesn't wait long, 342uS but it does a LOT and also resets the micro several times, and leaves the reset line low.
I recompiled stm8flash from git (not an easy task as the windows support is currently broken) but this DID result in a much more sane wave and a delay of 344usec. It also leaves the reset line high, so you just get a single dip for each attempt. So nice!
Yet your max delay is only (ref https://cdn.hackaday.io/images/4887421641833549673.png) 128uS. The chip hasn't even entered SWIM mode yet. How can this work?
SWIM mode alone takes 9.76mS to enter into, after that the entire transaction takes (at LEAST 91.2 *milliseconds*.
Are you saying the chips reads RDP at bootup and so none of this matters?
I had some luck with a DIP NE555N from Philips (date code '96) which could go up to 1MHz in astable mode whereas all other brands stopped before 500kHz.
I suspect even faster variants exist and they will probably be CMOS based.
I am curious how you arrived at your delay number. According to my scope outs, sduino's stm8flash waits a whopping 16.6 *milliseconds* after dropping the reset line to initiate SWIM, and also resets the micro THREE TIMES for reasons?!? It also leaves the reset line low.
The ST Visual Studio doesn't wait long, 342uS but it does a LOT and also resets the micro several times, and leaves the reset line low.
I recompiled stm8flash from git (not an easy task as the windows support is currently broken) but this DID result in a much more sane wave and a delay of 344usec. It also leaves the reset line high, so you just get a single dip for each attempt. So nice!
Yet your max delay is only (ref https://cdn.hackaday.io/images/4887421641833549673.png) 128uS. The chip hasn't even entered SWIM mode yet. How can this work?
SWIM mode alone takes 9.76mS to enter into, after that the entire transaction takes (at LEAST 91.2 *milliseconds*.
Are you saying the chips reads RDP at bootup and so none of this matters?