Branch data Line data Source code
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 : : */
92 : 4 : 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 : 4 : plen = mbedtls_mpi_size(&grp->P);
104 : :
105 : 4 : *olen = 2 * plen + 1;
106 : :
107 [ - + ]: 4 : if (osize < *olen)
108 : 0 : return (MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL);
109 : :
110 : : // output will consist of 0x04|X|Y
111 : 4 : memcpy(output + 1, input, ilen);
112 : 4 : output[0] = 0x04;
113 : :
114 : 4 : mbedtls_mpi_init(&r);
115 : 4 : mbedtls_mpi_init(&x);
116 : 4 : mbedtls_mpi_init(&n);
117 : :
118 : : // x <= input
119 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&x, input, plen));
120 : :
121 : : // r = x^2
122 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &x, &x));
123 : :
124 : : // r = x^2 + a
125 [ + - ]: 4 : if (grp->A.p == NULL) {
126 : : // Special case where a is -3
127 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&r, &r, 3));
128 : : } else {
129 [ # # ]: 0 : MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&r, &r, &grp->A));
130 : : }
131 : :
132 : : // r = x^3 + ax
133 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&r, &r, &x));
134 : :
135 : : // r = x^3 + ax + b
136 [ - + ]: 4 : 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 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&n, &grp->P, 1));
143 : :
144 : : // n = (P + 1) / 4
145 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&n, 2));
146 : :
147 : : // r ^ ((P + 1) / 4) (mod p)
148 [ - + ]: 4 : 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 [ + - ]: 4 : if ((input[0] == 0x03) != mbedtls_mpi_get_bit(&r, 0)) {
152 : : // r = p - r
153 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&r, &grp->P, &r));
154 : : }
155 : :
156 : : // y => output
157 : 4 : ret = mbedtls_mpi_write_binary(&r, output + 1 + plen, plen);
158 : :
159 : 4 : cleanup:
160 : 4 : mbedtls_mpi_free(&r);
161 : 4 : mbedtls_mpi_free(&x);
162 : 4 : mbedtls_mpi_free(&n);
163 : :
164 : 4 : 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 */
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 */
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 */
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
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 : :
265 : 34 : 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 : 34 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
308 : :
309 [ - + - - ]: 34 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
310 : : unexpected_result_from_ext_lib);
311 : :
312 : 34 : psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(
313 : : PSA_ALG_CCM, (uint32_t)tag->len);
314 : :
315 : 34 : psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
316 : 34 : psa_set_key_usage_flags(&attr,
317 : : PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT);
318 : 34 : psa_set_key_algorithm(&attr, alg);
319 : 34 : psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
320 : 34 : psa_set_key_bits(&attr, ((size_t)key->len << 3));
321 : 34 : psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
322 [ - + - - ]: 34 : 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 [ + + ]: 34 : if (op == DECRYPT) {
326 : 16 : size_t out_len_re = 0;
327 [ - + - - ]: 16 : 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 [ - + - - ]: 18 : 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 : 18 : memcpy(tag->ptr, out->ptr + out_len_re - tag->len, tag->len);
341 : : }
342 [ - + ]: 34 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
343 : :
344 : : #endif
345 : 34 : return ok;
346 : : }
347 : :
348 : : #ifdef EDHOC_MOCK_CRYPTO_WRAPPER
349 : : static bool
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 : :
367 : 6 : 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 [ + + ]: 6 : if (alg == EdDSA) {
386 : : #if defined(COMPACT25519)
387 : 2 : edsign_sign(out, pk->ptr, sk->ptr, msg->ptr, msg->len);
388 : 2 : return ok;
389 : : #endif
390 [ + - ]: 4 : } 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 : 4 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
411 : :
412 : 4 : psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
413 : 4 : bits = PSA_BYTES_TO_BITS((size_t)sk->len);
414 : :
415 [ - + - - ]: 4 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
416 : : unexpected_result_from_ext_lib);
417 : :
418 : 4 : psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
419 : 4 : 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 : 4 : psa_set_key_algorithm(&attributes, psa_alg);
425 : 4 : psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
426 : : PSA_ECC_FAMILY_SECP_R1));
427 : 4 : psa_set_key_bits(&attributes, bits);
428 : 4 : psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
429 : :
430 [ - + - - ]: 4 : 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 [ - + - - ]: 4 : 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 [ - + - - ]: 4 : TRY_EXPECT_PSA(signature_length, SIGNATURE_SIZE, key_id,
442 : : sign_failed);
443 [ - + ]: 4 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
444 : 4 : return ok;
445 : : #endif
446 : : }
447 : 0 : return unsupported_ecdh_curve;
448 : : }
449 : :
450 : 8 : 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 [ + + ]: 8 : if (alg == EdDSA) {
455 : : #ifdef COMPACT25519
456 : 2 : int verified =
457 : 2 : edsign_verify(sgn->ptr, pk->ptr, msg->ptr, msg->len);
458 [ + - ]: 2 : if (verified) {
459 : 2 : *result = true;
460 : : } else {
461 : 0 : *result = false;
462 : : }
463 : 2 : return ok;
464 : : #endif
465 : : }
466 [ + - ]: 6 : if (alg == ES256) {
467 : : #if defined(MBEDTLS)
468 : : psa_status_t status;
469 : : psa_algorithm_t psa_alg;
470 : : size_t bits;
471 : 6 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
472 : :
473 : 6 : psa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
474 : 6 : bits = PSA_BYTES_TO_BITS(P_256_PRIV_KEY_SIZE);
475 : :
476 [ - + - - ]: 6 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
477 : : unexpected_result_from_ext_lib);
478 : :
479 : 6 : psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
480 : :
481 : 6 : psa_set_key_usage_flags(&attributes,
482 : : PSA_KEY_USAGE_VERIFY_MESSAGE |
483 : : PSA_KEY_USAGE_VERIFY_HASH);
484 : 6 : psa_set_key_algorithm(&attributes, psa_alg);
485 : 6 : psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(
486 : : PSA_ECC_FAMILY_SECP_R1));
487 : 6 : psa_set_key_bits(&attributes, bits);
488 [ - + - - ]: 6 : 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 : 6 : status = psa_verify_message(key_id, psa_alg, msg->ptr, msg->len,
493 : : sgn->ptr, sgn->len);
494 [ + - ]: 6 : if (PSA_SUCCESS == status) {
495 : 6 : *result = true;
496 : : } else {
497 : 0 : *result = false;
498 : : }
499 [ - + ]: 6 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
500 : 6 : 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 : 0 : return crypto_operation_not_implemented;
522 : : }
523 : :
524 : 39 : 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 [ - + ]: 39 : if (alg != SHA_256) {
535 : 0 : 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 : 39 : psa_algorithm_t psa_alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
552 : 39 : psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
553 : 39 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
554 : :
555 [ - + - - ]: 39 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
556 : : unexpected_result_from_ext_lib);
557 : :
558 : 39 : psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
559 : 39 : psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
560 : 39 : psa_set_key_algorithm(&attr, psa_alg);
561 : 39 : psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
562 : :
563 [ + + + - ]: 39 : if (salt->ptr && salt->len) {
564 [ - + - - ]: 33 : 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 : 6 : uint8_t zero_salt[32] = { 0 };
569 : :
570 [ - + - - ]: 6 : 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 [ - + - - ]: 39 : 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 [ - + ]: 39 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
580 : : #endif
581 : 39 : return ok;
582 : : }
583 : :
584 : 85 : 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 [ - + ]: 85 : if (alg != SHA_256) {
588 : 0 : return crypto_operation_not_implemented;
589 : : }
590 : : /* "N = ceil(L/HashLen)" */
591 : 85 : uint32_t iterations = (out->len + 31) / 32;
592 : : /* "L length of output keying material in octets (<= 255*HashLen)"*/
593 [ - + ]: 85 : if (iterations > 255) {
594 : 0 : 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 : 85 : psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
620 : 85 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
621 : 85 : PRINTF("key_id: %d\n", key_id);
622 : :
623 [ - + - - ]: 85 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
624 : : unexpected_result_from_ext_lib);
625 : 85 : psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
626 : 85 : psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
627 : 85 : psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
628 : 85 : psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
629 : :
630 : 85 : PRINT_ARRAY("PRK:", prk->ptr, prk->len);
631 [ - + - - ]: 85 : 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 : 85 : size_t combo_len = (32 + (size_t)info->len + 1);
635 : :
636 [ - + - - ]: 85 : 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 : 85 : memset(tmp_out, 0, 32);
643 : 85 : memcpy(combo + 32, info->ptr, info->len);
644 : 85 : size_t offset = 32;
645 [ + + ]: 200 : for (uint32_t i = 1; i <= iterations; i++) {
646 : 115 : memcpy(combo, tmp_out, 32);
647 : 115 : combo[combo_len - 1] = (uint8_t)i;
648 : : size_t tmp_out_len;
649 : 115 : 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 [ - + - - ]: 115 : TRY_EXPECT_PSA(status, PSA_SUCCESS, key_id,
653 : : unexpected_result_from_ext_lib);
654 : 115 : offset = 0;
655 : 115 : uint8_t *dest = out->ptr + ((i - 1) << 5);
656 [ + + ]: 115 : if (out->len < (uint32_t)(i << 5)) {
657 : 61 : memcpy(dest, tmp_out, out->len & 31);
658 : : } else {
659 : 54 : memcpy(dest, tmp_out, 32);
660 : : }
661 : : }
662 [ - + ]: 85 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
663 : : #endif
664 : 85 : return ok;
665 : : }
666 : :
667 : 33 : 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 [ - + ]: 33 : BYTE_ARRAY_NEW(prk, HASH_SIZE, HASH_SIZE);
672 [ - + ]: 33 : TRY(hkdf_extract(SHA_256, master_salt, master_secret, prk.ptr));
673 [ - + ]: 33 : TRY(hkdf_expand(SHA_256, &prk, info, out));
674 : 33 : return ok;
675 : : }
676 : :
677 : 6 : 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 [ + + ]: 6 : if (alg == X25519) {
683 : : #ifdef COMPACT25519
684 : : uint8_t e[F25519_SIZE];
685 : 2 : f25519_copy(e, sk->ptr);
686 : 2 : c25519_prepare(e);
687 : 2 : c25519_smult(shared_secret, pk->ptr, e);
688 : 2 : return ok;
689 : : #endif
690 : : }
691 [ + - ]: 4 : 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 : 4 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
708 : : psa_algorithm_t psa_alg;
709 : : size_t bits;
710 : 4 : psa_status_t result = ok;
711 : :
712 : 4 : psa_alg = PSA_ALG_ECDH;
713 : 4 : bits = PSA_BYTES_TO_BITS(sk->len);
714 : :
715 [ - + - - ]: 4 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
716 : : unexpected_result_from_ext_lib);
717 : :
718 : 4 : psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
719 : 4 : psa_set_key_lifetime(&attr, PSA_KEY_LIFETIME_VOLATILE);
720 : 4 : psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
721 : 4 : psa_set_key_algorithm(&attr, psa_alg);
722 : 4 : psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(
723 : : PSA_ECC_FAMILY_SECP_R1));
724 : :
725 [ - + - - ]: 4 : 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 : 4 : psa_key_type_t type = psa_get_key_type(&attr);
730 : 4 : size_t shared_size =
731 [ + - ]: 4 : PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(type, bits);
732 : :
733 : 4 : 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 : 4 : mbedtls_pk_context ctx_verify = { 0 };
739 : 4 : mbedtls_pk_init(&ctx_verify);
740 [ - + ]: 4 : if (PSA_SUCCESS !=
741 : 4 : mbedtls_pk_setup(&ctx_verify, mbedtls_pk_info_from_type(
742 : : MBEDTLS_PK_ECKEY))) {
743 : 0 : result = unexpected_result_from_ext_lib;
744 : 0 : goto cleanup;
745 : : }
746 [ - + ]: 4 : if (PSA_SUCCESS !=
747 : 4 : mbedtls_ecp_group_load(&mbedtls_pk_ec(ctx_verify)->grp,
748 : : MBEDTLS_ECP_DP_SECP256R1)) {
749 : 0 : result = unexpected_result_from_ext_lib;
750 : 0 : goto cleanup;
751 : : }
752 [ - + ]: 4 : if (PSA_SUCCESS !=
753 : 4 : mbedtls_ecp_decompress(&mbedtls_pk_ec(ctx_verify)->grp,
754 : 4 : pk->ptr, pk->len, pk_decompressed,
755 : : &pk_decompressed_len,
756 : : sizeof(pk_decompressed))) {
757 : 0 : result = unexpected_result_from_ext_lib;
758 : 0 : goto cleanup;
759 : : }
760 : :
761 : 4 : PRINT_ARRAY("pk_decompressed", pk_decompressed,
762 : : (uint32_t)pk_decompressed_len);
763 : :
764 [ + - ]: 4 : if (PSA_SUCCESS !=
765 : 4 : psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk_decompressed,
766 : : pk_decompressed_len, shared_secret,
767 : : shared_size, &shared_secret_len)) {
768 : 0 : result = unexpected_result_from_ext_lib;
769 : 0 : goto cleanup;
770 : : }
771 : 4 : cleanup:
772 [ + - ]: 4 : if (PSA_KEY_HANDLE_INIT != key_id) {
773 [ - + ]: 4 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
774 : : }
775 : 4 : mbedtls_pk_free(&ctx_verify);
776 : 4 : return result;
777 : : #endif
778 : : }
779 : 0 : return crypto_operation_not_implemented;
780 : : }
781 : :
782 : 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, (uint8_t *)&seed,
798 : : sizeof(seed), sk->ptr, HASH_SIZE,
799 : : &length),
800 : : 0);
801 [ # # ]: 0 : if (length != 32) {
802 : 0 : return sha_failed;
803 : : }
804 : : #endif
805 : 0 : compact_x25519_keygen(sk->ptr, pk->ptr, extended_seed);
806 : 0 : pk->len = X25519_KEY_SIZE;
807 : 0 : sk->len = X25519_KEY_SIZE;
808 : : #endif
809 [ # # ]: 0 : } 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 : 0 : psa_key_id_t key_id = PSA_KEY_HANDLE_INIT;
824 : 0 : psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
825 : 0 : psa_algorithm_t psa_alg = PSA_ALG_ECDH;
826 : 0 : uint8_t priv_key_size = P_256_PRIV_KEY_SIZE;
827 : 0 : size_t bits = PSA_BYTES_TO_BITS((size_t)priv_key_size);
828 : 0 : 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 [ # # ]: 0 : if (P_256_PUB_KEY_X_CORD_SIZE > pk->len) {
833 : 0 : return buffer_to_small;
834 : : }
835 [ # # # # ]: 0 : TRY_EXPECT_PSA(psa_crypto_init(), PSA_SUCCESS, key_id,
836 : : unexpected_result_from_ext_lib);
837 : :
838 : 0 : 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 : 0 : psa_set_key_algorithm(&attributes, psa_alg);
844 : 0 : psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(
845 : : PSA_ECC_FAMILY_SECP_R1));
846 : 0 : psa_set_key_bits(&attributes, bits);
847 : :
848 [ # # # # ]: 0 : TRY_EXPECT_PSA(psa_generate_key(&attributes, &key_id),
849 : : PSA_SUCCESS, key_id,
850 : : unexpected_result_from_ext_lib);
851 : :
852 : 0 : size_t key_len = 0;
853 : 0 : size_t public_key_len = 0;
854 : :
855 [ # # # # ]: 0 : 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 [ # # # # ]: 0 : 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 [ # # # # ]: 0 : 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 : 0 : memcpy(pk->ptr, (pub_key_uncompressed + 1),
868 : : P_256_PUB_KEY_X_CORD_SIZE);
869 [ # # ]: 0 : TRY_EXPECT(psa_destroy_key(key_id), PSA_SUCCESS);
870 : 0 : pk->len = P_256_PUB_KEY_X_CORD_SIZE;
871 : : #endif
872 : : } else {
873 : 0 : return unsupported_ecdh_curve;
874 : : }
875 : 0 : return ok;
876 : : }
877 : :
878 : 24 : enum err WEAK hash(enum hash_alg alg, const struct byte_array *in,
879 : : struct byte_array *out)
880 : : {
881 [ + - ]: 24 : 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 [ - + ]: 24 : TRY_EXPECT(psa_hash_compute(PSA_ALG_SHA_256, in->ptr, in->len,
893 : : out->ptr, HASH_SIZE, &length),
894 : : PSA_SUCCESS);
895 [ - + ]: 24 : if (length != HASH_SIZE) {
896 : 0 : return sha_failed;
897 : : }
898 : 24 : out->len = HASH_SIZE;
899 : 24 : PRINT_ARRAY("hash", out->ptr, out->len);
900 : 24 : return ok;
901 : : #endif
902 : : }
903 : :
904 : 0 : return crypto_operation_not_implemented;
905 : : }
|