API

This is where the documentation for the public API functions, and classes lives.

Scope

The chipwhisperer.scope() API function creates and returns a scope object based on the supplied type argument. The are two currently supported classes for the type argument:

The OpenADC scope provides support for the ChipWhisperer Lite and the ChipWhisperer Pro, and the CWNano scope provides support for the ChipWhisperer Nano.

The scope object provides the API for configuring the capture side of the hardware (the scope). To create an instance of a connected scope use:

import chipwhisperer as cw
scope = cw.scope()

This will return a connected instance of one of the scope types or raise an exception. If no scope type is given the function will try to determine the scope type automatically.

scope chipwhisperer.scope(type=None, sn=None)

Create a scope object and connect to it.

This function allows any type of scope to be created. By default, the object created is based on the attached hardware (OpenADC for CWLite/CW1200, CWNano for CWNano).

Scope Types:

If multiple chipwhisperers are connected, the serial number of the one you want to connect to can be specified by passing sn=<SERIAL_NUMBER>

Parameters:
  • scope_type (ScopeTemplate, optional) – Scope type to connect to. Types can be found in chipwhisperer.scopes. If None, will try to detect the type of ChipWhisperer connected. Defaults to None.
  • sn (str, optional) – Serial number of ChipWhisperer that you want to connect to. Required if more than one ChipWhisperer of the same type is connected (i.e. two CWNano’s or a CWLite and CWPro). Defaults to None.
Returns:

Connected scope object.

Raises:
  • OSError – Can be raised for issues connecting to the chipwhisperer, such as not having permission to access the USB device or no ChipWhisperer being connected.
  • Warning – Raised if multiple chipwhisperers are connected, but the type and/or the serial numbers are not specified

Changed in version 5.1: Added autodetection of scope_type

OpenADC Scope

class OpenADC

OpenADC scope object.

This class contains the public API for the OpenADC hardware, including the ChipWhisperer Lite/ CW1200 Pro boards. It includes specific settings for each of these devices.

To connect to one of these devices, the easiest method is:

import chipwhisperer as cw
scope = cw.scope(type=scopes.OpenADC)

Some sane default settings are available via:

scope.default_setup()

This code will automatically detect an attached ChipWhisperer device and connect to it.

For more help about scope settings, try help() on each of the ChipWhisperer scope submodules (scope.gain, scope.adc, scope.clock, scope.io, scope.trigger, and scope.glitch):

If you have a CW1200 ChipWhisperer Pro, you have access to some additional features:

gain scope.gain
db scope.gain.db

The gain of the ChipWhisperer’s low-noise amplifier in dB. Ranges from -6.5 dB to 56 dB, depending on the amplifier settings.

Getter:Return the current gain in dB (float)
Setter:Set the gain level in dB
Raises:ValueError – if new gain is outside of [-6.5, 56]

Examples:

# reading and storing
gain_db = scope.gain.db

# setting
scope.gain.db = 20
mode scope.gain.mode

The current mode of the LNA.

The LNA can operate in two modes: low-gain or high-gain. Generally, the high-gain setting is better to use. Note that this value will be automatically updated if the dB gain is set.

Getter:Return the current gain mode (“low” or “high”)
Setter:Set the gain mode
Raises:ValueError – if mode not one of “low” or “high”
gain scope.gain.gain

The current LNA gain setting.

This gain is a dimensionless number in the range [0, 78]. Higher value causes higher gain in dB.

Note that this function is unnecessary - the dB gain can be set directly. This property is only here to help convert old scripts.

Getter:Return the current gain setting (int)
Setter:Set the gain
Raises:ValueError – if gain outside [0, 78]
adc scope.adc
state scope.trigger.state

The current state of the trigger input.

This is a digital value (ie: high or low), which is some combination of the pins in the triggermux object. Read-only.

Getter: Return the current state (True or False).

stream_mode scope.trigger.stream_mode

The ChipWhisperer’s streaming status. Only available on CW1200.

When stream mode is enabled, the ChipWhisperer sends back ADC data as soon as it is recorded. In this mode, there is no hardware limit on the maximum number of samples per trace (although Python may run out of memory when recording billions of points). However, there is a maximum streaming data rate, which is approximately 10 Msamp/s.

Note that no pre-trigger samples can be recorded when stream mode is enabled.

Getter:Return True if stream mode is enabled and False otherwise
Setter:Enable or disable stream mode
decimate scope.trigger.decimate

The ADC downsampling factor.

This value instructs the ChipWhisperer to only record 1 sample in every <decimate>. In other words, if this value is set to 10, the sampling rate is set to 1/10th of the sampling clock.

This setting is helpful for recording very long operations or for reducing the sampling rate for streaming mode.

Getter:Return an integer with the current decimation factor
Setter:Set the decimation factor
Raises:ValueError – if the new factor is not positive
samples scope.trigger.samples

The number of ADC samples to record in a single capture.

The maximum number of samples is hardware-dependent: - cwlite: 24400 - cw1200: 96000

Getter:Return the current number of total samples (integer)
Setter:Set the number of samples to capture
Raises:ValueError – if number of samples is negative
timeout scope.trigger.timeout

The number of seconds to wait before aborting a capture.

If no trigger event is detected before this time limit is up, the capture fails and no data is returned.

Getter:Return the number of seconds before a timeout (float)
Setter:Set the timeout in seconds
offset scope.trigger.offset

The number of samples to before recording data after seeing a trigger event.

This offset is useful for long operations. For instance, if an encryption is 1 million samples long, it’s difficult to capture the entire power trace, but an offset can be used to skip to the end of the encryption.

The offset must be a 32 bit unsigned integer.

Getter:Return the current offset (integer)
Setter:Set a new offset
Raises:ValueError – if offset outside of range [0, 2**32)
presamples scope.trigger.presamples

The number of samples to record from before the trigger event.

This setting must be a positive integer, and it cannot be larger than the number of samples. When streaming mode is enabled, this value is set to 0.

Getter:Return the current number of presamples
Setter:Set the number of presamples.
Raises:ValueError – if presamples is outside of range [0, samples]
basic_mode scope.trigger.basic_mode

The type of event to use as a trigger.

There are four possible types of trigger events:
  • “low”: triggers when line is low (logic 0)
  • “high”: triggers when line is high (logic 1)
  • “rising_edge”: triggers when line transitions from low to high
  • “falling_edge:” triggers when line transitions from high to low

Warning

This must be set to “rising_edge” if a trigger other than “basic” is used. The SAD/DecodeIO triggers will not work with any other setting!

Getter:Return the current trigger mode (one of the 4 above strings)
Setter:Set the trigger mode
Raises:ValueError – if value is not one of the allowed strings
trig_count scope.trigger.trig_count

The number of samples that the trigger input was active.

This value indicates how long the trigger was high or low last time a trace was captured. It is the number of samples where the input was low (in “low” or “falling edge” modes) or high (in “high” or “rising edge” modes). Read-only.

This counter is not meaningful if the trigger is still active.

Getter:Return the last trigger duration (integer)
clock scope.clock
adc_src scope.clock.adc_src

The clock source for the ADC module.

The ADC can be clocked by one of five possible sources:
  • “clkgen_x1”: CLKGEN output via DCM
  • “clkgen_x4”: CLKGEN output via DCM with x4 clk multiplier
  • “extclk_x1”: External clock input via DCM
  • “extclk_x4”: External clock input via DCM with x4 clk multiplier
  • “extclk_dir”: External clock input with no DCM
