Software APIs
kmac_kdf.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 
6 
8 #include "sw/device/lib/crypto/drivers/kmac.h"
9 #include "sw/device/lib/crypto/impl/integrity.h"
10 #include "sw/device/lib/crypto/impl/keyblob.h"
11 #include "sw/device/lib/crypto/impl/status.h"
13 
14 // Module ID for status codes.
15 #define MODULE_ID MAKE_MODULE_ID('k', 'k', 'd')
16 
18  const otcrypto_blinded_key_t key_derivation_key,
19  const otcrypto_const_byte_buf_t label,
20  const otcrypto_const_byte_buf_t context,
21  otcrypto_blinded_key_t *output_key_material) {
22  // Check NULL pointers.
23  if (key_derivation_key.keyblob == NULL || output_key_material == NULL ||
24  output_key_material->keyblob == NULL) {
25  return OTCRYPTO_BAD_ARGS;
26  }
27 
28  // Check for null label with nonzero length.
29  if (label.data == NULL && label.len != 0) {
30  return OTCRYPTO_BAD_ARGS;
31  }
32  // Because of KMAC HWIPs prefix limitation, `label` should not exceed
33  // `kKmacCustStrMaxSize` bytes.
34  if (label.len > kKmacCustStrMaxSize) {
35  return OTCRYPTO_BAD_ARGS;
36  }
37 
38  // Check for null context with nonzero length.
39  if (context.data == NULL && context.len != 0) {
40  return OTCRYPTO_BAD_ARGS;
41  }
42 
43  // Check the private key checksum.
44  if (integrity_blinded_key_check(&key_derivation_key) != kHardenedBoolTrue) {
45  return OTCRYPTO_BAD_ARGS;
46  }
47 
48  // Check `key_len` is supported by KMAC HWIP.
49  // The set of supported key sizes is {128, 192, 256, 384, 512}.
50  HARDENED_TRY(kmac_key_length_check(key_derivation_key.config.key_length));
51 
52  kmac_blinded_key_t kmac_key = {
53  .share0 = NULL,
54  .share1 = NULL,
55  .hw_backed = key_derivation_key.config.hw_backed,
56  .len = key_derivation_key.config.key_length,
57  };
58 
59  // Validate key length of `key_derivation_key`.
60  if (key_derivation_key.config.hw_backed == kHardenedBoolTrue) {
61  // Check that 1) key size matches sideload port size, 2) keyblob length
62  // matches diversification length.
63  if (keyblob_share_num_words(key_derivation_key.config) * sizeof(uint32_t) !=
64  kKmacSideloadKeyLength / 8) {
65  return OTCRYPTO_BAD_ARGS;
66  }
67  // Configure keymgr with diversification input and then generate the
68  // sideload key.
69  keymgr_diversification_t diversification;
70  // Diversification call also checks that `key_derivation_key.keyblob_length`
71  // is 8 words long.
72  HARDENED_TRY(keyblob_to_keymgr_diversification(&key_derivation_key,
73  &diversification));
74  HARDENED_TRY(keymgr_generate_key_kmac(diversification));
75  } else if (key_derivation_key.config.hw_backed == kHardenedBoolFalse) {
76  if (key_derivation_key.keyblob_length !=
77  keyblob_num_words(key_derivation_key.config) * sizeof(uint32_t)) {
78  return OTCRYPTO_BAD_ARGS;
79  }
80  HARDENED_TRY(keyblob_to_shares(&key_derivation_key, &kmac_key.share0,
81  &kmac_key.share1));
82  } else {
83  return OTCRYPTO_BAD_ARGS;
84  }
85 
86  // At the moment, `kmac_kmac_128/256` only supports word-sized digest lengths.
87  if (output_key_material->config.key_length % sizeof(uint32_t) != 0) {
88  return OTCRYPTO_NOT_IMPLEMENTED;
89  }
90 
91  // Output key cannot be hardware-backed.
92  if (output_key_material->config.hw_backed != kHardenedBoolFalse) {
93  return OTCRYPTO_BAD_ARGS;
94  }
95  HARDENED_CHECK_EQ(output_key_material->config.hw_backed, kHardenedBoolFalse);
96 
97  // Check the keyblob length.
98  if (output_key_material->keyblob_length !=
99  keyblob_num_words(output_key_material->config) * sizeof(uint32_t)) {
100  return OTCRYPTO_BAD_ARGS;
101  }
102 
103  switch (launder32(key_derivation_key.config.key_mode)) {
104  case kOtcryptoKeyModeKdfKmac128: {
105  HARDENED_CHECK_EQ(key_derivation_key.config.key_mode,
106  kOtcryptoKeyModeKdfKmac128);
107  // No need to further check key size against security level because
108  // `kmac_key_length_check` ensures that the key is at least 128-bit.
109  HARDENED_TRY(kmac_kmac_128(
110  &kmac_key, /*masked_digest=*/kHardenedBoolTrue, context.data,
111  context.len, label.data, label.len, output_key_material->keyblob,
112  output_key_material->config.key_length / sizeof(uint32_t)));
113  break;
114  }
115  case kOtcryptoKeyModeKdfKmac256: {
116  HARDENED_CHECK_EQ(key_derivation_key.config.key_mode,
117  kOtcryptoKeyModeKdfKmac256);
118  // Check that key size matches the security strength. It should be at
119  // least 256-bit.
120  if (key_derivation_key.config.key_length < 256 / 8) {
121  return OTCRYPTO_BAD_ARGS;
122  }
123  HARDENED_TRY(kmac_kmac_256(
124  &kmac_key, /*masked_digest=*/kHardenedBoolTrue, context.data,
125  context.len, label.data, label.len, output_key_material->keyblob,
126  output_key_material->config.key_length / sizeof(uint32_t)));
127  break;
128  }
129  default:
130  return OTCRYPTO_BAD_ARGS;
131  }
132 
133  output_key_material->checksum =
134  integrity_blinded_checksum(output_key_material);
135 
136  // Clear the KMAC sideload slot in case the key was sideloaded.
137  return keymgr_sideload_clear_kmac();
138 }