Software APIs
edn_sw_mode.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "hw/ip/aes/model/aes_modes.h"
11 #include "sw/device/lib/testing/aes_testutils.h"
12 #include "sw/device/lib/testing/edn_testutils.h"
13 #include "sw/device/lib/testing/entropy_testutils.h"
14 #include "sw/device/lib/testing/rand_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
18 #include "edn_regs.h" // Generated
20 
21 #define TIMEOUT (10 * 1000 * 1000)
22 // AES with Domain-Oriented Masking (DOM) takes 72 cycles per 16B data
23 // block for a 256 bit key. Multiply this number by 20, to be on the safe side,
24 // to get the number of micro seconds for the timeout.
25 #define PLAIN_TEXT_BYTES (4 * 4)
26 #define TIMEOUT_AES (72 * (PLAIN_TEXT_BYTES / 16) * 20)
27 
28 static dif_csrng_t csrng;
29 static dif_edn_t edn0;
30 static dif_edn_t edn1;
31 static dif_aes_t aes;
32 
33 OTTF_DEFINE_TEST_CONFIG();
34 
35 // Initializes the peripherals used in this test.
36 static void init_peripherals(void) {
37  CHECK_DIF_OK(dif_csrng_init(
39  CHECK_DIF_OK(
41  CHECK_DIF_OK(
43  CHECK_DIF_OK(
45 }
46 
47 // Wrapper function for the AES_TESTUTILS_WAIT_FOR_STATUS macro.
48 static status_t aes_wait_for_status(dif_aes_status_t aes_state, bool flag,
49  uint32_t timeout) {
50  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, aes_state, flag, timeout);
51  return OK_STATUS();
52 }
53 
54 // Generate bits in SW mode.
55 static void edn_generate_sw_bits(void) {
56  dif_edn_seed_material_t seed0 = edn_testutils_seed_material_build(true);
57  const dif_edn_entropy_src_toggle_t entropy_src_enable =
59  CHECK_DIF_OK(dif_edn_instantiate(&edn0, entropy_src_enable, &seed0));
61 }
62 
63 // Configure the entropy complex.
64 static void entropy_config(void) {
65  // Disable the entropy complex.
66  CHECK_STATUS_OK(entropy_testutils_stop_all());
67  // Enable ENTROPY_SRC in FIPS mode.
68  CHECK_STATUS_OK(entropy_testutils_entropy_src_init());
69  // Enable CSRNG.
70  CHECK_DIF_OK(dif_csrng_configure(&csrng));
71  // Enable EDN1 in auto request mode. This does not generate entropy for AES.
72  CHECK_DIF_OK(dif_edn_set_auto_mode(
73  &edn1, edn_testutils_auto_params_build(true,
74  /*res_itval=*/0,
75  /*glen_val=*/0)));
76  // Enable EDN0 in software port mode.
77  CHECK_DIF_OK(dif_edn_configure(&edn0));
78 }
79 
80 static void execute_test(void) {
81  // Trigger the execution of AES to test EDN0. Consecutively,
82  // verify that it hangs.
83  LOG_INFO("aes_trigger_execution start");
84  // Setup ECB encryption transaction.
85  dif_aes_transaction_t transaction = {
86  .operation = kDifAesOperationEncrypt,
87  .mode = kDifAesModeEcb,
88  .key_len = kDifAesKey256,
89  .key_provider = kDifAesKeySoftwareProvided,
90  .mask_reseeding = kDifAesReseedPerBlock,
91  .manual_operation = kDifAesManualOperationAuto,
92  .reseed_on_key_change = false,
93  .ctrl_aux_lock = false,
94  };
95 
96  CHECK_STATUS_OK(aes_testutils_setup_encryption(transaction, &aes));
97 
98  // Wait for AES to stall.
99  status_t status = aes_wait_for_status(kDifAesStatusIdle, true, TIMEOUT_AES);
100 
101  // We only care about the MSB and the 5 LSB.
102  // MSB is the error flag and the 5 LSB are the error code.
103  bool error_flag = (status.value >> 31) & 0x1;
104  absl_status_t error_code = status.value & 0x1f;
105  CHECK(error_flag && (error_code == kDeadlineExceeded));
106 
107  // Provide the required commands to EDN0, via SW_CMD_REQ register,
108  // to start generating and delivering entropy to AES.
109  LOG_INFO("edn_generate_sw_bits start");
110  edn_generate_sw_bits();
111  aes_wait_for_status(kDifAesStatusOutputValid, true, TIMEOUT);
112 
113  CHECK_STATUS_OK(aes_testutils_decrypt_ciphertext(transaction, &aes));
114 }
115 
116 bool test_main(void) {
117  LOG_INFO("init_peripherals start");
118  init_peripherals();
119  // Disable and restart the entropy complex.
120  LOG_INFO("entropy_config start");
121  entropy_config();
122  // Execute the main body of the test.
123  execute_test();
124  return true;
125 }