Getter:Return the current ADC clock source (one of five strings above)
Setter:Set the ADC clock source and reset the ADC DCM to lock it.
Raises:ValueError – if string not in valid settings
adc_phase scope.clock.adc_phase

Fine adjustment for the ADC sampling point.

This setting moves the sampling point approximately 5 ns forward or backward, regardless of the sampling frequency. It may be helpful to improve the stability of the measurement.

The value of this setting is dimensionless and has a non-linear effect on the phase adjustment.

Getter:

Return the current phase setting (integer) NOTE: This getter is currently broken due to an FPGA bug.

Setter:

Set a new phase offset

Raises:
  • ValueError – if offset not in [-255, 255]
  • TypeError – if offset not integer
adc_freq scope.clock.adc_freq

The current frequency of the ADC clock in Hz. Read-only.

This clock frequency is derived from one of the ADC clock sources as described in adc_src.

Getter:Return the current frequency in MHz (float)
adc_rate scope.clock.adc_rate

The current sampling rate of the ADC clock in samples/s. Read-only.

Note that the sampling rate may be less than the clock frequency if the downsampling factor is greater than 1.

Getter:Return the current sampling rate in MS/s (float)
adc_locked scope.clock.adc_locked

The current status of the ADC DCM. Read-only.

To try re-locking the ADC, see reset_adc().

Getter:Return whether the ADC DCM is locked (True or False)
freq_ctr scope.clock.freq_ctr

The current frequency at the frequency counter in MHz. Read-only.

The frequency counter can be used to check the speed of the CLKGEN output or the EXTCLK input. This value shows the current frequency reading.

Getter:Return the current frequency in MHz (float)
freq_ctr_src scope.clock.freq_ctr_src

The current input to the frequency counter.

There are two possible inputs to the frequency counter: - “clkgen”: The CLKGEN DCM output - “extclk”: The external input clock signal

Getter:Return the frequency counter input (one of the above strings)
Setter:Set the frequency counter source
Raises:ValueError – if source is not “clkgen” or “extclk”
clkgen_src scope.clock.clkgen_src

The input source for the CLKGEN DCM.

This DCM can receive input from one of two places: - “extclk”: The external clock input - “system” or “internal”: The system clock (96 MHz)

Getter:Return the current CLKGEN input (either “extclk” or “system”)
Setter:Change the CLKGEN source and reset all the DCMs.
Raises:ValueError – if source is not one of three strings above
extclk_freq scope.clock.extclk_freq

The input frequency from the EXTCLK source in Hz.

This value is used to help calculate the correct CLKGEN settings to obtain a desired output frequency when using EXTCLK as CLKGEN input. It is not a frequency counter - it is only helpful if the EXTCLK frequency is already known.

Getter:Return the last set EXTCLK frequency in MHz (int)
Setter:Update the EXTCLK frequency
clkgen_mul scope.clock.clkgen_mul

The multiplier in the CLKGEN DCM.

This multiplier must be in the range [2, 256].

Getter:Return the current CLKGEN multiplier (integer)
Setter:Set a new CLKGEN multiplier.
clkgen_div scope.clock.clkgen_div

The divider in the CLKGEN DCM.

This divider must be in the range [1, 256].

Getter:Return the current CLKGEN divider (integer)
Setter:Set a new CLKGEN divider.
clkgen_freq scope.clock.clkgen_freq

The CLKGEN output frequency in Hz.

The CLKGEN module takes the input source and multiplies/divides it to get a faster or slower clock as desired.

Getter:Return the current calculated CLKGEN output frequency in Hz (float). Note that this is the theoretical frequency - use the freq counter to determine the actual output.
Setter:Attempt to set a new CLKGEN frequency in Hz. When this value is set, all possible DCM multiply/divide settings are tested to find which is closest to the desired output speed. If EXTCLK is the CLKGEN source, the EXTCLK frequency must be properly set for this to work. Also, both DCMs are reset.
clkgen_locked scope.clock.clkgen_locked

The current status of the CLKGEN DCM. Read-only.

Getter:Return whether the CLKGEN DCM is locked (True or False)
io scope.io
tio1 scope.io.tio1

The function of the Target IO1 pin.

TIO1 can be used for the following functions:
  • “serial_rx”: UART input
  • “serial_tx”: UART output
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “serial_rx”.

Getter:Return one of the above strings
Setter:Set the Target IO1 mode.
Raises:ValueError – if new value is not one of the above modes
tio2 scope.io.tio2

The function of the Target IO2 pin.

TIO2 can be used for the following functions:
  • “serial_rx”: UART input
  • “serial_tx”: UART output
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “serial_tx”.

Getter:Return one of the above strings
Setter:Set the Target IO2 mode.
Raises:ValueError – if new value is not one of the above modes
tio3 scope.io.tio3

The function of the Target IO3 pin.

TIO3 can be used for the following functions:
  • “serial_rx”: UART input
  • “serial_tx”: UART output
  • “serial_tx_rx”: UART 1-wire I/O (for smartcards)
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “high_z”.

Getter:Return one of the above strings
Setter:Set the Target IO3 mode.
Raises:ValueError – if new value is not one of the above modes
tio4 scope.io.tio4

The function of the Target IO4 pin.

TIO4 can be used for the following functions:
  • “serial_tx”: UART output
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “high_z”. Typically, this pin is used as a trigger input.

Getter:Return one of the above strings
Setter:Set the Target IO4 mode
Raises:ValueError – if new value is not one of the above modes
pdid scope.io.pdid

The state of the PDID pin.

See pdic for more information.

pdic scope.io.pdic

The state of the PDIC pin output pin.

This is a GPIO pin. The following values are allowed:
  • “high” / True: logic 1
  • “low” / False: logic 0
  • “disabled” / “default” / “high_z” / None: undriven
Getter:Return one of “high”, “low”, or “high_z”
Setter:Set the pin’s state

Raises: ValueError: if new state not listed above

nrst scope.io.nrst

The state of the NRST pin.

See pdic for more information.

glitch_hp scope.io.glitch_hp

Whether the high-power crowbar MOSFET is enabled.

The glitch output is an SMA-connected output line that is normally connected to a target’s power rails. If this setting is enabled, a high-powered MOSFET shorts the power-rail to ground when the glitch module’s output is active.

Warning

Use with caution - ensure that the glitch module is properly configured before enabling this setting, as it is possible to permanently damage hardware with this output.

Getter:Return True if enabled or False if disabled
Setter:Turn the high-power MOSFET on or off
extclk_src scope.io.extclk_src

The clock signal being used as input for EXTCLK.

Currently, this can only be HS1, which is the clock from the target. As such, this value is read-only.

hs2 scope.io.hs2

The clock signal routed to the HS2 high speed output pin.

Allowed clock signals are:
  • “clkgen”: The output from the CLKGEN module
  • “glitch”: The output from the glitch module
  • “disabled” / None: No clock; output driven low
Getter:Return one of “clkgen”, “glitch”, or “disabled”
Setter:Set the clock to be output on HS2.

Raises: ValueError: if new value not listed above

target_pwr scope.io.target_pwr

Whether the target board is powered by the ChipWhisperer.

If True, the ChipWhisperer is currently supplying power to the target board; if False, it is not. This setting can be used to cycle power to the target or to help program it.

If the target board is powered through an external supply, this setting may have no effect.

Getter:Return the current power state of the target (True or False)
Setter:Turn the target power on or off.
trigger scope.trigger
triggers scope.trigger.triggers

The logical input into the trigger module.

The trigger module uses some combination of the scope’s I/O pins to produce a single value, which it uses for edge/level detection or UART triggers. This trigger output can combine 5 pins using one of 3 different boolean operations.

