Software APIs
kmac_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_clkmgr.h" // Generated
6 #include "dt/dt_kmac.h" // Generated
11 #include "sw/device/lib/testing/test_framework/check.h"
13 
14 static_assert(kDtKmacCount >= 1, "this test requires at least one kmac");
15 const dt_kmac_t kKmacDt = (dt_kmac_t)0;
16 
17 static dif_clkmgr_t clkmgr;
18 static dif_kmac_t kmac;
19 
20 OTTF_DEFINE_TEST_CONFIG();
21 
23 
24 #define TIMEOUT (1000 * 1000)
25 
26 // Digest lengths in 32-bit words.
27 #define DIGEST_LEN_SHA3_256 (256 / 32)
28 #define DIGEST_LEN_SHA3_512 (512 / 32)
29 #define DIGEST_LEN_SHA3_MAX DIGEST_LEN_SHA3_512
30 
31 // SHA-3 test description.
32 typedef struct sha3_test {
34 
35  const char *message;
36  size_t message_len;
37 
38  const uint32_t digest[DIGEST_LEN_SHA3_MAX];
39  size_t digest_len;
40 } sha3_test_t;
41 
42 // SHA-3 test.
43 const sha3_test_t sha3_256_test = {
44  // Example taken from NIST FIPS-202 Algorithm Test Vectors:
45  // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
46  .mode = kDifKmacModeSha3Len256,
47  .message = "\xe7\x37\x21\x05",
48  .message_len = 4,
49  .digest = {0x8ab6423a, 0x8cf279b0, 0x52c7a34c, 0x90276f29, 0x78fec406,
50  0xd979ebb1, 0x057f7789, 0xae46401e},
51  .digest_len = DIGEST_LEN_SHA3_256};
52 
53 static void check_clock_state(dif_toggle_t expected_clock_state) {
54  dif_toggle_t clock_state;
55  CHECK_DIF_OK(
56  dif_clkmgr_hintable_clock_get_enabled(&clkmgr, kmac_clock, &clock_state));
57  CHECK(clock_state == expected_clock_state,
58  "Clock enabled state is not as expected (%d).", expected_clock_state);
59 }
60 
61 static bool is_hintable_clock_enabled(const dif_clkmgr_t *clkmgr,
63  dif_toggle_t clock_state;
64  CHECK_DIF_OK(
65  dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &clock_state));
66  return clock_state == kDifToggleEnabled;
67 }
68 
69 static void do_sha3_test(void) {
70  dif_kmac_operation_state_t kmac_operation_state;
71  // Run SHA3 test case using single blocking absorb/squeeze operations.
72  CHECK_DIF_OK(dif_kmac_mode_sha3_start(&kmac, &kmac_operation_state,
73  sha3_256_test.mode));
74 
75  // Set hint and check clk state remains enabled as KMAC is now not idle.
76  CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
78  check_clock_state(kDifToggleEnabled);
79 
80  CHECK_DIF_OK(dif_kmac_absorb(&kmac, &kmac_operation_state,
81  sha3_256_test.message, sha3_256_test.message_len,
82  NULL));
83 
84  uint32_t out[DIGEST_LEN_SHA3_MAX];
85  CHECK_DIF_OK(dif_kmac_squeeze(&kmac, &kmac_operation_state, out,
86  sha3_256_test.digest_len, /*processed=*/NULL,
87  /*capacity=*/NULL));
88 
89  // Check clock state again which should still be enabled.
90  check_clock_state(kDifToggleEnabled);
91 
92  CHECK_DIF_OK(dif_kmac_end(&kmac, &kmac_operation_state));
93 
94  // On FPGA, it may take a while until the DONE command gets actually executed
95  // (see SecCmdDelay SystemVerilog parameter). However, once the clock is
96  // disabled, KMAC cannot be accessed anymore. Thus polling the KMAC status
97  // register doesn't work. Instead, wait for the clock to stop.
98  IBEX_SPIN_FOR(!is_hintable_clock_enabled(&clkmgr, kmac_clock), TIMEOUT);
99 
100  // Check the clock is now stopped.
101  check_clock_state(kDifToggleDisabled);
102 
103  // Check the result to be sure the SHA3 operation completed correctly.
104  CHECK_ARRAYS_EQ(out, sha3_256_test.digest, sha3_256_test.digest_len,
105  "Digest mismatch for test SHA3 256.");
106 
107  // Set hint to enabled again to check that clock can be re-enabled.
108  CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
110  check_clock_state(kDifToggleEnabled);
111 }
112 
113 bool test_main(void) {
114  CHECK_DIF_OK(dif_clkmgr_init_from_dt(kDtClkmgrAon, &clkmgr));
115  CHECK_DIF_OK(dif_clkmgr_find_hintable_clock(
116  &clkmgr, dt_kmac_instance_id(kKmacDt), &kmac_clock));
117 
118  // Get initial hint and enable for KMAC clock and check both are enabled.
119  dif_toggle_t clock_hint_state;
120  CHECK_DIF_OK(dif_clkmgr_hintable_clock_get_hint(&clkmgr, kmac_clock,
121  &clock_hint_state));
122  CHECK(clock_hint_state == kDifToggleEnabled);
123  check_clock_state(kDifToggleEnabled);
124 
125  // While KMAC is not in use, set disabled hint for KMAC clock
126  // then check clock state, set back to enabled and check again.
127  // Note: disabled means the clock can be disabled.
128  CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
130  check_clock_state(kDifToggleDisabled);
131  CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
133  check_clock_state(kDifToggleEnabled);
134 
135  // Initialize KMAC hardware.
136  static_assert(kDtKmacCount > 0, "This test requires a KMAC instance");
137  CHECK_DIF_OK(dif_kmac_init_from_dt(kKmacDt, &kmac));
138 
139  // Configure KMAC hardware using software entropy.
141  .entropy_mode = kDifKmacEntropyModeSoftware,
142  .entropy_seed = {0xb153e3fe, 0x09596819, 0x3e85a6e8, 0xb6dcdaba,
143  0x50dc409c, 0x11e1ebd1},
144  .entropy_fast_process = kDifToggleEnabled,
145  };
146  CHECK_DIF_OK(dif_kmac_configure(&kmac, config));
147 
148  // call sha3 test twice to check that when clock
149  // is enabled again after the first call
150  // that all still works for the second call.
151 
152  do_sha3_test();
153  do_sha3_test();
154 
155  return true;
156 }