diff --git a/ci/azure-pipelines.yml b/ci/azure-pipelines.yml index 4ebbcc116..cc672ef49 100644 --- a/ci/azure-pipelines.yml +++ b/ci/azure-pipelines.yml @@ -28,3 +28,11 @@ jobs: - publish: ./ci/ci_projects/opentitan_simple_aes_data/ artifact: traces displayName: "Upload traces" + - bash: | + pushd ci + ./ci_check_aes_traces.sh + popd + displayName: "Capture & check static AES traces" + - publish: ./ci/tmp/ + artifact: traces + displayName: "Upload traces AES." \ No newline at end of file diff --git a/ci/ci_capture_aes_cw310.yaml b/ci/ci_capture_aes_cw310.yaml index 85532f0c4..35f799e91 100644 --- a/ci/ci_capture_aes_cw310.yaml +++ b/ci/ci_capture_aes_cw310.yaml @@ -25,6 +25,6 @@ capture: project_name: ci_projects/opentitan_simple_aes waverunner_ip: 192.168.1.228 plot_capture: - show: False - num_traces: 100 - trace_image_filename: null + show: True + num_traces: 2 + trace_image_filename: ci_projects/sample_traces_aes.html diff --git a/ci/ci_check_aes_traces.sh b/ci/ci_check_aes_traces.sh new file mode 100755 index 000000000..51bd3a838 --- /dev/null +++ b/ci/ci_check_aes_traces.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +# Simple script to test AES captures +# Create results folder. +mkdir -p tmp + +# AES +MODE="aes" +BOARD=cw310 +declare -A aes_test_list +aes_test_list["aes-static"]=2 + +ARGS="--force-program-bitstream" +for test in ${!aes_test_list[@]}; do + echo Testing ${test} on CW310 - `date` + NUM_TRACES=${aes_test_list[${test}]} + ../cw/capture.py --cfg-file ci_capture_aes_cw310.yaml capture ${test} \ + --num-traces ${NUM_TRACES} ${ARGS} &>> "tmp/test_capture.log" + + mv ./ci_projects/sample_traces_${MODE}.html tmp/${test}_traces.html + ARGS="" +done \ No newline at end of file diff --git a/cw/capture.py b/cw/capture.py index bce16f114..3e0182825 100755 --- a/cw/capture.py +++ b/cw/capture.py @@ -210,6 +210,43 @@ def capture_end(cfg): plot_results(cfg["plot_capture"], cfg["capture"]["project_name"]) +def capture_aes_static(ot): + """A generator for capturing AES traces for fixed key and test. + + Args: + ot: Initialized OpenTitan target. + """ + key = bytearray([0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12, 0x0A, 0x78, + 0x42, 0x78, 0x1E, 0x22, 0xB2, 0x5C, 0xDD, 0xF9]) + text = bytearray([0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA]) + + tqdm.write(f'Fixed key: {binascii.b2a_hex(bytes(key))}') + + while True: + cipher = AES.new(bytes(key), AES.MODE_ECB) + ret = cw.capture_trace(ot.scope, ot.target, text, key, ack=False, as_int=True) + if not ret: + raise RuntimeError('Capture failed.') + expected = binascii.b2a_hex(cipher.encrypt(bytes(text))) + got = binascii.b2a_hex(ret.textout) + if got != expected: + raise RuntimeError(f'Bad ciphertext: {got} != {expected}.') + yield ret + + +@app_capture.command() +def aes_static(ctx: typer.Context, + force_program_bitstream: bool = opt_force_program_bitstream, + num_traces: int = opt_num_traces, + plot_traces: int = opt_plot_traces): + """Capture AES traces from a target that runs the `aes_serial` program.""" + capture_init(ctx, force_program_bitstream, num_traces, plot_traces) + capture_loop(capture_aes_static(ctx.obj.ot), ctx.obj.ot, + ctx.obj.cfg["capture"], ctx.obj.cfg["device"]) + capture_end(ctx.obj.cfg) + + def capture_aes_random(ot, ktp): """A generator for capturing AES traces. Fixed key, Random texts.