Pins:
  • tio1-4: Target I/O pins 1-4. Note that these pins can be in any mode.
  • sma: An auxiliary SMA input, if available (only on CW1200)
Boolean operations:
  • OR: True if any inputs are True; False if none are
  • AND: True if all inputs are True; False if any are not
  • NAND: False if all inputs are True; True if any are not

Note that only one boolean operation can be used over all input pins.

Examples of acceptable trigger inputs:
  • “tio1”
  • “tio3 OR tio4”
  • “tio1 NAND tio2 NAND sma”
Examples of unallowed trigger inputs:
  • “tio1 tio2”
  • “tio1 AND tio2 OR tio3”
  • “tio1 OR tio1”
  • “tio1 XOR tio2”
  • “serial-tx”
Getter:Return a string describing the trigger mode (see examples)
Setter:Set the trigger mode using a string like the ones above
Raises:ValueError – if string cannot be converted to a legal mode
module scope.trigger.module

The trigger module in use.

The trigger modules available depend on the hardware. On the CWLite, only the basic trigger module can be used; on the CW1200, the serial data and SAD triggers are available too.

Available trigger modules:
  • ‘basic’: Trigger on a logic level or edge
Getter:Returns ‘basic’
glitch scope.glitch
clk_src scope.glitch.clk_src

The clock signal that the glitch DCM is using as input.

This DCM can be clocked from two different sources:
  • “target”: The HS1 clock from the target device
  • “clkgen”: The CLKGEN DCM output
Getter:Return the clock signal currently in use
Setter:Change the glitch clock source
Raises:ValueError – New value not one of “target” or “clkgen”
width scope.glitch.width

The width of a single glitch pulse, as a percentage of one period.

One pulse can range from -49.8% to roughly 49.8% of a period. The system may not be reliable at 0%. Note that negative widths are allowed; these act as if they are positive widths on the other half of the clock cycle.

Getter:Return a float with the current glitch width.
Setter:Update the glitch pulse width. The value will be adjusted to the closest possible glitch width.
Raises:UserWarning – Width outside of [-49.8, 49.8]. The value is rounded to one of these
width_fine scope.glitch.width_fine

The fine adjustment value on the glitch width.

This is a dimensionless number that makes small adjustments to the glitch pulses’ width. Valid range is [-255, 255].

Warning

This value is write-only. Reads will always return 0.

Getter:

Returns 0

Setter:

Update the glitch fine width

Raises:
  • TypeError – offset not an integer
  • ValueError – offset is outside of [-255, 255]
offset scope.glitch.offset

The offset from a rising clock edge to a glitch pulse rising edge, as a percentage of one period.

A pulse may begin anywhere from -49.8% to 49.8% away from a rising edge, allowing glitches to be swept over the entire clock cycle.

Getter:

Return a float with the current glitch offset.

Setter:

Set the glitch offset. The new value is rounded to the nearest possible offset.

Raises:
  • TypeError – offset not an integer
  • UserWarning – value outside range [-50, 50] (value is rounded)
offset_fine scope.glitch.offset_fine

The fine adjustment value on the glitch offset.

This is a dimensionless number that makes small adjustments to the glitch pulses’ offset. Valid range is [-255, 255].

Warning

This value is write-only. Reads will always return 0.

Getter:

Returns 0

Setter:

Update the glitch fine offset

Raises:
  • TypeError – if offset not an integer
  • ValueError – if offset is outside of [-255, 255]
trigger_src scope.glitch.trigger_src

The trigger signal for the glitch pulses.

The glitch module can use four different types of triggers:
  • “continuous”: Constantly trigger glitches
  • “manual”: Only trigger glitches through API calls/GUI actions
  • “ext_single”: Use the trigger module. One glitch per scope arm.
  • “ext_continuous”: Use the trigger module. Many glitches per arm.
Getter:Return the current trigger source.
Setter:Change the trigger source.
Raises:ValueError – value not listed above.
arm_timing scope.glitch.arm_timing

When to arm the glitch in single-shot mode.

If the glitch module is in “ext_single” trigger mode, it must be armed when the scope is armed. There are two timings for this event:

  • “before_scope”: The glitch module is armed first.
  • “after_scope”: The scope is armed first. This is the default.

This setting may be helpful if trigger events are happening very early.

If the glitch module is not in external trigger single-shot mode, this setting has no effect.

Getter:Return the current arm timing (“before_scope” or “after_scope”)
Setter:Change the arm timing
Raises:ValueError – if value not listed above
ext_offset scope.glitch.ext_offset

How long the glitch module waits between a trigger and a glitch.

After the glitch module is triggered, it waits for a number of clock cycles before generating glitch pulses. This delay allows the glitch to be inserted at a precise moment during the target’s execution to glitch specific instructions.

Note

It is possible to get more precise offsets by clocking the glitch module faster than the target board.

This offset must be in the range [0, 2**32).

Getter:

Return the current external trigger offset.

Setter:

Set the external trigger offset.

Raises:
  • TypeError – if offset not an integer
  • ValueError – if offset outside of range [0, 2**32)
repeat scope.glitch.repeat

The number of glitch pulses to generate per trigger.

When the glitch module is triggered, it produces a number of pulses that can be combined with the clock signal. This setting allows for the glitch module to produce stronger glitches (especially during voltage glitching).

Repeat counter must be in the range [1, 255].

Getter:

Return the current repeat value (integer)

Setter:

Set the repeat counter

Raises:
  • TypeError – if value not an integer
  • ValueError – if value outside [1, 255]
output scope.glitch.output

The type of output produced by the glitch module.

There are 5 ways that the glitch module can combine the clock with its glitch pulses:

  • “clock_only”: Output only the original input clock.
  • “glitch_only”: Output only the glitch pulses - do not use the clock.
  • “clock_or”: Output is high if either the clock or glitch are high.
  • “clock_xor”: Output is high if clock and glitch are different.
  • “enable_only”: Output is high for glitch.repeat cycles.
Some of these settings are only useful in certain scenarios:
  • Clock glitching: “clock_or” or “clock_xor”
  • Voltage glitching: “glitch_only” or “enable_only”
Getter:Return the current glitch output mode (one of above strings)
Setter:Change the glitch output mode.
Raises:ValueError – if value not in above strings
SAD scope.SAD - CW1200 Pro Only

Communicates with and drives the Sum of Absolute Differences module on the ChipWhisperer Pro.

Example for triggering off of some previously collected scope data:

scope.SAD.reference = trace.wave[1000:1000+128]
scope.SAD.threshold = 5000
scope.SAD.start()
scope.trigger.module = "SAD"
scope.adc.basic_mode = "rising_edge"

#can now capture as normal
trace = cw.capture_trace(scope, target, text, key)
threshold scope.SAD.threshold

The threshold for the SAD trigger.

The threshold has a maximum value of 100 000. You should set the reference waveform via SAD.reference before setting this value.

Getter:

Return the current threshold

Setter:

Set the current threshold

Raises:
  • ValueError – The user attempted to set a threshold above 100 000
  • IOError – User attempted to set the threshold before the reference waveform.
reference scope.SAD.reference

Set the reference data for the SAD Trigger.

The reference must be 128 samples long. Through this interface, it is represented as a numpy array of floats between -0.5 and 0.5 (the same as trace data).

Getter:Gets the currently set SAD reference
Setter:Sets the SAD reference
Raises:ValueError – Data not 128 samples long
SAD.start()

Starts the SAD module. Must be done each time after changing the reference waveform.

DecodeIO scope.DecodeIO - CW1200 Pro Only

