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