Software APIs
kmac_testutils.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 "sw/device/lib/testing/kmac_testutils.h"
6 
8 #include "sw/device/lib/testing/test_framework/check.h"
9 
10 status_t kmac_testutils_config(dif_kmac_t *kmac, bool sideload) {
11  dif_kmac_config_t config = {
12  // Use software-provided "entropy" to avoid waiting for EDN.
13  .entropy_mode = kDifKmacEntropyModeSoftware,
14  // This option minimizes masking to improve speed.
15  .entropy_fast_process = true,
16  // No need to have real entropy for tests.
17  .entropy_seed = {0},
18  .entropy_hash_threshold = 0,
19  // Ignored because the entropy source is software.
20  .entropy_wait_timer = 0,
21  // Leave message as the little-endian default.
22  .entropy_prescaler = 0,
23  .message_big_endian = false,
24  // Leave output as the little-endian default.
25  .output_big_endian = false,
26  // Use a sideloaded key if the caller requested to.
27  .sideload = sideload,
28  // Avoid masking the message to improve speed.
29  .msg_mask = false,
30  };
31 
32  TRY(dif_kmac_configure(kmac, config));
33  return OK_STATUS();
34 }
35 
36 status_t kmac_testutils_kmac(const dif_kmac_t *kmac,
37  const dif_kmac_mode_kmac_t mode,
38  const dif_kmac_key_t *key,
39  const char *custom_string,
40  const size_t custom_string_len,
41  const char *message, const size_t message_len,
42  const size_t output_len, uint32_t *output,
43  uint32_t *capacity) {
44  // Initialize customization string.
45  dif_kmac_customization_string_t kmac_custom_string;
46  TRY(dif_kmac_customization_string_init(custom_string, custom_string_len,
47  &kmac_custom_string));
48 
49  // Start the KMAC operation and check that KMAC doesn't report an error.
50  dif_kmac_operation_state_t operation_state;
51  TRY(dif_kmac_mode_kmac_start(kmac, &operation_state, mode, output_len, key,
52  &kmac_custom_string));
53  TRY(kmac_testutils_check_error(kmac));
54 
55  // Pass the entire message to KMAC ("absorb" stage) and check that KMAC
56  // doesn't report an error.
57  TRY(dif_kmac_absorb(kmac, &operation_state, message, message_len, NULL));
58  TRY(kmac_testutils_check_error(kmac));
59 
60  // Get the output ("squeeze" stage) and check that KMAC doesn't report an
61  // error.
62  TRY(dif_kmac_squeeze(kmac, &operation_state, output, output_len, NULL,
63  capacity));
64  TRY(kmac_testutils_check_error(kmac));
65 
66  // End the operation and check that KMAC doesn't report an error.
67  TRY(dif_kmac_end(kmac, &operation_state));
68  TRY(kmac_testutils_check_error(kmac));
69 
70  return OK_STATUS();
71 }
72 
73 status_t kmac_testutils_check_error(const dif_kmac_t *kmac) {
74  bool error;
75  TRY(dif_kmac_has_error_occurred(kmac, &error));
76 
77  // If no error has occurred, return early with OK.
78  if (!error) {
79  return OK_STATUS();
80  }
81 
82  // Obtain more information on the error.
83  dif_kmac_error_t err;
84  uint32_t info;
85  TRY(dif_kmac_get_error(kmac, &err, &info));
86 
87  // Clear the error IRQ.
88  TRY(dif_kmac_clear_err_irq(kmac));
89 
90  // Inform HW that we have handled the error.
91  TRY(dif_kmac_err_processed(kmac));
92 
93  // Return with a status based on the error code.
94  switch (err) {
96  return FAILED_PRECONDITION();
97  default:
98  return INTERNAL();
99  }
100 }