Communicates with and drives the Digital Pattern Match module on the ChipWhisperer Pro.

Basic usage for triggering on ‘r\n’:

# assuming setup scope
scope.trigger.triggers = 'tio1'
scope.trigger.module = 'DECODEIO'
scope.decode_IO.rx_baud = 38400
scope.decode_IO.decode_type = 'USART'
scope.decode_IO.trigger_pattern = ['r', '\n']
trigger_pattern scope.DecodeIO.trigger_pattern

The pattern to trigger off of.

Getter:Get the currently set trigger pattern
Setter:Sets the trigger pattern. Expects a list of ASCII characters/ints. ints in this list are equivalent to their corresponding ASCII representation. For example, [0x10] is the same as [‘\n’].

Warns the user if they try to set an incorrect pattern.

Example to trigger off of ‘r\n’:

scope.decode_IO.trigger_pattern = ['r', 0x10]
rx_baud scope.DecodeIO.rx_baud

The baud rate of the serial data to trigger off of

The baud rate can be between 0 and 1E6

Getter:Gets the set baud rate
Setter:Sets the baud rate
Raises:ValueError – User attempted to set baud rate out of bounds
default_setup()

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

New in version 5.1: Added default setup for OpenADC

arm()

Setup scope to begin capture/glitching when triggered.

The scope must be armed before capture or glitching (when set to ‘ext_single’) can begin.

Raises:
  • OSError – Scope isn’t connected.
  • Exception – Error when arming. This method catches these and disconnects before reraising them.
capture()

Captures trace. Scope must be armed before capturing.

Returns:True if capture timed out, false if it didn’t.
Raises:IOError – Unknown failure.
get_last_trace()

Return the last trace captured with this scope.

Returns:Numpy array of the last capture trace.
dis()

Disconnects the current scope object.

Returns:A boolean of whether the disconnect was successful.
con(sn=None)

Connects to attached chipwhisperer hardware (Lite or Pro)

Parameters:

sn – The serial number of the attached device. Does not need to be specified unless there are multiple device attached.

Returns:

A boolean of whether the connection was successful.

Raises:
OSError:Raised when there is issues connecting to the hardware, such as user not having the correct device permissions to access the hardware.

ChipWhisperer Nano Scope

class CWNano

CWNano scope object.

This class contains the public API for the CWNano hardware. It includes specific settings for each of these devices.

To connect to one of these devices, the easiest method is:

import chipwhisperer as cw
scope = cw.scope(type=scopes.CWNano)

Some sane default settings can be set using:

scope.default_setup()

For more help about scope settings, try help() on each of the ChipWhisperer scope submodules (scope.adc, scope.io, scope.glitch):

adc scope.adc
samples scope.adc.samples

Number of samples to store.

clk_src scope.adc.clk_src

ADC Clock source.

Getter:Returns ‘int’ or ‘ext’ based on the clock source.
Setter:(str) Set the ADC clock source to either internal or external: (‘int’ or ‘ext’)
clk_freq scope.adc.clk_freq

Set the frequency for CLKOUT. Will be rounded to nearest possible values, check results to see programmed value. Set to ‘None’ for disabling (High-Z) output.

Getter:Returns the actual frequency for CLKOUT
Setter:Sets CLKOUT to the nearest possible value.
io scope.io
tio1 scope.io.tio1

The function of the Target IO1 pin.

TIO1 can be used for the following functions:
  • “serial_rx”: UART input
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “serial_rx”.

Getter:Return one of the above strings
Setter:Set the Target IO1 mode. Raises: ValueError if new value is not one of the above modes
tio2 scope.io.tio2

The function of the Target IO2 pin.

TIO2 can be used for the following functions:
  • “serial_tx”: UART output
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “serial_tx”.

Getter:Return one of the above strings
Setter:Set the Target IO2 mode. Raises: ValueError if new value is not one of the above modes
tio3 scope.io.tio3

The function of the Target IO3 pin.

TIO3 can be used for the following functions:
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “high_z”.

Getter:Return one of the above strings
Setter:Set the Target IO3 mode. Raises: ValueError if new value is not one of the above modes
tio4 scope.io.tio4

The function of the Target IO4 pin.

TIO4 can be used for the following functions:
  • “high_z” / None: High impedance input
  • “gpio_low” / False: Driven output: logic 0
  • “gpio_high” / True: Driven output: logic 1
  • “gpio_disabled”: Driven output: no effect

Default value is “high_z”. Typically, this pin is used as a trigger input.

Getter:Return one of the above strings
Setter:Set the Target IO4 mode Raises: ValueError if new value is not one of the above modes
pdid scope.io.pdid

The state of the PDID pin.

See pdic for more information.

pdic scope.io.pdic

The state of the PDIC pin output pin.

This is a GPIO pin. The following values are allowed:
  • “high” / True: logic 1
  • “low” / False: logic 0
  • “disabled” / “default” / “high_z” / None: undriven
Getter:Return one of “high”, “low”, or “high_z”
Setter:Set the pin’s state Raises: ValueError if new state not listed above
nrst scope.io.nrst

The state of the NRST pin.

See pdic for more information.

clkout scope.io.clkout

“Set the frequency for CLKOUT. Will be rounded to nearest possible values, check results to see programmed value. Set to ‘None’ for disabling (High-Z) output.

glitch scope.glitch
ext_offset scope.glitch.ext_offset

Offset from rising edge of trigger & when glitch gets inserted, approx = 8.3 ns * ext_offset

repeat scope.glitch.repeat

Width of glitch in cycles (approx = 8.3 ns * width)

default_setup()

Sets up sane capture defaults for this scope

  • 7.5MHz ADC clock
  • 7.5MHz output clock
  • 5000 capture samples
  • tio1 = serial rx
  • tio2 = serial tx
  • glitch module off

New in version 5.1: Added default setup for CWNano

arm()

Arm the ADC, the trigger will be GPIO4 rising edge (fixed trigger).

capture()

Raises IOError if unknown failure, returns ‘True’ if timeout, ‘False’ if no timeout

get_last_trace()

Return the last trace captured with this scope.

dis()

Disconnects the current scope object.

Returns:A boolean of whether the disconnect was successful.
con(sn=None)

Connects to attached chipwhisperer hardware (ChipWhisperer Nano)

Parameters:

sn – The serial number of the attached device. Does not need to be specified unless there are multiple device attached.

Returns:

A boolean of whether the connection was successful.

Raises:
OSError:Raised when there is issues connecting to the hardware, such as user not having the correct device permissions to access the hardware.

Firmware Update

On some occasions it is necessary to reprogram the scope of the ChipWhisperer Nano, Lite or Pro.

Warning

This is not necessary most of the time. It should be only done if you know exactly what you are doing. This process will erase the firmware on the scope and make it unusable until reprogrammed.

See also

The manual way of updating the SAM3U Firmware can be found on the wiki.

class SAMFWLoader(scope=None)

Object for easy reprogramming of ChipWhisperers

Despite the name of the file, this will work with the Lite, the Pro, and the Nano. If the ChipWhisperer has already been erased, pass None instead of the scope object and skip the enter_bootloader() call.

