5 #include "sw/device/tests/penetrationtests/firmware/sca/otbn_sca.h"
7 #include "ecc256_keygen_sca.h"
10 #include "sw/device/lib/base/status.h"
11 #include "sw/device/lib/crypto/drivers/keymgr.h"
12 #include "sw/device/lib/crypto/impl/keyblob.h"
13 #include "sw/device/lib/crypto/impl/status.h"
16 #include "sw/device/lib/testing/entropy_testutils.h"
17 #include "sw/device/lib/testing/keymgr_testutils.h"
18 #include "sw/device/lib/testing/test_framework/ottf_test_config.h"
19 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
20 #include "sw/device/lib/ujson/ujson.h"
22 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
23 #include "sw/device/tests/penetrationtests/json/otbn_sca_commands.h"
26 #include "otbn_regs.h"
28 static dif_otbn_t otbn;
29 static dif_keymgr_t keymgr;
30 static dif_kmac_t kmac;
33 #define NOP1 "addi x0, x0, 0\n"
34 #define NOP10 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1 NOP1
35 #define NOP30 NOP10 NOP10 NOP10
38 kKeySideloadNumIt = 16,
43 kEcc256NumBytes = 256 / 8,
48 kEcc256NumWords = kEcc256NumBytes /
sizeof(uint32_t),
52 kNumBatchOpsMax = 256,
65 static const otbn_addr_t kOtbnAppKeySideloadks0l =
67 static const otbn_addr_t kOtbnAppKeySideloadks0h =
69 static const otbn_addr_t kOtbnAppKeySideloadks1l =
71 static const otbn_addr_t kOtbnAppKeySideloadks1h =
73 static const otbn_addr_t kOtbnAppKeySideloadkl =
75 static const otbn_addr_t kOtbnAppKeySideloadkh =
90 static const otbn_addr_t kOtbnVarRsaModulus =
OTBN_ADDR_T_INIT(rsa, modulus);
110 static const otbn_addr_t kOtbnVarMode =
OTBN_ADDR_T_INIT(p256_ecdsa_sca, mode);
111 static const otbn_addr_t kOtbnVarMsg =
OTBN_ADDR_T_INIT(p256_ecdsa_sca, msg);
126 TRY(otbn_dmem_sec_wipe());
127 TRY(otbn_imem_sec_wipe());
142 void gen_mask_data(uint32_t *dest_array,
bool mask_en,
size_t len) {
144 for (
size_t j = 0; j < len; ++j) {
148 memset(dest_array, 0, len *
sizeof(dest_array[0]));
163 void gen_fvsr_data(uint32_t *dest_array,
bool fixed, uint32_t *src_fixed_array,
166 memcpy(dest_array, src_fixed_array, len *
sizeof(src_fixed_array[0]));
168 for (
size_t j = 0; j < len; ++j) {
190 static status_t p256_ecdsa_sign(
const uint32_t *msg,
191 const uint32_t *private_key_d,
192 uint32_t *signature_r, uint32_t *signature_s,
196 TRY(otbn_dmem_write(1, &mode, kOtbnVarMode));
198 TRY(otbn_dmem_write(kEcc256NumWords, msg, kOtbnVarMsg));
200 TRY(otbn_dmem_write(kEcc256NumWords, private_key_d, kOtbnVarD0));
201 TRY(otbn_dmem_write(kEcc256NumWords, private_key_d + kEcc256NumWords,
204 TRY(otbn_dmem_write(kEcc256NumWords, k, kOtbnVarK0));
205 TRY(otbn_dmem_write(kEcc256NumWords, k + kEcc256NumWords, kOtbnVarK1));
208 pentest_set_trigger_high();
212 otbn_busy_wait_for_done();
213 pentest_set_trigger_low();
216 TRY(otbn_dmem_read(kEcc256NumWords, kOtbnVarR, signature_r));
217 TRY(otbn_dmem_read(kEcc256NumWords, kOtbnVarS, signature_s));
224 penetrationtest_otbn_sca_en_masks_t uj_data_masks;
227 penetrationtest_otbn_sca_ecdsa_p256_sign_t uj_data;
228 TRY(ujson_deserialize_penetrationtest_otbn_sca_ecdsa_p256_sign_t(uj,
232 uint32_t ecc256_private_key_d1[kEcc256NumWords];
233 memset(ecc256_private_key_d1, 0,
sizeof(ecc256_private_key_d1));
235 if (uj_data_masks.en_masks) {
236 for (
size_t j = 0; j < kEcc256NumWords; j++) {
242 uint32_t ecc256_secret_k1[kEcc256NumWords];
243 memset(ecc256_secret_k1, 0,
sizeof(ecc256_secret_k1));
245 if (uj_data_masks.en_masks) {
246 for (
size_t j = 0; j < kEcc256NumWords; j++) {
252 uint32_t ecc256_private_key_d[2 * kEcc256NumWords];
253 memset(ecc256_private_key_d, 0,
sizeof(ecc256_private_key_d));
254 memcpy(ecc256_private_key_d, uj_data.d0,
sizeof(uj_data.d0));
255 memcpy(ecc256_private_key_d + kEcc256NumWords, ecc256_private_key_d1,
256 sizeof(ecc256_private_key_d1));
259 uint32_t ecc256_secret_k[2 * kEcc256NumWords];
260 memset(ecc256_secret_k, 0,
sizeof(ecc256_secret_k));
261 memcpy(ecc256_secret_k, uj_data.k0,
sizeof(uj_data.k0));
262 memcpy(ecc256_secret_k + kEcc256NumWords, ecc256_secret_k1,
263 sizeof(ecc256_secret_k1));
265 otbn_load_app(kOtbnAppP256Ecdsa);
268 uint32_t ecc256_signature_r[kEcc256NumWords];
269 uint32_t ecc256_signature_s[kEcc256NumWords];
272 p256_ecdsa_sign(uj_data.msg, ecc256_private_key_d, ecc256_signature_r,
273 ecc256_signature_s, ecc256_secret_k);
276 penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
277 memcpy(uj_output.r, ecc256_signature_r,
sizeof(ecc256_signature_r));
278 memcpy(uj_output.s, ecc256_signature_s,
sizeof(ecc256_signature_s));
279 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
290 penetrationtest_otbn_sca_num_traces_t uj_data_num_traces;
291 TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(
292 uj, &uj_data_num_traces));
294 if (uj_data_num_traces.num_traces > kNumBatchOpsMax) {
295 return OUT_OF_RANGE();
299 penetrationtest_otbn_sca_en_masks_t uj_data_masks;
300 TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj,
304 uint32_t ecc256_message_batch[kNumBatchOpsMax][kEcc256NumWords];
306 uint32_t ecc256_private_key_d0_batch[kNumBatchOpsMax][kEcc256NumWords];
307 uint32_t ecc256_private_key_d1_batch[kNumBatchOpsMax][kEcc256NumWords];
308 uint32_t ecc256_private_key_d_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
310 uint32_t ecc256_secret_key_k0_batch[kNumBatchOpsMax][kEcc256NumWords];
311 uint32_t ecc256_secret_key_k1_batch[kNumBatchOpsMax][kEcc256NumWords];
312 uint32_t ecc256_secret_key_k_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
315 for (
size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
317 gen_fvsr_data(ecc256_message_batch[i],
false, NULL, kEcc256NumWords);
320 gen_fvsr_data(ecc256_private_key_d0_batch[i],
false, NULL, kEcc256NumWords);
323 gen_mask_data(ecc256_private_key_d1_batch[i], uj_data_masks.en_masks,
327 memcpy(ecc256_private_key_d_batch[i], ecc256_private_key_d0_batch[i],
328 sizeof(ecc256_private_key_d0_batch[i]));
329 memcpy(ecc256_private_key_d_batch[i] + kEcc256NumWords,
330 ecc256_private_key_d1_batch[i],
331 sizeof(ecc256_private_key_d1_batch[i]));
334 gen_fvsr_data(ecc256_secret_key_k0_batch[i],
false, NULL, kEcc256NumWords);
337 gen_mask_data(ecc256_secret_key_k1_batch[i], uj_data_masks.en_masks,
341 memcpy(ecc256_secret_key_k_batch[i], ecc256_secret_key_k0_batch[i],
342 sizeof(ecc256_secret_key_k0_batch[i]));
343 memcpy(ecc256_secret_key_k_batch[i] + kEcc256NumWords,
344 ecc256_secret_key_k1_batch[i],
345 sizeof(ecc256_secret_key_k1_batch[i]));
349 uint32_t ecc256_signature_r[kEcc256NumWords];
350 uint32_t ecc256_signature_s[kEcc256NumWords];
352 for (
size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
353 otbn_load_app(kOtbnAppP256Ecdsa);
356 p256_ecdsa_sign(ecc256_message_batch[i], ecc256_private_key_d_batch[i],
357 ecc256_signature_r, ecc256_signature_s,
358 ecc256_secret_key_k_batch[i]);
362 penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
363 memcpy(uj_output.r, ecc256_signature_r,
sizeof(ecc256_signature_r));
364 memcpy(uj_output.s, ecc256_signature_s,
sizeof(ecc256_signature_s));
365 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
376 penetrationtest_otbn_sca_num_traces_t uj_data_num_traces;
377 TRY(ujson_deserialize_penetrationtest_otbn_sca_num_traces_t(
378 uj, &uj_data_num_traces));
380 if (uj_data_num_traces.num_traces > kNumBatchOpsMax) {
381 return OUT_OF_RANGE();
385 penetrationtest_otbn_sca_en_masks_t uj_data_masks;
386 TRY(ujson_deserialize_penetrationtest_otbn_sca_en_masks_t(uj,
390 penetrationtest_otbn_sca_ecdsa_p256_sign_t uj_data;
391 TRY(ujson_deserialize_penetrationtest_otbn_sca_ecdsa_p256_sign_t(uj,
394 uint32_t ecc256_message_batch[kNumBatchOpsMax][kEcc256NumWords];
396 uint32_t ecc256_private_key_d0_batch[kNumBatchOpsMax][kEcc256NumWords];
397 uint32_t ecc256_private_key_d1_batch[kNumBatchOpsMax][kEcc256NumWords];
398 uint32_t ecc256_private_key_d_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
400 uint32_t ecc256_secret_key_k0_batch[kNumBatchOpsMax][kEcc256NumWords];
401 uint32_t ecc256_secret_key_k1_batch[kNumBatchOpsMax][kEcc256NumWords];
402 uint32_t ecc256_secret_key_k_batch[kNumBatchOpsMax][2 * kEcc256NumWords];
406 bool run_fixed =
true;
407 for (
size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
409 gen_fvsr_data(ecc256_message_batch[i], run_fixed, uj_data.msg,
414 gen_fvsr_data(ecc256_private_key_d0_batch[i], run_fixed, uj_data.d0,
419 gen_mask_data(ecc256_private_key_d1_batch[i], uj_data_masks.en_masks,
423 memcpy(ecc256_private_key_d_batch[i], ecc256_private_key_d0_batch[i],
424 sizeof(ecc256_private_key_d0_batch[i]));
425 memcpy(ecc256_private_key_d_batch[i] + kEcc256NumWords,
426 ecc256_private_key_d1_batch[i],
427 sizeof(ecc256_private_key_d1_batch[i]));
432 gen_fvsr_data(ecc256_secret_key_k0_batch[i], run_fixed, uj_data.k0,
436 gen_mask_data(ecc256_secret_key_k1_batch[i], uj_data_masks.en_masks,
440 memcpy(ecc256_secret_key_k_batch[i], ecc256_secret_key_k0_batch[i],
441 sizeof(ecc256_secret_key_k0_batch[i]));
442 memcpy(ecc256_secret_key_k_batch[i] + kEcc256NumWords,
443 ecc256_secret_key_k1_batch[i],
444 sizeof(ecc256_secret_key_k1_batch[i]));
450 uint32_t ecc256_signature_r[kEcc256NumWords];
451 uint32_t ecc256_signature_s[kEcc256NumWords];
453 for (
size_t i = 0; i < uj_data_num_traces.num_traces; ++i) {
454 otbn_load_app(kOtbnAppP256Ecdsa);
457 p256_ecdsa_sign(uj_data.msg, ecc256_private_key_d_batch[i],
458 ecc256_signature_r, ecc256_signature_s,
459 ecc256_secret_key_k_batch[i]);
463 penetrationtest_otbn_sca_ecdsa_p256_signature_t uj_output;
464 memcpy(uj_output.r, ecc256_signature_r,
sizeof(ecc256_signature_r));
465 memcpy(uj_output.s, ecc256_signature_s,
sizeof(ecc256_signature_s));
466 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_ecdsa_p256_signature_t, uj,
476 penetrationtest_cpuctrl_t uj_data;
477 TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_data));
481 TRY(pentest_configure_entropy_source_max_reseed_interval());
483 pentest_init(kPentestTriggerSourceOtbn,
484 kPentestPeripheralEntropy | kPentestPeripheralIoDiv4 |
485 kPentestPeripheralOtbn | kPentestPeripheralCsrng |
486 kPentestPeripheralEdn | kPentestPeripheralHmac |
487 kPentestPeripheralKmac);
493 if (otbn_load_app(kOtbnAppP256KeyFromSeed).value != OTCRYPTO_OK.value) {
498 penetrationtest_device_info_t uj_output;
499 TRY(pentest_configure_cpu(
500 uj_data.icache_disable, uj_data.dummy_instr_disable,
501 uj_data.enable_jittery_clock, uj_data.enable_sram_readback,
502 &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
503 &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
504 &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
507 TRY(pentest_read_device_id(uj_output.device_id));
508 RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
515 TRY(keymgr_testutils_startup(&keymgr, &kmac));
517 TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
518 TRY(keymgr_testutils_check_state(&keymgr,
520 LOG_INFO(
"Keymgr entered OwnerIntKey State");
535 penetrationtest_otbn_sca_big_num_t uj_data;
536 TRY(ujson_deserialize_penetrationtest_otbn_sca_big_num_t(uj, &uj_data));
543 static const otbn_app_t kOtbnAppInsnCarryFlag =
545 static const otbn_addr_t kOtbnVarInsnCarryFlagBigNum =
547 static const otbn_addr_t kOtbnVarInsnCarryFlagBigNumOut =
551 otbn_load_app(kOtbnAppInsnCarryFlag);
553 sizeof(uj_data.big_num)));
555 pentest_set_trigger_high();
557 otbn_busy_wait_for_done();
558 pentest_set_trigger_low();
560 penetrationtest_otbn_sca_big_num_t uj_output;
561 memset(uj_output.big_num, 0,
sizeof(uj_output.big_num));
563 uj_output.big_num,
sizeof(uj_output.big_num)));
565 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_big_num_t, uj, &uj_output);
572 penetrationtest_otbn_sca_fixed_seed_t uj_data;
573 TRY(ujson_deserialize_penetrationtest_otbn_sca_fixed_seed_t(uj, &uj_data));
579 bool sample_fixed =
true;
580 for (
size_t it = 0; it < kKeySideloadNumIt; it++) {
581 sideload_params[it].
version = 0x0;
583 memset(sideload_params[it].salt, 0,
sizeof(sideload_params[it].salt));
585 sideload_params[it].
salt[0] = uj_data.fixed_seed;
592 otbn_load_app(kOtbnAppKeySideloadSca);
594 uint32_t key_share_0_l[kKeySideloadNumIt], key_share_0_h[kKeySideloadNumIt];
595 uint32_t key_share_1_l[16], key_share_1_h[kKeySideloadNumIt];
596 uint32_t key_l[kKeySideloadNumIt], key_h[kKeySideloadNumIt];
599 for (
size_t it = 0; it < kKeySideloadNumIt; it++) {
600 TRY(keymgr_testutils_generate_versioned_key(&keymgr, sideload_params[it]));
604 pentest_set_trigger_high();
608 otbn_busy_wait_for_done();
609 pentest_set_trigger_low();
612 otbn_dmem_read(1, kOtbnAppKeySideloadks0l, &key_share_0_l[it]);
613 otbn_dmem_read(1, kOtbnAppKeySideloadks0h, &key_share_0_h[it]);
614 otbn_dmem_read(1, kOtbnAppKeySideloadks1l, &key_share_1_l[it]);
615 otbn_dmem_read(1, kOtbnAppKeySideloadks1h, &key_share_1_h[it]);
616 otbn_dmem_read(1, kOtbnAppKeySideloadkl, &key_l[it]);
617 otbn_dmem_read(1, kOtbnAppKeySideloadkh, &key_h[it]);
621 penetrationtest_otbn_sca_key_t uj_output;
622 for (
size_t it = 0; it < kKeySideloadNumIt; it++) {
623 uj_output.shares[0] = key_share_0_l[it];
624 uj_output.shares[1] = key_share_0_h[it];
625 uj_output.shares[2] = key_share_1_l[it];
626 uj_output.shares[3] = key_share_1_h[it];
627 uj_output.keys[0] = key_l[it];
628 uj_output.keys[1] = key_h[it];
629 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_key_t, uj, &uj_output);
637 penetrationtest_otbn_sca_rsa512_dec_t uj_data;
638 TRY(ujson_deserialize_penetrationtest_otbn_sca_rsa512_dec_t(uj, &uj_data));
640 otbn_load_app(kOtbnAppRsa);
644 uint32_t n_limbs = 2;
650 sizeof(uj_data.mod)));
652 sizeof(uj_data.exp)));
654 sizeof(uj_data.msg)));
656 pentest_set_trigger_high();
660 otbn_busy_wait_for_done();
661 pentest_set_trigger_low();
664 penetrationtest_otbn_sca_rsa512_dec_out_t uj_output;
666 sizeof(uj_output.out)));
667 RESP_OK(ujson_serialize_penetrationtest_otbn_sca_rsa512_dec_out_t, uj,
673 otbn_sca_subcommand_t cmd;
674 TRY(ujson_deserialize_otbn_sca_subcommand_t(uj, &cmd));
676 case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrKeyBatch:
677 return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_key_batch(uj);
678 case kOtbnScaSubcommandEcc256EcdsaKeygenFvsrSeedBatch:
679 return handle_otbn_sca_ecc256_ecdsa_keygen_fvsr_seed_batch(uj);
680 case kOtbnScaSubcommandEcc256EnMasks:
681 return handle_otbn_sca_ecc256_en_masks(uj);
682 case kOtbnScaSubcommandEcc256SetC:
683 return handle_otbn_sca_ecc256_set_c(uj);
684 case kOtbnScaSubcommandEcc256SetSeed:
685 return handle_otbn_sca_ecc256_set_seed(uj);
686 case kOtbnScaSubcommandEcdsaP256Sign:
687 return handle_otbn_sca_ecdsa_p256_sign(uj);
688 case kOtbnScaSubcommandEcdsaP256SignBatch:
689 return handle_otbn_sca_ecdsa_p256_sign_batch(uj);
690 case kOtbnScaSubcommandEcdsaP256SignFvsrBatch:
691 return handle_otbn_sca_ecdsa_p256_sign_fvsr_batch(uj);
692 case kOtbnScaSubcommandInit:
693 return handle_otbn_pentest_init(uj);
694 case kOtbnScaSubcommandInitKeyMgr:
695 return handle_otbn_pentest_init_keymgr(uj);
696 case kOtbnScaSubcommandInsnCarryFlag:
697 return handle_otbn_sca_insn_carry_flag(uj);
698 case kOtbnScaSubcommandKeySideloadFvsr:
699 return handle_otbn_sca_key_sideload_fvsr(uj);
700 case kOtbnScaSubcommandRsa512Decrypt:
701 return handle_otbn_sca_rsa512_decrypt(uj);
703 LOG_ERROR(
"Unrecognized OTBN SCA subcommand: %d", cmd);
704 return INVALID_ARGUMENT();