Skip to content

Commit

Permalink
[capture] Enable uJSON for OTBN
Browse files Browse the repository at this point in the history
This commit enables communication with the OTBN SCA code over uJSON.

The device code is located in lowRISC/opentitan#22190.

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa committed Mar 22, 2024
1 parent c4575d2 commit aa953b9
Show file tree
Hide file tree
Showing 10 changed files with 458 additions and 71 deletions.
59 changes: 59 additions & 0 deletions .github/workflows/fpga.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,65 @@ jobs:
name: traces_sha3_random_cw310_ujson
path: ./ci/projects/sha3_sca_random_cw310_ujson.html

otbn_sca_capture_cw310:
name: Capture OTBN SCA traces (CW310)
runs-on: [ubuntu-22.04-fpga, cw310]
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
with:
lfs: true

- name: Install python dependencies
run: |
python3 -m pip install --user -r python-requirements.txt
mkdir -p ci/projects
- name: Capture OTBN Vertical Keygen traces (simpleserial)
working-directory: ci
run: |
../capture/capture_otbn.py -c cfg/ci_otbn_sca_vertical_keygen_cw310_simpleserial.yaml -p projects/otbn_sca_vertical_keygen_cw310_simpleserial
- name: Upload OTBN Vertical Keygen traces (simpleserial)
uses: actions/upload-artifact@v4
with:
name: traces_otbn_sca_vertical_keygen_cw310_simpleserial
path: ./ci/projects/otbn_sca_vertical_keygen_cw310_simpleserial.html

- name: Capture OTBN Vertical Keygen traces (ujson)
working-directory: ci
run: |
../capture/capture_otbn.py -c cfg/ci_otbn_sca_vertical_keygen_cw310_ujson.yaml -p projects/otbn_sca_vertical_keygen_cw310_ujson
- name: Upload OTBN Vertical Keygen traces (ujson)
uses: actions/upload-artifact@v4
with:
name: traces_otbn_sca_vertical_keygen_cw310_ujson
path: ./ci/projects/otbn_sca_vertical_keygen_cw310_ujson.html

- name: Capture OTBN Vertical Modinv traces (simpleserial)
working-directory: ci
run: |
../capture/capture_otbn.py -c cfg/ci_otbn_sca_vertical_modinv_cw310_simpleserial.yaml -p projects/otbn_sca_vertical_modinv_cw310_simpleserial
- name: Upload OTBN Vertical Modinv traces (simpleserial)
uses: actions/upload-artifact@v4
with:
name: traces_otbn_sca_vertical_modinv_cw310_simpleserial
path: ./ci/projects/otbn_sca_vertical_modinv_cw310_simpleserial.html

- name: Capture OTBN Vertical Modinv traces (ujson)
working-directory: ci
run: |
../capture/capture_otbn.py -c cfg/ci_otbn_sca_vertical_modinv_cw310_ujson.yaml -p projects/otbn_sca_vertical_modinv_cw310_ujson
- name: Upload OTBN Vertical Modinv traces (ujson)
uses: actions/upload-artifact@v4
with:
name: traces_otbn_sca_vertical_modinv_cw310_ujson
path: ./ci/projects/otbn_sca_vertical_modinv_cw310_ujson.html

