Skip to content

Commit 28a8bf3

Browse files
committed
Update ot-sca to opentitan
Integrate the capture and fault injection scripts to the latest testOS. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent c81a42a commit 28a8bf3

File tree

197 files changed

+18688
-8628
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+18688
-8628
lines changed

.github/workflows/fpga.yml

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -99,55 +99,6 @@ jobs:
9999
name: traces_sha3_random_cw310_ujson
100100
path: ./ci/projects/sha3_sca_random_cw310_ujson.html
101101

102-
sca_capture_cw305:
103-
name: Capture AES SCA traces (CW305)
104-
runs-on: [ubuntu-22.04-fpga, cw305]
105-
timeout-minutes: 30
106-
107-
steps:
108-
- uses: actions/checkout@v4
109-
with:
110-
lfs: true
111-
112-
- name: Install python dependencies
113-
run: |
114-
python3 -m pip install --user -r python-requirements.txt
115-
mkdir -p ci/projects
116-
117-
- name: Capture AES FVSR traces
118-
working-directory: ci
119-
run: |
120-
../capture/capture_aes.py -c cfg/ci_aes_sca_fvsr_cw305.yaml -p projects/aes_sca_fvsr_cw305
121-
122-
- name: Upload AES FVSR traces
123-
uses: actions/upload-artifact@v4
124-
with:
125-
name: traces_aes_fvsr_key_cw305
126-
path: ./ci/projects/aes_sca_fvsr_cw305.html
127-
128-
- name: Capture AES Random traces
129-
working-directory: ci
130-
run: |
131-
../capture/capture_aes.py -c cfg/ci_aes_sca_random_cw305.yaml -p projects/aes_sca_random_cw305
132-
133-
- name: Upload AES Random traces
134-
uses: actions/upload-artifact@v4
135-
with:
136-
name: traces_aes_random_cw305
137-
path: ./ci/projects/aes_sca_random_cw305.html
138-
139-
- name: Perform specific TVLA on AES Random traces
140-
working-directory: ci
141-
run: |
142-
../analysis/tvla.py --cfg-file cfg/ci_tvla_cfg_aes_specific_byte_0_15_rnd_0_1.yaml run-tvla
143-
continue-on-error: true
144-
145-
- name: Upload figures of specific TVLA for AES.
146-
uses: actions/upload-artifact@v4
147-
with:
148-
name: tvla_figures_aes_specific
149-
path: ./ci/tmp/figures
150-
151102
kmac_sca_capture_cw310:
152103
name: Capture KMAC SCA traces (CW310)
153104
runs-on: [ubuntu-22.04-fpga, cw310]

analysis/ceca.py

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# Append ot-sca root directory to path such that ceca.py can find the
2222
# project_library module located in the capture/ directory.
2323
ABS_PATH = os.path.dirname(os.path.abspath(__file__))
24-
sys.path.append(ABS_PATH + '/..')
24+
sys.path.append(ABS_PATH + "/..")
2525
from capture.project_library.project import ProjectConfig # noqa : E402
2626
from capture.project_library.project import SCAProject # noqa : E402
2727

@@ -91,28 +91,29 @@ def __init__(self, project_file, trace_slice, attack_window, attack_direction):
9191
# ChipWhisperer or ot_trace_library project?
9292
project_type = "cw"
9393
if ".db" in project_file:
94-
project_type = 'ot_trace_library'
94+
project_type = "ot_trace_library"
9595

9696
# Open the project.
97-
project_cfg = ProjectConfig(type = project_type,
98-
path = project_file,
99-
wave_dtype = np.uint16,
100-
overwrite = False
101-
)
97+
project_cfg = ProjectConfig(
98+
type=project_type, path=project_file, wave_dtype=np.uint16, overwrite=False
99+
)
102100
self.project = SCAProject(project_cfg)
103101
self.project.open_project()
104102

105103
# TODO: Consider more efficient formats.
106104
self.num_samples = attack_window.stop - attack_window.start
107105
if attack_direction == AttackDirection.INPUT:
108-
self.texts = np.vstack(self.project.get_plaintexts(
109-
trace_slice.start, trace_slice.stop))
106+
self.texts = np.vstack(
107+
self.project.get_plaintexts(trace_slice.start, trace_slice.stop)
108+
)
110109
else:
111-
self.texts = np.vstack(self.project.get_ciphertexts(
112-
trace_slice.start, trace_slice.stop))
110+
self.texts = np.vstack(
111+
self.project.get_ciphertexts(trace_slice.start, trace_slice.stop)
112+
)
113113

114-
self.traces = np.asarray(self.project.get_waves(
115-
trace_slice.start, trace_slice.stop))[:, attack_window]
114+
self.traces = np.asarray(
115+
self.project.get_waves(trace_slice.start, trace_slice.stop)
116+
)[:, attack_window]
116117

117118
self.project.close(save=False)
118119

