Skip to content

Commit

Permalink
[objs] Update binary for OTBN vertical capture
Browse files Browse the repository at this point in the history
Signed-off-by: Moritz Wettermann <[email protected]>
  • Loading branch information
wettermo authored and nasahlpa committed Dec 20, 2023
1 parent 6dc28b6 commit c959d89
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 56 deletions.
94 changes: 55 additions & 39 deletions capture/capture_otbn.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import binascii
import logging
import random
import signal
import sys
import time
import typer
from dataclasses import dataclass
from datetime import datetime
from functools import partial
Expand All @@ -24,12 +21,23 @@
from scopes.scope import Scope, ScopeConfig, determine_sampling_rate
from tqdm import tqdm

sys.path.append("../")
import util.helpers as helpers
from target.cw_fpga import CWFPGA # noqa: E402
from util import check_version # noqa: E402
from util import plot # noqa: E402
from util import data_generator as dg # noqa: E402
from target.cw_fpga import CWFPGA
from util import check_version
from util import data_generator as dg
from util import plot

"""OTBN vertical SCA capture script.
Captures power traces during OTBN operations.
The data format of the crypto material (ciphertext, plaintext, and key) inside
the script is stored in plain integer arrays.
Typical usage:
>>> ./capture_otbn.py -c configs/otbn_vertical_keygen_sca_cw310.yaml \
-p projects/otbn_vertical_sca_cw310_keygen
"""

logger = logging.getLogger()

Expand Down Expand Up @@ -116,8 +124,8 @@ def setup(cfg: dict, project: Path):
cfg[scope_type]["offset_samples"] = convert_offset_cycles(cfg, scope_type)

logger.info(
f"Initializing scope {scope_type} with a sampling rate of {cfg[scope_type]['sampling_rate']}..."
) # noqa: E501
f"Initializing scope {scope_type} with a sampling rate of {cfg[scope_type]['sampling_rate']}..." # noqa: E501
)

