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