No trigger seen!

Trying to get the scope to trigger on transition from low to high on tio3.

 SCOPETYPE = 'OPENADC'
 
 import chipwhisperer as cw
 import matplotlib.pyplot as plt
 import time
 
 # Initialize CW
 scope = cw.scope()
 
 def cap_trig_trace(guess):
     power_cycle_target()
     scope.arm()
     ret = scope.capture()
     if ret:
         print('Timeout happened during acquisition')
     trace = scope.get_last_trace()
     return trace
 
 def power_cycle_target():
     print("Bouncing tio3")
     scope.io.tio3 = 0
     time.sleep(1.50)
     scope.io.tio3 = 1
     time.sleep(.50)
 
 
 # Initialize Target
 target = cw.target(scope)
 target.baud = 19200
 print("Target Baud =", target.baud)
 
 # turn off the target
 scope.io.tio3 = 0
 
 # 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 clock to 12Mhz
 scope.clock.clkgen_freq = 12000000
 
 # Set scope trigger to tio3, the pin used for power cycling the DUT
 scope.trigger = "tio3"
 
 def cap_trig_trace(guess):
     power_cycle_target()
     scope.arm()
     ret = scope.capture()
     if ret:
         print('Timeout happened during acquisition')
     trace = scope.get_last_trace()
     return trace
 
 def power_cycle_target():
     print("Bouncing tio3")
     scope.io.tio3 = 0
     time.sleep(1.50)
     scope.io.tio3 = 1
     time.sleep(.50)
 
 # 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()
 plt.plot(cap_pass_trace("\x00"))
 plt.plot(cap_pass_trace("\x01"))
 plt.show()

Result


image

The scope is not attached because I am not sure where to attach it to, but still should be getting the trigger?

Hi,

You’ll need to call scope.arm() before you call power_cycle_target(). The ChipWhisperer doesn’t start looking for the trigger until it’s armed.

Alex

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

Your best bet for a trigger is probably to trigger on the serial message, since the stuff you’re interested in should be roughly dependent on receiving that message. You’ll introduce a bit of jitter, which you can probably solve by resynchronizing your traces. We go over a basic technique for that in SCA201: https://github.com/newaetech/chipwhisperer-jupyter/blob/master/courses/sca201/Lab%201_1A%20-%20Resychronizing%20Traces%20with%20Sum%20of%20Absolute%20Difference.ipynb.

For the capture connection, it’s pretty important that you’ve got a shunt resistor between the DUT board power supply and the chip you’re looking at. Other than that, once you’re confident in the DUT’s operation, removing the decoupling capacitors will help a lot.

Reset target comes from https://github.com/newaetech/chipwhisperer-jupyter/blob/master/Setup_Scripts/Setup_Generic.ipynb. Some of the hardware we offer has different reset pins, which means how a target is reset depends on which target it is. Your power_cycle_target() function does the same thing, so you should be able to safely omit that function.

Also, for future reference, you can just do print(scope) to print all the scope settings.

Alex

There is no serial message, other than what is transmitted from the CW to the DUT. I guess there is an echo back. So trigger on the RX from the DUT? Rising edge? High/low? Low High? It is serial, I think a transition from high to low is what I want…? I am reviewing that link now.

Will something like this work?

https://www.amazon.com/gp/product/B07PMMX6MG/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

https://www.amazon.com/gp/product/B07F8RFMD4/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

I am running the CW and DUT from the same USB port, should I not do this?
Any recommendations on the shunt resistor? The datasheet does not say what the current draw is but the voltage can go as low as 2.0v, max 5.5v. 8 bit micro. Think I saw a general shunt resistor in a post somewhere but can’t remember where it was, let alone the value. A shunt resistor totally makes sense. How else will it measure the load? Value of shunt, location, VCC - Embedded Security - NewAE Forum … What does a shunt resistor look like?
Oh, I see some on Mouser. I don’t have any of these; can I barrow one from the ATMEGA Target board?

Thank you for the note on the reset_target(scope)… I have my own function that does the same thing.

I will change to print(scope) haha too easy.

Gracious for your response!

It’s better if you can trigger off a message from the target, since that will usually give lower jitter, but if you can only trigger off sending a message, that should work fine as well.

We typically do around 50 ohms for an 8bit micro, but you might need to size that down a bit to get full device functionality. Any regular resistor will work here - it doesn’t need to be a special type or anything. If you don’t have any resistors lying around, you can steal the one off a target board.

Hope that helps,

Alex

Thanks for the tips!

I am stuck on trigger now. The only way I can get a trigger is in the code above. Which is “low” on tio2, my transmit. I think I need to change it to “high” on tio1? How do I know the trigger condition is valid?

Is every call to scope.arm() setting up a new trace?

What is ending the capture in the current loop? Guess I need to go back and read scope again. There’s scope timeout and number of traces… if timeout is 10 and number of traces is 500, is that 500 traces over 10 seconds? I don’t think so.

Meanwhile, I will mess with shunt resistors to find highest level and still function. Remove any caps. Add the SAD function and run attack again.

Starting and Stopping the trace…

Off topic
I picked up the CW506 today. Not sure I will use it for this project but more than likely future one’s.
kinda cool.

