Skip to content

Commit

Permalink
[pentest] Add ECC256 Keygen SCA test
Browse files Browse the repository at this point in the history
This commit adds the ECC256 key generation side-channel
penetration test to the codebase.

The host code is located in lowRISC/ot-sca#347

Signed-off-by: Pascal Nasahl <[email protected]>
  • Loading branch information
nasahlpa committed Apr 17, 2024
1 parent abeb556 commit ac21c4f
Show file tree
Hide file tree
Showing 23 changed files with 816 additions and 16 deletions.
2 changes: 1 addition & 1 deletion sw/device/sca/aes_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ static void aes_encrypt(const uint8_t *plaintext, size_t plaintext_len) {
// Using the SecAesStartTriggerDelay hardware parameter, the AES unit is
// configured to start operation 40 cycles after receiving the start trigger.
// This allows Ibex to go to sleep in order to not disturb the capture.
sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, false);
sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, false, false);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion sw/device/sca/kmac_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ static void sha3_serial_absorb(const uint8_t *msg, size_t msg_len) {
// configured to start operation 40 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_msg_proc, kIbexSha3SleepCycles, false);
sca_call_and_sleep(kmac_msg_proc, kIbexSha3SleepCycles, false, false);
}

/**
Expand Down
1 change: 1 addition & 0 deletions sw/device/sca/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ cc_library(
"//sw/device/lib/arch:device",
"//sw/device/lib/base:bitfield",
"//sw/device/lib/base:macros",
"//sw/device/lib/crypto/drivers:otbn",
"//sw/device/lib/dif:clkmgr",
"//sw/device/lib/dif:csrng",
"//sw/device/lib/dif:edn",
Expand Down
11 changes: 8 additions & 3 deletions sw/device/sca/lib/sca.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/bitfield.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/crypto/drivers/otbn.h"
#include "sw/device/lib/dif/dif_clkmgr.h"
#include "sw/device/lib/dif/dif_entropy_src.h"
#include "sw/device/lib/dif/dif_gpio.h"
Expand Down Expand Up @@ -310,7 +311,7 @@ void sca_set_trigger_low(void) {
}

void sca_call_and_sleep(sca_callee callee, uint32_t sleep_cycles,
bool sw_trigger) {
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
Expand All @@ -335,12 +336,16 @@ void sca_call_and_sleep(sca_callee callee, uint32_t sleep_cycles,

callee();

wait_for_interrupt();

if (otbn) {
otbn_busy_wait_for_done();
}

if (sw_trigger) {
sca_set_trigger_low();
}

wait_for_interrupt();

// 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));
Expand Down
3 changes: 2 additions & 1 deletion sw/device/sca/lib/sca.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@ typedef void (*sca_callee)(void);
* @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.
*/
void sca_call_and_sleep(sca_callee callee, uint32_t sleep_cycles,
bool sw_trigger);
bool sw_trigger, bool otbn);

/**
* Seeds the software LFSR usable e.g. for key masking.
Expand Down
2 changes: 1 addition & 1 deletion sw/device/sca/otbn_vertical/ecc256_keygen_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ static void p256_run_keygen(uint32_t mode, const uint32_t *share0,

// Execute program.
sca_set_trigger_high();
sca_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles, false);
sca_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles, false, false);
SS_CHECK_STATUS_OK(otbn_busy_wait_for_done());
sca_set_trigger_low();
}
Expand Down
2 changes: 1 addition & 1 deletion sw/device/sca/otbn_vertical/ecc256_modinv_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static void p256_run_modinv(uint32_t *k0, uint32_t *k1) {

// Execute program.
sca_set_trigger_high();
sca_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles, false);
sca_call_and_sleep(otbn_manual_trigger, kIbexOtbnSleepCycles, false, false);
otbn_busy_wait_for_done();
sca_set_trigger_low();
}
Expand Down
2 changes: 1 addition & 1 deletion sw/device/sca/sha3_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ static void sha3_serial_absorb(const uint8_t *msg, size_t msg_len) {
// configured to start operation 40 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_msg_proc, kIbexSha3SleepCycles, true);
sca_call_and_sleep(kmac_msg_proc, kIbexSha3SleepCycles, true, false);
}

/**
Expand Down
47 changes: 47 additions & 0 deletions sw/device/tests/penetrationtests/firmware/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,46 @@ cc_library(
],
)

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/json:otbn_sca_commands",
"//sw/otbn/crypto:p256_key_from_seed_sca",
],
)

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/impl:status",
"//sw/device/lib/runtime:log",
"//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:sca_lib",
"//sw/device/tests/penetrationtests/json:otbn_sca_commands",
],
)

cc_library(
name = "ibex_fi",
srcs = [
Expand Down Expand Up @@ -176,11 +216,17 @@ cc_library(
hdrs = ["sca_lib.h"],
deps = [
"//sw/device/lib/base:csr",
"//sw/device/lib/base:mmio",
"//sw/device/lib/dif:alert_handler",
"//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:rstmgr",
"//sw/device/lib/dif:rv_core_ibex",
"//sw/device/lib/dif:rv_plic",
"//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/ujson",
Expand Down Expand Up @@ -227,6 +273,7 @@ FIRMWARE_DEPS = [
":ibex_fi",
":ibex_sca",
":kmac_sca",
":otbn_sca",
":otbn_fi",
":prng_sca",
":sha3_sca",
Expand Down
4 changes: 2 additions & 2 deletions sw/device/tests/penetrationtests/firmware/aes_sca.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ 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);
sca_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);
sca_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles, true, false);
}

return aesScaOk;
Expand Down
Loading

0 comments on commit ac21c4f

Please sign in to comment.