Software APIs
aes_idle_test.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/clkmgr_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 
16 #define TIMEOUT (1000 * 1000)
17 
18 // The mask share, used to mask kKey. Note that the masking should not be done
19 // manually. Software is expected to get the key in two shares right from the
20 // beginning.
21 static const uint8_t kKeyShare1[] = {
22  0x0f, 0x1f, 0x2f, 0x3F, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x9f, 0xaf,
23  0xbf, 0xcf, 0xdf, 0xef, 0xff, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a,
24  0x6a, 0x7a, 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
25 };
26 
27 OTTF_DEFINE_TEST_CONFIG();
28 static dif_clkmgr_t clkmgr;
29 static const dif_clkmgr_hintable_clock_t kAesClock =
30 #if defined(OPENTITAN_IS_EARLGREY)
32 #elif defined(OPENTITAN_IS_DARJEELING)
33  kTopDarjeelingHintableClocksMainAes
34 #else
35 #error Unsupported top
36 #endif
37  ;
38 
39 static bool is_hintable_clock_enabled(const dif_clkmgr_t *clkmgr,
41  dif_toggle_t clock_state;
42  CHECK_DIF_OK(
43  dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &clock_state));
44  return clock_state == kDifToggleEnabled;
45 }
46 
47 static status_t initialize_clkmgr(void) {
48  CHECK_DIF_OK(dif_clkmgr_init_from_dt(kDtClkmgrAon, &clkmgr));
49 
50  // Get initial hint and enable for AES clock and check both are enabled.
51  dif_toggle_t clock_hint_state;
52  CHECK_DIF_OK(dif_clkmgr_hintable_clock_get_hint(&clkmgr, kAesClock,
53  &clock_hint_state));
54  CHECK(clock_hint_state == kDifToggleEnabled);
55  return CLKMGR_TESTUTILS_CHECK_CLOCK_HINT(clkmgr, kAesClock,
57 }
58 
59 status_t execute_test(dif_aes_t *aes) {
60  // Mask the key. Note that this should not be done manually. Software is
61  // expected to get the key in two shares right from the beginning.
62  uint8_t key_share0[sizeof(kAesModesKey256)];
63  for (int i = 0; i < sizeof(kAesModesKey256); ++i) {
64  key_share0[i] = kAesModesKey256[i] ^ kKeyShare1[i];
65  }
66 
67  // "Convert" key share byte arrays to `dif_aes_key_share_t`.
69  memcpy(key.share0, key_share0, sizeof(key.share0));
70  memcpy(key.share1, kKeyShare1, sizeof(key.share1));
71 
72  // Setup ECB decryption transaction. ECB decryption is selected because
73  // operating the AES cipher in inverse operation mode requires to first
74  // generate the decryption start key. As a result, the AES cipher is busy
75  // for the duration of two encryption/decryption runs which gives this
76  // test sufficient time to update the clock hint and verify that the clock
77  // is still active.
78  dif_aes_transaction_t transaction = {
79  .operation = kDifAesOperationDecrypt,
80  .mode = kDifAesModeEcb,
81  .key_len = kDifAesKey256,
82  .key_provider = kDifAesKeySoftwareProvided,
83  .mask_reseeding = kDifAesReseedPerBlock,
84  .manual_operation = kDifAesManualOperationAuto,
85  .reseed_on_key_change = false,
86  .ctrl_aux_lock = false,
87  };
88 
89  // With the AES unit idle, write the AES clk hint to 0 within clkmgr to
90  // indicate AES clk can be gated and verify that the AES clk hint status
91  // within clkmgr reads 0 (AES is disabled).
92  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
93  clkmgr, kAesClock, kDifToggleDisabled, kDifToggleDisabled);
94 
95  // Write the AES clk hint to 1 within clkmgr to indicate AES clk can be
96  // enabled.
97  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
98  clkmgr, kAesClock, kDifToggleEnabled, kDifToggleEnabled);
99 
100  // Initiate an AES operation with a known key, cipher text and plain text,
101  // write AES clk hint to 0 and verify that the AES clk hint status within
102  // clkmgr now reads 1 (AES is enabled), before the AES operation is complete.
103  TRY(dif_aes_start(aes, &transaction, &key, NULL));
104 
105  // "Convert" plain data byte arrays to `dif_aes_data_t`.
106  dif_aes_data_t in_data_cipher;
107  memcpy(in_data_cipher.data, kAesModesCipherTextEcb256,
108  sizeof(in_data_cipher.data));
109 
110  // Load the plain text to trigger the encryption operation.
111  AES_TESTUTILS_WAIT_FOR_STATUS(aes, kDifAesStatusInputReady, true, TIMEOUT);
112  dif_result_t ret = dif_aes_load_data(aes, in_data_cipher);
113  // Write the clock hint to 0 and verify that the clock is still enabled.
114  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
115  clkmgr, kAesClock, kDifToggleDisabled, kDifToggleEnabled);
116  TRY(ret);
117 
118  // This is a bit awkward, but when the AES finishes the operation the clock
119  // will be gated as the clock hint has requested and the AES registers can't
120  // be read. So the safest way to check whether the AES has finished is by
121  // checking that the clock is not gated.
122  IBEX_SPIN_FOR(!is_hintable_clock_enabled(&clkmgr, kAesClock), TIMEOUT);
123 
124  // After the AES operation is complete verify that the AES clk hint status
125  // within clkmgr now reads 0 again (AES is idle).
126  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
127  clkmgr, kAesClock, kDifToggleDisabled, kDifToggleDisabled);
128 
129  // Write the AES clk hint to 1, read and check the AES output for
130  // correctness.
131  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
132  clkmgr, kAesClock, kDifToggleEnabled, kDifToggleEnabled);
133  dif_aes_data_t out_data;
134  TRY(dif_aes_read_output(aes, &out_data));
135 
136  // Finish the ECB decryption transaction.
137  TRY(dif_aes_end(aes));
138  TRY_CHECK_ARRAYS_EQ((uint8_t *)out_data.data, kAesModesPlainText,
139  sizeof(out_data.data));
140  return OK_STATUS();
141 }
142 
143 bool test_main(void) {
144  dif_aes_t aes;
145  CHECK_STATUS_OK(initialize_clkmgr());
146 
147  // Initialise AES.
148  CHECK_DIF_OK(dif_aes_init_from_dt(kDtAes, &aes));
149  CHECK_DIF_OK(dif_aes_reset(&aes));
150 
151  return status_ok(execute_test(&aes));
152 }