sca_capture_cw305:
name: Capture AES SCA traces (CW305)
runs-on: [ubuntu-22.04-fpga, cw305]
Expand Down
42 changes: 22 additions & 20 deletions capture/capture_otbn.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import util.helpers as helpers
from target.communication.sca_otbn_commands import OTOTBNVERT
from target.communication.sca_prng_commands import OTPRNG
from target.communication.sca_trigger_commands import OTTRIGGER
from target.targets import Target, TargetConfig
from util import check_version
Expand Down Expand Up @@ -191,39 +192,45 @@ def establish_communication(target, capture_cfg: CaptureConfig):
Returns:
ot_otbn_vert: The communication interface to the OTBN app.
ot_prng: The communication interface to the PRNG SCA application.
ot_trig: The communication interface to the SCA trigger.
"""
# Create communication interface to OTBN.
ot_otbn_vert = OTOTBNVERT(target=target, protocol=capture_cfg.protocol)

# Create communication interface to OT PRNG.
ot_prng = OTPRNG(target=target, protocol=capture_cfg.protocol)

# Create communication interface to SCA trigger.
ot_trig = OTTRIGGER(target=target, protocol=capture_cfg.protocol)

return ot_otbn_vert, ot_trig
return ot_otbn_vert, ot_prng, ot_trig


def configure_cipher(cfg: dict, target, capture_cfg: CaptureConfig,
ot_otbn_vert) -> OTOTBNVERT:
def configure_cipher(cfg: dict, capture_cfg: CaptureConfig, ot_otbn_vert,
ot_prng) -> OTOTBNVERT:
""" Configure the OTBN app.
Establish communication with the OTBN keygen app and configure the seed.
Args:
cfg: The configuration for the current experiment.
target: The OT target.
curve_cfg: The curve config.
capture_cfg: The configuration of the capture.
ot_otbn_vert: The communication interface to the OTBN app.
ot_prng: The communication interface to the PRNG SCA application.
Returns:
curve_cfg: The curve configuration values.
"""
# Initialize OTBN on the target.
ot_otbn_vert.init()

# Seed host's PRNG.
random.seed(cfg["test"]["batch_prng_seed"])

# Seed the target's PRNGs
ot_otbn_vert.write_batch_prng_seed(cfg["test"]["batch_prng_seed"].to_bytes(
4, "little"))
ot_prng.seed_prng(cfg["test"]["batch_prng_seed"].to_bytes(4, "little"))

# select the otbn app on the device (0 -> keygen, 1 -> modinv)
ot_otbn_vert.choose_otbn_app(cfg["test"]["app"])
Expand Down Expand Up @@ -474,12 +481,7 @@ def check_ciphertext_keygen(ot_otbn_vert: OTOTBNVERT, expected_key,
"""
# Read the output, unmask the key, and check if it matches
# expectations.
share0 = ot_otbn_vert.read_output(curve_cfg.seed_bytes)
share1 = ot_otbn_vert.read_output(curve_cfg.seed_bytes)
if share0 is None:
raise RuntimeError('Random share0 is none')
if share1 is None:
raise RuntimeError('Random share1 is none')
share0, share1 = ot_otbn_vert.read_seeds(curve_cfg.seed_bytes)

