Skip to content

Commit

Permalink
[sca] streamlined vertical otbn part
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Tempelmeier <[email protected]>
  • Loading branch information
m-temp committed Jan 27, 2023
1 parent df6da38 commit 063a3ca
Showing 1 changed file with 33 additions and 43 deletions.
76 changes: 33 additions & 43 deletions cw/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ def kmac_fvsr_key_batch(ctx: typer.Context,
capture_end(ctx.obj.cfg)


def capture_ecdsa_secret_keygen(ot, ktp, fw_bin, pll_frequency, capture_cfg):
def capture_otbn_vertical(ot, ktp, fw_bin, pll_frequency, capture_cfg):
"""Capture traces for ECDSA P256/P384 secret key generation.
Uses a fixed seed and generates several random masks. For the corresponding
Expand All @@ -1011,14 +1011,10 @@ def capture_ecdsa_secret_keygen(ot, ktp, fw_bin, pll_frequency, capture_cfg):
reset_firmware = False

# OTBN operations are long. CW-Husky can store only 131070 samples
# in the non-stream mode. In case we want to collect more samples,
# we can run the operation multiple times with different adc_offset
# values.
# The trace from each run is kept in a section, and all sections are
# concatenated to create the final trace.
# in the non-stream mode.
fifo_size = 131070
num_sections = capture_cfg["num_samples"] // fifo_size
print(f"num_sections = {num_sections}")
if capture_cfg["num_samples"] > fifo_size:
raise RuntimeError('Current setup only supports up to 130k smaples')

# Be sure we don't use the stream mode
if ot.scope._is_husky:
Expand Down Expand Up @@ -1064,50 +1060,44 @@ def capture_ecdsa_secret_keygen(ot, ktp, fw_bin, pll_frequency, capture_cfg):
# Loop to collect each power trace
for _ in tqdm(range(capture_cfg["num_traces"]), desc='Capturing',
ncols=80):
# Create a clean array to keep each section
waves = np.array([])

if reset_firmware:
ot.program_target(fw_bin, pll_frequency)

ot.scope.adc.offset = capture_cfg["offset"]

# Generate a new random mask for each trace.
mask = ktp.next_text()
tqdm.write(f'mask = {mask.hex()}')

# Loop to collect each section of the power trace
for ii in range(num_sections):
if reset_firmware:
ot.program_target(fw_bin, pll_frequency)
# Set the seed.
ot.target.simpleserial_write('x', seed)

# For each section ii, set the adc_offset parameter accordingly
ot.scope.adc.offset = ii * fifo_size
# Check for errors.
err = ot.target.read()
if err:
raise RuntimeError(f'Error writing seed: {err}')

# Set the seed.
ot.target.simpleserial_write('x', seed)

# Check for errors.
err = ot.target.read()
if err:
raise RuntimeError(f'Error writing seed: {err}')

# Arm the scope
ot.scope.arm()

# Send the mask and start the keygen operation.
ot.target.simpleserial_write('k', mask)
# Arm the scope
ot.scope.arm()

# Wait until operation is done.
ret = ot.scope.capture(poll_done=True)
# If getting inconsistent results (e.g. variable number of cycles),
# adding a sufficient sleep below here appears to fix things
# time.sleep(1) # we cannot afford 1 second per run.
if ret:
raise RuntimeError('Timeout during capture')
# Send the mask and start the keygen operation.
ot.target.simpleserial_write('k', mask)

# Check the number of cycles where the trigger signal was high.
cycles = ot.scope.adc.trig_count
tqdm.write("Observed number of cycles: %d" % cycles)
# Wait until operation is done.
ret = ot.scope.capture(poll_done=True)
# TODO: change this
# If getting inconsistent results (e.g. variable number of cycles),
# adding a sufficient sleep below here appears to fix things
# time.sleep(1) # we cannot afford 1 second per run.
if ret:
raise RuntimeError('Timeout during capture')

# Append the section into the waves array
waves = np.append(waves, ot.scope.get_last_trace(as_int=True))
# Check the number of cycles where the trigger signal was high.
cycles = ot.scope.adc.trig_count
tqdm.write("Observed number of cycles: %d" % cycles)

waves = ot.scope.get_last_trace(as_int=True)
# Read the output, unmask the key, and check if it matches
# expectations.
share0 = ot.target.simpleserial_read("r", seed_bytes, ack=False)
Expand All @@ -1133,7 +1123,7 @@ def capture_ecdsa_secret_keygen(ot, ktp, fw_bin, pll_frequency, capture_cfg):


@app_capture.command()
def ecdsa_secret_keygen(ctx: typer.Context,
def otbn_vertical(ctx: typer.Context,
num_traces: int = opt_num_traces,
plot_traces: int = opt_plot_traces):
"""Capture ECDSA secret key generation traces."""
Expand All @@ -1160,7 +1150,7 @@ def ecdsa_secret_keygen(ctx: typer.Context,
)

# Call the capture loop
capture_ecdsa_secret_keygen(ctx.obj.ot,
capture_otbn_vertical(ctx.obj.ot,
ctx.obj.ktp,
ctx.obj.cfg["device"]["fw_bin"],
ctx.obj.cfg["device"]["pll_frequency"],
Expand Down

0 comments on commit 063a3ca

Please sign in to comment.