Analyzer API#
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.
- analyzer.cpa cpa(proj, leak_model, algorithm=cpa_algorithms.Progressive)#
- chipwhisperer.analyzer.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.Added in version 5.1: Add leakage_models to analyzer 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 chipwhisperer.analyzer.preprocessing.resync_sad.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.
- property max_shift#
Maximum amount to shift around a trace around the target_window
- preprocess()#
Process all traces.
- Returns:
A new project containing the processed traces.
- Return type:
- property ref_trace#
The trace being used as a reference.
- Raises:
TypeError – If attempting to set to non integer value.
- property 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.
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 chipwhisperer.analyzer.attacks.models.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.- __str__()#
Structured glossary of all the different leakage models.
The glossary includes the name of the leakage model and the description (doc string).
- property after_key_mix#
Hamming weight of 1st round key mix (pt ^ key)
- property half_pipeline_diff#
Hamming distance between previous round 10 and current round 9 (for successive encryptions)
- property inverse_sbox_output#
Hamming weight of 1st round InvSBox (for decryption)
- property inverse_sbox_output_alt#
ISbox output with correct key scheduling so it’s highlighted in the jupyter callback
- property last_round_state#
Hamming weight of 9th round state (InvSBox output)
- property last_round_state_diff#
Hamming distance between rounds 9 and 10
- property last_round_state_diff_alternate#
Hamming distance between rounds 9 and 10 (alternate calculation)
- property mix_columns_output#
Hamming weight of 1st round mix columns
- 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
- property pipeline_diff#
Hamming distance between previous round 9 and current round 9 (for successive encryptions)
- property plaintext_key_xor#
Hamming weight of 1st round key mix (pt ^ key)
- property round_1_2_state_diff_key_mix#
Hamming distance between initial key mix and round 1 key mix
- property round_1_2_state_diff_sbox#
Hamming distance between round 1 and round 2 sbox output
- property round_1_2_state_diff_text#
Hamming distance between AES input and mix columns output
- property sbox_in_out_diff#
Hamming distance between SBox input and output.
- property sbox_input_successive#
Hamming distance between 2 AES sbox inputs
- property sbox_output#
Hamming weight of 1st round SBox output
- property sbox_output_successive#
Hamming distance between 2 AES sbox outputs
- property shift_rows_output#
Hamming weight of shift rows output
- property t_table#
Hamming weight of t-table
- property t_table_dec#
Hamming weight of inverse t-table
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 chipwhisperer.analyzer.attacks.cpa_new.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 thechipwhisperer.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).
Added 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 chipwhisperer.analyzer.attacks._stats.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.
- key_guess()#
Get best guess for key in a list.
- Returns:
Guessed key as a list
- 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 separately. For this there is the AES helper functions. They are accessible using:
from chipwhisperer.analyzer import aes_funcs
- Available functions:
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.funcs.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
- chipwhisperer.analyzer.attacks.models.aes.key_schedule.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)
- chipwhisperer.analyzer.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.