Example

  1. Attach the scope part of the hardware to your computer.

  2. Connect to the scope using:

    import chipwhisperer as cw
    
    # For the ChipWhisperer Lite or Pro
    scope = cw.scope(scope_type=cw.scopes.OpenADC)
    
    # For the ChipWhisperer Nano
    scope = cw.scope(scope_type=cw.scopes.CWNano)
    
  3. Place the hardware in bootloader mode using:

    # use created scope object from previous step
    programmer = cw.SAMFWLoader(scope=scope)
    
    # WARNING: this will erase the firmware on the device
    # and make it unusable until reprogrammed.
    programmer.enter_bootloader(really_enter=True)
    
  4. Unplug then plug in the hardware into your computer again. The device should be shown as BOSSA in the device manager on Windows. Make not of the port number the BOSSA device is attached to (for example: COM1, or COM2, and so on)

  5. Program the SAM3U with:

    import chipwhisperer as cw
    programmer = cw.SAMFWLoader(scope=None)
    

    Two methods:

    1. Using the firmware_path:

      # the firmware file is included with chipwhisperer # and is in the .bin file in the # (ChipWhisperer Lite) chipwhispererhardwarecapturechipwhisperer-litesam3u_fwSAM3U_VendorExampleDebug # (ChipWhisperer Pro) # directory. programmer.program(<port>, <path to firmware file>)

    2. Using the hardware_type:

      programmer.program(<port>, hardware_type='cwlite')
      

    On linux instead of ‘COM#’ use the linux equivalent to a port ‘ttyASM#’ or equivalent.

  6. Once the programming is done. Unplug then plug in the hardware into your computer again. The device should show up as a ChipWhisperer again.

enter_bootloader(really_enter=False)

Enters the bootloader of the ChipWhisperer by erasing the flash

Only use this if you want to erase the scope’s firmware (i.e. the ChipWhisperer Lite). This does NOT erase the firmware of a target ( i.e. an STM32 target). Will raise a Warning the first time an erase is attempted and really_enter=False.

Parameters:really_enter (bool, optional) – If True, enter the bootloader without ever raising a warning. If False, raise a warning if this is the user’s first time calling it.
Raises:Warning – really_enter=False and user hasn’t seen this warning before
program(port, fw_path=None, hardware_type=None)

Program the ChipWhisperer with new firmware.

Parameters:
  • port (str) – Serial port that the ChipWhisperer bootloader is on
  • fw_path (str) – Path to firmware, if specified leave out hardware type.
  • hardware_type (str) – The type of hardware that you want to program. If specified leave out fw_path. Valid types: (cwlite, )

Target

The target object provides the interface for configuring the target device under test (DUT). Supported targets:

The Simple Serial target type provides the target interface for all targets that use a simple serial connection. A object can be created using:

import chipwhisperer as cw
scope = cw.scope()
target = cw.target(scope)

You now have access to the target configuration using the target variable.

target chipwhisperer.target(scope, target_type=targets.SimpleSerial, **kwargs)

Create a target object and connect to it.

Parameters:
  • scope (ScopeTemplate) – Scope object that we’re connecting to the target through.
  • target_type (TargetTemplate, optional) – Target type to connect to. Defaults to targets.SimpleSerial. Types can be found in chipwhisperer.targets.
  • **kwargs – Additional keyword arguments to pass to target setup. Rarely needed.
Returns:

Connected target object specified by target_type.

Simple Serial Target

class SimpleSerial

SimpleSerial target object.

This class contains the public API for a target that uses serial communication.

The easiest way to connect to the target is:

import chipwhisperer as cw
scope = cw.scope()
target = cw.target(scope)

The target is automatically connected to if the default configuration adequate.

For more help use the help() function with one of the submodules (target.baud, target.write, target.read, …).

write(data)

Writes data to the target over serial.

Parameters:data (str) – Data to write over serial.
Raises:Warning – Target not connected

New in version 5.1: Added target.write()

read(num_char=0, timeout=250)

Reads data from the target over serial.

Parameters:
  • num_char (int, optional) – Number of byte to read. If 0, read all data available. Defaults to 0.
  • timeout (int, optional) – How long in ms to wait before returning. If 0, block until data received. Defaults to 250.
Returns:

String of received data.

New in version 5.1: Added target.read()

simpleserial_wait_ack(timeout=500)

Waits for an ack from the target for timeout ms

Parameters:timeout (int, optional) – Time to wait for an ack in ms. If 0, block until we get an ack. Defaults to 500.
Raises:Warning – Target not connected.

New in version 5.1: Added target.simpleserial_wait_ack

simpleserial_write(cmd, num, end='\n')

Writes a simpleserial command to the target over serial.

Writes ‘cmd’ + ascii(num) + ‘end’ over serial. Flushes the read and write buffers before writing.

Parameters:
  • cmd (str) – String to start the simpleserial command with. For ‘p’.
  • num (bytearray) – Number to write as part of command. For example, the 16 byte plaintext for the ‘p’ command. Converted to ascii before being sent.
  • end (str, optional) – String to end the simpleserial command with. Defaults to ‘n’.

Example

Sending a ‘p’ command:

key, pt = ktp.new_pair()
target.simpleserial_write('p', pt)
Raises:Warning – Write attempted while disconnected or error during write.

New in version 5.1: Added target.simpleserial_write()

simpleserial_read(cmd, pay_len, end='\n', timeout=250, ack=True)

Reads a simpleserial command from the target over serial.

Reads a command starting with <start> with an ASCII encoded bytearray payload of length exp_len*2 (i.e. exp_len=16 for an AES128 key) and ending with <end>. Converts the payload to a bytearray. Will ignore non-ASCII bytes in the payload, but warn the user of them.

Parameters:
  • cmd (str) – Expected start of the command. Will warn the user if the received command does not start with this string.
  • pay_len (int) – Expected length of the returned bytearray in number of bytes. Note that SimpleSerial commands send data as ASCII; this is the length of the data that was encoded.
  • end (str, optional) – Expected end of the command. Will warn the user if the received command does not end with this string. Defaults to ‘n’
  • timeout (int, optional) – Value to use for timeouts during reads in ms. If 0, block until all expected data is returned. Defaults to 250.
  • ack (bool, optional) – Expect an ack at the end for SimpleSerial >= 1.1. Defaults to True.
Returns:

The received payload as a bytearray or None if the read failed.

Example

Reading ciphertext back from the target after a ‘p’ command:

ct = target.simpleserial_read('r', 16)
Raises:Warning – Device did not ack or error during read.

New in version 5.1: Added target.simpleserial_read()

set_key(key, ack=True, timeout=250)

Checks if key is different than the last one sent. If so, send it.

Uses simpleserial_write(‘k’)

Parameters:
  • key (bytearray) – key to send
  • ack (bool, optional) – Wait for ack after sending key. Defaults to True.
  • timeout (int, optional) – How long in ms to wait for the ack. Defaults to 250.
Raises:

Warning – Device did not ack or error during read.

New in version 5.1: Added target.set_key()

in_waiting()

Returns the number of characters available from the serial buffer.

Returns:The number of characters available via a target.read() call.

New in version 5.1: Added target.in_waiting()

flush()

Removes all data from the serial buffer.

New in version 5.1: Added target.flush()

close()

Close target

con(scope=None, **kwargs)

Connect to target

baud

The current baud rate of the serial connection.

Getter:Return the current baud rate.
Setter:Set a new baud rate. Valid baud rates are any integer in the range [500, 2000000].
Raises:AttributeError – Target doesn’t allow baud to be changed.

CW305 FPGA Target

class CW305

CW305 target object.

This class contains the public API for the CW305 hardware. To connect to the CW305, the easiest method is:

import chipwhisperer as cw
scope = cw.scope()
target = cw.target(scope,
        targets.CW305, bsfile=<valid FPGA bitstream file>)

Note that connecting to the CW305 includes programming the CW305 FPGA. For more help about CW305 settings, try help() on this CW305 submodule:

  • target.pll
