5 #include "hw/ip/aes/model/aes_modes.h"
9 #include "sw/device/lib/base/status.h"
18 #include "sw/device/lib/testing/aes_testutils.h"
19 #include "sw/device/lib/testing/csrng_testutils.h"
20 #include "sw/device/lib/testing/entropy_testutils.h"
22 #include "sw/device/lib/testing/test_framework/check.h"
24 #include "sw/device/tests/otbn_randomness_impl.h"
26 #include "entropy_src_regs.h"
29 #define TIMEOUT (1000 * 1000)
32 kEntropySrcStartupWaitMicros = 250000,
35 OTTF_DEFINE_TEST_CONFIG();
38 static dif_entropy_src_t entropy_src;
39 static dif_csrng_t csrng;
40 static dif_edn_t edn0;
41 static dif_edn_t edn1;
43 static dif_otbn_t otbn;
44 static dif_alert_handler_t alert_handler;
46 status_t init_test_environment(
void) {
48 "Initializing modules entropy_src, csrng, edn0, edn1, aes, otbn and "
50 TRY(dif_entropy_src_init(
58 TRY(dif_alert_handler_init(
64 status_t print_entropy_src_state(
const dif_entropy_src_t *entropy_src) {
72 LOG_INFO(
"Current ENTROPY_SRC state: 0x%x", cur_state);
74 const char *state_description;
76 case kDifEntropySrcMainFsmStateIdle:
77 state_description =
"Idle: Initial or inactive state.";
79 case kDifEntropySrcMainFsmStateBootHTRunning:
81 "Boot Health Tests Running: Health tests during boot.";
83 case kDifEntropySrcMainFsmStateBootPostHTChk:
85 "Boot Post Health Test Check: Health tests completed after boot.";
87 case kDifEntropySrcMainFsmStateBootPhaseDone:
89 "Boot Phase Done: Initial setup and checks completed.";
91 case kDifEntropySrcMainFsmStateStartupHTStart:
93 "Startup Health Tests Start: Start of health tests during startup.";
95 case kDifEntropySrcMainFsmStateStartupPhase1:
97 "Startup Phase 1: Initial configuration or loading constants.";
99 case kDifEntropySrcMainFsmStateStartupPass1:
101 "Startup Phase 1 Pass: Successful completion of the first phase of "
104 case kDifEntropySrcMainFsmStateStartupFail1:
106 "Startup Phase 1 Fail: Failure during the first phase of startup.";
108 case kDifEntropySrcMainFsmStateContHTStart:
110 "Continuous Health Tests Start: Start of continuous health tests.";
112 case kDifEntropySrcMainFsmStateContHTRunning:
114 "Continuous Health Tests Running: Health tests running in the "
117 case kDifEntropySrcMainFsmStateFWInsertStart:
119 "Firmware Insert Start: Start of firmware insertion process.";
121 case kDifEntropySrcMainFsmStateFWInsertMsg:
123 "Firmware Insert Message: Firmware is providing data to the entropy "
126 case kDifEntropySrcMainFsmStateSha3MsgDone:
128 "SHA-3 Message Done: SHA-3 message processing complete.";
130 case kDifEntropySrcMainFsmStateSha3Process:
132 "SHA-3 Process: SHA-3 hashing process actively running.";
134 case kDifEntropySrcMainFsmStateSha3Valid:
135 state_description =
"SHA-3 Valid: SHA-3 hash output is valid and ready.";
137 case kDifEntropySrcMainFsmStateSha3Done:
139 "SHA-3 Done: SHA-3 hashing process is fully complete.";
141 case kDifEntropySrcMainFsmStateAlertState:
142 state_description =
"Alert State: Entropy source has triggered an alert.";
144 case kDifEntropySrcMainFsmStateAlertHang:
146 "Alert Hang: Entropy source is in a hang state due to an alert.";
148 case kDifEntropySrcMainFsmStateError:
150 "Error: Generic error condition within the entropy source.";
153 state_description =
"Unknown State";
156 LOG_INFO(
"Current Entropy Source State: %s (0x%x)", state_description,
163 status_t log_entropy_src_failures_and_alerts(
164 const dif_entropy_src_t *entropy_src) {
174 for (
size_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
177 LOG_INFO(
"Test Repetition Count (Index %u):", i);
182 LOG_INFO(
"Alert Fails (RepetitionCount): high=%u, low=%u",
186 LOG_INFO(
"Test Adaptive Proportion (Index %u):", i);
191 LOG_INFO(
"Alert Fails (Adaptive Proportion): high=%u, low=%u",
195 LOG_INFO(
"Test Bucket (Index %u):", i);
200 LOG_INFO(
"Alert Fails (Bucket): high=%u, low=%u",
204 LOG_INFO(
"Test Markov (Index %u):", i);
209 LOG_INFO(
"Alert Fails (Markov): high=%u, low=%u",
213 LOG_INFO(
"Test %u: Unused test type, moving on...", i);
222 status_t disable_entropy_complex(
void) {
225 LOG_INFO(
"Disabling the entropy complex...");
226 return entropy_testutils_stop_all();
229 status_t configure_realistic_fips_health_tests(
void) {
230 LOG_INFO(
"Configuring loose health test thresholds...");
235 TRY_CHECK(!is_locked,
236 "Entropy source is locked. Cannot configure ENTROPY_SRC");
241 .high_threshold = 512,
249 .high_threshold = 512,
257 .high_threshold = 512,
265 .high_threshold = 512,
273 status_t enable_realistic_entropy_src_fips_mode(
274 uint16_t health_test_window_size) {
275 LOG_INFO(
"Enabling ENTROPY_SRC in fips mode...");
280 TRY_CHECK(!is_locked,
281 "Entropy source is locked. Cannot configure ENTROPY_SRC");
286 .route_to_firmware =
false,
289 .bypass_conditioner =
false,
291 .health_test_threshold_scope =
true,
292 .health_test_window_size = health_test_window_size,
293 .alert_threshold = 0xFF,
302 status_t set_threshold_and_enable_stringent_entropy_src_fips_mode(
void) {
303 LOG_INFO(
"Enabling stringent ENTROPY_SRC in fips mode...");
308 TRY_CHECK(!is_locked,
309 "Entropy source is locked. Cannot configure ENTROPY_SRC");
314 .route_to_firmware =
false,
317 .bypass_conditioner =
false,
319 .health_test_threshold_scope =
true,
320 .health_test_window_size = 4096,
321 .alert_threshold = 1,
324 print_entropy_src_state(&entropy_src);
325 LOG_INFO(
"ENTROPY_SRC Configuration:");
332 LOG_INFO(
"health_test_threshold_scope: %d",
341 LOG_INFO(
"ENTROPY_SRC Errors: 0x%x", errors);
343 dif_entropy_src_irq_state_snapshot_t irq_state;
344 TRY(dif_entropy_src_irq_get_state(&entropy_src, &irq_state));
345 LOG_INFO(
"ENTROPY_SRC IRQ State: 0x%x", irq_state);
346 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
351 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
353 LOG_INFO(
"Done enabling stringent ENTROPY_SRC in fips mode...");
357 status_t configure_stringent_fips_health_tests(
void) {
358 LOG_INFO(
"Configuring stringent health test thresholds...");
363 TRY_CHECK(!is_locked,
364 "Entropy source is locked. Cannot configure ENTROPY_SRC");
368 .high_threshold = 50,
371 LOG_INFO(
"Repetition Count Test Configuration:");
380 .high_threshold = 270,
383 LOG_INFO(
"Adaptive Proportion Test Configuration:");
392 .high_threshold = 270,
395 LOG_INFO(
"Bucket Test Configuration:");
404 .high_threshold = 270,
407 LOG_INFO(
"Markov Test Configuration:");
424 status_t my_entropy_testutils_auto_mode_init(
void) {
425 TRY(entropy_testutils_stop_all());
428 print_entropy_src_state(&entropy_src);
430 CHECK_STATUS_OK(entropy_testutils_entropy_src_init());
431 print_entropy_src_state(&entropy_src);
435 print_entropy_src_state(&entropy_src);
437 LOG_INFO(
"Configuring csrng done:");
438 LOG_INFO(
"Setting EDN in auto mode...");
439 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
440 const int my_reseed_interval = 4;
441 LOG_INFO(
"Setting EDN0 reseed_interval to %d", my_reseed_interval);
442 print_entropy_src_state(&entropy_src);
451 .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
462 .cmd = csrng_cmd_header_build(
473 .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
483 .reseed_interval = my_reseed_interval,
487 print_entropy_src_state(&entropy_src);
496 .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
507 .cmd = csrng_cmd_header_build(
518 .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
528 .reseed_interval = 4,
534 status_t enable_realistic_csrng_edns_auto_mode(
void) {
535 LOG_INFO(
"Enabling EDNs in auto mode...");
536 CHECK_STATUS_OK(entropy_testutils_auto_mode_init());
540 status_t enable_csrng_edns_auto_mode(
void) {
541 LOG_INFO(
"Enabling EDNs in auto mode for fips(locally modified function)...");
542 CHECK_STATUS_OK(my_entropy_testutils_auto_mode_init());
543 LOG_INFO(
"Done Enabling EDNs in auto mode for fips...");
547 status_t test_and_verify_aes_operation(
void) {
548 LOG_INFO(
"Triggering AES operation in ECB mode...");
558 .reseed_on_key_change =
false,
559 .ctrl_aux_lock =
false,
563 CHECK_STATUS_OK(aes_testutils_setup_encryption(transaction, &aes));
569 CHECK_STATUS_OK(aes_testutils_decrypt_ciphertext(transaction, &aes));
571 LOG_INFO(
"AES operation in ECB mode verified successfully");
575 static bool poll_for_output_valid_or_starve(
const dif_aes_t *aes) {
576 const uint32_t kMaxRetries = 1000;
577 for (uint32_t i = 0; i < kMaxRetries; i++) {
578 bool out_valid =
false;
582 LOG_ERROR(
"dif_aes_get_status() = %d while polling OUTPUT_VALID.",
596 #define AES_OPERATION_HANG_STATUS_VALUE 0x700B
597 static inline status_t aes_starve_ok_status(
void) {
599 st.value = AES_OPERATION_HANG_STATUS_VALUE;
603 static inline bool status_is_aes_starve_ok(
status_t s) {
604 return (s.value == AES_OPERATION_HANG_STATUS_VALUE);
607 status_t test_and_verify_aes_operation_hang(
void) {
608 LOG_INFO(
"Perform AES-256 in ECB mode");
613 static const uint8_t kKeyShare1[32] = {
614 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf,
615 0xbf, 0xcf, 0xdf, 0xef, 0xff, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
616 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa};
619 uint8_t key_share0[32];
620 for (
int i = 0; i < 32; i++) {
621 key_share0[i] = kAesModesKey256[i] ^ kKeyShare1[i];
623 memcpy(key.share0, key_share0, 16);
624 memcpy(key.share1, &key_share0[16], 16);
634 .reseed_on_key_change =
false,
635 .ctrl_aux_lock =
false,
640 memcpy(in_data.data, kAesModesPlainText, 16);
643 LOG_INFO(
"Starting AES encryption...");
648 LOG_INFO(
"Wait for AES InputReady, then load the single-block plaintext...");
651 LOG_INFO(
"Plaintext block loaded for encryption.");
654 LOG_INFO(
"Polling for OutputValid in encryption...", TIMEOUT);
655 bool got_output_valid = poll_for_output_valid_or_starve(&aes);
657 if (!got_output_valid) {
660 "No OUTPUT_VALID... EDN starved during encryption expected pass "
662 return aes_starve_ok_status();
671 LOG_INFO(
"AES encryption transaction ended successfully.");
674 LOG_INFO(
"Switching to AES decryption mode...");
680 LOG_INFO(
"Waiting for InputReady to load ciphertext for decryption...");
685 LOG_INFO(
"Polling for OutputValid in decryption...");
686 got_output_valid = poll_for_output_valid_or_starve(&aes);
688 if (!got_output_valid) {
691 "EDN starved during decryption expected pass "
693 return aes_starve_ok_status();
699 LOG_INFO(
"Decryption output read from hardware.");
701 uint8_t *dec_bytes = (uint8_t *)dec_data.data;
705 LOG_INFO(
"ECB decryption transaction ended successfully.");
708 LOG_INFO(
"Verifying decrypted block with original plaintext?");
709 if (
memcmp(dec_data.data, kAesModesPlainText, 16) != 0) {
710 LOG_ERROR(
"Decryption mismatch => final plaintext != original!");
711 for (
int i = 0; i < 16; i++) {
712 LOG_ERROR(
"Byte[%d]: got=0x%02x, want=0x%02x", i, dec_bytes[i],
713 kAesModesPlainText[i]);
718 LOG_INFO(
"AES operation in ECB mode verified successfully");
722 status_t test_and_verify_otbn_operation(
void) {
723 LOG_INFO(
"Starting OTBN randomness test...(expect completion)");
726 otbn_randomness_test_start(&otbn, 1);
730 const uint32_t kIterateMaxRetries = 10;
731 bool otbn_busy =
true;
732 uint32_t iter_cntr = kIterateMaxRetries;
736 while (iter_cntr > 0) {
741 otbn_busy = (otbn_status &
742 (kDifOtbnStatusBusyExecute | kDifOtbnStatusBusySecWipeDmem |
743 kDifOtbnStatusBusySecWipeImem)) != 0;
758 LOG_INFO(
"OTBN status: 0x%x", otbn_status);
759 LOG_INFO(
"OTBN error bits: 0x%x", otbn_err_bits);
761 LOG_INFO(
"OTBN program ran as expected with no hang");
765 if (otbn_err_bits != kDifOtbnErrBitsNoError) {
766 LOG_ERROR(
"OTBN encountered unexpected errors");
770 LOG_ERROR(
"A BAD_DATA_ADDR error was observed");
773 LOG_ERROR(
"A BAD_INSN_ADDR error was observed");
776 LOG_ERROR(
"A CALL_STACK error was observed");
779 LOG_ERROR(
"An ILLEGAL_INSN error was observed");
785 otbn_randomness_test_end(&otbn, 1);
791 LOG_ERROR(
"OTBN program did not complete run");
796 status_t wait_for_recoverable_alert(
void) {
797 LOG_INFO(
"Waiting for Entropy Source recoverable alert to be asserted...");
805 LOG_ERROR(
"dif_entropy_src_get_recoverable_alerts failed (res=%d)", res);
811 LOG_INFO(
"Recoverable alert detected. Alerts: 0x%x", alerts);
813 print_entropy_src_state(&entropy_src);
814 log_entropy_src_failures_and_alerts(&entropy_src);
816 const uint32_t kEsMainSmAlertBit =
817 ENTROPY_SRC_RECOV_ALERT_STS_ES_MAIN_SM_ALERT_BIT;
819 if ((alerts & kEsMainSmAlertBit) != 0) {
820 LOG_INFO(
"ES_MAIN_SM_ALERT bit is set, as expected.");
822 LOG_INFO(
"ES_MAIN_SM_ALERT bit not set, continuing anyway...");
827 &entropy_src, kDifEntropySrcIrqEsHealthTestFailed);
829 LOG_INFO(
"Failed to acknowledge HealthTestFailed IRQ (res=%d).",
832 LOG_INFO(
"HealthTestFailed IRQ acknowledged.");
840 LOG_INFO(
"Done waiting for Entropy Source recoverable alert (found).");
845 LOG_INFO(
"Starting OTBN randomness test...");
848 otbn_randomness_test_start(&otbn, 1);
850 LOG_INFO(
"OTBN randomness test started");
856 CHECK_STATUS_OK(init_test_environment());
860 uint16_t window_sizes[5] = {256, 512, 1024, 2048, 4096};
861 for (uint16_t i = 0; i <
ARRAYSIZE(window_sizes); i++) {
862 LOG_INFO(
"Testing health test window size value = %u", window_sizes[i]);
864 CHECK_STATUS_OK(disable_entropy_complex());
868 CHECK_STATUS_OK(configure_realistic_fips_health_tests());
871 CHECK_STATUS_OK(enable_realistic_entropy_src_fips_mode(window_sizes[i]));
875 CHECK_STATUS_OK(enable_realistic_csrng_edns_auto_mode());
881 CHECK_STATUS_OK(test_and_verify_aes_operation());
882 CHECK_STATUS_OK(test_and_verify_aes_operation());
883 CHECK_STATUS_OK(test_and_verify_aes_operation());
884 CHECK_STATUS_OK(test_and_verify_otbn_operation());
885 CHECK_STATUS_OK(test_and_verify_otbn_operation());
886 CHECK_STATUS_OK(test_and_verify_otbn_operation());
889 "Realistic Test successfully passed with different health test window "
892 for (uint16_t iter = 0; iter < 1; iter++) {
896 LOG_INFO(
"Step 9: Disable the entropy complex again. iter = %d", iter);
897 CHECK_STATUS_OK(disable_entropy_complex());
902 "Step 10: Configure unrealistically stringent health test threshold "
905 CHECK_STATUS_OK(configure_stringent_fips_health_tests());
910 "Step 11 and Step 12:Configure a low alert threshold value in the "
911 "ALERT_THRESHOLD and enable entropy_src. iter = %d",
913 CHECK_STATUS_OK(set_threshold_and_enable_stringent_entropy_src_fips_mode());
921 "Step 13 and Step 14:Enable CSRNG and both EDNs in auto request mode. "
924 CHECK_STATUS_OK(enable_csrng_edns_auto_mode());
925 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
932 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
937 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
940 LOG_INFO(
"Step 16: Wait for recoverable alert");
941 LOG_INFO(
"Step 16:iter = %d", iter);
942 status_t st = wait_for_recoverable_alert();
943 if (!status_ok(st)) {
944 LOG_ERROR(
"wait_for_recoverable_alert() error=0x%x", st.value);
947 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
952 for (uint16_t i = 0; i < 500; i++) {
953 status_t st = test_and_verify_aes_operation_hang();
954 if (status_is_aes_starve_ok(st)) {
956 "Step 17: Starve event encountered confirming AES expected hang");
961 CHECK_STATUS_OK(print_entropy_src_state(&entropy_src));
964 LOG_INFO(
"Entropy source fips mode health test completed");
970 LOG_INFO(
"Entering Entropy Source FIPS Mode Health Test");
972 return status_ok(execute_test());