5 #include "sw/device/tests/penetrationtests/firmware/sca/aes_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"
14 #include "sw/device/sca/lib/aes.h"
16 #include "sw/device/tests/penetrationtests/firmware/lib/pentest_lib.h"
17 #include "sw/device/tests/penetrationtests/json/aes_sca_commands.h"
18 #include "sw/device/tests/penetrationtests/json/commands.h"
20 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
21 #include "sw/device/lib/testing/aes_testutils.h"
29 static bool fpga_mode =
false;
32 kAesKeyLengthMax = 32,
35 kTestTimeout = (1000 * 1000),
43 kIbexAesSleepCycles = 680,
54 kNumBatchOpsMax = 256,
67 uint8_t batch_keys[kNumBatchOpsMax][kAesKeyLength];
72 uint8_t batch_plaintexts[kNumBatchOpsMax][kAesTextLength];
77 bool sample_fixed =
true;
88 static const uint32_t kKeyGenRoundKeys[(kAesKeyLength / 4) * 11] = {
89 0xab239a12, 0xcd45bc34, 0xe067de56, 0xf089f178, 0xbc1734ae, 0xe12c69d5,
90 0x836304da, 0x9262eb1a, 0xcb776054, 0x9d7c5039, 0x71f29195, 0x64f6947f,
91 0xd2196e0e, 0x2bb6ca9a, 0xc4b547d6, 0x6602f460, 0x528099f7, 0xd1fa4c86,
92 0xd317a2e5, 0x452321d5, 0x92c040d9, 0x8756ace0, 0xed3e298b, 0x92d7f4d5,
93 0xfc6eaeee, 0xc84f19b5, 0x3ed3edc4, 0x2bb96e9a, 0x7a86e846, 0x99511e07,
94 0x350bd835, 0xd6fd442a, 0x3c46c028, 0x47de8f91, 0x25101bc3, 0x9f49b4f0,
95 0x29155393, 0xb8ff21ae, 0x36130318, 0x79e6af1b, 0xa68f9ac9, 0xcd758aab,
96 0x88beadae, 0x8ef711be};
101 static uint8_t plaintext_fixed[kAesTextLength] = {
102 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
103 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
107 static uint8_t key_fixed[kAesTextLength] = {0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12,
108 0x0A, 0x78, 0x42, 0x78, 0x1E, 0x22,
109 0xB2, 0x5C, 0xDD, 0xF9};
113 static uint8_t plaintext_random[kAesTextLength] = {
114 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
115 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
119 static uint8_t key_random[kAesTextLength] = {0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
120 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
121 0x53, 0x53, 0x53, 0x53};
125 static uint8_t ciphertext_temp[kAesTextLength];
130 static uint8_t batch_plaintext[kAesTextLength];
136 static uint32_t block_ctr;
138 static dif_aes_t aes;
147 .reseed_on_key_change =
false,
148 .force_masks =
false,
149 .ctrl_aux_lock =
false,
164 static status_t aes_sca_load_fixed_seed(
void) {
185 static status_t aes_key_mask_and_config(
const uint8_t *key,
size_t key_len) {
186 if (key_len != kAesKeyLength) {
191 for (
int i = 0; i < key_len / 4; ++i) {
192 key_shares.
share1[i] = pentest_non_linear_layer(
193 pentest_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking)));
194 key_shares.
share0[i] = *((uint32_t *)key + i) ^ key_shares.
share1[i];
197 for (
size_t i = key_len / 4; i < kAesKeyLengthMax / 4; ++i) {
199 pentest_non_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking));
201 pentest_non_linear_layer(pentest_next_lfsr(1, kPentestLfsrMasking));
205 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
208 TRY(aes_sca_load_fixed_seed());
218 static void aes_manual_trigger(
void) {
232 static status_t aes_encrypt(
const uint8_t *plaintext,
size_t plaintext_len) {
239 if (plaintext_len !=
sizeof(data.data)) {
242 memcpy(data.data, plaintext, plaintext_len);
249 pentest_set_trigger_high();
250 pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles,
false,
252 pentest_set_trigger_low();
257 pentest_call_and_sleep(aes_manual_trigger, kIbexAesSleepCycles,
true,
269 static status_t aes_send_ciphertext(
bool only_first_word,
ujson_t *uj) {
277 return OUT_OF_RANGE();
280 aes_sca_ciphertext_t uj_output;
281 memset(uj_output.ciphertext, 0, AESSCA_CMD_MAX_DATA_BYTES);
282 uj_output.ciphertext_length = kAesTextLength;
283 if (only_first_word) {
284 uj_output.ciphertext_length = 4;
286 memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data,
287 uj_output.ciphertext_length);
288 RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output);
298 static void aes_serial_advance_fixed(
void) {
299 aes_sw_encrypt_block(plaintext_fixed, kKeyGenRoundKeys, ciphertext_temp);
300 memcpy(plaintext_fixed, ciphertext_temp, kAesTextLength);
309 static void aes_serial_advance_random(
void) {
310 aes_sw_encrypt_block(plaintext_random, kKeyGenRoundKeys, ciphertext_temp);
311 memcpy(plaintext_random, ciphertext_temp, kAesTextLength);
312 aes_sw_encrypt_block(key_random, kKeyGenRoundKeys, ciphertext_temp);
313 memcpy(key_random, ciphertext_temp, kAesTextLength);
322 static void aes_serial_advance_random_data(
void) {
323 aes_sw_encrypt_block(plaintext_random, kKeyGenRoundKeys, ciphertext_temp);
324 memcpy(plaintext_random, ciphertext_temp, kAesTextLength);
354 static status_t aes_sca_fvsr_key_batch_generate(
355 penetrationtest_num_enc_t uj_data) {
356 if (uj_data.num_enc > kNumBatchOpsMax) {
357 return OUT_OF_RANGE();
360 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
362 memcpy(batch_keys[i], key_fixed, kAesKeyLength);
363 memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength);
364 aes_serial_advance_fixed();
366 memcpy(batch_keys[i], key_random, kAesKeyLength);
367 memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength);
368 aes_serial_advance_random();
370 sample_fixed = batch_plaintexts[i][0] & 0x1;
377 penetrationtest_num_enc_t uj_data;
378 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
381 block_ctr += uj_data.num_enc;
385 if (block_ctr > kBlockCtrMax) {
386 TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
387 block_ctr = uj_data.num_enc;
393 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
395 TRY(aes_encrypt(batch_plaintext, kAesTextLength));
408 memcpy(batch_plaintext, ciphertext.data, kAesTextLength);
412 aes_sca_ciphertext_t uj_output;
413 memcpy(uj_output.ciphertext, (uint8_t *)ciphertext.data, kAesTextLength);
414 RESP_OK(ujson_serialize_aes_sca_ciphertext_t, uj, &uj_output);
420 penetrationtest_num_enc_t uj_data;
421 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
423 block_ctr += uj_data.num_enc;
427 if (block_ctr > kBlockCtrMax) {
428 TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
429 block_ctr = uj_data.num_enc;
432 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
433 TRY(aes_encrypt(plaintext_random, kAesTextLength));
434 aes_serial_advance_random();
437 TRY(aes_send_ciphertext(
true, uj));
443 penetrationtest_num_enc_t uj_data;
444 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
446 block_ctr += uj_data.num_enc;
450 if (block_ctr > kBlockCtrMax) {
451 TRY(aes_key_mask_and_config(key_random, kAesKeyLength));
452 block_ctr = uj_data.num_enc;
455 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
456 TRY(aes_key_mask_and_config(key_random, kAesKeyLength));
457 TRY(aes_encrypt(plaintext_random, kAesTextLength));
458 aes_serial_advance_random();
461 TRY(aes_send_ciphertext(
true, uj));
467 aes_sca_text_t uj_data;
468 TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data));
470 if (uj_data.text_length != kAesTextLength) {
471 return OUT_OF_RANGE();
473 memcpy(batch_plaintext, uj_data.text, uj_data.text_length);
479 penetrationtest_num_enc_t uj_data;
480 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
482 if (uj_data.num_enc > kNumBatchOpsMax) {
483 return OUT_OF_RANGE();
486 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
487 memcpy(batch_keys[i], key_fixed, kAesKeyLength);
489 memcpy(batch_plaintexts[i], plaintext_fixed, kAesKeyLength);
491 memcpy(batch_plaintexts[i], plaintext_random, kAesKeyLength);
492 aes_serial_advance_random_data();
494 sample_fixed = pentest_next_lfsr(1, kPentestLfsrOrder) & 0x1;
497 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
498 TRY(aes_key_mask_and_config(batch_keys[i], kAesKeyLength));
499 TRY(aes_encrypt(batch_plaintexts[i], kAesTextLength));
502 TRY(aes_send_ciphertext(
false, uj));
508 penetrationtest_num_enc_t uj_data;
509 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
511 if (uj_data.num_enc > kNumBatchOpsMax) {
512 return OUT_OF_RANGE();
515 for (uint32_t i = 0; i < uj_data.num_enc; ++i) {
516 TRY(aes_key_mask_and_config(batch_keys[i], kAesKeyLength));
517 TRY(aes_encrypt(batch_plaintexts[i], kAesTextLength));
520 TRY(aes_send_ciphertext(
false, uj));
524 return aes_sca_fvsr_key_batch_generate(uj_data);
528 penetrationtest_num_enc_t uj_data;
529 TRY(ujson_deserialize_penetrationtest_num_enc_t(uj, &uj_data));
531 return aes_sca_fvsr_key_batch_generate(uj_data);
535 aes_sca_key_t uj_key_data;
536 TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data));
538 if (uj_key_data.key_length != kAesKeyLength) {
539 return OUT_OF_RANGE();
541 memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length);
546 aes_sca_cmd_t uj_data;
547 TRY(ujson_deserialize_aes_sca_cmd_t(uj, &uj_data));
549 static const uint8_t kPlaintextFixedStartFvsrKey[kAesTextLength] = {
550 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
551 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
552 static const uint8_t kKeyFixedStartFvsrKey[kAesTextLength] = {
553 0x81, 0x1E, 0x37, 0x31, 0xB0, 0x12, 0x0A, 0x78,
554 0x42, 0x78, 0x1E, 0x22, 0xB2, 0x5C, 0xDD, 0xF9};
555 static const uint8_t kPlaintextRandomStartFvsrKey[kAesTextLength] = {
556 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
557 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc};
558 static const uint8_t kKeyRandomStartFvsrKey[kAesTextLength] = {
559 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
560 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53};
562 static const uint8_t kPlaintextFixedStartFvsrData[kAesTextLength] = {
563 0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D,
564 0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90};
565 static const uint8_t kPlaintextRandomStartFvsrData[kAesTextLength] = {
566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
568 static const uint8_t kKeyStartFvsrData[kAesTextLength] = {
569 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
570 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
573 static const uint32_t kPrngInitialState = 0x99999999;
576 if (uj_data.cmd == 1) {
577 memcpy(plaintext_fixed, kPlaintextFixedStartFvsrKey, kAesTextLength);
578 memcpy(key_fixed, kKeyFixedStartFvsrKey, kAesKeyLength);
579 memcpy(plaintext_random, kPlaintextRandomStartFvsrKey, kAesTextLength);
580 memcpy(key_random, kKeyRandomStartFvsrKey, kAesKeyLength);
584 if (uj_data.cmd == 2) {
585 memcpy(plaintext_fixed, kPlaintextFixedStartFvsrData, kAesTextLength);
586 memcpy(key_fixed, kKeyStartFvsrData, kAesKeyLength);
587 memcpy(plaintext_random, kPlaintextRandomStartFvsrData, kAesTextLength);
590 pentest_seed_lfsr(kPrngInitialState, kPentestLfsrOrder);
597 aes_sca_fpga_mode_t uj_data;
598 TRY(ujson_deserialize_aes_sca_fpga_mode_t(uj, &uj_data));
599 if (uj_data.fpga_mode == 0x01) {
603 penetrationtest_cpuctrl_t uj_cpuctrl;
604 TRY(ujson_deserialize_penetrationtest_cpuctrl_t(uj, &uj_cpuctrl));
606 pentest_init(kPentestTriggerSourceAes,
607 kPentestPeripheralIoDiv4 | kPentestPeripheralAes);
619 penetrationtest_device_info_t uj_output;
620 TRY(pentest_configure_cpu(
621 uj_cpuctrl.icache_disable, uj_cpuctrl.dummy_instr_disable,
622 uj_cpuctrl.enable_jittery_clock, uj_cpuctrl.enable_sram_readback,
623 &uj_output.clock_jitter_locked, &uj_output.clock_jitter_en,
624 &uj_output.sram_main_readback_locked, &uj_output.sram_ret_readback_locked,
625 &uj_output.sram_main_readback_en, &uj_output.sram_ret_readback_en));
628 TRY(pentest_read_device_id(uj_output.device_id));
629 RESP_OK(ujson_serialize_penetrationtest_device_info_t, uj, &uj_output);
635 aes_sca_key_t uj_key_data;
636 TRY(ujson_deserialize_aes_sca_key_t(uj, &uj_key_data));
638 memcpy(key_fixed, uj_key_data.key, uj_key_data.key_length);
640 TRY(aes_key_mask_and_config(key_fixed, uj_key_data.key_length));
645 aes_sca_lfsr_t uj_lfsr_data;
646 TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data));
648 uint32_t seed_local =
read_32(uj_lfsr_data.seed);
649 if (seed_local == 0) {
656 pentest_seed_lfsr(seed_local, kPentestLfsrMasking);
658 #ifndef OPENTITAN_IS_ENGLISHBREAKFAST
661 const dif_csrng_t csrng = {
663 const dif_edn_t edn0 = {
666 status_t res = aes_testutils_masking_prng_zero_output_seed(&csrng, &edn0);
667 if (res.value != 0) {
672 TRY(aes_sca_load_fixed_seed());
682 aes_sca_lfsr_t uj_lfsr_data;
683 TRY(ujson_deserialize_aes_sca_lfsr_t(uj, &uj_lfsr_data));
685 uint32_t seed_local =
read_32(uj_lfsr_data.seed);
686 pentest_seed_lfsr(seed_local, kPentestLfsrOrder);
692 aes_sca_text_t uj_data;
693 TRY(ujson_deserialize_aes_sca_text_t(uj, &uj_data));
694 if (uj_data.text_length != kAesTextLength) {
695 return OUT_OF_RANGE();
702 if (block_ctr > kBlockCtrMax) {
703 TRY(aes_key_mask_and_config(key_fixed, kAesKeyLength));
707 TRY(aes_encrypt(uj_data.text, uj_data.text_length));
709 TRY(aes_send_ciphertext(
false, uj));
714 aes_sca_subcommand_t cmd;
715 TRY(ujson_deserialize_aes_sca_subcommand_t(uj, &cmd));
717 case kAesScaSubcommandBatchAlternativeEncrypt:
718 return handle_aes_sca_batch_alternative_encrypt(uj);
719 case kAesScaSubcommandBatchEncrypt:
720 return handle_aes_sca_batch_encrypt(uj);
721 case kAesScaSubcommandBatchEncryptRandom:
722 return handle_aes_sca_batch_encrypt_random(uj);
723 case kAesScaSubcommandBatchPlaintextSet:
724 return handle_aes_sca_batch_plaintext_set(uj);
725 case kAesScaSubcommandFvsrDataBatchEncrypt:
726 return handle_aes_sca_fvsr_data_batch_encrypt(uj);
727 case kAesScaSubcommandFvsrKeyBatchEncrypt:
728 return handle_aes_sca_fvsr_key_batch_encrypt(uj);
729 case kAesScaSubcommandFvsrKeyBatchGenerate:
730 return handle_aes_sca_fvsr_key_batch_generate(uj);
731 case kAesScaSubcommandFvsrKeySet:
732 return handle_aes_sca_fvsr_key_set(uj);
733 case kAesScaSubcommandFvsrKeyStartBatchGenerate:
734 return handle_aes_sca_fvsr_key_start_batch_generate(uj);
735 case kAesScaSubcommandInit:
736 return handle_aes_pentest_init(uj);
737 case kAesScaSubcommandKeySet:
738 return handle_aes_sca_key_set(uj);
739 case kAesScaSubcommandSeedLfsr:
740 return handle_aes_pentest_seed_lfsr(uj);
741 case kAesScaSubcommandSeedLfsrOrder:
742 return handle_aes_pentest_seed_lfsr_order(uj);
743 case kAesScaSubcommandSingleEncrypt:
744 return handle_aes_sca_single_encrypt(uj);
746 LOG_ERROR(
"Unrecognized AES SCA subcommand: %d", cmd);
747 return INVALID_ARGUMENT();