diff --git a/sw/device/tests/penetrationtests/firmware/BUILD b/sw/device/tests/penetrationtests/firmware/BUILD index 4e2cae8a72b67..ee64bc52dd8a1 100644 --- a/sw/device/tests/penetrationtests/firmware/BUILD +++ b/sw/device/tests/penetrationtests/firmware/BUILD @@ -16,6 +16,7 @@ FIRMWARE_DEPS_FPGA = [ "//sw/device/tests/penetrationtests/firmware/fi:ibex_fi", "//sw/device/tests/penetrationtests/firmware/fi:otbn_fi", "//sw/device/tests/penetrationtests/firmware/fi:rng_fi", + "//sw/device/tests/penetrationtests/firmware/fi:rom_fi", "//sw/device/tests/penetrationtests/firmware/sca:aes_sca", "//sw/device/tests/penetrationtests/firmware/sca:ibex_sca", "//sw/device/tests/penetrationtests/firmware/sca:kmac_sca", @@ -40,6 +41,7 @@ FIRMWARE_DEPS_FI = [ "//sw/device/tests/penetrationtests/firmware/fi:ibex_fi", "//sw/device/tests/penetrationtests/firmware/fi:otbn_fi", "//sw/device/tests/penetrationtests/firmware/fi:rng_fi", + "//sw/device/tests/penetrationtests/firmware/fi:rom_fi", "//sw/device/tests/penetrationtests/firmware/lib:extclk_sca_fi", "//sw/device/lib/base:csr", "//sw/device/lib/base:status", diff --git a/sw/device/tests/penetrationtests/firmware/fi/BUILD b/sw/device/tests/penetrationtests/firmware/fi/BUILD index b55b44271e18d..f412ac3cc134e 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/BUILD +++ b/sw/device/tests/penetrationtests/firmware/fi/BUILD @@ -109,3 +109,23 @@ cc_library( "//sw/device/tests/penetrationtests/json:rng_fi_commands", ], ) + +cc_library( + name = "rom_fi", + srcs = ["rom_fi.c"], + hdrs = ["rom_fi.h"], + deps = [ + "//hw/ip/rom_ctrl/data:rom_ctrl_c_regs", + "//sw/device/lib/base:abs_mmio", + "//sw/device/lib/base:memory", + "//sw/device/lib/base:status", + "//sw/device/lib/dif:rom_ctrl", + "//sw/device/lib/dif:rv_core_ibex", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing/test_framework:ujson_ottf", + "//sw/device/lib/ujson", + "//sw/device/sca/lib:sca", + "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/json:rom_fi_commands", + ], +) diff --git a/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c new file mode 100644 index 0000000000000..a347e3bbe0673 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c @@ -0,0 +1,122 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/tests/penetrationtests/firmware/fi/rom_fi.h" + +#include "sw/device/lib/base/abs_mmio.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/lib/base/status.h" +#include "sw/device/lib/dif/dif_rom_ctrl.h" +#include "sw/device/lib/dif/dif_rv_core_ibex.h" +#include "sw/device/lib/runtime/log.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" +#include "sw/device/sca/lib/sca.h" +#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/json/rom_fi_commands.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" +#include "rom_ctrl_regs.h" + +// NOP macros. +#define NOP1 "addi x0, x0, 0\n" +#define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 +#define NOP30 NOP10 NOP10 NOP10 + +// Interface to Ibex. +static dif_rv_core_ibex_t rv_core_ibex; + +static dif_rom_ctrl_t rom_ctrl; + +status_t handle_rom_read(ujson_t *uj) { + sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + + dif_rom_ctrl_digest_t expected_digest; + dif_rom_ctrl_digest_t fi_digest[8]; + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &expected_digest)); + + sca_set_trigger_high(); + asm volatile(NOP30); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[0])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[1])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[2])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[3])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[4])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[5])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[6])); + TRY(dif_rom_ctrl_get_digest(&rom_ctrl, &fi_digest[7])); + asm volatile(NOP30); + sca_set_trigger_low(); + + // Get registered alerts from alert handler. + reg_alerts = sca_get_triggered_alerts(); + + // Read ERR_STATUS register. + dif_rv_core_ibex_error_status_t codes; + TRY(dif_rv_core_ibex_get_error_status(&rv_core_ibex, &codes)); + + rom_fi_digest_t uj_output; + memset(uj_output.digest, 0, sizeof(uj_output.digest)); + for (size_t i = 0; i < 8; i++) { + if (memcmp(&expected_digest, &fi_digest[i], + ROM_CTRL_DIGEST_MULTIREG_COUNT)) { + uj_output.digest[i] = + fi_digest[i] + .digest[0]; // Just return the first 32-bit of the digest. + } + } + + // Send the first 8 bytes of the digest and the alerts back to the host. + uj_output.err_status = codes; + memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts)); + RESP_OK(ujson_serialize_rom_fi_digest_t, uj, &uj_output); + return OK_STATUS(); +} + +status_t handle_rom_fi_init(ujson_t *uj) { + sca_select_trigger_type(kScaTriggerTypeSw); + sca_init(kScaTriggerSourceAes, + kScaPeripheralIoDiv4 | kScaPeripheralEdn | kScaPeripheralCsrng | + kScaPeripheralEntropy | kScaPeripheralKmac); + + // Configure the alert handler. Alerts triggered by IP blocks are captured + // and reported to the test. + sca_configure_alert_handler(); + + // Disable the instruction cache and dummy instructions for FI attacks. + sca_configure_cpu(); + + // Initialize rom_ctrl. + mmio_region_t rom_ctrl_reg = + mmio_region_from_addr(TOP_EARLGREY_ROM_CTRL_REGS_BASE_ADDR); + TRY(dif_rom_ctrl_init(rom_ctrl_reg, &rom_ctrl)); + + // Configure Ibex to allow reading ERR_STATUS register. + TRY(dif_rv_core_ibex_init( + mmio_region_from_addr(TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR), + &rv_core_ibex)); + + // Read device ID and return to host. + penetrationtest_device_id_t uj_output; + TRY(sca_read_device_id(uj_output.device_id)); + RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); + + return OK_STATUS(); +} + +status_t handle_rom_fi(ujson_t *uj) { + rom_fi_subcommand_t cmd; + TRY(ujson_deserialize_rom_fi_subcommand_t(uj, &cmd)); + switch (cmd) { + case kRomFiSubcommandInit: + return handle_rom_fi_init(uj); + case kRomFiSubcommandRead: + return handle_rom_read(uj); + default: + LOG_ERROR("Unrecognized Rom FI subcommand: %d", cmd); + return INVALID_ARGUMENT(); + } + return OK_STATUS(); +} diff --git a/sw/device/tests/penetrationtests/firmware/fi/rom_fi.h b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.h new file mode 100644 index 0000000000000..d9bfffc49dfc3 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.h @@ -0,0 +1,39 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_FI_ROM_FI_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_FI_ROM_FI_H_ + +#include "sw/device/lib/base/status.h" +#include "sw/device/lib/ujson/ujson.h" + +/** + * ROM read FI test. + * + * Read the ROM digest while injecting faults. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_rom_fi_init(ujson_t *uj); + +/** + * Initializes the trigger and configures the device for the Rom FI test. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_rom_fi_init(ujson_t *uj); + +/** + * Rom FI command handler. + * + * Command handler for the Rom FI command. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_rom_fi(ujson_t *uj); + +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_FI_ROM_FI_H_ diff --git a/sw/device/tests/penetrationtests/firmware/firmware.c b/sw/device/tests/penetrationtests/firmware/firmware.c index abca4b4e9097b..7d4b663a160b4 100644 --- a/sw/device/tests/penetrationtests/firmware/firmware.c +++ b/sw/device/tests/penetrationtests/firmware/firmware.c @@ -21,6 +21,7 @@ #include "sw/device/tests/penetrationtests/json/otbn_fi_commands.h" #include "sw/device/tests/penetrationtests/json/prng_sca_commands.h" #include "sw/device/tests/penetrationtests/json/rng_fi_commands.h" +#include "sw/device/tests/penetrationtests/json/rom_fi_commands.h" #include "sw/device/tests/penetrationtests/json/sha3_sca_commands.h" #include "sw/device/tests/penetrationtests/json/trigger_sca_commands.h" @@ -29,6 +30,7 @@ #include "fi/ibex_fi.h" #include "fi/otbn_fi.h" #include "fi/rng_fi.h" +#include "fi/rom_fi.h" #include "lib/extclk_sca_fi.h" #include "sca/aes_sca.h" #include "sca/ibex_sca.h" @@ -71,6 +73,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandRngFi: RESP_ERR(uj, handle_rng_fi(uj)); break; + case kPenetrationtestCommandRomFi: + RESP_ERR(uj, handle_rom_fi(uj)); + break; case kPenetrationtestCommandSha3Sca: RESP_ERR(uj, handle_sha3_sca(uj)); break; diff --git a/sw/device/tests/penetrationtests/firmware/firmware_fi.c b/sw/device/tests/penetrationtests/firmware/firmware_fi.c index 6f4193ad5d8de..05908e1aa7bcc 100644 --- a/sw/device/tests/penetrationtests/firmware/firmware_fi.c +++ b/sw/device/tests/penetrationtests/firmware/firmware_fi.c @@ -16,12 +16,14 @@ #include "sw/device/tests/penetrationtests/json/ibex_fi_commands.h" #include "sw/device/tests/penetrationtests/json/otbn_fi_commands.h" #include "sw/device/tests/penetrationtests/json/rng_fi_commands.h" +#include "sw/device/tests/penetrationtests/json/rom_fi_commands.h" // Include handlers #include "fi/crypto_fi.h" #include "fi/ibex_fi.h" #include "fi/otbn_fi.h" #include "fi/rng_fi.h" +#include "fi/rom_fi.h" #include "lib/extclk_sca_fi.h" OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true); @@ -46,6 +48,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandRngFi: RESP_ERR(uj, handle_rng_fi(uj)); break; + case kPenetrationtestCommandRomFi: + RESP_ERR(uj, handle_rom_fi(uj)); + break; default: LOG_ERROR("Unrecognized command: %d", cmd); RESP_ERR(uj, INVALID_ARGUMENT()); diff --git a/sw/device/tests/penetrationtests/json/BUILD b/sw/device/tests/penetrationtests/json/BUILD index 03ad68184a288..75227cceca5fd 100644 --- a/sw/device/tests/penetrationtests/json/BUILD +++ b/sw/device/tests/penetrationtests/json/BUILD @@ -16,6 +16,7 @@ cc_library( ":kmac_sca_commands", ":otbn_fi_commands", ":prng_sca_commands", + ":rom_fi_commands", ":sha3_sca_commands", ":trigger_sca_commands", "//sw/device/lib/ujson", @@ -85,6 +86,13 @@ cc_library( deps = ["//sw/device/lib/ujson"], ) +cc_library( + name = "rom_fi_commands", + srcs = ["rom_fi_commands.c"], + hdrs = ["rom_fi_commands.h"], + deps = ["//sw/device/lib/ujson"], +) + cc_library( name = "sca_lib_commands", srcs = ["sca_lib_commands.c"], diff --git a/sw/device/tests/penetrationtests/json/commands.h b/sw/device/tests/penetrationtests/json/commands.h index 708f745f8f20c..98a0a04b82460 100644 --- a/sw/device/tests/penetrationtests/json/commands.h +++ b/sw/device/tests/penetrationtests/json/commands.h @@ -21,6 +21,7 @@ extern "C" { value(_, OtbnFi) \ value(_, PrngSca) \ value(_, RngFi) \ + value(_, RomFi) \ value(_, Sha3Sca) \ value(_, TriggerSca) UJSON_SERDE_ENUM(PenetrationtestCommand, penetrationtest_cmd_t, COMMAND); diff --git a/sw/device/tests/penetrationtests/json/rom_fi_commands.c b/sw/device/tests/penetrationtests/json/rom_fi_commands.c new file mode 100644 index 0000000000000..cc88ff3fd4b83 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/rom_fi_commands.c @@ -0,0 +1,6 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#define UJSON_SERDE_IMPL 1 +#include "rom_fi_commands.h" diff --git a/sw/device/tests/penetrationtests/json/rom_fi_commands.h b/sw/device/tests/penetrationtests/json/rom_fi_commands.h new file mode 100644 index 0000000000000..f321c55240929 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/rom_fi_commands.h @@ -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 + +#ifndef OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_ROM_FI_COMMANDS_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_ROM_FI_COMMANDS_H_ +#include "sw/device/lib/ujson/ujson_derive.h" +#ifdef __cplusplus +extern "C" { +#endif + +// clang-format off + +#define ROMFI_SUBCOMMAND(_, value) \ + value(_, Init) \ + value(_, Read) +UJSON_SERDE_ENUM(RomFiSubcommand, rom_fi_subcommand_t, ROMFI_SUBCOMMAND); + + +#define ROMFI_DIGEST(field, string) \ + field(digest, uint32_t, 8) \ + field(alerts, uint32_t, 3) \ + field(err_status, uint32_t) +UJSON_SERDE_STRUCT(RomFiDigest, rom_fi_digest_t, ROMFI_DIGEST); + +// clang-format on + +#ifdef __cplusplus +} +#endif +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_ROM_FI_COMMANDS_H_