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"
16 #define MODULE_ID MAKE_MODULE_ID('k', 'd', 'f')
25 for (
size_t i = 0; i < buffer.len; i++) {
26 if (buffer.data[i] == 0x00) {
27 return OTCRYPTO_BAD_ARGS;
41 size_t *digest_words) {
43 switch (launder32(key_mode)) {
44 case kOtcryptoKeyModeHmacSha256:
46 *digest_words = 256 / 32;
48 case kOtcryptoKeyModeHmacSha384:
50 *digest_words = 384 / 32;
52 case kOtcryptoKeyModeHmacSha512:
54 *digest_words = 512 / 32;
57 return OTCRYPTO_BAD_ARGS;
59 HARDENED_CHECK_NE(*digest_words, 0);
69 if (keying_material == NULL || keying_material->keyblob == NULL ||
70 key_derivation_key.keyblob == NULL) {
71 return OTCRYPTO_BAD_ARGS;
74 if (launder32(keying_material->config.security_level) !=
75 kOtcryptoKeySecurityLevelLow ||
76 launder32(key_derivation_key.config.security_level) !=
77 kOtcryptoKeySecurityLevelLow) {
79 return OTCRYPTO_NOT_IMPLEMENTED;
83 if (kdf_label.data == NULL && kdf_label.len != 0) {
84 return OTCRYPTO_BAD_ARGS;
88 if (kdf_context.data == NULL && kdf_context.len != 0) {
89 return OTCRYPTO_BAD_ARGS;
94 return OTCRYPTO_BAD_ARGS;
98 if (required_byte_len == 0) {
99 return OTCRYPTO_BAD_ARGS;
103 size_t digest_word_len = 0;
104 HARDENED_TRY(digest_num_words_from_key_mode(
105 key_derivation_key.config.key_mode, &digest_word_len));
109 HARDENED_TRY(keyblob_ensure_xor_masked(keying_material->config));
115 return OTCRYPTO_BAD_ARGS;
117 if (keying_material->config.key_length != required_byte_len ||
118 keying_material->keyblob_length !=
119 keyblob_num_words(keying_material->config) *
sizeof(uint32_t)) {
120 return OTCRYPTO_BAD_ARGS;
123 return OTCRYPTO_BAD_ARGS;
128 size_t required_word_len =
ceil_div(required_byte_len,
sizeof(uint32_t));
129 size_t num_iterations =
ceil_div(required_word_len, digest_word_len);
130 if (launder32(num_iterations) > UINT32_MAX) {
131 return OTCRYPTO_BAD_ARGS;
133 HARDENED_CHECK_LE(num_iterations, UINT32_MAX);
138 HARDENED_TRY(check_zero_byte(kdf_label));
139 HARDENED_TRY(check_zero_byte(kdf_context));
143 HARDENED_CHECK_LE(required_byte_len, UINT32_MAX / 8);
144 uint32_t required_bit_len = __builtin_bswap32(required_byte_len * 8);
153 uint32_t keying_material_len =
154 required_word_len + digest_word_len - required_word_len % digest_word_len;
155 uint32_t keying_material_data[keying_material_len];
157 for (uint32_t i = 0; i < num_iterations; i++) {
160 uint32_t counter_be = __builtin_bswap32(i + 1);
163 .data = (
const unsigned char *
const)&counter_be,
164 .len =
sizeof(counter_be)}));
169 .len =
sizeof(zero)}));
173 .data = (
const unsigned char *
const)&required_bit_len,
174 .len =
sizeof(required_bit_len)}));
175 uint32_t *tag_dest = keying_material_data + i * digest_word_len;
182 uint32_t mask[digest_word_len];
183 memset(mask, 0,
sizeof(mask));
186 HARDENED_TRY(keyblob_from_key_and_mask(keying_material_data, mask,
187 keying_material->config,
188 keying_material->keyblob));
190 keying_material->checksum = integrity_blinded_checksum(keying_material);
201 if (key_derivation_key.keyblob == NULL || keying_material == NULL ||
202 keying_material->keyblob == NULL) {
203 return OTCRYPTO_BAD_ARGS;
207 if (kdf_label.data == NULL && kdf_label.len != 0) {
208 return OTCRYPTO_BAD_ARGS;
212 if (kdf_label.len > kKmacCustStrMaxSize) {
213 return OTCRYPTO_BAD_ARGS;
217 if (kdf_context.data == NULL && kdf_context.len != 0) {
218 return OTCRYPTO_BAD_ARGS;
223 return OTCRYPTO_BAD_ARGS;
228 HARDENED_TRY(kmac_key_length_check(key_derivation_key.config.key_length));
233 .hw_backed = key_derivation_key.config.hw_backed,
234 .len = key_derivation_key.config.key_length,
240 if (keyblob_share_num_words(key_derivation_key.config) *
sizeof(uint32_t) !=
241 kKmacSideloadKeyLength / 8) {
242 return OTCRYPTO_BAD_ARGS;
249 HARDENED_TRY(keyblob_to_keymgr_diversification(&key_derivation_key,
251 HARDENED_TRY(keymgr_generate_key_kmac(diversification));
253 if (key_derivation_key.keyblob_length !=
254 keyblob_num_words(key_derivation_key.config) *
sizeof(uint32_t)) {
255 return OTCRYPTO_BAD_ARGS;
257 HARDENED_TRY(keyblob_to_shares(&key_derivation_key, &kmac_key.share0,
260 return OTCRYPTO_BAD_ARGS;
264 if (required_byte_len == 0) {
265 return OTCRYPTO_BAD_ARGS;
268 if (required_byte_len %
sizeof(uint32_t) != 0) {
269 return OTCRYPTO_NOT_IMPLEMENTED;
276 return OTCRYPTO_BAD_ARGS;
278 if (keying_material->config.key_length != required_byte_len ||
279 keying_material->keyblob_length !=
280 keyblob_num_words(keying_material->config) *
sizeof(uint32_t)) {
281 return OTCRYPTO_BAD_ARGS;
284 return OTCRYPTO_BAD_ARGS;
287 if (kmac_mode == kOtcryptoKmacModeKmac128) {
289 if (key_derivation_key.config.key_mode != kOtcryptoKeyModeKdfKmac128) {
290 return OTCRYPTO_BAD_ARGS;
294 HARDENED_TRY(kmac_kmac_128(&kmac_key, kdf_context.data, kdf_context.len,
295 kdf_label.data, kdf_label.len,
296 keying_material->keyblob,
297 required_byte_len /
sizeof(uint32_t)));
298 }
else if (kmac_mode == kOtcryptoKmacModeKmac256) {
300 if (key_derivation_key.config.key_mode != kOtcryptoKeyModeKdfKmac256) {
301 return OTCRYPTO_BAD_ARGS;
305 if (key_derivation_key.config.key_length < 256 / 8) {
306 return OTCRYPTO_BAD_ARGS;
308 HARDENED_TRY(kmac_kmac_256(&kmac_key, kdf_context.data, kdf_context.len,
309 kdf_label.data, kdf_label.len,
310 keying_material->keyblob,
311 required_byte_len /
sizeof(uint32_t)));
313 return OTCRYPTO_BAD_ARGS;
316 keying_material->checksum = integrity_blinded_checksum(keying_material);
319 HARDENED_TRY(keymgr_sideload_clear_kmac());
321 return OTCRYPTO_BAD_ARGS;
332 size_t digest_wordlen;
334 digest_num_words_from_key_mode(ikm.config.key_mode, &digest_wordlen));
335 size_t digest_bytelen = digest_wordlen *
sizeof(uint32_t);
339 .version = kOtcryptoLibVersion1,
340 .key_mode = ikm.config.key_mode,
341 .key_length = digest_bytelen,
344 .security_level = kOtcryptoKeySecurityLevelLow,
346 size_t keyblob_wordlen = keyblob_num_words(prk_config);
347 uint32_t keyblob[keyblob_wordlen];
349 .config = prk_config,
351 .keyblob_length =
sizeof(keyblob),
371 static status_t hkdf_check_prk(
size_t digest_words,
373 if (launder32(prk->config.key_mode) >> 16 != kOtcryptoKeyTypeHmac) {
374 return OTCRYPTO_BAD_ARGS;
379 size_t digest_bytelen = digest_words *
sizeof(uint32_t);
380 if (launder32(prk->config.key_length) != digest_bytelen) {
381 return OTCRYPTO_BAD_ARGS;
386 size_t keyblob_bytelen = keyblob_num_words(prk->config) *
sizeof(uint32_t);
387 if (launder32(prk->keyblob_length) != keyblob_bytelen) {
388 return OTCRYPTO_BAD_ARGS;
394 HARDENED_TRY(keyblob_ensure_xor_masked(prk->config));
403 if (ikm.keyblob == NULL || prk == NULL || prk->keyblob == NULL) {
404 return OTCRYPTO_BAD_ARGS;
406 if (salt.data == NULL && salt.len != 0) {
407 return OTCRYPTO_BAD_ARGS;
412 return OTCRYPTO_BAD_ARGS;
415 if (launder32(ikm.config.security_level) != kOtcryptoKeySecurityLevelLow ||
416 launder32(prk->config.security_level) != kOtcryptoKeySecurityLevelLow) {
418 return OTCRYPTO_NOT_IMPLEMENTED;
424 if (launder32(prk->config.key_mode) != launder32(ikm.config.key_mode)) {
425 return OTCRYPTO_BAD_ARGS;
431 size_t digest_words = 0;
433 digest_num_words_from_key_mode(ikm.config.key_mode, &digest_words));
436 HARDENED_TRY(hkdf_check_prk(digest_words, prk));
440 size_t salt_bytelen =
441 (salt.len == 0) ? digest_words *
sizeof(uint32_t) : salt.len;
442 size_t salt_wordlen =
ceil_div(salt_bytelen,
sizeof(uint32_t));
443 uint32_t salt_aligned_data[salt_wordlen];
444 memset(salt_aligned_data, 0,
sizeof(salt_aligned_data));
446 memcpy(salt_aligned_data, salt.data, salt.len);
454 uint32_t *ikm_share0;
455 uint32_t *ikm_share1;
456 HARDENED_TRY(keyblob_to_shares(&ikm, &ikm_share0, &ikm_share1));
457 uint32_t unmasked_ikm_data[keyblob_share_num_words(ikm.config)];
458 for (
size_t i = 0; i <
ARRAYSIZE(unmasked_ikm_data); i++) {
459 unmasked_ikm_data[i] = ikm_share0[i] ^ ikm_share1[i];
462 .data = (
unsigned char *)unmasked_ikm_data,
463 .len = ikm.config.key_length,
468 uint32_t salt_mask[
ARRAYSIZE(salt_aligned_data)];
469 memset(salt_mask, 0,
sizeof(salt_mask));
471 .version = kOtcryptoLibVersion1,
472 .key_mode = ikm.config.key_mode,
473 .key_length = salt_bytelen,
476 .security_level = kOtcryptoKeySecurityLevelLow,
478 uint32_t salt_keyblob[keyblob_num_words(salt_key_config)];
479 TRY(keyblob_from_key_and_mask(salt_aligned_data, salt_mask, salt_key_config,
482 .config = salt_key_config,
483 .keyblob = salt_keyblob,
484 .keyblob_length =
sizeof(salt_keyblob),
488 uint32_t tag_data[digest_words];
494 uint32_t prk_mask[digest_words];
495 memset(prk_mask, 0,
sizeof(prk_mask));
497 keyblob_from_key_and_mask(tag_data, prk_mask, prk->config, prk->keyblob));
498 prk->checksum = integrity_blinded_checksum(prk);
505 if (okm == NULL || okm->keyblob == NULL || prk.keyblob == NULL) {
506 return OTCRYPTO_BAD_ARGS;
508 if (info.data == NULL && info.len != 0) {
509 return OTCRYPTO_BAD_ARGS;
512 if (launder32(okm->config.security_level) != kOtcryptoKeySecurityLevelLow ||
513 launder32(prk.config.security_level) != kOtcryptoKeySecurityLevelLow) {
515 return OTCRYPTO_NOT_IMPLEMENTED;
519 size_t digest_words = 0;
521 digest_num_words_from_key_mode(prk.config.key_mode, &digest_words));
524 HARDENED_TRY(hkdf_check_prk(digest_words, &prk));
528 HARDENED_TRY(keyblob_ensure_xor_masked(okm->config));
531 size_t keyblob_bytelen = keyblob_num_words(okm->config) *
sizeof(uint32_t);
532 if (launder32(okm->keyblob_length) != keyblob_bytelen) {
533 return OTCRYPTO_BAD_ARGS;
539 size_t okm_bytelen = okm->config.key_length;
540 size_t okm_wordlen =
ceil_div(okm_bytelen,
sizeof(uint32_t));
541 size_t num_iterations =
ceil_div(okm_wordlen, digest_words);
542 if (launder32(num_iterations) > 255) {
543 return OTCRYPTO_BAD_ARGS;
545 HARDENED_CHECK_LE(num_iterations, 255);
548 uint8_t info_and_counter_data[info.len + 1];
549 memcpy(info_and_counter_data, info.data, info.len);
550 info_and_counter_data[info.len] = 0x00;
552 .data = info_and_counter_data,
553 .len =
sizeof(info_and_counter_data),
558 uint32_t okm_data[okm_wordlen];
559 uint32_t *t_data = okm_data;
560 for (uint8_t i = 0; i < num_iterations; i++) {
561 info_and_counter_data[info.len] = i + 1;
564 if (launder32(i) != 0) {
566 .data = (
unsigned char *)t_data,
567 .len = digest_words *
sizeof(uint32_t),
570 t_data += digest_words;
581 uint32_t mask[digest_words];
582 memset(mask, 0,
sizeof(mask));
586 keyblob_from_key_and_mask(okm_data, mask, okm->config, okm->keyblob));
587 okm->checksum = integrity_blinded_checksum(okm);