From c3f30b1c850b374fad3577d84f90fce9a51222a4 Mon Sep 17 00:00:00 2001 From: Pascal Nasahl Date: Fri, 9 Aug 2024 15:02:47 +0200 Subject: [PATCH] [pentest] Add new OTBN FI tests This commit pulls over the following tests from the pentest branch of nasahlpa/opentitan that has been used for the penetration testing: - otbn.fi.load_integrity - otbn.fi.key_sideload Signed-off-by: Pascal Nasahl --- .../tests/penetrationtests/firmware/fi/BUILD | 4 + .../penetrationtests/firmware/fi/otbn/BUILD | 14 + .../firmware/fi/otbn/otbn_key_sideload.s | 53 ++++ .../firmware/fi/otbn/otbn_load_integrity.s | 31 ++ .../penetrationtests/firmware/fi/otbn_fi.c | 274 +++++++++++++++++- .../penetrationtests/firmware/fi/otbn_fi.h | 38 +++ .../penetrationtests/json/otbn_fi_commands.h | 20 +- 7 files changed, 429 insertions(+), 5 deletions(-) create mode 100644 sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_key_sideload.s create mode 100644 sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_load_integrity.s diff --git a/sw/device/tests/penetrationtests/firmware/fi/BUILD b/sw/device/tests/penetrationtests/firmware/fi/BUILD index f7cca8939149d5..d71837e175b1c1 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/BUILD +++ b/sw/device/tests/penetrationtests/firmware/fi/BUILD @@ -34,11 +34,13 @@ cc_library( deps = [ "//sw/device/lib/base:memory", "//sw/device/lib/base:status", + "//sw/device/lib/crypto/drivers:keymgr", "//sw/device/lib/crypto/drivers:otbn", "//sw/device/lib/dif:otbn", "//sw/device/lib/dif:rv_core_ibex", "//sw/device/lib/runtime:log", "//sw/device/lib/testing:entropy_testutils", + "//sw/device/lib/testing:keymgr_testutils", "//sw/device/lib/testing/test_framework:ujson_ottf", "//sw/device/lib/ujson", "//sw/device/sca/lib:sca", @@ -46,6 +48,8 @@ cc_library( "//sw/device/tests/penetrationtests/firmware/fi/otbn:otbn_char_hardware_reg_op_loop", "//sw/device/tests/penetrationtests/firmware/fi/otbn:otbn_char_unrolled_dmem_op_loop", "//sw/device/tests/penetrationtests/firmware/fi/otbn:otbn_char_unrolled_reg_op_loop", + "//sw/device/tests/penetrationtests/firmware/fi/otbn:otbn_key_sideload", + "//sw/device/tests/penetrationtests/firmware/fi/otbn:otbn_load_integrity", "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", "//sw/device/tests/penetrationtests/json:otbn_fi_commands", ], diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn/BUILD b/sw/device/tests/penetrationtests/firmware/fi/otbn/BUILD index d8b69b1aa6190e..220dabd84b29ba 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/otbn/BUILD +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn/BUILD @@ -33,3 +33,17 @@ otbn_binary( "otbn_char_unrolled_reg_op_loop.s", ], ) + +otbn_binary( + name = "otbn_key_sideload", + srcs = [ + "otbn_key_sideload.s", + ], +) + +otbn_binary( + name = "otbn_load_integrity", + srcs = [ + "otbn_load_integrity.s", + ], +) diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_key_sideload.s b/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_key_sideload.s new file mode 100644 index 00000000000000..d57588e47f3ccb --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_key_sideload.s @@ -0,0 +1,53 @@ +/* Copyright lowRISC contributors (OpenTitan project). */ +/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + OBTN.KEY_SIDELOAD FI Penetration Test +*/ +.section .text.start + + /* Load all key shares into w20...w23. */ + bn.wsrr w20, KEY_S0_L + bn.wsrr w21, KEY_S1_L + bn.wsrr w22, KEY_S0_H + bn.wsrr w23, KEY_S1_H + + /* Write key shared into accessible DMEM. */ + li x2, 20 + la x3, k_s0_l + bn.sid x2, 0(x3) + + li x2, 21 + la x3, k_s0_h + bn.sid x2, 0(x3) + + li x2, 22 + la x3, k_s1_l + bn.sid x2, 0(x3) + + li x2, 23 + la x3, k_s1_h + bn.sid x2, 0(x3) + + ecall + +.data + .globl k_s0_l + .balign 32 + k_s0_l: + .zero 32 + + .globl k_s0_h + .balign 32 + k_s0_h: + .zero 32 + + .globl k_s1_l + .balign 32 + k_s1_l: + .zero 32 + + .globl k_s1_h + .balign 32 + k_s1_h: + .zero 32 diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_load_integrity.s b/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_load_integrity.s new file mode 100644 index 00000000000000..b2e6736e365289 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn/otbn_load_integrity.s @@ -0,0 +1,31 @@ +/* Copyright lowRISC contributors (OpenTitan project). */ +/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + OBTN.LOAD_INTEGRITY FI Penetration Test +*/ +.section .text.start + + /* Execute 10 NOPs. */ + li x1, 10 + loop x1, 1 + nop + + ecall + +.data + /* Reference values. */ + .balign 32 + .globl refval1 + refval1: + .word 0x1BADB002 + + .balign 32 + .globl refval2 + refval2: + .word 0x8BADF00D + + .balign 32 + .globl refval3 + refval3: + .word 0xA5A5A5A5 diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c index d7e8e869497e47..215c71a4527258 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c @@ -6,9 +6,13 @@ #include "sw/device/lib/base/memory.h" #include "sw/device/lib/base/status.h" +#include "sw/device/lib/crypto/drivers/keymgr.h" +#include "sw/device/lib/crypto/drivers/otbn.h" +#include "sw/device/lib/dif/dif_otbn.h" #include "sw/device/lib/dif/dif_rv_core_ibex.h" #include "sw/device/lib/runtime/log.h" #include "sw/device/lib/testing/entropy_testutils.h" +#include "sw/device/lib/testing/keymgr_testutils.h" #include "sw/device/lib/testing/test_framework/ottf_test_config.h" #include "sw/device/lib/testing/test_framework/ujson_ottf.h" #include "sw/device/lib/ujson/ujson.h" @@ -23,11 +27,237 @@ static dif_rv_core_ibex_t rv_core_ibex; static dif_otbn_t otbn; +static dif_keymgr_t keymgr; + +// Indicates whether the load_integrity test is already initialized. +static bool load_integrity_init; +// Reference checksum for the load integrity test. +static uint32_t load_checksum_ref; +// Load integrity test. Initialize OTBN app, load it, and get interface to +// OTBN data memory. +OTBN_DECLARE_APP_SYMBOLS(otbn_load_integrity); +OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval1); +OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval2); +OTBN_DECLARE_SYMBOL_ADDR(otbn_load_integrity, refval3); +const otbn_app_t kOtbnAppLoadIntegrity = OTBN_APP_T_INIT(otbn_load_integrity); +static const otbn_addr_t kOtbnAppLoadIntegrityRefVal1 = + OTBN_ADDR_T_INIT(otbn_load_integrity, refval1); +static const otbn_addr_t kOtbnAppLoadIntegrityRefVal2 = + OTBN_ADDR_T_INIT(otbn_load_integrity, refval2); +static const otbn_addr_t kOtbnAppLoadIntegrityRefVal3 = + OTBN_ADDR_T_INIT(otbn_load_integrity, refval3); + +// Indicates whether the key sideloading test is already initialized. +static bool key_sideloading_init; +// Key sideloading test. Initialize OTBN app, load it, and get interface to +// OTBN data memory. +OTBN_DECLARE_APP_SYMBOLS(otbn_key_sideload); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s0_l); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s0_h); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s1_l); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload, k_s1_h); +const otbn_app_t kOtbnAppKeySideload = OTBN_APP_T_INIT(otbn_key_sideload); +static const otbn_addr_t kOtbnAppKeySideloadks0l = + OTBN_ADDR_T_INIT(otbn_key_sideload, k_s0_l); +static const otbn_addr_t kOtbnAppKeySideloadks0h = + OTBN_ADDR_T_INIT(otbn_key_sideload, k_s0_h); +static const otbn_addr_t kOtbnAppKeySideloadks1l = + OTBN_ADDR_T_INIT(otbn_key_sideload, k_s1_l); +static const otbn_addr_t kOtbnAppKeySideloadks1h = + OTBN_ADDR_T_INIT(otbn_key_sideload, k_s1_h); + +uint32_t key_share_0_l_ref, key_share_0_h_ref; +uint32_t key_share_1_l_ref, key_share_1_h_ref; + +static const dif_keymgr_versioned_key_params_t kKeyVersionedParamsOTBNFI = { + .dest = kDifKeymgrVersionedKeyDestSw, + .salt = // the salt doesn't really matter here. + { + 0xb6521d8f, + 0x13a0e876, + 0x1ca1567b, + 0xb4fb0fdf, + 0x9f89bc56, + 0x4bd127c7, + 0x322288d8, + 0xde919d54, + }, + .version = 0x0, // specify a low enough version to work with the ROM EXT. +}; + +/** + * Clears the OTBN DMEM and IMEM. + * + * @returns OK or error. + */ +static status_t clear_otbn(void) { + // Clear OTBN memory. + TRY(otbn_dmem_sec_wipe()); + TRY(otbn_imem_sec_wipe()); -status_t read_otbn_err_bits(dif_otbn_err_bits_t *err_bits) { - dif_otbn_t otbn; - TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn)); - TRY(dif_otbn_get_err_bits(&otbn, err_bits)); + return OK_STATUS(); +} + +/** + * Read the error bits of the OTBN accelerator. + * + * @returns Error bits. + */ +status_t read_otbn_err_bits(dif_otbn_err_bits_t *err_otbn) { + TRY(dif_otbn_get_err_bits(&otbn, err_otbn)); + return OK_STATUS(); +} + +/** + * Read the OTBN load checksum. + * + * @returns Load checksum. + */ +status_t read_otbn_load_checksum(uint32_t *checksum) { + TRY(dif_otbn_get_load_checksum(&otbn, checksum)); + return OK_STATUS(); +} + +/** + * Clear the OTBN load checksum. + */ +status_t clear_otbn_load_checksum(void) { + TRY(dif_otbn_clear_load_checksum(&otbn)); + return OK_STATUS(); +} + +status_t handle_otbn_fi_key_sideload(ujson_t *uj) { + TRY(dif_otbn_set_ctrl_software_errs_fatal(&otbn, /*enable=*/false)); + // Clear registered alerts in alert handler. + sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + + if (!key_sideloading_init) { + // Setup keymanager for sideloading key into OTBN. + otbn_load_app(kOtbnAppKeySideload); + // Get reference keys. + otbn_execute(); + otbn_busy_wait_for_done(); + + otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l_ref); + otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h_ref); + otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l_ref); + otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h_ref); + + key_sideloading_init = true; + } + + // FI code target. + sca_set_trigger_high(); + otbn_execute(); + otbn_busy_wait_for_done(); + sca_set_trigger_low(); + + // Get registered alerts from alert handler. + reg_alerts = sca_get_triggered_alerts(); + + // Read loop counter from OTBN data memory. + uint32_t key_share_0_l, key_share_0_h; + uint32_t key_share_1_l, key_share_1_h; + otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l); + otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h); + otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l); + otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h); + + // Read ERR_STATUS register from OTBN. + dif_otbn_err_bits_t err_otbn; + read_otbn_err_bits(&err_otbn); + + // Read ERR_STATUS register from Ibex. + dif_rv_core_ibex_error_status_t err_ibx; + TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + + otbn_fi_keys_t uj_output; + uj_output.keys[0] = key_share_0_l; + uj_output.keys[1] = key_share_0_h; + uj_output.keys[2] = key_share_1_l; + uj_output.keys[3] = key_share_1_h; + + uj_output.res = 0; + if ((key_share_0_l != key_share_0_l_ref) || + (key_share_0_h != key_share_0_h_ref) || + (key_share_1_l != key_share_1_l_ref) || + (key_share_1_h != key_share_1_h_ref)) { + uj_output.res = 1; + } + + // Send result & ERR_STATUS to host. + uj_output.err_otbn = err_otbn; + uj_output.err_ibx = err_ibx; + memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts)); + RESP_OK(ujson_serialize_otbn_fi_keys_t, uj, &uj_output); + return OK_STATUS(); +} + +status_t handle_otbn_fi_load_integrity(ujson_t *uj) { + // Clear registered alerts in alert handler. + sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + + if (!load_integrity_init) { + // Load the OTBN app and read the load checksum without FI to retrieve + // reference value. + clear_otbn_load_checksum(); + otbn_load_app(kOtbnAppLoadIntegrity); + read_otbn_load_checksum(&load_checksum_ref); + clear_otbn_load_checksum(); + + load_integrity_init = true; + } + + // FI code target. + sca_set_trigger_high(); + otbn_load_app(kOtbnAppLoadIntegrity); + sca_set_trigger_low(); + // Get registered alerts from alert handler. + reg_alerts = sca_get_triggered_alerts(); + + // Read back checksum. + uint32_t load_checksum; + read_otbn_load_checksum(&load_checksum); + clear_otbn_load_checksum(); + + // Read loop counter from OTBN data memory. + uint32_t ref_val1, ref_val2, ref_val3; + otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal1, &ref_val1); + otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal2, &ref_val2); + otbn_dmem_read(1, kOtbnAppLoadIntegrityRefVal3, &ref_val3); + + // Check if DMEM is corrupted. + bool dmem_corrupted = false; + if ((ref_val1 != 0x1BADB002) || (ref_val2 != 0x8BADF00D) || + (ref_val3 != 0xA5A5A5A5)) { + dmem_corrupted = true; + } + + // If DMEM is corrupted and the checksum is still correct, we achieved the + // attack goal. + uint32_t res = 0; + if ((load_checksum_ref == load_checksum) && dmem_corrupted) { + res = 1; + } + + // Read ERR_STATUS register from OTBN. + dif_otbn_err_bits_t err_otbn; + read_otbn_err_bits(&err_otbn); + + // Read ERR_STATUS register from Ibex. + dif_rv_core_ibex_error_status_t err_ibx; + TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + + // Clear OTBN memory. + TRY(clear_otbn()); + + // Send result & ERR_STATUS to host. + otbn_fi_result_t uj_output; + uj_output.result = res; + uj_output.err_otbn = err_otbn; + uj_output.err_ibx = err_ibx; + memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts)); + RESP_OK(ujson_serialize_otbn_fi_result_t, uj, &uj_output); return OK_STATUS(); } @@ -65,6 +295,9 @@ status_t handle_otbn_fi_char_hardware_dmem_op_loop(ujson_t *uj) { dif_rv_core_ibex_error_status_t err_ibx; TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + // Clear OTBN memory. + TRY(clear_otbn()); + // Send loop counter & ERR_STATUS to host. otbn_fi_loop_counter_t uj_output; uj_output.loop_counter = loop_counter; @@ -109,6 +342,9 @@ status_t handle_otbn_fi_char_hardware_reg_op_loop(ujson_t *uj) { dif_rv_core_ibex_error_status_t err_ibx; TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + // Clear OTBN memory. + TRY(clear_otbn()); + // Send loop counter & ERR_STATUS to host. otbn_fi_loop_counter_t uj_output; uj_output.loop_counter = loop_counter; @@ -153,6 +389,9 @@ status_t handle_otbn_fi_char_unrolled_dmem_op_loop(ujson_t *uj) { dif_rv_core_ibex_error_status_t err_ibx; TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + // Clear OTBN memory. + TRY(clear_otbn()); + // Send loop counter & ERR_STATUS to host. otbn_fi_loop_counter_t uj_output; uj_output.loop_counter = loop_counter; @@ -197,6 +436,9 @@ status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj) { dif_rv_core_ibex_error_status_t err_ibx; TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &err_ibx)); + // Clear OTBN memory. + TRY(clear_otbn()); + // Send loop counter & ERR_STATUS to host. otbn_fi_loop_counter_t uj_output; uj_output.loop_counter = loop_counter; @@ -207,6 +449,19 @@ status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj) { return OK_STATUS(); } +status_t handle_otbn_fi_init_keymgr(ujson_t *uj) { + dif_kmac_t kmac; + TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac)); + TRY(dif_keymgr_init(mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR), + &keymgr)); + TRY(keymgr_testutils_initialize(&keymgr, &kmac)); + + dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParamsOTBNFI; + sideload_params.dest = kDifKeymgrVersionedKeyDestOtbn; + TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params)); + return OK_STATUS(); +} + status_t handle_otbn_fi_init(ujson_t *uj) { // Configure the entropy complex for OTBN. Set the reseed interval to max // to avoid a non-constant trigger window. @@ -233,6 +488,11 @@ status_t handle_otbn_fi_init(ujson_t *uj) { // Disable the instruction cache and dummy instructions for FI attacks. sca_configure_cpu(); + // The load integrity & key sideloading tests get initialized at the first + // run. + load_integrity_init = false; + key_sideloading_init = false; + // Read device ID and return to host. penetrationtest_device_id_t uj_output; TRY(sca_read_device_id(uj_output.device_id)); @@ -245,6 +505,8 @@ status_t handle_otbn_fi(ujson_t *uj) { otbn_fi_subcommand_t cmd; TRY(ujson_deserialize_otbn_fi_subcommand_t(uj, &cmd)); switch (cmd) { + case kOtbnFiSubcommandInitKeyMgr: + return handle_otbn_fi_init_keymgr(uj); case kOtbnFiSubcommandInit: return handle_otbn_fi_init(uj); case kOtbnFiSubcommandCharUnrolledRegOpLoop: @@ -255,6 +517,10 @@ status_t handle_otbn_fi(ujson_t *uj) { return handle_otbn_fi_char_hardware_reg_op_loop(uj); case kOtbnFiSubcommandCharHardwareDmemOpLoop: return handle_otbn_fi_char_hardware_dmem_op_loop(uj); + case kOtbnFiSubcommandLoadIntegrity: + return handle_otbn_fi_load_integrity(uj); + case kOtbnFiSubcommandKeySideload: + return handle_otbn_fi_key_sideload(uj); default: LOG_ERROR("Unrecognized OTBN FI subcommand: %d", cmd); return INVALID_ARGUMENT(); diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.h b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.h index 677da894416fac..3058ecfd04a126 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.h +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.h @@ -8,6 +8,36 @@ #include "sw/device/lib/base/status.h" #include "sw/device/lib/ujson/ujson.h" +/** + * otbn.fi.key_sideload command handler. + * + * Injects a fault when a key is sideloaded from the key manager into OTBN. + * + * Faults are injected during the trigger_high & trigger_low. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_fi_key_sideload(ujson_t *uj); + +/** + * otbn.fi.load_integrity command handler. + * + * Tests, whether a fault during loading the OTBN app can manipulate data in + * DMEM without changing the CRC-32 checksum that is used to check the + * integrity of the DMEM and IMEM. + * + * As the OTBN app itself is not the target of this FI analysis, it only + * consists of NOPs. The DMEM is initialized with reference values that + * are checked. + * + * Faults are injected during the trigger_high & trigger_low. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_fi_load_integrity(ujson_t *uj); + /** * otbn.fi.char.hardware.dmem.op.loop command handler. * @@ -75,6 +105,14 @@ status_t handle_otbn_fi_char_unrolled_dmem_op_loop(ujson_t *uj); */ status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj); +/** + * Initializes the key manager. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_fi_init_keymgr(ujson_t *uj); + /** * Initializes the OTBN FI test. * diff --git a/sw/device/tests/penetrationtests/json/otbn_fi_commands.h b/sw/device/tests/penetrationtests/json/otbn_fi_commands.h index a81bcba831953b..1fef1f85044d6c 100644 --- a/sw/device/tests/penetrationtests/json/otbn_fi_commands.h +++ b/sw/device/tests/penetrationtests/json/otbn_fi_commands.h @@ -12,11 +12,14 @@ extern "C" { // clang-format off #define OTBNFI_SUBCOMMAND(_, value) \ + value(_, InitKeyMgr) \ value(_, Init) \ value(_, CharUnrolledRegOpLoop) \ value(_, CharUnrolledDmemOpLoop) \ value(_, CharHardwareRegOpLoop) \ - value(_, CharHardwareDmemOpLoop) + value(_, CharHardwareDmemOpLoop) \ + value(_, LoadIntegrity) \ + value(_, KeySideload) UJSON_SERDE_ENUM(OtbnFiSubcommand, otbn_fi_subcommand_t, OTBNFI_SUBCOMMAND); #define OTBNFI_LOOP_COUNTER_OUTPUT(field, string) \ @@ -26,6 +29,21 @@ UJSON_SERDE_ENUM(OtbnFiSubcommand, otbn_fi_subcommand_t, OTBNFI_SUBCOMMAND); field(alerts, uint32_t, 3) UJSON_SERDE_STRUCT(OtbnFiLoopCounterOutput, otbn_fi_loop_counter_t, OTBNFI_LOOP_COUNTER_OUTPUT); +#define OTBNFI_RESULT_OUTPUT(field, string) \ + field(result, uint32_t) \ + field(err_otbn, uint32_t) \ + field(err_ibx, uint32_t) \ + field(alerts, uint32_t, 3) +UJSON_SERDE_STRUCT(OtbnFiResultOutput, otbn_fi_result_t, OTBNFI_RESULT_OUTPUT); + +#define OTBNFI_KEY_OUTPUT(field, string) \ + field(res, uint32_t) \ + field(keys, uint32_t, 4) \ + field(err_otbn, uint32_t) \ + field(err_ibx, uint32_t) \ + field(alerts, uint32_t, 3) +UJSON_SERDE_STRUCT(OtbnFiKeyOutput, otbn_fi_keys_t, OTBNFI_KEY_OUTPUT); + // clang-format on #ifdef __cplusplus