Software APIs
hmac_enc_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 "dt/dt_hmac.h"
10 #include "sw/device/lib/testing/clkmgr_testutils.h"
11 #include "sw/device/lib/testing/hmac_testutils.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 #define TIMEOUT (1000 * 1000)
16 
17 OTTF_DEFINE_TEST_CONFIG();
18 static_assert(kDtHmacCount >= 1,
19  "This test requires at least one HMAC instance");
20 
21 static const dt_hmac_t kTestHmac = (dt_hmac_t)0;
22 
23 static dif_hmac_t hmac;
24 static dif_clkmgr_t clkmgr;
25 static dif_clkmgr_hintable_clock_t hmac_clock;
26 
27 static const dif_hmac_transaction_t kHmacTransactionConfig = {
29  .message_endianness = kDifHmacEndiannessLittle,
30 };
31 
32 static bool is_hintable_clock_enabled(const dif_clkmgr_t *clkmgr,
34  dif_toggle_t clock_state;
35  CHECK_DIF_OK(
36  dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &clock_state));
37  return clock_state == kDifToggleEnabled;
38 }
39 
40 static status_t initialize_clkmgr(dif_clkmgr_hintable_clock_t clock) {
41  CHECK_DIF_OK(dif_clkmgr_init_from_dt(kDtClkmgrAon, &clkmgr));
42  CHECK_DIF_OK(dif_clkmgr_find_hintable_clock(
43  &clkmgr, dt_hmac_instance_id(kTestHmac), &hmac_clock));
44 
45  // Get initial hint and enable for AES clock and check both are enabled.
46  dif_toggle_t clock_hint_state;
47  CHECK_DIF_OK(
48  dif_clkmgr_hintable_clock_get_hint(&clkmgr, clock, &clock_hint_state));
49  CHECK(clock_hint_state == kDifToggleEnabled);
50  return CLKMGR_TESTUTILS_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleEnabled);
51 }
52 
53 // This waits for the process to end with a looming hint, checks the hint status
54 // shows the clock is disabled, and reanable it. The check for process
55 // completion cannot be done using hmac registers since the clock will be
56 // disabled as soon as the process ends, so we just wait for the clkmgr hint
57 // status to indicate the clock is off, implying the process actually ended.
58 static status_t handle_end_of_process(dif_clkmgr_hintable_clock_t clock) {
59  IBEX_SPIN_FOR(!is_hintable_clock_enabled(&clkmgr, clock), TIMEOUT);
60  LOG_INFO("Done");
61 
62  // After the AES operation is complete verify that the AES clk hint status
63  // within clkmgr now reads 0 again (AES is idle).
64  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleDisabled,
66 
67  // Write the HMAC clk hint to 1, read and check the HMAC output for
68  // correctness.
69  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleEnabled,
71  return OK_STATUS();
72 }
73 
74 static status_t execute_test(void) {
75  // With the HMAC unit idle, write the HMAC clk hint to 0 within clkmgr to
76  // indicate HMAC clk can be gated and verify that the HMAC clk hint status
77  // within clkmgr reads 0 (HMAC is disabled).
78  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
79  clkmgr, hmac_clock, kDifToggleDisabled, kDifToggleDisabled);
80 
81  // Write the HMAC clk hint to 1 within clkmgr to indicate HMAC clk can be
82  // enabled.
83  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
84  clkmgr, hmac_clock, kDifToggleEnabled, kDifToggleEnabled);
85 
86  // Use HMAC in SHA256 mode to generate a 256bit key from `kHmacRefLongKey`.
87  CHECK_DIF_OK(dif_hmac_mode_sha256_start(&hmac, kHmacTransactionConfig));
88  TRY(hmac_testutils_push_message(&hmac, (char *)kHmacRefLongKey,
89  sizeof(kHmacRefLongKey)));
90  LOG_INFO("Pushed message");
91  CHECK_STATUS_OK(
92  hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefLongKey) * 8));
93  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
94  clkmgr, hmac_clock, kDifToggleDisabled, kDifToggleEnabled);
95  LOG_INFO("Cleared hints");
96  CHECK_DIF_OK(dif_hmac_process(&hmac));
97  LOG_INFO("Process");
98 
99  CHECK_STATUS_OK(handle_end_of_process(hmac_clock));
100 
101  dif_hmac_digest_t key_digest;
102  CHECK_STATUS_OK(hmac_testutils_finish_polled(&hmac, &key_digest));
103  CHECK_ARRAYS_EQ(key_digest.digest, kHmacRefExpectedLongKeyDigest.digest,
104  ARRAYSIZE(key_digest.digest));
105 
106  // Generate HMAC final digest, using the resulted SHA256 digest over the
107  // `kHmacRefLongKey`.
108  CHECK_DIF_OK(dif_hmac_mode_hmac_start(&hmac, (uint8_t *)&key_digest.digest[0],
109  kHmacTransactionConfig));
110  CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
111  clkmgr, hmac_clock, kDifToggleDisabled, kDifToggleEnabled);
112  LOG_INFO("Cleared hints");
113  CHECK_STATUS_OK(
114  hmac_testutils_push_message(&hmac, kHmacRefData, sizeof(kHmacRefData)));
115  CHECK_STATUS_OK(
116  hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefData) * 8));
117  CHECK_DIF_OK(dif_hmac_process(&hmac));
118  LOG_INFO("Process");
119 
120  CHECK_STATUS_OK(handle_end_of_process(hmac_clock));
121 
122  return hmac_testutils_finish_and_check_polled(&hmac, &kHmacRefExpectedDigest);
123 }
124 
125 bool test_main(void) {
126  CHECK_STATUS_OK(initialize_clkmgr(hmac_clock));
127 
128  CHECK_DIF_OK(dif_hmac_init_from_dt(kTestHmac, &hmac));
129 
130  return status_ok(execute_test());
131 }