Software APIs
kdf_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"
8 #include "sw/device/lib/crypto/impl/keyblob.h"
14 #include "sw/device/lib/testing/keymgr_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
18 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
19 
20 // Most fields of the following structs are not used during sideload testing
21 // but they are copied over from KDF-KMAC testing for consistency. Later, we can
22 // merge the sideload and non-sideload testing if required. Normally, these two
23 // structs would be defined by "kdf_testvectors.h" generated automatically by
24 // a Bazel rule.
25 typedef enum kdf_test_operation_t {
26  kKdfTestOperationKmac128,
27  kKdfTestOperationKmac256,
28 } kdf_test_operation_t;
29 
30 typedef struct kdf_test_vector {
31  char *vector_identifier;
32  kdf_test_operation_t test_operation;
38 
39 // Most fields of the following structs are not used during sideload testing
40 // but they are copied over from KMAC testing for consistency. Later, we can
41 // merge the sideload and non-sideload testing if required. Normally, these two
42 // structs would be defined by "kmac_testvectors.h" generated automatically by
43 // a Bazel rule.
44 typedef enum kmac_test_operation_t {
45  kKmacTestOperationCshake,
46  kKmacTestOperationShake,
47  kKmacTestOperationSha3,
48  kKmacTestOperationKmac,
49 } kmac_test_operation_t;
50 
51 typedef struct kmac_test_vector {
52  char *vector_identifier;
53  kmac_test_operation_t test_operation;
54  size_t security_strength;
56  otcrypto_const_byte_buf_t input_msg;
57  otcrypto_const_byte_buf_t func_name;
61 
62 // Note that since the following vectors are used for sideloading, the resulting
63 // `keying_material` result is irrelevant. Only its length is used as input.
64 static kdf_kmac_test_vector_t kKdfTestVectors[] = {
65  {
66  .vector_identifier = "Manually edited KDF-KMAC sample #1",
67  .test_operation = kKdfTestOperationKmac128,
68  .key_derivation_key =
69  {
70  .config =
71  {
72  .key_mode = kOtcryptoKeyModeKdfKmac128,
73  .key_length = 32,
74  .hw_backed = kHardenedBoolTrue,
75  .security_level = kOtcryptoKeySecurityLevelLow,
76  .exportable = kHardenedBoolFalse,
77  },
78  .keyblob_length = 32,
79  .keyblob =
80  (uint32_t[]){
81  0x00000000,
82  0xa0d0e9b4,
83  0x7e790e8b,
84  0x2ed764b2,
85  0x7ad25f92,
86  0x4ba41700,
87  0x75553000,
88  0xe3089c7a,
89  },
90  },
91  .context =
92  {
93  .data =
94  (uint8_t[]){
95  0x5f,
96  0x67,
97  0x2e,
98  },
99  .len = 3,
100  },
101  .label =
102  {
103  .data =
104  (uint8_t[]){
105  0xdc, 0xd5, 0x70, 0x1f, 0x22, 0x83, 0x53,
106  0xa9, 0xc7, 0x3a, 0xe6, 0x72, 0x65, 0xb4,
107  0xa5, 0x55, 0x84, 0xa0, 0x4f, 0x3d, 0x62,
108  0x2b, 0xac, 0x32, 0x69, 0x8f, 0xb0, 0xf3,
109  },
110  .len = 28,
111  },
112  .keying_material =
113  {
114  // other fields of `keying_material` is not used, since it is
115  // not
116  // directy passed to KDF-KMAC function.
117  .config =
118  {
119  .key_length = 24,
120  },
121  },
122  },
123  {
124  .vector_identifier = "Manually edited KDF-KMAC sample #2",
125  .test_operation = kKdfTestOperationKmac128,
126  .key_derivation_key =
127  {
128  .config =
129  {
130  .key_mode = kOtcryptoKeyModeKdfKmac128,
131  .key_length = 32,
132  .hw_backed = kHardenedBoolTrue,
133  .security_level = kOtcryptoKeySecurityLevelHigh,
134  .exportable = kHardenedBoolFalse,
135  },
136  .keyblob_length = 32,
137  .keyblob =
138  (uint32_t[]){
139  0x00000000,
140  0x1600a35a,
141  0x6f03675a,
142  0x6b0d549b,
143  0x11e20b8f,
144  0x3d9c1724,
145  0x1738f7d9,
146  0x8d116ece,
147  },
148  },
149  .context =
150  {
151  .data =
152  (uint8_t[]){
153  0xfe,
154  0x55,
155  0x18,
156  0xcb,
157  0xe8,
158  0xdf,
159  0xe5,
160  0x92,
161  0x96,
162  0x94,
163  0x6b,
164  0xd2,
165  0x35,
166  0xa0,
167  0x14,
168  },
169  .len = 15,
170  },
171  .label =
172  {
173  .data =
174  (uint8_t[]){
175  0xbe,
176  0x3a,
177  0x2b,
178  0x7c,
179  0x73,
180  0xa4,
181  0x20,
182  0xc3,
183  0x39,
184  0xa0,
185  0xf9,
186  0x42,
187  0x37,
188  0x37,
189  0x6d,
190  0x09,
191  },
192  .len = 16,
193  },
194  .keying_material =
195  {
196  // other fields of `keying_material` is not used, since it is
197  // not
198  // directy passed to KDF-KMAC function.
199  .config =
200  {
201  .key_length = 32,
202  },
203  },
204  },
205  {
206  .vector_identifier = "Manually edited KDF-KMAC sample #3",
207  .test_operation = kKdfTestOperationKmac256,
208  .key_derivation_key =
209  {
210  .config =
211  {
212  .key_mode = kOtcryptoKeyModeKdfKmac256,
213  .key_length = 32,
214  .hw_backed = kHardenedBoolTrue,
215  .security_level = kOtcryptoKeySecurityLevelHigh,
216  .exportable = kHardenedBoolFalse,
217  },
218  .keyblob_length = 32,
219  .keyblob =
220  (uint32_t[]){
221  0x00000000,
222  0xe5f6db1d,
223  0x9acd8acd,
224  0x14b044d7,
225  0x558298e2,
226  0x8de4ab47,
227  0xefb6fbfe,
228  0x9ddcc6f8,
229  },
230  },
231  .context =
232  {
233  .data =
234  (uint8_t[]){
235  0x6e, 0xa6, 0x87, 0x76, 0x6e, 0xac, 0xfb,
236  0x9c, 0xf0, 0x5e, 0x91, 0x5f, 0xfc, 0xeb,
237  0x62, 0x44, 0x51, 0x77, 0x23,
238  },
239  .len = 19,
240  },
241  .label =
242  {
243  .data =
244  (uint8_t[]){
245  0x07, 0x32, 0xa7, 0x2f, 0x55, 0xff, 0xd6, 0xdd,
246  0x5e, 0x83, 0x38, 0xad, 0x50, 0xba, 0xa5, 0x01,
247  0x36, 0x80, 0x9c, 0x56, 0x53, 0xb6, 0x80,
248  },
249  .len = 23,
250  },
251  .keying_material =
252  {
253  // other fields of `keying_material` is not used, since it is
254  // not
255  // directy passed to KDF-KMAC function.
256  .config =
257  {
258  .key_length = 64,
259  },
260  },
261  },
262 };
263 
264 // We use the following SHA-3 vector between 2 sideload executions in order to
265 // clear internal KMAC engine.
266 static kmac_test_vector_t sha3_test_vector = {
267  .vector_identifier =
268  "NIST CAVP, byte-oriented, SHA3_224ShortMsg.rsp, Len = 8",
269  .test_operation = kKmacTestOperationSha3,
270  .security_strength = 224,
271  .input_msg =
272  {
273  .data =
274  (uint8_t[]){
275  0x01,
276  },
277  .len = 1,
278  },
279  .func_name =
280  {
281  .data = NULL,
282  .len = 0,
283  },
284  .cust_str =
285  {
286  .data = NULL,
287  .len = 0,
288  },
289  .digest =
290  {
291  .data =
292  (uint8_t[]){
293  0x48, 0x82, 0x86, 0xd9, 0xd3, 0x27, 0x16, 0xe5, 0x88, 0x1e,
294  0xa1, 0xee, 0x51, 0xf3, 0x6d, 0x36, 0x60, 0xd7, 0x0f, 0x0d,
295  0xb0, 0x3b, 0x3f, 0x61, 0x2c, 0xe9, 0xed, 0xa4,
296  },
297  .len = 28,
298  },
299 };
300 
301 // Global pointer to the current test vector.
302 static kdf_kmac_test_vector_t *current_test_vector = NULL;
303 
304 /**
305  * Get the mode for SHA3 based on the security strength.
306  *
307  * @param security_str Security strength (in bits).
308  * @param[out] mode Hash mode enum value.
309  */
310 status_t get_sha3_mode(size_t security_strength, otcrypto_hash_mode_t *mode) {
311  switch (security_strength) {
312  case 224:
313  *mode = kOtcryptoHashModeSha3_224;
314  break;
315  case 256:
316  *mode = kOtcryptoHashModeSha3_256;
317  break;
318  case 384:
319  *mode = kOtcryptoHashModeSha3_384;
320  break;
321  case 512:
322  *mode = kOtcryptoHashModeSha3_512;
323  break;
324  default:
325  LOG_INFO("Invalid size for SHA3: %d bits", security_strength);
326  return INVALID_ARGUMENT();
327  }
328  return OK_STATUS();
329 }
330 
331 /**
332  * Get the mode for KMAC based on test operation.
333  *
334  * @param test_operation Security strength of KMAC.
335  * @param[out] mode KMAC mode enum value.
336  */
337 status_t get_kmac_mode(kdf_test_operation_t test_operation,
338  otcrypto_kmac_mode_t *mode) {
339  switch (test_operation) {
340  case kKdfTestOperationKmac128:
341  *mode = kOtcryptoKmacModeKmac128;
342  break;
343  case kKdfTestOperationKmac256:
344  *mode = kOtcryptoKmacModeKmac256;
345  break;
346  default:
347  LOG_INFO("Invalid test operation is given for KDF-KMAC");
348  return INVALID_ARGUMENT();
349  }
350  return OK_STATUS();
351 }
352 
353 /**
354  * Run the test pointed to by `current_test_vector`.
355  */
356 static status_t run_test_vector(void) {
357  // Below, `km` prefix refers to keying_material, and
358  // `kdk` prefix refers to key derivation key
359  size_t km_key_len = current_test_vector->keying_material.config.key_length;
360  size_t km_keyblob_len =
361  keyblob_num_words(current_test_vector->keying_material.config);
362  uint32_t km_buffer1[km_keyblob_len];
363  uint32_t km_buffer2[km_keyblob_len];
364 
365  current_test_vector->key_derivation_key.checksum =
366  integrity_blinded_checksum(&current_test_vector->key_derivation_key);
367 
369  TRY(get_kmac_mode(current_test_vector->test_operation, &mode));
370 
371  otcrypto_key_config_t km_config = {
372  // The following key_mode is a dummy placeholder. It does not
373  // necessarily match the `key_length`.
374  .key_mode = kOtcryptoKeyModeKdfKmac128,
375  .key_length = km_key_len,
376  .hw_backed = kHardenedBoolFalse,
377  .security_level = kOtcryptoKeySecurityLevelHigh,
378  .exportable = kHardenedBoolFalse,
379  };
380 
381  otcrypto_blinded_key_t keying_material1 = {
382  .config = km_config,
383  .keyblob = km_buffer1,
384  .keyblob_length = km_keyblob_len * sizeof(uint32_t),
385  };
386 
387  otcrypto_blinded_key_t keying_material2 = {
388  .config = km_config,
389  .keyblob = km_buffer2,
390  .keyblob_length = km_keyblob_len * sizeof(uint32_t),
391  };
392 
393  size_t digest_num_words = sha3_test_vector.digest.len / sizeof(uint32_t);
394  if (sha3_test_vector.digest.len % sizeof(uint32_t) != 0) {
395  digest_num_words++;
396  }
397  uint32_t digest[digest_num_words];
398 
399  otcrypto_hash_digest_t digest_buf = {
400  .data = digest,
401  .len = ARRAYSIZE(digest),
402  };
403 
404  LOG_INFO("Running the first KDF-KMAC sideload operation.");
405  TRY(otcrypto_kdf_kmac(
406  current_test_vector->key_derivation_key, mode, current_test_vector->label,
407  current_test_vector->context, km_key_len, &keying_material1));
408 
409  // Run a SHA-3 operation in between the two KMAC operations.
410  LOG_INFO("Running the intermediate SHA3 operation.");
411  TRY(get_sha3_mode(sha3_test_vector.security_strength, &digest_buf.mode));
412  TRY(otcrypto_hash(sha3_test_vector.input_msg, digest_buf));
413 
414  LOG_INFO("Running the second KDF-KMAC sideload operation for comparison.");
415  TRY(otcrypto_kdf_kmac(
416  current_test_vector->key_derivation_key, mode, current_test_vector->label,
417  current_test_vector->context, km_key_len, &keying_material2));
418 
419  TRY_CHECK_ARRAYS_EQ((unsigned char *)keying_material1.keyblob,
420  (unsigned char *)keying_material2.keyblob, km_key_len);
421  return OTCRYPTO_OK;
422 }
423 
424 OTTF_DEFINE_TEST_CONFIG();
425 bool test_main(void) {
426  // Initialize keymgr and advance to CreatorRootKey state.
427  dif_keymgr_t keymgr;
428  dif_kmac_t kmac;
429  CHECK_STATUS_OK(keymgr_testutils_initialize(&keymgr, &kmac));
430 
431  const char *state_name;
432  CHECK_STATUS_OK(keymgr_testutils_state_string_get(&keymgr, &state_name));
433 
434  LOG_INFO("Keymgr entered %s State", state_name);
435  LOG_INFO("Testing cryptolib KDF-KMAC driver with sideloaded key.");
436 
437  // Initialize the core with default parameters
438  CHECK_STATUS_OK(entropy_complex_init());
439  CHECK_STATUS_OK(kmac_hwip_default_configure());
440 
441  status_t test_result = OK_STATUS();
442  for (size_t i = 0; i < ARRAYSIZE(kKdfTestVectors); i++) {
443  // copy version
444  current_test_vector = &kKdfTestVectors[i];
445 
446  LOG_INFO("Running test %d of %d, test vector identifier: %s", i + 1,
447  ARRAYSIZE(kKdfTestVectors),
448  current_test_vector->vector_identifier);
449  EXECUTE_TEST(test_result, run_test_vector);
450  }
451  return status_ok(test_result);
452 }