5 #include "sw/device/tests/penetrationtests/firmware/sca/ibex_sca.h"
8 #include "sw/device/lib/base/status.h"
12 #include "sw/device/lib/testing/keymgr_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
14 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
15 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
16 #include "sw/device/lib/ujson/ujson.h"
18 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
19 #include "sw/device/tests/penetrationtests/json/ibex_sca_commands.h"
23 static dif_keymgr_t keymgr;
24 static dif_kmac_t kmac;
26 #define MAX_BATCH_SIZE 256
27 #define DEST_REGS_CNT 6
30 static bool key_manager_init;
36 static volatile uint32_t sram_main_buffer[8];
37 static volatile uint32_t sram_main_buffer_batch[256];
40 static inline
void init_registers(uint32_t val0, uint32_t val1, uint32_t val2,
41 uint32_t val3, uint32_t val4, uint32_t val5) {
42 asm volatile(
"mv x5, %0" : :
"r"(val0) :
"x5");
43 asm volatile(
"mv x18, %0" : :
"r"(val1) :
"x18");
44 asm volatile(
"mv x19, %0" : :
"r"(val2) :
"x19");
45 asm volatile(
"mv x20, %0" : :
"r"(val3) :
"x20");
46 asm volatile(
"mv x21, %0" : :
"r"(val4) :
"x21");
47 asm volatile(
"mv x22, %0" : :
"r"(val5) :
"x22");
48 asm volatile(
"mv x6, x0" : : :
"x6");
49 asm volatile(
"mv x7, x0" : : :
"x7");
50 asm volatile(
"mv x28, x0" : : :
"x28");
51 asm volatile(
"mv x29, x0" : : :
"x29");
52 asm volatile(
"mv x30, x0" : : :
"x30");
53 asm volatile(
"mv x31, x0" : : :
"x31");
58 static inline void move_bw_registers(
void) {
59 asm volatile(
"mv x6, x5" : : :
"x6");
60 asm volatile(
"mv x7, x18" : : :
"x7");
61 asm volatile(
"mv x28, x19" : : :
"x28");
62 asm volatile(
"mv x29, x20" : : :
"x29");
63 asm volatile(
"mv x30, x21" : : :
"x30");
64 asm volatile(
"mv x31, x22" : : :
"x31");
69 static inline void copy_to_registers(uint32_t val0, uint32_t val1,
70 uint32_t val2, uint32_t val3,
71 uint32_t val4, uint32_t val5,
73 asm volatile(
"mv x5, %0" : :
"r"(val0) :
"x5");
74 asm volatile(
"mv x6, %0" : :
"r"(val1) :
"x6");
75 asm volatile(
"mv x7, %0" : :
"r"(val2) :
"x7");
76 asm volatile(
"mv x28, %0" : :
"r"(val3) :
"x28");
77 asm volatile(
"mv x29, %0" : :
"r"(val4) :
"x29");
78 asm volatile(
"mv x30, %0" : :
"r"(val5) :
"x30");
79 asm volatile(
"mv x31, %0" : :
"r"(val6) :
"x31");
85 static void generate_fvsr(
size_t num_iterations, uint32_t fixed_data,
87 bool sample_fixed =
true;
88 for (
size_t i = 0; i < num_iterations; i++) {
90 values[i] = fixed_data;
99 static void generate_random(
size_t num_iterations, uint32_t values[]) {
100 for (
size_t i = 0; i < num_iterations; i++) {
106 penetrationtest_cpuctrl_t uj_data;
107 TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
110 pentest_select_trigger_type(kPentestTriggerTypeSw);
114 pentest_init(kPentestTriggerSourceAes,
115 kPentestPeripheralIoDiv4 | kPentestPeripheralKmac);
118 penetrationtest_device_info_t uj_output;
119 TRY(pentest_configure_cpu(
120 uj_data.icache_disable, uj_data.dummy_instr_disable,
121 uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
122 &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
123 &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
124 &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
127 key_manager_init =
false;
130 TRY(pentest_read_device_id(uj_output.device_id));
131 RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
137 ibex_sca_salt_t uj_data;
138 TRY(ujson_deserialize_ibex_sca_salt_t(uj, &uj_data));
140 if (!key_manager_init) {
142 TRY(keymgr_testutils_startup(&keymgr, &kmac));
146 TRY(keymgr_testutils_generate_identity(
151 TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
152 TRY(keymgr_testutils_check_state(&keymgr,
154 key_manager_init =
true;
159 for (
int i = 0; i < 8; i++) {
160 sideload_params.
salt[i] = uj_data.salt[i];
164 pentest_set_trigger_high();
165 TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params));
166 pentest_set_trigger_low();
173 ibex_sca_key_t uj_key;
174 for (
int i = 0; i < 8; i++) {
175 uj_key.share0[i] = key.value[0][i];
176 uj_key.share1[i] = key.value[1][i];
178 RESP_OK(ujson_serialize_ibex_sca_key_t, uj, &uj_key);
184 ibex_sca_test_data_t uj_data;
185 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
187 copy_to_registers(uj_data.data[0], uj_data.data[1], uj_data.data[2],
188 uj_data.data[3], uj_data.data[4], uj_data.data[5], 0);
191 pentest_set_trigger_high();
195 asm volatile(
"mv x28, x5");
196 asm volatile(
"mv x29, x6");
197 asm volatile(
"mv x30, x7");
198 pentest_set_trigger_low();
201 ibex_sca_result_t uj_output;
202 uj_output.result = 0;
203 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
209 ibex_sca_test_fvsr_t uj_data;
210 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
211 TRY_CHECK(uj_data.num_iterations < 256);
214 uint32_t values[256];
215 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
217 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
219 copy_to_registers(0, 0, 0, values[i], values[i], values[i], values[i]);
222 pentest_set_trigger_high();
226 asm volatile(
"mv x5, x28");
227 asm volatile(
"mv x6, x29");
228 asm volatile(
"mv x7, x30");
229 pentest_set_trigger_low();
233 ibex_sca_result_t uj_output;
234 uj_output.result = values[uj_data.num_iterations - 1];
235 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
239 status_t handle_ibex_sca_register_file_read_batch_random(
ujson_t *uj) {
241 ibex_sca_batch_t uj_data;
242 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
243 TRY_CHECK(uj_data.num_iterations < 256);
246 uint32_t values[256];
247 generate_random(uj_data.num_iterations, values);
249 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
251 copy_to_registers(0, 0, 0, values[i], values[i], values[i], values[i]);
254 pentest_set_trigger_high();
258 asm volatile(
"mv x5, x28");
259 asm volatile(
"mv x6, x29");
260 asm volatile(
"mv x7, x30");
261 pentest_set_trigger_low();
265 ibex_sca_result_t uj_output;
266 uj_output.result = values[uj_data.num_iterations - 1];
267 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
273 ibex_sca_test_data_t uj_data;
274 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
277 pentest_set_trigger_high();
281 copy_to_registers(uj_data.data[0], uj_data.data[1], uj_data.data[2],
282 uj_data.data[3], uj_data.data[4], uj_data.data[5],
284 pentest_set_trigger_low();
287 ibex_sca_result_t uj_output;
288 uj_output.result = 0;
289 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
295 ibex_sca_test_fvsr_t uj_data;
296 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
297 TRY_CHECK(uj_data.num_iterations < MAX_BATCH_SIZE);
300 uint32_t values[MAX_BATCH_SIZE];
301 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
304 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
305 pentest_set_trigger_high();
306 init_registers(values[i], values[i], values[i], values[i], values[i],
312 pentest_set_trigger_low();
317 ibex_sca_result_t uj_output;
318 uj_output.result = values[uj_data.num_iterations - 1];
319 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
323 status_t handle_ibex_sca_register_file_write_batch_random(
ujson_t *uj) {
325 ibex_sca_batch_t uj_data;
326 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
327 TRY_CHECK(uj_data.num_iterations < MAX_BATCH_SIZE);
330 uint32_t values[MAX_BATCH_SIZE * DEST_REGS_CNT];
331 generate_random(uj_data.num_iterations * DEST_REGS_CNT, values);
334 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
335 pentest_set_trigger_high();
336 init_registers(values[i * DEST_REGS_CNT], values[i * DEST_REGS_CNT + 1],
337 values[i * DEST_REGS_CNT + 2], values[i * DEST_REGS_CNT + 3],
338 values[i * DEST_REGS_CNT + 4],
339 values[i * DEST_REGS_CNT + 5]);
344 pentest_set_trigger_low();
349 ibex_sca_result_t uj_output;
350 uj_output.result = values[uj_data.num_iterations * DEST_REGS_CNT - 1];
351 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
357 ibex_sca_test_data_t uj_data;
358 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
361 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
366 for (
int i = 0; i < 8; i++) {
367 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
371 uint32_t read_data[8];
374 pentest_set_trigger_high();
378 for (
int i = 0; i < 8; i++) {
379 read_data[i] = mmio_region_read32(sram_region_main_addr,
380 i * (ptrdiff_t)
sizeof(uint32_t));
382 pentest_set_trigger_low();
384 ibex_sca_result_t uj_output;
385 uj_output.result = 0;
386 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
392 ibex_sca_test_fvsr_t uj_data;
393 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
394 TRY_CHECK(uj_data.num_iterations < 256);
397 uint32_t values[256];
398 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
401 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
406 for (
int i = 0; i < uj_data.num_iterations; i++) {
407 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
411 uint32_t read_data[256];
415 for (
int i = 0; i < uj_data.num_iterations; i++) {
416 pentest_set_trigger_high();
419 read_data[i] = mmio_region_read32(sram_region_main_addr,
420 i * (ptrdiff_t)
sizeof(uint32_t));
421 pentest_set_trigger_low();
426 ibex_sca_result_t uj_output;
427 uj_output.result = read_data[uj_data.num_iterations - 1];
428 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
434 ibex_sca_test_fvsr_t uj_data;
435 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
436 TRY_CHECK(uj_data.num_iterations < 256);
439 uint32_t values[256];
440 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
443 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
447 uint32_t read_data[256];
451 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
452 mmio_region_write32(sram_region_main_addr, 0, values[i]);
454 pentest_set_trigger_high();
457 read_data[i] = mmio_region_read32(sram_region_main_addr, 0);
458 pentest_set_trigger_low();
462 ibex_sca_result_t uj_output;
463 uj_output.result = read_data[uj_data.num_iterations - 1];
464 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
470 ibex_sca_batch_t uj_data;
471 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
472 TRY_CHECK(uj_data.num_iterations < 256);
475 uint32_t values[256];
476 generate_random(uj_data.num_iterations, values);
479 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
484 for (
int i = 0; i < uj_data.num_iterations; i++) {
485 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
489 uint32_t read_data[256];
494 for (
int i = 0; i < uj_data.num_iterations; i++) {
495 pentest_set_trigger_high();
498 read_data[i] = mmio_region_read32(sram_region_main_addr,
499 i * (ptrdiff_t)
sizeof(uint32_t));
500 pentest_set_trigger_low();
505 ibex_sca_result_t uj_output;
506 uj_output.result = read_data[uj_data.num_iterations - 1];
507 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
511 status_t handle_ibex_sca_tl_read_batch_random_fix_address(
ujson_t *uj) {
513 ibex_sca_batch_t uj_data;
514 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
515 TRY_CHECK(uj_data.num_iterations < 256);
518 uint32_t values[256];
519 generate_random(uj_data.num_iterations, values);
522 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
526 uint32_t read_data[256];
529 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
530 mmio_region_write32(sram_region_main_addr, 0, values[i]);
532 pentest_set_trigger_high();
535 read_data[i] = mmio_region_read32(sram_region_main_addr, 0);
536 pentest_set_trigger_low();
540 ibex_sca_result_t uj_output;
541 uj_output.result = read_data[uj_data.num_iterations - 1];
542 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
548 ibex_sca_test_data_t uj_data;
549 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
552 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
557 pentest_set_trigger_high();
561 for (
int i = 0; i < 8; i++) {
562 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
565 pentest_set_trigger_low();
568 ibex_sca_result_t uj_output;
569 uj_output.result = 0;
570 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
576 ibex_sca_test_fvsr_t uj_data;
577 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
578 TRY_CHECK(uj_data.num_iterations < 256);
581 uint32_t values[256];
582 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
585 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
590 for (
int it = 0; it < uj_data.num_iterations; it++) {
591 pentest_set_trigger_high();
595 mmio_region_write32(sram_region_main_addr, it * (ptrdiff_t)
sizeof(uint32_t),
597 pentest_set_trigger_low();
602 ibex_sca_result_t uj_output;
603 uj_output.result = values[uj_data.num_iterations - 1];
604 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
608 status_t handle_ibex_sca_tl_write_batch_fvsr_fix_address(
ujson_t *uj) {
610 ibex_sca_test_fvsr_t uj_data;
611 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
612 TRY_CHECK(uj_data.num_iterations < 256);
615 uint32_t values[256];
616 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
619 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
624 for (
int it = 0; it < uj_data.num_iterations; it++) {
625 pentest_set_trigger_high();
629 mmio_region_write32(sram_region_main_addr, 0, values[it]);
630 pentest_set_trigger_low();
635 ibex_sca_result_t uj_output;
636 uj_output.result = values[uj_data.num_iterations - 1];
637 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
643 ibex_sca_batch_t uj_data;
644 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
645 TRY_CHECK(uj_data.num_iterations < 256);
648 uint32_t values[256];
649 generate_random(uj_data.num_iterations, values);
652 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
657 for (
int it = 0; it < uj_data.num_iterations; it++) {
658 pentest_set_trigger_high();
662 mmio_region_write32(sram_region_main_addr, it * (ptrdiff_t)
sizeof(uint32_t),
664 pentest_set_trigger_low();
669 ibex_sca_result_t uj_output;
670 uj_output.result = values[uj_data.num_iterations - 1];
671 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
675 status_t handle_ibex_sca_tl_write_batch_random_fix_address(
ujson_t *uj) {
677 ibex_sca_batch_t uj_data;
678 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
679 TRY_CHECK(uj_data.num_iterations < 256);
682 uint32_t values[256];
683 generate_random(uj_data.num_iterations, values);
686 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
691 for (
int it = 0; it < uj_data.num_iterations; it++) {
692 pentest_set_trigger_high();
696 mmio_region_write32(sram_region_main_addr, 0, values[it]);
697 pentest_set_trigger_low();
702 ibex_sca_result_t uj_output;
703 uj_output.result = values[uj_data.num_iterations - 1];
704 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
709 ibex_sca_subcommand_t cmd;
710 TRY(ujson_deserialize_ibex_sca_subcommand_t(uj, &cmd));
712 case kIbexScaSubcommandInit:
713 return handle_ibex_pentest_init(uj);
714 case kIbexScaSubcommandKeySideloading:
715 return handle_ibex_sca_key_sideloading(uj);
716 case kIbexScaSubcommandRFRead:
717 return handle_ibex_sca_register_file_read(uj);
718 case kIbexScaSubcommandRFReadBatchFvsr:
719 return handle_ibex_sca_register_file_read_batch_fvsr(uj);
720 case kIbexScaSubcommandRFReadBatchRandom:
721 return handle_ibex_sca_register_file_read_batch_random(uj);
722 case kIbexScaSubcommandRFWrite:
723 return handle_ibex_sca_register_file_write(uj);
724 case kIbexScaSubcommandRFWriteBatchFvsr:
725 return handle_ibex_sca_register_file_write_batch_fvsr(uj);
726 case kIbexScaSubcommandRFWriteBatchRandom:
727 return handle_ibex_sca_register_file_write_batch_random(uj);
728 case kIbexScaSubcommandTLRead:
729 return handle_ibex_sca_tl_read(uj);
730 case kIbexScaSubcommandTLReadBatchFvsr:
731 return handle_ibex_sca_tl_read_batch_fvsr(uj);
732 case kIbexScaSubcommandTLReadBatchFvsrFixAddress:
733 return handle_ibex_sca_tl_read_batch_fvsr_fix_address(uj);
734 case kIbexScaSubcommandTLReadBatchRandom:
735 return handle_ibex_sca_tl_read_batch_random(uj);
736 case kIbexScaSubcommandTLReadBatchRandomFixAddress:
737 return handle_ibex_sca_tl_read_batch_random_fix_address(uj);
738 case kIbexScaSubcommandTLWrite:
739 return handle_ibex_sca_tl_write(uj);
740 case kIbexScaSubcommandTLWriteBatchFvsr:
741 return handle_ibex_sca_tl_write_batch_fvsr(uj);
742 case kIbexScaSubcommandTLWriteBatchFvsrFixAddress:
743 return handle_ibex_sca_tl_write_batch_fvsr_fix_address(uj);
744 case kIbexScaSubcommandTLWriteBatchRandom:
745 return handle_ibex_sca_tl_write_batch_random(uj);
746 case kIbexScaSubcommandTLWriteBatchRandomFixAddress:
747 return handle_ibex_sca_tl_write_batch_random_fix_address(uj);
749 LOG_ERROR(
"Unrecognized IBEX SCA subcommand: %d", cmd);
750 return INVALID_ARGUMENT();