Hello,
I am trying to implement the PA_HW_CW305_1-Attacking_AES_on_an_FPGA
notebook using the default setup with CW Husky, CW313, and CW312T-A35. However, the traces I am capturing appear to be entirely noise. I have experimented with various sample sizes, but the issue persists. Here is an image of the traces I am getting:
I was expecting to see all 10 rounds of AES in the simple power analysis trace, but that’s not happening. Can anyone identify the problem and suggest how to make all rounds clearly visible in the trace?
Here’s the code I’m using:
import chipwhisperer as cw
scope = cw.scope()
if scope._is_husky:
scope.adc.samples = 200
else:
scope.adc.samples = 129
scope.adc.offset = 0
scope.adc.basic_mode = "rising_edge"
scope.trigger.triggers = "tio4"
scope.io.tio1 = "serial_rx"
scope.io.tio2 = "serial_tx"
scope.io.hs2 = "disabled"
#TARGET_PLATFORM = 'CW305_100t'
#TARGET_PLATFORM = 'CW305_35t'
TARGET_PLATFORM = 'CW312T_A35'
#TARGET_PLATFORM = 'CW312T_ICE40'
if TARGET_PLATFORM in ['CW312T_A35', 'CW312T_ICE40']:
scope.io.hs2 = 'clkgen'
fpga_id = None # not needed
if TARGET_PLATFORM == 'CW312T_A35':
platform = 'ss2_a35'
scope.gain.db = 45 # this is a good setting for the inductive shunt; if using another, adjust as needed
else:
platform = 'ss2_ice40'
scope.gain.db = 15
else:
scope.gain.db = 25
scope.io.hs2 = "disabled"
platform = 'cw305'
if TARGET_PLATFORM == 'CW305_100t':
fpga_id = '100t'
elif TARGET_PLATFORM == 'CW305_35t':
fpga_id = '35t'
# On the CW305, setting force=False only programs the FPGA if it is currently unprogrammed, whereas force=True programs the FPGA regardless.
# This option isn't available on the CW312T_A35 or CW312T_ICE40.
target = cw.target(scope, cw.targets.CW305, force=True, fpga_id=fpga_id, platform=platform)
if TARGET_PLATFORM in ['CW305_100t', 'CW305_35t']:
target.vccint_set(1.0)
# we only need PLL1:
target.pll.pll_enable_set(True)
target.pll.pll_outenable_set(False, 0)
target.pll.pll_outenable_set(True, 1)
target.pll.pll_outenable_set(False, 2)
# run at 10 MHz:
target.pll.pll_outfreq_set(10E6, 1)
# 1ms is plenty of idling time
target.clkusbautooff = True
target.clksleeptime = 1
if TARGET_PLATFORM in ['CW305_100t', 'CW305_35t']:
if scope._is_husky:
scope.clock.clkgen_freq = 40e6
scope.clock.clkgen_src = 'extclk'
scope.clock.adc_mul = 4
# if the target PLL frequency is changed, the above must also be changed accordingly
else:
scope.clock.adc_src = "extclk_x4"
if TARGET_PLATFORM in ['CW312T_A35', 'CW312T_ICE40']:
scope.clock.clkgen_freq = 7.37e6
scope.io.hs2 = 'clkgen'
if scope._is_husky:
scope.clock.clkgen_src = 'system'
scope.clock.adc_mul = 4
scope.clock.reset_dcms()
else:
scope.clock.adc_src = "clkgen_x4"
import time
time.sleep(0.1)
target._ss2_test_echo()
import time
for i in range(5):
scope.clock.reset_adc()
time.sleep(1)
if scope.clock.adc_locked:
break
assert (scope.clock.adc_locked), "ADC failed to lock"
project_file = "projects/Tutorial_HW_CW305.cwp"
project = cw.create_project(project_file, overwrite=True)
from tqdm.notebook import tnrange
import numpy as np
import time
from Crypto.Cipher import AES
ktp = cw.ktp.Basic()
traces = []
textin = []
keys = []
N = 50 # Number of traces
# initialize cipher to verify DUT result:
key, text = ktp.next()
cipher = AES.new(bytes(key), AES.MODE_ECB)
for i in tnrange(N, desc='Capturing traces'):
# run aux stuff that should come before trace here
key, text = ktp.next() # manual creation of a key, text pair can be substituted here
textin.append(text)
keys.append(key)
ret = cw.capture_trace(scope, target, text, key)
if not ret:
print("Failed capture")
continue
assert (list(ret.textout) == list(cipher.encrypt(bytes(text)))), "Incorrect encryption result!\nGot {}\nExp {}\n".format(ret.textout, list(text))
#trace += scope.getLastTrace()
traces.append(ret.wave)
project.traces.append(ret)