How to use segmented capture?#
Segmented capture is a Husky-only feature which allows you to “do more with less” (sample storage).
When the duration of the target operation exceeds Husky’s sample storage capacity and you cannot or do not want to use streaming, a possible solution is to capture only the portions of the target operation that you care about.
This is covered at a high level in the 01 - Introduction to ChipWhisperer-Husky.ipynb notebook; here we put it into practice with a simple example.
Supported Capture Hardware:
❌ CW-Nano
❌ CW-Lite
❌ CW-Pro
✅ CW-Husky
Required ChipWhisperer software installation:
✅ any release
%run '../connect.ipynb'
In this example we will use simpleserial-aes
firmware.
scope.adc.samples = 32000
trace = cw.capture_trace(scope, target, bytearray(16), bytearray(16))
oplen = scope.adc.trig_count
print('Operation length: %d cycles' % oplen)
Operation length: 31864 cycles
Here Husky can capture the full target operation. But what if we want more samples per clock cycle?
Here the sampling rate was 29.48 MS/s; Husky supports up to 200 MS/s. Let’s increase scope.clock.adc_mul
to 26 samples per clock cycle:
scope.clock.adc_mul = 26
print('ADC clock frequency: %d MHz' % int(scope.clock.adc_freq))
(ChipWhisperer Scope WARNING|File ChipWhispererHuskyClock.py:663)
Could not calculate pll settings for the requested frequency (7370000);
generating a 7692307 clock instead.
It may be possible to get closer to the requested frequency
with a different adc_mul.
It may also be possible to get closer to the requested
frequency if you set scope.clock.pll._allow_rdiv to True;
however this can result in an inconsistant clock phase between
the target and ADC clocks; use at your own risk!
(ChipWhisperer Scope WARNING|File ChipWhispererHuskyClock.py:703) Target clock may drop; you may need to reset your target.
ADC clock frequency: 200000000 MHz
This will increase the operation length to oplen*26/4
cycles, which is more than what Husky can store:
oplen*26//4
207116
Because we are using a very high ADC sampling rate, streaming is not an option.
Let’s imagine that we are only interested in the first 1000 samples of each AES round. Visual inspection of our 29.48 MS/s capture shows a clear periodicity from the AES rounds; this shows the first few rounds:
cw.plot(trace.wave[:15000])
From the waveform, we can confirm that the rounds are equally-spaced: they are exactly 20202 samples apart. We choose our capture parameters accordingly:
scope.adc.samples = 1000
scope.adc.segment_cycles = 20202
scope.adc.segment_cycle_counter_en = True
scope.adc.segments = 10
scope.adc.offset = 17654
With these settings, Husky will capture 1000 samples every 20202 cycles, 10 times, for a total of 10000 samples.
scope.gain.db = 22
fasttrace = cw.capture_trace(scope, target, bytearray(16), bytearray(16))
cw.plot(fasttrace.wave)
Voilà: now we can see a portion of each AES round at 26 samples per clock!
This is a toy example that’s probably not useful for an attack (AES attacks typically use leakage from either the first or the last round only).
For examples of segmented capture that are useful for attacks, look at our sca204 and sca205 ECC attack notebooks.
assert not scope.adc.errors, scope.adc.errors