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