Software APIs
kmac.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"
12 
13 // Module ID for status codes.
14 #define MODULE_ID MAKE_MODULE_ID('k', 'm', 'c')
15 
17  otcrypto_const_byte_buf_t input_message,
18  otcrypto_const_byte_buf_t customization_string,
19  size_t required_output_len,
21  // TODO (#16410) Revisit/complete error checks
22 
23  // Check for null pointers.
24  if (key == NULL || key->keyblob == NULL || tag.data == NULL) {
25  return OTCRYPTO_BAD_ARGS;
26  }
27 
28  // Check for null input message with nonzero length.
29  if (input_message.data == NULL && input_message.len != 0) {
30  return OTCRYPTO_BAD_ARGS;
31  }
32 
33  // Check for null customization string with nonzero length.
34  if (customization_string.data == NULL && customization_string.len != 0) {
35  return OTCRYPTO_BAD_ARGS;
36  }
37 
38  // Ensure that tag buffer length and `required_output_len` match each other.
39  if (required_output_len != tag.len * sizeof(uint32_t) ||
40  required_output_len == 0) {
41  return OTCRYPTO_BAD_ARGS;
42  }
43 
44  size_t key_len = keyblob_share_num_words(key->config) * sizeof(uint32_t);
45 
46  // Check `key_len` is valid/supported by KMAC HWIP.
47  HARDENED_TRY(kmac_key_length_check(key_len));
48 
49  // Check the integrity of the blinded key.
50  if (integrity_blinded_key_check(key) != kHardenedBoolTrue) {
51  return OTCRYPTO_BAD_ARGS;
52  }
53 
54  kmac_blinded_key_t kmac_key = {
55  .share0 = NULL,
56  .share1 = NULL,
57  .hw_backed = key->config.hw_backed,
58  .len = key_len,
59  };
60 
61  if (key->config.hw_backed == kHardenedBoolTrue) {
62  if (key_len != kKmacSideloadKeyLength / 8) {
63  return OTCRYPTO_BAD_ARGS;
64  }
65  // Configure keymgr with diversification input and then generate the
66  // sideload key.
67  keymgr_diversification_t diversification;
68  // Diversification call also checks that `key->keyblob_length` is 8 words
69  // long.
70  HARDENED_TRY(keyblob_to_keymgr_diversification(key, &diversification));
71  HARDENED_TRY(keymgr_generate_key_kmac(diversification));
72  } else if (key->config.hw_backed == kHardenedBoolFalse) {
73  // Check `key_len` matches `keyblob_length`.
74  if (key->keyblob_length != 2 * key->config.key_length) {
75  return OTCRYPTO_BAD_ARGS;
76  }
77  HARDENED_TRY(keyblob_to_shares(key, &kmac_key.share0, &kmac_key.share1));
78  } else {
79  return OTCRYPTO_BAD_ARGS;
80  }
81 
82  switch (key->config.key_mode) {
83  case kOtcryptoKeyModeKmac128:
84  HARDENED_TRY(kmac_kmac_128(
85  &kmac_key, /*masked_digest=*/kHardenedBoolFalse, input_message.data,
86  input_message.len, customization_string.data,
87  customization_string.len, tag.data, tag.len));
88  break;
89  case kOtcryptoKeyModeKmac256:
90  HARDENED_TRY(kmac_kmac_256(
91  &kmac_key, /*masked_digest=*/kHardenedBoolFalse, input_message.data,
92  input_message.len, customization_string.data,
93  customization_string.len, tag.data, tag.len));
94  break;
95  default:
96  return OTCRYPTO_BAD_ARGS;
97  }
98 
99  if (key->config.hw_backed == kHardenedBoolTrue) {
100  HARDENED_TRY(keymgr_sideload_clear_kmac());
101  } else if (key->config.hw_backed != kHardenedBoolFalse) {
102  return OTCRYPTO_BAD_ARGS;
103  }
104 
105  return OTCRYPTO_OK;
106 }