Software APIs
kmac_unittest.cc
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 "sw/device/silicon_creator/lib/drivers/kmac.h"
6 
7 #include <array>
8 
9 #include "gtest/gtest.h"
10 #include "sw/device/lib/base/mock_abs_mmio.h"
11 #include "sw/device/silicon_creator/testing/rom_test.h"
12 
14 #include "kmac_regs.h" // Generated.
15 
16 namespace kmac_unittest {
17 namespace {
18 using ::testing::ElementsAreArray;
19 
20 class KmacTest : public rom_test::RomTest {
21  protected:
22  /**
23  * Sets expectations for polling the KMAC block state.
24  *
25  * @param flag Flag value being polled.
26  * @param err Whether to simulate an error.
27  */
28  void ExpectPollState(uint32_t flag, bool err) {
29  // Test assumption: the status flags idle/absorb/squeeze are bits 0..2.
30  static_assert(KMAC_STATUS_SHA3_IDLE_BIT < 3, "");
31  static_assert(KMAC_STATUS_SHA3_ABSORB_BIT < 3, "");
32  static_assert(KMAC_STATUS_SHA3_SQUEEZE_BIT < 3, "");
33 
34  // Calculate the status flags that are not this flag.
35  uint32_t other_status_flag1 = (flag + 1) % 3;
36  uint32_t other_status_flag2 = (flag + 2) % 3;
37 
38  // Return wrong statuses and non-error interrupts a few times; expect to
39  // keep polling (even with non-error interrupts visible).
40  EXPECT_ABS_READ32(base_ + KMAC_INTR_STATE_REG_OFFSET, 0);
41  EXPECT_ABS_READ32(base_ + KMAC_STATUS_REG_OFFSET, 0);
42  EXPECT_ABS_READ32(base_ + KMAC_INTR_STATE_REG_OFFSET,
43  1 << KMAC_INTR_STATE_KMAC_DONE_BIT);
44  EXPECT_ABS_READ32(base_ + KMAC_STATUS_REG_OFFSET, 1 << other_status_flag1);
45  EXPECT_ABS_READ32(base_ + KMAC_INTR_STATE_REG_OFFSET,
46  1 << KMAC_INTR_STATE_FIFO_EMPTY_BIT);
47  EXPECT_ABS_READ32(base_ + KMAC_STATUS_REG_OFFSET, 1 << other_status_flag2);
48 
49  if (err) {
50  // Return an error.
51  EXPECT_ABS_READ32(base_ + KMAC_INTR_STATE_REG_OFFSET,
52  1 << KMAC_INTR_STATE_KMAC_ERR_BIT);
53  EXPECT_ABS_READ32(base_ + KMAC_STATUS_REG_OFFSET, 1 << flag);
54  } else {
55  // Set the expected flag.
56  EXPECT_ABS_READ32(base_ + KMAC_INTR_STATE_REG_OFFSET, 0);
57  EXPECT_ABS_READ32(base_ + KMAC_STATUS_REG_OFFSET, 1 << flag);
58  }
59  }
60  /**
61  * Sets expectations for issuing a KMAC command.
62  *
63  * @param cmd Command value to send.
64  */
65  void ExpectCmdWrite(uint32_t cmd) {
66  EXPECT_ABS_WRITE32(base_ + KMAC_CMD_REG_OFFSET, cmd << KMAC_CMD_CMD_OFFSET);
67  }
68  uint32_t base_ = TOP_EARLGREY_KMAC_BASE_ADDR;
69  const size_t shake256_rate_words_ = (1600 - 512) / 32;
70  const uint32_t share0_addr_ = base_ + KMAC_STATE_REG_OFFSET;
71  const uint32_t share1_addr_ =
72  base_ + KMAC_STATE_REG_OFFSET + (KMAC_STATE_SIZE_BYTES / 2);
73  rom_test::MockAbsMmio abs_mmio_;
74 };
75 
76 class ConfigureTest : public KmacTest {};
77 
78 TEST_F(ConfigureTest, SuccessKeyMgr) {
79  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/false);
80 
81  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_PERIOD_REG_OFFSET,
82  (KMAC_ENTROPY_PERIOD_WAIT_TIMER_MASK
83  << KMAC_ENTROPY_PERIOD_WAIT_TIMER_OFFSET) |
84  (KMAC_ENTROPY_PERIOD_PRESCALER_MASK
85  << KMAC_ENTROPY_PERIOD_PRESCALER_OFFSET));
86 
87  // Expected configuration.
88  uint32_t cfg =
89  (KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256
90  << KMAC_CFG_SHADOWED_KSTRENGTH_OFFSET) |
91  (KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE << KMAC_CFG_SHADOWED_MODE_OFFSET) |
92  (KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_SW_MODE
93  << KMAC_CFG_SHADOWED_ENTROPY_MODE_OFFSET) |
94  (1 << KMAC_CFG_SHADOWED_ENTROPY_READY_BIT) |
95  (1 << KMAC_CFG_SHADOWED_MSG_MASK_BIT) |
96  (1 << KMAC_CFG_SHADOWED_SIDELOAD_BIT);
97 
98  EXPECT_ABS_WRITE32_SHADOWED(base_ + KMAC_CFG_SHADOWED_REG_OFFSET, cfg);
99  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x5d2a3764);
100  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x37d3ecba);
101  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xe1859094);
102  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xb153e3fe);
103  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x09596819);
104  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x3e85a6e8);
105  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xb6dcdaba);
106  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x50dc409c);
107  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x11e1ebd1);
108 
109  EXPECT_EQ(kmac_keymgr_configure(), kErrorOk);
110 }
111 
112 TEST_F(ConfigureTest, Success) {
113  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/false);
114 
115  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_PERIOD_REG_OFFSET,
116  (KMAC_ENTROPY_PERIOD_WAIT_TIMER_MASK
117  << KMAC_ENTROPY_PERIOD_WAIT_TIMER_OFFSET) |
118  (KMAC_ENTROPY_PERIOD_PRESCALER_MASK
119  << KMAC_ENTROPY_PERIOD_PRESCALER_OFFSET));
120 
121  // Expected configuration.
122  uint32_t cfg =
123  (KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256
124  << KMAC_CFG_SHADOWED_KSTRENGTH_OFFSET) |
125  (KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE << KMAC_CFG_SHADOWED_MODE_OFFSET) |
126  (KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_SW_MODE
127  << KMAC_CFG_SHADOWED_ENTROPY_MODE_OFFSET) |
128  (1 << KMAC_CFG_SHADOWED_ENTROPY_READY_BIT);
129 
130  EXPECT_ABS_WRITE32_SHADOWED(base_ + KMAC_CFG_SHADOWED_REG_OFFSET, cfg);
131  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x5d2a3764);
132  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x37d3ecba);
133  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xe1859094);
134  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xb153e3fe);
135  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x09596819);
136  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x3e85a6e8);
137  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0xb6dcdaba);
138  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x50dc409c);
139  EXPECT_ABS_WRITE32(base_ + KMAC_ENTROPY_SEED_REG_OFFSET, 0x11e1ebd1);
140 
141  EXPECT_EQ(kmac_shake256_configure(), kErrorOk);
142 }
143 
144 TEST_F(ConfigureTest, Failure) {
145  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/true);
146  EXPECT_EQ(kmac_shake256_configure(), kErrorKmacInvalidStatus);
147 }
148 
149 class StartTest : public KmacTest {};
150 
151 TEST_F(StartTest, Success) {
152  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/false);
153  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_START);
154 
155  ExpectPollState(KMAC_STATUS_SHA3_ABSORB_BIT, /*err=*/false);
156  EXPECT_EQ(kmac_shake256_start(), kErrorOk);
157 }
158 
159 TEST_F(StartTest, ErrorBeforeStart) {
160  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/true);
161  EXPECT_EQ(kmac_shake256_start(), kErrorKmacInvalidStatus);
162 }
163 
164 TEST_F(StartTest, ErrorAfterStart) {
165  ExpectPollState(KMAC_STATUS_SHA3_IDLE_BIT, /*err=*/false);
166  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_START);
167 
168  ExpectPollState(KMAC_STATUS_SHA3_ABSORB_BIT, /*err=*/true);
169  EXPECT_EQ(kmac_shake256_start(), kErrorKmacInvalidStatus);
170 }
171 
172 class AbsorbTest : public KmacTest {};
173 
174 TEST_F(AbsorbTest, Success) {
175  // Test assumption.
176  static_assert(2 * sizeof(uint32_t) <= KMAC_STATUS_FIFO_DEPTH_MASK,
177  "Message FIFO is too small.");
178 
179  std::array<uint32_t, 2> test_data = {0x12345678, 0xabcdef01};
180 
181  // Expect all test data to be written to the FIFO.
182  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
183  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
184 
185  kmac_shake256_absorb((unsigned char *)test_data.data(),
186  test_data.size() * sizeof(uint32_t));
187 }
188 
189 TEST_F(AbsorbTest, Empty) { kmac_shake256_absorb(NULL, 0); }
190 
191 TEST_F(AbsorbTest, ExtraSpace) {
192  std::array<uint32_t, 3> test_data = {0x12345678, 0xabcdef01, 0x02030405};
193 
194  // Expect all test data to be written to the FIFO.
195  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
196  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
197  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[2]);
198 
199  kmac_shake256_absorb((unsigned char *)test_data.data(),
200  test_data.size() * sizeof(uint32_t));
201 }
202 
203 TEST_F(AbsorbTest, SmallInput) {
204  // Test assumption.
205  static_assert(1 * sizeof(uint32_t) <= KMAC_STATUS_FIFO_DEPTH_MASK,
206  "Message FIFO is too small.");
207 
208  std::array<uint8_t, 2> test_data = {0x78, 0x56};
209 
210  // Input should be written to the FIFO in byte-writes (the input is aligned
211  // but too small for word writes).
212  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
213  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
214 
215  kmac_shake256_absorb(test_data.data(), test_data.size());
216 }
217 
218 TEST_F(AbsorbTest, UnalignedStart) {
219  // Test assumption.
220  static_assert(2 * sizeof(uint32_t) <= KMAC_STATUS_FIFO_DEPTH_MASK,
221  "Message FIFO is too small.");
222 
223  // Create an aligned array, then create an unaligned pointer to the second
224  // byte.
225  std::array<uint32_t, 2> data_aligned = {0x12345678, 0xabcdef01};
226  unsigned char *test_data = (unsigned char *)data_aligned.data() + 1;
227  size_t test_data_len = data_aligned.size() * sizeof(uint32_t) - 1;
228 
229  // First (unaligned) bytes should use byte-wide writes.
230  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
231  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
232  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[2]);
233  // Next (aligned) word of input should use a word-wide write.
234  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, data_aligned[1]);
235 
236  kmac_shake256_absorb(test_data, test_data_len);
237 }
238 
239 TEST_F(AbsorbTest, UnalignedStartAndEnd) {
240  // Test assumption.
241  static_assert(3 * sizeof(uint32_t) <= KMAC_STATUS_FIFO_DEPTH_MASK,
242  "Message FIFO is too small.");
243 
244  // Create an aligned array, then create an unaligned pointer to the third
245  // byte. Use a length which excludes the last two bytes.
246  std::array<uint32_t, 3> data_aligned = {0x12345678, 0xabcdef01, 0x02030405};
247  unsigned char *test_data = (unsigned char *)data_aligned.data() + 2;
248  size_t test_data_len = data_aligned.size() * sizeof(uint32_t) - 4;
249 
250  // First (unaligned) bytes should use byte-wide writes.
251  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
252  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
253  // Expect next word of input (now aligned) to use a word-wide write.
254  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, data_aligned[1]);
255  // Last two bytes should use byte-wide writes.
256  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET,
257  test_data[test_data_len - 2]);
258  EXPECT_ABS_WRITE8(base_ + KMAC_MSG_FIFO_REG_OFFSET,
259  test_data[test_data_len - 1]);
260 
261  kmac_shake256_absorb(test_data, test_data_len);
262 }
263 
264 class AbsorbWordsTest : public KmacTest {};
265 
266 TEST_F(AbsorbWordsTest, Success) {
267  std::array<uint32_t, 3> test_data = {0x12345678, 0xabcdef01, 0x02030405};
268 
269  // Expect all test data to be written to the FIFO.
270  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[0]);
271  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[1]);
272  EXPECT_ABS_WRITE32(base_ + KMAC_MSG_FIFO_REG_OFFSET, test_data[2]);
273 
274  kmac_shake256_absorb_words(test_data.data(), test_data.size());
275 }
276 
277 TEST_F(AbsorbWordsTest, EmptyInput) {
278  // Nothing should happen.
279  kmac_shake256_absorb_words(NULL, 0);
280 }
281 
282 class SqueezeTest : public KmacTest {};
283 
284 TEST_F(SqueezeTest, Success) {
285  std::array<uint32_t, 3> test_data = {0x12345678, 0xabcdef01, 0x02030405};
286  std::array<uint32_t, 3> test_mask = {0xabcdef01, 0x02030405, 0x00000000};
287 
288  // Test assumption: test data fits in SHAKE-256 rate.
289  ASSERT_LE(test_data.size(), shake256_rate_words_);
290 
291  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
292 
293  // Expect all data to be read from the state, one share at a time.
294  for (size_t i = 0; i < test_data.size(); i++) {
295  EXPECT_ABS_READ32(share0_addr_ + (i * sizeof(uint32_t)), test_mask[i]);
296  EXPECT_ABS_READ32(share1_addr_ + (i * sizeof(uint32_t)),
297  test_data[i] ^ test_mask[i]);
298  }
299 
300  // End
301  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
302  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_DONE);
303 
304  uint32_t out[test_data.size()];
305  EXPECT_EQ(kmac_shake256_squeeze_end(out, test_data.size()), kErrorOk);
306  EXPECT_THAT(out, ElementsAreArray(test_data));
307 }
308 
309 TEST_F(SqueezeTest, SuccessStart) {
310  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_PROCESS);
311 
312  kmac_shake256_squeeze_start();
313 }
314 
315 TEST_F(SqueezeTest, StartAndEndEmpty) {
316  // Start
317  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_PROCESS);
318  kmac_shake256_squeeze_start();
319 
320  // End
321  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
322  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_DONE);
323 
324  EXPECT_EQ(kmac_shake256_squeeze_end(NULL, 0), kErrorOk);
325 }
326 
327 TEST_F(SqueezeTest, StartAndEndNonEmpty) {
328  std::array<uint32_t, 3> test_data = {0x12345678, 0xabcdef01, 0x02030405};
329  std::array<uint32_t, 3> test_mask = {0xabcdef01, 0x02030405, 0x00000000};
330 
331  // Test assumption: test data fits in SHAKE-256 rate.
332  ASSERT_LE(test_data.size(), shake256_rate_words_);
333 
334  // Start
335  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_PROCESS);
336  kmac_shake256_squeeze_start();
337 
338  // Squeeze
339  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
340  for (size_t i = 0; i < test_data.size(); i++) {
341  EXPECT_ABS_READ32(share0_addr_ + (i * sizeof(uint32_t)), test_mask[i]);
342  EXPECT_ABS_READ32(share1_addr_ + (i * sizeof(uint32_t)),
343  test_data[i] ^ test_mask[i]);
344  }
345 
346  // End
347  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
348  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_DONE);
349 
350  uint32_t out[test_data.size()];
351  EXPECT_EQ(kmac_shake256_squeeze_end(out, test_data.size()), kErrorOk);
352  EXPECT_THAT(out, ElementsAreArray(test_data));
353 }
354 
355 TEST_F(SqueezeTest, LongOutput) {
356  // Note: for this test, it is important that the Keccak rate for SHAKE-256 is
357  // (1600 - (security strength * 2)) = 1088 bits = 34 words.
358  std::array<uint32_t, 100> test_data; // 0, 1, 2... 99
359  std::array<uint32_t, 100> test_mask; // 100, 99, 98,... 1
360  for (size_t i = 0; i < test_data.size(); i++) {
361  test_data[i] = i;
362  test_mask[i] = test_data.size() - i;
363  }
364 
365  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
366 
367  // Read remaining bits of state from offset..rate.
368  // After this, we should have squeezed 34 out of 100 words.
369  for (size_t i = 0; i < shake256_rate_words_; i++) {
370  EXPECT_ABS_READ32(share0_addr_ + i * sizeof(uint32_t), test_mask[i]);
371  EXPECT_ABS_READ32(share1_addr_ + i * sizeof(uint32_t),
372  test_data[i] ^ test_mask[i]);
373  }
374 
375  // Expect a `RUN` command and a repeated polling.
376  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_RUN);
377  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
378 
379  // Read all available state bits.
380  // After this, we should have squeezed 68 out of 100 words.
381  size_t offset = shake256_rate_words_;
382  for (size_t i = 0; i < shake256_rate_words_; i++) {
383  EXPECT_ABS_READ32(share0_addr_ + i * sizeof(uint32_t),
384  test_mask[offset + i]);
385  EXPECT_ABS_READ32(share1_addr_ + i * sizeof(uint32_t),
386  test_data[offset + i] ^ test_mask[offset + i]);
387  }
388 
389  // Expect a `RUN` command and a repeated polling.
390  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_RUN);
391  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
392 
393  // Read the last 32 requested words.
394  offset += shake256_rate_words_;
395  for (size_t i = 0; i < test_data.size() - (2 * shake256_rate_words_); i++) {
396  EXPECT_ABS_READ32(share0_addr_ + i * sizeof(uint32_t),
397  test_mask[offset + i]);
398  EXPECT_ABS_READ32(share1_addr_ + i * sizeof(uint32_t),
399  test_data[offset + i] ^ test_mask[offset + i]);
400  }
401 
402  // End
403  ExpectPollState(KMAC_STATUS_SHA3_SQUEEZE_BIT, /*err=*/false);
404  ExpectCmdWrite(KMAC_CMD_CMD_VALUE_DONE);
405 
406  uint32_t out[test_data.size()];
407  EXPECT_EQ(kmac_shake256_squeeze_end(out, test_data.size()), kErrorOk);
408  EXPECT_THAT(out, ElementsAreArray(test_data));
409 }
410 
411 } // namespace
412 } // namespace kmac_unittest