Over the past week, I have been slowly progressing on glitching USB descriptors of a Trezor ONE. I have succeeded in creating a framework for this, and other USB-based glitching attacks, and will document this work for future reference. As background reading, I advise that you review the following resources:
- Scanlime’s video https://www.youtube.com/watch?v=TeCQatNcF20
- Colin O’Flynn’s work https://www.youtube.com/watch?v=BHqrA8lzz2o
- Colin O’Flynn’s (not related) blog post: https://colinoflynn.com/2019/03/glitching-trezor-using-emfi-through-the-enclosure/
- The “breaking bitcoin” presentation: https://www.youtube.com/watch?v=hAtoRrxFBWs
In a nutshell, this attack was performed using a Chipwhisperer back-end to insert a VCC glitch, a Facedancer to handle USB interfacing and some Python scripting to tie it all together.
The Facedancer is a GoodFET core (well, an MSP430 microcontroller) tied to a MAX3421 front-end over an SPI bus, and a FTDI UART IC for host communication. It’s originally designed to interface arbitrarily with USB, and has no support for glitch triggering – but it is easy to modify the MAXUSB app (goodfet/firmware/apps/usb/maxusb.c) to override any command to do what READ/WRITE does, but also pull a pin high.
As an aside: the FTDI protocol is quite simple, and leads me to wonder why more pins are not broken out on the Facedancer for integration with other projects (and in this case, freeing a laptop USB port by driving the UART directly from the ChipWhisperer). I may add these in future.
Note that this isn’t perfect – there’s still significant horizontal jitter between when the MSP430 tells the MAX3421 to send a USB packet, and when vulnerable code executes on the target – but it’s better than nothing.
The final Facedancer modification looks like this:
You’ll note an extra GPIO pin is broken out (second from the right, far right is trigger) – this controls a 2N7000 pin which resets the Trezor after every glitch insertion.
Finally, the Python driver code must be modified to support a variant form of USB transaction, where we simply call IN_Transfer continuously until it falls over or nothing is transmitted. This is described in scanlime’s glitching video, and is included in the source repository listed below.
One of the most significant challenges in this exercise was to correctly time the glitch. To an extent, this is impossible – due to natural jitter on both ends of the USB pipe, it’s impossible to accurately time any glitch perfectly, with a degree of reliability. Instead, my goal was to time the glitch so it landed in the right ballpark. This is compounded by the ChipWhisperer’s clock not being synchronised with the target’s internal PLL.
This is ultimately a small problem that can be solved with some logic analyzer time:
Of course, the actual parameters used will be different for you, depending on your clock generator configuration and USB sender setup.
Using a logic analyzer, I was able to also see when my glitches caused the device to reset, or enter an unrecoverable error state – this helped refine the size of my inserted glitches.
Note that it is also possible to generate glitches by affecting the output (at the other end, when a USB IN transfer occurs, but this (imo) is less likely to affect the actual integrity of the USB packet (just thinking logically, how would you implement it with a discrete USB controller – buffering it and waiting for the host to give you bandwidth is the only sane way to do it).
Some work also needed to be done on the target, to prepare it for VCC glitching. Primarily, the decoupling capacitors need to be removed. If you are reading the datasheets for this, be careful that you count all the capacitors (including the VBAT ones) – these aren’t all located in one place on the official Trezor schematic.
An additional 2N7000 is used to allow the Facedancer to conveniently reset the device without power cycling the USB.
A power cleaning net is used to provide a relatively stable source of 3.3v power to the CPU: a pair of capacitors is used to clean the power supply (not perfect, but fuck knows it’s better than USB straight through a 3.3v regulator), and a small resistor (10 Ohms) is used to isolate the switching noise of the CPU so we’re better able to analyze our work with an oscilloscope.
Finally, a Python script is used to tie together the Chipwhisperer and the script. This is similar to my other glitching experiments, and a copy of the code can be found on my Github. Note that no integration is available at the time of writing with my graphing / project review utilities, I’ll add these as time permits.
Note that you must build and update the Facedancer’s firmware if you want to use this the Python scripts make use of new commands which are not implemented by default.
Alternatively, Kate Temkin’s work might also be useful, particularly if you are using an alternative back-end to the MAX3421.
And with this, we sit back and wait for the glitches to appear: