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