@@ -176,7 +177,7 @@ def count_and_sum_text_traces(self):
176177
val_changes = np.where(np.roll(sorted_bytes, 1) != sorted_bytes)[0]
177178
# Append the number of rows to be able to use ``pairwise``.
178179
val_indices = list(val_changes) + [sorted_bytes.shape[0]]
179-
for (start, end) in more_itertools.pairwise(val_indices):
180+
for start, end in more_itertools.pairwise(val_indices):
180181
byte_val = sorted_bytes[start]
181182
cnts[byte_pos, byte_val] = end - start
182183
act_indices = sorted_indices[start:end]
@@ -396,7 +397,7 @@ def find_best_diffs(pairwise_diffs_scores):
396397
# other bytes.
397398
diffs = np.zeros(16, dtype=np.uint8)
398399
for byte in range(1, 16):
399-
for (a, b) in more_itertools.pairwise(paths[byte]):
400+
for a, b in more_itertools.pairwise(paths[byte]):
400401
diffs[byte] ^= int(pairwise_diffs_scores[a, b, 0])
401402
return diffs
402403

@@ -502,14 +503,12 @@ def perform_attack(
502503
# ChipWhisperer or ot_trace_library project?
503504
project_type = "cw"
504505
if ".db" in project_file:
505-
project_type = 'ot_trace_library'
506+
project_type = "ot_trace_library"
506507

507508
# Open the project.
508-
project_cfg = ProjectConfig(type = project_type,
509-
path = project_file,
510-
wave_dtype = np.uint16,
511-
overwrite = False
512-
)
509+
project_cfg = ProjectConfig(
510+
type=project_type, path=project_file, wave_dtype=np.uint16, overwrite=False
511+
)
513512
project = SCAProject(project_cfg)
514513
project.open_project()
515514

@@ -559,7 +558,7 @@ def worker_trace_slices():
559558
num_traces = filter_noisy_traces(workers, mean, std_dev, max_std)
560559
logging.info(
561560
f"Will use {num_traces} traces "
562-
f"({100*num_traces/orig_num_traces:.1f}% of all traces)"
561+
f"({100 * num_traces / orig_num_traces:.1f}% of all traces)"
563562
)
564563
# Mean traces for all values of all text bytes.
565564
mean_text_traces = compute_mean_text_traces(workers)
@@ -568,18 +567,21 @@ def worker_trace_slices():
568567
diffs = find_best_diffs(pairwise_diffs_scores)
569568
logging.info(f"Difference values (delta_0_i): {diffs}")
570569
# Recover the key.
571-
key = recover_key(diffs, attack_direction, project.get_plaintexts(0),
572-
project.get_ciphertexts(0))
570+
key = recover_key(
571+
diffs, attack_direction, project.get_plaintexts(0), project.get_ciphertexts(0)
572+
)
573573
if key is not None:
574574
logging.info(f"Recovered AES key: {bytes(key).hex()}")
575575
else:
576576
logging.error("Failed to recover the AES key")
577577
# Compare differences - both matrices are symmetric and have an all-zero main diagonal.
578-
correct_diffs = compare_diffs(pairwise_diffs_scores, attack_direction,
579-
project.get_keys(0))
578+
correct_diffs = compare_diffs(
579+
pairwise_diffs_scores, attack_direction, project.get_keys(0)
580+
)
580581
logging.info(
581-
f"Recovered {((np.sum(correct_diffs)-16)/2).astype(int)}/120 "
582-
"differences between key bytes")
582+
f"Recovered {((np.sum(correct_diffs) - 16) / 2).astype(int)}/120 "
583+
"differences between key bytes"
584+
)
583585
project.close(save=False)
584586
return key
585587

@@ -592,8 +594,10 @@ def parse_args():
592594
Mischke, and T. Eisenbarth (https://eprint.iacr.org/2010/297.pdf)."""
593595
)
594596
parser.add_argument(
595-
"-f", "--project-file", required=True,
596-
help="chipwhisperer or ot_trace_library project file"
597+
"-f",
598+
"--project-file",
599+
required=True,
600+
help="chipwhisperer or ot_trace_library project file",
597601
)
598602
parser.add_argument(
599603
"-n",
@@ -658,9 +662,12 @@ def main():
658662
attack."""
659663
args = parse_args()
660664
config_logger()
661-
ray.init(runtime_env={"working_dir": "../",
662-
"excludes": ["*.db", "*.cwp", "*.npy", "*.bit",
663-
"*/lfs/*", "*.pack"]})
665+
ray.init(
666+
runtime_env={
667+
"working_dir": "../",
668+
"excludes": ["*.db", "*.cwp", "*.npy", "*.bit", "*/lfs/*", "*.pack"],
669+
}
670+
)
664671

665672
key = perform_attack(**vars(args))
666673
sys.exit(0 if key is not None else 1)

0 commit comments

Comments
 (0)