1 /*
2 Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
3 file at the top-level directory of this distribution.
4
5 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 option. This file may not be copied, modified, or distributed
9 except according to those terms.
10 */
11 #include <string.h>
12
13 #include "edhoc.h"
14
15 #include "common/crypto_wrapper.h"
16 #include "common/byte_array.h"
17 #include "common/oscore_edhoc_error.h"
18 #include "common/print_util.h"
19 #include "common/memcpy_s.h"
20
21 #include "edhoc/suites.h"
22 #include "edhoc/buffer_sizes.h"
23
24 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
25 struct edhoc_mock_cb edhoc_crypto_mock_cb;
26 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
27
28 #ifdef MBEDTLS
29 /*
30 IMPORTANT!!!!
31 make sure MBEDTLS_PSA_CRYPTO_CONFIG is defined in include/mbedtls/mbedtls_config.h
32
33
34 modify setting in include/psa/crypto_config.h
35 */
36 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
37
38 #include <psa/crypto.h>
39
40 #include "mbedtls/ecp.h"
41 #include "mbedtls/platform.h"
42 #include "mbedtls/entropy.h"
43 #include "mbedtls/ctr_drbg.h"
44 #include "mbedtls/ecdsa.h"
45 #include "mbedtls/error.h"
46 #include "mbedtls/rsa.h"
47 #include "mbedtls/x509.h"
48
49 #endif
50
51 #ifdef COMPACT25519
52 #include <c25519.h>
53 #include <edsign.h>
54 #include <compact_x25519.h>
55 #endif
56
57 #ifdef TINYCRYPT
58 #include <tinycrypt/aes.h>
59 #include <tinycrypt/ccm_mode.h>
60 #include <tinycrypt/constants.h>
61 #include <tinycrypt/hmac.h>
62 #include <tinycrypt/ecc_dsa.h>
63 #include <tinycrypt/ecc_dh.h>
64 #endif
65
66 #ifdef MBEDTLS
67 #define TRY_EXPECT_PSA(x, expected_result, key_id, err_code) \
68 do { \
69 int retval = (int)(x); \
70 if ((expected_result) != retval) { \
71 if (PSA_KEY_HANDLE_INIT != (key_id)) { \
72 psa_destroy_key(key_id); \
73 } \
74 handle_external_runtime_error(retval, __FILE__, \
75 __LINE__); \
76 return err_code; \
77 } \
78 } while (0)
79
80 /**
81 * @brief Decompresses an elliptic curve point.
82 *
83 *
84 * @param grp elliptic curve group point
85 * @param input the compressed key
86 * @param ilen the lenhgt if the compressed key
87 * @param output the uncopressed key
88 * @param olen the lenhgt of the output
89 * @param osize the actual available size of the out buffer
90 * @return 0 on success
91 */
mbedtls_ecp_decompress(const mbedtls_ecp_group * grp,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen,size_t osize)92 static inline int mbedtls_ecp_decompress(const mbedtls_ecp_group *grp,
93 const unsigned char *input,
94 size_t ilen, unsigned char *output,
95 size_t *olen, size_t osize)
96 {
97 int ret;
98 size_t plen;
99 mbedtls_mpi r;
100 mbedtls_mpi x;
101 mbedtls_mpi n;
102
103 plen = mbedtls_mpi_size(&grp->P);
104
105 *olen = 2 * plen + 1;
106
107 if (osize < *olen)
108 return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
109
110 // output will consist of 0x04|X|Y
111 memcpy(output + 1, input, ilen);
112 output[0] = 0x04;
113
114 mbedtls_mpi_init(&r);
115 mbedtls_mpi_init(&x);
116 mbedtls_mpi_init(&n);
117
118 // x <= input
119 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&x, input, plen));
120
121 // r = x^2
122 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &x, &x));
123
124 // r = x^2 + a
125 if (grp->A.p == NULL) {
126 // Special case where a is -3
127 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&r, &r, 3));
128 } else {
129 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r, &r, &grp->A));
130 }
131
132 // r = x^3 + ax
133 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &r, &x));
134
135 // r = x^3 + ax + b
136 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r, &r, &grp->B));
137
138 // Calculate square root of r over finite field P:
139 // r = sqrt(x^3 + ax + b) = (x^3 + ax + b) ^ ((P + 1) / 4) (mod P)
140
141 // n = P + 1
142 MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&n, &grp->P, 1));
143
144 // n = (P + 1) / 4
145 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&n, 2));
146
147 // r ^ ((P + 1) / 4) (mod p)
148 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&r, &r, &n, &grp->P, NULL));
149
150 // Select solution that has the correct "sign" (equals odd/even solution in finite group)
151 if ((input[0] == 0x03) != mbedtls_mpi_get_bit(&r, 0)) {
152 // r = p - r
153 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&r, &grp->P, &r));
154 }
155
156 // y => output
157 ret = mbedtls_mpi_write_binary(&r, output + 1 + plen, plen);
158
159 cleanup:
160 mbedtls_mpi_free(&r);
161 mbedtls_mpi_free(&x);
162 mbedtls_mpi_free(&n);
163
164 return (ret);
165 }
166
167 #endif
168
169 #ifdef TINYCRYPT
170 /* Declaration of function from TinyCrypt ecc.c */
171 uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false,
172 unsigned int cond);
173
174 /* From uECC project embedded in TinyCrypt - ecc.c
175 BSD-2-Clause license */
uECC_vli_add(uECC_word_t * result,const uECC_word_t * left,const uECC_word_t * right,wordcount_t num_words)176 static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
177 const uECC_word_t *right, wordcount_t num_words)
178 {
179 uECC_word_t carry = 0U;
180 wordcount_t i;
181 for (i = 0; i < num_words; ++i) {
182 uECC_word_t sum = left[i] + right[i] + carry;
183 uECC_word_t val = (sum < left[i]);
184 carry = cond_set(val, carry, (sum != left[i]));
185 result[i] = sum;
186 }
187 return carry;
188 }
189
190 /* From uECC project; curve-specific.inc */
191 /* Calculates EC square root of bignum (Very Large Integer) based on curve */
mod_sqrt_default(uECC_word_t * a,uECC_Curve curve)192 static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve)
193 {
194 bitcount_t i;
195 uECC_word_t p1[NUM_ECC_WORDS] = { 1 };
196 uECC_word_t l_result[NUM_ECC_WORDS] = { 1 };
197 wordcount_t num_words = curve->num_words;
198
199 /* When curve->p == 3 (mod 4), we can compute
200 sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
201 uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
202 for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
203 uECC_vli_modMult_fast(l_result, l_result, l_result, curve);
204 if (uECC_vli_testBit(p1, i)) {
205 uECC_vli_modMult_fast(l_result, l_result, a, curve);
206 }
207 }
208 uECC_vli_set(a, l_result, num_words);
209 }
210
211 /**
212 * @brief Decompresses an elliptic curve point.
213 *
214 *
215 * @param compressed the compressed key
216 * @param public_key the uncopressed key
217 * @param curve elliptic curve group point
218 */
219 /* From uECC project
220 BSD-2-Clause license */
uECC_decompress(const uint8_t * compressed,uint8_t * public_key,uECC_Curve curve)221 static inline void uECC_decompress(const uint8_t *compressed,
222 uint8_t *public_key, uECC_Curve curve)
223 {
224 uECC_word_t point[NUM_ECC_WORDS * 2];
225
226 uECC_word_t *y = point + curve->num_words;
227
228 uECC_vli_bytesToNative(point, compressed, curve->num_bytes);
229
230 curve->x_side(y, point, curve);
231 mod_sqrt_default(y, curve);
232
233 if ((y[0] & 0x01) != (compressed[0] == 0x03)) {
234 uECC_vli_sub(y, curve->p, y, curve->num_words);
235 }
236
237 uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
238 uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes,
239 y);
240 }
241 #endif
242
243 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
244 static bool
aead_mock_args_match_predefined(struct edhoc_mock_aead_in_out * predefined,const uint8_t * key,const uint16_t key_len,uint8_t * nonce,const uint16_t nonce_len,const uint8_t * aad,const uint16_t aad_len,uint8_t * tag,const uint16_t tag_len)245 aead_mock_args_match_predefined(struct edhoc_mock_aead_in_out *predefined,
246 const uint8_t *key, const uint16_t key_len,
247 uint8_t *nonce, const uint16_t nonce_len,
248 const uint8_t *aad, const uint16_t aad_len,
249 uint8_t *tag, const uint16_t tag_len)
250 {
251 return array_equals(&predefined->key,
252 &(struct byte_array){ .ptr = (void *)key,
253 .len = key_len }) &&
254 array_equals(&predefined->nonce,
255 &(struct byte_array){ .ptr = nonce,
256 .len = nonce_len }) &&
257 array_equals(&predefined->aad,
258 &(struct byte_array){ .ptr = (void *)aad,
259 .len = aad_len }) &&
260 array_equals(&predefined->tag,
261 &(struct byte_array){ .ptr = tag, .len = tag_len });
262 }
263 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
264
aead(enum aes_operation op,const struct byte_array * in,const struct byte_array * key,struct byte_array * nonce,const struct byte_array * aad,struct byte_array * out,struct byte_array * tag)265 enum err WEAK aead(enum aes_operation op, const struct byte_array *in,
266 const struct byte_array *key, struct byte_array *nonce,
267 const struct byte_array *aad, struct byte_array *out,
268 struct byte_array *tag)
269 {
270 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
271 for (uint32_t i = 0; i < edhoc_crypto_mock_cb.aead_in_out_count; i++) {
272 struct edhoc_mock_aead_in_out *predefined_in_out =
273 edhoc_crypto_mock_cb.aead_in_out + i;
274 if (aead_mock_args_match_predefined(
275 predefined_in_out, key->ptr, key->len, nonce->ptr,
276 nonce->len, aad->ptr, aad->len, tag->ptr,
277 tag->len)) {
278 memcpy(out->ptr, predefined_in_out->out.ptr,
279 predefined_in_out->out.len);
280 return ok;
281 }
282 }
283 // if no mocked data has been found - continue with normal aead
284 #endif
285
286 #if defined(TINYCRYPT)
287 struct tc_ccm_mode_struct c;
288 struct tc_aes_key_sched_struct sched;
289 TRY_EXPECT(tc_aes128_set_encrypt_key(&sched, key->ptr), 1);
290 TRY_EXPECT(tc_ccm_config(&c, &sched, nonce->ptr, nonce->len, tag->len),
291 1);
292
293 if (op == DECRYPT) {
294 TRY_EXPECT(tc_ccm_decryption_verification(out->ptr, out->len,
295 aad->ptr, aad->len,
296 in->ptr, in->len, &c),
297 1);
298
299 } else {
300 TRY_EXPECT(tc_ccm_generation_encryption(
301 out->ptr, (out->len + tag->len), aad->ptr,
302 aad->len, in->ptr, in->len, &c),
303 1);
304 memcpy(tag->ptr, out->ptr + out->len, tag->len);
305 }
306 #elif defined(MBEDTLS)
307 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
308
309 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
310 unexpected_result_from_ext_lib);
311
312 psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(
313 PSA_ALG_CCM, (uint32_t)tag->len);
314
315 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
316 psa_set_key_usage_flags(&attr,
317 PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT);
318 psa_set_key_algorithm(&attr, alg);
319 psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
320 psa_set_key_bits(&attr, ((size_t)key->len << 3));
321 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
322 TRY_EXPECT_PSA(psa_import_key(&attr, key->ptr, key->len, &key_id),
323 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
324
325 if (op == DECRYPT) {
326 size_t out_len_re = 0;
327 TRY_EXPECT_PSA(
328 psa_aead_decrypt(key_id, alg, nonce->ptr, nonce->len,
329 aad->ptr, aad->len, in->ptr, in->len,
330 out->ptr, out->len, &out_len_re),
331 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
332 } else {
333 size_t out_len_re;
334 TRY_EXPECT_PSA(
335 psa_aead_encrypt(key_id, alg, nonce->ptr, nonce->len,
336 aad->ptr, aad->len, in->ptr, in->len,
337 out->ptr, (size_t)(in->len + tag->len),
338 &out_len_re),
339 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
340 memcpy(tag->ptr, out->ptr + out_len_re - tag->len, tag->len);
341 }
342 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
343
344 #endif
345 return ok;
346 }
347
348 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
349 static bool
sign_mock_args_match_predefined(struct edhoc_mock_sign_in_out * predefined,const uint8_t * sk,const size_t sk_len,const uint8_t * pk,const size_t pk_len,const uint8_t * msg,const size_t msg_len)350 sign_mock_args_match_predefined(struct edhoc_mock_sign_in_out *predefined,
351 const uint8_t *sk, const size_t sk_len,
352 const uint8_t *pk, const size_t pk_len,
353 const uint8_t *msg, const size_t msg_len)
354 {
355 return array_equals(&predefined->sk,
356 &(struct byte_array){ .len = sk_len,
357 .ptr = (void *)sk }) &&
358 array_equals(&predefined->pk,
359 &(struct byte_array){ .len = pk_len,
360 .ptr = (void *)pk }) &&
361 array_equals(&predefined->msg,
362 &(struct byte_array){ .len = msg_len,
363 .ptr = (void *)msg });
364 }
365 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
366
sign(enum sign_alg alg,const struct byte_array * sk,const struct byte_array * pk,const struct byte_array * msg,uint8_t * out)367 enum err WEAK sign(enum sign_alg alg, const struct byte_array *sk,
368 const struct byte_array *pk, const struct byte_array *msg,
369 uint8_t *out)
370 {
371 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
372 for (uint32_t i = 0; i < edhoc_crypto_mock_cb.sign_in_out_count; i++) {
373 struct edhoc_mock_sign_in_out *predefined_in_out =
374 edhoc_crypto_mock_cb.sign_in_out + i;
375 if (sign_mock_args_match_predefined(predefined_in_out, sk->ptr,
376 sk->len, pk->ptr, PK_SIZE,
377 msg->ptr, msg->len)) {
378 memcpy(out, predefined_in_out->out.ptr,
379 predefined_in_out->out.len);
380 return ok;
381 }
382 }
383 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
384
385 if (alg == EdDSA) {
386 #if defined(COMPACT25519)
387 edsign_sign(out, pk->ptr, sk->ptr, msg->ptr, msg->len);
388 return ok;
389 #endif
390 } else if (alg == ES256) {
391 #if defined(TINYCRYPT)
392
393 uECC_Curve p256 = uECC_secp256r1();
394 struct tc_sha256_state_struct ctx_sha256;
395 uint8_t hash[NUM_ECC_BYTES];
396
397 TRY_EXPECT(tc_sha256_init(&ctx_sha256), 1);
398 TRY_EXPECT(tc_sha256_update(&ctx_sha256, msg->ptr, msg->len),
399 1);
400 TRY_EXPECT(tc_sha256_final(hash, &ctx_sha256), 1);
401
402 TRY_EXPECT(uECC_sign(sk->ptr, hash, NUM_ECC_BYTES, out, p256),
403 TC_CRYPTO_SUCCESS);
404
405 return ok;
406
407 #elif defined(MBEDTLS)
408 psa_algorithm_t psa_alg;
409 size_t bits;
410 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
411
412 psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
413 bits = PSA_BYTES_TO_BITS((size_t)sk->len);
414
415 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
416 unexpected_result_from_ext_lib);
417
418 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
419 psa_set_key_usage_flags(&attributes,
420 PSA_KEY_USAGE_VERIFY_MESSAGE |
421 PSA_KEY_USAGE_VERIFY_HASH |
422 PSA_KEY_USAGE_SIGN_MESSAGE |
423 PSA_KEY_USAGE_SIGN_HASH);
424 psa_set_key_algorithm(&attributes, psa_alg);
425 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
426 PSA_ECC_FAMILY_SECP_R1));
427 psa_set_key_bits(&attributes, bits);
428 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
429
430 TRY_EXPECT_PSA(
431 psa_import_key(&attributes, sk->ptr, sk->len, &key_id),
432 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
433
434 size_t signature_length;
435 TRY_EXPECT_PSA(psa_sign_message(key_id, psa_alg, msg->ptr,
436 msg->len, out, SIGNATURE_SIZE,
437 &signature_length),
438 PSA_SUCCESS, key_id,
439 unexpected_result_from_ext_lib);
440
441 TRY_EXPECT_PSA(signature_length, SIGNATURE_SIZE, key_id,
442 sign_failed);
443 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
444 return ok;
445 #endif
446 }
447 return unsupported_ecdh_curve;
448 }
449
verify(enum sign_alg alg,const struct byte_array * pk,struct const_byte_array * msg,struct const_byte_array * sgn,bool * result)450 enum err WEAK verify(enum sign_alg alg, const struct byte_array *pk,
451 struct const_byte_array *msg, struct const_byte_array *sgn,
452 bool *result)
453 {
454 if (alg == EdDSA) {
455 #ifdef COMPACT25519
456 int verified =
457 edsign_verify(sgn->ptr, pk->ptr, msg->ptr, msg->len);
458 if (verified) {
459 *result = true;
460 } else {
461 *result = false;
462 }
463 return ok;
464 #endif
465 }
466 if (alg == ES256) {
467 #if defined(MBEDTLS)
468 psa_status_t status;
469 psa_algorithm_t psa_alg;
470 size_t bits;
471 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
472
473 psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
474 bits = PSA_BYTES_TO_BITS(P_256_PRIV_KEY_SIZE);
475
476 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
477 unexpected_result_from_ext_lib);
478
479 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
480
481 psa_set_key_usage_flags(&attributes,
482 PSA_KEY_USAGE_VERIFY_MESSAGE |
483 PSA_KEY_USAGE_VERIFY_HASH);
484 psa_set_key_algorithm(&attributes, psa_alg);
485 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(
486 PSA_ECC_FAMILY_SECP_R1));
487 psa_set_key_bits(&attributes, bits);
488 TRY_EXPECT_PSA(
489 psa_import_key(&attributes, pk->ptr, pk->len, &key_id),
490 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
491
492 status = psa_verify_message(key_id, psa_alg, msg->ptr, msg->len,
493 sgn->ptr, sgn->len);
494 if (PSA_SUCCESS == status) {
495 *result = true;
496 } else {
497 *result = false;
498 }
499 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
500 return ok;
501 #elif defined(TINYCRYPT)
502 uECC_Curve p256 = uECC_secp256r1();
503 struct tc_sha256_state_struct ctx_sha256;
504 uint8_t hash[NUM_ECC_BYTES];
505 TRY_EXPECT(tc_sha256_init(&ctx_sha256), 1);
506 TRY_EXPECT(tc_sha256_update(&ctx_sha256, msg->ptr, msg->len),
507 1);
508 TRY_EXPECT(tc_sha256_final(hash, &ctx_sha256), 1);
509 uint8_t *pk_ptr = pk->ptr;
510 if ((P_256_PUB_KEY_UNCOMPRESSED_SIZE == pk->len) &&
511 (0x04 == *pk->ptr)) {
512 pk_ptr++;
513 }
514 TRY_EXPECT(uECC_verify(pk_ptr, hash, NUM_ECC_BYTES, sgn->ptr,
515 p256),
516 1);
517 *result = true;
518 return ok;
519 #endif
520 }
521 return crypto_operation_not_implemented;
522 }
523
hkdf_extract(enum hash_alg alg,const struct byte_array * salt,struct byte_array * ikm,uint8_t * out)524 enum err WEAK hkdf_extract(enum hash_alg alg, const struct byte_array *salt,
525 struct byte_array *ikm, uint8_t *out)
526 {
527 /*"Note that [RFC5869] specifies that if the salt is not provided,
528 it is set to a string of zeros. For implementation purposes,
529 not providing the salt is the same as setting the salt to the empty byte
530 string. OSCORE sets the salt default value to empty byte string, which
531 is converted to a string of zeroes (see Section 2.2 of [RFC5869])".*/
532
533 /*all currently prosed suites use hmac-sha256*/
534 if (alg != SHA_256) {
535 return crypto_operation_not_implemented;
536 }
537 #ifdef TINYCRYPT
538 struct tc_hmac_state_struct h;
539 memset(&h, 0x00, sizeof(h));
540 if (salt->ptr == NULL || salt->len == 0) {
541 uint8_t zero_salt[32] = { 0 };
542 TRY_EXPECT(tc_hmac_set_key(&h, zero_salt, 32), 1);
543 } else {
544 TRY_EXPECT(tc_hmac_set_key(&h, salt->ptr, salt->len), 1);
545 }
546 TRY_EXPECT(tc_hmac_init(&h), 1);
547 TRY_EXPECT(tc_hmac_update(&h, ikm->ptr, ikm->len), 1);
548 TRY_EXPECT(tc_hmac_final(out, TC_SHA256_DIGEST_SIZE, &h), 1);
549 #endif
550 #ifdef MBEDTLS
551 psa_algorithm_t psa_alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
552 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
553 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
554
555 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
556 unexpected_result_from_ext_lib);
557
558 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
559 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
560 psa_set_key_algorithm(&attr, psa_alg);
561 psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
562
563 if (salt->ptr && salt->len) {
564 TRY_EXPECT_PSA(
565 psa_import_key(&attr, salt->ptr, salt->len, &key_id),
566 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
567 } else {
568 uint8_t zero_salt[32] = { 0 };
569
570 TRY_EXPECT_PSA(psa_import_key(&attr, zero_salt, 32, &key_id),
571 PSA_SUCCESS, key_id,
572 unexpected_result_from_ext_lib);
573 }
574 size_t out_len;
575 TRY_EXPECT_PSA(psa_mac_compute(key_id, psa_alg, ikm->ptr, ikm->len, out,
576 32, &out_len),
577 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
578
579 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
580 #endif
581 return ok;
582 }
583
hkdf_expand(enum hash_alg alg,const struct byte_array * prk,const struct byte_array * info,struct byte_array * out)584 enum err WEAK hkdf_expand(enum hash_alg alg, const struct byte_array *prk,
585 const struct byte_array *info, struct byte_array *out)
586 {
587 if (alg != SHA_256) {
588 return crypto_operation_not_implemented;
589 }
590 /* "N = ceil(L/HashLen)" */
591 uint32_t iterations = (out->len + 31) / 32;
592 /* "L length of output keying material in octets (<= 255*HashLen)"*/
593 if (iterations > 255) {
594 return hkdf_failed;
595 }
596
597 #ifdef TINYCRYPT
598 uint8_t t[32] = { 0 };
599 struct tc_hmac_state_struct h;
600 for (uint8_t i = 1; i <= iterations; i++) {
601 memset(&h, 0x00, sizeof(h));
602 TRY_EXPECT(tc_hmac_set_key(&h, prk->ptr, prk->len), 1);
603 tc_hmac_init(&h);
604 if (i > 1) {
605 TRY_EXPECT(tc_hmac_update(&h, t, 32), 1);
606 }
607 TRY_EXPECT(tc_hmac_update(&h, info->ptr, info->len), 1);
608 TRY_EXPECT(tc_hmac_update(&h, &i, 1), 1);
609 TRY_EXPECT(tc_hmac_final(t, TC_SHA256_DIGEST_SIZE, &h), 1);
610 if (out->len < i * 32) {
611 memcpy(&out->ptr[(i - 1) * 32], t, out->len % 32);
612 } else {
613 memcpy(&out->ptr[(i - 1) * 32], t, 32);
614 }
615 }
616 #endif
617 #ifdef MBEDTLS
618 psa_status_t status;
619 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
620 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
621 PRINTF("key_id: %d\n", key_id);
622
623 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
624 unexpected_result_from_ext_lib);
625 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
626 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
627 psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
628 psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
629
630 PRINT_ARRAY("PRK:", prk->ptr, prk->len);
631 TRY_EXPECT_PSA(psa_import_key(&attr, prk->ptr, prk->len, &key_id),
632 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
633
634 size_t combo_len = (32 + (size_t)info->len + 1);
635
636 TRY_EXPECT_PSA(check_buffer_size(INFO_MAX_SIZE + 32 + 1,
637 (uint32_t)combo_len),
638 ok, key_id, unexpected_result_from_ext_lib);
639
640 uint8_t combo[INFO_MAX_SIZE + 32 + 1];
641 uint8_t tmp_out[32];
642 memset(tmp_out, 0, 32);
643 memcpy(combo + 32, info->ptr, info->len);
644 size_t offset = 32;
645 for (uint32_t i = 1; i <= iterations; i++) {
646 memcpy(combo, tmp_out, 32);
647 combo[combo_len - 1] = (uint8_t)i;
648 size_t tmp_out_len;
649 status = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
650 combo + offset, combo_len - offset,
651 tmp_out, 32, &tmp_out_len);
652 TRY_EXPECT_PSA(status, PSA_SUCCESS, key_id,
653 unexpected_result_from_ext_lib);
654 offset = 0;
655 uint8_t *dest = out->ptr + ((i - 1) << 5);
656 if (out->len < (uint32_t)(i << 5)) {
657 memcpy(dest, tmp_out, out->len & 31);
658 } else {
659 memcpy(dest, tmp_out, 32);
660 }
661 }
662 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
663 #endif
664 return ok;
665 }
666
hkdf_sha_256(struct byte_array * master_secret,struct byte_array * master_salt,struct byte_array * info,struct byte_array * out)667 enum err WEAK hkdf_sha_256(struct byte_array *master_secret,
668 struct byte_array *master_salt,
669 struct byte_array *info, struct byte_array *out)
670 {
671 BYTE_ARRAY_NEW(prk, HASH_SIZE, HASH_SIZE);
672 TRY(hkdf_extract(SHA_256, master_salt, master_secret, prk.ptr));
673 TRY(hkdf_expand(SHA_256, &prk, info, out));
674 return ok;
675 }
676
shared_secret_derive(enum ecdh_alg alg,const struct byte_array * sk,const struct byte_array * pk,uint8_t * shared_secret)677 enum err WEAK shared_secret_derive(enum ecdh_alg alg,
678 const struct byte_array *sk,
679 const struct byte_array *pk,
680 uint8_t *shared_secret)
681 {
682 if (alg == X25519) {
683 #ifdef COMPACT25519
684 uint8_t e[F25519_SIZE];
685 f25519_copy(e, sk->ptr);
686 c25519_prepare(e);
687 c25519_smult(shared_secret, pk->ptr, e);
688 return ok;
689 #endif
690 }
691 if (alg == P256) {
692 #if defined(TINYCRYPT)
693 uECC_Curve p256 = uECC_secp256r1();
694 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
695
696 uECC_decompress(pk->ptr, pk_decompressed, p256);
697
698 PRINT_ARRAY("pk_decompressed", pk_decompressed,
699 2 * P_256_PUB_KEY_X_CORD_SIZE);
700
701 TRY_EXPECT(uECC_shared_secret(pk_decompressed, sk->ptr,
702 shared_secret, p256),
703 1);
704
705 return ok;
706 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
707 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
708 psa_algorithm_t psa_alg;
709 size_t bits;
710 psa_status_t result = ok;
711
712 psa_alg = PSA_ALG_ECDH;
713 bits = PSA_BYTES_TO_BITS(sk->len);
714
715 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
716 unexpected_result_from_ext_lib);
717
718 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
719 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
720 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
721 psa_set_key_algorithm(&attr, psa_alg);
722 psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(
723 PSA_ECC_FAMILY_SECP_R1));
724
725 TRY_EXPECT_PSA(psa_import_key(&attr, sk->ptr, (size_t)sk->len,
726 &key_id),
727 PSA_SUCCESS, key_id,
728 unexpected_result_from_ext_lib);
729 psa_key_type_t type = psa_get_key_type(&attr);
730 size_t shared_size =
731 PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits);
732
733 size_t shared_secret_len = 0;
734
735 size_t pk_decompressed_len;
736 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
737
738 mbedtls_pk_context ctx_verify = { 0 };
739 mbedtls_pk_init(&ctx_verify);
740 if (PSA_SUCCESS !=
741 mbedtls_pk_setup(&ctx_verify, mbedtls_pk_info_from_type(
742 MBEDTLS_PK_ECKEY))) {
743 result = unexpected_result_from_ext_lib;
744 goto cleanup;
745 }
746 if (PSA_SUCCESS !=
747 mbedtls_ecp_group_load(&mbedtls_pk_ec(ctx_verify)->grp,
748 MBEDTLS_ECP_DP_SECP256R1)) {
749 result = unexpected_result_from_ext_lib;
750 goto cleanup;
751 }
752 if (PSA_SUCCESS !=
753 mbedtls_ecp_decompress(&mbedtls_pk_ec(ctx_verify)->grp,
754 pk->ptr, pk->len, pk_decompressed,
755 &pk_decompressed_len,
756 sizeof(pk_decompressed))) {
757 result = unexpected_result_from_ext_lib;
758 goto cleanup;
759 }
760
761 PRINT_ARRAY("pk_decompressed", pk_decompressed,
762 (uint32_t)pk_decompressed_len);
763
764 if (PSA_SUCCESS !=
765 psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk_decompressed,
766 pk_decompressed_len, shared_secret,
767 shared_size, &shared_secret_len)) {
768 result = unexpected_result_from_ext_lib;
769 goto cleanup;
770 }
771 cleanup:
772 if (PSA_KEY_HANDLE_INIT != key_id) {
773 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
774 }
775 mbedtls_pk_free(&ctx_verify);
776 return result;
777 #endif
778 }
779 return crypto_operation_not_implemented;
780 }
781
ephemeral_dh_key_gen(enum ecdh_alg alg,uint32_t seed,struct byte_array * sk,struct byte_array * pk)782 enum err WEAK ephemeral_dh_key_gen(enum ecdh_alg alg, uint32_t seed,
783 struct byte_array *sk, struct byte_array *pk)
784 {
785 if (alg == X25519) {
786 #ifdef COMPACT25519
787 uint8_t extended_seed[32];
788 #if defined(TINYCRYPT)
789 struct tc_sha256_state_struct s;
790 TRY_EXPECT(tc_sha256_init(&s), 1);
791 TRY_EXPECT(tc_sha256_update(&s, (uint8_t *)&seed, sizeof(seed)),
792 1);
793 TRY_EXPECT(tc_sha256_final(extended_seed, &s),
794 TC_CRYPTO_SUCCESS);
795 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
796 size_t length;
797 TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, (uint8_t *)&seed,
798 sizeof(seed), sk->ptr, HASH_SIZE,
799 &length),
800 0);
801 if (length != 32) {
802 return sha_failed;
803 }
804 #endif
805 compact_x25519_keygen(sk->ptr, pk->ptr, extended_seed);
806 pk->len = X25519_KEY_SIZE;
807 sk->len = X25519_KEY_SIZE;
808 #endif
809 } else if (alg == P256) {
810 #if defined(TINYCRYPT)
811 if (P_256_PUB_KEY_X_CORD_SIZE > pk->len) {
812 return buffer_to_small;
813 }
814 uECC_Curve p256 = uECC_secp256r1();
815 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
816 TRY_EXPECT(uECC_make_key(pk_decompressed, sk->ptr, p256),
817 TC_CRYPTO_SUCCESS);
818 TRY(_memcpy_s(pk->ptr, P_256_PUB_KEY_X_CORD_SIZE,
819 pk_decompressed, P_256_PUB_KEY_X_CORD_SIZE));
820 pk->len = P_256_PUB_KEY_X_CORD_SIZE;
821 return ok;
822 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
823 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
824 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
825 psa_algorithm_t psa_alg = PSA_ALG_ECDH;
826 uint8_t priv_key_size = P_256_PRIV_KEY_SIZE;
827 size_t bits = PSA_BYTES_TO_BITS((size_t)priv_key_size);
828 size_t pub_key_uncompressed_size =
829 P_256_PUB_KEY_UNCOMPRESSED_SIZE;
830 uint8_t pub_key_uncompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
831
832 if (P_256_PUB_KEY_X_CORD_SIZE > pk->len) {
833 return buffer_to_small;
834 }
835 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
836 unexpected_result_from_ext_lib);
837
838 psa_set_key_usage_flags(&attributes,
839 PSA_KEY_USAGE_EXPORT |
840 PSA_KEY_USAGE_DERIVE |
841 PSA_KEY_USAGE_SIGN_MESSAGE |
842 PSA_KEY_USAGE_SIGN_HASH);
843 psa_set_key_algorithm(&attributes, psa_alg);
844 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
845 PSA_ECC_FAMILY_SECP_R1));
846 psa_set_key_bits(&attributes, bits);
847
848 TRY_EXPECT_PSA(psa_generate_key(&attributes, &key_id),
849 PSA_SUCCESS, key_id,
850 unexpected_result_from_ext_lib);
851
852 size_t key_len = 0;
853 size_t public_key_len = 0;
854
855 TRY_EXPECT_PSA(psa_export_key(key_id, sk->ptr, priv_key_size,
856 &key_len),
857 PSA_SUCCESS, key_id,
858 unexpected_result_from_ext_lib);
859 TRY_EXPECT_PSA(
860 psa_export_public_key(key_id, pub_key_uncompressed,
861 pub_key_uncompressed_size,
862 &public_key_len),
863 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
864 TRY_EXPECT_PSA(public_key_len, P_256_PUB_KEY_UNCOMPRESSED_SIZE,
865 key_id, unexpected_result_from_ext_lib);
866 /* Prepare output format - only x parameter */
867 memcpy(pk->ptr, (pub_key_uncompressed + 1),
868 P_256_PUB_KEY_X_CORD_SIZE);
869 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
870 pk->len = P_256_PUB_KEY_X_CORD_SIZE;
871 #endif
872 } else {
873 return unsupported_ecdh_curve;
874 }
875 return ok;
876 }
877
hash(enum hash_alg alg,const struct byte_array * in,struct byte_array * out)878 enum err WEAK hash(enum hash_alg alg, const struct byte_array *in,
879 struct byte_array *out)
880 {
881 if (alg == SHA_256) {
882 #ifdef TINYCRYPT
883 struct tc_sha256_state_struct s;
884 TRY_EXPECT(tc_sha256_init(&s), 1);
885 TRY_EXPECT(tc_sha256_update(&s, in->ptr, in->len), 1);
886 TRY_EXPECT(tc_sha256_final(out->ptr, &s), 1);
887 out->len = HASH_SIZE;
888 return ok;
889 #endif
890 #ifdef MBEDTLS
891 size_t length;
892 TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, in->ptr, in->len,
893 out->ptr, HASH_SIZE, &length),
894 PSA_SUCCESS);
895 if (length != HASH_SIZE) {
896 return sha_failed;
897 }
898 out->len = HASH_SIZE;
899 PRINT_ARRAY("hash", out->ptr, out->len);
900 return ok;
901 #endif
902 }
903
904 return crypto_operation_not_implemented;
905 }
906