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"
15 #define MODULE_ID MAKE_MODULE_ID('h', 'k', 'd')
25 size_t *digest_words) {
27 switch (launder32(key_mode)) {
28 case kOtcryptoKeyModeHmacSha256:
30 *digest_words = 256 / 32;
32 case kOtcryptoKeyModeHmacSha384:
34 *digest_words = 384 / 32;
36 case kOtcryptoKeyModeHmacSha512:
38 *digest_words = 512 / 32;
41 return OTCRYPTO_BAD_ARGS;
43 HARDENED_CHECK_NE(*digest_words, 0);
52 size_t digest_wordlen;
54 digest_num_words_from_key_mode(ikm.config.key_mode, &digest_wordlen));
55 size_t digest_bytelen = digest_wordlen *
sizeof(uint32_t);
59 .version = kOtcryptoLibVersion1,
60 .key_mode = ikm.config.key_mode,
61 .key_length = digest_bytelen,
64 .security_level = kOtcryptoKeySecurityLevelLow,
66 size_t keyblob_wordlen = keyblob_num_words(prk_config);
67 uint32_t keyblob[keyblob_wordlen];
71 .keyblob_length =
sizeof(keyblob),
91 static status_t hkdf_check_prk(
size_t digest_words,
93 if (launder32(prk->config.key_mode) >> 16 != kOtcryptoKeyTypeHmac) {
94 return OTCRYPTO_BAD_ARGS;
99 size_t digest_bytelen = digest_words *
sizeof(uint32_t);
100 if (launder32(prk->config.key_length) != digest_bytelen) {
101 return OTCRYPTO_BAD_ARGS;
106 size_t keyblob_bytelen = keyblob_num_words(prk->config) *
sizeof(uint32_t);
107 if (launder32(prk->keyblob_length) != keyblob_bytelen) {
108 return OTCRYPTO_BAD_ARGS;
114 HARDENED_TRY(keyblob_ensure_xor_masked(prk->config));
123 if (ikm.keyblob == NULL || prk == NULL || prk->keyblob == NULL) {
124 return OTCRYPTO_BAD_ARGS;
126 if (salt.data == NULL && salt.len != 0) {
127 return OTCRYPTO_BAD_ARGS;
132 return OTCRYPTO_BAD_ARGS;
135 if (launder32(ikm.config.security_level) != kOtcryptoKeySecurityLevelLow ||
136 launder32(prk->config.security_level) != kOtcryptoKeySecurityLevelLow) {
138 return OTCRYPTO_NOT_IMPLEMENTED;
144 if (launder32(prk->config.key_mode) != launder32(ikm.config.key_mode)) {
145 return OTCRYPTO_BAD_ARGS;
151 size_t digest_words = 0;
153 digest_num_words_from_key_mode(ikm.config.key_mode, &digest_words));
156 HARDENED_TRY(hkdf_check_prk(digest_words, prk));
160 size_t salt_bytelen =
161 (salt.len == 0) ? digest_words *
sizeof(uint32_t) : salt.len;
162 size_t salt_wordlen =
ceil_div(salt_bytelen,
sizeof(uint32_t));
163 uint32_t salt_aligned_data[salt_wordlen];
164 memset(salt_aligned_data, 0,
sizeof(salt_aligned_data));
166 memcpy(salt_aligned_data, salt.data, salt.len);
174 uint32_t *ikm_share0;
175 uint32_t *ikm_share1;
176 HARDENED_TRY(keyblob_to_shares(&ikm, &ikm_share0, &ikm_share1));
177 uint32_t unmasked_ikm_data[keyblob_share_num_words(ikm.config)];
178 for (
size_t i = 0; i <
ARRAYSIZE(unmasked_ikm_data); i++) {
179 unmasked_ikm_data[i] = ikm_share0[i] ^ ikm_share1[i];
182 .data = (
unsigned char *)unmasked_ikm_data,
183 .len = ikm.config.key_length,
188 uint32_t salt_mask[
ARRAYSIZE(salt_aligned_data)];
189 memset(salt_mask, 0,
sizeof(salt_mask));
191 .version = kOtcryptoLibVersion1,
192 .key_mode = ikm.config.key_mode,
193 .key_length = salt_bytelen,
196 .security_level = kOtcryptoKeySecurityLevelLow,
198 uint32_t salt_keyblob[keyblob_num_words(salt_key_config)];
199 TRY(keyblob_from_key_and_mask(salt_aligned_data, salt_mask, salt_key_config,
202 .config = salt_key_config,
203 .keyblob = salt_keyblob,
204 .keyblob_length =
sizeof(salt_keyblob),
208 uint32_t tag_data[digest_words];
214 uint32_t prk_mask[digest_words];
215 memset(prk_mask, 0,
sizeof(prk_mask));
217 keyblob_from_key_and_mask(tag_data, prk_mask, prk->config, prk->keyblob));
218 prk->checksum = integrity_blinded_checksum(prk);
225 if (okm == NULL || okm->keyblob == NULL || prk.keyblob == NULL) {
226 return OTCRYPTO_BAD_ARGS;
228 if (info.data == NULL && info.len != 0) {
229 return OTCRYPTO_BAD_ARGS;
232 if (launder32(okm->config.security_level) != kOtcryptoKeySecurityLevelLow ||
233 launder32(prk.config.security_level) != kOtcryptoKeySecurityLevelLow) {
235 return OTCRYPTO_NOT_IMPLEMENTED;
239 size_t digest_words = 0;
241 digest_num_words_from_key_mode(prk.config.key_mode, &digest_words));
244 HARDENED_TRY(hkdf_check_prk(digest_words, &prk));
248 HARDENED_TRY(keyblob_ensure_xor_masked(okm->config));
251 size_t keyblob_bytelen = keyblob_num_words(okm->config) *
sizeof(uint32_t);
252 if (launder32(okm->keyblob_length) != keyblob_bytelen) {
253 return OTCRYPTO_BAD_ARGS;
259 size_t okm_bytelen = okm->config.key_length;
260 size_t okm_wordlen =
ceil_div(okm_bytelen,
sizeof(uint32_t));
261 size_t num_iterations =
ceil_div(okm_wordlen, digest_words);
262 if (launder32(num_iterations) > 255) {
263 return OTCRYPTO_BAD_ARGS;
265 HARDENED_CHECK_LE(num_iterations, 255);
268 uint8_t info_and_counter_data[info.len + 1];
269 memcpy(info_and_counter_data, info.data, info.len);
270 info_and_counter_data[info.len] = 0x00;
272 .data = info_and_counter_data,
273 .len =
sizeof(info_and_counter_data),
278 uint32_t okm_data[okm_wordlen];
279 uint32_t *t_data = okm_data;
280 for (uint8_t i = 0; i < num_iterations; i++) {
281 info_and_counter_data[info.len] = i + 1;
284 if (launder32(i) != 0) {
286 .data = (
unsigned char *)t_data,
287 .len = digest_words *
sizeof(uint32_t),
290 t_data += digest_words;
301 uint32_t mask[digest_words];
302 memset(mask, 0,
sizeof(mask));
306 keyblob_from_key_and_mask(okm_data, mask, okm->config, okm->keyblob));
307 okm->checksum = integrity_blinded_checksum(okm);