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