There is 8.2v needed on the IRQ line of the target to put it into bootloader mode. This affects the power reading, I think, on the shunt. So maybe it will be better to use ground side for analysis. I think power on this pin will somehow feedback to the VCC pin. Let me verify this.

After poking around, adding resistors to VCC, the chip will source current it needs from the RX/TX pin (it uses same pin for communication). Not sure VCC scope is good. However tonight I get better numbers that before.

I typically avoid using “high” or “low” trigger, since that means the trigger can happen on an idle trigger line.
You can typically tell if your trigger is okay by the power trace you collect - if you can see the same shapes, but they don’t line up, you can usually fix it by post processing. If every power trace you collect looks completely different, your trigger probably isn’t good.

scope.arm() basically tells the capture end to start looking for a trigger. Once it sees that trigger, it starts collecting samples (determined by scope.adc.samples) and, once it’s done collecting those samples, we transfer the samples from the board to the PC.

Alex

I am losing ground on this script. Looking to add project using Lab5.1 as an example so I can use the analyzer and SAD on the traces as suggested… scope, trace, project, append traces, not clicking for me at the moment.

proj.traces.append(scope.get_last_trace())

Getting type error, expected trace but got {} and it shows a bunch of comma separated stuff.

Meanwhile I have the same chip where I know the password and would like to run analysis on that using a new script.

Starting new script.

Let’s say I need to pause 500ms between entering the characters for the password. If password length is 8 characters, that’s 4 seconds to enter the password. I think 500 samples runs out long before this.
What is needed to ensure I capture the whole password entry? 5000? 10000?

Note, print(scope) gives error

---> 83 print(scope)
     84 
     85 ####################

c:\revers~1\chipwh~3\cw\home\portable\chipwhisperer\software\chipwhisperer\capture\scopes\OpenADC.py in __str__(self)
    535 
    536     def __str__(self):
--> 537         return self.__repr__()
    538 
    539     def upgrade_firmware(self):

c:\revers~1\chipwh~3\cw\home\portable\chipwhisperer\software\chipwhisperer\capture\scopes\OpenADC.py in __repr__(self)
    529         if self._is_connected:
    530             ret = "%s Device\n" % self._getCWType()
--> 531             return ret + dict_to_str(self._dict_repr())
    532         else:
    533             ret = "ChipWhisperer/OpenADC device (disconnected)"

c:\revers~1\chipwh~3\cw\home\portable\chipwhisperer\software\chipwhisperer\capture\scopes\OpenADC.py in _dict_repr(self)
    510         dict['adc']     = self.adc._dict_repr()
    511         dict['clock']   = self.clock._dict_repr()
--> 512         dict['trigger'] = self.trigger._dict_repr()
    513         dict['io']      = self.io._dict_repr()
    514         dict['glitch']  = self.glitch._dict_repr()

AttributeError: 'str' object has no attribute '_dict_repr'

New scripts. First one enters one known character of the password (0xff). The second one enters an incorrect first character.

Posting resulting graphs on 2 runs. Hopefully there is some noticeable something in there. Please help.

Having problems with ‘project’ too, commented them out in second script.

It is odd I have to wait for the second test to complete before the graphs populate.

Script 1, 1 known character and 1 wrong character of password.
import chipwhisperer as cw

%matplotlib notebook
import matplotlib.pyplot as plt

import numpy as np
import time

# Globals
trace = 0
ref_trace = 0
ON  = 0
OFF = 1
OFFTIMEDELAY      = 1.50
ONTIMEDELAY       = 1.00
PROJECTFILENAME   = "KnownPassword_1Char"

# Initialize CW
scope = cw.scope()
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

scope.default_setup()
scope.adc.samples = 500
scope.adc.timeout = 3
scope.clock.clkgen_freq = 12000000
scope.clock.extclk_freq = 12000000
scope.trigger = "tio4"
scope.io.tio3 = "gpio_low"
scope.io.tio4 = "gpio_low"
scope.adc.basic_mode = "rising_edge"

# 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.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)
#print(scope)

####################
# Define functions #
####################
def cap_pass_trace(pass_guess):
    power_cycle_target()
    scope.arm()

    #print(hex(ord(pass_guess)))

    #print("Sending...")
    scope.io.tio4 = 1
    target.write(pass_guess)
    scope.io.tio4 = 0
    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(OFFTIMEDELAY)
    #print("ON")
    scope.io.tio3 = ON
    time.sleep(ONTIMEDELAY)

    
def read80():
    response_text = ""
    target.write("\x4a")
    time.sleep(0.250)
    target.write("\x00")
    time.sleep(0.250)
    target.write("\x80")
    time.sleep(0.250)

    if (target.in_waiting() > 0):
        print("Response from Read: ")
        
    ##while (target.in_waiting() > 0):
    ##    print(" ".join(hex(ord(n)) for n in target.read(target.in_waiting())))
    while (target.in_waiting() > 0):
        response_text = target.read(target.in_waiting())
    print(" ".join(hex(ord(n)) for n in response_text))
    if (response_text[-1] != "\x3f"):
        print("Last char was NOT 0x3f!")
        print(" ".join(hex(ord(n)) for n in response_text))
        scope.dis()
        target.dis()
        while(1):
            a = 1

