Software APIs
key_transport.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/impl/integrity.h"
9 #include "sw/device/lib/crypto/impl/keyblob.h"
10 #include "sw/device/lib/crypto/impl/status.h"
13 
14 // Module ID for status codes.
15 #define MODULE_ID MAKE_MODULE_ID('k', 't', 'r')
16 
19  if (key == NULL || key->keyblob == NULL) {
20  return OTCRYPTO_BAD_ARGS;
21  }
22 
23  // Ensure that the key material is masked with XOR; this will fail on
24  // hardware-backed or non-symmetric keys.
25  HARDENED_TRY(keyblob_ensure_xor_masked(key->config));
26 
27  // Get pointers to the shares within the keyblob. Fails if the key length
28  // doesn't match the mode.
29  uint32_t *share0;
30  uint32_t *share1;
31  HARDENED_TRY(keyblob_to_shares(key, &share0, &share1));
32 
33  // Construct buffers to direct the DRBG output into the keyblob.
34  otcrypto_word32_buf_t share0_buf = {
35  .data = share0,
36  .len = keyblob_share_num_words(key->config),
37  };
38  otcrypto_word32_buf_t share1_buf = {
39  .data = share1,
40  .len = keyblob_share_num_words(key->config),
41  };
42 
43  // Construct an empty buffer for the "additional input" to the DRBG generate
44  // function.
45  otcrypto_const_byte_buf_t empty = {.data = NULL, .len = 0};
46 
47  // Generate each share of the key independently.
48  HARDENED_TRY(otcrypto_drbg_instantiate(perso_string));
49  HARDENED_TRY(otcrypto_drbg_generate(empty, share0_buf));
50  HARDENED_TRY(otcrypto_drbg_generate(empty, share1_buf));
51 
52  // Populate the checksum and return.
53  key->checksum = integrity_blinded_checksum(key);
54  return OTCRYPTO_OK;
55 }
56 
58  const uint32_t salt[7],
60  if (key == NULL || key->keyblob == NULL) {
61  return OTCRYPTO_BAD_ARGS;
62  }
63  if (key->keyblob_length != 8 * sizeof(uint32_t) ||
64  key->config.hw_backed != kHardenedBoolTrue) {
65  return OTCRYPTO_BAD_ARGS;
66  }
67 
68  // Get the key type from the top 16 bits of the full mode and ensure that it
69  // is not RSA. All other key types are acceptable for hardware-backed keys.
70  otcrypto_key_type_t key_type =
71  (otcrypto_key_type_t)(key->config.key_mode >> 16);
72  if (key_type == kOtcryptoKeyTypeRsa) {
73  return OTCRYPTO_BAD_ARGS;
74  }
75 
76  // Copy the version and salt into the keyblob.
77  key->keyblob[0] = version;
78  memcpy(&key->keyblob[1], salt, 7 * sizeof(uint32_t));
79 
80  // Set the checksum.
81  key->checksum = integrity_blinded_checksum(key);
82 
83  return OTCRYPTO_OK;
84 }
85 
87  const otcrypto_const_word32_buf_t key_share0,
88  const otcrypto_const_word32_buf_t key_share1,
89  otcrypto_blinded_key_t *blinded_key) {
90  if (blinded_key == NULL || blinded_key->keyblob == NULL ||
91  key_share0.data == NULL || key_share1.data == NULL) {
92  return OTCRYPTO_BAD_ARGS;
93  }
94 
95  // Ensure the key is symmetric and not hardware-backed.
96  HARDENED_TRY(keyblob_ensure_xor_masked(blinded_key->config));
97 
98  // Check the lengths of the shares.
99  size_t share_words = launder32(keyblob_share_num_words(blinded_key->config));
100  if (launder32(key_share0.len) != share_words ||
101  launder32(key_share1.len) != share_words) {
102  return OTCRYPTO_BAD_ARGS;
103  }
104  HARDENED_CHECK_EQ(key_share0.len,
105  keyblob_share_num_words(blinded_key->config));
106  HARDENED_CHECK_EQ(key_share1.len,
107  keyblob_share_num_words(blinded_key->config));
108 
109  // Check the length of the keyblob.
110  size_t keyblob_words = launder32(keyblob_num_words(blinded_key->config));
111  if ((blinded_key->keyblob_length % sizeof(uint32_t) != 0) ||
112  (blinded_key->keyblob_length / sizeof(uint32_t) != keyblob_words)) {
113  return OTCRYPTO_BAD_ARGS;
114  }
115  HARDENED_CHECK_EQ(blinded_key->keyblob_length,
116  keyblob_words * sizeof(uint32_t));
117 
118  // Construct the blinded key.
119  keyblob_from_shares(key_share0.data, key_share1.data, blinded_key->config,
120  blinded_key->keyblob);
121  blinded_key->checksum = integrity_blinded_checksum(blinded_key);
122  return OTCRYPTO_OK;
123 }
124 
126  const otcrypto_blinded_key_t blinded_key, otcrypto_word32_buf_t key_share0,
127  otcrypto_word32_buf_t key_share1) {
128  if (blinded_key.keyblob == NULL || key_share0.data == NULL ||
129  key_share1.data == NULL) {
130  return OTCRYPTO_BAD_ARGS;
131  }
132 
133  // Check key integrity.
134  if (launder32(integrity_blinded_key_check(&blinded_key)) !=
136  return OTCRYPTO_BAD_ARGS;
137  }
138  HARDENED_CHECK_EQ(integrity_blinded_key_check(&blinded_key),
140 
141  // Ensure the key is symmetric and not hardware-backed.
142  HARDENED_TRY(keyblob_ensure_xor_masked(blinded_key.config));
143 
144  // Check that key is exportable.
145  if (launder32(blinded_key.config.exportable) != kHardenedBoolTrue) {
146  return OTCRYPTO_BAD_ARGS;
147  }
148  HARDENED_CHECK_EQ(blinded_key.config.exportable, kHardenedBoolTrue);
149 
150  // Check the lengths of the shares.
151  size_t share_words = launder32(keyblob_share_num_words(blinded_key.config));
152  if (launder32(key_share0.len) != share_words ||
153  launder32(key_share1.len) != share_words) {
154  return OTCRYPTO_BAD_ARGS;
155  }
156  HARDENED_CHECK_EQ(key_share0.len,
157  keyblob_share_num_words(blinded_key.config));
158  HARDENED_CHECK_EQ(key_share1.len,
159  keyblob_share_num_words(blinded_key.config));
160 
161  // Check the length of the keyblob.
162  size_t keyblob_words = launder32(keyblob_num_words(blinded_key.config));
163  if ((blinded_key.keyblob_length % sizeof(uint32_t) != 0) ||
164  (blinded_key.keyblob_length / sizeof(uint32_t) != keyblob_words)) {
165  return OTCRYPTO_BAD_ARGS;
166  }
167  HARDENED_CHECK_EQ(blinded_key.keyblob_length,
168  keyblob_words * sizeof(uint32_t));
169 
170  // Get pointers to the internal shares and copy them into output buffers.
171  uint32_t *keyblob_share0;
172  uint32_t *keyblob_share1;
173  HARDENED_TRY(
174  keyblob_to_shares(&blinded_key, &keyblob_share0, &keyblob_share1));
175  hardened_memcpy(key_share0.data, keyblob_share0, key_share0.len);
176  hardened_memcpy(key_share1.data, keyblob_share1, key_share1.len);
177  return OTCRYPTO_OK;
178 }