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
23 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
24 struct edhoc_mock_cb edhoc_crypto_mock_cb;
25 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
26
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, unsigned int cond);
172
173 /* From uECC project embedded in TinyCrypt - ecc.c
174 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)175 static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
176 const uECC_word_t *right, wordcount_t num_words)
177 {
178 uECC_word_t carry = 0U;
179 wordcount_t i;
180 for (i = 0; i < num_words; ++i) {
181 uECC_word_t sum = left[i] + right[i] + carry;
182 uECC_word_t val = (sum < left[i]);
183 carry = cond_set(val, carry, (sum != left[i]));
184 result[i] = sum;
185 }
186 return carry;
187 }
188
189 /* From uECC project; curve-specific.inc */
190 /* Calculates EC square root of bignum (Very Large Integer) based on curve */
mod_sqrt_default(uECC_word_t * a,uECC_Curve curve)191 static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
192 bitcount_t i;
193 uECC_word_t p1[NUM_ECC_WORDS] = {1};
194 uECC_word_t l_result[NUM_ECC_WORDS] = {1};
195 wordcount_t num_words = curve->num_words;
196
197 /* When curve->p == 3 (mod 4), we can compute
198 sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
199 uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
200 for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
201 uECC_vli_modMult_fast(l_result, l_result, l_result, curve);
202 if (uECC_vli_testBit(p1, i)) {
203 uECC_vli_modMult_fast(l_result, l_result, a, curve);
204 }
205 }
206 uECC_vli_set(a, l_result, num_words);
207 }
208
209 /**
210 * @brief Decompresses an elliptic curve point.
211 *
212 *
213 * @param compressed the compressed key
214 * @param public_key the uncopressed key
215 * @param curve elliptic curve group point
216 */
217 /* From uECC project
218 BSD-2-Clause license */
uECC_decompress(const uint8_t * compressed,uint8_t * public_key,uECC_Curve curve)219 static inline void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
220
221 uECC_word_t point[NUM_ECC_WORDS * 2];
222
223 uECC_word_t *y = point + curve->num_words;
224
225 uECC_vli_bytesToNative(point, compressed, curve->num_bytes);
226
227 curve->x_side(y, point, curve);
228 mod_sqrt_default(y, curve);
229
230 if ((y[0] & 0x01) != (compressed[0] == 0x03)) {
231 uECC_vli_sub(y, curve->p, y, curve->num_words);
232 }
233
234 uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
235 uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
236 }
237 #endif
238
239 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
240 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)241 aead_mock_args_match_predefined(struct edhoc_mock_aead_in_out *predefined,
242 const uint8_t *key, const uint16_t key_len,
243 uint8_t *nonce, const uint16_t nonce_len,
244 const uint8_t *aad, const uint16_t aad_len,
245 uint8_t *tag, const uint16_t tag_len)
246 {
247 return array_equals(&predefined->key,
248 &(struct byte_array){ .ptr = (void *)key,
249 .len = key_len }) &&
250 array_equals(&predefined->nonce,
251 &(struct byte_array){ .ptr = nonce,
252 .len = nonce_len }) &&
253 array_equals(&predefined->aad,
254 &(struct byte_array){ .ptr = (void *)aad,
255 .len = aad_len }) &&
256 array_equals(&predefined->tag,
257 &(struct byte_array){ .ptr = tag, .len = tag_len });
258 }
259 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
260
aead(enum aes_operation op,const uint8_t * in,const uint32_t in_len,const uint8_t * key,const uint32_t key_len,uint8_t * nonce,const uint32_t nonce_len,const uint8_t * aad,const uint32_t aad_len,uint8_t * out,const uint32_t out_len,uint8_t * tag,const uint32_t tag_len)261 enum err WEAK aead(enum aes_operation op, const uint8_t *in,
262 const uint32_t in_len, const uint8_t *key,
263 const uint32_t key_len, uint8_t *nonce,
264 const uint32_t nonce_len, const uint8_t *aad,
265 const uint32_t aad_len, uint8_t *out, const uint32_t out_len,
266 uint8_t *tag, const uint32_t tag_len)
267 {
268 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
269 for (uint32_t i = 0; i < edhoc_crypto_mock_cb.aead_in_out_count; i++) {
270 struct edhoc_mock_aead_in_out *predefined_in_out =
271 edhoc_crypto_mock_cb.aead_in_out + i;
272 if (aead_mock_args_match_predefined(
273 predefined_in_out, key, key_len, nonce, nonce_len,
274 aad, aad_len, tag, tag_len)) {
275 memcpy(out, predefined_in_out->out.ptr,
276 predefined_in_out->out.len);
277 return ok;
278 }
279 }
280 // if no mocked data has been found - continue with normal aead
281 #endif
282
283 #if defined(TINYCRYPT)
284 struct tc_ccm_mode_struct c;
285 struct tc_aes_key_sched_struct sched;
286 TRY_EXPECT(tc_aes128_set_encrypt_key(&sched, key), 1);
287 TRY_EXPECT(tc_ccm_config(&c, &sched, nonce, nonce_len, tag_len), 1);
288
289 if (op == DECRYPT) {
290 TRY_EXPECT(tc_ccm_decryption_verification(
291 out, out_len, aad, aad_len, in, in_len, &c),
292 1);
293
294 } else {
295 TRY_EXPECT(tc_ccm_generation_encryption(
296 out, (out_len + tag_len), aad, aad_len, in,
297 in_len, &c),
298 1);
299 memcpy(tag, out + out_len, tag_len);
300 }
301 #elif defined(MBEDTLS)
302 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
303
304 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
305 unexpected_result_from_ext_lib);
306
307 psa_algorithm_t alg =
308 PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, (uint32_t)tag_len);
309
310 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
311 psa_set_key_usage_flags(&attr,
312 PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT);
313 psa_set_key_algorithm(&attr, alg);
314 psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
315 psa_set_key_bits(&attr, ((size_t)key_len << 3));
316 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
317 TRY_EXPECT_PSA(psa_import_key(&attr, key, key_len, &key_id),
318 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
319
320 if (op == DECRYPT) {
321 size_t out_len_re = 0;
322 TRY_EXPECT_PSA(psa_aead_decrypt(key_id, alg, nonce, nonce_len,
323 aad, aad_len, in, in_len, out,
324 out_len, &out_len_re),
325 PSA_SUCCESS, key_id,
326 unexpected_result_from_ext_lib);
327 } else {
328 size_t out_len_re;
329 TRY_EXPECT_PSA(psa_aead_encrypt(key_id, alg, nonce, nonce_len,
330 aad, aad_len, in, in_len, out,
331 (size_t)(in_len + tag_len),
332 &out_len_re),
333 PSA_SUCCESS, key_id,
334 unexpected_result_from_ext_lib);
335 memcpy(tag, out + out_len_re - tag_len, tag_len);
336 }
337 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
338
339 #endif
340 return ok;
341 }
342
343 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
344 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)345 sign_mock_args_match_predefined(struct edhoc_mock_sign_in_out *predefined,
346 const uint8_t *sk, const size_t sk_len,
347 const uint8_t *pk, const size_t pk_len,
348 const uint8_t *msg, const size_t msg_len)
349 {
350 return array_equals(&predefined->sk,
351 &(struct byte_array){ .len = sk_len,
352 .ptr = (void *)sk }) &&
353 array_equals(&predefined->pk,
354 &(struct byte_array){ .len = pk_len,
355 .ptr = (void *)pk }) &&
356 array_equals(&predefined->msg,
357 &(struct byte_array){ .len = msg_len,
358 .ptr = (void *)msg });
359 }
360 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
361
sign(enum sign_alg alg,const uint8_t * sk,const uint32_t sk_len,const uint8_t * pk,const uint8_t * msg,const uint32_t msg_len,uint8_t * out)362 enum err WEAK sign(enum sign_alg alg, const uint8_t *sk, const uint32_t sk_len,
363 const uint8_t *pk, const uint8_t *msg,
364 const uint32_t msg_len, uint8_t *out)
365 {
366 #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
367 for (uint32_t i = 0; i < edhoc_crypto_mock_cb.sign_in_out_count; i++) {
368 struct edhoc_mock_sign_in_out *predefined_in_out =
369 edhoc_crypto_mock_cb.sign_in_out + i;
370 if (sign_mock_args_match_predefined(predefined_in_out, sk,
371 sk_len, pk, PK_DEFAULT_SIZE,
372 msg, msg_len)) {
373 memcpy(out, predefined_in_out->out.ptr,
374 predefined_in_out->out.len);
375 return ok;
376 }
377 }
378 #endif // EDHOC_MOCK_CRYPTO_WRAPPER
379
380 if (alg == EdDSA) {
381 #if defined(COMPACT25519)
382 edsign_sign(out, pk, sk, msg, msg_len);
383 return ok;
384 #endif
385 } else if (alg == ES256) {
386 #if defined(TINYCRYPT)
387
388 uECC_Curve p256 = uECC_secp256r1();
389 struct tc_sha256_state_struct ctx_sha256;
390 uint8_t hash[NUM_ECC_BYTES];
391
392 TRY_EXPECT(tc_sha256_init(&ctx_sha256), 1);
393 TRY_EXPECT(tc_sha256_update(&ctx_sha256, msg, msg_len), 1);
394 TRY_EXPECT(tc_sha256_final(hash, &ctx_sha256), 1);
395
396 TRY_EXPECT(uECC_sign(sk, hash,
397 NUM_ECC_BYTES, out, p256), TC_CRYPTO_SUCCESS);
398
399 return ok;
400
401 #elif defined(MBEDTLS)
402 psa_algorithm_t psa_alg;
403 size_t bits;
404 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
405
406 psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
407 bits = PSA_BYTES_TO_BITS((size_t)sk_len);
408
409 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
410 unexpected_result_from_ext_lib);
411
412 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
413 psa_set_key_usage_flags(&attributes,
414 PSA_KEY_USAGE_VERIFY_MESSAGE |
415 PSA_KEY_USAGE_VERIFY_HASH |
416 PSA_KEY_USAGE_SIGN_MESSAGE |
417 PSA_KEY_USAGE_SIGN_HASH);
418 psa_set_key_algorithm(&attributes, psa_alg);
419 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
420 PSA_ECC_FAMILY_SECP_R1));
421 psa_set_key_bits(&attributes, bits);
422 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
423
424 TRY_EXPECT_PSA(psa_import_key(&attributes, sk, sk_len, &key_id),
425 PSA_SUCCESS, key_id,
426 unexpected_result_from_ext_lib);
427
428 size_t signature_length;
429 TRY_EXPECT_PSA(psa_sign_message(key_id, psa_alg, msg, msg_len,
430 out, SIGNATURE_DEFAULT_SIZE,
431 &signature_length),
432 PSA_SUCCESS, key_id,
433 unexpected_result_from_ext_lib);
434
435 TRY_EXPECT_PSA(signature_length, SIGNATURE_DEFAULT_SIZE, key_id,
436 sign_failed);
437 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
438 return ok;
439 #endif
440 }
441 return unsupported_ecdh_curve;
442 }
443
verify(enum sign_alg alg,const uint8_t * pk,const uint32_t pk_len,const uint8_t * msg,const uint32_t msg_len,const uint8_t * sgn,const uint32_t sgn_len,bool * result)444 enum err WEAK verify(enum sign_alg alg, const uint8_t *pk,
445 const uint32_t pk_len, const uint8_t *msg,
446 const uint32_t msg_len, const uint8_t *sgn,
447 const uint32_t sgn_len, bool *result)
448 {
449 if (alg == EdDSA) {
450 #ifdef COMPACT25519
451 int verified = edsign_verify(sgn, pk, msg, msg_len);
452 if (verified) {
453 *result = true;
454 } else {
455 *result = false;
456 }
457 return ok;
458 #endif
459 }
460 if (alg == ES256) {
461 #if defined(MBEDTLS)
462 psa_status_t status;
463 psa_algorithm_t psa_alg;
464 size_t bits;
465 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
466
467 psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
468 bits = PSA_BYTES_TO_BITS(P_256_PRIV_KEY_DEFAULT_SIZE);
469
470 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
471 unexpected_result_from_ext_lib);
472
473 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
474
475 psa_set_key_usage_flags(&attributes,
476 PSA_KEY_USAGE_VERIFY_MESSAGE |
477 PSA_KEY_USAGE_VERIFY_HASH);
478 psa_set_key_algorithm(&attributes, psa_alg);
479 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(
480 PSA_ECC_FAMILY_SECP_R1));
481 psa_set_key_bits(&attributes, bits);
482 TRY_EXPECT_PSA(psa_import_key(&attributes, pk, pk_len, &key_id),
483 PSA_SUCCESS, key_id,
484 unexpected_result_from_ext_lib);
485
486 status = psa_verify_message(key_id, psa_alg, msg, msg_len, sgn,
487 sgn_len);
488 if (PSA_SUCCESS == status) {
489 *result = true;
490 } else {
491 *result = false;
492 }
493 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
494 return ok;
495 #elif defined(TINYCRYPT)
496 uECC_Curve p256 = uECC_secp256r1();
497 struct tc_sha256_state_struct ctx_sha256;
498 uint8_t hash[NUM_ECC_BYTES];
499 TRY_EXPECT(tc_sha256_init(&ctx_sha256), 1);
500 TRY_EXPECT(tc_sha256_update(&ctx_sha256, msg, msg_len), 1);
501 TRY_EXPECT(tc_sha256_final(hash, &ctx_sha256), 1);
502 if ((P_256_PUB_KEY_UNCOMPRESSED_SIZE == pk_len) && (0x04 == *pk))
503 {
504 pk++;
505 }
506 TRY_EXPECT(uECC_verify(pk, hash, NUM_ECC_BYTES, sgn, p256), 1);
507 *result = true;
508 return ok;
509 #endif
510 }
511 return crypto_operation_not_implemented;
512 }
513
hkdf_extract(enum hash_alg alg,const uint8_t * salt,uint32_t salt_len,uint8_t * ikm,uint32_t ikm_len,uint8_t * out)514 enum err WEAK hkdf_extract(enum hash_alg alg, const uint8_t *salt,
515 uint32_t salt_len, uint8_t *ikm, uint32_t ikm_len,
516 uint8_t *out)
517 {
518 /*"Note that [RFC5869] specifies that if the salt is not provided,
519 it is set to a string of zeros. For implementation purposes,
520 not providing the salt is the same as setting the salt to the empty byte
521 string. OSCORE sets the salt default value to empty byte string, which
522 is converted to a string of zeroes (see Section 2.2 of [RFC5869])".*/
523
524 /*all currently prosed suites use hmac-sha256*/
525 if (alg != SHA_256) {
526 return crypto_operation_not_implemented;
527 }
528 #ifdef TINYCRYPT
529 struct tc_hmac_state_struct h;
530 memset(&h, 0x00, sizeof(h));
531 if (salt == NULL || salt_len == 0) {
532 uint8_t zero_salt[32] = { 0 };
533 TRY_EXPECT(tc_hmac_set_key(&h, zero_salt, 32), 1);
534 } else {
535 TRY_EXPECT(tc_hmac_set_key(&h, salt, salt_len), 1);
536 }
537 TRY_EXPECT(tc_hmac_init(&h), 1);
538 TRY_EXPECT(tc_hmac_update(&h, ikm, ikm_len), 1);
539 TRY_EXPECT(tc_hmac_final(out, TC_SHA256_DIGEST_SIZE, &h), 1);
540 #endif
541 #ifdef MBEDTLS
542 psa_algorithm_t psa_alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
543 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
544 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
545
546 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
547 unexpected_result_from_ext_lib);
548
549 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
550 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
551 psa_set_key_algorithm(&attr, psa_alg);
552 psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
553
554 if (salt && salt_len) {
555 TRY_EXPECT_PSA(psa_import_key(&attr, salt, salt_len, &key_id),
556 PSA_SUCCESS, key_id,
557 unexpected_result_from_ext_lib);
558 } else {
559 uint8_t zero_salt[32] = { 0 };
560
561 TRY_EXPECT_PSA(psa_import_key(&attr, zero_salt, 32, &key_id),
562 PSA_SUCCESS, key_id,
563 unexpected_result_from_ext_lib);
564 }
565 size_t out_len;
566 TRY_EXPECT_PSA(psa_mac_compute(key_id, psa_alg, ikm, ikm_len, out, 32,
567 &out_len),
568 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
569
570 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
571 #endif
572 return ok;
573 }
574
hkdf_expand(enum hash_alg alg,const uint8_t * prk,const uint32_t prk_len,const uint8_t * info,const uint32_t info_len,uint8_t * out,uint32_t out_len)575 enum err WEAK hkdf_expand(enum hash_alg alg, const uint8_t *prk,
576 const uint32_t prk_len, const uint8_t *info,
577 const uint32_t info_len, uint8_t *out,
578 uint32_t out_len)
579 {
580 if (alg != SHA_256) {
581 return crypto_operation_not_implemented;
582 }
583 /* "N = ceil(L/HashLen)" */
584 uint32_t iterations = (out_len + 31) / 32;
585 /* "L length of output keying material in octets (<= 255*HashLen)"*/
586 if (iterations > 255) {
587 return hkdf_failed;
588 }
589
590 #ifdef TINYCRYPT
591 uint8_t t[32] = { 0 };
592 struct tc_hmac_state_struct h;
593 for (uint8_t i = 1; i <= iterations; i++) {
594 memset(&h, 0x00, sizeof(h));
595 TRY_EXPECT(tc_hmac_set_key(&h, prk, prk_len), 1);
596 tc_hmac_init(&h);
597 if (i > 1) {
598 TRY_EXPECT(tc_hmac_update(&h, t, 32), 1);
599 }
600 TRY_EXPECT(tc_hmac_update(&h, info, info_len), 1);
601 TRY_EXPECT(tc_hmac_update(&h, &i, 1), 1);
602 TRY_EXPECT(tc_hmac_final(t, TC_SHA256_DIGEST_SIZE, &h), 1);
603 if (out_len < i * 32) {
604 memcpy(&out[(i - 1) * 32], t, out_len % 32);
605 } else {
606 memcpy(&out[(i - 1) * 32], t, 32);
607 }
608 }
609 #endif
610 #ifdef MBEDTLS
611 psa_status_t status;
612 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
613 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
614
615 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
616 unexpected_result_from_ext_lib);
617 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
618 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
619 psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
620 psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
621
622 TRY_EXPECT_PSA(psa_import_key(&attr, prk, prk_len, &key_id),
623 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
624
625 size_t combo_len = (32 + (size_t)info_len + 1);
626
627 TRY_EXPECT_PSA(check_buffer_size(INFO_DEFAULT_SIZE,
628 (uint32_t)combo_len),
629 ok, key_id, unexpected_result_from_ext_lib);
630
631 uint8_t combo[INFO_DEFAULT_SIZE];
632 uint8_t tmp_out[32];
633 memset(tmp_out, 0, 32);
634 memcpy(combo + 32, info, info_len);
635 size_t offset = 32;
636 for (uint32_t i = 1; i <= iterations; i++) {
637 memcpy(combo, tmp_out, 32);
638 combo[combo_len - 1] = (uint8_t)i;
639 size_t tmp_out_len;
640 status = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
641 combo + offset, combo_len - offset,
642 tmp_out, 32, &tmp_out_len);
643 TRY_EXPECT_PSA(status, PSA_SUCCESS, key_id,
644 unexpected_result_from_ext_lib);
645 offset = 0;
646 uint8_t *dest = out + ((i - 1) << 5);
647 if (out_len < (uint32_t)(i << 5)) {
648 memcpy(dest, tmp_out, out_len & 31);
649 } else {
650 memcpy(dest, tmp_out, 32);
651 }
652 }
653 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
654 #endif
655 return ok;
656 }
657
hkdf_sha_256(struct byte_array * master_secret,struct byte_array * master_salt,struct byte_array * info,struct byte_array * out)658 enum err WEAK hkdf_sha_256(struct byte_array *master_secret,
659 struct byte_array *master_salt,
660 struct byte_array *info, struct byte_array *out)
661 {
662 uint8_t prk[HASH_DEFAULT_SIZE];
663 TRY(hkdf_extract(SHA_256, master_salt->ptr, master_salt->len,
664 master_secret->ptr, master_secret->len, prk));
665
666 TRY(hkdf_expand(SHA_256, prk, sizeof(prk), info->ptr, info->len,
667 out->ptr, out->len));
668 return ok;
669 }
670
shared_secret_derive(enum ecdh_alg alg,const uint8_t * sk,const uint32_t sk_len,const uint8_t * pk,const uint32_t pk_len,uint8_t * shared_secret)671 enum err WEAK shared_secret_derive(enum ecdh_alg alg, const uint8_t *sk,
672 const uint32_t sk_len, const uint8_t *pk,
673 const uint32_t pk_len,
674 uint8_t *shared_secret)
675 {
676 if (alg == X25519) {
677 #ifdef COMPACT25519
678 uint8_t e[F25519_SIZE];
679 f25519_copy(e, sk);
680 c25519_prepare(e);
681 c25519_smult(shared_secret, pk, e);
682 return ok;
683 #endif
684 }
685 if (alg == P256) {
686 #if defined(TINYCRYPT)
687 uECC_Curve p256 = uECC_secp256r1();
688 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
689
690 uECC_decompress(pk, pk_decompressed, p256);
691
692 PRINT_ARRAY("pk_decompressed", pk_decompressed,
693 2 * P_256_PUB_KEY_X_CORD_SIZE);
694
695 TRY_EXPECT(uECC_shared_secret(pk_decompressed, sk, shared_secret, p256), 1);
696
697 return ok;
698 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
699 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
700 psa_algorithm_t psa_alg;
701 size_t bits;
702 psa_status_t result = ok;
703
704 psa_alg = PSA_ALG_ECDH;
705 bits = PSA_BYTES_TO_BITS(sk_len);
706
707 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
708 unexpected_result_from_ext_lib);
709
710 psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
711 psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
712 psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
713 psa_set_key_algorithm(&attr, psa_alg);
714 psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(
715 PSA_ECC_FAMILY_SECP_R1));
716
717 TRY_EXPECT_PSA(
718 psa_import_key(&attr, sk, (size_t)sk_len, &key_id),
719 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
720 psa_key_type_t type = psa_get_key_type(&attr);
721 size_t shared_size =
722 PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits);
723
724 size_t shared_secret_len = 0;
725
726 size_t pk_decompressed_len;
727 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
728
729 mbedtls_pk_context ctx_verify = { 0 };
730 mbedtls_pk_init(&ctx_verify);
731 if (PSA_SUCCESS !=
732 mbedtls_pk_setup(&ctx_verify, mbedtls_pk_info_from_type(
733 MBEDTLS_PK_ECKEY))) {
734 result = unexpected_result_from_ext_lib;
735 goto cleanup;
736 }
737 if (PSA_SUCCESS !=
738 mbedtls_ecp_group_load(&mbedtls_pk_ec(ctx_verify)->grp,
739 MBEDTLS_ECP_DP_SECP256R1)) {
740 result = unexpected_result_from_ext_lib;
741 goto cleanup;
742 }
743 if (PSA_SUCCESS !=
744 mbedtls_ecp_decompress(&mbedtls_pk_ec(ctx_verify)->grp, pk,
745 pk_len, pk_decompressed,
746 &pk_decompressed_len,
747 sizeof(pk_decompressed))) {
748 result = unexpected_result_from_ext_lib;
749 goto cleanup;
750 }
751
752 PRINT_ARRAY("pk_decompressed", pk_decompressed,
753 (uint32_t)pk_decompressed_len);
754
755 if (PSA_SUCCESS !=
756 psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk_decompressed,
757 pk_decompressed_len, shared_secret,
758 shared_size, &shared_secret_len)) {
759 result = unexpected_result_from_ext_lib;
760 goto cleanup;
761 }
762 cleanup:
763 if (PSA_KEY_HANDLE_INIT != key_id) {
764 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
765 }
766 mbedtls_pk_free(&ctx_verify);
767 return result;
768 #endif
769 }
770 return crypto_operation_not_implemented;
771 }
772
ephemeral_dh_key_gen(enum ecdh_alg alg,uint32_t seed,uint8_t * sk,uint8_t * pk,uint32_t * pk_size)773 enum err WEAK ephemeral_dh_key_gen(enum ecdh_alg alg, uint32_t seed,
774 uint8_t *sk, uint8_t *pk, uint32_t *pk_size)
775 {
776 if (alg == X25519) {
777 #ifdef COMPACT25519
778 uint8_t extended_seed[32];
779 #if defined(TINYCRYPT)
780 struct tc_sha256_state_struct s;
781 TRY_EXPECT(tc_sha256_init(&s), 1);
782 TRY_EXPECT(tc_sha256_update(&s, (uint8_t *)&seed, sizeof(seed)),
783 1);
784 TRY_EXPECT(tc_sha256_final(extended_seed, &s), TC_CRYPTO_SUCCESS);
785 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
786 size_t length;
787 TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, (uint8_t *)&seed,
788 sizeof(seed), sk, HASH_DEFAULT_SIZE,
789 &length),
790 0);
791 if (length != 32) {
792 return sha_failed;
793 }
794 #endif
795 compact_x25519_keygen(sk, pk, extended_seed);
796 *pk_size = X25519_KEY_SIZE;
797 #endif
798 } else if (alg == P256) {
799 #if defined(TINYCRYPT)
800 if (P_256_PUB_KEY_X_CORD_SIZE > *pk_size) {
801 return buffer_to_small;
802 }
803 uECC_Curve p256 = uECC_secp256r1();
804 uint8_t pk_decompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
805 TRY_EXPECT(uECC_make_key(pk_decompressed, sk, p256), TC_CRYPTO_SUCCESS);
806 TRY(_memcpy_s(pk, P_256_PUB_KEY_X_CORD_SIZE, pk_decompressed, P_256_PUB_KEY_X_CORD_SIZE));
807 *pk_size = P_256_PUB_KEY_X_CORD_SIZE;
808 return ok;
809 #elif defined(MBEDTLS) /* TINYCRYPT / MBEDTLS */
810 psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
811 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
812 psa_algorithm_t psa_alg = PSA_ALG_ECDH;
813 uint8_t priv_key_size = P_256_PRIV_KEY_DEFAULT_SIZE;
814 size_t bits = PSA_BYTES_TO_BITS((size_t)priv_key_size);
815 size_t pub_key_uncompressed_size =
816 P_256_PUB_KEY_UNCOMPRESSED_SIZE;
817 uint8_t pub_key_uncompressed[P_256_PUB_KEY_UNCOMPRESSED_SIZE];
818
819 if (P_256_PUB_KEY_X_CORD_SIZE > *pk_size) {
820 return buffer_to_small;
821 }
822 TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
823 unexpected_result_from_ext_lib);
824
825 psa_set_key_usage_flags(&attributes,
826 PSA_KEY_USAGE_EXPORT |
827 PSA_KEY_USAGE_DERIVE |
828 PSA_KEY_USAGE_SIGN_MESSAGE |
829 PSA_KEY_USAGE_SIGN_HASH);
830 psa_set_key_algorithm(&attributes, psa_alg);
831 psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
832 PSA_ECC_FAMILY_SECP_R1));
833 psa_set_key_bits(&attributes, bits);
834
835 TRY_EXPECT_PSA(psa_generate_key(&attributes, &key_id),
836 PSA_SUCCESS, key_id,
837 unexpected_result_from_ext_lib);
838
839 size_t key_len = 0;
840 size_t public_key_len = 0;
841
842 TRY_EXPECT_PSA(
843 psa_export_key(key_id, sk, priv_key_size, &key_len),
844 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
845 TRY_EXPECT_PSA(
846 psa_export_public_key(key_id, pub_key_uncompressed,
847 pub_key_uncompressed_size,
848 &public_key_len),
849 PSA_SUCCESS, key_id, unexpected_result_from_ext_lib);
850 TRY_EXPECT_PSA(public_key_len, P_256_PUB_KEY_UNCOMPRESSED_SIZE,
851 key_id, unexpected_result_from_ext_lib);
852 /* Prepare output format - only x parameter */
853 memcpy(pk, (pub_key_uncompressed + 1),
854 P_256_PUB_KEY_X_CORD_SIZE);
855 TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
856 *pk_size = P_256_PUB_KEY_X_CORD_SIZE;
857 #endif
858 } else {
859 return unsupported_ecdh_curve;
860 }
861 return ok;
862 }
863
hash(enum hash_alg alg,const uint8_t * in,const uint32_t in_len,uint8_t * out)864 enum err WEAK hash(enum hash_alg alg, const uint8_t *in, const uint32_t in_len,
865 uint8_t *out)
866 {
867 if (alg == SHA_256) {
868 #ifdef TINYCRYPT
869 struct tc_sha256_state_struct s;
870 TRY_EXPECT(tc_sha256_init(&s), 1);
871 TRY_EXPECT(tc_sha256_update(&s, in, in_len), 1);
872 TRY_EXPECT(tc_sha256_final(out, &s), 1);
873 return ok;
874 #endif
875 #ifdef MBEDTLS
876 size_t length;
877 TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, in, in_len, out,
878 HASH_DEFAULT_SIZE, &length),
879 PSA_SUCCESS);
880 if (length != HASH_DEFAULT_SIZE) {
881 return sha_failed;
882 }
883 return ok;
884 #endif
885 }
886
887 return crypto_operation_not_implemented;
888 }
889