Software APIs
kmac_error_conditions_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 
11 #include "sw/device/lib/testing/keymgr_testutils.h"
12 #include "sw/device/lib/testing/kmac_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 
17 #include "keymgr_regs.h" // Generated.
18 #include "kmac_regs.h" // Generated.
19 
20 static dif_kmac_t kmac;
21 static dif_keymgr_t keymgr;
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 /**
26  * KMAC test description.
27  */
28 typedef struct kmac_test {
30  dif_kmac_key_t key;
31 
32  const char *message;
33  size_t message_len;
34 
35  const char *customization_string;
36  size_t customization_string_len;
37 
38  const uint32_t digest[16];
39  size_t digest_len;
40  bool digest_len_is_fixed;
41 } kmac_test_t;
42 
43 /**
44  * A single KMAC example taken from:
45  * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
46  */
47 static const kmac_test_t kKmacTestVector = {
48  .mode = kDifKmacModeKmacLen256,
49  .key =
51  .share0 = {0x43424140, 0x47464544, 0x4b4a4948, 0x4f4e4f4c,
52  0x53525150, 0x57565554, 0x5b5a5958, 0x5f5e5d5c},
53  .share1 = {0},
54  .length = kDifKmacKeyLen256,
55  },
56  .message =
57  "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
58  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
59  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
60  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
61  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
62  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
63  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
64  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
65  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
66  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
67  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
68  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
69  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
70  .message_len = 200,
71  .customization_string = "My Tagged Application",
72  .customization_string_len = 21,
73  .digest = {0x1c73bed5, 0x73d74e95, 0x59bb4628, 0xe3a8e3db, 0x7ae7830f,
74  0x5944ff4b, 0xb4c2f1f2, 0xceb8ebec, 0xc601ba67, 0x57b88a2e,
75  0x9b492d8d, 0x6727bbd1, 0x90117868, 0x6a300a02, 0x1d28de97,
76  0x5d3030cc},
77  .digest_len = 16,
78  .digest_len_is_fixed = false,
79 };
80 
81 /**
82  * Init key manager.
83  *
84  * @return OK or error.
85  */
86 status_t setup_keymgr(void) {
87  // Initialize keymgr and advance to the state specified by the loaded ROM.
88  TRY(keymgr_testutils_initialize(&keymgr, &kmac));
89 
90  return OK_STATUS();
91 }
92 
93 /**
94  * Poll the SHA3_IDLE bit.
95  *
96  * @param kmac The KMAC handle.
97  */
98 void poll_sha3_idle_bit(const dif_kmac_t *kmac) {
99  uint32_t reg;
100  do {
101  reg = mmio_region_read32(kmac->base_addr, KMAC_STATUS_REG_OFFSET);
102  } while (!bitfield_bit32_read(reg, KMAC_STATUS_SHA3_IDLE_BIT));
103 }
104 
105 /**
106  * Poll the KMAC_DONE bit.
107  *
108  * @param kmac The KMAC handle.
109  */
110 void poll_kmac_done_bit(const dif_kmac_t *kmac) {
111  uint32_t reg;
112  do {
113  reg = mmio_region_read32(kmac->base_addr, KMAC_INTR_STATE_REG_OFFSET);
114  } while (!bitfield_bit32_read(reg, KMAC_INTR_STATE_KMAC_DONE_BIT));
115 }
116 
117 /**
118  * Check and clear the KMAC error.
119  *
120  * Performs the following:
121  * - Check whether error interrupt was seen.
122  * - Check whether the expected error was seen.
123  * - Clears the error interrupt.
124  * - Sets the error processed bit.
125  * - Reset the KMAC IP.
126  * - Waits until KMAC again gets ready.
127  * - Waits until the KMAC_DONE bit is seen.
128  *
129  * @param kmac The KMAC handle.
130  * @param exp_err The expected error.
131  * @param wait_done Wait for kmac_done bit. Not needed for tests that don't
132  * start KMAC.
133  * @return OK or error.
134  */
135 status_t check_and_clear_error(const dif_kmac_t *kmac, dif_kmac_error_t exp_err,
136  bool wait_done) {
137  dif_kmac_error_t err;
138  dif_kmac_operation_state_t kmac_operation_state;
139  uint32_t info;
140  bool error;
141 
142  // Check whether the KMAC ERR bit was set in the interrupt state register.
143  TRY(dif_kmac_has_error_occurred(kmac, &error));
144  TRY_CHECK(error, "No error was triggered.");
145 
146  TRY(dif_kmac_get_error(kmac, &err, &info));
147  TRY_CHECK(err == exp_err, "Unexpected error was triggered.");
148 
149  // Clear the error IRQ.
150  TRY(dif_kmac_clear_err_irq(kmac));
151  // Set err_processed bit.
152  TRY(dif_kmac_err_processed(kmac));
153  // Reset the KMAC IP.
154  TRY(dif_kmac_reset(kmac, &kmac_operation_state));
155 
156  // Wait until sha3_idle is again set.
157  poll_sha3_idle_bit(kmac);
158 
159  // Wait until KMAC flags the done bit.
160  if (wait_done) {
161  poll_kmac_done_bit(kmac);
162  }
163 
164  return OK_STATUS();
165 }
166 
167 /**
168  * ErrWaitTimerExpired.
169  *
170  * This test checks whether the ErrWaitTimerExpired error code is
171  * returned by the hardware when KMAC timed out while waiting for EDN entropy.
172  * By configuring a small wait timer (=1), the timeout immediately will be
173  * triggered and we should see the expected error code.
174  *
175  * @return OK or error.
176  */
177 status_t test_err_wait_timer_expired(void) {
178  LOG_INFO("Testing ErrWaitTimerExpired error.");
179 
180  // Init the KMAC block.
181  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
182 
183  const dif_kmac_config_t config = (dif_kmac_config_t){
184  .entropy_mode = kDifKmacEntropyModeEdn,
185  .entropy_wait_timer = 0x001, // Small wait time out to trigger the error.
186  .entropy_prescaler = 0x000,
187  .entropy_fast_process = kDifToggleDisabled,
188  .entropy_seed = {0xaa25b4bf, 0x48ce8fff, 0x5a78282a, 0x48465647,
189  0x70410fef},
190  .message_big_endian = kDifToggleDisabled,
191  .output_big_endian = kDifToggleDisabled,
192  .sideload = kDifToggleDisabled,
193  .msg_mask = kDifToggleEnabled,
194  };
195 
196  TRY(dif_kmac_configure(&kmac, config));
197 
198  dif_kmac_operation_state_t kmac_operation_state;
199  TRY(dif_kmac_mode_kmac_start(&kmac, &kmac_operation_state,
200  kKmacTestVector.mode, 0, &kKmacTestVector.key,
201  NULL));
202 
203  TRY(dif_kmac_absorb(&kmac, &kmac_operation_state, kKmacTestVector.message,
204  kKmacTestVector.message_len, NULL));
205 
206  // This is where timeout might happen, so we handle dif return manually.
207  uint32_t digest[kKmacTestVector.digest_len];
208  dif_result_t res = dif_kmac_squeeze(&kmac, &kmac_operation_state, digest,
209  kKmacTestVector.digest_len,
210  /*processed=*/NULL, /*capacity=*/NULL);
211 
212  // It is OK to get kDifError at this point because of possible timeout.
213  TRY_CHECK(res == kDifOk || res == kDifError);
214 
215  // Check if there is a new error.
216  bool irq_err_pending;
217  TRY(dif_kmac_irq_is_pending(&kmac, kDifKmacIrqKmacErr, &irq_err_pending));
218  if (irq_err_pending) {
219  dif_kmac_error_t err_status;
220  uint32_t err_info;
221  TRY(dif_kmac_get_error(&kmac, &err_status, &err_info));
222  TRY_CHECK(err_status == kDifErrorEntropyWaitTimerExpired,
223  "Error other than EDN timeout occurred.");
224  LOG_INFO("EDN timed out.");
225  } else {
226  LOG_INFO("EDN seed received before timeout.");
227  }
228 
229  // At this point, irq_err_pending says if timeout is observed
230  TRY_CHECK(irq_err_pending == true,
231  "EDN timeout expectation doesn't match observation.");
232 
233  // Flush out the result and check correctness
234  TRY(dif_kmac_end(&kmac, &kmac_operation_state));
235 
236  // If err interrupt is generated, we need clean-up
237  if (irq_err_pending) {
238  // Clean INTR_STATE
239  TRY(dif_kmac_irq_acknowledge_all(&kmac));
240 
241  // Reset FSM by setting `err_processed` bit
242  TRY(dif_kmac_reset(&kmac, &kmac_operation_state));
243 
244  // At this point, we expect that there are no remaining interrupts.
245  dif_kmac_irq_state_snapshot_t intr_snapshot;
246  TRY(dif_kmac_irq_get_state(&kmac, &intr_snapshot));
247  TRY_CHECK(intr_snapshot == 0,
248  "INTR_STATE is non-zero after timeout clean-up.");
249 
250  bool is_kmac_locked;
251  TRY(dif_kmac_config_is_locked(&kmac, &is_kmac_locked));
252  TRY_CHECK(!is_kmac_locked, "KMAC still locked after timeout clean-up.");
253  }
254 
255  return OK_STATUS();
256 }
257 
258 /**
259  * ErrIncorrectEntropyMode.
260  *
261  * This test checks whether the ErrIncorrectEntropyMode error code is
262  * returned by the hardware when using a wrong entropy mode configuration.
263  *
264  * @return OK or error.
265  */
266 status_t test_err_incorrect_entropy_mode(void) {
267  LOG_INFO("Testing ErrIncorrectEntropyMode error.");
268 
269  // Re-init KMAC for the test.
270  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
271 
272  // Write configuration register.
273  uint32_t cfg_reg = 0;
274  // Provide invalid entropy mode (other than kDifKmacEntropyModeSoftware or
275  // kDifKmacEntropyModeEdn)
276  cfg_reg = bitfield_field32_write(cfg_reg,
277  KMAC_CFG_SHADOWED_ENTROPY_MODE_FIELD, 0xf);
278  // Set remaining config to a valid one.
279  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_MSG_ENDIANNESS_BIT,
281  cfg_reg = bitfield_bit32_write(
282  cfg_reg, KMAC_CFG_SHADOWED_STATE_ENDIANNESS_BIT, kDifToggleDisabled);
283  cfg_reg = bitfield_bit32_write(
284  cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_FAST_PROCESS_BIT, kDifToggleDisabled);
285  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_SIDELOAD_BIT,
287  cfg_reg =
288  bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_READY_BIT, true);
289  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_MSG_MASK_BIT,
291  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
292  cfg_reg);
293 
294  // Check whether we got the expected error.
295  return check_and_clear_error(&kmac, kDifErrorEntropyModeIncorrect, false);
296 }
297 
298 /**
299  * ErrSwHashingWithoutEntropyReady.
300  *
301  * This test checks whether the ErrSwHashingWithoutEntropyReady error code is
302  * returned by the hardware when the entropy is not ready within the KMAC IP
303  * block.
304  *
305  * @return OK or error.
306  */
307 status_t test_err_sw_hashing_without_entropy_ready(void) {
308  LOG_INFO("Testing ErrSwHashingWithoutEntropyReady error.");
309 
310  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
311 
312  // Manually init the KMAC block and do not set entropy_ready bit.
313  // Write entropy period register.
314  uint32_t entropy_period_reg = 0;
315  entropy_period_reg = bitfield_field32_write(
316  entropy_period_reg, KMAC_ENTROPY_PERIOD_WAIT_TIMER_FIELD, 0);
317  entropy_period_reg = bitfield_field32_write(
318  entropy_period_reg, KMAC_ENTROPY_PERIOD_PRESCALER_FIELD, 0);
319  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_PERIOD_REG_OFFSET,
320  entropy_period_reg);
321 
322  // Write threshold register.
323  uint32_t entropy_threshold_reg =
324  KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_REG_RESVAL;
325  entropy_threshold_reg = bitfield_field32_write(
326  entropy_threshold_reg,
327  KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_THRESHOLD_FIELD, 0);
328  mmio_region_write32_shadowed(
329  kmac.base_addr, KMAC_ENTROPY_REFRESH_THRESHOLD_SHADOWED_REG_OFFSET,
330  entropy_threshold_reg);
331  // Write configuration register.
332  uint32_t cfg_reg = 0;
333  // Set entropy ready bit to false in order to trigger the error we want to
334  // see.
335  cfg_reg =
336  bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_READY_BIT, false);
337  cfg_reg =
338  bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_MODE_FIELD,
339  KMAC_CFG_SHADOWED_ENTROPY_MODE_VALUE_EDN_MODE);
340  cfg_reg = bitfield_bit32_write(
341  cfg_reg, KMAC_CFG_SHADOWED_ENTROPY_FAST_PROCESS_BIT, kDifToggleDisabled);
342  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_SIDELOAD_BIT,
344  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_MSG_MASK_BIT,
346  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
347  cfg_reg);
348  // Write entropy seed registers.
349  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_SEED_REG_OFFSET, 0xaa25b4bf);
350  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_SEED_REG_OFFSET, 0x48ce8fff);
351  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_SEED_REG_OFFSET, 0x5a78282a);
352  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_SEED_REG_OFFSET, 0x48465647);
353  mmio_region_write32(kmac.base_addr, KMAC_ENTROPY_SEED_REG_OFFSET, 0x70410fef);
354 
355  // Configure cSHAKE mode with the given strength and enable KMAC mode.
356  cfg_reg = mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
357  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, true);
358  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
359  KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256);
360  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
361  KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
362  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
363  cfg_reg);
364 
365  // Write prefix to module.
366  uint32_t prefix_regs[11] = {
367  0x4D4B2001, // 1 32 'K' 'M'
368  0x00014341, // 'A' 'C' 1 0
369  };
370  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
371  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
372  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
373  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
374  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
375  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
376  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
377  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
378  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
379  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
380  mmio_region_write32(kmac.base_addr, KMAC_PREFIX_10_REG_OFFSET,
381  prefix_regs[10]);
382 
383  // Issue START command.
384  uint32_t cmd_reg =
385  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
386  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
387 
388  // Check whether we got the expected error.
389  return check_and_clear_error(
390  &kmac, kDifErrorSoftwareHashingWithoutEntropyReady, false);
391 }
392 
393 /**
394  * ErrorIncorrectFunctionName.
395  *
396  * This test checks whether the kDifErrorIncorrectFunctionName error code is
397  * returned by the hardware when using a wrong (i.e., other than "KMAC")
398  * function name when in KMAC mode.
399  *
400  * @return OK or error.
401  */
402 status_t test_err_incorrect_fnc_name(void) {
403  LOG_INFO("Testing kDifErrorIncorrectFunctionName error.");
404  // Re-init KMAC for the test.
405  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
406  TRY(kmac_testutils_config(&kmac, false));
407 
408  // Configure cSHAKE mode with the given strength and enable KMAC mode.
409  uint32_t cfg_reg =
410  mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
411  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, true);
412  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
413  KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256);
414  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
415  KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
416  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
417  cfg_reg);
418 
419  // Expected function name is "KMAC", set it to something different in order to
420  // trigger the expected error.
421  uint32_t prefix_regs[11];
422  memset(&prefix_regs, 0xff, ARRAYSIZE(prefix_regs) * sizeof(uint32_t));
423 
424  // Write PREFIX register values.
425  const mmio_region_t base = kmac.base_addr;
426  mmio_region_write32(base, KMAC_PREFIX_0_REG_OFFSET, prefix_regs[0]);
427  mmio_region_write32(base, KMAC_PREFIX_1_REG_OFFSET, prefix_regs[1]);
428  mmio_region_write32(base, KMAC_PREFIX_2_REG_OFFSET, prefix_regs[2]);
429  mmio_region_write32(base, KMAC_PREFIX_3_REG_OFFSET, prefix_regs[3]);
430  mmio_region_write32(base, KMAC_PREFIX_4_REG_OFFSET, prefix_regs[4]);
431  mmio_region_write32(base, KMAC_PREFIX_5_REG_OFFSET, prefix_regs[5]);
432  mmio_region_write32(base, KMAC_PREFIX_6_REG_OFFSET, prefix_regs[6]);
433  mmio_region_write32(base, KMAC_PREFIX_7_REG_OFFSET, prefix_regs[7]);
434  mmio_region_write32(base, KMAC_PREFIX_8_REG_OFFSET, prefix_regs[8]);
435  mmio_region_write32(base, KMAC_PREFIX_9_REG_OFFSET, prefix_regs[9]);
436  mmio_region_write32(base, KMAC_PREFIX_10_REG_OFFSET, prefix_regs[10]);
437 
438  // Issue START command.
439  uint32_t cmd_reg =
440  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
441  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
442  // The error should have been triggered after issuing the START command.
443  // Manually finish the KMAC operation in order to again reach the IDLE state.
444  dif_kmac_operation_state_t kmac_operation_state;
445  kmac_operation_state.r = 34;
446  kmac_operation_state.squeezing = false;
447  kmac_operation_state.offset = 0;
448  kmac_operation_state.d = 0;
449  kmac_operation_state.append_d = false;
450  TRY(dif_kmac_absorb(&kmac, &kmac_operation_state, kKmacTestVector.message,
451  kKmacTestVector.message_len, NULL));
452  TRY(dif_kmac_squeeze(&kmac, &kmac_operation_state, NULL, 0,
453  /*processed=*/NULL, /*capacity=*/NULL));
454  TRY(dif_kmac_end(&kmac, &kmac_operation_state));
455 
456  // Check whether we got the expected error.
457  return check_and_clear_error(&kmac, kDifErrorIncorrectFunctionName, true);
458 }
459 
460 /**
461  * ErrKeyNotValid.
462  *
463  * This test checks whether the ErrKeyNotValid error code is returned by the
464  * hardware when an invalid key is provided.
465  *
466  * @return OK or error.
467  */
468 status_t test_err_key_not_valid(void) {
469  LOG_INFO("Testing ErrKeyNotValid error.");
470  // Re-init KMAC for the test.
471  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
472  // Configure KMAC to use the sideloaded key.
473  TRY(kmac_testutils_config(&kmac, true));
474 
475  // Start the KMAC operation without setting a valid sideloaded key. The
476  // provided SW key is ignored as we configured KMAC to use the sideloaded key.
477  dif_kmac_operation_state_t kmac_operation_state;
478  TRY(dif_kmac_mode_kmac_start(&kmac, &kmac_operation_state,
479  kKmacTestVector.mode, 0, &kKmacTestVector.key,
480  NULL));
481 
482  // Check whether we got the expected error.
483  return check_and_clear_error(&kmac, kDifErrorKeyNotValid, true);
484 }
485 
486 /**
487  * Shadow register update alert.
488  *
489  * This test checks whether the recoverable alert gets triggered when a shadow
490  * register update error occurs. For this test, the KMAC_CFG_SHADOWED register
491  * is written twice with two different configurations.
492  *
493  * @return OK or error.
494  */
495 status_t test_err_shadow_reg_update(void) {
496  LOG_INFO("Testing shadow register update error.");
497 
498  // Init the KMAC block.
499  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
500 
501  // Configure KMAC hardware.
502  TRY(kmac_testutils_config(&kmac, false));
503  // Configure some valid mode and strength.
504  uint32_t cfg_reg =
505  mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
506  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
507  KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L256);
508  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
509  KMAC_CFG_SHADOWED_MODE_VALUE_CSHAKE);
510  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, true);
511  // Only write once to the register.
512  mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
513  // Change the value of one config bit and write again.
514  cfg_reg = bitfield_bit32_write(cfg_reg, KMAC_CFG_SHADOWED_KMAC_EN_BIT, false);
515  mmio_region_write32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET, cfg_reg);
516 
517  // On a mismatch between first and second write, the recoverable alert should
518  // trigger.
519  uint32_t status_reg =
520  mmio_region_read32(kmac.base_addr, KMAC_STATUS_REG_OFFSET);
521  TRY_CHECK(bitfield_bit32_read(status_reg,
522  KMAC_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_BIT),
523  "No recoverable alert occured.");
524 
525  // Reset the KMAC FSM.
526  dif_kmac_operation_state_t kmac_operation_state;
527  TRY(dif_kmac_reset(&kmac, &kmac_operation_state));
528 
529  return OK_STATUS();
530 }
531 
532 /**
533  * ErrorSoftwareCommandSequence.
534  *
535  * This test checks whether the kDifErrorSoftwareCommandSequence error code is
536  * returned by the hardware when sending software commands in a wrong order to
537  * the KMAC block. Note that this test is not exhaustive, i.e., the test does
538  * not trying to reach the ErrorSoftwareCommandSequence error state from each
539  * other state.
540  *
541  * @return OK or error.
542  */
543 status_t test_err_sw_cmd_sequence(void) {
544  LOG_INFO("Testing kDifErrorSoftwareCommandSequence error.");
545  uint32_t cmds[3] = {KMAC_CMD_CMD_VALUE_PROCESS, KMAC_CMD_CMD_VALUE_RUN,
546  KMAC_CMD_CMD_VALUE_DONE};
547 
548  for (int it = 0; it < ARRAYSIZE(cmds); it++) {
549  // Re-init KMAC for the test.
551  &kmac));
552  // Configure KMAC hardware (using software key and software entropy).
553  TRY(kmac_testutils_config(&kmac, false));
554 
555  // Send CmdDone after initializing KMAC.
556  uint32_t cmd_reg = bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, cmds[it]);
557  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
558 
559  // Check whether we got the expected error.
560  check_and_clear_error(&kmac, kDifErrorSoftwareCommandSequence, true);
561  }
562 
563  return OK_STATUS();
564 }
565 
566 /**
567  * ErrUnexpectedModeStrength.
568  *
569  * This test checks whether the ErrUnexpectedModeStrength error code is
570  * returned by the hardware when using a wrong strength. For mode SHA3 use
571  * 128-bit strength and for SHAKE 224-bit.
572  *
573  * @return OK or error.
574  */
575 status_t test_err_unexpected_mode_strength(void) {
576  LOG_INFO("Testing ErrUnexpectedModeStrength error.");
577 
578  uint32_t misconfigured_strength[2] = {KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L128,
579  KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L224};
580  uint32_t mode[2] = {KMAC_CFG_SHADOWED_MODE_VALUE_SHA3,
581  KMAC_CFG_SHADOWED_MODE_VALUE_SHAKE};
582 
583  for (int it = 0; it < ARRAYSIZE(mode); it++) {
584  // Re-init KMAC for the test.
586  &kmac));
587  TRY(kmac_testutils_config(&kmac, false));
588 
589  uint32_t cfg_reg =
590  mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
591  // Misconfigure the strength.
592  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
593  misconfigured_strength[it]);
594  cfg_reg =
595  bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD, mode[it]);
596  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
597  cfg_reg);
598 
599  // Issue start command.
600  uint32_t cmd_reg =
601  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
602  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_reg);
603 
604  // Check whether we got the expected error.
605  check_and_clear_error(&kmac, kDifErrorUnexpectedModeStrength, false);
606  }
607 
608  return OK_STATUS();
609 }
610 
611 /**
612  * ErrSwIssuedCmdInAppActive.
613  *
614  * This test checks whether the ErrSwIssuedCmdInAppActive error code is
615  * returned by the hardware when a KMAC software command is issued during the
616  * app interface is active. For this, the key manager is instrumented to request
617  * a key from KMAC, which triggers an app interface request.
618  *
619  * @return OK or error.
620  */
621 status_t test_err_sw_issued_cmd_in_app(void) {
622  LOG_INFO("Testing ErrSwIssuedCmdInAppActive error.");
623 
624  // Configure KMAC with some config.
625  uint32_t cfg_reg =
626  mmio_region_read32(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET);
627  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_KSTRENGTH_FIELD,
628  KMAC_CFG_SHADOWED_KSTRENGTH_VALUE_L224);
629  cfg_reg = bitfield_field32_write(cfg_reg, KMAC_CFG_SHADOWED_MODE_FIELD,
630  KMAC_CFG_SHADOWED_MODE_VALUE_SHA3);
631  mmio_region_write32_shadowed(kmac.base_addr, KMAC_CFG_SHADOWED_REG_OFFSET,
632  cfg_reg);
633 
634  // Instrument key manager to use the KMAC app interface.
635  uint32_t reg_control =
636  bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD,
637  KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC);
638  reg_control = bitfield_field32_write(
639  reg_control, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD,
640  KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT);
641  mmio_region_write32_shadowed(keymgr.base_addr,
642  KEYMGR_CONTROL_SHADOWED_REG_OFFSET, reg_control);
643 
644  // Test whether ErrSwIssuedCmdInAppActive can be triggered by writing START
645  // command. Setup the START KMAC command.
646  uint32_t cmd_start =
647  bitfield_field32_write(0, KMAC_CMD_CMD_FIELD, KMAC_CMD_CMD_VALUE_START);
648  // Start the key manager operation.
649  mmio_region_write32(keymgr.base_addr, KEYMGR_START_REG_OFFSET,
650  1 << KEYMGR_START_EN_BIT);
651  // Do not wait until operation has finished. Directly issue the command to
652  // trigger the ErrSwIssuedCmdInAppActive error.
653  mmio_region_write32(kmac.base_addr, KMAC_CMD_REG_OFFSET, cmd_start);
654 
655  // Check whether we got the expected error.
656  return check_and_clear_error(
658 }
659 
660 /**
661  * ErrSwPushedMsgFifo.
662  *
663  * This test checks whether the ErrSwPushedMsgFifo error code is
664  * returned by the hardware when writing to the message FIFO while the
665  * application interface is active.
666  *
667  * @return OK or error.
668  */
669 status_t test_err_sw_pushed_msg_fifo(void) {
670  LOG_INFO("Testing ErrSwPushedMsgFifo error.");
671 
672  // Instrument key manager to use the KMAC app interface.
673  uint32_t reg_control =
674  bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD,
675  KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC);
676  reg_control = bitfield_field32_write(
677  reg_control, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD,
678  KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT);
679  mmio_region_write32_shadowed(keymgr.base_addr,
680  KEYMGR_CONTROL_SHADOWED_REG_OFFSET, reg_control);
681 
682  // Start the key manager operation.
683  mmio_region_write32(keymgr.base_addr, KEYMGR_START_REG_OFFSET,
684  1 << KEYMGR_START_EN_BIT);
685  // Write to message FIFO while app interface operation is ongoing.
686  mmio_region_write8(kmac.base_addr, KMAC_MSG_FIFO_REG_OFFSET, 0xff);
687 
688  // Check whether we got the expected error.
689  return check_and_clear_error(&kmac, kDifErrorSoftwarePushedMessageFifo, true);
690 }
691 
692 bool test_main(void) {
693  // The first three tests don't run on CW310 (see lowRISC/opentitan#15530).
694  if (kDeviceType != kDeviceFpgaCw310) {
695  test_err_wait_timer_expired();
696  test_err_incorrect_entropy_mode();
697  test_err_sw_hashing_without_entropy_ready();
698  }
699 
700  test_err_incorrect_fnc_name();
701  test_err_key_not_valid();
702  test_err_shadow_reg_update();
703  test_err_sw_cmd_sequence();
704  test_err_unexpected_mode_strength();
705 
706  // Setup the key manager as the last two tests use the key manager KMAC app
707  // interface.
708  setup_keymgr();
709  test_err_sw_issued_cmd_in_app();
710  test_err_sw_pushed_msg_fifo();
711 
712  return true;
713 }