Capture Helpers

This page documents the included helper functions and classes for capturing, storing, and plotting traces.

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.

close(save=True)

Closes the project cleanly.

Saves by default. Then closes all claimed files.

Parameters:

save (bool) – Saves the project before closing.

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.

get_filename()

Gets the filename associated with the project.

Returns:

Filename of the project config file ending with “.cwp”.

property 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
property 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.

save()

Saves the project.

Writes the project to the disk. Before this is called your data is not saved. Filenames for traces are set in this method.

property 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
property 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
trace_manager()

Gets the trace manager for the project

Returns:

The trace manager for the project

property traces

The interface to all traces contained in the project.

Instance of Traces.

property 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
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, dtype=<class 'numpy.float64'>)

Append a Trace containing the trace and related operation information.

Parameters:
  • trace (Trace) – A captured or created trace.

  • dtype – Numpy data type for storing trace.wave

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, ack=True, poll_done=False, as_int=False, always_send_key=False)

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.). Uses target.output_len as the length of the expected target reponse for simpleserial.

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.

  • ack (bool, optional) – Check for ack when reading response from target. Defaults to True.

  • poll_done (bool, optional) – poll Husky to find out when it’s done capturing, instead of calculating the capture time based on the capture parameters. Useful for long trigger-based segmented captures. Can also result in slightly faster captures when the number of samples is high. Defaults to False. Supported by Husky only.

  • as_int (bool, optional) – If False, return trace as a float. Otherwise, return as an int.

  • always_send_key (bool, optional) – If True, always send key. Otherwise, only send if the key is different from the last one sent.

Return type:

Optional[Trace]

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.

Changed in version 5.2: Added ack parameter and use of target.output_len

Changed in version 5.6.1: Added poll_done parameter for Husky

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)
key

Alias for field number 3

textin

Alias for field number 1

textout

Alias for field number 2

wave

Alias for field number 0

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()
property 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

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

new_pair()

Called when a new encryption pair is requested

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

new_pair()

Called when a new encryption pair is requested

next()

Returns the next key text pair

Updates last key and text

Returns:

(key (bytearray), text (bytearray))

New in version 5.1: Added next