# Create scope config & setup scope.
scope_cfg = ScopeConfig(
Expand Down Expand Up @@ -145,7 +153,7 @@ def setup(cfg: dict, project: Path):
if "decimate" in cfg["husky"]:
scope.scope.scope.adc.decimate = cfg["husky"]["decimate"]
# Print final scope parameter
print(
logger.info(
f'Scope setup with final sampling rate of {scope.scope.scope.clock.adc_freq} S/s'
)

Expand Down Expand Up @@ -220,7 +228,7 @@ def configure_cipher(cfg: dict, target,
if capture_cfg.capture_mode == "keygen":
if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not yet supported.')
raise NotImplementedError('Batch mode not yet supported.')
else:
# Generate fixed constants for all traces of the keygen operation.
if cfg["test"]["test_type"] == 'KEY':
Expand Down Expand Up @@ -258,7 +266,7 @@ def configure_cipher(cfg: dict, target,
elif capture_cfg.capture_mode == "modinv":
if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not supported.')
raise NotImplementedError('Batch mode not supported.')
else:
# set fixed key and share inputs
# (uncomment the desired fixed shares depending on whether
Expand Down Expand Up @@ -297,7 +305,7 @@ def generate_ref_crypto_keygen(cfg: dict, sample_fixed, curve_cfg: CurveConfig,

if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not yet supported.')
raise NotImplementedError('Batch mode not yet supported.')
else:
if cfg["test"]["masks_off"] == 'True':
# Use a constant mask for each trace
Expand Down Expand Up @@ -372,7 +380,7 @@ def generate_ref_crypto_modinv(cfg: dict, sample_fixed, curve_cfg: CurveConfig,

if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not yet supported.')
raise NotImplementedError('Batch mode not yet supported.')
else:
if sample_fixed:
# Compute the fixed input shares:
Expand Down Expand Up @@ -468,7 +476,7 @@ def check_ciphertext_modinv(ot_otbn_vert: OTOTBNVERT, expected_output,
ot_otbn_vert: The OpenTitan OTBN vertical communication interface.
expected_key: The pre-computed key.
curve_cfg: The curve config.
Returns:
actual_output: The received output of the modinv operation.
"""
Expand Down Expand Up @@ -537,7 +545,7 @@ def capture_keygen(cfg: dict, scope: Scope, ot_otbn_vert: OTOTBNVERT,
# Trigger encryption.
if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not yet supported.')
raise NotImplementedError('Batch mode not yet supported.')
else:
# Send the seed to ibex.
# Ibex receives the seed and the mask and computes the two shares as:
Expand Down Expand Up @@ -607,13 +615,13 @@ def capture_modinv(cfg: dict, scope: Scope, ot_otbn_vert: OTOTBNVERT,
# Arm the scope.
scope.arm()

k_used, input_k0_used, input_k1_used, expected_output, sample_fixed = generate_ref_crypto_modinv(
cfg, sample_fixed, curve_cfg, capture_cfg)
k_used, input_k0_used, input_k1_used, expected_output, sample_fixed = \
generate_ref_crypto_modinv(cfg, sample_fixed, curve_cfg, capture_cfg)

# Trigger encryption.
if capture_cfg.batch_mode:
# TODO: add support for batch mode
raise NotImplementedError(f'Batch mode not supported.')
raise NotImplementedError('Batch mode not supported.')
else:
# Start modinv device computation
ot_otbn_vert.start_modinv(input_k0_used, input_k1_used)
Expand Down Expand Up @@ -643,24 +651,24 @@ def capture_modinv(cfg: dict, scope: Scope, ot_otbn_vert: OTOTBNVERT,
pbar.update(capture_cfg.num_segments)


def print_plot(project: SCAProject, config: dict) -> None:
def print_plot(project: SCAProject, config: dict, file: Path) -> None:
""" Print plot of traces.
Printing the plot helps to adjust the scope gain and check for clipping.
Args:
project: The project containing the traces.
config: The capture configuration.
file: The output file path.
"""
if config["capture"]["show_plot"]:
plot.save_plot_to_file(
project.get_waves(0, config["capture"]["plot_traces"]),
set_indices=None,
num_traces=config["capture"]["plot_traces"],
outfile=config["capture"]["trace_image_filename"],
add_mean_stddev=True)
print(f'Created plot with {config["capture"]["plot_traces"]} traces: '
f'{Path(config["capture"]["trace_image_filename"]).resolve()}')
plot.save_plot_to_file(project.get_waves(0, config["capture"]["plot_traces"]),
set_indices = None,
num_traces = config["capture"]["plot_traces"],
outfile = file,
add_mean_stddev=True)
logger.info(f'Created plot with {config["capture"]["plot_traces"]} traces: '
f'{Path(str(file) + ".html").resolve()}')


def main(argv=None):
Expand All @@ -682,7 +690,7 @@ def main(argv=None):
# Determine the capture mode and configure the current capture.
mode = cfg["test"]["app"]
batch = cfg["test"]["batch_mode"]
if batch == False:
if batch is False:
# For non-batch mode, make sure that num_segments = 1.
cfg[cfg["capture"]["scope_select"]]["num_segments"] = 1
logger.info(
Expand Down Expand Up @@ -725,10 +733,10 @@ def main(argv=None):
project, target)
else:
# TODO: add support for modinv app
raise NotImplementedError(f'Cofigured OTBN app not yet supported.')
raise NotImplementedError('Cofigured OTBN app not yet supported.')

# Print plot.
print_plot(project, cfg)
print_plot(project, cfg, args.project)

# Save metadata.
metadata = {}
Expand All @@ -738,13 +746,21 @@ def main(argv=None):
metadata["offset_samples"] = scope.scope_cfg.offset_samples
metadata["scope_gain"] = scope.scope_cfg.scope_gain
metadata["cfg_file"] = str(args.cfg)
metadata["fpga_bitstream"] = cfg["target"]["fpga_bitstream"]
# TODO: Store binary into database instead of binary path.
# (Issue lowrisc/ot-sca#214)
metadata["fw_bin"] = cfg["target"]["fw_bin"]
# TODO: Allow user to enter notes via CLI.
# (Issue lowrisc/ot-sca#213)
metadata["notes"] = ""
# Store bitstream information.
metadata["fpga_bitstream_path"] = cfg["target"]["fpga_bitstream"]
metadata["fpga_bitstream_crc"] = helpers.file_crc(cfg["target"]["fpga_bitstream"])
if args.save_bitstream:
metadata["fpga_bitstream"] = helpers.get_binary_blob(cfg["target"]["fpga_bitstream"])
# Store binary information.
metadata["fw_bin_path"] = cfg["target"]["fw_bin"]
metadata["fw_bin_crc"] = helpers.file_crc(cfg["target"]["fw_bin"])
if args.save_binary:
metadata["fw_bin"] = helpers.get_binary_blob(cfg["target"]["fw_bin"])
# Store user provided notes.
metadata["notes"] = args.notes
# Store the Git hash.
metadata["git_hash"] = helpers.get_git_hash()
# Write metadata into project database.
project.write_metadata(metadata)

# Save and close project.
Expand Down
1 change: 0 additions & 1 deletion capture/configs/otbn_vertical_keygen_sca_cw310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ capture:
offset_cycles: 0
num_traces: 1000
trace_threshold: 10000
trace_image_filename: "projects/simple_capture_otbn_vertical_keygen_sca_sample_traces.html"
trace_db: ot_trace_library
test:
batch_prng_seed: 6
Expand Down
1 change: 0 additions & 1 deletion capture/configs/otbn_vertical_modinv_sca_cw310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ capture:
offset_cycles: 0
num_traces: 1000
trace_threshold: 10000
trace_image_filename: "projects/simple_capture_otbn_vertical_modinv_sca_sample_traces.html"
trace_db: ot_trace_library
test:
batch_prng_seed: 6
Expand Down
26 changes: 13 additions & 13 deletions capture/lib/ot_communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ def read_ciphertext(self, len_bytes):
except Exception:
pass # noqa: E302


class OTOTBNVERT:
def __init__(self, target, protocol: str,
port: Optional[OTUART] = None) -> None:
Expand All @@ -583,56 +584,55 @@ def __init__(self, target, protocol: str,
self.port = port
if protocol == "ujson":
self.simple_serial = False

def choose_otbn_app(self, app):
""" Select the OTBN application.
Args:
app: OTBN application
"""
if self.simple_serial:
# select the otbn app on the device (0 -> keygen, 1 -> modinv)
# Select the otbn app on the device (0 -> keygen, 1 -> modinv).
if app == 'keygen':
self.target.simpleserial_write("a", bytearray([0x00]))
if app == 'modinv':
self.target.simpleserial_write("a", bytearray([0x01]))

def write_batch_prng_seed(self, seed):
""" Seed the PRNG.
Args:
seed: The 4-byte seed.
"""
if self.simple_serial:
self.target.simpleserial_write("s", seed)



def write_keygen_seed(self, seed):
""" Write the seed used for the keygen app.
Args:
seed: byte array containing the seed.
"""
if self.simple_serial:
self.target.simpleserial_write('x', seed)

def write_keygen_key_constant_redundancy(self, const):
""" Write the constant redundancy value for the keygen app.
Args:
seed: byte array containing the redundancy value.
"""
if self.simple_serial:
self.target.simpleserial_write("c", const)

def config_keygen_masking(self, off):
""" Disable/enable masking.
Args:
off: boolean value.
"""
if self.simple_serial:
# enable/disable masking
# Enable/disable masking.
if off is True:
self.target.simpleserial_write("m", bytearray([0x00]))
else:
self.target.simpleserial_write("m", bytearray([0x01]))

def start_keygen(self, mask):
""" Write the seed mask and start the keygen app.
Args:
Expand All @@ -641,25 +641,25 @@ def start_keygen(self, mask):
if self.simple_serial:
# Send the mask and start the keygen operation.
self.target.simpleserial_write('k', mask)

def start_modinv(self, scalar_k0, scalar_k1):
""" Write the two scalar shares and start the modinv app.
Args:
scalar_k0: byte array containing the first scalar share.
scalar_k1: byte array containing the second scalar share.
"""
if self.simple_serial:
# Start modinv device computation
# Start modinv device computation.
self.target.simpleserial_write('q', scalar_k0 + scalar_k1)

def start_keygen_batch(self, test_type, num_segments):
""" Start the keygen app in batch mode.
Args:
test_type: string selecting the test type (KEY or SEED).
num_segments: number of keygen executions to perform.
"""
if self.simple_serial:
# Start batch keygen
# Start batch keygen.
if test_type == 'KEY':
self.target.simpleserial_write("e", num_segments)
else:
Expand Down
4 changes: 2 additions & 2 deletions objs/otbn_vertical_serial_fpga_cw310.bin
Git LFS file not shown

0 comments on commit c959d89

Please sign in to comment.