simpleserial_read(cmd, pay_len, end='\n', timeout=250, ack=True)

Read data from target

Mimics simpleserial protocol of serial based targets

Parameters:
  • cmd (str) – Command to ues. Only accepts ‘r’ for now.
  • pay_len – Unused
  • end – Unused
  • timeout – Unused
  • ack – Unused

Returns: Value from Crypto output register

New in version 5.1: Added simpleserial_read to CW305

simpleserial_write(cmd, data, end=None)

Write data to target.

Mimics simpleserial protocol of serial based targets.

Parameters:
  • cmd (str) – Command to use. Target supports ‘p’ (write plaintext), and ‘k’ (write key).
  • data (bytearray) – Data to write to target
  • end – Unused
Raises:

ValueError – Unknown command

New in version 5.1: Added simpleserial_write to CW305

clksleeptime

Time (in milliseconds) that the USB clock is disabled for upon capture, if self.clkusbautooff is set.

clkusbautooff

If set, the USB clock is automatically disabled on capture.

The USB clock is re-enabled after self.clksleeptime milliseconds.

Getter:Gets whether to turn off the USB clock on capture
Setter:Sets whether to turn off the USB clock on capture
pll target.pll
pll_outenable_set target.pll.pll_outenable_set

Enable or disable a PLL

Parameters:
  • enabled (bool) – Whether to enable (True) or disable (False) the specified PLL.
  • outnum (int) – The PLL to enable or disable
pll_outenable_get target.pll.pll_outenable_get

Get whether a PLL is enabled or not

Parameters:outnum (int) – The PLL to get the enable status of
Returns:True if the PLL is enabled, False if it isn’t
pll_outfreq_set target.pll.pll_outfreq_set

Set the output frequency of a PLL

Parameters:
  • freq (int) – The desired output frequency of the PLL. Must be in range [630kHz, 167MHz]
  • outnum (int) – The PLL to set the output frequency of
Raises:

ValueError – Desired frequency is bigger than 167MHz or smaller than 630kHz

pll_outfreq_get target.pll.pll_outfreq_get

Read the programmed output frequency from a PLL on the CW305

Parameters:outnum (int) – PLL to read from (i.e. for PLL 0, use outnum=0)
Returns:The output frequency of the specified PLL

Program

When testing out different firmware on the target it is useful to be able to reprogram the target. This can be done using the chipwhisperer.program_target() function. There are multiple programmer types available:

  • programmers.STM32FProgrammer
  • programmers.XMEGAProgrammer
  • programmers.AVRProgrammer
program_target(scope, prog_type, fw_path, **kwargs)

Program the target using the programmer <type>

Programmers can be found in the programmers submodule

Parameters:
  • scope (ScopeTemplate) – Connected scope object to use for programming
  • prog_type (Programmer) – Programmer to use. See chipwhisperer.programmers for available programmers
  • fw_path (str) – Path to hex file to program

New in version 5.0.1: Simplified programming target

Project

The project is a way of storing a traces, and other project data together using a bag-of-files. These projects can be exported and imported to a new session.

A project can be accessed a few different ways. It can either be loaded from storage, created new, or imported. Importing currently only supports zip files.

open_project(filename)

Load an existing project from disk.

Parameters:filename (str) – Path to project file.
Returns:A chipwhisperer project object.
Raises:OSError – filename does not exist.
create_project(filename, overwrite=False)

Create a new project with the path <filename>.

If <overwrite> is False, raise an OSError if this path already exists.

Parameters:
  • filename (str) – File path to create project file at. Must end with .cwp
  • overwrite (bool, optional) – Whether or not to overwrite an existing project with <filename>. Raises an OSError if path already exists and this is false. Defaults to false.
Returns:

A chipwhisperer project object.

Raises:

OSError – filename exists and overwrite is False.

import_project(filename, file_type='zip', overwrite=False)

Import and open a project.

Will import the filename by extracting to the current working directory.

Currently support file types:
  • zip
Parameters:
  • filename (str) – The file name to import.
  • file_type (str) – The type of file that is being imported. Default is zip.
  • overwrite (bool) – Whether or not to overwrite the project given as the import_as project.

New in version 5.1: Add import_project function.

The open_project and the create_project return a Project instance.

class Project(prog_name='ChipWhisperer', prog_ver='')

Class describing an open ChipWhisperer project.

Basic capture usage:

import chipwhisperer as cw
proj = cw.create_project("project")
trace = cw.Trace(trace_data, plaintext, ciphertext, key)
proj.traces.append(trace)
proj.save()

Basic analyzer usage:

import chipwhisperer as cw
import chipwhisperer.analyzer as cwa
proj = cw.open_project("project")
attack = cwa.cpa(proj)
#run attack

Use a trace_manager when analyzing traces, since that allows analyzer to work with multiple trace segments.

location

The directory in which the project is located.

Example:

print(project.location)
'/path/to/the/directory/containing/this/project'
Getter:(str) Returns the file path of the projects parent directory.

New in version 5.1: Added location attribute to project.

traces

The interface to all traces contained in the project.

Instance of Traces.

waves

Iterable for working with only the trace data.

Each item in the iterable is a numpy array.

Supports iterating, indexing, and slicing:

for wave in my_project.waves:
    # do something
textins

Iterable for working with only the text in.

Each item in the iterable is a byte array.

Supports iterating, indexing, and slicing:

for textin in my_project.textins:
    # do something
textouts

Iterable for working with only the text out.

Each item in the iterable is a byte array.

Supports iterating, indexing, and slicing:

for textout in my_project.textouts:
    # do something
keys

Iterable for working with only the known keys.

Each item in the iterable is a byte array.

Supports iterating, indexing, and slicing:

for key in my_project.keys:
    # do something
get_filename()

Gets the filename associated with the project.

Returns:Filename of the project config file ending with “.cwp”.
trace_manager()

Gets the trace manager for the project

Returns:The trace manager for the project
export(file_path, file_type='zip')

Export a chipwhisperer project.

Saves project before exporting.

Supported export types:
  • zip (default)
Returns:(str) Path to the exported file.

New in version 5.1: Add export method to active project.

save()

Saves the project.

Writes the project to the disk. Before this is called your data is not saved.

close(save=True)

Closes the project cleanly.

Saves by default. Then closes all claimed files.

Parameters:save (bool) – Saves the project before closing.
class Traces(project, segment_length=10000)

Contains the trace interface for the project.

The class adds support for indexing, slicing and iterating of project traces. To add traces to the project use append.

for trace in my_traces:
    my_project.traces.append(trace)

To iterate through all traces use:

for trace in my_project.traces:
    print(trace.wave, trace.textin, trace.textout, trace.key)

Indexing is supported:

trace_of_interest = my_project.traces[99]

So is slicing:

interesting_traces = my_project.traces[20:35]
Parameters:
  • project – The project class where traces will be stored.
  • segment_length (int) – The number of traces stored in one file before another file is created. This is used for unloading and loading traces from disk to keep memory usage reasonable.
Returns:

(iterable) of traces in the project if the traces belongs to a segment that is enabled. The iterable contains tuples of length four containing the trace, plain text in, encrypted text out, and known key.

Raises:
  • IndexError – When the index used for indexing is out of range.
  • TypeError – When key used to get item is not a slice or integer.

New in version 5.1: Added Traces class to project interface.

append(trace)

Append a Trace containing the trace and related operation information.

Parameters:trace (Trace) – A captured or created trace.
Raises:TypeError – When trying to append something other than a trace.
extend(iterable)

Add all traces in an iterable to the project.

