Software APIs
kmac_functest.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/crypto/drivers/entropy.h"
6 #include "sw/device/lib/crypto/drivers/kmac.h"
7 #include "sw/device/lib/crypto/impl/integrity.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 // The autogen rule that creates this header creates it in a directory named
16 // after the rule, then manipulates the include path in the
17 // cc_compilation_context to include that directory, so the compiler will find
18 // the version of this file matching the Bazel rule under test.
19 #include "kmac_testvectors.h"
20 
21 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
22 
23 // Global pointer to the current test vector.
24 static kmac_test_vector_t *current_test_vector = NULL;
25 
26 /**
27  * Get the mode for SHAKE based on the security strength.
28  *
29  * @param security_str Security strength (in bits).
30  * @param[out] mode SHAKE mode enum value.
31  */
32 status_t get_shake_mode(size_t security_strength, otcrypto_hash_mode_t *mode) {
33  switch (security_strength) {
34  case 128:
35  *mode = kOtcryptoHashXofModeShake128;
36  break;
37  case 256:
38  *mode = kOtcryptoHashXofModeShake256;
39  break;
40  default:
41  LOG_INFO("Invalid security strength for SHAKE: %d bits",
42  security_strength);
43  return INVALID_ARGUMENT();
44  }
45  return OK_STATUS();
46 }
47 
48 /**
49  * Get the mode for cSHAKE based on the security strength.
50  *
51  * @param security_str Security strength (in bits).
52  * @param[out] mode cSHAKE mode enum value.
53  */
54 status_t get_cshake_mode(size_t security_strength, otcrypto_hash_mode_t *mode) {
55  switch (security_strength) {
56  case 128:
57  *mode = kOtcryptoHashXofModeCshake128;
58  break;
59  case 256:
60  *mode = kOtcryptoHashXofModeCshake256;
61  break;
62  default:
63  LOG_INFO("Invalid security strength for cSHAKE: %d bits",
64  security_strength);
65  return INVALID_ARGUMENT();
66  }
67  return OK_STATUS();
68 }
69 
70 /**
71  * Get the mode for SHA3 based on the security strength.
72  *
73  * @param security_str Security strength (in bits).
74  * @param[out] mode Hash mode enum value.
75  */
76 status_t get_sha3_mode(size_t security_strength, otcrypto_hash_mode_t *mode) {
77  switch (security_strength) {
78  case 224:
79  *mode = kOtcryptoHashModeSha3_224;
80  break;
81  case 256:
82  *mode = kOtcryptoHashModeSha3_256;
83  break;
84  case 384:
85  *mode = kOtcryptoHashModeSha3_384;
86  break;
87  case 512:
88  *mode = kOtcryptoHashModeSha3_512;
89  break;
90  default:
91  LOG_INFO("Invalid size for SHA3: %d bits", security_strength);
92  return INVALID_ARGUMENT();
93  }
94  return OK_STATUS();
95 }
96 
97 /**
98  * Run the test pointed to by `current_test_vector`.
99  */
100 static status_t run_test_vector(void) {
101  size_t digest_num_words = current_test_vector->digest.len / sizeof(uint32_t);
102  if (current_test_vector->digest.len % sizeof(uint32_t) != 0) {
103  digest_num_words++;
104  }
105  uint32_t digest[digest_num_words];
106  otcrypto_hash_digest_t digest_buf = {
107  .data = digest,
108  .len = digest_num_words,
109  };
110 
111  switch (current_test_vector->test_operation) {
112  case kKmacTestOperationShake: {
113  TRY(get_shake_mode(current_test_vector->security_strength,
114  &digest_buf.mode));
115  TRY(otcrypto_xof_shake(current_test_vector->input_msg, digest_buf));
116  break;
117  }
118  case kKmacTestOperationCshake: {
119  TRY(get_cshake_mode(current_test_vector->security_strength,
120  &digest_buf.mode));
121  TRY(otcrypto_xof_cshake(current_test_vector->input_msg,
122  current_test_vector->func_name,
123  current_test_vector->cust_str, digest_buf));
124  break;
125  }
126  case kKmacTestOperationSha3: {
127  TRY(get_sha3_mode(current_test_vector->security_strength,
128  &digest_buf.mode));
129  TRY(otcrypto_hash(current_test_vector->input_msg, digest_buf));
130  break;
131  }
132  case kKmacTestOperationKmac: {
133  current_test_vector->key.checksum =
134  integrity_blinded_checksum(&current_test_vector->key);
135  otcrypto_word32_buf_t tag_buf = {
136  .data = digest_buf.data,
137  .len = digest_buf.len,
138  };
139  TRY(otcrypto_kmac(&current_test_vector->key,
140  current_test_vector->input_msg,
141  current_test_vector->cust_str,
142  current_test_vector->digest.len, tag_buf));
143  break;
144  }
145  default: {
146  LOG_INFO("Unrecognized `operation` field: 0x%04x",
147  current_test_vector->test_operation);
148  return INVALID_ARGUMENT();
149  }
150  }
151 
152  TRY_CHECK_ARRAYS_EQ((unsigned char *)digest_buf.data,
153  current_test_vector->digest.data,
154  current_test_vector->digest.len);
155  return OTCRYPTO_OK;
156 }
157 
158 OTTF_DEFINE_TEST_CONFIG();
159 bool test_main(void) {
160  LOG_INFO("Testing cryptolib KMAC driver.");
161 
162  // Initialize the core with default parameters
163  CHECK_STATUS_OK(entropy_complex_init());
164  CHECK_STATUS_OK(kmac_hwip_default_configure());
165 
166  status_t test_result = OK_STATUS();
167  for (size_t i = 0; i < ARRAYSIZE(kKmacTestVectors); i++) {
168  current_test_vector = &kKmacTestVectors[i];
169  LOG_INFO("Running test %d of %d, test vector identifier: %s", i + 1,
170  ARRAYSIZE(kKmacTestVectors),
171  current_test_vector->vector_identifier);
172  EXECUTE_TEST(test_result, run_test_vector);
173  }
174  return status_ok(test_result);
175 }