5 #include "sw/device/tests/penetrationtests/firmware/sca/kmac_sca.h"
8 #include "sw/device/lib/base/status.h"
11 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
12 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
13 #include "sw/device/lib/ujson/ujson.h"
15 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
16 #include "sw/device/tests/penetrationtests/json/commands.h"
17 #include "sw/device/tests/penetrationtests/json/kmac_sca_commands.h"
20 #include "kmac_regs.h"
45 kIbexSha3SleepCycles = 1180,
51 kIbexLoadHashPrefixKeySleepCycles = 300,
56 kIbexLoadHashMessageSleepCycles = 500,
60 kNumBatchOpsMax = 128,
66 static bool fpga_mode =
false;
71 static dif_kmac_t kmac;
92 uint8_t key_fixed[kKeyLength];
100 static bool run_fixed =
false;
105 uint8_t kmac_batch_keys[kNumBatchOpsMax][kKeyLength];
110 uint8_t batch_messages[kNumBatchOpsMax][kMessageLength];
115 static void kmac_block_until_idle(
void) {
119 reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
126 static void kmac_reset(
void) {
129 kmac.base_addr, KMAC_CMD_REG_OFFSET,
131 kmac_block_until_idle();
142 static bool is_state_idle(
void) {
143 uint32_t reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
153 static uint32_t calculate_rate_bits(uint32_t security_level) {
159 return 1600 - 2 * security_level;
171 static kmac_sca_error_t kmac_msg_start(
175 return kmacScaOutOfRange;
182 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128;
183 kmac_operation_state.
r = calculate_rate_bits(128) / 32;
186 kstrength = KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256;
187 kmac_operation_state.
r = calculate_rate_bits(256) / 32;
190 return kmacScaOutOfRange;
192 kmac_operation_state.
offset = 0;
193 kmac_operation_state.
d = l;
194 kmac_operation_state.
append_d =
true;
199 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY128;
202 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY192;
205 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY256;
208 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY384;
211 key_len = KMAC_KEY_LEN_LEN_VALUE_KEY512;
214 return kmacScaOutOfRange;
218 if (!is_state_idle()) {
219 return kmacScaAborted;
224 mmio_region_write32(kmac.base_addr, KMAC_KEY_LEN_REG_OFFSET, key_len);
225 for (
int i = 0; i <
ARRAYSIZE(k->share0); ++i) {
227 const uint32_t a = pentest_next_lfsr(32, kPentestLfsrMasking);
228 mmio_region_write32(kmac.base_addr,
229 KMAC_KEY_SHARE0_0_REG_OFFSET +
230 (ptrdiff_t)i * (ptrdiff_t)
sizeof(uint32_t),
232 mmio_region_write32(kmac.base_addr,
233 KMAC_KEY_SHARE1_0_REG_OFFSET +
234 (ptrdiff_t)i * (ptrdiff_t)
sizeof(uint32_t),
240 mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
245 KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
246 mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
247 mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
252 uint32_t prefix_regs[11] = {
259 if (s != NULL && s->
length >= 3) {
261 prefix_regs[1] &= 0xFFFF;
262 prefix_regs[1] |= (uint32_t)((uint8_t)s->
buffer[0]) << 16;
263 prefix_regs[1] |= (uint32_t)((uint8_t)s->
buffer[1]) << 24;
269 mmio_region_write32(base, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
270 mmio_region_write32(base, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
271 mmio_region_write32(base, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
272 mmio_region_write32(base, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
273 mmio_region_write32(base, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
274 mmio_region_write32(base, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
275 mmio_region_write32(base, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
276 mmio_region_write32(base, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
277 mmio_region_write32(base, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
278 mmio_region_write32(base, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
279 mmio_region_write32(base, KMAC_PREFIX_10_REG_OFFSET, prefix_regs[10]);
294 static kmac_sca_error_t kmac_msg_write(
const void *msg,
size_t msg_len,
297 if (processed != NULL) {
301 if (msg == NULL && msg_len != 0) {
302 return kmacScaOutOfRange;
306 if (kmac_operation_state.
r == 0) {
307 return kmacScaAborted;
314 for (
size_t i = 0; i < msg_len; ++i) {
315 mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
316 ((
const uint8_t *)msg)[i]);
319 if (processed != NULL) {
320 *processed = msg_len;
328 uint32_t d = kmac_operation_state.
d * 32;
329 int out_len = 1 + (d > 0xFF) + (d > 0xFFFF) + (d > 0xFFFFFF);
330 int shift = (out_len - 1) * 8;
332 mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
333 (uint8_t)(d >> shift));
336 mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET, (uint8_t)d);
337 mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET,
349 static void kmac_process_cmd(
void) {
353 mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
361 static void kmac_start_cmd(
void) {
365 mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
373 static void kmac_start_process_cmd(
void) {
387 static void kmac_msg_done(
void) {
391 reg = mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
404 kmac_sca_error_t kmac_get_digest(uint32_t *out,
size_t len) {
405 if (out == NULL && len != 0) {
406 return kmacScaOutOfRange;
411 size_t remaining = kmac_operation_state.
r - kmac_operation_state.
offset;
412 if (kmac_operation_state.
d != 0 &&
413 kmac_operation_state.
d < kmac_operation_state.
r) {
414 remaining = kmac_operation_state.
d - kmac_operation_state.
offset;
423 return kmacScaAborted;
427 KMAC_STATE_REG_OFFSET +
428 (ptrdiff_t)kmac_operation_state.
offset * (ptrdiff_t)
sizeof(uint32_t);
429 for (
size_t i = 0; i < n; ++i) {
431 uint32_t share0 = mmio_region_read32(kmac.base_addr, offset);
434 *out++ = share0 ^ share1;
435 offset +=
sizeof(uint32_t);
437 kmac_operation_state.
offset += n;
450 cryptotest_kmac_sca_fpga_mode_t uj_data;
451 TRY(ujson_deserialize_cryptotest_kmac_sca_fpga_mode_t(uj, &uj_data));
452 if (uj_data.fpga_mode == 0x01) {
456 penetrationtest_cpuctrl_t uj_cpuctrl;
457 TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_cpuctrl));
460 pentest_init(kPentestTriggerSourceKmac,
461 kPentestPeripheralIoDiv4 | kPentestPeripheralKmac);
467 .entropy_seed = {0xb153e3fe, 0x09596819, 0x3e85a6e8, 0xb6dcdaba,
468 0x50dc409c, 0x11e1ebd1},
476 kmac_block_until_idle();
479 penetrationtest_device_info_t uj_output;
480 TRY(pentest_configure_cpu(
481 uj_cpuctrl.icache_disable, uj_cpuctrl.dummy_instr_disable,
482 uj_cpuctrl.enable_jittery_clock, uj_cpuctrl.enable_sram_readback,
483 &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
484 &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
485 &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
488 TRY(pentest_read_device_id(uj_output.device_id));
489 RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
509 cryptotest_kmac_sca_key_t uj_key;
510 TRY(ujson_deserialize_cryptotest_kmac_sca_key_t(uj, &uj_key));
512 if (uj_key.key_length != kKeyLength) {
513 return OUT_OF_RANGE();
519 memcpy(kmac_key.share0, uj_key.key, kKeyLength);
547 static kmac_sca_error_t sha3_ujson_absorb(
const uint8_t *msg,
size_t msg_len) {
551 return kmacScaAborted;
554 if (fpga_mode ==
false) {
557 pentest_call_and_sleep(kmac_start_cmd, kIbexLoadHashPrefixKeySleepCycles,
562 if (kmac_msg_write(msg, msg_len, NULL) != kmacScaOk) {
563 return kmacScaAborted;
572 pentest_call_and_sleep(kmac_start_process_cmd, kIbexSha3SleepCycles,
false,
577 pentest_call_and_sleep(kmac_process_cmd, kIbexLoadHashMessageSleepCycles,
598 cryptotest_kmac_sca_msg_t uj_msg;
599 TRY(ujson_deserialize_cryptotest_kmac_sca_msg_t(uj, &uj_msg));
601 if (uj_msg.msg_length != kMessageLength) {
602 return OUT_OF_RANGE();
606 pentest_set_trigger_high();
607 if (sha3_ujson_absorb(uj_msg.msg, uj_msg.msg_length) != kmacScaOk) {
610 pentest_set_trigger_low();
616 uint32_t out[kDigestLength];
617 if (kmac_get_digest(out, kDigestLength) != kmacScaOk) {
621 cryptotest_kmac_sca_batch_digest_t uj_output;
622 memcpy(uj_output.batch_digest, (uint8_t *)out, kDigestLength * 4);
623 RESP_OK(ujson_serialize_cryptotest_kmac_sca_batch_digest_t, uj, &uj_output);
642 cryptotest_kmac_sca_key_t uj_key;
643 TRY(ujson_deserialize_cryptotest_kmac_sca_key_t(uj, &uj_key));
645 if (uj_key.key_length != kKeyLength) {
646 return OUT_OF_RANGE();
649 memcpy(key_fixed, uj_key.key, uj_key.key_length);
665 penetrationtest_num_enc_t uj_data;
666 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
668 uint32_t out[kDigestLength];
669 uint32_t batch_digest[kDigestLength];
671 for (uint32_t j = 0; j < kDigestLength; ++j) {
675 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
677 memcpy(kmac_batch_keys[i], key_fixed, kKeyLength);
682 run_fixed = batch_messages[i][0] & 0x1;
685 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
687 memcpy(kmac_key.share0, kmac_batch_keys[i], kKeyLength);
689 pentest_set_trigger_high();
690 if (sha3_ujson_absorb(batch_messages[i], kMessageLength) != kmacScaOk) {
693 pentest_set_trigger_low();
696 if (kmac_get_digest(out, kDigestLength) != kmacScaOk) {
703 for (uint32_t j = 0; j < kDigestLength; ++j) {
704 batch_digest[j] ^= out[j];
708 cryptotest_kmac_sca_batch_digest_t uj_output;
709 memcpy(uj_output.batch_digest, (uint8_t *)batch_digest, kDigestLength * 4);
710 RESP_OK(ujson_serialize_cryptotest_kmac_sca_batch_digest_t, uj, &uj_output);
726 cryptotest_kmac_sca_lfsr_t uj_lfsr_data;
727 TRY(ujson_deserialize_cryptotest_kmac_sca_lfsr_t(uj, &uj_lfsr_data));
728 pentest_seed_lfsr(
read_32(uj_lfsr_data.seed), kPentestLfsrMasking);
741 kmac_sca_subcommand_t cmd;
742 TRY(ujson_deserialize_kmac_sca_subcommand_t(uj, &cmd));
744 case kKmacScaSubcommandInit:
745 return handle_kmac_pentest_init(uj);
746 case kKmacScaSubcommandSetKey:
747 return handle_kmac_sca_set_key(uj);
748 case kKmacScaSubcommandSingleAbsorb:
749 return handle_kmac_sca_single_absorb(uj);
750 case kKmacScaSubcommandBatch:
751 return handle_kmac_sca_batch(uj);
752 case kKmacScaSubcommandFixedKeySet:
753 return handle_kmac_sca_fixed_key_set(uj);
754 case kKmacScaSubcommandSeedLfsr:
755 return handle_kmac_pentest_seed_lfsr(uj);
757 LOG_ERROR(
"Unrecognized KMAC SCA FI subcommand: %d", cmd);
758 return INVALID_ARGUMENT();