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 #include "sw/device/lib/base/status.h"
7 #include "sw/device/lib/crypto/impl/integrity.h"
8 #include "sw/device/lib/crypto/impl/keyblob.h"
12 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
13 #include "sw/device/lib/ujson/ujson.h"
14 #include "sw/device/tests/crypto/cryptotest/json/kmac_commands.h"
15 
16 const int MaxCustomizationStringBytes = 36;
17 
18 const int MaxKmacTagBytes = 64;
19 const int MaxKmacTagWords = MaxKmacTagBytes / sizeof(uint32_t);
20 
21 const unsigned int kOtcryptoKmacTagBytesKmac128 = 32;
22 const unsigned int kOtcryptoKmacTagBytesKmac256 = 64;
23 
24 // Random value for masking, as large as the longest test key. This value
25 // should not affect the result.
26 static const uint32_t kTestMask[48] = {
27  0x61A5D83D, 0x55D6B114, 0xFD2771B8, 0xF70CB89D, 0x342A1205, 0x03571376,
28  0xA23651E3, 0xD246D8E6, 0x9A6AAAA0, 0x105880E2, 0x0C22EA57, 0xB86D07D5,
29  0x6BAA9320, 0xD09F20D8, 0xE9A4520E, 0xEB0BA531, 0x19FEBE66, 0xEAEA1CF1,
30  0x3618EFF5, 0x66FB71DC, 0x703A9932, 0x8C7C7807, 0xFA5D68E5, 0x8364B8C5,
31  0x5BAFF5E7, 0x32BDD917, 0x66254D17, 0xABAB9FD4, 0x7FAE4EE8, 0x3D1F7A0D,
32  0x00C2C8A6, 0xC6ED700E, 0xD86D283C, 0xD6753A6E, 0x0555D290, 0x08C0DA0A,
33  0x9F18BE27, 0x263EA1FC, 0xCA8D6517, 0x88156B88, 0xE6BE966E, 0xD6D8E410,
34  0x2E5A7583, 0xDDB18102, 0x0C9157A7, 0x8437AA66, 0x88EF488A, 0x45A1B1B1,
35 };
36 
37 status_t handle_kmac(ujson_t *uj) {
38  // Declare test arguments
39  cryptotest_kmac_mode_t uj_mode;
40  cryptotest_kmac_required_tag_length_t uj_required_tag_length;
41  cryptotest_kmac_key_t uj_key;
42  cryptotest_kmac_message_t uj_message;
43  cryptotest_kmac_customization_string_t uj_customization_string;
44  // Deserialize test arguments from UART
45  TRY(ujson_deserialize_cryptotest_kmac_mode_t(uj, &uj_mode));
46  TRY(ujson_deserialize_cryptotest_kmac_required_tag_length_t(
47  uj, &uj_required_tag_length));
48  TRY(ujson_deserialize_cryptotest_kmac_key_t(uj, &uj_key));
49  TRY(ujson_deserialize_cryptotest_kmac_message_t(uj, &uj_message));
50  TRY(ujson_deserialize_cryptotest_kmac_customization_string_t(
51  uj, &uj_customization_string));
52 
54  otcrypto_key_mode_t key_mode;
55  switch (uj_mode) {
56  case kCryptotestKmacModeKmac128:
57  key_mode = kOtcryptoKeyModeKmac128;
58  mode = kOtcryptoKmacModeKmac128;
59  break;
60  case kCryptotestKmacModeKmac256:
61  key_mode = kOtcryptoKeyModeKmac256;
62  mode = kOtcryptoKmacModeKmac256;
63  break;
64  default:
65  LOG_ERROR("Unsupported KMAC mode: %d", uj_mode);
66  return INVALID_ARGUMENT();
67  }
68  // Build the key configuration
69  otcrypto_key_config_t config = {
70  .version = kOtcryptoLibVersion1,
71  .key_mode = key_mode,
72  .key_length = uj_key.key_len,
73  .hw_backed = kHardenedBoolFalse,
74  .security_level = kOtcryptoKeySecurityLevelLow,
75  };
76  // Create buffer to store key
77  uint32_t key_buf[uj_key.key_len];
78  memcpy(key_buf, uj_key.key, uj_key.key_len);
79  // Create keyblob
80  uint32_t keyblob[keyblob_num_words(config)];
81  // Create blinded key
82  TRY(keyblob_from_key_and_mask(key_buf, kTestMask, config, keyblob));
84  .config = config,
85  .keyblob_length = sizeof(keyblob),
86  .keyblob = keyblob,
87  };
88 
89  // Create input message
90  uint8_t msg_buf[uj_message.message_len];
91  memcpy(msg_buf, uj_message.message, uj_message.message_len);
92  otcrypto_const_byte_buf_t input_message = {
93  .len = uj_message.message_len,
94  .data = msg_buf,
95  };
96 
97  // Create customization string
98  uint8_t customization_string_buf[uj_customization_string
99  .customization_string_len];
100  memcpy(customization_string_buf, uj_customization_string.customization_string,
101  uj_customization_string.customization_string_len);
102  otcrypto_const_byte_buf_t customization_string = {
103  .len = uj_customization_string.customization_string_len,
104  .data = customization_string_buf,
105  };
106 
107  // Create tag
108  uint32_t tag_buf[MaxKmacTagWords];
109  otcrypto_word32_buf_t tag = {
110  .len = uj_required_tag_length.required_tag_length / sizeof(uint32_t),
111  .data = tag_buf,
112  };
114  otcrypto_kmac(&key, input_message, mode, customization_string,
115  uj_required_tag_length.required_tag_length, tag);
116  if (status.value != kOtcryptoStatusValueOk) {
117  return INTERNAL(status.value);
118  }
119  // Copy tag to uJSON type
120  cryptotest_kmac_tag_t uj_tag;
121  memcpy(uj_tag.tag, tag_buf, uj_required_tag_length.required_tag_length);
122  uj_tag.tag_len = uj_required_tag_length.required_tag_length;
123 
124  // Send tag to host via UART
125  RESP_OK(ujson_serialize_cryptotest_kmac_tag_t, uj, &uj_tag);
126  return OK_STATUS(0);
127 }