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 #define NOP1 "addi x0, x0, 0\n"
31 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
32 #define NOP30 NOP10 NOP10 NOP10
33 #define NOP100 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10
36 static bool key_manager_init;
38 #define NOP1 "addi x0, x0, 0\n"
39 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
40 #define NOP100 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10 NOP10
46 static volatile uint32_t sram_main_buffer[8];
47 static volatile uint32_t sram_main_buffer_batch[256];
50 static inline
void init_registers(uint32_t val0, uint32_t val1, uint32_t val2,
51 uint32_t val3, uint32_t val4, uint32_t val5) {
52 asm volatile(
"mv x5, %0" : :
"r"(val0) :
"x5");
53 asm volatile(
"mv x18, %0" : :
"r"(val1) :
"x18");
54 asm volatile(
"mv x19, %0" : :
"r"(val2) :
"x19");
55 asm volatile(
"mv x20, %0" : :
"r"(val3) :
"x20");
56 asm volatile(
"mv x21, %0" : :
"r"(val4) :
"x21");
57 asm volatile(
"mv x22, %0" : :
"r"(val5) :
"x22");
58 asm volatile(
"mv x6, x0" : : :
"x6");
59 asm volatile(
"mv x7, x0" : : :
"x7");
60 asm volatile(
"mv x28, x0" : : :
"x28");
61 asm volatile(
"mv x29, x0" : : :
"x29");
62 asm volatile(
"mv x30, x0" : : :
"x30");
63 asm volatile(
"mv x31, x0" : : :
"x31");
68 static inline void move_bw_registers(
void) {
69 asm volatile(
"mv x6, x5" : : :
"x6");
70 asm volatile(
"mv x7, x18" : : :
"x7");
71 asm volatile(
"mv x28, x19" : : :
"x28");
72 asm volatile(
"mv x29, x20" : : :
"x29");
73 asm volatile(
"mv x30, x21" : : :
"x30");
74 asm volatile(
"mv x31, x22" : : :
"x31");
79 static inline void copy_to_registers(uint32_t val0, uint32_t val1,
80 uint32_t val2, uint32_t val3,
81 uint32_t val4, uint32_t val5,
83 asm volatile(
"mv x5, %0" : :
"r"(val0) :
"x5");
84 asm volatile(
"mv x6, %0" : :
"r"(val1) :
"x6");
85 asm volatile(
"mv x7, %0" : :
"r"(val2) :
"x7");
86 asm volatile(
"mv x28, %0" : :
"r"(val3) :
"x28");
87 asm volatile(
"mv x29, %0" : :
"r"(val4) :
"x29");
88 asm volatile(
"mv x30, %0" : :
"r"(val5) :
"x30");
89 asm volatile(
"mv x31, %0" : :
"r"(val6) :
"x31");
95 static void generate_fvsr(
size_t num_iterations, uint32_t fixed_data,
97 bool sample_fixed =
true;
98 for (
size_t i = 0; i < num_iterations; i++) {
100 values[i] = fixed_data;
109 static void generate_random(
size_t num_iterations, uint32_t values[]) {
110 for (
size_t i = 0; i < num_iterations; i++) {
116 penetrationtest_cpuctrl_t uj_data;
117 TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
120 pentest_select_trigger_type(kPentestTriggerTypeSw);
124 pentest_init(kPentestTriggerSourceAes,
125 kPentestPeripheralIoDiv4 | kPentestPeripheralKmac);
128 penetrationtest_device_info_t uj_output;
129 TRY(pentest_configure_cpu(
130 uj_data.icache_disable, uj_data.dummy_instr_disable,
131 uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
132 &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
133 &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
134 &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
137 key_manager_init =
false;
140 TRY(pentest_read_device_id(uj_output.device_id));
141 RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
147 ibex_sca_salt_t uj_data;
148 TRY(ujson_deserialize_ibex_sca_salt_t(uj, &uj_data));
150 if (!key_manager_init) {
152 TRY(keymgr_testutils_startup(&keymgr, &kmac));
156 TRY(keymgr_testutils_generate_identity(
161 TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
162 TRY(keymgr_testutils_check_state(&keymgr,
164 key_manager_init =
true;
169 for (
int i = 0; i < 8; i++) {
170 sideload_params.
salt[i] = uj_data.salt[i];
174 pentest_set_trigger_high();
175 TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params));
176 pentest_set_trigger_low();
183 ibex_sca_key_t uj_key;
184 for (
int i = 0; i < 8; i++) {
185 uj_key.share0[i] = key.value[0][i];
186 uj_key.share1[i] = key.value[1][i];
188 RESP_OK(ujson_serialize_ibex_sca_key_t, uj, &uj_key);
194 ibex_sca_test_data_t uj_data;
195 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
197 copy_to_registers(uj_data.data[0], uj_data.data[1], uj_data.data[2],
198 uj_data.data[3], uj_data.data[4], uj_data.data[5], 0);
201 pentest_set_trigger_high();
205 asm volatile(
"mv x28, x5");
206 asm volatile(
"mv x29, x6");
207 asm volatile(
"mv x30, x7");
208 pentest_set_trigger_low();
211 ibex_sca_result_t uj_output;
212 uj_output.result = 0;
213 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
219 ibex_sca_test_fvsr_t uj_data;
220 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
221 TRY_CHECK(uj_data.num_iterations < 256);
224 uint32_t values[256];
225 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
227 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
229 copy_to_registers(0, 0, 0, values[i], values[i], values[i], values[i]);
232 pentest_set_trigger_high();
236 asm volatile(
"mv x5, x28");
237 asm volatile(
"mv x6, x29");
238 asm volatile(
"mv x7, x30");
239 pentest_set_trigger_low();
243 ibex_sca_result_t uj_output;
244 uj_output.result = values[uj_data.num_iterations - 1];
245 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
249 status_t handle_ibex_sca_register_file_read_batch_random(
ujson_t *uj) {
251 ibex_sca_batch_t uj_data;
252 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
253 TRY_CHECK(uj_data.num_iterations < 256);
256 uint32_t values[256];
257 generate_random(uj_data.num_iterations, values);
259 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
261 copy_to_registers(0, 0, 0, values[i], values[i], values[i], values[i]);
264 pentest_set_trigger_high();
268 asm volatile(
"mv x5, x28");
269 asm volatile(
"mv x6, x29");
270 asm volatile(
"mv x7, x30");
271 pentest_set_trigger_low();
275 ibex_sca_result_t uj_output;
276 uj_output.result = values[uj_data.num_iterations - 1];
277 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
283 ibex_sca_test_data_t uj_data;
284 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
287 pentest_set_trigger_high();
291 copy_to_registers(uj_data.data[0], uj_data.data[1], uj_data.data[2],
292 uj_data.data[3], uj_data.data[4], uj_data.data[5],
294 pentest_set_trigger_low();
297 ibex_sca_result_t uj_output;
298 uj_output.result = 0;
299 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
305 ibex_sca_test_fvsr_t uj_data;
306 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
307 TRY_CHECK(uj_data.num_iterations < MAX_BATCH_SIZE);
310 uint32_t values[MAX_BATCH_SIZE];
311 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
314 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
315 pentest_set_trigger_high();
316 init_registers(values[i], values[i], values[i], values[i], values[i],
322 pentest_set_trigger_low();
327 ibex_sca_result_t uj_output;
328 uj_output.result = values[uj_data.num_iterations - 1];
329 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
333 status_t handle_ibex_sca_register_file_write_batch_random(
ujson_t *uj) {
335 ibex_sca_batch_t uj_data;
336 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
337 TRY_CHECK(uj_data.num_iterations < MAX_BATCH_SIZE);
340 uint32_t values[MAX_BATCH_SIZE * DEST_REGS_CNT];
341 generate_random(uj_data.num_iterations * DEST_REGS_CNT, values);
344 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
345 pentest_set_trigger_high();
346 init_registers(values[i * DEST_REGS_CNT], values[i * DEST_REGS_CNT + 1],
347 values[i * DEST_REGS_CNT + 2], values[i * DEST_REGS_CNT + 3],
348 values[i * DEST_REGS_CNT + 4],
349 values[i * DEST_REGS_CNT + 5]);
354 pentest_set_trigger_low();
359 ibex_sca_result_t uj_output;
360 uj_output.result = values[uj_data.num_iterations * DEST_REGS_CNT - 1];
361 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
367 ibex_sca_test_data_t uj_data;
368 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
371 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
376 for (
int i = 0; i < 8; i++) {
377 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
381 uint32_t read_data[8];
384 pentest_set_trigger_high();
388 for (
int i = 0; i < 8; i++) {
389 read_data[i] = mmio_region_read32(sram_region_main_addr,
390 i * (ptrdiff_t)
sizeof(uint32_t));
392 pentest_set_trigger_low();
394 ibex_sca_result_t uj_output;
395 uj_output.result = 0;
396 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
402 ibex_sca_test_fvsr_t uj_data;
403 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
404 TRY_CHECK(uj_data.num_iterations < 256);
407 uint32_t values[256];
408 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
411 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
416 for (
int i = 0; i < uj_data.num_iterations; i++) {
417 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
421 uint32_t read_data[256];
425 for (
int i = 0; i < uj_data.num_iterations; i++) {
426 pentest_set_trigger_high();
429 read_data[i] = mmio_region_read32(sram_region_main_addr,
430 i * (ptrdiff_t)
sizeof(uint32_t));
431 pentest_set_trigger_low();
436 ibex_sca_result_t uj_output;
437 uj_output.result = read_data[uj_data.num_iterations - 1];
438 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
444 ibex_sca_test_fvsr_t uj_data;
445 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
446 TRY_CHECK(uj_data.num_iterations < 256);
449 uint32_t values[256];
450 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
453 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
457 uint32_t read_data[256];
461 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
462 mmio_region_write32(sram_region_main_addr, 0, values[i]);
464 pentest_set_trigger_high();
467 read_data[i] = mmio_region_read32(sram_region_main_addr, 0);
468 pentest_set_trigger_low();
472 ibex_sca_result_t uj_output;
473 uj_output.result = read_data[uj_data.num_iterations - 1];
474 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
480 ibex_sca_batch_t uj_data;
481 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
482 TRY_CHECK(uj_data.num_iterations < 256);
485 uint32_t values[256];
486 generate_random(uj_data.num_iterations, values);
489 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
494 for (
int i = 0; i < uj_data.num_iterations; i++) {
495 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
499 uint32_t read_data[256];
504 for (
int i = 0; i < uj_data.num_iterations; i++) {
505 pentest_set_trigger_high();
508 read_data[i] = mmio_region_read32(sram_region_main_addr,
509 i * (ptrdiff_t)
sizeof(uint32_t));
510 pentest_set_trigger_low();
515 ibex_sca_result_t uj_output;
516 uj_output.result = read_data[uj_data.num_iterations - 1];
517 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
521 status_t handle_ibex_sca_tl_read_batch_random_fix_address(
ujson_t *uj) {
523 ibex_sca_batch_t uj_data;
524 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
525 TRY_CHECK(uj_data.num_iterations < 256);
528 uint32_t values[256];
529 generate_random(uj_data.num_iterations, values);
532 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
536 uint32_t read_data[256];
539 for (
size_t i = 0; i < uj_data.num_iterations; i++) {
540 mmio_region_write32(sram_region_main_addr, 0, values[i]);
542 pentest_set_trigger_high();
545 read_data[i] = mmio_region_read32(sram_region_main_addr, 0);
546 pentest_set_trigger_low();
550 ibex_sca_result_t uj_output;
551 uj_output.result = read_data[uj_data.num_iterations - 1];
552 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
558 ibex_sca_test_data_t uj_data;
559 TRY(ujson_deserialize_ibex_sca_test_data_t(uj, &uj_data));
562 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
567 pentest_set_trigger_high();
571 for (
int i = 0; i < 8; i++) {
572 mmio_region_write32(sram_region_main_addr, i * (ptrdiff_t)
sizeof(uint32_t),
575 pentest_set_trigger_low();
578 ibex_sca_result_t uj_output;
579 uj_output.result = 0;
580 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
586 ibex_sca_test_fvsr_t uj_data;
587 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
588 TRY_CHECK(uj_data.num_iterations < 256);
591 uint32_t values[256];
592 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
595 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
600 for (
int it = 0; it < uj_data.num_iterations; it++) {
601 pentest_set_trigger_high();
605 mmio_region_write32(sram_region_main_addr, it * (ptrdiff_t)
sizeof(uint32_t),
607 pentest_set_trigger_low();
612 ibex_sca_result_t uj_output;
613 uj_output.result = values[uj_data.num_iterations - 1];
614 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
618 status_t handle_ibex_sca_tl_write_batch_fvsr_fix_address(
ujson_t *uj) {
620 ibex_sca_test_fvsr_t uj_data;
621 TRY(ujson_deserialize_ibex_sca_test_fvsr_t(uj, &uj_data));
622 TRY_CHECK(uj_data.num_iterations < 256);
625 uint32_t values[256];
626 generate_fvsr(uj_data.num_iterations, uj_data.fixed_data, values);
629 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
634 for (
int it = 0; it < uj_data.num_iterations; it++) {
635 pentest_set_trigger_high();
639 mmio_region_write32(sram_region_main_addr, 0, values[it]);
640 pentest_set_trigger_low();
645 ibex_sca_result_t uj_output;
646 uj_output.result = values[uj_data.num_iterations - 1];
647 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
653 ibex_sca_batch_t uj_data;
654 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
655 TRY_CHECK(uj_data.num_iterations < 256);
658 uint32_t values[256];
659 generate_random(uj_data.num_iterations, values);
662 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
667 for (
int it = 0; it < uj_data.num_iterations; it++) {
668 pentest_set_trigger_high();
672 mmio_region_write32(sram_region_main_addr, it * (ptrdiff_t)
sizeof(uint32_t),
674 pentest_set_trigger_low();
679 ibex_sca_result_t uj_output;
680 uj_output.result = values[uj_data.num_iterations - 1];
681 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
685 status_t handle_ibex_sca_tl_write_batch_random_fix_address(
ujson_t *uj) {
687 ibex_sca_batch_t uj_data;
688 TRY(ujson_deserialize_ibex_sca_batch_t(uj, &uj_data));
689 TRY_CHECK(uj_data.num_iterations < 256);
692 uint32_t values[256];
693 generate_random(uj_data.num_iterations, values);
696 uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer_batch;
701 for (
int it = 0; it < uj_data.num_iterations; it++) {
702 pentest_set_trigger_high();
706 mmio_region_write32(sram_region_main_addr, 0, values[it]);
707 pentest_set_trigger_low();
712 ibex_sca_result_t uj_output;
713 uj_output.result = values[uj_data.num_iterations - 1];
714 RESP_OK(ujson_serialize_ibex_sca_result_t, uj, &uj_output);
719 ibex_sca_subcommand_t cmd;
720 TRY(ujson_deserialize_ibex_sca_subcommand_t(uj, &cmd));
722 case kIbexScaSubcommandInit:
723 return handle_ibex_pentest_init(uj);
724 case kIbexScaSubcommandKeySideloading:
725 return handle_ibex_sca_key_sideloading(uj);
726 case kIbexScaSubcommandRFRead:
727 return handle_ibex_sca_register_file_read(uj);
728 case kIbexScaSubcommandRFReadBatchFvsr:
729 return handle_ibex_sca_register_file_read_batch_fvsr(uj);
730 case kIbexScaSubcommandRFReadBatchRandom:
731 return handle_ibex_sca_register_file_read_batch_random(uj);
732 case kIbexScaSubcommandRFWrite:
733 return handle_ibex_sca_register_file_write(uj);
734 case kIbexScaSubcommandRFWriteBatchFvsr:
735 return handle_ibex_sca_register_file_write_batch_fvsr(uj);
736 case kIbexScaSubcommandRFWriteBatchRandom:
737 return handle_ibex_sca_register_file_write_batch_random(uj);
738 case kIbexScaSubcommandTLRead:
739 return handle_ibex_sca_tl_read(uj);
740 case kIbexScaSubcommandTLReadBatchFvsr:
741 return handle_ibex_sca_tl_read_batch_fvsr(uj);
742 case kIbexScaSubcommandTLReadBatchFvsrFixAddress:
743 return handle_ibex_sca_tl_read_batch_fvsr_fix_address(uj);
744 case kIbexScaSubcommandTLReadBatchRandom:
745 return handle_ibex_sca_tl_read_batch_random(uj);
746 case kIbexScaSubcommandTLReadBatchRandomFixAddress:
747 return handle_ibex_sca_tl_read_batch_random_fix_address(uj);
748 case kIbexScaSubcommandTLWrite:
749 return handle_ibex_sca_tl_write(uj);
750 case kIbexScaSubcommandTLWriteBatchFvsr:
751 return handle_ibex_sca_tl_write_batch_fvsr(uj);
752 case kIbexScaSubcommandTLWriteBatchFvsrFixAddress:
753 return handle_ibex_sca_tl_write_batch_fvsr_fix_address(uj);
754 case kIbexScaSubcommandTLWriteBatchRandom:
755 return handle_ibex_sca_tl_write_batch_random(uj);
756 case kIbexScaSubcommandTLWriteBatchRandomFixAddress:
757 return handle_ibex_sca_tl_write_batch_random_fix_address(uj);
759 LOG_ERROR(
"Unrecognized IBEX SCA subcommand: %d", cmd);
760 return INVALID_ARGUMENT();