side channels: using the chipwhisperer
This is a post in a series regarding side channels, from the theoretical and pratical point of view; the posts are
- introduction on the model of computing devices (to be finished)
- using the Chipwhisperer (this post)
- power analysis (here)
- glitching (to be finished)
All the practical experimentations performed in these posts are done using my own Chipwhisperer's board, the CWLITE one, it's an open source, open hardware device that allows to quickly setup and execute side channels related attacks.
This model come along with its own target board attached (named CW303 with an an Atmel's XMEGA128 (datasheet)) and in the official repository of the project are available a couple of firmwares to experiment with.
Installation steps
This part is primarly for me in order to remember what I did to getting started, you can see a more precise (and up to date) procedure in the documentation.
First of all you need to have the board accessible by the user
# bash -c 'printf "SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"2b3e\", ATTRS{idProduct}==\"*\", TAG+=\"uaccess\"\\n" >> /etc/udev/rules.d/50-newae.rules'
# bash -c 'printf "SUBSYSTEM==\"tty\", ATTRS{idVendor}==\"2b3e\",ATTRS{idProduct}==\"*\", TAG+=\"uaccess\", SYMLINK+=\"cw_serial%n\"\\n" >> /etc/udev/rules.d/50-newae.rules'
# bash -c 'printf "SUBSYSTEM==\"tty\", ATTRS{idVendor}==\"03eb\",ATTRS{idProduct}==\"6124\", TAG+=\"uaccess\", SYMLINK += \"cw_bootloader%n\"\\n" >> /etc/udev/rules.d/50-newae.rules'
# udevadm control --reload-rules
# usermod -a -G dialout $USER
(these steps above must be done only once system-wide); then you can install the library
$ git clone https://github.com/newaetech/chipwhisperer.git && cd chipwhisperer
$ git submodule update --init jupyter # To get the jupyter notebook tutorials
$ python3 -m pip install -r jupyter/requirements.txt --user
$ jupyter nbextension enable --py widgetsnbextension # enable jpyter interactive widgets
$ python3 -m pip install -e . --user # use pip to install in develop mode
the jupyter part is related to the tutorials, if you don't need them, only clone and install.
The compilation of the firmware for the target can be done in this way, where
the -C
flag tells which firmware we want (PLATFORM
tells the build
sistem that the target is the XMega)
$ make -C hardware/victims/firmware/simpleserial-base PLATFORM=CW303
If instead you want to compile some code "out of the tree" you can use directly the compiler with the right flags:
$ avr-gcc \
-Wall \
-mmcu=atxmega128d3 \
-o <output ELF file \
<c source file>
$ avr-objcopy -O ihex <ELF file> <HEX file>
the last line generates the HEX
file that is the format needed for flashing.
In general is very useful to double check the generated code; you can use avr-objdump
$ avr-objdump -d <ELF file> | less
The ChipWhisperer's library is implemented in python and you can use the
REPL
to interact with the device, for the example the following is a snippet
of a session
python3
Python 3.7.5 (default, Oct 27 2019, 15:43:29)
[GCC 9.2.1 20191022] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import chipwhisperer as cw
>>> scope = cw.scope()
>>> scope
cwlite Device
gain =
mode = low
gain = 0
db = 5.5
adc =
state = False
basic_mode = low
timeout = 2
offset = 0
presamples = 0
samples = 24400
decimate = 1
trig_count = 226703590
clock =
adc_src = clkgen_x1
adc_phase = 0
adc_freq = 96000000
adc_rate = 96000000.0
adc_locked = True
freq_ctr = 0
freq_ctr_src = extclk
clkgen_src = system
extclk_freq = 10000000
clkgen_mul = 2
clkgen_div = 1
clkgen_freq = 192000000.0
clkgen_locked = True
trigger =
triggers = tio4
module = basic
io =
tio1 = serial_tx
tio2 = serial_rx
tio3 = high_z
tio4 = high_z
pdid = high_z
pdic = high_z
nrst = high_z
glitch_hp = False
glitch_lp = False
extclk_src = hs1
hs2 = None
target_pwr = True
glitch =
clk_src = target
width = 10.15625
width_fine = 0
offset = 10.15625
offset_fine = 0
trigger_src = manual
arm_timing = after_scope
ext_offset = 0
repeat = 1
output = clock_xor
>>> target = cw.target(scope)
Serial baud rate = 38400
However you need to call the default_setup()
in order to have all configured
correctly
class OpenADC(ScopeTemplate, util.DisableNewAttr):
"""OpenADC scope object. ..."""
def default_setup(self):
"""Sets up sane capture defaults for this scope
* 45dB gain
* 5000 capture samples
* 0 sample offset
* rising edge trigger
* 7.37MHz clock output on hs2
* 4*7.37MHz ADC clock
* tio1 = serial rx
* tio2 = serial tx
.. versionadded:: 5.1
Added default setup for OpenADC
"""
self.gain.db = 25
self.adc.samples = 5000
self.adc.offset = 0
self.adc.basic_mode = "rising_edge"
self.clock.clkgen_freq = 7.37e6
self.trigger.triggers = "tio4"
self.io.tio1 = "serial_rx"
self.io.tio2 = "serial_tx"
self.io.hs2 = "clkgen"
self.clock.adc_src = "clkgen_x4"
...
If you want to flash the firmware you can do it directly from python
scope = cw.scope()
prog = cw.programmers.XMEGAProgrammer
cw.program_target(
scope,
prog,
<path_fw>)
Pinout
There is a header with 20 pin at the edge of the board intended to be the interface between the board and the target. This allows to power the board (but only with 3.3 Volts), to provide clock, to interact with the serial and to program it (XMega and AVR protocols).
From the original documentation
Left | number | number | Right |
---|---|---|---|
5V (not connected in this model) | 1 | 2 | GND |
3V3 | 3 | 4 | HS1/I (clock input) |
nRST | 5 | 6 | HS2/O (output clock and glitch) |
MISO (SPI and AVR programming) |
7 | 8 | VREF |
MOSI (SPI and AVR programming) |
9 | 10 | IO1 (serial RX) |
SCK (SPI and AVR programming) |
11 | 12 | IO2 (serial TX) |
PC (XMega128 programming pin) | 13 | 14 | IO3 |
PD (XMega128 programming pin) | 15 | 16 | IO4 (used as a trigger) |
GND | 17 | 18 | 3V3 |
GND | 19 | 20 | 5V (not connected in this model) |
Firmware updating
It's possible to update the firmware that runs on the ChipWhisperer itself via python: issuing the following
import chipwhisperer as cw
scope = cw.scope()
programmer = cw.SAMFWLoader(scope=scope)
programmer.enter_bootloader(really_enter=True)
programmer.program('/dev/ttyACM0', hardware_type='cwlite')
you should see a device appearing in the dmesg
log.
[1111253.064641] usb 2-10: USB disconnect, device number 27
[1111253.449854] usb 2-10: new high-speed USB device number 28 using xhci_hcd
[1111253.602083] usb 2-10: New USB device found, idVendor=03eb, idProduct=6124, bcdDevice= 1.10
[1111253.602086] usb 2-10: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[1111253.630152] cdc_acm 2-10:1.0: ttyACM0: USB ACM device
[1111253.630322] usbcore: registered new interface driver cdc_acm
[1111253.630324] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
Comments
Comments powered by Disqus