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