Parameters:iterable – Any iterable of Trace objects.
Raises:TypeError – If any of the object in the iterable are not a trace.

Capture

Before capturing a trace make sure:

  1. The scope has been connected.
  2. The scope is configured.
  3. The target has been connected.
  4. The target is configured.
  5. The target has been programmed with the correct firmware.

Once you completed these steps you can use the capture_trace function to complete a capture of one trace. There are some helper classes that generate types of key text patterns for input to the capture_trace function. The function will return a Trace.

capture_trace(scope, target, plaintext, key=None)

Capture a trace, sending plaintext and key

Does all individual steps needed to capture a trace (arming the scope sending the key/plaintext, getting the trace data back, etc.)

Parameters:
  • scope (ScopeTemplate) – Scope object to use for capture.
  • target (TargetTemplate) – Target object to read/write text from.
  • plaintext (bytearray) – Plaintext to send to the target. Should be unencoded bytearray (will be converted to SimpleSerial when it’s sent). If None, don’t send plaintext.
  • key (bytearray, optional) – Key to send to target. Should be unencoded bytearray. If None, don’t send key. Defaults to None.
Returns:

Trace or None if capture timed out.

Raises:

Warning or OSError – Error during capture.

Example

Capturing a trace:

import chipwhisperer as cw
scope = cw.scope()
scope.default_setup()
target = cw.target()
ktp = cw.ktp.Basic()
key, pt = ktp.new_pair()
trace = cw.capture_trace(scope, target, pt, key)

New in version 5.1: Added to simplify trace capture.

Trace

This class is used throughout the ChipWhisperer software to package together the relevant data for each captured power trace. After a capture is complete the capture_trace function will return a Trace. This trace is namedtuple of four pieces of data (wave, textin, textout, key), where wave is the actually numpy array of the power trace captured during the target’s operation. The individual pieces of data can be accessed as a one would with a tuple or by using the provided attributes. Example:

import chipwhisperer as cw
trace = cw.Trace(wave, textin, textout, key)

This trace groups together the power trace (wave), and the process information that resulted in that trace such as textin, textout, and key.

class Trace(wave, textin, textout, key)
wave

Alias for field number 0

textin

Alias for field number 1

textout

Alias for field number 2

key

Alias for field number 3

New in version 5.1: Added Trace class.

Key Text Patterns

There are a few different types of classes for generating key text patterns for your capture:

Basic

class AcqKeyTextPattern_Basic

Class for getting basic keys and plaintexts.

Basic usage:

import chipwhisperer as cw
ktp = cw.ktp.Basic()
key, text = ktp.next()
fixed_key

Generate fixed key (True) or not (False).

Getter:Return True if using fixed key or False if not.
Setter:Set whether to use fixed key (True) or not (False).

New in version 5.1: Added fixed_key property

fixed_text

Generate fixed plaintext (True) or not (False).

Getter:Return True if using fixed plaintext or False if not.
Setter:Set whether to use fixed plaintext (True) or not (False).

New in version 5.1: Added fixed_text property

next()

Returns the next key text pair

Updates last key and text

Returns:(key (bytearray), text (bytearray))

New in version 5.1: Added next

next_key()

Returns the next key

Does not update text. If key is fixed, returns the same key as last time

Returns:key (bytearray)

New in version 5.1: Added next_key

next_text()

Returns the next plaintext

Does not update key. If text is fixed, returns the same plaintext as last time

Returns:text (bytearray)

New in version 5.1: Added next_text

TVLA TTest

class AcqKeyTextPattern_TVLATTest(target=None)

Class for getting key and text for TVLA T-Tests.

Basic usage:

import chipwhisperer as cw
ktp = cw.ktp.TVLATTest()
ktp.init(num_traces) # init with the number of traces you plan to
                     # capture
key, text = ktp.next()
init(maxtraces)

Initialize key text pattern for a specific number of traces.

Parameters:maxtraces (int) – Number of traces to initialize for.
Raises:ValueError – Invalid key length
next()

Returns the next key text pair

Updates last key and text

Returns:(key (bytearray), text (bytearray))

New in version 5.1: Added next

Analyzer

You may want to use your captured traces to perform an attack based on a type of side-channel analysis, in comes the analyzer. You can import the analyzer API using:

import chipwhisperer.analyzer as cwa

One of the ways to analyze your traces is using correlation power analysis (CPA). The cpa function returns a CPA object that can be used to run the attack.

cpa cpa(proj, leak_model, algorithm=cpa_algorithms.Progressive)

Create a CPA object to attack traces in project using leak_model and algorithm.

Parameters:
  • proj (Project) – TraceManager or preprocessing object that holds traces, plaintext, etc.
  • leak_model (AESLeakageHelper) – Model describing information leaked from target.
  • algorithm (AlgorithmsBase, optional) – Algorithm to perform CPA loop. Default is almost always the right choice. Defaults to cpa_algorithms.Progressive.
Returns:

A CPA object. For more information, see documentation for CPA.

Changed in version 5.1: Now uses new CPA attack object

leakage_models

Contains all available leakage models that can be passed to the cpa function as the leak_model parameter.

Instance of the EightBitAES128LeakageModels class.

New in version 5.1: Add leakage_models to anlayzer API.

Preprocessing

Before performing an attack you may want to apply some pre-processing to the captured traces. There is currently one pre-processing class that has been moved to the latest ChipWhisperer API.

class ResyncSAD(trace_source=None)

Resynchronize traces by shifting them to match in a certain window.

This method of pre-processing uses the Sum of Absolute Difference (SAD) algorithm, also known as the Sum of Absolute Error. Uses a portion of one of the traces as a reference. This reference is then slid over the input “window” of each trace, and the amount of the shift resulting in the minimum SAD criteria is used as the shift amount for each trace.

Parameters:trace_source (Project) – A project containing the traces to preprocess.
max_shift

Maximum amount to shift around a trace around the target_window

ref_trace

The trace being used as a reference.

Raises:TypeError – If attempting to set to non integer value.
target_window

Section of the trace we are trying to minimize SAD for.

This must be a tuple of (first point, last point).

Raises:TypeError – If attempting to set to a non tuple or if points are not integers.
preprocess()

Process all traces.

Returns:A new project containing the processed traces.
Return type:Project

Leakage Models

The analyzer includes various leakage models that can be passed to the cpa as the leak_model argument. The leakage_models variable provides a convenient way to list and access all the available leakage models:

import chipwhisperer.analyzer as cwa
print(cwa.leakage_models)

Any attribute can be chosen from this list and accessed with the dot syntax.

class EightBitAES128LeakageModels

Contains the available leakage models for 8 bit AES128.

To use a leakage model during a correlation power analysis attack see cpa.

leakage_models is an instance of this class.

after_key_mix

After key mix operation.

inverse_sbox_output

Inverse Sbox output.

last_round_state

Last round state.

last_round_state_diff

Last round state using hamming distance.

last_round_state_diff_alternate

Last round state using hamming distance, alternate.

mix_columns_output

Output of the mix columns operation.

plaintext_key_xor

Plain text key XOR.

round_1_2_state_diff_key_mix

Hamming distance between round 1 and 2 state during key mix operation.

round_1_2_state_diff_sbox

Hamming distance between round 1 and 2 state during sbox lookup operation.

round_1_2_state_diff_text

Hamming distance between round 1 and 2 state using plain text.

sbox_in_out_diff

Hamming distance between SBox input and output.

sbox_input_successive

Successive Sbox input.

sbox_output

SBox Output.

sbox_output_successive

Successive SBox output.

