Software APIs
kmac_sideload_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/keymgr_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 
16 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
17 
18 // Most fields of the following structs are not used during sideload testing
19 // but they are copied over from KMAC testing for consistency. Later, we can
20 // merge the sideload and non-sideload testing if required. Normally, these two
21 // structs would be defined by "kmac_testvectors.h" generated automatically by
22 // a Bazel rule.
23 typedef enum kmac_test_operation_t {
24  kKmacTestOperationCshake,
25  kKmacTestOperationShake,
26  kKmacTestOperationSha3,
27  kKmacTestOperationKmac,
28 } kmac_test_operation_t;
29 
30 typedef struct kmac_test_vector {
31  char *vector_identifier;
32  kmac_test_operation_t test_operation;
33  size_t security_strength;
35  otcrypto_const_byte_buf_t input_msg;
36  otcrypto_const_byte_buf_t func_name;
40 
41 // Note that since the following vectors are used for sideloading, the digest
42 // result is irrelevant.
43 static kmac_test_vector_t kKmacTestVectors[] = {
44  {
45  .vector_identifier = "Manually edited sample #1",
46  .security_strength = 128,
47  .key =
48  {
49  .config =
50  {
51  .key_mode = kOtcryptoKeyModeKmac128,
52  .key_length = kKmacSideloadKeyLength / 8,
53  .hw_backed = kHardenedBoolTrue,
54  .exportable = kHardenedBoolFalse,
55  .security_level = kOtcryptoKeySecurityLevelHigh,
56  },
57  .keyblob_length = 32,
58  .keyblob =
59  (uint32_t[]){
60  0x00000000,
61  0x47464544,
62  0x4b4a4948,
63  0x4f4e4d4c,
64  0x53525150,
65  0x57565554,
66  0x5b5a5958,
67  0x5f5e5d5c,
68  },
69  },
70  .input_msg =
71  {
72  .data =
73  (uint8_t[]){
74  0xf5, 0xb1, 0x65, 0x22, 0x4a, 0x58, 0xb7, 0x91,
75  0xdf, 0x6a, 0xf1, 0xd8, 0x30, 0x3e, 0x61, 0xcd,
76  0xc4, 0xbb, 0x86, 0xc3, 0xd1, 0xc4, 0x27, 0x10,
77  0x3c, 0x34, 0x4c, 0x41, 0x89, 0xeb, 0x2f, 0x1e,
78  },
79  .len = 32,
80  },
81  .cust_str =
82  {
83  .data =
84  (uint8_t[]){
85  0x7b, 0xd5, 0xd4, 0x7e, 0x44, 0x6f, 0xce, 0xc2,
86  0xa3, 0xd8, 0x11, 0x73, 0x61, 0x10, 0xe5, 0x78,
87  0x1b, 0xcc, 0xce, 0xa6, 0x96, 0x76, 0x2e, 0x61,
88  0x16, 0xc6, 0xe9, 0xc9, 0x2d, 0x99, 0xbf, 0x35,
89  },
90  .len = 32,
91  },
92  .digest =
93  {
94  // `data` field does not matter because this is a sideload test
95  // vector.
96  .len = 20,
97  },
98  },
99  {
100  .vector_identifier = "Manually edited sample #2",
101  .security_strength = 256,
102  .key =
103  {
104  .config =
105  {
106  .key_mode = kOtcryptoKeyModeKmac256,
107  .key_length = kKmacSideloadKeyLength / 8,
108  .hw_backed = kHardenedBoolTrue,
109  .exportable = kHardenedBoolFalse,
110  .security_level = kOtcryptoKeySecurityLevelHigh,
111  },
112  .keyblob_length = 32,
113  .keyblob =
114  (uint32_t[]){
115  0x00000000,
116  0x11111111,
117  0x4b4a4948,
118  0x4f4e4d4c,
119  0x53525150,
120  0x57565554,
121  0x5b5a5958,
122  0xffffffff,
123  },
124  },
125  .input_msg =
126  {
127  .data =
128  (uint8_t[]){
129  0xf5,
130  0xb1,
131  0x65,
132  0x22,
133  0x4a,
134  0x58,
135  0xb7,
136  0x91,
137  0xdf,
138  0x6a,
139  0xf1,
140  0xd8,
141  0x30,
142  0x3e,
143  0x61,
144  0xcd,
145  },
146  .len = 16,
147  },
148  .cust_str =
149  {
150  .data =
151  (uint8_t[]){
152  0x7b,
153  0xd5,
154  0xd4,
155  0x7e,
156  0x44,
157  0x6f,
158  0xce,
159  0xc2,
160  0xa3,
161  0xd8,
162  0x11,
163  0x73,
164  0x61,
165  0x10,
166  0xe5,
167  0x78,
168  },
169  .len = 16,
170  },
171  .digest =
172  {
173  // `data` field does not matter because this is a sideload test
174  // vector.
175  .len = 32,
176  },
177  },
178  {
179  .vector_identifier = "Manually edited sample #3",
180  .security_strength = 128,
181  .key =
182  {
183  .config =
184  {
185  .key_mode = kOtcryptoKeyModeKmac128,
186  .key_length = kKmacSideloadKeyLength / 8,
187  .hw_backed = kHardenedBoolTrue,
188  .exportable = kHardenedBoolFalse,
189  .security_level = kOtcryptoKeySecurityLevelHigh,
190  },
191  .keyblob_length = 32,
192  .keyblob =
193  (uint32_t[]){
194  0x00000000,
195  0x00000000,
196  0x00000000,
197  0x00000000,
198  0x00000000,
199  0x00000000,
200  0x00000000,
201  0x0000000f,
202  },
203  },
204  .input_msg =
205  {
206  .data = (uint8_t[]){0xf5, 0xb1, 0x65, 0x22},
207  .len = 4,
208  },
209  .cust_str =
210  {
211  .data = (uint8_t[]){0x7b, 0xd5, 0xd4, 0x7e},
212  .len = 4,
213  },
214  .digest =
215  {
216  // `data` field does not matter because this is a sideload test
217  // vector.
218  .len = 16,
219  },
220  },
221 };
222 
223 // We use the following SHA-3 vector between 2 sideload executions in order to
224 // clear internal KMAC engine.
225 static kmac_test_vector_t sha3_test_vector = {
226  .vector_identifier =
227  "NIST CAVP, byte-oriented, SHA3_224ShortMsg.rsp, Len = 8",
228  .test_operation = kKmacTestOperationSha3,
229  .security_strength = 224,
230  .input_msg =
231  {
232  .data =
233  (uint8_t[]){
234  0x01,
235  },
236  .len = 1,
237  },
238  .func_name =
239  {
240  .data = NULL,
241  .len = 0,
242  },
243  .cust_str =
244  {
245  .data = NULL,
246  .len = 0,
247  },
248  .digest =
249  {
250  .data =
251  (uint8_t[]){
252  0x48, 0x82, 0x86, 0xd9, 0xd3, 0x27, 0x16, 0xe5, 0x88, 0x1e,
253  0xa1, 0xee, 0x51, 0xf3, 0x6d, 0x36, 0x60, 0xd7, 0x0f, 0x0d,
254  0xb0, 0x3b, 0x3f, 0x61, 0x2c, 0xe9, 0xed, 0xa4,
255  },
256  .len = 28,
257  },
258 };
259 
260 // Global pointer to the current test vector.
261 static kmac_test_vector_t *current_test_vector = NULL;
262 
263 /**
264  * Get the mode for SHA3 based on the security strength.
265  *
266  * @param security_str Security strength (in bits).
267  * @param[out] mode Hash mode enum value.
268  */
269 status_t get_sha3_mode(size_t security_strength, otcrypto_hash_mode_t *mode) {
270  switch (security_strength) {
271  case 224:
272  *mode = kOtcryptoHashModeSha3_224;
273  break;
274  case 256:
275  *mode = kOtcryptoHashModeSha3_256;
276  break;
277  case 384:
278  *mode = kOtcryptoHashModeSha3_384;
279  break;
280  case 512:
281  *mode = kOtcryptoHashModeSha3_512;
282  break;
283  default:
284  LOG_INFO("Invalid size for SHA3: %d bits", security_strength);
285  return INVALID_ARGUMENT();
286  }
287  return OK_STATUS();
288 }
289 
290 /**
291  * Get the mode for KMAC based on the security strength.
292  *
293  * @param security_str Security strength (in bits).
294  * @param[out] mode KMAC mode enum value.
295  */
296 status_t get_kmac_mode(size_t security_strength, otcrypto_kmac_mode_t *mode) {
297  switch (security_strength) {
298  case 128:
299  *mode = kOtcryptoKmacModeKmac128;
300  break;
301  case 256:
302  *mode = kOtcryptoKmacModeKmac256;
303  break;
304  default:
305  LOG_INFO("Invalid size for KMAC: %d bits", security_strength);
306  return INVALID_ARGUMENT();
307  }
308  return OK_STATUS();
309 }
310 
311 /**
312  * Run the test pointed to by `current_test_vector`.
313  */
314 static status_t run_test_vector(void) {
315  size_t digest_num_words = current_test_vector->digest.len / sizeof(uint32_t);
316  if (current_test_vector->digest.len % sizeof(uint32_t) != 0) {
317  digest_num_words++;
318  }
319  uint32_t digest1[digest_num_words];
320  uint32_t digest2[digest_num_words];
321 
322  current_test_vector->key.checksum =
323  integrity_blinded_checksum(&current_test_vector->key);
324 
326  TRY(get_kmac_mode(current_test_vector->security_strength, &mode));
327 
328  otcrypto_word32_buf_t tag_buf1 = {
329  .data = digest1,
330  .len = ARRAYSIZE(digest1),
331  };
332  otcrypto_word32_buf_t tag_buf2 = {
333  .data = digest2,
334  .len = ARRAYSIZE(digest2),
335  };
336 
337  digest_num_words = sha3_test_vector.digest.len / sizeof(uint32_t);
338  if (sha3_test_vector.digest.len % sizeof(uint32_t) != 0) {
339  digest_num_words++;
340  }
341  uint32_t digest3[digest_num_words];
342 
343  otcrypto_hash_digest_t digest_buf = {
344  .data = digest3,
345  .len = ARRAYSIZE(digest3),
346  };
347 
348  LOG_INFO("Running the first KMAC sideload operation.");
349  TRY(otcrypto_kmac(&current_test_vector->key, current_test_vector->input_msg,
350  mode, current_test_vector->cust_str,
351  current_test_vector->digest.len, tag_buf1));
352 
353  // Run a SHA-3 operation in between the two KMAC operations.
354  LOG_INFO("Running the intermediate SHA3 operation.");
355  TRY(get_sha3_mode(sha3_test_vector.security_strength, &digest_buf.mode));
356  TRY(otcrypto_hash(sha3_test_vector.input_msg, digest_buf));
357 
358  LOG_INFO("Running the second KMAC sideload operation for comparison.");
359  TRY(otcrypto_kmac(&current_test_vector->key, current_test_vector->input_msg,
360  mode, current_test_vector->cust_str,
361  current_test_vector->digest.len, tag_buf2));
362 
363  TRY_CHECK_ARRAYS_EQ((unsigned char *)tag_buf1.data,
364  (unsigned char *)tag_buf2.data,
365  current_test_vector->digest.len);
366  return OTCRYPTO_OK;
367 }
368 
369 OTTF_DEFINE_TEST_CONFIG();
370 bool test_main(void) {
371  // Initialize keymgr and advance to CreatorRootKey state.
372  dif_keymgr_t keymgr;
373  dif_kmac_t kmac;
374  CHECK_STATUS_OK(keymgr_testutils_initialize(&keymgr, &kmac));
375 
376  const char *state_name;
377  CHECK_STATUS_OK(keymgr_testutils_state_string_get(&keymgr, &state_name));
378 
379  LOG_INFO("Keymgr entered %s State", state_name);
380  LOG_INFO("Testing cryptolib KMAC driver with sideloaded key.");
381 
382  // Initialize the core with default parameters
383  CHECK_STATUS_OK(entropy_complex_init());
384  CHECK_STATUS_OK(kmac_hwip_default_configure());
385 
386  status_t test_result = OK_STATUS();
387  for (size_t i = 0; i < ARRAYSIZE(kKmacTestVectors); i++) {
388  // copy version
389  current_test_vector = &kKmacTestVectors[i];
390 
391  LOG_INFO("Running test %d of %d, test vector identifier: %s", i + 1,
392  ARRAYSIZE(kKmacTestVectors),
393  current_test_vector->vector_identifier);
394  EXECUTE_TEST(test_result, run_test_vector);
395  }
396  return status_ok(test_result);
397 }