From af9630ab55952af9861d31d0209de5ebfeed9c94 Mon Sep 17 00:00:00 2001 From: Pascal Nasahl Date: Wed, 13 Mar 2024 15:25:36 +0000 Subject: [PATCH] [fi] Add OTBN command handlers This commit adds command handlers for the following tests: - otbn_key_sideload - otbn_load_integrity The device code is located in lowRISC/opentitan#21917. The binary was created from lowRISC/opentitan@55091e7 with ./bazelisk.sh build //sw/device/tests/crypto/cryptotest/firmware:firmware_fpga_cw310_test_rom Signed-off-by: Pascal Nasahl --- ...pen.global_fi.otbn.key_sideload.cw310.yaml | 38 +++++++++++++++++ ...n.global_fi.otbn.load_integrity.cw310.yaml | 38 +++++++++++++++++ fault_injection/fi_otbn.py | 8 ++-- objs/sca_ujson_fpga_cw310.bin | 4 +- target/communication/fi_otbn_commands.py | 41 +++++++++++++++++-- 5 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 fault_injection/configs/pen.global_fi.otbn.key_sideload.cw310.yaml create mode 100644 fault_injection/configs/pen.global_fi.otbn.load_integrity.cw310.yaml diff --git a/fault_injection/configs/pen.global_fi.otbn.key_sideload.cw310.yaml b/fault_injection/configs/pen.global_fi.otbn.key_sideload.cw310.yaml new file mode 100644 index 000000000..75470dc76 --- /dev/null +++ b/fault_injection/configs/pen.global_fi.otbn.key_sideload.cw310.yaml @@ -0,0 +1,38 @@ +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" + output_len_bytes: 16 + target_clk_mult: 0.24 + target_freq: 24000000 + baudrate: 115200 + protocol: "ujson" + port: "/dev/ttyACM1" +fisetup: + fi_gear: "husky" + fi_type: "voltage_glitch" + # Voltage glitch width in cycles. + glitch_width_min: 5 + glitch_width_max: 150 + glitch_width_step: 3 + # Range for trigger delay in cycles. + trigger_delay_min: 0 + trigger_delay_max: 500 + trigger_step: 10 + # Number of iterations for the parameter sweep. + num_iterations: 10000 +fiproject: + # Project database type and memory threshold. + project_db: "ot_fi_project" + project_mem_threshold: 10000 + # Store FI plot. + show_plot: True + num_plots: 100 + plot_x_axis: "trigger_delay" + plot_x_axis_legend: "[cycles]" + plot_y_axis: "glitch_width" + plot_y_axis_legend: "[cycles]" +test: + which_test: "otbn_key_sideload" + expected_result: '{"result":0,"err_status":0}' diff --git a/fault_injection/configs/pen.global_fi.otbn.load_integrity.cw310.yaml b/fault_injection/configs/pen.global_fi.otbn.load_integrity.cw310.yaml new file mode 100644 index 000000000..2c0af6bb7 --- /dev/null +++ b/fault_injection/configs/pen.global_fi.otbn.load_integrity.cw310.yaml @@ -0,0 +1,38 @@ +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" + output_len_bytes: 16 + target_clk_mult: 0.24 + target_freq: 24000000 + baudrate: 115200 + protocol: "ujson" + port: "/dev/ttyACM1" +fisetup: + fi_gear: "husky" + fi_type: "voltage_glitch" + # Voltage glitch width in cycles. + glitch_width_min: 5 + glitch_width_max: 150 + glitch_width_step: 3 + # Range for trigger delay in cycles. + trigger_delay_min: 0 + trigger_delay_max: 500 + trigger_step: 10 + # Number of iterations for the parameter sweep. + num_iterations: 10000 +fiproject: + # Project database type and memory threshold. + project_db: "ot_fi_project" + project_mem_threshold: 10000 + # Store FI plot. + show_plot: True + num_plots: 100 + plot_x_axis: "trigger_delay" + plot_x_axis_legend: "[cycles]" + plot_y_axis: "glitch_width" + plot_y_axis_legend: "[cycles]" +test: + which_test: "otbn_load_integrity" + expected_result: '{"result":0,"err_status":0}' diff --git a/fault_injection/fi_otbn.py b/fault_injection/fi_otbn.py index 0e8669f1c..819879510 100755 --- a/fault_injection/fi_otbn.py +++ b/fault_injection/fi_otbn.py @@ -78,6 +78,8 @@ def fi_parameter_sweep(cfg: dict, target: Target, fi_gear, project: The project to store the results. ot_communication: The OpenTitan OTBN FI communication interface. """ + # Setup key manager if needed by test. + ot_communication.init_keymgr(cfg["test"]["which_test"]) # Configure the trigger. ot_communication.init_trigger() # Start the parameter sweep. @@ -87,15 +89,13 @@ def fi_parameter_sweep(cfg: dict, target: Target, fi_gear, while remaining_iterations > 0: # Get fault parameters (e.g., trigger delay, glitch voltage). fault_parameters = fi_gear.generate_fi_parameters() - # Arm the FI gear. fi_gear.arm_trigger(fault_parameters) - # Start test on OpenTitan. ot_communication.start_test(cfg) # Read response. - response = ot_communication.read_response() + response = ot_communication.read_response(max_tries=20) # Compare response. # Check if result is expected result (FI failed), unexpected result @@ -111,6 +111,8 @@ def fi_parameter_sweep(cfg: dict, target: Target, fi_gear, ot_communication = target.reset_target(com_reset = True) # Re-establish UART connection. ot_communication = OTFIOtbn(target) + # Setup key manager if needed by test. + ot_communication.init_keymgr(cfg["test"]["which_test"]) # Configure the trigger. ot_communication.init_trigger() # Reset FIGear if necessary. diff --git a/objs/sca_ujson_fpga_cw310.bin b/objs/sca_ujson_fpga_cw310.bin index 8c31ca6dd..cdf4d79a3 100644 --- a/objs/sca_ujson_fpga_cw310.bin +++ b/objs/sca_ujson_fpga_cw310.bin @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9677a472d723de146c5930f1acdcd0dda6f9cc465505f92e2ca9dea5f2a194fc -size 251372 +oid sha256:0ad1df47ebaad117676b11d7b3937f5e3b6becf9c73914554badd4e32ba73052 +size 298684 diff --git a/target/communication/fi_otbn_commands.py b/target/communication/fi_otbn_commands.py index f91a4ab6c..acdc4d5a1 100644 --- a/target/communication/fi_otbn_commands.py +++ b/target/communication/fi_otbn_commands.py @@ -54,11 +54,46 @@ def otbn_char_hardware_dmem_op_loop(self) -> None: time.sleep(0.01) self.target.write(json.dumps("CharHardwareDmemOpLoop").encode("ascii")) - def init_trigger(self) -> None: - """ Initialize the FI trigger on the chip. + def otbn_key_sideload(self) -> None: + """ Starts the otbn.fi.key_sideload test. + """ + # OtbnFi command. + self._ujson_otbn_fi_cmd() + # KeySideload command. + time.sleep(0.01) + self.target.write(json.dumps("KeySideload").encode("ascii")) + + def otbn_load_integrity(self) -> None: + """ Starts the otbn.fi.load_integrity test. + """ + # OtbnFi command. + self._ujson_otbn_fi_cmd() + # LoadIntegrity command. + time.sleep(0.01) + self.target.write(json.dumps("LoadIntegrity").encode("ascii")) + def init_keymgr(self, test: str) -> None: + """ Initialize the key manager on the chip. Args: - cfg: Config dict containing the selected test. + test: Name of the test. Used to determine if key manager init is + needed. + """ + if "key_sideload" in test: + # OtbnFi command. + self._ujson_otbn_fi_cmd() + # InitTrigger command. + time.sleep(0.01) + self.target.write(json.dumps("InitKeyMgr").encode("ascii")) + # As the init resets the chip, we need to call it again to complete + # the initialization of the key manager. + time.sleep(2) + self._ujson_otbn_fi_cmd() + time.sleep(0.01) + self.target.write(json.dumps("InitKeyMgr").encode("ascii")) + time.sleep(2) + + def init_trigger(self) -> None: + """ Initialize the FI trigger on the chip. """ # OtbnFi command. self._ujson_otbn_fi_cmd()