shift_columns_output

Output of the shift columns operation.

new_model(model)

Makes a new leakage model for use with analyzer

Usage:

class AES256_Round13_Model(cwa.AESLeakageHelper):
    def leakage(self, pt, ct, guess, bnum):
        # You must put YOUR recovered 14th round key here.
        # This example may not be accurate!
        calc_round_key = [0xea, 0x79, 0x79, 0x20, 0xc8, 0x71,
                          0x44, 0x7d, 0x46, 0x62, 0x5f, 0x51,
                          0x85, 0xc1, 0x3b, 0xcb]
        xored = [calc_round_key[i] ^ pt[i] for i in range(0, 16)]
        block = xored
        block = self.inv_shiftrows(block)
        block = self.inv_subbytes(block)
        block = self.inv_mixcolumns(block)
        block = self.inv_shiftrows(block)
        result = block
        return self.inv_sbox((result[bnum] ^ guess[bnum]))

leak_model = cwa.leakage_models.new_model(AES256_Round13_Model)
Parameters:model (AESLeakageHelper) – New leakage model to create
Returns:Leakage model made from model

CPA Attack

The interface class to carry out a correlation power analysis attack on the previously captured traces. The easiest way to create a default CPA instance that is ready to perform an attack is to use the cpa function.

class CPA(proj, leak_model, algorithm)

Correlation Power Analysis (CPA).

Provides all the needed functionality for taking a project and performing a CPA attack with a specific type of leakage model.

Parameters:
  • proj (Project) – An open project instance.
  • algorithm – The algorithm used for the analysis. Default is Progressive which allows a callback to be given. The callback is called at increments of a specific interval. This is useful for auto-updating tables and equivalent.
  • leak_model – The leakage model used when analysing the captured traces.

The easiest way to use this class is through the cpa API function provided by the chipwhisperer.analyzer module.

Example:

import chipwhisperer.analyzer as cwa
import chipwhisperer as cw
proj = cw.open_project('/path/to/project')
attack = cwa.cpa(proj, cwa.leakage_models.sbox_output)
results = attack.run()
print(results)
project

Project to pull waves, textin, etc. from.

algorithm

Analysis algorithm to use for attack. Should be Progressive

leak_model

Leakage model to use during analysis. Should be of type AESLeakageHelper.

trace_range

Start and end trace number. Should be a list of length 2 (i.e. [start_num, end_num]).

point_range

Range of points to use from waves in project. Should be a list of length 2 ([start_point, end_point]).

subkey_list

List of subkeys to attack (subkey_list = [0, 1, 3] will attack subkeys 0, 1, and 3).

New in version 5.1: Added CPA in cpa_new.py to wrap old CPA object

change_project(proj)

Change the project property and update ranges

If you don’t want to update your ranges, change the project attribute instead.

Parameters:project (Project) – Project to switch to
Returns:None
run(callback=None, update_interval=25)

Runs the attack

Parameters:
  • callback (function(), optional) – Callback to call every update interval. No arguments are passed to callback. Defaults to None.
  • update_interval (int, optional) – Number of traces to process before updating the results of the attack.
Returns:

Results, the results of the attack. See documentation for Results for more details.

Results

The cpa.run function will return a results object. There are a few methods for interacting with the results object.

class Results(numSubkeys=16, numPerms=256)

Results type used for attacks generating peaks indicating the ‘best’ success. Examples include standard DPA & CPA attacks.

best_guesses()

Gets best subkey guesses from attack results

Returns:List of OrderedDicts with keys ‘guess’, ‘correlation’ and ‘pge’.
find_maximums(bytelist=None, use_absolute=True, use_single=False)

Information from the attack:

Parameters:
  • bytelist (list) – Iterable of subkeys to compute and organize results for.
  • use_absolute (bool) – Use absolute value of correlation to find highest correlation.
  • use_single (bool) – All table values are taken from the same point the maximum is taken from.
Returns:

Ordered by subkey index:

[subkey0_data, subkey1_data, subkey2_data, ...]

subkey0_data is another list containing guesses ordered by strength of correlation:

[guess0, guess1, guess2, ...]

guess0 is a tuple containing:

(key_guess, location_of_max, correlation)

Return type:

list

For example, if you want to print the correlation of the best guess of the 4th subkey, you would run:

print(attack_results.find_maximums()[4][0][2])

Note the “point location of the max” is normally not calculated/tracked, and thus returns as a 0.

set_known_key(known_key)

Sets the known encryption key.

simple_PGE(bnum)

Returns the partial guessing entropy of subkey.

Utilities

This section contains relatively independent functions that are useful for working with AES, and traces.

AES Functions

You may want to perform certain AES operations seperately. For this there is the AES helper functions. They are accessible using:

from chipwhisperer.analyzer import aes_funcs
Available functions:
sbox(inp)

Perform an SBox lookup.

Parameters:inp (int) – Byte used for the Sbox lookup.
Returns:The result of the SBox lookup.
Return type:int
inv_sbox(inp)

Perform an inverse SBox lookup.

Parameters:inp (int) – Byte used for the inverse Sbox lookup.
Returns:The result of the inverse SBox lookup.
Return type:int
subbytes(inp)

Perform an Sbox lookup for multiple bytes.

Parameters:inp (iterable) – Bytes to perform Sbox lookup on.
Returns:
List of bytes resulting from the multiple
SBox lookups.
Return type:list
inv_subbytes(inp)

Perform an inverse Sbox lookup for multiple bytes.

Parameters:inp (iterable) – Bytes to perform inverse Sbox lookup on.
Returns:
List of bytes resulting from the multiple
inverse SBox lookups.
Return type:list
shiftrows(state)

AES shift rows operation.

Parameters:state (iterable) – Iterable of 16 bytes.
Returns:List of 16 bytes after shift rows operation.
Return type:list
inv_shiftrows(state)

Inverse AES shift rows operation.

Parameters:state (iterable) – Iterable of 16 bytes.
Returns:List of 16 bytes after inverse shift rows operation.
Return type:list
mixcolumns(state)

AES mix columns operation.

Parameters:state (iterable) – Iterable of 16 bytes.
Returns:List of 16 bytes after mix columns operation.
Return type:list
inv_mixcolumns(state)

AES inverse mix columns operation.

Parameters:state (iterable) – Iterable of 16 bytes.
Returns:List of 16 bytes after inverse mix columns operation.
Return type:list
key_schedule_rounds(input_key, input_round, desired_round)

Use key schedule to determine key for different round.

When dealing with AES-256, inputkey is 16 bytes and inputround indicates round that bytes 0…15 are from.

Parameters:
  • input_key (list) – List of bytes of starting key, 16/32 bytes
  • input_round (int) – Starting round number (i.e. 0 = first)
  • desired_round (int) – Desired round number (i.e. 10 = last for 16-byte)
Returns:

Key at desired round number. Can go forward or backwards.

Return type:

list

Signal to Noise Ratio

Calculate the signal-to-noise ratio of your captured traces:

import chipwhisperer.analyzer as cwa
import chipwhisperer as cw

project = cw.open_project('my_project')
cwa.calculate_snr(project, cwa.leakage_models.sbox_output)
calculate_snr(input, leak_model, bnum=0, db=True)

Calculate the SNR based on the leakage model.

Uses same leakage model as the CPA attack.

Parameters:
  • input (Iterable of Traces) – An iterable of traces.
  • leak_model (ModelsBase) – A leakage model selected from leakage_models.
  • bnum (int) – Byte number used for leakage model.
  • bd (bool) – Return signal-to-noise ratio in decibals.