Skip to content

Commit

Permalink
[pentest] Add CSRNG Bias FI tests
Browse files Browse the repository at this point in the history
This commit adds the following two new FI tests:
- CsrngBiasFWOverride
- CsrngBiasFWOverrideStatic

These tests can be used to target the entropy source
and they allow to monitor the data over the CSRNG
interface.

Signed-off-by: Pascal Nasahl <nasahlpa@lowrisc.org>
  • Loading branch information
nasahlpa authored and vogelpi committed Sep 16, 2024
1 parent 7547f40 commit 0d00352
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
105 changes: 105 additions & 0 deletions sw/device/tests/penetrationtests/firmware/fi/rng_fi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -131,6 +138,24 @@ 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 = pentest_get_triggered_alerts();
Expand Down Expand Up @@ -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 = sca_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 = sca_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
Expand Down Expand Up @@ -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:
Expand Down
15 changes: 15 additions & 0 deletions sw/device/tests/penetrationtests/firmware/fi/rng_fi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
13 changes: 13 additions & 0 deletions sw/device/tests/penetrationtests/json/rng_fi_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ extern "C" {
#define RNGFI_SUBCOMMAND(_, value) \
value(_, CsrngInit) \
value(_, CsrngBias) \
value(_, CsrngBiasFWOverride) \
value(_, CsrngBiasFWOverrideStatic) \
value(_, EdnInit) \
value(_, EdnRespAck) \
value(_, EdnBias) \
Expand All @@ -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) \
Expand All @@ -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
Expand Down

0 comments on commit 0d00352

Please sign in to comment.