diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000000..d5df4ec64dcb7b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: CI +on: + pull_request: + +jobs: + airgapped_build: + name: Airgapped build + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Bitstream cache requires all commits. + - name: Install system dependencies + run: grep '^[^#]' apt-requirements.txt | xargs sudo apt install -y + - name: Prepare airgapped environment + run: ./util/prep-bazel-airgapped-build.sh + - name: Build in the airgapped environment + run: ./ci/scripts/test-airgapped-build.sh diff --git a/COMMITTERS b/COMMITTERS index a5fdf82761e025..62ba339145b19d 100644 --- a/COMMITTERS +++ b/COMMITTERS @@ -11,6 +11,7 @@ Committer list: * Miles Dai (milesdai) * Jon Flatley (jon-flatley) * Chris Frantz (cfrantz) +* Gary Guo (nbdd0121) * Jes Klinke (jesultra) * Andreas Kurth (andreaskurth) * Adrian Lees (alees24) @@ -21,6 +22,7 @@ Committer list: * Hugo McNally (HU90m) * Felix Miller (felixmiller) * Michael Munday (mundaym) +* Pascal Nasahl (nasahlpa) * Miguel Osorio (moidx) * Jade Philipoom (jadephilipoom) * Amaury Pouly (pamaury) diff --git a/WORKSPACE b/WORKSPACE index 566c956df23f3e..bda2ffd6579fc4 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -149,6 +149,10 @@ sphincsplus_repos() load("//rules:bitstreams.bzl", "bitstreams_repo") bitstreams_repo(name = "bitstreams") +# CBOR reader & writer from open-dice +load("//third_party/open-dice:repos.bzl", "open_dice_repos") +open_dice_repos() + # Setup for linking in externally managed test and provisioning customizations # for both secure/non-secure manufacturer domains. load("//rules:hooks_setup.bzl", "hooks_setup", "provisioning_exts_setup", "secure_hooks_setup") diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f74f80c42b6dbf..76ec9313aad246 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -131,6 +131,7 @@ jobs: steps: - template: ci/checkout-template.yml - template: ci/install-package-dependencies.yml + - bash: util/prep-bazel-airgapped-build.sh - bash: ci/scripts/test-airgapped-build.sh - job: slow_lints diff --git a/ci/scripts/test-airgapped-build.sh b/ci/scripts/test-airgapped-build.sh index 7604c288ac5d52..fbf52c4dec5515 100755 --- a/ci/scripts/test-airgapped-build.sh +++ b/ci/scripts/test-airgapped-build.sh @@ -5,8 +5,11 @@ set -ex -# Prefetch bazel airgapped dependencies. -util/prep-bazel-airgapped-build.sh -f +# Prefetch bazel airgapped dependencies if not already done. +if [ ! -d bazel-airgapped ]; then + echo "Airgapped environment not found, preparing..." >&2 + util/prep-bazel-airgapped-build.sh -f +fi # Remove the airgapped network namespace. remove_airgapped_netns() { diff --git a/doc/getting_started/setup_fpga.md b/doc/getting_started/setup_fpga.md index 7a2bb87a027b9c..7215bd0f3985d1 100644 --- a/doc/getting_started/setup_fpga.md +++ b/doc/getting_started/setup_fpga.md @@ -240,8 +240,8 @@ On your CW340 base board (the red board): 1. UART1 RX/TX (OpenTitan pins IOA0/1): JP3 & JP4 1. JTAG TAP select straps (OpenTitan pins IOC5/8): JP11 & JP12 1. Connect the following blue socket-to-socket jumpers in the middle of the board to `HD` (for "HyperDebug"). - 1. SPI Device: connect JP23 to JP25 - 1. JTAG: connect JP13 to JP15 + 1. SPI Device: connect J23 to J25 + 1. JTAG: connect J12 to J13 ##### Connecting HyperDebug to the CW340 Base Board @@ -251,7 +251,6 @@ On your CW340 base board (the red board): 1. Ensure the HyperDebug jumper JP4 is set to select `1.8V`. 1. Connect the HyperDebug board to the ST Zio connectors in the bottom left of the board. 1. Connect the PC USB-C cable back to your HyperDebug board. -1. Connect the PC USB-C cable back to your HyperDebug board. 1. Power on the CW340 by setting the *Control Power* switch in the top left corner, *SW7*, to the left towards the barrel jack. ### Detecting the PC Connections to the Board(s) diff --git a/hw/ip/prim/rtl/prim_count.sv b/hw/ip/prim/rtl/prim_count.sv index f70999c546bcdb..15eb4a9b850ea0 100644 --- a/hw/ip/prim/rtl/prim_count.sv +++ b/hw/ip/prim/rtl/prim_count.sv @@ -292,10 +292,14 @@ module prim_count $past(clr_i || set_i || (commit_i && (incr_en_i || decr_en_i))), clk_i, err_d || fpv_err_present || !rst_ni) - // Check that count errors are reported properly in err_d - `ASSERT(CntErrReported_A, ((cnt_q[1] + cnt_q[0]) != {Width{1'b1}}) == err_d) + // Check that count errors are reported properly in err_o + // + // This is essentially a "|=> implication", but is structured in a way to avoid generating a cover + // property for the left hand side if PrimCountFpv is not defined (because we won't have a way to + // inject an error if not) + `ASSERT(CntErrReported_A, ##1 $past((cnt_q[1] + cnt_q[0]) != {Width{1'b1}}) == err_o) `ifdef PrimCountFpv - `COVER(CntErr_C, err_d) + `COVER(CntErr_C, err_o) `endif // This logic that will be assign to one, when user adds macro diff --git a/hw/ip/prim/rtl/prim_fifo_sync.sv b/hw/ip/prim/rtl/prim_fifo_sync.sv index 6fc3560cbea9cd..c4c1ac429fd46a 100644 --- a/hw/ip/prim/rtl/prim_fifo_sync.sv +++ b/hw/ip/prim/rtl/prim_fifo_sync.sv @@ -148,7 +148,7 @@ module prim_fifo_sync #( // Known Assertions // ////////////////////// - `ASSERT(DataKnown_A, rvalid_o |-> !$isunknown(rdata_o)) + `ASSERT_KNOWN_IF(DataKnown_A, rdata_o, rvalid_o) `ASSERT_KNOWN(DepthKnown_A, depth_o) `ASSERT_KNOWN(RvalidKnown_A, rvalid_o) `ASSERT_KNOWN(WreadyKnown_A, wready_o) diff --git a/hw/ip/rv_dm/dv/cov/rv_dm_cov_excl.el b/hw/ip/rv_dm/dv/cov/rv_dm_cov_excl.el index 2851c854ce6f3a..eb0a5dd250c1b8 100644 --- a/hw/ip/rv_dm/dv/cov/rv_dm_cov_excl.el +++ b/hw/ip/rv_dm/dv/cov/rv_dm_cov_excl.el @@ -43,6 +43,12 @@ Transition StFlush->StActive "76->289" Transition StFlush->StError "76->186" Transition StOutstanding->StFlush "231->76" +// The code being waived here is from tlul_rsp_intg_gen.sv and gets run if the EnableRspIntgGen +// or EnableDataIntgGen parameters are zero. They aren't, so we need to waive this line coverage. +INSTANCE: tb.dut.u_reg_regs.u_reg_if.u_rsp_intg_gen +Block 1 "461445014" "assign rsp_intg = tl_i.d_user.rsp_intg;" +Block 2 "2643129081" "assign data_intg = tl_i.d_user.data_intg;" + // The following exclusions were generated by UNR. // //================================================== diff --git a/sw/device/tests/penetrationtests/firmware/BUILD b/sw/device/tests/penetrationtests/firmware/BUILD index fbdb2ac3d1b0b2..ca643d30b1f6e5 100644 --- a/sw/device/tests/penetrationtests/firmware/BUILD +++ b/sw/device/tests/penetrationtests/firmware/BUILD @@ -20,9 +20,11 @@ FIRMWARE_DEPS_FPGA = [ "//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:edn_sca", "//sw/device/tests/penetrationtests/firmware/sca:hmac_sca", "//sw/device/tests/penetrationtests/firmware/sca:ibex_sca", "//sw/device/tests/penetrationtests/firmware/sca:kmac_sca", + "//sw/device/tests/penetrationtests/firmware/sca:otbn_sca", "//sw/device/tests/penetrationtests/firmware/sca:prng_sca", "//sw/device/tests/penetrationtests/firmware/sca:sha3_sca", "//sw/device/tests/penetrationtests/firmware/sca:trigger_sca", @@ -62,9 +64,11 @@ FIRMWARE_DEPS_FI = [ FIRMWARE_DEPS_SCA = [ "//sw/device/tests/penetrationtests/firmware/sca:aes_sca", + "//sw/device/tests/penetrationtests/firmware/sca:edn_sca", "//sw/device/tests/penetrationtests/firmware/sca:hmac_sca", "//sw/device/tests/penetrationtests/firmware/sca:ibex_sca", "//sw/device/tests/penetrationtests/firmware/sca:kmac_sca", + "//sw/device/tests/penetrationtests/firmware/sca:otbn_sca", "//sw/device/tests/penetrationtests/firmware/sca:prng_sca", "//sw/device/tests/penetrationtests/firmware/sca:sha3_sca", "//sw/device/tests/penetrationtests/firmware/sca:trigger_sca", diff --git a/sw/device/tests/penetrationtests/firmware/fi/BUILD b/sw/device/tests/penetrationtests/firmware/fi/BUILD index 90ae7ac2daf1a7..c221542cd6d1f1 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/BUILD +++ b/sw/device/tests/penetrationtests/firmware/fi/BUILD @@ -22,7 +22,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:crypto_fi_commands", ], ) @@ -52,7 +52,7 @@ cc_library( "//sw/device/sca/lib:sca", "//sw/device/silicon_creator/lib/drivers:retention_sram", "//sw/device/silicon_creator/manuf/lib:otp_fields", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:ibex_fi_commands", ], ) @@ -71,7 +71,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:lc_ctrl_fi_commands", ], ) @@ -99,7 +99,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:otbn_fi_commands", ], ) @@ -124,7 +124,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:rng_fi_commands", ], ) @@ -142,7 +142,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:otp_fi_commands", ], ) @@ -162,7 +162,7 @@ cc_library( "//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/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:rom_fi_commands", ], ) diff --git a/sw/device/tests/penetrationtests/firmware/fi/crypto_fi.c b/sw/device/tests/penetrationtests/firmware/fi/crypto_fi.c index 7d2825050596d1..5b17982dc3593c 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/crypto_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/crypto_fi.c @@ -17,7 +17,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/crypto_fi_commands.h" #include "aes_regs.h" @@ -156,7 +156,7 @@ status_t handle_crypto_fi_aes(ujson_t *uj) { crypto_fi_aes_mode_t uj_data; TRY(ujson_deserialize_crypto_fi_aes_mode_t(uj, &uj_data)); // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Write the key into the AES block. Set and unset the trigger when // key_trigger is true. @@ -214,7 +214,7 @@ status_t handle_crypto_fi_aes(ujson_t *uj) { } // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -236,10 +236,10 @@ status_t handle_crypto_fi_init(ujson_t *uj) { kScaPeripheralEdn | kScaPeripheralCsrng | kScaPeripheralEntropy); // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Init the AES block. TRY(dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes)); @@ -279,7 +279,7 @@ status_t handle_crypto_fi_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); @@ -290,7 +290,7 @@ status_t handle_crypto_fi_kmac(ujson_t *uj) { crypto_fi_kmac_mode_t uj_data; TRY(ujson_deserialize_crypto_fi_kmac_mode_t(uj, &uj_data)); // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Configure and write key to the KMAC block. Set and unset the trigger when // key_trigger is true. @@ -348,7 +348,7 @@ status_t handle_crypto_fi_kmac(ujson_t *uj) { /*capacity=*/NULL)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); TRY(dif_kmac_end(&kmac, &kmac_operation_state)); @@ -371,7 +371,7 @@ status_t handle_crypto_fi_kmac_state(ujson_t *uj) { crypto_fi_kmac_mode_t uj_data; TRY(ujson_deserialize_crypto_fi_kmac_mode_t(uj, &uj_data)); // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Configure and write key to the KMAC block. dif_kmac_operation_state_t kmac_operation_state; @@ -396,7 +396,7 @@ status_t handle_crypto_fi_kmac_state(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -426,7 +426,7 @@ status_t handle_crypto_fi_kmac_state(ujson_t *uj) { status_t handle_crypto_fi_shadow_reg_access(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); crypto_fi_test_result_mult_t uj_output; @@ -459,7 +459,7 @@ status_t handle_crypto_fi_shadow_reg_access(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -482,7 +482,7 @@ status_t handle_crypto_fi_shadow_reg_access(ujson_t *uj) { status_t handle_crypto_fi_shadow_reg_read(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); crypto_fi_test_result_mult_t uj_output; @@ -538,7 +538,7 @@ status_t handle_crypto_fi_shadow_reg_read(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; diff --git a/sw/device/tests/penetrationtests/firmware/fi/ibex_fi.c b/sw/device/tests/penetrationtests/firmware/fi/ibex_fi.c index ba142b366b35ff..ef7bec5465c389 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/ibex_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/ibex_fi.c @@ -22,7 +22,7 @@ #include "sw/device/sca/lib/sca.h" #include "sw/device/silicon_creator/lib/drivers/retention_sram.h" #include "sw/device/silicon_creator/manuf/lib/otp_fields.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/ibex_fi_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -239,7 +239,7 @@ static inline void read_all_regs(uint32_t buffer[]) { static status_t read_otp_partitions(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t otp_data_read_res_vendor_test[(OTP_CTRL_PARAM_VENDOR_TEST_SIZE - @@ -276,7 +276,7 @@ static status_t read_otp_partitions(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Detect potential mismatch caused by faults. uint32_t res = 0; @@ -342,7 +342,7 @@ void not_increment_counter(void) __attribute__((optnone)) { status_t handle_ibex_fi_address_translation(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Create translation descriptions. dif_rv_core_ibex_addr_translation_mapping_t increment_100x10_mapping = { @@ -394,7 +394,7 @@ status_t handle_ibex_fi_address_translation(ujson_t *uj) { result_expected = increment_100x10_remapped(0); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); uint32_t result_target = increment_100x1_remapped(0); // Compare values @@ -422,7 +422,7 @@ status_t handle_ibex_fi_address_translation(ujson_t *uj) { status_t handle_ibex_fi_address_translation_config(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Address translation configuration. dif_rv_core_ibex_addr_translation_mapping_t mapping1 = { @@ -452,7 +452,7 @@ status_t handle_ibex_fi_address_translation_config(ujson_t *uj) { asm volatile(NOP1000); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read back address translation configuration. dif_rv_core_ibex_addr_translation_mapping_t mapping1_read_back; @@ -495,7 +495,7 @@ status_t handle_ibex_fi_address_translation_config(ujson_t *uj) { status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -547,7 +547,7 @@ status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj) asm volatile("endfitestbeq:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -566,7 +566,7 @@ status_t handle_ibex_fi_char_conditional_branch_beq(ujson_t *uj) status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -618,7 +618,7 @@ status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj) asm volatile("endfitestbge:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -637,7 +637,7 @@ status_t handle_ibex_fi_char_conditional_branch_bge(ujson_t *uj) status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -689,7 +689,7 @@ status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj) asm volatile("endfitestbgeu:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -708,7 +708,7 @@ status_t handle_ibex_fi_char_conditional_branch_bgeu(ujson_t *uj) status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -760,7 +760,7 @@ status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj) asm volatile("endfitestblt:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -779,7 +779,7 @@ status_t handle_ibex_fi_char_conditional_branch_blt(ujson_t *uj) status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -831,7 +831,7 @@ status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj) asm volatile("endfitestbltu:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -850,7 +850,7 @@ status_t handle_ibex_fi_char_conditional_branch_bltu(ujson_t *uj) status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t result1 = 0; uint32_t result2 = 0; @@ -902,7 +902,7 @@ status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj) asm volatile("endfitestbne:\n"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -920,7 +920,7 @@ status_t handle_ibex_fi_char_conditional_branch_bne(ujson_t *uj) status_t handle_ibex_fi_char_csr_read(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Write reference value into CSR. CSR_WRITE(CSR_REG_MSCRATCH, ref_values[0]); @@ -947,7 +947,7 @@ status_t handle_ibex_fi_char_csr_read(ujson_t *uj) { read_temp_regs(res_values); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Compare against reference values. uint32_t res = 0; @@ -973,7 +973,7 @@ status_t handle_ibex_fi_char_csr_read(ujson_t *uj) { status_t handle_ibex_fi_char_csr_write(ujson_t *uj) { ibex_fi_test_result_t uj_output; // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Init x5 with reference value. asm volatile("li x5, %0" : : "i"(ref_values[0])); @@ -1014,7 +1014,7 @@ status_t handle_ibex_fi_char_csr_write(ujson_t *uj) { asm volatile("mv %0, x5" : "=r"(res_value)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Compare against reference values. uj_output.result = 0; @@ -1035,7 +1035,7 @@ status_t handle_ibex_fi_char_csr_write(ujson_t *uj) { status_t handle_ibex_fi_char_flash_read(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); if (!flash_init) { // Configure the data flash. @@ -1103,7 +1103,7 @@ status_t handle_ibex_fi_char_flash_read(ujson_t *uj) __attribute__((optnone)) { read_temp_regs(res_values); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Compare against reference values. ibex_fi_faulty_addresses_data_t uj_output; @@ -1133,7 +1133,7 @@ status_t handle_ibex_fi_char_flash_read(ujson_t *uj) __attribute__((optnone)) { status_t handle_ibex_fi_char_flash_write(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); if (!flash_init) { // Configure the data flash. @@ -1176,7 +1176,7 @@ status_t handle_ibex_fi_char_flash_write(ujson_t *uj) { kDifFlashCtrlPartitionTypeData, FLASH_UINT32_WORDS_PER_PAGE)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read back and compare against reference values. uint32_t res_values[32]; @@ -1205,7 +1205,7 @@ status_t handle_ibex_fi_char_flash_write(ujson_t *uj) { status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. // uint32_t value1 = 0; @@ -1228,7 +1228,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1247,7 +1247,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_complement_branch(ujson_t *uj) status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. // uint32_t value1 = 0; @@ -1267,7 +1267,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1286,7 +1286,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_unimp(ujson_t *uj) status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. // uint32_t value1 = 0; @@ -1306,7 +1306,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1325,7 +1325,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_2_unimps(ujson_t *uj) status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. // uint32_t value1 = 0; @@ -1345,7 +1345,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1364,7 +1364,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_3_unimps(ujson_t *uj) status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. // uint32_t value1 = 0; @@ -1384,7 +1384,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1403,7 +1403,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_4_unimps(ujson_t *uj) status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Values are intentially not equal. hardened_bool_t value1 = HARDENED_BOOL_TRUE; @@ -1420,7 +1420,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1438,7 +1438,7 @@ status_t handle_ibex_fi_char_hardened_check_eq_5_unimps(ujson_t *uj) status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t loop_counter1 = 0; @@ -1451,7 +1451,7 @@ status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj) { } sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1469,7 +1469,7 @@ status_t handle_ibex_fi_char_mem_op_loop(ujson_t *uj) { status_t handle_ibex_fi_char_register_file(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t res_values[7]; // Initialize temporary registers with reference values. @@ -1486,7 +1486,7 @@ status_t handle_ibex_fi_char_register_file(ujson_t *uj) { asm volatile(NOP1000); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Load register values. asm volatile("mv %0, x5" : "=r"(res_values[0])); @@ -1521,7 +1521,7 @@ status_t handle_ibex_fi_char_register_file(ujson_t *uj) { status_t handle_ibex_fi_char_register_file_read(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t res_values[6]; // Initialize temporary registers with reference values. @@ -1567,7 +1567,7 @@ status_t handle_ibex_fi_char_register_file_read(ujson_t *uj) { asm volatile("or x30, x30, x30"); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Load register values. asm volatile("mv %0, x5" : "=r"(res_values[0])); @@ -1602,7 +1602,7 @@ status_t handle_ibex_fi_char_register_file_read(ujson_t *uj) { status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t loop_counter1 = 0; @@ -1619,7 +1619,7 @@ status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj) { asm volatile("mv %0, x6" : "=r"(loop_counter2)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -1637,7 +1637,7 @@ status_t handle_ibex_fi_char_reg_op_loop(ujson_t *uj) { status_t handle_ibex_fi_char_sram_read(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Init t0...t6 with 0. init_temp_regs(0); @@ -1665,7 +1665,7 @@ status_t handle_ibex_fi_char_sram_read(ujson_t *uj) { read_temp_regs(res_values); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); ibex_fi_faulty_addresses_data_t uj_output; memset(uj_output.addresses, 0, sizeof(uj_output.addresses)); @@ -1705,7 +1705,7 @@ status_t handle_ibex_fi_char_sram_static(ujson_t *uj) { (TOP_EARLGREY_SRAM_CTRL_RET_AON_RAM_SIZE_BYTES / sizeof(uint32_t)) - 1; // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Get address of the ret. SRAM at the beginning of the owner section. uintptr_t sram_ret_buffer_addr = @@ -1725,7 +1725,7 @@ status_t handle_ibex_fi_char_sram_static(ujson_t *uj) { asm volatile(NOP1000); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Compare against reference values. ibex_fi_faulty_addresses_data_t uj_output; @@ -1760,7 +1760,7 @@ status_t handle_ibex_fi_char_sram_static(ujson_t *uj) { status_t handle_ibex_fi_char_sram_write(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Get address of buffer located in SRAM. uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer; @@ -1782,7 +1782,7 @@ status_t handle_ibex_fi_char_sram_write(ujson_t *uj) { } sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read back and compare against reference values. uint32_t res_values[32]; @@ -1811,7 +1811,7 @@ status_t handle_ibex_fi_char_sram_write(ujson_t *uj) { status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj) __attribute__((optnone)) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Initialize SRAM region with inverse reference value. sram_main_buffer[0] = ~ref_values[0]; @@ -1922,7 +1922,7 @@ status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj) asm volatile(NOP10); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); uint32_t res_values[3]; asm volatile("mv %0, x5" : "=r"(res_values[0])); @@ -1954,7 +1954,7 @@ status_t handle_ibex_fi_char_sram_write_read(ujson_t *uj) status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Get address of buffer located in SRAM. uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer; @@ -2101,7 +2101,7 @@ status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj) { ref_values[0]); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read back and compare against reference values. uint32_t res_values[64]; @@ -2129,7 +2129,7 @@ status_t handle_ibex_fi_char_sram_write_static_unrolled(ujson_t *uj) { status_t handle_ibex_fi_char_unconditional_branch(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t result = 0; @@ -2172,7 +2172,7 @@ status_t handle_ibex_fi_char_unconditional_branch(ujson_t *uj) { asm volatile("mv %0, x5" : "=r"(result)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -2191,7 +2191,7 @@ status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj) { uint32_t registers[32] = {0}; read_all_regs(registers); // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t result = 0; @@ -2235,7 +2235,7 @@ status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj) { asm volatile("mv %0, x5" : "=r"(result)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -2253,7 +2253,7 @@ status_t handle_ibex_fi_char_unconditional_branch_nop(ujson_t *uj) { status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t loop_counter = 0; @@ -2271,7 +2271,7 @@ status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj) { asm volatile(LWADDISW1000 : : "r"((uint32_t *)&loop_counter)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -2288,7 +2288,7 @@ status_t handle_ibex_fi_char_unrolled_mem_op_loop(ujson_t *uj) { status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // FI code target. uint32_t loop_counter = 0; @@ -2308,7 +2308,7 @@ status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj) { asm volatile("mv %0, x5" : "=r"(loop_counter)); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -2325,7 +2325,7 @@ status_t handle_ibex_fi_char_unrolled_reg_op_loop(ujson_t *uj) { status_t handle_ibex_fi_char_unrolled_reg_op_loop_chain(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint32_t addresses[8] = {0}; uint32_t data[8] = {0}; @@ -2353,7 +2353,7 @@ status_t handle_ibex_fi_char_unrolled_reg_op_loop_chain(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -2380,10 +2380,10 @@ status_t handle_ibex_fi_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Enable the flash. flash_info = dif_flash_ctrl_get_device_info(); @@ -2402,7 +2402,7 @@ status_t handle_ibex_fi_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); // Initialize flash for the flash test and write reference values into page. @@ -2435,7 +2435,7 @@ status_t handle_ibex_fi_otp_read_lock(ujson_t *uj) { status_t handle_ibex_fi_otp_write_lock(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); uint64_t faulty_token[kSecret0TestUnlockTokenSizeIn64BitWords]; for (size_t i = 0; i < kSecret0TestUnlockTokenSizeIn64BitWords; i++) { diff --git a/sw/device/tests/penetrationtests/firmware/fi/lc_ctrl_fi.c b/sw/device/tests/penetrationtests/firmware/fi/lc_ctrl_fi.c index ceb2943cb1fe86..c7d9645b095417 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/lc_ctrl_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/lc_ctrl_fi.c @@ -11,7 +11,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/lc_ctrl_fi_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -31,7 +31,7 @@ status_t handle_lc_ctrl_fi_init(ujson_t *uj) { sca_init(kScaTriggerSourceAes, kScaPeripheralIoDiv4 | kScaPeripheralCsrng); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Configure Ibex to allow reading ERR_STATUS register. TRY(dif_rv_core_ibex_init( @@ -44,11 +44,11 @@ status_t handle_lc_ctrl_fi_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); @@ -56,7 +56,7 @@ status_t handle_lc_ctrl_fi_init(ujson_t *uj) { status_t handle_lc_ctrl_fi_runtime_corruption(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Read LC CTRL to get reference values. dif_lc_ctrl_state_t lc_state_ref; @@ -71,7 +71,7 @@ status_t handle_lc_ctrl_fi_runtime_corruption(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Check if we have managed to manipulate the LC Controller. dif_lc_ctrl_state_t lc_state_cmp; diff --git a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c index aab8efa6b5d61b..6845852d09b8c0 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/otbn_fi.c @@ -17,7 +17,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/otbn_fi_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -129,7 +129,7 @@ status_t clear_otbn_load_checksum(void) { status_t handle_otbn_fi_char_hardware_dmem_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Initialize OTBN app, load it, and get interface to OTBN data memory. OTBN_DECLARE_APP_SYMBOLS(otbn_char_hardware_dmem_op_loop); @@ -148,7 +148,7 @@ status_t handle_otbn_fi_char_hardware_dmem_op_loop(ujson_t *uj) { otbn_busy_wait_for_done(); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read loop counter from OTBN data memory. otbn_dmem_read(1, kOtbnAppCharHardwareDmemOpLoopLC, &loop_counter); @@ -176,7 +176,7 @@ status_t handle_otbn_fi_char_hardware_dmem_op_loop(ujson_t *uj) { status_t handle_otbn_fi_char_hardware_reg_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Initialize OTBN app, load it, and get interface to OTBN data memory. OTBN_DECLARE_APP_SYMBOLS(otbn_char_hardware_reg_op_loop); @@ -195,7 +195,7 @@ status_t handle_otbn_fi_char_hardware_reg_op_loop(ujson_t *uj) { otbn_busy_wait_for_done(); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read loop counter from OTBN data memory. otbn_dmem_read(1, kOtbnAppCharHardwareRegOpLoopLC, &loop_counter); @@ -223,7 +223,7 @@ status_t handle_otbn_fi_char_hardware_reg_op_loop(ujson_t *uj) { status_t handle_otbn_fi_char_unrolled_dmem_op_loop(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Initialize OTBN app, load it, and get interface to OTBN data memory. OTBN_DECLARE_APP_SYMBOLS(otbn_char_unrolled_dmem_op_loop); @@ -242,7 +242,7 @@ status_t handle_otbn_fi_char_unrolled_dmem_op_loop(ujson_t *uj) { otbn_busy_wait_for_done(); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read loop counter from OTBN data memory. otbn_dmem_read(1, kOtbnAppCharUnrolledDmemOpLoopLC, &loop_counter); @@ -270,7 +270,7 @@ 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) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Initialize OTBN app, load it, and get interface to OTBN data memory. OTBN_DECLARE_APP_SYMBOLS(otbn_char_unrolled_reg_op_loop); @@ -289,7 +289,7 @@ status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj) { otbn_busy_wait_for_done(); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read loop counter from OTBN data memory. otbn_dmem_read(1, kOtbnAppCharUnrolledRegOpLoopLC, &loop_counter); @@ -318,7 +318,7 @@ status_t handle_otbn_fi_char_unrolled_reg_op_loop(ujson_t *uj) { 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. - TRY(sca_configure_entropy_source_max_reseed_interval()); + TRY(pentest_configure_entropy_source_max_reseed_interval()); sca_select_trigger_type(kScaTriggerTypeSw); sca_init(kScaTriggerSourceOtbn, @@ -336,10 +336,10 @@ status_t handle_otbn_fi_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // The load integrity & key sideloading tests get initialized at the first // run. @@ -348,7 +348,7 @@ status_t handle_otbn_fi_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); @@ -370,7 +370,7 @@ status_t handle_otbn_fi_init_keymgr(ujson_t *uj) { 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(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); if (!key_sideloading_init) { // Setup keymanager for sideloading key into OTBN. @@ -394,7 +394,7 @@ status_t handle_otbn_fi_key_sideload(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read loop counter from OTBN data memory. uint32_t key_share_0_l, key_share_0_h; @@ -436,7 +436,7 @@ status_t handle_otbn_fi_key_sideload(ujson_t *uj) { 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(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); if (!load_integrity_init) { // Load the OTBN app and read the load checksum without FI to retrieve @@ -454,7 +454,7 @@ status_t handle_otbn_fi_load_integrity(ujson_t *uj) { otbn_load_app(kOtbnAppLoadIntegrity); sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read back checksum. uint32_t load_checksum; diff --git a/sw/device/tests/penetrationtests/firmware/fi/otp_fi.c b/sw/device/tests/penetrationtests/firmware/fi/otp_fi.c index 1c6c78dec47c5c..c56ead785fcc39 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/otp_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/otp_fi.c @@ -12,7 +12,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/otp_fi_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -96,7 +96,7 @@ status_t otp_life_cycle_dump(uint32_t *buffer) { status_t handle_otp_fi_hw_cfg(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Read OTP partition for comparison values TRY(otp_hw_cfg_dump(otp_read32_result_hw_cfg_comp)); @@ -116,7 +116,7 @@ status_t handle_otp_fi_hw_cfg(ujson_t *uj) { TRY(otp_hw_cfg_dump(otp_read32_result_hw_cfg_fi)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Get OTP CTRL status dif_otp_ctrl_status_t status; @@ -150,10 +150,10 @@ status_t handle_otp_fi_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); TRY(dif_otp_ctrl_init( mmio_region_from_addr(TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR), &otp)); @@ -165,7 +165,7 @@ status_t handle_otp_fi_init(ujson_t *uj) { status_t handle_otp_fi_life_cycle(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Read OTP partition for comparison values TRY(otp_life_cycle_dump(otp_read32_result_life_cycle_comp)); @@ -185,7 +185,7 @@ status_t handle_otp_fi_life_cycle(ujson_t *uj) { TRY(otp_life_cycle_dump(otp_read32_result_life_cycle_fi)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Get OTP CTRL status dif_otp_ctrl_status_t status; @@ -210,7 +210,7 @@ status_t handle_otp_fi_life_cycle(ujson_t *uj) { status_t handle_otp_fi_owner_sw_cfg(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Read OTP partition for comparison values TRY(otp_owner_sw_cfg_dump(otp_read32_result_owner_sw_cfg_comp)); @@ -230,7 +230,7 @@ status_t handle_otp_fi_owner_sw_cfg(ujson_t *uj) { TRY(otp_owner_sw_cfg_dump(otp_read32_result_owner_sw_cfg_fi)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Get OTP CTRL status dif_otp_ctrl_status_t status; @@ -255,7 +255,7 @@ status_t handle_otp_fi_owner_sw_cfg(ujson_t *uj) { status_t handle_otp_fi_vendor_test(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Read OTP partition for comparison values TRY(otp_vendor_test_dump(otp_read32_result_vendor_test_comp)); @@ -275,7 +275,7 @@ status_t handle_otp_fi_vendor_test(ujson_t *uj) { TRY(otp_vendor_test_dump(otp_read32_result_vendor_test_fi)); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Get OTP CTRL status dif_otp_ctrl_status_t status; diff --git a/sw/device/tests/penetrationtests/firmware/fi/rng_fi.c b/sw/device/tests/penetrationtests/firmware/fi/rng_fi.c index 0d86b35c41b3e8..d0f41a4427224c 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/rng_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/rng_fi.c @@ -17,7 +17,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/rng_fi_commands.h" #include "edn_regs.h" // Generated @@ -37,7 +37,9 @@ enum { kEdnKatOutputLen = 16, kEdnKatWordsPerBlock = 4, kEntropyFifoBufferSize = 32, + kCsrngBiasFWFifoBufferSize = 12, kMaxReadCountNotBlocking = 32, + kTestParamEntropySrcMaxAttempts = 256, }; static dif_rv_core_ibex_t rv_core_ibex; @@ -49,6 +51,11 @@ static bool disable_health_check; static bool firmware_override_init; +static const uint32_t kInputMsg[kCsrngBiasFWFifoBufferSize] = { + 0xa52a0da9, 0xcae141b2, 0x6d5bab9d, 0x2c3e5cc0, 0x225afc93, 0x5d31a610, + 0x91b7f960, 0x0d566bb3, 0xef35e170, 0x94ba7d8e, 0x534eb741, 0x6b60b0da, +}; + // Seed material for the EDN KAT instantiate command. static const dif_edn_seed_material_t kEdnKatSeedMaterialInstantiate = { .len = kEdnKatMaxClen, @@ -131,9 +138,27 @@ static void entropy_data_flush(dif_entropy_src_t *entropy_src) { } } +/** + * Stops the entropy_src conditioner. + * + * @param entropy_src A entropy source handle. + */ +static void entropy_conditioner_stop(const dif_entropy_src_t *entropy_src) { + uint32_t fail_count = 0; + dif_result_t op_result; + do { + op_result = dif_entropy_src_conditioner_stop(entropy_src); + if (op_result == kDifIpFifoFull) { + CHECK(fail_count++ < kTestParamEntropySrcMaxAttempts); + } else { + CHECK_DIF_OK(op_result); + } + } while (op_result == kDifIpFifoFull); +} + status_t handle_rng_fi_entropy_src_bias(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); TRY(dif_entropy_src_set_enabled(&entropy_src, kDifToggleDisabled)); @@ -168,7 +193,7 @@ status_t handle_rng_fi_entropy_src_bias(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register from Ibex. dif_rv_core_ibex_error_status_t err_ibx; @@ -187,7 +212,7 @@ status_t handle_rng_fi_entropy_src_bias(ujson_t *uj) { status_t handle_rng_fi_firmware_override(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); if (!firmware_override_init) { // Check if we keep heal tests enabled. @@ -226,7 +251,7 @@ status_t handle_rng_fi_firmware_override(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register from Ibex. dif_rv_core_ibex_error_status_t err_ibx; @@ -245,7 +270,7 @@ status_t handle_rng_fi_firmware_override(ujson_t *uj) { status_t handle_rng_fi_edn_bias(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); TRY(dif_entropy_src_init( mmio_region_from_addr(TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR), &entropy_src)); @@ -295,7 +320,7 @@ status_t handle_rng_fi_edn_bias(ujson_t *uj) { } // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register from Ibex. dif_rv_core_ibex_error_status_t err_ibx; @@ -311,7 +336,7 @@ status_t handle_rng_fi_edn_bias(ujson_t *uj) { status_t handle_rng_fi_edn_resp_ack(ujson_t *uj) { // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); // Enable entropy complex, CSRNG and EDN so Ibex can get entropy. // Configure entropy in auto_mode to avoid starving the system from entropy, // given that boot mode entropy has a limited number of generated bits. @@ -346,7 +371,7 @@ status_t handle_rng_fi_edn_resp_ack(ujson_t *uj) { } // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register from Ibex. dif_rv_core_ibex_error_status_t err_ibx; @@ -368,7 +393,7 @@ status_t handle_rng_fi_edn_init(ujson_t *uj) { kScaPeripheralCsrng | kScaPeripheralEdn); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Configure Ibex to allow reading ERR_STATUS register. TRY(dif_rv_core_ibex_init( @@ -377,7 +402,7 @@ status_t handle_rng_fi_edn_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Initialize peripherals used in this FI test. TRY(dif_entropy_src_init( @@ -389,7 +414,7 @@ status_t handle_rng_fi_edn_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); firmware_override_init = false; @@ -402,7 +427,7 @@ status_t handle_rng_fi_csrng_bias(ujson_t *uj) { crypto_fi_csrng_mode_t uj_data; TRY(ujson_deserialize_crypto_fi_csrng_mode_t(uj, &uj_data)); // Clear registered alerts in alert handler. - sca_registered_alerts_t reg_alerts = sca_get_triggered_alerts(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); TRY(csrng_testutils_cmd_ready_wait(&csrng)); TRY(dif_csrng_uninstantiate(&csrng)); @@ -449,7 +474,7 @@ status_t handle_rng_fi_csrng_bias(ujson_t *uj) { } // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register from Ibex. dif_rv_core_ibex_error_status_t err_ibx; @@ -478,6 +503,82 @@ status_t handle_rng_fi_csrng_bias(ujson_t *uj) { return OK_STATUS(); } +status_t handle_rng_fi_csrng_bias_fw_override(ujson_t *uj, bool static_seed) { + // Clear registered alerts in alert handler. + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); + + uint32_t received_data[kCsrngBiasFWFifoBufferSize]; + const dif_csrng_seed_material_t kEmptySeedMaterial = {0}; + + uint32_t seed[kCsrngBiasFWFifoBufferSize]; + + if (static_seed) { + memcpy(seed, kInputMsg, sizeof(kInputMsg)); + } else { + rng_fi_seed_t uj_data; + TRY(ujson_deserialize_rng_fi_seed_t(uj, &uj_data)); + memcpy(seed, uj_data.seed, sizeof(uj_data.seed)); + } + + CHECK_STATUS_OK(entropy_testutils_stop_all()); + CHECK_STATUS_OK(entropy_testutils_fw_override_enable( + &entropy_src, kCsrngBiasFWFifoBufferSize, + /*route_to_firmware=*/false, + /*bypass_conditioner=*/false)); + + entropy_data_flush(&entropy_src); + + CHECK_DIF_OK(dif_csrng_configure(&csrng)); + + CHECK_DIF_OK(dif_entropy_src_conditioner_start(&entropy_src)); + + uint32_t fail_count = 0; + uint32_t total = 0; + do { + uint32_t count; + dif_result_t op_result = dif_entropy_src_fw_ov_data_write( + &entropy_src, seed + total, ARRAYSIZE(seed) - total, &count); + total += count; + if (op_result == kDifIpFifoFull) { + CHECK(fail_count++ < kTestParamEntropySrcMaxAttempts); + } else { + fail_count = 0; + CHECK_DIF_OK(op_result); + } + } while (total < ARRAYSIZE(seed)); + + sca_set_trigger_high(); + entropy_conditioner_stop(&entropy_src); + + TRY(csrng_testutils_cmd_ready_wait(&csrng)); + CHECK_DIF_OK(dif_csrng_instantiate(&csrng, kDifCsrngEntropySrcToggleEnable, + &kEmptySeedMaterial)); + + CHECK_STATUS_OK(csrng_testutils_cmd_generate_run(&csrng, received_data, + ARRAYSIZE(received_data))); + + asm volatile(NOP30); + sca_set_trigger_low(); + + // Get registered alerts from alert handler. + reg_alerts = pentest_get_triggered_alerts(); + + // 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)); + + rng_fi_csrng_ov_output_t uj_output; + + // Send result & ERR_STATUS to host. + uj_output.res = 0; // No result is returned. + memcpy(uj_output.rand, received_data, sizeof(received_data)); + uj_output.err_status = err_ibx; + memcpy(uj_output.alerts, reg_alerts.alerts, sizeof(reg_alerts.alerts)); + RESP_OK(ujson_serialize_rng_fi_csrng_ov_output_t, uj, &uj_output); + + return OK_STATUS(); +} + status_t handle_rng_fi_csrng_init(ujson_t *uj) { sca_select_trigger_type(kScaTriggerTypeSw); // As we are using the software defined trigger, the first argument of @@ -485,7 +586,7 @@ status_t handle_rng_fi_csrng_init(ujson_t *uj) { sca_init(kScaTriggerSourceAes, kScaPeripheralIoDiv4 | kScaPeripheralCsrng); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Configure Ibex to allow reading ERR_STATUS register. TRY(dif_rv_core_ibex_init( @@ -494,7 +595,7 @@ status_t handle_rng_fi_csrng_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Initialize CSRNG. mmio_region_t base_addr = mmio_region_from_addr(TOP_EARLGREY_CSRNG_BASE_ADDR); @@ -503,7 +604,7 @@ status_t handle_rng_fi_csrng_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); @@ -517,6 +618,10 @@ status_t handle_rng_fi(ujson_t *uj) { return handle_rng_fi_csrng_init(uj); case kRngFiSubcommandCsrngBias: return handle_rng_fi_csrng_bias(uj); + case kRngFiSubcommandCsrngBiasFWOverride: + return handle_rng_fi_csrng_bias_fw_override(uj, false); + case kRngFiSubcommandCsrngBiasFWOverrideStatic: + return handle_rng_fi_csrng_bias_fw_override(uj, true); case kRngFiSubcommandEdnInit: return handle_rng_fi_edn_init(uj); case kRngFiSubcommandEdnRespAck: diff --git a/sw/device/tests/penetrationtests/firmware/fi/rng_fi.h b/sw/device/tests/penetrationtests/firmware/fi/rng_fi.h index 244e6b782b81ad..66d936123cd564 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/rng_fi.h +++ b/sw/device/tests/penetrationtests/firmware/fi/rng_fi.h @@ -79,6 +79,21 @@ status_t handle_rng_fi_edn_init(ujson_t *uj); */ status_t handle_rng_fi_csrng_bias(ujson_t *uj); +/** + * rng_fi_entropy_src_bias_fw_override command handler. + * + * Write a fixed seed into the FW_OV_WR_DATA register in the FW override mode. + * This seed goes through the conditioner into the CSRNG. The software interface + * of the CSRNG is used to extract the random data. + * + * Faults are injected during the trigger_high & trigger_low. + * + * @param uj An initialized uJSON context. + * @param static_seed Use static seed or seed provided by user. + * @return OK or error. + */ +status_t handle_rng_fi_csrng_bias_fw_override(ujson_t *uj, bool static_seed); + /** * Initializes the trigger and configures the device for the CSRNG FI test. * diff --git a/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c index a347e3bbe0673a..edf285a0e25ec3 100644 --- a/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c +++ b/sw/device/tests/penetrationtests/firmware/fi/rom_fi.c @@ -14,7 +14,7 @@ #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/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/rom_fi_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -31,7 +31,7 @@ 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(); + sca_registered_alerts_t reg_alerts = pentest_get_triggered_alerts(); dif_rom_ctrl_digest_t expected_digest; dif_rom_ctrl_digest_t fi_digest[8]; @@ -51,7 +51,7 @@ status_t handle_rom_read(ujson_t *uj) { sca_set_trigger_low(); // Get registered alerts from alert handler. - reg_alerts = sca_get_triggered_alerts(); + reg_alerts = pentest_get_triggered_alerts(); // Read ERR_STATUS register. dif_rv_core_ibex_error_status_t codes; @@ -83,10 +83,10 @@ status_t handle_rom_fi_init(ujson_t *uj) { // Configure the alert handler. Alerts triggered by IP blocks are captured // and reported to the test. - sca_configure_alert_handler(); + pentest_configure_alert_handler(); // Disable the instruction cache and dummy instructions for FI attacks. - sca_configure_cpu(); + pentest_configure_cpu(); // Initialize rom_ctrl. mmio_region_t rom_ctrl_reg = @@ -100,7 +100,7 @@ status_t handle_rom_fi_init(ujson_t *uj) { // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); diff --git a/sw/device/tests/penetrationtests/firmware/firmware.c b/sw/device/tests/penetrationtests/firmware/firmware.c index d2dce947172d24..314019392332de 100644 --- a/sw/device/tests/penetrationtests/firmware/firmware.c +++ b/sw/device/tests/penetrationtests/firmware/firmware.c @@ -14,6 +14,7 @@ #include "sw/device/tests/penetrationtests/json/aes_sca_commands.h" #include "sw/device/tests/penetrationtests/json/commands.h" #include "sw/device/tests/penetrationtests/json/crypto_fi_commands.h" +#include "sw/device/tests/penetrationtests/json/edn_sca_commands.h" #include "sw/device/tests/penetrationtests/json/extclk_sca_fi_commands.h" #include "sw/device/tests/penetrationtests/json/hmac_sca_commands.h" #include "sw/device/tests/penetrationtests/json/ibex_fi_commands.h" @@ -21,6 +22,7 @@ #include "sw/device/tests/penetrationtests/json/kmac_sca_commands.h" #include "sw/device/tests/penetrationtests/json/lc_ctrl_fi_commands.h" #include "sw/device/tests/penetrationtests/json/otbn_fi_commands.h" +#include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h" #include "sw/device/tests/penetrationtests/json/otp_fi_commands.h" #include "sw/device/tests/penetrationtests/json/prng_sca_commands.h" #include "sw/device/tests/penetrationtests/json/rng_fi_commands.h" @@ -38,9 +40,11 @@ #include "fi/rom_fi.h" #include "lib/extclk_sca_fi.h" #include "sca/aes_sca.h" +#include "sca/edn_sca.h" #include "sca/hmac_sca.h" #include "sca/ibex_sca.h" #include "sca/kmac_sca.h" +#include "sca/otbn_sca.h" #include "sca/prng_sca.h" #include "sca/sha3_sca.h" #include "sca/trigger_sca.h" @@ -58,6 +62,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandCryptoFi: RESP_ERR(uj, handle_crypto_fi(uj)); break; + case kPenetrationtestCommandEdnSca: + RESP_ERR(uj, handle_edn_sca(uj)); + break; case kPenetrationtestCommandExtClkScaFi: RESP_ERR(uj, handle_extclk_sca_fi(uj)); break; @@ -82,6 +89,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandOtpFi: RESP_ERR(uj, handle_otp_fi(uj)); break; + case kPenetrationtestCommandOtbnSca: + RESP_ERR(uj, handle_otbn_sca(uj)); + break; case kPenetrationtestCommandPrngSca: RESP_ERR(uj, handle_prng_sca(uj)); break; diff --git a/sw/device/tests/penetrationtests/firmware/firmware_sca.c b/sw/device/tests/penetrationtests/firmware/firmware_sca.c index f81237718ba7eb..7b6ea19e68280a 100644 --- a/sw/device/tests/penetrationtests/firmware/firmware_sca.c +++ b/sw/device/tests/penetrationtests/firmware/firmware_sca.c @@ -13,9 +13,11 @@ // Include commands #include "sw/device/tests/penetrationtests/json/aes_sca_commands.h" #include "sw/device/tests/penetrationtests/json/commands.h" +#include "sw/device/tests/penetrationtests/json/edn_sca_commands.h" #include "sw/device/tests/penetrationtests/json/hmac_sca_commands.h" #include "sw/device/tests/penetrationtests/json/ibex_sca_commands.h" #include "sw/device/tests/penetrationtests/json/kmac_sca_commands.h" +#include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h" #include "sw/device/tests/penetrationtests/json/prng_sca_commands.h" #include "sw/device/tests/penetrationtests/json/sha3_sca_commands.h" #include "sw/device/tests/penetrationtests/json/trigger_sca_commands.h" @@ -23,9 +25,11 @@ // Include handlers #include "lib/extclk_sca_fi.h" #include "sca/aes_sca.h" +#include "sca/edn_sca.h" #include "sca/hmac_sca.h" #include "sca/ibex_sca.h" #include "sca/kmac_sca.h" +#include "sca/otbn_sca.h" #include "sca/prng_sca.h" #include "sca/sha3_sca.h" #include "sca/trigger_sca.h" @@ -40,6 +44,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandAesSca: RESP_ERR(uj, handle_aes_sca(uj)); break; + case kPenetrationtestCommandEdnSca: + RESP_ERR(uj, handle_edn_sca(uj)); + break; case kPenetrationtestCommandExtClkScaFi: RESP_ERR(uj, handle_extclk_sca_fi(uj)); break; @@ -52,6 +59,9 @@ status_t process_cmd(ujson_t *uj) { case kPenetrationtestCommandKmacSca: RESP_ERR(uj, handle_kmac_sca(uj)); break; + case kPenetrationtestCommandOtbnSca: + RESP_ERR(uj, handle_otbn_sca(uj)); + break; case kPenetrationtestCommandPrngSca: RESP_ERR(uj, handle_prng_sca(uj)); break; diff --git a/sw/device/tests/penetrationtests/firmware/lib/BUILD b/sw/device/tests/penetrationtests/firmware/lib/BUILD index 4178957a755aa5..c7b8f2f591e89e 100644 --- a/sw/device/tests/penetrationtests/firmware/lib/BUILD +++ b/sw/device/tests/penetrationtests/firmware/lib/BUILD @@ -21,13 +21,15 @@ cc_library( ) cc_library( - name = "sca_lib", - srcs = ["sca_lib.c"], - hdrs = ["sca_lib.h"], + name = "pentest_lib", + srcs = ["pentest_lib.c"], + hdrs = ["pentest_lib.h"], deps = [ "//sw/device/lib/base:csr", "//sw/device/lib/base:mmio", + "//sw/device/lib/crypto/drivers:otbn", "//sw/device/lib/dif:alert_handler", + "//sw/device/lib/dif:clkmgr", "//sw/device/lib/dif:csrng", "//sw/device/lib/dif:csrng_shared", "//sw/device/lib/dif:edn", @@ -36,12 +38,14 @@ cc_library( "//sw/device/lib/dif:rstmgr", "//sw/device/lib/dif:rv_core_ibex", "//sw/device/lib/dif:rv_plic", + "//sw/device/lib/dif:rv_timer", "//sw/device/lib/testing:alert_handler_testutils", "//sw/device/lib/testing:entropy_testutils", "//sw/device/lib/testing:rv_plic_testutils", "//sw/device/lib/testing/test_framework:ottf_main", "//sw/device/lib/testing/test_framework:ujson_ottf", "//sw/device/lib/ujson", - "//sw/device/tests/penetrationtests/json:sca_lib_commands", + "//sw/device/sca/lib:sca", + "//sw/device/tests/penetrationtests/json:pentest_lib_commands", ], ) diff --git a/sw/device/tests/penetrationtests/firmware/lib/sca_lib.c b/sw/device/tests/penetrationtests/firmware/lib/pentest_lib.c similarity index 80% rename from sw/device/tests/penetrationtests/firmware/lib/sca_lib.c rename to sw/device/tests/penetrationtests/firmware/lib/pentest_lib.c index f52ade31bbf1a5..2b1960493ba642 100644 --- a/sw/device/tests/penetrationtests/firmware/lib/sca_lib.c +++ b/sw/device/tests/penetrationtests/firmware/lib/pentest_lib.c @@ -2,12 +2,14 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/lib/base/csr.h" #include "sw/device/lib/base/mmio.h" #include "sw/device/lib/base/status.h" +#include "sw/device/lib/crypto/drivers/otbn.h" #include "sw/device/lib/dif/dif_alert_handler.h" +#include "sw/device/lib/dif/dif_clkmgr.h" #include "sw/device/lib/dif/dif_csrng.h" #include "sw/device/lib/dif/dif_csrng_shared.h" #include "sw/device/lib/dif/dif_edn.h" @@ -16,20 +18,29 @@ #include "sw/device/lib/dif/dif_rstmgr.h" #include "sw/device/lib/dif/dif_rv_core_ibex.h" #include "sw/device/lib/dif/dif_rv_plic.h" +#include "sw/device/lib/dif/dif_rv_timer.h" #include "sw/device/lib/runtime/irq.h" #include "sw/device/lib/testing/alert_handler_testutils.h" #include "sw/device/lib/testing/entropy_testutils.h" #include "sw/device/lib/testing/rv_plic_testutils.h" #include "sw/device/lib/testing/test_framework/ottf_main.h" +#include "sw/device/sca/lib/sca.h" +#include "clkmgr_regs.h" // Generated #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" static dif_rv_plic_t plic; static dif_rstmgr_t rstmgr; static dif_alert_handler_t alert_handler; static dif_lc_ctrl_t lc; +static dif_rv_timer_t timer; -status_t sca_configure_entropy_source_max_reseed_interval(void) { +enum { + kRvTimerComparator = 0, + kRvTimerHart = kTopEarlgreyPlicTargetIbex0, +}; + +status_t pentest_configure_entropy_source_max_reseed_interval(void) { const dif_entropy_src_t entropy_src = { .base_addr = mmio_region_from_addr(TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR)}; const dif_csrng_t csrng = { @@ -135,7 +146,7 @@ status_t sca_configure_entropy_source_max_reseed_interval(void) { return OK_STATUS(); } -sca_registered_alerts_t sca_get_triggered_alerts(void) { +sca_registered_alerts_t pentest_get_triggered_alerts(void) { bool is_cause; sca_registered_alerts_t registered; @@ -164,7 +175,7 @@ sca_registered_alerts_t sca_get_triggered_alerts(void) { return registered; } -void sca_configure_alert_handler(void) { +void pentest_configure_alert_handler(void) { irq_global_ctrl(true); irq_external_ctrl(true); @@ -221,7 +232,7 @@ void sca_configure_alert_handler(void) { &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled)); } -status_t sca_read_device_id(uint32_t device_id[]) { +status_t pentest_read_device_id(uint32_t device_id[]) { mmio_region_t lc_reg = mmio_region_from_addr(TOP_EARLGREY_LC_CTRL_BASE_ADDR); CHECK_DIF_OK(dif_lc_ctrl_init(lc_reg, &lc)); @@ -232,7 +243,7 @@ status_t sca_read_device_id(uint32_t device_id[]) { return OK_STATUS(); } -void sca_configure_cpu(void) { +void pentest_configure_cpu(void) { uint32_t cpuctrl_csr; // Get current config. CSR_READ(CSR_REG_CPUCTRL, &cpuctrl_csr); @@ -245,3 +256,44 @@ void sca_configure_cpu(void) { // Write back config. CSR_WRITE(CSR_REG_CPUCTRL, cpuctrl_csr); } + +void pentest_call_and_sleep(sca_callee callee, uint32_t sleep_cycles, + bool sw_trigger, bool otbn) { + // Disable the IO_DIV4_PERI clock to reduce noise during the actual capture. + // This also disables the UART(s) and GPIO modules required for + // communication with the scope. Therefore, it has to be re-enabled after + // the capture. + dif_clkmgr_t clkmgr; + OT_DISCARD(dif_clkmgr_init( + mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr)); + + // Start timer to wake Ibex after the callee is done. + uint64_t current_time; + // Return values of below functions are ignored to improve capture + // performance. + OT_DISCARD(dif_rv_timer_counter_read(&timer, kRvTimerHart, ¤t_time)); + OT_DISCARD(dif_rv_timer_arm(&timer, kRvTimerHart, kRvTimerComparator, + current_time + sleep_cycles)); + OT_DISCARD(dif_rv_timer_counter_set_enabled(&timer, kRvTimerHart, + kDifToggleEnabled)); + + if (sw_trigger) { + sca_set_trigger_high(); + } + + callee(); + + wait_for_interrupt(); + + if (otbn) { + otbn_busy_wait_for_done(); + } + + if (sw_trigger) { + sca_set_trigger_low(); + } + + // Re-enable IO_DIV4_PERI clock to resume communication with the scope. + OT_DISCARD(dif_clkmgr_gateable_clock_set_enabled( + &clkmgr, CLKMGR_CLK_ENABLES_CLK_IO_DIV4_PERI_EN_BIT, kDifToggleEnabled)); +} diff --git a/sw/device/tests/penetrationtests/firmware/lib/sca_lib.h b/sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h similarity index 57% rename from sw/device/tests/penetrationtests/firmware/lib/sca_lib.h rename to sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h index a8c80a3beefdfc..f8e4fbe7c0104d 100644 --- a/sw/device/tests/penetrationtests/firmware/lib/sca_lib.h +++ b/sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h @@ -2,11 +2,11 @@ // 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_LIB_SCA_LIB_H_ -#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_SCA_LIB_H_ +#ifndef OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_ #include "sw/device/lib/ujson/ujson.h" -#include "sw/device/tests/penetrationtests/json/sca_lib_commands.h" +#include "sw/device/tests/penetrationtests/json/pentest_lib_commands.h" typedef struct sca_registered_alerts { uint32_t alerts[3]; @@ -22,7 +22,7 @@ typedef struct sca_registered_alerts { * * @return OK or error. */ -status_t sca_configure_entropy_source_max_reseed_interval(void); +status_t pentest_configure_entropy_source_max_reseed_interval(void); /** * Returns the registered alerts. @@ -33,14 +33,14 @@ status_t sca_configure_entropy_source_max_reseed_interval(void); * @return A struct containing which of the alerts were triggered during the * test. */ -sca_registered_alerts_t sca_get_triggered_alerts(void); +sca_registered_alerts_t pentest_get_triggered_alerts(void); /** * Configures the alert handler for FI. * * Register all alerts and let them escalate to Phase0 only. */ -void sca_configure_alert_handler(void); +void pentest_configure_alert_handler(void); /** * Reads the device ID from the LC. @@ -50,7 +50,7 @@ void sca_configure_alert_handler(void); * @param device_id A buffer available to store the device id. * @return OK or error. */ -status_t sca_read_device_id(uint32_t device_id[]); +status_t pentest_read_device_id(uint32_t device_id[]); /** * Configures CPU for SCA and FI penetration tests. @@ -58,6 +58,28 @@ status_t sca_read_device_id(uint32_t device_id[]); * This function disables the iCache and the dummy instructions using the * CPU Control and Status Register (cpuctrlsts). */ -void sca_configure_cpu(void); +void pentest_configure_cpu(void); -#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_SCA_LIB_H_ +/** + * Functions called by `pentest_call_and_sleep()` must conform to this + * prototype. + */ +typedef void (*sca_callee)(void); + +/** + * Calls the given function and puts Ibex to sleep. + * + * This function can be used to minimize noise while capturing power traces for + * side-channel attacks, in which case `callee` would trigger the operation of + * interest, typically a crypto operation, on the target device. + * + * @param callee Function to call before putting Ibex to sleep. + * @param sleep_cycles Number of cycles to sleep. + * @param sw_trigger Raise trigger before calling the target function. + * @param otbn Wait until OTBN execution has finished. Not supported in + * ENGLISH_BREAKFAST. + */ +void pentest_call_and_sleep(sca_callee callee, uint32_t sleep_cycles, + bool sw_trigger, bool otbn); + +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_LIB_PENTEST_LIB_H_ diff --git a/sw/device/tests/penetrationtests/firmware/sca/BUILD b/sw/device/tests/penetrationtests/firmware/sca/BUILD index 825dd9ad58efa1..a6b99be3fd7450 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/BUILD +++ b/sw/device/tests/penetrationtests/firmware/sca/BUILD @@ -19,11 +19,57 @@ cc_library( "//sw/device/sca/lib:aes", "//sw/device/sca/lib:prng", "//sw/device/sca/lib:sca", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:aes_sca_commands", ], ) +cc_library( + name = "ecc256_keygen_sca", + srcs = ["ecc256_keygen_sca.c"], + hdrs = ["ecc256_keygen_sca.h"], + deps = [ + "//hw/top_earlgrey/sw/autogen:top_earlgrey", + "//sw/device/lib/base:abs_mmio", + "//sw/device/lib/base:memory", + "//sw/device/lib/crypto/drivers:otbn", + "//sw/device/lib/runtime:ibex", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing/test_framework:ottf_main", + "//sw/device/lib/testing/test_framework:ujson_ottf", + "//sw/device/lib/ujson", + "//sw/device/sca/lib:prng", + "//sw/device/sca/lib:sca", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", + "//sw/device/tests/penetrationtests/json:otbn_sca_commands", + "//sw/otbn/crypto:p256_key_from_seed_sca", + ], +) + +cc_library( + name = "edn_sca", + srcs = ["edn_sca.c"], + hdrs = ["edn_sca.h"], + deps = [ + "//sw/device/lib/base:memory", + "//sw/device/lib/base:status", + "//sw/device/lib/dif:csrng", + "//sw/device/lib/dif:csrng_shared", + "//sw/device/lib/dif:edn", + "//sw/device/lib/dif:entropy_src", + "//sw/device/lib/dif:rv_core_ibex", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing:entropy_testutils", + "//sw/device/lib/testing:rv_core_ibex_testutils", + "//sw/device/lib/testing/test_framework:ujson_ottf", + "//sw/device/lib/ujson", + "//sw/device/sca/lib:prng", + "//sw/device/sca/lib:sca", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", + "//sw/device/tests/penetrationtests/json:edn_sca_commands", + ], +) + cc_library( name = "extclk_sca_fi", srcs = ["extclk_sca_fi.c"], @@ -57,7 +103,7 @@ cc_library( "//sw/device/lib/ujson", "//sw/device/sca/lib:prng", "//sw/device/sca/lib:sca", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:hmac_sca_commands", ], ) @@ -77,7 +123,7 @@ cc_library( "//sw/device/lib/ujson", "//sw/device/sca/lib:prng", "//sw/device/sca/lib:sca", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:ibex_sca_commands", ], ) @@ -95,11 +141,35 @@ cc_library( "//sw/device/lib/ujson", "//sw/device/sca/lib:prng", "//sw/device/sca/lib:sca", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:kmac_sca_commands", ], ) +cc_library( + name = "otbn_sca", + srcs = ["otbn_sca.c"], + hdrs = ["otbn_sca.h"], + deps = [ + ":ecc256_keygen_sca", + "//sw/device/lib/base:memory", + "//sw/device/lib/base:status", + "//sw/device/lib/crypto/drivers:keymgr", + "//sw/device/lib/crypto/impl:keyblob", + "//sw/device/lib/crypto/impl:status", + "//sw/device/lib/dif:otbn", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing:keymgr_testutils", + "//sw/device/lib/testing/test_framework:ujson_ottf", + "//sw/device/lib/ujson", + "//sw/device/sca/lib:prng", + "//sw/device/sca/lib:sca", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", + "//sw/device/tests/penetrationtests/firmware/sca/otbn:otbn_key_sideload_sca", + "//sw/device/tests/penetrationtests/json:otbn_sca_commands", + ], +) + cc_library( name = "prng_sca", srcs = ["prng_sca.c"], @@ -128,7 +198,7 @@ cc_library( "//sw/device/lib/ujson", "//sw/device/sca/lib:prng", "//sw/device/sca/lib:sca", - "//sw/device/tests/penetrationtests/firmware/lib:sca_lib", + "//sw/device/tests/penetrationtests/firmware/lib:pentest_lib", "//sw/device/tests/penetrationtests/json:sha3_sca_commands", ], ) diff --git a/sw/device/tests/penetrationtests/firmware/sca/aes_sca.c b/sw/device/tests/penetrationtests/firmware/sca/aes_sca.c index 5238ff0527b150..524198f3a89339 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/aes_sca.c +++ b/sw/device/tests/penetrationtests/firmware/sca/aes_sca.c @@ -14,7 +14,7 @@ #include "sw/device/sca/lib/aes.h" #include "sw/device/sca/lib/prng.h" #include "sw/device/sca/lib/sca.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/aes_sca_commands.h" #if !OT_IS_ENGLISH_BREAKFAST @@ -192,38 +192,12 @@ static void aes_manual_trigger(void) { (void)dif_aes_trigger(&aes, kDifAesTriggerStart); } -/** - * Key set command handler. - * - * This command is designed to set the fixed_key variable and in addition also - * configures the key into the AES peripheral. - * - * The key must be `kAesKeyLength` bytes long. - * - * The uJSON data contains: - * - key: The key to use. - * - key_length: The length of the key. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_key_set(ujson_t *uj) { - cryptotest_aes_sca_key_t uj_key_data; - TRY(ujson_deserialize_cryptotest_aes_sca_key_t(uj, &uj_key_data)); - - memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length); - block_ctr = 0; - if (aes_key_mask_and_config(key_fixed, uj_key_data.key_length) != aesScaOk) { - return ABORTED(); - } - return OK_STATUS(); -} - /** * Encrypts a plaintext using the AES peripheral. * - * This function uses `sca_call_and_sleep()` from the sca library to put Ibex - * to sleep in order to minimize noise during captures. The plaintext must be - * `kAesTextLength` bytes long. + * This function uses `pentest_call_and_sleep()` from the pentest library to put + * Ibex to sleep in order to minimize noise during captures. The plaintext must + * be `kAesTextLength` bytes long. * * @param plaintext Plaintext. * @param plaintext_len Length of the plaintext. @@ -249,12 +223,14 @@ static aes_sca_error_t aes_encrypt(const uint8_t *plaintext, // Start AES operation (this triggers the capture) and go to sleep. if (fpga_mode) { // On the FPGA, the AES block automatically sets and unsets the trigger. - sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, false); + pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, false, + false); } else { // On the chip, we need to manually set and unset the trigger. This is done // in this function to have the trigger as close as possible to the AES // operation. - sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, true); + pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, true, + false); } return aesScaOk; } @@ -276,7 +252,7 @@ static status_t aes_send_ciphertext(bool only_first_word, ujson_t *uj) { return OUT_OF_RANGE(); } - cryptotest_aes_sca_ciphertext_t uj_output; + aes_sca_ciphertext_t uj_output; memset(uj_output.ciphertext, 0, AESSCA_CMD_MAX_DATA_BYTES); uj_output.ciphertext_length = kAesTextLength; if (only_first_word) { @@ -284,52 +260,7 @@ static status_t aes_send_ciphertext(bool only_first_word, ujson_t *uj) { } memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data, uj_output.ciphertext_length); - RESP_OK(ujson_serialize_cryptotest_aes_sca_ciphertext_t, uj, &uj_output); - return OK_STATUS(); -} - -/** - * Single encrypt command handler. - * - * Encrypts a `kAesTextLength` bytes long plaintext using the AES peripheral and - * sends the ciphertext over UART. This function also handles the trigger - * signal. - * - * The uJSON data contains: - * - text: The plaintext. - * - text_length: The length of the plaintext. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_single_encrypt(ujson_t *uj) { - cryptotest_aes_sca_text_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_text_t(uj, &uj_data)); - if (uj_data.text_length != kAesTextLength) { - return OUT_OF_RANGE(); - } - - block_ctr++; - // Rewrite the key to reset the internal block counter. Otherwise, the AES - // peripheral might trigger the reseeding of the internal masking PRNG which - // disturbs SCA measurements. - if (block_ctr > kBlockCtrMax) { - if (aes_key_mask_and_config(key_fixed, kAesKeyLength) != aesScaOk) { - return ABORTED(); - } - block_ctr = 1; - } - - if (fpga_mode) { - sca_set_trigger_high(); - } - if (aes_encrypt(uj_data.text, uj_data.text_length) != aesScaOk) { - return ABORTED(); - } - if (fpga_mode) { - sca_set_trigger_low(); - } - - TRY(aes_send_ciphertext(false, uj)); + RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output); return OK_STATUS(); } @@ -369,93 +300,58 @@ static void aes_serial_advance_random_data(void) { } /** - * Batch encrypt command handler. + * Fixed vs random key batch generate command handler. * - * This command is designed to maximize the capture rate for side-channel - * attacks. Instead of expecting a plaintext and sending the resulting - * ciphertext from and to the host for each encryption, this command repeatedly - * encrypts random plaintexts that are generated on the device. This minimizes - * the overhead of UART communication and significantly improves the capture - * rate. The host must use the same PRNG to be able to compute the plaintext and - * the ciphertext of each trace. + * This command generates random plaintexts and fixed or random keys using PRNG + * for AES fixed vs random key batch capture in order to remove fake leakage. + * Fixed or random key sequence is also determined here by using the lsb bit of + * the plaintext. In order to simplify the analysis, the first encryption has to + * use fixed key. The data collection method is based on the derived test + * requirements (DTR) for TVLA: + * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf + * The measurements are taken by using either fixed or randomly selected keys. + * In addition, a PRNG is used for random key and plaintext generation instead + * of AES algorithm as specified in the TVLA DTR. * * Packet payload must be a `uint32_t` representation of the number of - * encryptions to perform. Since generated plaintexts are not cached, there is - * no limit on the number of encryptions. - * - * The PRNG should be initialized using the seed PRNG command before - * starting batch encryption. In addition, the key should also be set - * using key set command before starting batch captures. + * encryptions to perform. Number of operations of a batch should not be greater + * than the 'kNumBatchOpsMax' value. * - * Note that the host can partially verify this operation by checking the - * contents of UART reponse that is sent at the end. + * The PRNG should be initialized using the 's' (seed PRNG) command before + * starting batch captures. In addition, the fixed key should also be set + * using 't' (fvsr key set) command before starting batch captures. * * The uJSON data contains: * - data: The number of encryptions. * * @param uj The received uJSON data. */ -status_t handle_aes_sca_batch_encrypt(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); +static status_t aes_sca_fvsr_key_batch_generate(aes_sca_data_t uj_data) { uint32_t num_encryptions = 0; num_encryptions = read_32(uj_data.data); - - block_ctr += num_encryptions; - // Rewrite the key to reset the internal block counter. Otherwise, the AES - // peripheral might trigger the reseeding of the internal masking PRNG which - // disturbs SCA measurements. - if (block_ctr > kBlockCtrMax) { - if (aes_key_mask_and_config(key_fixed, kAesKeyLength) != aesScaOk) { - return ABORTED(); - } - block_ctr = num_encryptions; + if (num_encryptions > kNumBatchOpsMax) { + return OUT_OF_RANGE(); } - if (fpga_mode) { - sca_set_trigger_high(); - } for (uint32_t i = 0; i < num_encryptions; ++i) { - if (aes_encrypt(plaintext_random, kAesTextLength) != aesScaOk) { - return ABORTED(); + if (sample_fixed) { + memcpy(batch_keys[i], key_fixed, kAesKeyLength); + memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength); + aes_serial_advance_fixed(); + } else { + memcpy(batch_keys[i], key_random, kAesKeyLength); + memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength); + aes_serial_advance_random(); } - aes_serial_advance_random(); - } - if (fpga_mode) { - sca_set_trigger_low(); + sample_fixed = batch_plaintexts[i][0] & 0x1; } - TRY(aes_send_ciphertext(true, uj)); - return OK_STATUS(); } -/** - * Simple serial 'a' (alternative batch encrypt) command handler. - * - * This command is designed to maximize the capture rate for side-channel - * attacks. It uses the first supplied plaintext and repeats AES encryptions - * by using every ciphertext as next plaintext with a constant key. This - * minimizes the overhead of UART communication and significantly improves the - * capture rate. - - * Packet payload must be a `uint32_t` representation of the number of - * encryptions to perform. Since generated plaintexts are not cached, there is - * no limit on the number of encryptions. - * - * The key should also be set using 'k' (key set) command. - * - * The host can verify the operation by checking the last 'r' (ciphertext) - * packet that is sent at the end. - * - * The uJSON data contains: - * - data: The number of encryptions. - * - * @param uj The received uJSON data. - */ status_t handle_aes_sca_batch_alternative_encrypt(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); // Get num_encryptions from input uint32_t num_encryptions = 0; @@ -504,226 +400,101 @@ status_t handle_aes_sca_batch_alternative_encrypt(ujson_t *uj) { } // send last ciphertext - cryptotest_aes_sca_ciphertext_t uj_output; + aes_sca_ciphertext_t uj_output; memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data, kAesTextLength); - RESP_OK(ujson_serialize_cryptotest_aes_sca_ciphertext_t, uj, &uj_output); - - return OK_STATUS(); -} - -/** - * Batch plaintext command handler. - * - * This command is designed to set the initial plaintext for - * aes_serial_batch_alternative_encrypt. - * - * The plaintext must be `kAesTextLength` bytes long. - * - * * The uJSON data contains: - * - text: The plaintext. - * - text_length: Plaintext length. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_batch_plaintext_set(ujson_t *uj) { - cryptotest_aes_sca_text_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_text_t(uj, &uj_data)); - - if (uj_data.text_length != kAesTextLength) { - return OUT_OF_RANGE(); - } - memcpy(batch_plaintext, uj_data.text, uj_data.text_length); + RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output); return OK_STATUS(); } -/** - * Fvsr key set command handler. - * - * This command is designed to set the fixed key which is used for fvsr key TVLA - * captures. - * - * The key must be `kAesKeyLength` bytes long. - * - * The uJSON data contains: - * - key: The key to use. - * - key_length: The length of the key. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_fvsr_key_set(ujson_t *uj) { - cryptotest_aes_sca_key_t uj_key_data; - TRY(ujson_deserialize_cryptotest_aes_sca_key_t(uj, &uj_key_data)); - - if (uj_key_data.key_length != kAesKeyLength) { - return OUT_OF_RANGE(); - } - memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length); - return OK_STATUS(); -} - -/** - * Fixed vs random key batch generate command handler. - * - * This command generates random plaintexts and fixed or random keys using PRNG - * for AES fixed vs random key batch capture in order to remove fake leakage. - * Fixed or random key sequence is also determined here by using the lsb bit of - * the plaintext. In order to simplify the analysis, the first encryption has to - * use fixed key. The data collection method is based on the derived test - * requirements (DTR) for TVLA: - * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf - * The measurements are taken by using either fixed or randomly selected keys. - * In addition, a PRNG is used for random key and plaintext generation instead - * of AES algorithm as specified in the TVLA DTR. - * - * Packet payload must be a `uint32_t` representation of the number of - * encryptions to perform. Number of operations of a batch should not be greater - * than the 'kNumBatchOpsMax' value. - * - * The PRNG should be initialized using the 's' (seed PRNG) command before - * starting batch captures. In addition, the fixed key should also be set - * using 't' (fvsr key set) command before starting batch captures. - * - * The uJSON data contains: - * - data: The number of encryptions. - * - * @param uj The received uJSON data. - */ -status_t aes_sca_fvsr_key_batch_generate(cryptotest_aes_sca_data_t uj_data) { +status_t handle_aes_sca_batch_encrypt(ujson_t *uj) { + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); uint32_t num_encryptions = 0; num_encryptions = read_32(uj_data.data); - if (num_encryptions > kNumBatchOpsMax) { - return OUT_OF_RANGE(); + + block_ctr += num_encryptions; + // Rewrite the key to reset the internal block counter. Otherwise, the AES + // peripheral might trigger the reseeding of the internal masking PRNG which + // disturbs SCA measurements. + if (block_ctr > kBlockCtrMax) { + if (aes_key_mask_and_config(key_fixed, kAesKeyLength) != aesScaOk) { + return ABORTED(); + } + block_ctr = num_encryptions; } + if (fpga_mode) { + sca_set_trigger_high(); + } for (uint32_t i = 0; i < num_encryptions; ++i) { - if (sample_fixed) { - memcpy(batch_keys[i], key_fixed, kAesKeyLength); - memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength); - aes_serial_advance_fixed(); - } else { - memcpy(batch_keys[i], key_random, kAesKeyLength); - memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength); - aes_serial_advance_random(); + if (aes_encrypt(plaintext_random, kAesTextLength) != aesScaOk) { + return ABORTED(); } - sample_fixed = batch_plaintexts[i][0] & 0x1; + aes_serial_advance_random(); + } + if (fpga_mode) { + sca_set_trigger_low(); } - return OK_STATUS(); -} - -/** - * Fixed vs random key batch generate command handler. - * - * The uJSON data contains: - * - data: The number of encryptions. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_fvsr_key_batch_generate(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); + TRY(aes_send_ciphertext(true, uj)); - return aes_sca_fvsr_key_batch_generate(uj_data); + return OK_STATUS(); } -/** - * Fixed vs random key batch encrypt and generate command handler. - * - * This command is designed to maximize the capture rate for side-channel - * attacks. Instead of expecting a plaintext and sending the resulting - * ciphertext from and to the host for each encryption, this command repeatedly - * encrypts random plaintexts that are generated on the device. The data - * collection method is based on the derived test requirements (DTR) for TVLA: - * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf - * The measurements are taken by using either fixed or randomly selected keys. - * In order to simplify the analysis, the first encryption has to use fixed key. - * In addition, a PRNG is used for random key and plaintext generation instead - * of AES algorithm as specified in the TVLA DTR. - * This minimizes the overhead of UART communication and significantly improves - * the capture rate. The host must use the same PRNG to be able to compute the - * random plaintext, random key and the ciphertext of each trace. - * - * Packet payload must be a `uint32_t` representation of the number of - * encryptions to perform. Number of operations of a batch should not be greater - * than the 'kNumBatchOpsMax' value. - * - * The PRNG should be initialized using the 's' (seed PRNG) command before - * starting batch encryption. In addition, the fixed key should also be set - * using 't' (fvsr key set) command before starting batch encryption. - * - * Note that the host can partially verify this operation by checking the - * contents of the 'r' (last ciphertext) packet that is sent at the end of every - * batch. - * - * The uJSON data contains: - * - data: The number of encryptions. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_fvsr_key_batch_encrypt(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); - +status_t handle_aes_sca_batch_encrypt_random(ujson_t *uj) { + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); uint32_t num_encryptions = 0; num_encryptions = read_32(uj_data.data); - if (num_encryptions > kNumBatchOpsMax) { - return OUT_OF_RANGE(); + + block_ctr += num_encryptions; + // Rewrite the key to reset the internal block counter. Otherwise, the AES + // peripheral might trigger the reseeding of the internal masking PRNG which + // disturbs SCA measurements. + if (block_ctr > kBlockCtrMax) { + if (aes_key_mask_and_config(key_random, kAesKeyLength) != aesScaOk) { + return ABORTED(); + } + block_ctr = num_encryptions; } if (fpga_mode) { sca_set_trigger_high(); } for (uint32_t i = 0; i < num_encryptions; ++i) { - if (aes_key_mask_and_config(batch_keys[i], kAesKeyLength) != aesScaOk) { + if (aes_key_mask_and_config(key_random, kAesKeyLength) != aesScaOk) { return ABORTED(); } - if (aes_encrypt(batch_plaintexts[i], kAesTextLength) != aesScaOk) { + if (aes_encrypt(plaintext_random, kAesTextLength) != aesScaOk) { return ABORTED(); } + aes_serial_advance_random(); } if (fpga_mode) { sca_set_trigger_low(); } - TRY(aes_send_ciphertext(false, uj)); + TRY(aes_send_ciphertext(true, uj)); - // Start to generate random keys and plaintexts for the next batch when the - // waves are getting from scope by the host to increase capture rate. - return aes_sca_fvsr_key_batch_generate(uj_data); + return OK_STATUS(); +} + +status_t handle_aes_sca_batch_plaintext_set(ujson_t *uj) { + aes_sca_text_t uj_data; + TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data)); + + if (uj_data.text_length != kAesTextLength) { + return OUT_OF_RANGE(); + } + memcpy(batch_plaintext, uj_data.text, uj_data.text_length); + + return OK_STATUS(); } -/** - * Fixed vs random data batch encrypt and generate command handler. - * - * This command is designed to maximize the capture rate for side-channel - * attacks. Instead of expecting a plaintext and sending the resulting - * ciphertext from and to the host for each encryption, this command repeatedly - * encrypts plaintexts that are generated on the device. The data - * collection method is based on the derived test requirements (DTR) for TVLA: - * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf - * The measurements are taken by using either fixed or randomly selected - * plaintexts. In order to simplify the analysis, the first encryption has to - * use fixed plaintext. This minimizes the overhead of UART communication and - * significantly improves the capture rate. The host must use the same PRNG to - * be able to compute the random plaintext and the ciphertext of each trace. - * - * Packet payload must be a `uint32_t` representation of the number of - * encryptions to perform. Number of operations of a batch should not be greater - * than the 'kNumBatchOpsMax' value. - * - * Note that the host can partially verify this operation by checking the - * contents of the 'r' (last ciphertext) packet that is sent at the end of every - * batch. - * - * The uJSON data contains: - * - data: The number of encryptions. - * - * @param uj The received uJSON data. - */ status_t handle_aes_sca_fvsr_data_batch_encrypt(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); uint32_t num_encryptions = 0; num_encryptions = read_32(uj_data.data); @@ -758,90 +529,59 @@ status_t handle_aes_sca_fvsr_data_batch_encrypt(ujson_t *uj) { return OK_STATUS(); } -/** - * Seed lfsr command handler. - * - * This function only supports 4-byte seeds. - * Enables/disables masking depending on seed value, i.e. 0 for disable. - * - * The uJSON data contains: - * - seed: A buffer holding the seed. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_seed_lfsr(ujson_t *uj) { - cryptotest_aes_sca_lfsr_t uj_lfsr_data; - TRY(ujson_deserialize_cryptotest_aes_sca_lfsr_t(uj, &uj_lfsr_data)); +status_t handle_aes_sca_fvsr_key_batch_encrypt(ujson_t *uj) { + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); - uint32_t seed_local = read_32(uj_lfsr_data.seed); - if (seed_local == 0) { - // disable masking - transaction.force_masks = true; - } else { - // enable masking - transaction.force_masks = false; + uint32_t num_encryptions = 0; + num_encryptions = read_32(uj_data.data); + if (num_encryptions > kNumBatchOpsMax) { + return OUT_OF_RANGE(); } - sca_seed_lfsr(seed_local, kScaLfsrMasking); -#if !OT_IS_ENGLISH_BREAKFAST - if (transaction.force_masks) { - LOG_INFO("Disabling masks."); - status_t res = aes_testutils_masking_prng_zero_output_seed(); - if (res.value != 0) { + if (fpga_mode) { + sca_set_trigger_high(); + } + for (uint32_t i = 0; i < num_encryptions; ++i) { + if (aes_key_mask_and_config(batch_keys[i], kAesKeyLength) != aesScaOk) { + return ABORTED(); + } + if (aes_encrypt(batch_plaintexts[i], kAesTextLength) != aesScaOk) { return ABORTED(); } - // Load the magic seed into the PRNG. After this, the PRNG outputs - // an all-zero vector. - TRY(dif_aes_trigger(&aes, kDifAesTriggerPrngReseed)); - bool idle = false; - do { - TRY(dif_aes_get_status(&aes, kDifAesStatusIdle, &idle)); - } while (!idle); - // Load the PRNG output into the buffer stage. - TRY(dif_aes_trigger(&aes, kDifAesTriggerDataOutClear)); } -#endif + if (fpga_mode) { + sca_set_trigger_low(); + } - return OK_STATUS(); + TRY(aes_send_ciphertext(false, uj)); + + // Start to generate random keys and plaintexts for the next batch when the + // waves are getting from scope by the host to increase capture rate. + return aes_sca_fvsr_key_batch_generate(uj_data); } -/** - * Seed lfsr command handler. - * - * This function only supports 4-byte seeds. - * Sets the seed for the LFSR used to determine the order of measurements - * in fixed-vs-random-data dataset. - * - * The uJSON data contains: - * - seed: A buffer holding the seed. - * - * @param uj The received uJSON data. - */ -status_t handle_aes_sca_seed_lfsr_order(ujson_t *uj) { - cryptotest_aes_sca_lfsr_t uj_lfsr_data; - TRY(ujson_deserialize_cryptotest_aes_sca_lfsr_t(uj, &uj_lfsr_data)); +status_t handle_aes_sca_fvsr_key_batch_generate(ujson_t *uj) { + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); - uint32_t seed_local = read_32(uj_lfsr_data.seed); - sca_seed_lfsr(seed_local, kScaLfsrOrder); + return aes_sca_fvsr_key_batch_generate(uj_data); +} + +status_t handle_aes_sca_fvsr_key_set(ujson_t *uj) { + aes_sca_key_t uj_key_data; + TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data)); + if (uj_key_data.key_length != kAesKeyLength) { + return OUT_OF_RANGE(); + } + memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length); return OK_STATUS(); } -/** - * Set starting values command handler. - * - * This function sets starting values for FvsR data generation - * if the received value is 1. - * These values are specified in DTR for AES TVLA. - * - * The uJSON data contains: - * - seed: A buffer holding the seed. - * - * @param uj The received uJSON data. - */ status_t handle_aes_sca_fvsr_key_start_batch_generate(ujson_t *uj) { - cryptotest_aes_sca_data_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_data_t(uj, &uj_data)); + aes_sca_data_t uj_data; + TRY(ujson_deserialize_aes_sca_data_t(uj, &uj_data)); uint32_t command = 0; command = read_32(uj_data.data); @@ -891,17 +631,10 @@ status_t handle_aes_sca_fvsr_key_start_batch_generate(ujson_t *uj) { return OK_STATUS(); } -/** - * Initialize AES command handler. - * - * This command is designed to setup the AES. - * - * @param uj The received uJSON data. - */ status_t handle_aes_sca_init(ujson_t *uj) { // Read mode. FPGA or discrete. - cryptotest_aes_sca_fpga_mode_t uj_data; - TRY(ujson_deserialize_cryptotest_aes_sca_fpga_mode_t(uj, &uj_data)); + aes_sca_fpga_mode_t uj_data; + TRY(ujson_deserialize_aes_sca_fpga_mode_t(uj, &uj_data)); if (uj_data.fpga_mode == 0x01) { fpga_mode = true; } @@ -918,59 +651,138 @@ status_t handle_aes_sca_init(ujson_t *uj) { // Disable the instruction cache and dummy instructions for better SCA // measurements. - sca_configure_cpu(); + pentest_configure_cpu(); // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); } +status_t handle_aes_sca_key_set(ujson_t *uj) { + aes_sca_key_t uj_key_data; + TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data)); + + memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length); + block_ctr = 0; + if (aes_key_mask_and_config(key_fixed, uj_key_data.key_length) != aesScaOk) { + return ABORTED(); + } + return OK_STATUS(); +} + +status_t handle_aes_sca_seed_lfsr(ujson_t *uj) { + aes_sca_lfsr_t uj_lfsr_data; + TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data)); + + uint32_t seed_local = read_32(uj_lfsr_data.seed); + if (seed_local == 0) { + // disable masking + transaction.force_masks = true; + } else { + // enable masking + transaction.force_masks = false; + } + sca_seed_lfsr(seed_local, kScaLfsrMasking); + +#if !OT_IS_ENGLISH_BREAKFAST + if (transaction.force_masks) { + LOG_INFO("Disabling masks."); + status_t res = aes_testutils_masking_prng_zero_output_seed(); + if (res.value != 0) { + return ABORTED(); + } + // Load the magic seed into the PRNG. After this, the PRNG outputs + // an all-zero vector. + TRY(dif_aes_trigger(&aes, kDifAesTriggerPrngReseed)); + bool idle = false; + do { + TRY(dif_aes_get_status(&aes, kDifAesStatusIdle, &idle)); + } while (!idle); + // Load the PRNG output into the buffer stage. + TRY(dif_aes_trigger(&aes, kDifAesTriggerDataOutClear)); + } +#endif + + return OK_STATUS(); +} + +status_t handle_aes_sca_seed_lfsr_order(ujson_t *uj) { + aes_sca_lfsr_t uj_lfsr_data; + TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data)); + + uint32_t seed_local = read_32(uj_lfsr_data.seed); + sca_seed_lfsr(seed_local, kScaLfsrOrder); + + return OK_STATUS(); +} + +status_t handle_aes_sca_single_encrypt(ujson_t *uj) { + aes_sca_text_t uj_data; + TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data)); + if (uj_data.text_length != kAesTextLength) { + return OUT_OF_RANGE(); + } + + block_ctr++; + // Rewrite the key to reset the internal block counter. Otherwise, the AES + // peripheral might trigger the reseeding of the internal masking PRNG which + // disturbs SCA measurements. + if (block_ctr > kBlockCtrMax) { + if (aes_key_mask_and_config(key_fixed, kAesKeyLength) != aesScaOk) { + return ABORTED(); + } + block_ctr = 1; + } + + if (fpga_mode) { + sca_set_trigger_high(); + } + if (aes_encrypt(uj_data.text, uj_data.text_length) != aesScaOk) { + return ABORTED(); + } + if (fpga_mode) { + sca_set_trigger_low(); + } + + TRY(aes_send_ciphertext(false, uj)); + return OK_STATUS(); +} + status_t handle_aes_sca(ujson_t *uj) { aes_sca_subcommand_t cmd; TRY(ujson_deserialize_aes_sca_subcommand_t(uj, &cmd)); switch (cmd) { - case kAesScaSubcommandInit: - return handle_aes_sca_init(uj); - break; - case kAesScaSubcommandKeySet: - return handle_aes_sca_key_set(uj); - break; - case kAesScaSubcommandSingleEncrypt: - return handle_aes_sca_single_encrypt(uj); - break; + case kAesScaSubcommandBatchAlternativeEncrypt: + return handle_aes_sca_batch_alternative_encrypt(uj); case kAesScaSubcommandBatchEncrypt: return handle_aes_sca_batch_encrypt(uj); - break; - case kAesScaSubcommandFvsrKeySet: - return handle_aes_sca_fvsr_key_set(uj); - break; - case kAesScaSubcommandFvsrKeyBatchGenerate: - return handle_aes_sca_fvsr_key_batch_generate(uj); - break; + case kAesScaSubcommandBatchEncryptRandom: + return handle_aes_sca_batch_encrypt_random(uj); + case kAesScaSubcommandBatchPlaintextSet: + return handle_aes_sca_batch_plaintext_set(uj); + case kAesScaSubcommandFvsrDataBatchEncrypt: + return handle_aes_sca_fvsr_data_batch_encrypt(uj); case kAesScaSubcommandFvsrKeyBatchEncrypt: return handle_aes_sca_fvsr_key_batch_encrypt(uj); - break; + case kAesScaSubcommandFvsrKeyBatchGenerate: + return handle_aes_sca_fvsr_key_batch_generate(uj); + case kAesScaSubcommandFvsrKeySet: + return handle_aes_sca_fvsr_key_set(uj); case kAesScaSubcommandFvsrKeyStartBatchGenerate: return handle_aes_sca_fvsr_key_start_batch_generate(uj); - break; - case kAesScaSubcommandFvsrDataBatchEncrypt: - return handle_aes_sca_fvsr_data_batch_encrypt(uj); - break; + case kAesScaSubcommandInit: + return handle_aes_sca_init(uj); + case kAesScaSubcommandKeySet: + return handle_aes_sca_key_set(uj); case kAesScaSubcommandSeedLfsr: return handle_aes_sca_seed_lfsr(uj); - break; case kAesScaSubcommandSeedLfsrOrder: return handle_aes_sca_seed_lfsr_order(uj); - break; - case kAesScaSubcommandBatchAlternativeEncrypt: - return handle_aes_sca_batch_alternative_encrypt(uj); - break; - case kAesScaSubcommandBatchPlaintextSet: - return handle_aes_sca_batch_plaintext_set(uj); - break; + case kAesScaSubcommandSingleEncrypt: + return handle_aes_sca_single_encrypt(uj); default: LOG_ERROR("Unrecognized AES SCA subcommand: %d", cmd); return INVALID_ARGUMENT(); diff --git a/sw/device/tests/penetrationtests/firmware/sca/aes_sca.h b/sw/device/tests/penetrationtests/firmware/sca/aes_sca.h index 6cebf56aedcaac..09701c0b6d2ff7 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/aes_sca.h +++ b/sw/device/tests/penetrationtests/firmware/sca/aes_sca.h @@ -27,18 +27,300 @@ typedef enum aes_sca_error { aesScaOutOfRange = 2 } aes_sca_error_t; -status_t handle_aes_sca_batch_plaintext_set(ujson_t *uj); +/** + * Simple serial 'a' (alternative batch encrypt) command handler. + * + * This command is designed to maximize the capture rate for side-channel + * attacks. It uses the first supplied plaintext and repeats AES encryptions + * by using every ciphertext as next plaintext with a constant key. This + * minimizes the overhead of UART communication and significantly improves the + * capture rate. + + * Packet payload must be a `uint32_t` representation of the number of + * encryptions to perform. Since generated plaintexts are not cached, there is + * no limit on the number of encryptions. + * + * The key should also be set using 'k' (key set) command. + * + * The host can verify the operation by checking the last 'r' (ciphertext) + * packet that is sent at the end. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca_batch_alternative_encrypt(ujson_t *uj); -status_t handle_aes_sca_seed_lfsr(ujson_t *uj); -status_t handle_aes_sca_fvsr_key_start_batch_generate(ujson_t *uj); + +/** + * Batch encrypt command handler. + * + * This command is designed to maximize the capture rate for side-channel + * attacks. Instead of expecting a plaintext and sending the resulting + * ciphertext from and to the host for each encryption, this command repeatedly + * encrypts random plaintexts that are generated on the device. This minimizes + * the overhead of UART communication and significantly improves the capture + * rate. The host must use the same PRNG to be able to compute the plaintext and + * the ciphertext of each trace. + * + * Packet payload must be a `uint32_t` representation of the number of + * encryptions to perform. Since generated plaintexts are not cached, there is + * no limit on the number of encryptions. + * + * The PRNG should be initialized using the seed PRNG command before + * starting batch encryption. In addition, the key should also be set + * using key set command before starting batch captures. + * + * Note that the host can partially verify this operation by checking the + * contents of UART reponse that is sent at the end. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_batch_encrypt(ujson_t *uj); + +/** + * Batch encrypt random command handler. + * + * This command is designed to maximize the capture rate for side-channel + * attacks. Instead of expecting a plaintext and sending the resulting + * ciphertext from and to the host for each encryption, this command repeatedly + * encrypts random plaintexts that are generated on the device. This minimizes + * the overhead of UART communication and significantly improves the capture + * rate. The host must use the same PRNG to be able to compute the plaintext and + * the ciphertext of each trace. + * + * Packet payload must be a `uint32_t` representation of the number of + * encryptions to perform. Since generated plaintexts are not cached, there is + * no limit on the number of encryptions. + * + * The PRNG should be initialized using the seed PRNG command before + * starting batch encryption. In addition, the key should also be set + * using key set command before starting batch captures. + * + * Note that the host can partially verify this operation by checking the + * contents of UART reponse that is sent at the end. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_batch_encrypt_random(ujson_t *uj); + +/** + * Batch plaintext command handler. + * + * This command is designed to set the initial plaintext for + * aes_serial_batch_alternative_encrypt. + * + * The plaintext must be `kAesTextLength` bytes long. + * + * * The uJSON data contains: + * - text: The plaintext. + * - text_length: Plaintext length. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_batch_plaintext_set(ujson_t *uj); + +/** + * Fixed vs random data batch encrypt and generate command handler. + * + * This command is designed to maximize the capture rate for side-channel + * attacks. Instead of expecting a plaintext and sending the resulting + * ciphertext from and to the host for each encryption, this command repeatedly + * encrypts plaintexts that are generated on the device. The data + * collection method is based on the derived test requirements (DTR) for TVLA: + * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf + * The measurements are taken by using either fixed or randomly selected + * plaintexts. In order to simplify the analysis, the first encryption has to + * use fixed plaintext. This minimizes the overhead of UART communication and + * significantly improves the capture rate. The host must use the same PRNG to + * be able to compute the random plaintext and the ciphertext of each trace. + * + * Packet payload must be a `uint32_t` representation of the number of + * encryptions to perform. Number of operations of a batch should not be greater + * than the 'kNumBatchOpsMax' value. + * + * Note that the host can partially verify this operation by checking the + * contents of the 'r' (last ciphertext) packet that is sent at the end of every + * batch. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_fvsr_data_batch_encrypt(ujson_t *uj); + +/** + * Fixed vs random key batch encrypt and generate command handler. + * + * This command is designed to maximize the capture rate for side-channel + * attacks. Instead of expecting a plaintext and sending the resulting + * ciphertext from and to the host for each encryption, this command repeatedly + * encrypts random plaintexts that are generated on the device. The data + * collection method is based on the derived test requirements (DTR) for TVLA: + * https://www.rambus.com/wp-content/uploads/2015/08/TVLA-DTR-with-AES.pdf + * The measurements are taken by using either fixed or randomly selected keys. + * In order to simplify the analysis, the first encryption has to use fixed key. + * In addition, a PRNG is used for random key and plaintext generation instead + * of AES algorithm as specified in the TVLA DTR. + * This minimizes the overhead of UART communication and significantly improves + * the capture rate. The host must use the same PRNG to be able to compute the + * random plaintext, random key and the ciphertext of each trace. + * + * Packet payload must be a `uint32_t` representation of the number of + * encryptions to perform. Number of operations of a batch should not be greater + * than the 'kNumBatchOpsMax' value. + * + * The PRNG should be initialized using the 's' (seed PRNG) command before + * starting batch encryption. In addition, the fixed key should also be set + * using 't' (fvsr key set) command before starting batch encryption. + * + * Note that the host can partially verify this operation by checking the + * contents of the 'r' (last ciphertext) packet that is sent at the end of every + * batch. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca_fvsr_key_batch_encrypt(ujson_t *uj); + +/** + * Fixed vs random key batch generate command handler. + * + * The uJSON data contains: + * - data: The number of encryptions. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca_fvsr_key_batch_generate(ujson_t *uj); + +/** + * Fvsr key set command handler. + * + * This command is designed to set the fixed key which is used for fvsr key TVLA + * captures. + * + * The key must be `kAesKeyLength` bytes long. + * + * The uJSON data contains: + * - key: The key to use. + * - key_length: The length of the key. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca_fvsr_key_set(ujson_t *uj); -status_t handle_aes_sca_batch_encrypt(ujson_t *uj); -status_t handle_aes_sca_single_encrypt(ujson_t *uj); -status_t handle_aes_sca_key_set(ujson_t *uj); -status_t handle_aes_sca_select_trigger_source(ujson_t *uj); + +/** + * Set starting values command handler. + * + * This function sets starting values for FvsR data generation + * if the received value is 1. + * These values are specified in DTR for AES TVLA. + * + * The uJSON data contains: + * - seed: A buffer holding the seed. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_fvsr_key_start_batch_generate(ujson_t *uj); + +/** + * Initialize AES command handler. + * + * This command is designed to setup the AES. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca_init(ujson_t *uj); + +/** + * Key set command handler. + * + * This command is designed to set the fixed_key variable and in addition also + * configures the key into the AES peripheral. + * + * The key must be `kAesKeyLength` bytes long. + * + * The uJSON data contains: + * - key: The key to use. + * - key_length: The length of the key. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_key_set(ujson_t *uj); + +/** + * Seed lfsr command handler. + * + * This function only supports 4-byte seeds. + * Enables/disables masking depending on seed value, i.e. 0 for disable. + * + * The uJSON data contains: + * - seed: A buffer holding the seed. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_seed_lfsr(ujson_t *uj); + +/** + * Seed lfsr command handler. + * + * This function only supports 4-byte seeds. + * Sets the seed for the LFSR used to determine the order of measurements + * in fixed-vs-random-data dataset. + * + * The uJSON data contains: + * - seed: A buffer holding the seed. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_seed_lfsr_order(ujson_t *uj); + +/** + * Single encrypt command handler. + * + * Encrypts a `kAesTextLength` bytes long plaintext using the AES peripheral and + * sends the ciphertext over UART. This function also handles the trigger + * signal. + * + * The uJSON data contains: + * - text: The plaintext. + * - text_length: The length of the plaintext. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_aes_sca_single_encrypt(ujson_t *uj); + +/** + * HMAC SCA command handler. + * + * Command handler for the HMAC SCA command. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ status_t handle_aes_sca(ujson_t *uj); #endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_AES_SCA_H_ diff --git a/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.c b/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.c new file mode 100644 index 00000000000000..a7471d8f5badd1 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.c @@ -0,0 +1,354 @@ +// 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/sca/ecc256_keygen_sca.h" + +#include "sw/device/lib/base/abs_mmio.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/lib/runtime/ibex.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/test_framework/ottf_main.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/prng.h" +#include "sw/device/sca/lib/sca.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" +#include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" +#include "otbn_regs.h" + +enum { + /** + * Number of bytes for ECDSA P-256 seeds and masked private keys. + */ + kEcc256SeedNumBytes = 320 / 8, + /** + * Number of 32b words for ECDSA P-256 seeds and masked private keys. + */ + kEcc256SeedNumWords = kEcc256SeedNumBytes / sizeof(uint32_t), + /** + * Number of bytes for ECDSA P-256 point coordinates. + */ + kEcc256CoordNumBytes = 256 / 8, + /** + * Number of 32b words for ECDSA P-256 point coordinates. + */ + kEcc256CoordNumWords = kEcc256CoordNumBytes / sizeof(uint32_t), + /** + * Mode option for the ECDSA keygen app (generates the private key only). + */ + kEcc256ModePrivateKeyOnly = 1, + /** + * Mode option for the ECDSA keygen app (generates the full keypair). + */ + kEcc256ModeKeypair = 2, + /** + * Max number of traces per batch. + */ + kNumBatchOpsMax = 256, + /** + * Number of cycles that Ibex should sleep to minimize noise during OTBN + * operations. Caution: This number should be chosen to provide enough time + * to complete the operation. Otherwise, Ibex might wake up while OTBN is + * still busy and disturb the capture. This was measured using mcycle_read + * when otbn_manual_trigger and otbn_busy_wait_for_done get executed. + */ + kIbexOtbnSleepCycles = 1100, +}; + +/** + * App configuration for p256_key_from_seed_sca + */ +const otbn_app_t kOtbnAppP256KeyFromSeed = + OTBN_APP_T_INIT(p256_key_from_seed_sca); + +static const otbn_addr_t kOtbnVarMode = + OTBN_ADDR_T_INIT(p256_key_from_seed_sca, mode); +static const otbn_addr_t kOtbnVarSeed0 = + OTBN_ADDR_T_INIT(p256_key_from_seed_sca, seed0); +static const otbn_addr_t kOtbnVarSeed1 = + OTBN_ADDR_T_INIT(p256_key_from_seed_sca, seed1); +static const otbn_addr_t kOtbnVarD0 = + OTBN_ADDR_T_INIT(p256_key_from_seed_sca, d0); +static const otbn_addr_t kOtbnVarD1 = + OTBN_ADDR_T_INIT(p256_key_from_seed_sca, d1); + +/** + * An array of seeds to be used in a batch + */ +uint32_t batch_share0[kNumBatchOpsMax][kEcc256SeedNumWords]; + +/** + * An array of masks to be used in a batch + */ +uint32_t batch_share1[kNumBatchOpsMax][kEcc256SeedNumWords]; + +/** + * Arrays for first and second share of masked private key d to be used in a + * batch + */ +uint32_t d0_batch[kEcc256SeedNumWords]; +uint32_t d1_batch[kEcc256SeedNumWords]; + +/** + * Fixed-message indicator. + * + * Used in the 'b' (batch capture) command for indicating whether to use fixed + * or random message. + */ +static bool run_fixed = true; + +/** + * Masking indicator. + * + * Used in the 'b' (batch capture) command for indicating whether to use masks. + */ +static bool en_masks = false; + +uint32_t ecc256_seed[kEcc256SeedNumWords]; + +uint32_t ecc256_C[kEcc256SeedNumWords]; + +uint32_t random_number[kEcc256CoordNumWords]; + +uint32_t ecc256_fixed_number[kEcc256CoordNumWords]; + +/** + * Adds two integers storred in byte arrays. + * + * Adds the integer stored in source array to the integer stored in + * destination aray. + * The user needs to ensure that dest_len is enough to store the result + * without overflow. + * + * @param[in] dest Location of the first input array and the result. + * @param[in] source Location of the second input array. + * @param[in] dest_len Length of the dest array in bytes. + * @param[in] source_len Length of the source array in bytes. + */ +static void add_arrays(uint8_t *dest, uint8_t *source, size_t dest_len, + size_t source_len) { + uint16_t temp = 0; + + for (size_t i = 0; i < source_len; i++) { + temp += (uint16_t)source[i] + dest[i]; + dest[i] = (uint8_t)(temp & 0x00FF); + temp >>= 8; + } + + for (size_t i = source_len; i < dest_len; i++) { + temp += (uint16_t)dest[i]; + dest[i] = (uint8_t)(temp & 0x00FF); + temp >>= 8; + } +} + +/** + * Callback wrapper for OTBN manual trigger function. + */ +static void otbn_manual_trigger(void) { otbn_execute(); } + +/** + * Runs the OTBN key generation program. + * + * The seed shares must be `kEcc256SeedNumWords` words long. + * + * @param[in] mode Mode parameter (private key only or full keypair). + * @param[in] seed Seed for key generation. + * @param[in] mask Mask for seed. + * @return OK or error. + */ +static status_t p256_run_keygen(uint32_t mode, const uint32_t *share0, + const uint32_t *share1) { + // Secure wipe to scramble DMEM. + TRY(otbn_load_app(kOtbnAppP256KeyFromSeed)); + + // Write mode. + TRY(otbn_dmem_write(/*num_words=*/1, &mode, kOtbnVarMode)); + + // Write seed shares. + TRY(otbn_dmem_write(kEcc256SeedNumWords, share0, kOtbnVarSeed0)); + TRY(otbn_dmem_write(kEcc256SeedNumWords, share1, kOtbnVarSeed1)); + + // Execute program. Trigger is set inside this function. + pentest_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles, true, true); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(ujson_t *uj) { + penetrationtest_otbn_sca_num_traces_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(uj, &uj_data)); + + uint32_t num_traces = uj_data.num_traces; + uint32_t batch_digest[kEcc256SeedNumWords]; + + if (num_traces > kNumBatchOpsMax) { + return OUT_OF_RANGE(); + } + + // Zero the batch digest. + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_digest[j] = 0; + } + + for (size_t i = 0; i < num_traces; ++i) { + // Set mask to a random mask (en_masks = true) or to 0 (en_masks = false). + if (en_masks) { + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share1[i][j] = prng_rand_uint32(); + } + } else { + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share1[i][j] = 0; + } + } + + // If the run is fixed, take the fixed seed received from the host. Else, + // generate a random seed. + if (run_fixed) { + memcpy(batch_share0[i], ecc256_seed, kEcc256SeedNumBytes); + } else { + // Here change to random_number + C. + // It is necessary to set the C first. + memcpy(batch_share0[i], ecc256_C, kEcc256SeedNumBytes); + for (size_t j = 0; j < kEcc256CoordNumWords; ++j) { + random_number[j] = prng_rand_uint32(); + } + add_arrays((unsigned char *)batch_share0[i], + (unsigned char *)random_number, kEcc256SeedNumBytes, + kEcc256CoordNumBytes); + } + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share0[i][j] ^= batch_share1[i][j]; + } + // Another PRNG run to determine 'run_fixed' for the next cycle. + run_fixed = prng_rand_uint32() & 0x1; + } + + for (size_t i = 0; i < num_traces; ++i) { + TRY(p256_run_keygen(kEcc256ModePrivateKeyOnly, batch_share0[i], + batch_share1[i])); + + // Read results. + TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD0, d0_batch)); + TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD1, d1_batch)); + + // The correctness of each batch is verified by computing and sending + // the batch digest. This digest is computed by XORing all d0 shares of + // the batch. + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_digest[j] ^= d0_batch[j]; + } + } + // Send the batch digest to the host for verification. + penetrationtest_otbn_sca_batch_digest_t uj_output; + memcpy(uj_output.batch_digest, (uint8_t *)batch_digest, + kEcc256SeedNumWords * 4); + RESP_OK(ujson_serialize_penetrationtest_otbn_sca_batch_digest_t, uj, + &uj_output); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(ujson_t *uj) { + penetrationtest_otbn_sca_num_traces_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(uj, &uj_data)); + + uint32_t num_traces = uj_data.num_traces; + uint32_t batch_digest[kEcc256SeedNumWords]; + + if (num_traces > kNumBatchOpsMax) { + return OUT_OF_RANGE(); + } + + // Zero the batch digest. + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_digest[j] = 0; + } + + for (size_t i = 0; i < num_traces; ++i) { + // Set mask to a random mask (en_masks = true) or to 0 (en_masks = false). + if (en_masks) { + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share1[i][j] = prng_rand_uint32(); + } + } else { + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share1[i][j] = 0; + } + } + + // If the run is fixed, take the fixed seed received from the host. Else, + // generate a random seed. + if (run_fixed) { + memcpy(batch_share0[i], ecc256_seed, kEcc256SeedNumBytes); + } else { + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share0[i][j] = prng_rand_uint32(); + } + } + + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_share0[i][j] ^= batch_share1[i][j]; + } + run_fixed = prng_rand_uint32() & 0x1; + } + + for (size_t i = 0; i < num_traces; ++i) { + TRY(p256_run_keygen(kEcc256ModePrivateKeyOnly, batch_share0[i], + batch_share1[i])); + + // Read results. + TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD0, d0_batch)); + TRY(otbn_dmem_read(kEcc256SeedNumWords, kOtbnVarD1, d1_batch)); + + // The correctness of each batch is verified by computing and sending + // the batch digest. This digest is computed by XORing all d0 shares of + // the batch. + for (size_t j = 0; j < kEcc256SeedNumWords; ++j) { + batch_digest[j] ^= d0_batch[j]; + } + } + + // Send the batch digest to the host for verification. + penetrationtest_otbn_sca_batch_digest_t uj_output; + memcpy(uj_output.batch_digest, (uint8_t *)batch_digest, + kEcc256SeedNumWords * 4); + RESP_OK(ujson_serialize_penetrationtest_otbn_sca_batch_digest_t, uj, + &uj_output); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_ecc256_en_masks(ujson_t *uj) { + penetrationtest_otbn_sca_en_masks_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj, &uj_data)); + if (uj_data.en_masks) { + en_masks = true; + } else { + en_masks = false; + } + return OK_STATUS(); +} + +status_t handle_otbn_sca_ecc256_set_c(ujson_t *uj) { + penetrationtest_otbn_sca_constant_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_constant_t(uj, &uj_data)); + + memcpy(ecc256_C, uj_data.constant, kEcc256SeedNumBytes); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_ecc256_set_seed(ujson_t *uj) { + penetrationtest_otbn_sca_seed_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_seed_t(uj, &uj_data)); + + memcpy(ecc256_seed, uj_data.seed, kEcc256SeedNumBytes); + + return OK_STATUS(); +} diff --git a/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.h b/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.h new file mode 100644 index 00000000000000..70e7d076ad35f6 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/ecc256_keygen_sca.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_FIRMWARE_SCA_ECC256_KEYGEN_SCA_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_ECC256_KEYGEN_SCA_H_ + +#include "sw/device/lib/crypto/drivers/otbn.h" + +/** + * App configuration for p256_key_from_seed_sca + */ +OTBN_DECLARE_APP_SYMBOLS(p256_key_from_seed_sca); + +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, mode); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, seed0); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, seed1); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, d0); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, d1); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, x); +OTBN_DECLARE_SYMBOL_ADDR(p256_key_from_seed_sca, y); + +extern const otbn_app_t kOtbnAppP256KeyFromSeed; + +static const otbn_addr_t kOtbnVarMode; +static const otbn_addr_t kOtbnVarSeed0; +static const otbn_addr_t kOtbnVarSeed1; +static const otbn_addr_t kOtbnVarD0; +static const otbn_addr_t kOtbnVarD1; + +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_ECC256_KEYGEN_SCA_H_ diff --git a/sw/device/tests/penetrationtests/firmware/sca/edn_sca.c b/sw/device/tests/penetrationtests/firmware/sca/edn_sca.c new file mode 100644 index 00000000000000..cc1cc9ccdb1451 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/edn_sca.c @@ -0,0 +1,239 @@ +// 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/lib/base/memory.h" +#include "sw/device/lib/base/status.h" +#include "sw/device/lib/dif/dif_csrng.h" +#include "sw/device/lib/dif/dif_csrng_shared.h" +#include "sw/device/lib/dif/dif_edn.h" +#include "sw/device/lib/dif/dif_entropy_src.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/rv_core_ibex_testutils.h" +#include "sw/device/lib/testing/test_framework/ujson_ottf.h" +#include "sw/device/lib/ujson/ujson.h" +#include "sw/device/sca/lib/prng.h" +#include "sw/device/sca/lib/sca.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" +#include "sw/device/tests/penetrationtests/json/edn_sca_commands.h" + +#include "edn_regs.h" // Generated +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.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 + +enum { + kEdnKatTimeout = (10 * 1000 * 1000), + kEdnKatMaxClen = 12, + kEdnKatOutputLen = 16, + kEdnKatWordsPerBlock = 4, + /** + * Max number of traces per batch. + */ + kNumBatchOpsMax = 128, +}; + +static dif_rv_core_ibex_t rv_core_ibex; +static dif_entropy_src_t entropy_src; +static dif_csrng_t csrng; +static dif_edn_t edn0; + +// Generate random values used by the test by calling the SCA PRNG. +static void generate_random(size_t num_values, uint32_t values[]) { + for (size_t i = 0; i < num_values; i++) { + values[i] = prng_rand_uint32(); + } +} + +// Configure the EDN with the provided seed material, set the SCA trigger, +// generate and receive random data, and unset the trigger. +static status_t config_run_edn(uint32_t init_seed[12], uint32_t reseed[12]) { + // Setup seed material. + // Seed material for the EDN instantiate command. + dif_edn_seed_material_t kEdnKatSeedMaterialInstantiate = { + .len = kEdnKatMaxClen, + .data = {init_seed[0], init_seed[1], init_seed[2], init_seed[3], + init_seed[4], init_seed[5], init_seed[6], init_seed[7], + init_seed[8], init_seed[9], init_seed[10], init_seed[11]}}; + // Seed material for the EDN reseed command. + dif_edn_seed_material_t kEdnKatSeedMaterialReseed = { + .len = kEdnKatMaxClen, + .data = {reseed[0], reseed[1], reseed[2], reseed[3], reseed[4], reseed[5], + reseed[6], reseed[7], reseed[8], reseed[9], reseed[10], + reseed[11]}}; + // Seed material for the EDN generate command. + const dif_edn_seed_material_t kEdnKatSeedMaterialGenerate = { + .len = 0, + }; + + dif_edn_auto_params_t edn_params; + edn_params.instantiate_cmd.cmd = csrng_cmd_header_build( + kCsrngAppCmdInstantiate, kDifCsrngEntropySrcToggleDisable, + kEdnKatSeedMaterialInstantiate.len, /*generate_len=*/0); + edn_params.instantiate_cmd.seed_material = kEdnKatSeedMaterialInstantiate; + edn_params.reseed_cmd.cmd = csrng_cmd_header_build( + kCsrngAppCmdReseed, kDifCsrngEntropySrcToggleDisable, + kEdnKatSeedMaterialReseed.len, + /*generate_len=*/0); + edn_params.reseed_cmd.seed_material = kEdnKatSeedMaterialReseed; + edn_params.generate_cmd.cmd = csrng_cmd_header_build( + kCsrngAppCmdGenerate, kDifCsrngEntropySrcToggleDisable, + kEdnKatSeedMaterialGenerate.len, + /*generate_len=*/ + kEdnKatOutputLen / kEdnKatWordsPerBlock); + + edn_params.generate_cmd.seed_material = kEdnKatSeedMaterialGenerate; + edn_params.reseed_interval = 32; + + // Disable the entropy complex. + TRY(entropy_testutils_stop_all()); + // Enable ENTROPY_SRC in FIPS mode. + TRY(dif_entropy_src_configure( + &entropy_src, entropy_testutils_config_default(), kDifToggleEnabled)); + // Enable CSRNG. + TRY(dif_csrng_configure(&csrng)); + // Enable EDN0 in auto request mode. + TRY(dif_edn_set_auto_mode(&edn0, edn_params)); + + uint32_t ibex_rnd_data; + + // Capture trace during generation and transportation of random data. + sca_set_trigger_high(); + asm volatile(NOP30); + TRY(rv_core_ibex_testutils_get_rnd_data(&rv_core_ibex, kEdnKatTimeout, + &ibex_rnd_data)); + sca_set_trigger_low(); + asm volatile(NOP30); + + return OK_STATUS(); +} + +status_t handle_edn_sca_bus_data(ujson_t *uj) { + // Get seed material. + edn_sca_seed_t uj_data; + TRY(ujson_deserialize_edn_sca_seed_t(uj, &uj_data)); + + // Configure EDN with provided seed material, set trigger and start generating + // and fetching data. + config_run_edn(uj_data.init_seed, uj_data.reseed); + + // Acknowledge test. + edn_sca_result_t uj_output; + uj_output.result = 0; + RESP_OK(ujson_serialize_edn_sca_result_t, uj, &uj_output); + return OK_STATUS(); +} + +status_t handle_edn_sca_bus_data_batch_fvsr(ujson_t *uj) { + // Get seed material. + edn_sca_seed_batch_t uj_data; + TRY(ujson_deserialize_edn_sca_seed_batch_t(uj, &uj_data)); + + bool sample_fixed = true; + uint32_t last_value = 0; + + uint32_t init_seed[kNumBatchOpsMax][12]; + uint32_t reseed[kNumBatchOpsMax][12]; + + for (size_t it = 0; it < uj_data.num_iterations; it++) { + if (sample_fixed) { + memcpy(init_seed[it], uj_data.init_seed, 12 * sizeof(uint32_t)); + memcpy(reseed[it], uj_data.reseed, 12 * sizeof(uint32_t)); + } else { + // Generate random seeds for the EDN configuration. + generate_random(12, init_seed[it]); + generate_random(12, reseed[it]); + } + sample_fixed = prng_rand_uint32() & 0x1; + } + + for (size_t it = 0; it < uj_data.num_iterations; it++) { + // Configure EDN with random seed material, set trigger and start generating + // and fetching data. + TRY(config_run_edn(init_seed[it], reseed[it])); + last_value = reseed[it][11]; + } + + // Acknowledge test, send last reseed value back to host + // for verification. + edn_sca_result_t uj_output; + uj_output.result = last_value; + RESP_OK(ujson_serialize_edn_sca_result_t, uj, &uj_output); + return OK_STATUS(); +} + +status_t handle_edn_sca_bus_data_batch_random(ujson_t *uj) { + // Get number of iterations. + edn_sca_batch_t uj_data; + TRY(ujson_deserialize_edn_sca_batch_t(uj, &uj_data)); + + uint32_t init_seed[kNumBatchOpsMax][12]; + uint32_t reseed[kNumBatchOpsMax][12]; + for (size_t it = 0; it < uj_data.num_iterations; it++) { + // Generate random seeds for the EDN configuration. + generate_random(12, init_seed[it]); + generate_random(12, reseed[it]); + } + + for (size_t it = 0; it < uj_data.num_iterations; it++) { + // Configure EDN with random seed material, set trigger and start generating + // and fetching data. + TRY(config_run_edn(init_seed[it], reseed[it])); + } + + // Acknowledge test, send last random reseed value back to host + // for verification. + edn_sca_result_t uj_output; + uj_output.result = reseed[uj_data.num_iterations - 1][11]; + RESP_OK(ujson_serialize_edn_sca_result_t, uj, &uj_output); + return OK_STATUS(); +} + +status_t handle_edn_sca_init(ujson_t *uj) { + sca_select_trigger_type(kScaTriggerTypeSw); + // As we are using the software defined trigger, the first argument of + // sca_init is not needed. kScaTriggerSourceAes is selected as a placeholder. + sca_init(kScaTriggerSourceAes, kScaPeripheralIoDiv4 | kScaPeripheralEntropy | + kScaPeripheralCsrng | kScaPeripheralEdn); + + // Disable the instruction cache and dummy instructions for SCA attacks. + pentest_configure_cpu(); + + // 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)); + + // Initialize peripherals used in this SCA test. + TRY(dif_entropy_src_init( + mmio_region_from_addr(TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR), &entropy_src)); + TRY(dif_csrng_init(mmio_region_from_addr(TOP_EARLGREY_CSRNG_BASE_ADDR), + &csrng)); + TRY(dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN0_BASE_ADDR), &edn0)); + + return OK_STATUS(); +} + +status_t handle_edn_sca(ujson_t *uj) { + edn_sca_subcommand_t cmd; + TRY(ujson_deserialize_edn_sca_subcommand_t(uj, &cmd)); + switch (cmd) { + case kEdnScaSubcommandBusData: + return handle_edn_sca_bus_data(uj); + case kEdnScaSubcommandBusDataBatchFvsr: + return handle_edn_sca_bus_data_batch_fvsr(uj); + case kEdnScaSubcommandBusDataBatchRandom: + return handle_edn_sca_bus_data_batch_random(uj); + case kEdnScaSubcommandInit: + return handle_edn_sca_init(uj); + default: + LOG_ERROR("Unrecognized EDN SCA subcommand: %d", cmd); + return INVALID_ARGUMENT(); + } + return OK_STATUS(); +} diff --git a/sw/device/tests/penetrationtests/firmware/sca/edn_sca.h b/sw/device/tests/penetrationtests/firmware/sca/edn_sca.h new file mode 100644 index 00000000000000..3b3ef99635734c --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/edn_sca.h @@ -0,0 +1,60 @@ +// 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_SCA_EDN_SCA_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_EDN_SCA_H_ + +#include "sw/device/lib/base/status.h" +#include "sw/device/lib/ujson/ujson.h" + +/** + * edn.sca.bus_data command handler. + * + * The goal of this penetration test is to capture traces when + * the EDN generated random data and transfers it to Ibex. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_edn_sca_bus_data(ujson_t *uj); + +/** + * edn.sca.bus_data_batch_fvsr command handler. + * + * Batch version of edn.sca.bus_data with FvsR data. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_edn_sca_bus_data_batch_fvsr(ujson_t *uj); + +/** + * edn.sca.bus_data_batch_random command handler. + * + * Batch version of edn.sca.bus_data with random data. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_edn_sca_bus_data_batch_random(ujson_t *uj); + +/** + * Initializes the trigger and configures the device for the EDN SCA test. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_edn_sca_init(ujson_t *uj); + +/** + * EDN SCA command handler. + * + * Command handler for the EDN SCA command. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_edn_sca(ujson_t *uj); + +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_EDN_SCA_H_ diff --git a/sw/device/tests/penetrationtests/firmware/sca/hmac_sca.c b/sw/device/tests/penetrationtests/firmware/sca/hmac_sca.c index 047cad2f9ac321..838d56b73c4da2 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/hmac_sca.c +++ b/sw/device/tests/penetrationtests/firmware/sca/hmac_sca.c @@ -15,7 +15,7 @@ #include "sw/device/lib/ujson/ujson.h" #include "sw/device/sca/lib/prng.h" #include "sw/device/sca/lib/sca.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/hmac_sca_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -94,11 +94,11 @@ status_t handle_hmac_sca_init(ujson_t *uj) { kScaPeripheralEdn | kScaPeripheralHmac); // Disable the instruction cache and dummy instructions for SCA. - sca_configure_cpu(); + pentest_configure_cpu(); // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); diff --git a/sw/device/tests/penetrationtests/firmware/sca/ibex_sca.c b/sw/device/tests/penetrationtests/firmware/sca/ibex_sca.c index eabb24473df3ae..04ba578a5b13bf 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/ibex_sca.c +++ b/sw/device/tests/penetrationtests/firmware/sca/ibex_sca.c @@ -16,7 +16,7 @@ #include "sw/device/lib/ujson/ujson.h" #include "sw/device/sca/lib/prng.h" #include "sw/device/sca/lib/sca.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/ibex_sca_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -121,14 +121,14 @@ status_t handle_ibex_sca_init(ujson_t *uj) { sca_init(kScaTriggerSourceAes, kScaPeripheralIoDiv4 | kScaPeripheralKmac); // Disable the instruction cache and dummy instructions for SCA. - sca_configure_cpu(); + pentest_configure_cpu(); // Key manager not initialized for the handle_ibex_sca_key_sideloading test. key_manager_init = false; // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); diff --git a/sw/device/tests/penetrationtests/firmware/sca/kmac_sca.c b/sw/device/tests/penetrationtests/firmware/sca/kmac_sca.c index 70fccca5a86c48..7719e28436042d 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/kmac_sca.c +++ b/sw/device/tests/penetrationtests/firmware/sca/kmac_sca.c @@ -13,7 +13,7 @@ #include "sw/device/lib/ujson/ujson.h" #include "sw/device/sca/lib/prng.h" #include "sw/device/sca/lib/sca.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/kmac_sca_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -472,11 +472,11 @@ status_t handle_kmac_sca_init(ujson_t *uj) { // Disable the instruction cache and dummy instructions for better SCA // measurements. - sca_configure_cpu(); + pentest_configure_cpu(); // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); @@ -545,8 +545,8 @@ static kmac_sca_error_t sha3_ujson_absorb(const uint8_t *msg, size_t msg_len) { if (fpga_mode == false) { // Start command. On the chip, we need to first issue a START command // before writing to the message FIFO. - sca_call_and_sleep(kmac_start_cmd, kIbexLoadHashPrefixKeySleepCycles, - false); + pentest_call_and_sleep(kmac_start_cmd, kIbexLoadHashPrefixKeySleepCycles, + false, false); } // Write data to message FIFO. @@ -560,12 +560,13 @@ static kmac_sca_error_t sha3_ujson_absorb(const uint8_t *msg, size_t msg_len) { // configured to start operation 320 cycles after receiving the START and // PROC commands. This allows Ibex to go to sleep in order to not disturb // the capture. - sca_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles, false); + pentest_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles, false, + false); } else { // On the chip, issue a PROCESS command to start operation and put Ibex // into sleep. - sca_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles, - false); + pentest_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles, + false, false); } return kmacScaOk; diff --git a/sw/device/tests/penetrationtests/firmware/sca/otbn/BUILD b/sw/device/tests/penetrationtests/firmware/sca/otbn/BUILD new file mode 100644 index 00000000000000..a7ae88c15be491 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/otbn/BUILD @@ -0,0 +1,14 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +load("//rules:otbn.bzl", "otbn_binary") + +package(default_visibility = ["//visibility:public"]) + +otbn_binary( + name = "otbn_key_sideload_sca", + srcs = [ + "otbn_key_sideload_sca.s", + ], +) diff --git a/sw/device/tests/penetrationtests/firmware/sca/otbn/otbn_key_sideload_sca.s b/sw/device/tests/penetrationtests/firmware/sca/otbn/otbn_key_sideload_sca.s new file mode 100644 index 00000000000000..46382546f061b5 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/otbn/otbn_key_sideload_sca.s @@ -0,0 +1,77 @@ +/* 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 + + /* w8 <= KEY_S0_L ^ KEY_S1_L */ + bn.xor w8, w20, w21 + + /* w9 <= KEY_S0_H ^ KEY_S1_H */ + bn.xor w9, w22, w23 + + /* Write shares and keys 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) + + li x2, 8 + la x3, k_l + bn.sid x2, 0(x3) + + li x2, 9 + la x3, k_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 + + .globl k_l + .balign 32 + k_l: + .zero 32 + + .globl k_h + .balign 32 + k_h: + .zero 32 diff --git a/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.c b/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.c new file mode 100644 index 00000000000000..cf3ab16d376448 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.c @@ -0,0 +1,218 @@ +// 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/sca/otbn_sca.h" + +#include "ecc256_keygen_sca.h" +#include "sw/device/lib/arch/boot_stage.h" +#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/impl/keyblob.h" +#include "sw/device/lib/crypto/impl/status.h" +#include "sw/device/lib/dif/dif_otbn.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" +#include "sw/device/sca/lib/prng.h" +#include "sw/device/sca/lib/sca.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" +#include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" +#include "otbn_regs.h" // Generated. + +static dif_otbn_t otbn; +static dif_keymgr_t keymgr; +static dif_kmac_t kmac; + +// 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 + +enum { + kKeySideloadNumIt = 16, +}; + +// Data structs for key sideloading test. +OTBN_DECLARE_APP_SYMBOLS(otbn_key_sideload_sca); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s0_l); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s0_h); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s1_l); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_s1_h); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_l); +OTBN_DECLARE_SYMBOL_ADDR(otbn_key_sideload_sca, k_h); +const otbn_app_t kOtbnAppKeySideloadSca = + OTBN_APP_T_INIT(otbn_key_sideload_sca); +static const otbn_addr_t kOtbnAppKeySideloadks0l = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s0_l); +static const otbn_addr_t kOtbnAppKeySideloadks0h = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s0_h); +static const otbn_addr_t kOtbnAppKeySideloadks1l = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s1_l); +static const otbn_addr_t kOtbnAppKeySideloadks1h = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_s1_h); +static const otbn_addr_t kOtbnAppKeySideloadkl = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_l); +static const otbn_addr_t kOtbnAppKeySideloadkh = + OTBN_ADDR_T_INIT(otbn_key_sideload_sca, k_h); + +/** + * 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()); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_init(ujson_t *uj) { + // Configure the entropy complex for OTBN. Set the reseed interval to max + // to avoid a non-constant trigger window. + TRY(pentest_configure_entropy_source_max_reseed_interval()); + + sca_init(kScaTriggerSourceOtbn, kScaPeripheralEntropy | kScaPeripheralIoDiv4 | + kScaPeripheralOtbn | kScaPeripheralCsrng | + kScaPeripheralEdn | kScaPeripheralHmac | + kScaPeripheralKmac); + + // Init the OTBN core. + TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn)); + + // Load p256 keygen from seed app into OTBN. + if (otbn_load_app(kOtbnAppP256KeyFromSeed).value != OTCRYPTO_OK.value) { + return ABORTED(); + } + + // Disable the instruction cache and dummy instructions for better SCA + // measurements. + pentest_configure_cpu(); + + // Read device ID and return to host. + penetrationtest_device_id_t uj_output; + TRY(pentest_read_device_id(uj_output.device_id)); + RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_init_keymgr(ujson_t *uj) { + if (kBootStage != kBootStageOwner) { + TRY(keymgr_testutils_startup(&keymgr, &kmac)); + // Advance to OwnerIntermediateKey state. + TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams)); + TRY(keymgr_testutils_check_state(&keymgr, + kDifKeymgrStateOwnerIntermediateKey)); + LOG_INFO("Keymgr entered OwnerIntKey State"); + } else { + TRY(dif_keymgr_init(mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR), + &keymgr)); + TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey)); + } + + dif_otbn_t otbn; + TRY(dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn)); + + return OK_STATUS(); +} + +status_t handle_otbn_sca_key_sideload_fvsr(ujson_t *uj) { + // Get fixed seed. + penetrationtest_otbn_sca_fixed_seed_t uj_data; + TRY(ujson_deserialize_penetrationtest_otbn_sca_fixed_seed_t(uj, &uj_data)); + + // Key generation parameters. + dif_keymgr_versioned_key_params_t sideload_params[kKeySideloadNumIt]; + + // Generate FvsR values. + bool sample_fixed = true; + for (size_t it = 0; it < kKeySideloadNumIt; it++) { + sideload_params[it].version = 0x0; + sideload_params[it].dest = kDifKeymgrVersionedKeyDestOtbn; + memset(sideload_params[it].salt, 0, sizeof(sideload_params[it].salt)); + if (sample_fixed) { + sideload_params[it].salt[0] = uj_data.fixed_seed; + } else { + sideload_params[it].salt[0] = prng_rand_uint32(); + } + sample_fixed = prng_rand_uint32() & 0x1; + } + + otbn_load_app(kOtbnAppKeySideloadSca); + + uint32_t key_share_0_l[kKeySideloadNumIt], key_share_0_h[kKeySideloadNumIt]; + uint32_t key_share_1_l[16], key_share_1_h[kKeySideloadNumIt]; + uint32_t key_l[kKeySideloadNumIt], key_h[kKeySideloadNumIt]; + + // SCA code target. + for (size_t it = 0; it < kKeySideloadNumIt; it++) { + TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params[it])); + + TRY(dif_otbn_set_ctrl_software_errs_fatal(&otbn, /*enable=*/false)); + + sca_set_trigger_high(); + // Give the trigger time to rise. + asm volatile(NOP30); + otbn_execute(); + otbn_busy_wait_for_done(); + sca_set_trigger_low(); + asm volatile(NOP30); + + otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l[it]); + otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h[it]); + otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l[it]); + otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h[it]); + otbn_dmem_read(1, kOtbnAppKeySideloadkl, &key_l[it]); + otbn_dmem_read(1, kOtbnAppKeySideloadkh, &key_h[it]); + } + + // Write back shares and keys to host. + penetrationtest_otbn_sca_key_t uj_output; + for (size_t it = 0; it < kKeySideloadNumIt; it++) { + uj_output.shares[0] = key_share_0_l[it]; + uj_output.shares[1] = key_share_0_h[it]; + uj_output.shares[2] = key_share_1_l[it]; + uj_output.shares[3] = key_share_1_h[it]; + uj_output.keys[0] = key_l[it]; + uj_output.keys[1] = key_h[it]; + RESP_OK(ujson_serialize_penetrationtest_otbn_sca_key_t, uj, &uj_output); + } + + return OK_STATUS(); +} + +status_t handle_otbn_sca(ujson_t *uj) { + otbn_sca_subcommand_t cmd; + TRY(ujson_deserialize_otbn_sca_subcommand_t(uj, &cmd)); + switch (cmd) { + case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrKeyBatch: + return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(uj); + case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrSeedBatch: + return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(uj); + case kOtbnScaSubcommandEcc256EnMasks: + return handle_otbn_sca_ecc256_en_masks(uj); + case kOtbnScaSubcommandEcc256SetC: + return handle_otbn_sca_ecc256_set_c(uj); + case kOtbnScaSubcommandEcc256SetSeed: + return handle_otbn_sca_ecc256_set_seed(uj); + case kOtbnScaSubcommandInit: + return handle_otbn_sca_init(uj); + case kOtbnScaSubcommandInitKeyMgr: + return handle_otbn_sca_init_keymgr(uj); + case kOtbnScaSubcommandKeySideloadFvsr: + return handle_otbn_sca_key_sideload_fvsr(uj); + default: + LOG_ERROR("Unrecognized OTBN SCA subcommand: %d", cmd); + return INVALID_ARGUMENT(); + } + return OK_STATUS(); +} diff --git a/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.h b/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.h new file mode 100644 index 00000000000000..0026cb94168218 --- /dev/null +++ b/sw/device/tests/penetrationtests/firmware/sca/otbn_sca.h @@ -0,0 +1,103 @@ +// 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_SCA_OTBN_SCA_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_OTBN_SCA_H_ + +#include "sw/device/lib/base/status.h" +#include "sw/device/lib/ujson/ujson.h" + +/** + * Starts the P-256 ECDSA Key Generation from a key in batch mode. + * + * Num_traces fixed vs random keys are generated using the SCA PRNG and + * for each key the key generation operation on OTBN is started. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(ujson_t *uj); + +/** + * Starts the P-256 ECDSA Key Generation from a seed in batch mode. + * + * Num_traces fixed vs random seeds are generated using the SCA PRNG and + * for each seed the key generation operation on OTBN is started. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(ujson_t *uj); + +/** + * Enable or disable masking. + * + * This command handler allows to enable or disable the masking. When masking is + * turned on, a random 320-bit mask is generated for the seed share 1. The mask + * is 0 when masking is turned off. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_ecc256_en_masks(ujson_t *uj); + +/** + * Set the constant C. + * + * This command handler allows the host to set the constant C to generate the + * random key. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_ecc256_set_c(ujson_t *uj); + +/** + * Set the seed share 0. + * + * Allows the host to set the 320-bit seed share 0 that is used for the key + * generation. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_ecc256_set_seed(ujson_t *uj); + +/** + * Initializes the OTBN SCA test on the device. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_init(ujson_t *uj); + +/** + * Initializes the Keymanager used for the OTBN SCA tests. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_init_keymgr(ujson_t *uj); + +/** + * Command handler for the otbn.sca.key_sideload_fvsr test. + * + * Side-load 16 fixed vs. random keys from keymanager to OTBN. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca_key_sideload_fvsr(ujson_t *uj); + +/** + * OTBN SCA command handler. + * + * Command handler for the OTBN SCA command. + * + * @param uj An initialized uJSON context. + * @return OK or error. + */ +status_t handle_otbn_sca(ujson_t *uj); + +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_FIRMWARE_SCA_OTBN_SCA_H_ diff --git a/sw/device/tests/penetrationtests/firmware/sca/sha3_sca.c b/sw/device/tests/penetrationtests/firmware/sca/sha3_sca.c index bb64310bc35ae7..d08b02c9b32fae 100644 --- a/sw/device/tests/penetrationtests/firmware/sca/sha3_sca.c +++ b/sw/device/tests/penetrationtests/firmware/sca/sha3_sca.c @@ -13,7 +13,7 @@ #include "sw/device/lib/ujson/ujson.h" #include "sw/device/sca/lib/prng.h" #include "sw/device/sca/lib/sca.h" -#include "sw/device/tests/penetrationtests/firmware/lib/sca_lib.h" +#include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h" #include "sw/device/tests/penetrationtests/json/sha3_sca_commands.h" #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" @@ -416,11 +416,13 @@ sha3_sca_error_t sha3_serial_absorb(const uint8_t *msg, size_t msg_len) { // configured to start operation 320 cycles after receiving the START and // PROC commands. This allows Ibex to go to sleep in order to not disturb // the capture. - sca_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles, true); + pentest_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles, true, + false); } else { // On the chip, issue a PROCESS command to start operation and put Ibex // into sleep. - sca_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles, true); + pentest_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles, + true, false); } return sha3ScaOk; @@ -603,11 +605,11 @@ status_t handle_sha3_sca_init(ujson_t *uj) { // Disable the instruction cache and dummy instructions for better SCA // measurements. - sca_configure_cpu(); + pentest_configure_cpu(); // Read device ID and return to host. penetrationtest_device_id_t uj_output; - TRY(sca_read_device_id(uj_output.device_id)); + TRY(pentest_read_device_id(uj_output.device_id)); RESP_OK(ujson_serialize_penetrationtest_device_id_t, uj, &uj_output); return OK_STATUS(); diff --git a/sw/device/tests/penetrationtests/json/BUILD b/sw/device/tests/penetrationtests/json/BUILD index 542a5352476935..87979faf0bcbd1 100644 --- a/sw/device/tests/penetrationtests/json/BUILD +++ b/sw/device/tests/penetrationtests/json/BUILD @@ -11,12 +11,14 @@ cc_library( deps = [ ":aes_sca_commands", ":crypto_fi_commands", + ":edn_sca_commands", ":extclk_sca_fi_commands", ":hmac_sca_commands", ":ibex_fi_commands", ":kmac_sca_commands", ":lc_ctrl_fi_commands", ":otbn_fi_commands", + ":otbn_sca_commands", ":otp_fi_commands", ":prng_sca_commands", ":rom_fi_commands", @@ -40,6 +42,13 @@ cc_library( deps = ["//sw/device/lib/ujson"], ) +cc_library( + name = "edn_sca_commands", + srcs = ["edn_sca_commands.c"], + hdrs = ["edn_sca_commands.h"], + deps = ["//sw/device/lib/ujson"], +) + cc_library( name = "extclk_sca_fi_commands", srcs = ["extclk_sca_fi_commands.c"], @@ -89,6 +98,13 @@ cc_library( deps = ["//sw/device/lib/ujson"], ) +cc_library( + name = "otbn_sca_commands", + srcs = ["otbn_sca_commands.c"], + hdrs = ["otbn_sca_commands.h"], + deps = ["//sw/device/lib/ujson"], +) + cc_library( name = "otp_fi_commands", srcs = ["otp_fi_commands.c"], @@ -118,9 +134,9 @@ cc_library( ) cc_library( - name = "sca_lib_commands", - srcs = ["sca_lib_commands.c"], - hdrs = ["sca_lib_commands.h"], + name = "pentest_lib_commands", + srcs = ["pentest_lib_commands.c"], + hdrs = ["pentest_lib_commands.h"], deps = ["//sw/device/lib/ujson"], ) diff --git a/sw/device/tests/penetrationtests/json/aes_sca_commands.h b/sw/device/tests/penetrationtests/json/aes_sca_commands.h index 7192e9f1398efd..95fb27afc99812 100644 --- a/sw/device/tests/penetrationtests/json/aes_sca_commands.h +++ b/sw/device/tests/penetrationtests/json/aes_sca_commands.h @@ -19,47 +19,48 @@ extern "C" { // AES SCA arguments #define AESSCA_SUBCOMMAND(_, value) \ - value(_, Init) \ - value(_, KeySet) \ - value(_, SingleEncrypt) \ + value(_, BatchAlternativeEncrypt) \ value(_, BatchEncrypt) \ - value(_, FvsrKeySet) \ - value(_, FvsrKeyBatchGenerate) \ + value(_, BatchEncryptRandom) \ + value(_, BatchPlaintextSet) \ + value(_, FvsrDataBatchEncrypt) \ value(_, FvsrKeyBatchEncrypt) \ + value(_, FvsrKeyBatchGenerate) \ + value(_, FvsrKeySet) \ value(_, FvsrKeyStartBatchGenerate) \ - value(_, FvsrDataBatchEncrypt) \ + value(_, Init) \ + value(_, KeySet) \ value(_, SeedLfsr) \ value(_, SeedLfsrOrder) \ - value(_, BatchAlternativeEncrypt) \ - value(_, BatchPlaintextSet) + value(_, SingleEncrypt) UJSON_SERDE_ENUM(AesScaSubcommand, aes_sca_subcommand_t, AESSCA_SUBCOMMAND); #define AES_SCA_KEY(field, string) \ field(key, uint8_t, AESSCA_CMD_MAX_KEY_BYTES) \ field(key_length, size_t) -UJSON_SERDE_STRUCT(CryptotestAesScaKey, cryptotest_aes_sca_key_t, AES_SCA_KEY); +UJSON_SERDE_STRUCT(CryptotestAesScaKey, aes_sca_key_t, AES_SCA_KEY); #define AES_SCA_DATA(field, string) \ field(data, uint8_t, AESSCA_CMD_MAX_DATA_BYTES) -UJSON_SERDE_STRUCT(CryptotestAesScaData, cryptotest_aes_sca_data_t, AES_SCA_DATA); +UJSON_SERDE_STRUCT(CryptotestAesScaData, aes_sca_data_t, AES_SCA_DATA); #define AES_SCA_TEXT(field, string) \ field(text, uint8_t, AESSCA_CMD_MAX_DATA_BYTES) \ field(text_length, size_t) -UJSON_SERDE_STRUCT(CryptotestAesScaText, cryptotest_aes_sca_text_t, AES_SCA_TEXT); +UJSON_SERDE_STRUCT(CryptotestAesScaText, aes_sca_text_t, AES_SCA_TEXT); #define AES_SCA_LFSR(field, string) \ field(seed, uint8_t, AESSCA_CMD_MAX_LFSR_BYTES) -UJSON_SERDE_STRUCT(CryptotestAesScaLfsr, cryptotest_aes_sca_lfsr_t, AES_SCA_LFSR); +UJSON_SERDE_STRUCT(CryptotestAesScaLfsr, aes_sca_lfsr_t, AES_SCA_LFSR); #define AES_SCA_CIPHERTEXT(field, string) \ field(ciphertext, uint8_t, AESSCA_CMD_MAX_MSG_BYTES) \ field(ciphertext_length, uint32_t) -UJSON_SERDE_STRUCT(CryptotestAesScaCiphertext, cryptotest_aes_sca_ciphertext_t, AES_SCA_CIPHERTEXT); +UJSON_SERDE_STRUCT(CryptotestAesScaCiphertext, aes_sca_ciphertext_t, AES_SCA_CIPHERTEXT); #define AES_SCA_FPGA_MODE(field, string) \ field(fpga_mode, uint8_t) -UJSON_SERDE_STRUCT(CryptotestAesScaFpgaMode, cryptotest_aes_sca_fpga_mode_t, AES_SCA_FPGA_MODE); +UJSON_SERDE_STRUCT(CryptotestAesScaFpgaMode, aes_sca_fpga_mode_t, AES_SCA_FPGA_MODE); // clang-format on #ifdef __cplusplus diff --git a/sw/device/tests/penetrationtests/json/commands.h b/sw/device/tests/penetrationtests/json/commands.h index 4d84ba6d86e477..147218315bc2e8 100644 --- a/sw/device/tests/penetrationtests/json/commands.h +++ b/sw/device/tests/penetrationtests/json/commands.h @@ -14,6 +14,7 @@ extern "C" { #define COMMAND(_, value) \ value(_, AesSca) \ value(_, CryptoFi) \ + value(_, EdnSca) \ value(_, ExtClkScaFi) \ value(_, HmacSca) \ value(_, IbexFi) \ @@ -21,6 +22,7 @@ extern "C" { value(_, KmacSca) \ value(_, LCCtrlFi) \ value(_, OtbnFi) \ + value(_, OtbnSca) \ value(_, OtpFi) \ value(_, PrngSca) \ value(_, RngFi) \ diff --git a/sw/device/tests/penetrationtests/json/sca_lib_commands.c b/sw/device/tests/penetrationtests/json/edn_sca_commands.c similarity index 86% rename from sw/device/tests/penetrationtests/json/sca_lib_commands.c rename to sw/device/tests/penetrationtests/json/edn_sca_commands.c index f1e2161b776f86..f1b03a63b79d6c 100644 --- a/sw/device/tests/penetrationtests/json/sca_lib_commands.c +++ b/sw/device/tests/penetrationtests/json/edn_sca_commands.c @@ -3,4 +3,4 @@ // SPDX-License-Identifier: Apache-2.0 #define UJSON_SERDE_IMPL 1 -#include "sca_lib_commands.h" +#include "edn_sca_commands.h" diff --git a/sw/device/tests/penetrationtests/json/edn_sca_commands.h b/sw/device/tests/penetrationtests/json/edn_sca_commands.h new file mode 100644 index 00000000000000..b5c7e48635a657 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/edn_sca_commands.h @@ -0,0 +1,45 @@ +// 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_EDN_SCA_COMMANDS_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_EDN_SCA_COMMANDS_H_ +#include "sw/device/lib/ujson/ujson_derive.h" +#ifdef __cplusplus +extern "C" { +#endif + +// clang-format off + +#define EDNSCA_SUBCOMMAND(_, value) \ + value(_, BusData) \ + value(_, BusDataBatchFvsr) \ + value(_, BusDataBatchRandom) \ + value(_, Init) +UJSON_SERDE_ENUM(EdnScaSubcommand, edn_sca_subcommand_t, EDNSCA_SUBCOMMAND); + +#define EDNSCA_RESULT(field, string) \ + field(result, uint32_t) +UJSON_SERDE_STRUCT(EdnScaResult, edn_sca_result_t, EDNSCA_RESULT); + +#define EDNSCA_SEED(field, string) \ + field(init_seed, uint32_t, 12) \ + field(reseed, uint32_t, 12) +UJSON_SERDE_STRUCT(EdnScaSeed, edn_sca_seed_t, EDNSCA_SEED); + +#define EDNSCA_SEED_BATCH(field, string) \ + field(init_seed, uint32_t, 12) \ + field(reseed, uint32_t, 12) \ + field(num_iterations, uint32_t) +UJSON_SERDE_STRUCT(EdnScaSeedBatch, edn_sca_seed_batch_t, EDNSCA_SEED_BATCH); + +#define EDNSCA_BATCH(field, string) \ + field(num_iterations, uint32_t) +UJSON_SERDE_STRUCT(EdnScaBatch, edn_sca_batch_t, EDNSCA_BATCH); + +// clang-format on + +#ifdef __cplusplus +} +#endif +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_EDN_SCA_COMMANDS_H_ diff --git a/sw/device/tests/penetrationtests/json/otbn_sca_commands.c b/sw/device/tests/penetrationtests/json/otbn_sca_commands.c new file mode 100644 index 00000000000000..3647bf0cc04a17 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/otbn_sca_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 "otbn_sca_commands.h" diff --git a/sw/device/tests/penetrationtests/json/otbn_sca_commands.h b/sw/device/tests/penetrationtests/json/otbn_sca_commands.h new file mode 100644 index 00000000000000..896e9a869a94f5 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/otbn_sca_commands.h @@ -0,0 +1,64 @@ +// 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_OTBN_SCA_COMMANDS_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_OTBN_SCA_COMMANDS_H_ +#include "sw/device/lib/ujson/ujson_derive.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define OTBNSCA_CMD_MAX_BATCH_DIGEST_BYTES 40 +#define OTBNSCA_CMD_MAX_SEED_BYTES 40 + +// clang-format off + +// OTBN SCA arguments + +#define OTBNSCA_SUBCOMMAND(_, value) \ + value(_, Ecc256EcdsaKeygenFvsrKeyBatch) \ + value(_, Ecc256EcdsaKeygenFvsrSeedBatch) \ + value(_, Ecc256EnMasks) \ + value(_, Ecc256SetC) \ + value(_, Ecc256SetSeed) \ + value(_, Init) \ + value(_, InitKeyMgr) \ + value(_, KeySideloadFvsr) +UJSON_SERDE_ENUM(OtbnScaSubcommand, otbn_sca_subcommand_t, OTBNSCA_SUBCOMMAND); + +#define OTBN_SCA_EN_MASKS(field, string) \ + field(en_masks, bool) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaEnMasks, penetrationtest_otbn_sca_en_masks_t, OTBN_SCA_EN_MASKS); + +#define OTBN_SCA_NUM_TRACES(field, string) \ + field(num_traces, uint32_t) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaNumTraces, penetrationtest_otbn_sca_num_traces_t, OTBN_SCA_NUM_TRACES); + +#define OTBN_SCA_BATCH_DIGEST(field, string) \ + field(batch_digest, uint8_t, OTBNSCA_CMD_MAX_BATCH_DIGEST_BYTES) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaBatchDigest, penetrationtest_otbn_sca_batch_digest_t, OTBN_SCA_BATCH_DIGEST); + +#define OTBN_SCA_SEED(field, string) \ + field(seed, uint8_t, OTBNSCA_CMD_MAX_SEED_BYTES) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaSeed, penetrationtest_otbn_sca_seed_t, OTBN_SCA_SEED); + +#define OTBN_SCA_CONSTANT(field, string) \ + field(constant, uint8_t, OTBNSCA_CMD_MAX_SEED_BYTES) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaConstant, penetrationtest_otbn_sca_constant_t, OTBN_SCA_CONSTANT); + +#define OTBN_SCA_KEY(field, string) \ + field(shares, uint32_t, 4) \ + field(keys, uint32_t, 2) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaKey, penetrationtest_otbn_sca_key_t, OTBN_SCA_KEY); + +#define OTBN_SCA_FIXED_SEED(field, string) \ + field(fixed_seed, uint32_t) +UJSON_SERDE_STRUCT(PenetrationtestOtbnScaFixedKey, penetrationtest_otbn_sca_fixed_seed_t, OTBN_SCA_FIXED_SEED); + +// clang-format on + +#ifdef __cplusplus +} +#endif +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_OTBN_SCA_COMMANDS_H_ diff --git a/sw/device/tests/penetrationtests/json/pentest_lib_commands.c b/sw/device/tests/penetrationtests/json/pentest_lib_commands.c new file mode 100644 index 00000000000000..5f091557bbf191 --- /dev/null +++ b/sw/device/tests/penetrationtests/json/pentest_lib_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 "pentest_lib_commands.h" diff --git a/sw/device/tests/penetrationtests/json/sca_lib_commands.h b/sw/device/tests/penetrationtests/json/pentest_lib_commands.h similarity index 67% rename from sw/device/tests/penetrationtests/json/sca_lib_commands.h rename to sw/device/tests/penetrationtests/json/pentest_lib_commands.h index bb076509a19e86..71bb991367f366 100644 --- a/sw/device/tests/penetrationtests/json/sca_lib_commands.h +++ b/sw/device/tests/penetrationtests/json/pentest_lib_commands.h @@ -2,8 +2,8 @@ // 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_SCA_LIB_COMMANDS_H_ -#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_SCA_LIB_COMMANDS_H_ +#ifndef OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_PENTEST_LIB_COMMANDS_H_ +#define OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_PENTEST_LIB_COMMANDS_H_ #include "sw/device/lib/ujson/ujson_derive.h" #ifdef __cplusplus extern "C" { @@ -20,4 +20,4 @@ UJSON_SERDE_STRUCT(PenetrationtestDeviceId, penetrationtest_device_id_t, PENETRA #ifdef __cplusplus } #endif -#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_SCA_LIB_COMMANDS_H_ +#endif // OPENTITAN_SW_DEVICE_TESTS_PENETRATIONTESTS_JSON_PENTEST_LIB_COMMANDS_H_ diff --git a/sw/device/tests/penetrationtests/json/rng_fi_commands.h b/sw/device/tests/penetrationtests/json/rng_fi_commands.h index a46ebaae723a03..83d04ea9c74b8c 100644 --- a/sw/device/tests/penetrationtests/json/rng_fi_commands.h +++ b/sw/device/tests/penetrationtests/json/rng_fi_commands.h @@ -14,6 +14,8 @@ extern "C" { #define RNGFI_SUBCOMMAND(_, value) \ value(_, CsrngInit) \ value(_, CsrngBias) \ + value(_, CsrngBiasFWOverride) \ + value(_, CsrngBiasFWOverrideStatic) \ value(_, EdnInit) \ value(_, EdnRespAck) \ value(_, EdnBias) \ @@ -35,6 +37,13 @@ UJSON_SERDE_STRUCT(CryptoFiCsrngMode, crypto_fi_csrng_mode_t, CRYPTOFI_CSRNG_MOD field(err_status, uint32_t) UJSON_SERDE_STRUCT(RngFiCsrngOutput, rng_fi_csrng_output_t, RNGFI_CSRNG_OUTPUT); +#define RNGFI_CSRNG_OV_OUTPUT(field, string) \ + field(res, uint32_t) \ + field(rand, uint32_t, 12) \ + field(alerts, uint32_t, 3) \ + field(err_status, uint32_t) +UJSON_SERDE_STRUCT(RngFiCsrngOvOutput, rng_fi_csrng_ov_output_t, RNGFI_CSRNG_OV_OUTPUT); + #define RNGFI_ENTRBIAS_OUTPUT(field, string) \ field(rand, uint32_t, 32) \ field(alerts, uint32_t, 3) \ @@ -58,6 +67,10 @@ UJSON_SERDE_STRUCT(RngFiEdn, rng_fi_edn_t, RNGFI_EDN); field(disable_health_check, bool) UJSON_SERDE_STRUCT(RngFiFwOverwriteHealt, rng_fi_fw_overwrite_health_t, RNGFI_FWOVERWRITE_HEALTH); +#define RNGFI_SEED(field, string) \ + field(seed, uint32_t, 12) +UJSON_SERDE_STRUCT(RngFiSeed, rng_fi_seed_t, RNGFI_SEED); + // clang-format on #ifdef __cplusplus diff --git a/third_party/open-dice/BUILD b/third_party/open-dice/BUILD new file mode 100644 index 00000000000000..3e8bb41965a28f --- /dev/null +++ b/third_party/open-dice/BUILD @@ -0,0 +1,3 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 diff --git a/third_party/open-dice/BUILD.open-dice.bazel b/third_party/open-dice/BUILD.open-dice.bazel new file mode 100644 index 00000000000000..ae659d0f384d7f --- /dev/null +++ b/third_party/open-dice/BUILD.open-dice.bazel @@ -0,0 +1,18 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "cbor_reader_writer", + srcs = [ + "src/cbor_reader.c", + "src/cbor_writer.c", + ], + hdrs = [ + "include/dice/cbor_reader.h", + "include/dice/cbor_writer.h", + ], + includes = ["include"], + visibility = ["//visibility:public"], +) diff --git a/third_party/open-dice/repos.bzl b/third_party/open-dice/repos.bzl new file mode 100644 index 00000000000000..e5ecb69079e85d --- /dev/null +++ b/third_party/open-dice/repos.bzl @@ -0,0 +1,15 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +load("//rules:repo.bzl", "http_archive_or_local") + +def open_dice_repos(local = None): + http_archive_or_local( + name = "open-dice", + local = local, + build_file = Label("//third_party/open-dice:BUILD.open-dice.bazel"), + strip_prefix = "open-dice-cf3f4cc7a3506a33ee3a437544ef6f40056b3563", + urls = ["https://github.com/google/open-dice/archive/cf3f4cc7a3506a33ee3a437544ef6f40056b3563.zip"], + sha256 = "d7ce830111451afe2a255cac3b750f82e50efe2aaf6bac0b076881c964cfe78d", + )