# Configure TARGET
target = cw.target(scope, cw.targets.SimpleSerial) #cw.targets.SimpleSerial can be omitted
target.baud = 19200

#Create Project
#proj = cw.create_project(PROJECTFILENAME, overwrite=True)

# Test 1
plt.figure()
time.sleep(0.1)
ref_trace = cap_pass_trace("\xFF")
plt.title("Known Password - Good First Char") 
plt.plot(ref_trace,'g')
plt.show()

# Test 2
time.sleep(2.0)
plt.figure()
other_trace = cap_pass_trace("\x45")
plt.title("Known Password - Wrong First Char") 
plt.plot(other_trace, 'r')
plt.show()


# done
scope.io.tio3 = OFF
scope.dis()
target.dis()

Run 1



Run 2

Script 2, Good password, all 8 characters and wrong password, all 8 characters.
import chipwhisperer as cw

%matplotlib notebook
import matplotlib.pyplot as plt

import numpy as np
import time

# Globals
trace = 0
ref_trace = 0
ON  = 0
OFF = 1
OFFTIMEDELAY      = 1.50
ONTIMEDELAY       = 1.00
DELAYBETWEENCHARS = 1.00
#PROJECTFILENAME   = "KnownPassword_8Chars"

# Initialize CW
scope = cw.scope()
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

scope.default_setup()
scope.adc.samples = 5000
scope.adc.timeout = 3
scope.clock.clkgen_freq = 12000000
scope.clock.extclk_freq = 12000000
scope.trigger = "tio4"
scope.io.tio3 = "gpio_low"
scope.io.tio4 = "gpio_low"
scope.adc.basic_mode = "rising_edge"

# Print Scope settings  (print(scope) errors)
print("scope.adc.state           = ", scope.adc.state)
print("scope.adc.samples         = ", scope.adc.samples)
print("scope.adc.timeout         = ", scope.adc.timeout)
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)

####################
# Define functions #
####################
def cap_pass_trace_correct():
    power_cycle_target()
    scope.arm()

    scope.io.tio4 = 1   # Trigger Scope
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x0FF")
    scope.io.tio4 = 0
    ret = scope.capture()
    if ret:
        print('Timeout happened during acquisition')

    trace = scope.get_last_trace()
    return trace

def cap_pass_trace_wrong():
    power_cycle_target()
    scope.arm()

    #print(hex(ord(pass_guess)))
    scope.io.tio4 = 1
    target.write("\x045")  # E
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x043")  # C
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x050")  # P
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x050")  # P
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x043")  # C
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x04a")  # J
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x046")  # F
    time.sleep(DELAYBETWEENCHARS)
    target.write("\x054")  # T
    scope.io.tio4 = 0
    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(OFFTIMEDELAY)
    #print("ON")
    scope.io.tio3 = ON
    time.sleep(ONTIMEDELAY)

    
def read80():
    response_text = ""
    target.write("\x4a")
    time.sleep(0.250)
    target.write("\x00")
    time.sleep(0.250)
    target.write("\x80")
    time.sleep(0.250)

    if (target.in_waiting() > 0):
        print("Response from Read: ")
        
    ##while (target.in_waiting() > 0):
    ##    print(" ".join(hex(ord(n)) for n in target.read(target.in_waiting())))
    while (target.in_waiting() > 0):
        response_text = target.read(target.in_waiting())
    print(" ".join(hex(ord(n)) for n in response_text))
    if (response_text[-1] != "\x3f"):
        print("Last char was NOT 0x3f!")
        print(" ".join(hex(ord(n)) for n in response_text))
        scope.dis()
        target.dis()
        while(1):
            a = 1

# Configure TARGET
target = cw.target(scope, cw.targets.SimpleSerial) #cw.targets.SimpleSerial can be omitted
target.baud = 19200

#Create Project
#proj = cw.create_project(PROJECTFILENAME, overwrite=True)

# Test 1
plt.figure()
time.sleep(0.1)
ref_trace = cap_pass_trace_correct()
#proj.traces.append(ref_trace)
plt.title("Known Password - Good") 
plt.plot(ref_trace,'g')
plt.show()

# Test 2
plt.figure()
time.sleep(0.1)
other_trace = cap_pass_trace_wrong()
plt.title("Known Password - Wrong") 
plt.plot(other_trace, 'r')
plt.show()


# done
scope.io.tio3 = OFF  # Turn off Target
scope.dis()
target.dis()
#project.save()

Run 1



Run 2

If there was a way to align the traces…

image

Try doing proj.traces.append(cw.Trace(scope.get_last_trace(), None, None, None))). I’ve added some additional error messages to this to make this requirement more clear.

You’ll need to capture 8 separate traces. You can convert samples to time via the formula scope.adc.samples/scope.clock.adc_freq. 1 second will be somewhere in the range of tens of millions of samples.

Try switching scope.trigger = "tio2" to scope.trigger.triggers = "tio2". I’ll change these modules so that they’re read-only to prevent this in the future.

Thanks,

Alex