Software APIs
kdf_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"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 // The autogen rule that creates this header creates it in a directory named
18 // after the rule, then manipulates the include path in the
19 // cc_compilation_context to include that directory, so the compiler will find
20 // the version of this file matching the Bazel rule under test.
21 #include "kdf_testvectors.h"
22 
23 // Global pointer to the current test vector.
24 static kdf_kmac_test_vector_t *current_test_vector = NULL;
25 
26 /**
27  * Get the mode for KMAC based on test operation.
28  *
29  * @param test_operation Security strength of KMAC.
30  * @param[out] mode KMAC mode enum value.
31  */
32 status_t get_kmac_mode(kdf_test_operation_t test_operation,
33  otcrypto_kmac_mode_t *mode) {
34  switch (test_operation) {
35  case kKdfTestOperationKmac128:
36  *mode = kOtcryptoKmacModeKmac128;
37  break;
38  case kKdfTestOperationKmac256:
39  *mode = kOtcryptoKmacModeKmac256;
40  break;
41  default:
42  LOG_INFO("Invalid test operation is given for KDF-KMAC");
43  return INVALID_ARGUMENT();
44  }
45  return OK_STATUS();
46 }
47 
48 /**
49  * Run the test pointed to by `current_test_vector`.
50  */
51 static status_t run_test_vector(void) {
52  // Below, `km` prefix refers to keying_material, and
53  // `kdk` prefix refers to key derivation key
54  size_t km_num_words = current_test_vector->expected_output.len;
55  uint32_t km_buffer[2 * km_num_words];
56 
58  TRY(get_kmac_mode(current_test_vector->test_operation, &mode));
59 
60  otcrypto_blinded_key_t keying_material = {
61  .config =
62  {
63  // The following key_mode is a dummy placeholder. It does not
64  // necessarily match the `key_length`.
65  .key_mode = kOtcryptoKeyModeKdfKmac128,
66  .key_length = km_num_words * sizeof(uint32_t),
67  .hw_backed = kHardenedBoolFalse,
68  .security_level = kOtcryptoKeySecurityLevelLow,
69  .exportable = kHardenedBoolTrue,
70  },
71  .keyblob = km_buffer,
72  .keyblob_length = sizeof(km_buffer),
73  };
74 
75  // Populate `checksum` and `config.security_level` fields.
76  current_test_vector->key_derivation_key.checksum =
77  integrity_blinded_checksum(&current_test_vector->key_derivation_key);
78 
79  TRY(otcrypto_kdf_kmac(current_test_vector->key_derivation_key, mode,
80  current_test_vector->label,
81  current_test_vector->context,
82  keying_material.config.key_length, &keying_material));
83 
84  HARDENED_CHECK_EQ(integrity_blinded_key_check(&keying_material),
86 
87  // Export the derived blinded key.
88  uint32_t km_share0[km_num_words];
89  uint32_t km_share1[km_num_words];
91  keying_material,
92  (otcrypto_word32_buf_t){.data = km_share0, .len = ARRAYSIZE(km_share0)},
93  (otcrypto_word32_buf_t){.data = km_share1, .len = ARRAYSIZE(km_share1)}));
94 
95  // Unmask the derived key and compare to the expected value.
96  uint32_t actual_output[km_num_words];
97  for (size_t i = 0; i < ARRAYSIZE(actual_output); i++) {
98  actual_output[i] = km_share0[i] ^ km_share1[i];
99  }
100  TRY_CHECK_ARRAYS_EQ(actual_output, current_test_vector->expected_output.data,
101  km_num_words);
102  return OTCRYPTO_OK;
103 }
104 
105 OTTF_DEFINE_TEST_CONFIG();
106 bool test_main(void) {
107  LOG_INFO("Testing cryptolib KDF-KMAC driver.");
108 
109  // Initialize the core with default parameters
110  CHECK_STATUS_OK(entropy_complex_init());
111  CHECK_STATUS_OK(kmac_hwip_default_configure());
112 
113  status_t test_result = OK_STATUS();
114  for (size_t i = 0; i < ARRAYSIZE(kKdfTestVectors); i++) {
115  current_test_vector = &kKdfTestVectors[i];
116  LOG_INFO("Running test %d of %d, test vector identifier: %s", i + 1,
117  ARRAYSIZE(kKdfTestVectors),
118  current_test_vector->vector_identifier);
119  EXECUTE_TEST(test_result, run_test_vector);
120  }
121  return status_ok(test_result);
122 }