d0 = int.from_bytes(share0, byteorder='little')
d1 = int.from_bytes(share1, byteorder='little')
Expand All @@ -505,8 +507,7 @@ def check_ciphertext_modinv(ot_otbn_vert: OTOTBNVERT, expected_output,
actual_output: The received output of the modinv operation.
"""
# Read the output, unmask it, and check if it matches expectations.
kalpha_inv = ot_otbn_vert.read_output(curve_cfg.key_bytes)
alpha = ot_otbn_vert.read_output(curve_cfg.modinv_mask_bytes)
kalpha_inv, alpha = ot_otbn_vert.read_alpha(curve_cfg.key_bytes, curve_cfg.modinv_mask_bytes)
if kalpha_inv is None:
raise RuntimeError('kaplpha_inv is none')
if alpha is None:
Expand Down Expand Up @@ -589,8 +590,8 @@ def capture_keygen(cfg: dict, scope: Scope, ot_otbn_vert: OTOTBNVERT,

# Store trace into database.
project.append_trace(wave=waves[0, :],
plaintext=mask,
ciphertext=share0 + share1,
plaintext=bytearray(mask),
ciphertext=bytearray(share0 + share1),
key=seed_used)

# Memory allocation optimization for CW trace library.
Expand Down Expand Up @@ -660,11 +661,11 @@ def capture_modinv(cfg: dict, scope: Scope, ot_otbn_vert: OTOTBNVERT,

# Store trace into database.
project.append_trace(wave=waves[0, :],
plaintext=k_used,
plaintext=bytearray(k_used),
ciphertext=bytearray(
actual_output.to_bytes(
curve_cfg.key_bytes, 'little')),
key=k_used)
key=bytearray(k_used))

# Memory allocation optimization for CW trace library.
num_segments_storage = project.optimize_capture(
Expand Down Expand Up @@ -729,6 +730,7 @@ def main(argv=None):
key_len_bytes=cfg["test"]["key_len_bytes"],
text_len_bytes=cfg["test"]["text_len_bytes"],
protocol=cfg["target"]["protocol"],
port = cfg["target"].get("port"),
C=bytearray(),
seed_fixed=bytearray(),
expected_fixed_key=bytearray(),
Expand All @@ -739,10 +741,10 @@ def main(argv=None):
)

# Open communication with target.
ot_otbn_vert, ot_trig = establish_communication(target, capture_cfg)
ot_otbn_vert, ot_prng, ot_trig = establish_communication(target, capture_cfg)

# Configure cipher.
curve_cfg = configure_cipher(cfg, target, capture_cfg, ot_otbn_vert)
curve_cfg = configure_cipher(cfg, capture_cfg, ot_otbn_vert, ot_prng)

# Configure trigger source.
# 0 for HW, 1 for SW.
Expand Down
13 changes: 7 additions & 6 deletions capture/configs/otbn_vertical_keygen_sca_cw310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,31 @@ target:
target_type: cw310
fpga_bitstream: "../objs/lowrisc_systems_chip_earlgrey_cw310_0.1.bit"
force_program_bitstream: True
fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
# fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
fw_bin: ../objs/sca_ujson_fpga_cw310.bin
# target_clk_mult is a hardcoded value in the bitstream. Do not change.
target_clk_mult: 0.24
target_freq: 24000000
baudrate: 115200
output_len_bytes: 40
protocol: "simpleserial"
# protocol: "ujson"
# port: "/dev/ttyACM4"
# protocol: "simpleserial"
protocol: "ujson"
port: "/dev/ttyACM4"
# Trigger source.
# hw: Precise, hardware-generated trigger - FPGA only.
# sw: Fully software-controlled trigger.
trigger: "hw"
husky:
sampling_rate: 200000000
num_segments: 20
num_segments: 1
num_cycles: 200
offset_cycles: 0
scope_gain: 24
adc_mul: 1
decimate: 1
waverunner:
waverunner_ip: 100.107.71.10
num_segments: 20
num_segments: 1
num_samples: 6000
sample_offset: 0
capture:
Expand Down
11 changes: 6 additions & 5 deletions capture/configs/otbn_vertical_modinv_sca_cw310.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ target:
target_type: cw310
fpga_bitstream: "../objs/lowrisc_systems_chip_earlgrey_cw310_0.1.bit"
force_program_bitstream: True
fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
# fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
fw_bin: ../objs/sca_ujson_fpga_cw310.bin
# target_clk_mult is a hardcoded value in the bitstream. Do not change.
target_clk_mult: 0.24
target_freq: 24000000
baudrate: 115200
output_len_bytes: 40
protocol: "simpleserial"
# protocol: "ujson"
# port: "/dev/ttyACM4"
# protocol: "simpleserial"
protocol: "ujson"
port: "/dev/ttyACM4"
# Trigger source.
# hw: Precise, hardware-generated trigger - FPGA only.
# sw: Fully software-controlled trigger.
trigger: "hw"
trigger: "sw"
husky:
sampling_rate: 200000000
num_segments: 20
Expand Down
44 changes: 44 additions & 0 deletions ci/cfg/ci_otbn_sca_vertical_keygen_cw310_simpleserial.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
target:
target_type: cw310
fpga_bitstream: "../objs/lowrisc_systems_chip_earlgrey_cw310_0.1.bit"
force_program_bitstream: False
fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
# target_clk_mult is a hardcoded value in the bitstream. Do not change.
target_clk_mult: 0.24
target_freq: 24000000
baudrate: 115200
output_len_bytes: 40
protocol: "simpleserial"
# Trigger source.
# hw: Precise, hardware-generated trigger - FPGA only.
# sw: Fully software-controlled trigger.
trigger: "hw"
husky:
sampling_rate: 200000000
num_segments: 1
num_cycles: 200
offset_cycles: 0
scope_gain: 24
adc_mul: 1
decimate: 1
capture:
scope_select: husky
show_plot: True
plot_traces: 10
num_traces: 100
trace_threshold: 10000
trace_db: ot_trace_library
test:
batch_prng_seed: 6
key_len_bytes: 40
text_len_bytes: 40
plain_text_len_bytes: 40
masks_off: False
# Currently, 'p256' is the only supported curve.
curve: p256
# Select the OTBN app to analyze. Currently available: 'keygen', 'modinv'
app: keygen
# For app = keygen: There are two fixed-vs-random test types, KEY and SEED
# Currently batch-mode capture only works with SEED
test_type: SEED
batch_mode: False
45 changes: 45 additions & 0 deletions ci/cfg/ci_otbn_sca_vertical_keygen_cw310_ujson.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
target:
target_type: cw310
fpga_bitstream: "../objs/lowrisc_systems_chip_earlgrey_cw310_0.1.bit"
force_program_bitstream: False
fw_bin: ../objs/sca_ujson_fpga_cw310.bin
# target_clk_mult is a hardcoded value in the bitstream. Do not change.
target_clk_mult: 0.24
target_freq: 24000000
baudrate: 115200
output_len_bytes: 40
protocol: "ujson"
port: "/dev/ttyACM_CW310_1"
# Trigger source.
# hw: Precise, hardware-generated trigger - FPGA only.
# sw: Fully software-controlled trigger.
trigger: "hw"
husky:
sampling_rate: 200000000
num_segments: 1
num_cycles: 200
offset_cycles: 0
scope_gain: 24
adc_mul: 1
decimate: 1
capture:
scope_select: husky
show_plot: True
plot_traces: 10
num_traces: 100
trace_threshold: 10000
trace_db: ot_trace_library
test:
batch_prng_seed: 6
key_len_bytes: 40
text_len_bytes: 40
plain_text_len_bytes: 40
masks_off: False
# Currently, 'p256' is the only supported curve.
curve: p256
# Select the OTBN app to analyze. Currently available: 'keygen', 'modinv'
app: keygen
# For app = keygen: There are two fixed-vs-random test types, KEY and SEED
# Currently batch-mode capture only works with SEED
test_type: SEED
batch_mode: False
44 changes: 44 additions & 0 deletions ci/cfg/ci_otbn_sca_vertical_modinv_cw310_simpleserial.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
target:
target_type: cw310
fpga_bitstream: "../objs/lowrisc_systems_chip_earlgrey_cw310_0.1.bit"
force_program_bitstream: False
fw_bin: "../objs/otbn_vertical_serial_fpga_cw310.bin"
# target_clk_mult is a hardcoded value in the bitstream. Do not change.
target_clk_mult: 0.24
target_freq: 24000000
baudrate: 115200
output_len_bytes: 40
protocol: "simpleserial"
# Trigger source.
# hw: Precise, hardware-generated trigger - FPGA only.
# sw: Fully software-controlled trigger.
trigger: "sw"
husky:
sampling_rate: 200000000
num_segments: 20
num_cycles: 1000
offset_cycles: 0
scope_gain: 24
adc_mul: 1
decimate: 1
capture:
scope_select: husky
show_plot: True
plot_traces: 10
num_traces: 100
trace_threshold: 10000
trace_db: ot_trace_library
test:
batch_prng_seed: 6
key_len_bytes: 40
text_len_bytes: 40
plain_text_len_bytes: 40
masks_off: False
# Currently, 'p256' is the only supported curve.
curve: p256
# Select the OTBN app to analyze. Currently available: 'keygen', 'modinv'
app: modinv
# For app = keygen: There are two fixed-vs-random test types, KEY and SEED
# Currently batch-mode capture only works with SEED
test_type: SEED
batch_mode: False
Loading

0 comments on commit aa953b9

Please sign in to comment.