Branch data Line data Source code
1 : : /*
2 : : * PSA ECP layer on top of Mbed TLS crypto
3 : : */
4 : : /*
5 : : * Copyright The Mbed TLS Contributors
6 : : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7 : : */
8 : :
9 : : #include "common.h"
10 : :
11 : : #if defined(MBEDTLS_PSA_CRYPTO_C)
12 : :
13 : : #include <psa/crypto.h>
14 : : #include "psa_crypto_core.h"
15 : : #include "psa_crypto_ecp.h"
16 : : #include "psa_crypto_random_impl.h"
17 : : #include "mbedtls/psa_util.h"
18 : :
19 : : #include <stdlib.h>
20 : : #include <string.h>
21 : : #include "mbedtls/platform.h"
22 : :
23 : : #include <mbedtls/ecdsa.h>
24 : : #include <mbedtls/ecdh.h>
25 : : #include <mbedtls/ecp.h>
26 : : #include <mbedtls/error.h>
27 : :
28 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
29 : : defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
30 : : defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
31 : : defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
32 : : defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
33 : : defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
34 : : defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
35 : : /* Helper function to verify if the provided EC's family and key bit size are valid.
36 : : *
37 : : * Note: "bits" parameter is used both as input and output and it might be updated
38 : : * in case provided input value is not multiple of 8 ("sloppy" bits).
39 : : */
40 : 32 : static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)
41 : : {
42 [ + - - - : 32 : switch (family) {
- ]
43 : 32 : case PSA_ECC_FAMILY_SECP_R1:
44 [ + - - ]: 32 : switch (*bits) {
45 : : case 192:
46 : : case 224:
47 : : case 256:
48 : : case 384:
49 : : case 521:
50 : : return PSA_SUCCESS;
51 : 0 : case 528:
52 : 0 : *bits = 521;
53 : 0 : return PSA_SUCCESS;
54 : : }
55 : : break;
56 : :
57 : 0 : case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
58 [ # # ]: 0 : switch (*bits) {
59 : : case 256:
60 : : case 384:
61 : : case 512:
62 : : return PSA_SUCCESS;
63 : : }
64 : : break;
65 : :
66 : 0 : case PSA_ECC_FAMILY_MONTGOMERY:
67 [ # # # ]: 0 : switch (*bits) {
68 : : case 448:
69 : : case 255:
70 : : return PSA_SUCCESS;
71 : 0 : case 256:
72 : 0 : *bits = 255;
73 : 0 : return PSA_SUCCESS;
74 : : }
75 : : break;
76 : :
77 : 0 : case PSA_ECC_FAMILY_SECP_K1:
78 [ # # ]: 0 : switch (*bits) {
79 : : case 192:
80 : : /* secp224k1 is not and will not be supported in PSA (#3541). */
81 : : case 256:
82 : : return PSA_SUCCESS;
83 : : }
84 : : break;
85 : : }
86 : :
87 : : return PSA_ERROR_INVALID_ARGUMENT;
88 : : }
89 : :
90 : 32 : psa_status_t mbedtls_psa_ecp_load_representation(
91 : : psa_key_type_t type, size_t curve_bits,
92 : : const uint8_t *data, size_t data_length,
93 : : mbedtls_ecp_keypair **p_ecp)
94 : : {
95 : 32 : mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
96 : 32 : psa_status_t status;
97 : 32 : mbedtls_ecp_keypair *ecp = NULL;
98 : 32 : size_t curve_bytes = data_length;
99 : 32 : int explicit_bits = (curve_bits != 0);
100 : :
101 [ + + ]: 32 : if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
102 [ + - + - ]: 16 : PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
103 : : /* A Weierstrass public key is represented as:
104 : : * - The byte 0x04;
105 : : * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
106 : : * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
107 : : * So its data length is 2m+1 where m is the curve size in bits.
108 : : */
109 [ + - ]: 16 : if ((data_length & 1) == 0) {
110 : : return PSA_ERROR_INVALID_ARGUMENT;
111 : : }
112 : 16 : curve_bytes = data_length / 2;
113 : :
114 : : /* Montgomery public keys are represented in compressed format, meaning
115 : : * their curve_bytes is equal to the amount of input. */
116 : :
117 : : /* Private keys are represented in uncompressed private random integer
118 : : * format, meaning their curve_bytes is equal to the amount of input. */
119 : : }
120 : :
121 [ + + ]: 32 : if (explicit_bits) {
122 : : /* With an explicit bit-size, the data must have the matching length. */
123 [ + - ]: 28 : if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
124 : : return PSA_ERROR_INVALID_ARGUMENT;
125 : : }
126 : : } else {
127 : : /* We need to infer the bit-size from the data. Since the only
128 : : * information we have is the length in bytes, the value of curve_bits
129 : : * at this stage is rounded up to the nearest multiple of 8. */
130 : 4 : curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
131 : : }
132 : :
133 : : /* Allocate and initialize a key representation. */
134 : 32 : ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
135 [ + - ]: 32 : if (ecp == NULL) {
136 : : return PSA_ERROR_INSUFFICIENT_MEMORY;
137 : : }
138 : 32 : mbedtls_ecp_keypair_init(ecp);
139 : :
140 [ + - ]: 32 : status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);
141 [ - + ]: 32 : if (status != PSA_SUCCESS) {
142 : 0 : goto exit;
143 : : }
144 : :
145 : : /* Load the group. */
146 : 32 : grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
147 : : curve_bits);
148 [ - + ]: 32 : if (grp_id == MBEDTLS_ECP_DP_NONE) {
149 : 0 : status = PSA_ERROR_NOT_SUPPORTED;
150 : 0 : goto exit;
151 : : }
152 : :
153 : 32 : status = mbedtls_to_psa_error(
154 : : mbedtls_ecp_group_load(&ecp->grp, grp_id));
155 [ - + ]: 32 : if (status != PSA_SUCCESS) {
156 : 0 : goto exit;
157 : : }
158 : :
159 : : /* Load the key material. */
160 [ + + ]: 32 : if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
161 : : /* Load the public value. */
162 : 16 : status = mbedtls_to_psa_error(
163 : : mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
164 : : data,
165 : : data_length));
166 [ - + ]: 16 : if (status != PSA_SUCCESS) {
167 : 0 : goto exit;
168 : : }
169 : :
170 : : /* Check that the point is on the curve. */
171 : 16 : status = mbedtls_to_psa_error(
172 : : mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
173 [ - + ]: 16 : if (status != PSA_SUCCESS) {
174 : 0 : goto exit;
175 : : }
176 : : } else {
177 : : /* Load and validate the secret value. */
178 : 16 : status = mbedtls_to_psa_error(
179 : : mbedtls_ecp_read_key(ecp->grp.id,
180 : : ecp,
181 : : data,
182 : : data_length));
183 [ - + ]: 16 : if (status != PSA_SUCCESS) {
184 : 0 : goto exit;
185 : : }
186 : : }
187 : :
188 : 32 : *p_ecp = ecp;
189 : : exit:
190 : 32 : if (status != PSA_SUCCESS) {
191 : 0 : mbedtls_ecp_keypair_free(ecp);
192 : 0 : mbedtls_free(ecp);
193 : : }
194 : :
195 : : return status;
196 : : }
197 : : #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) ||
198 : : * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
199 : : * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
200 : : * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
201 : : * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
202 : : * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
203 : : * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
204 : :
205 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
206 : : defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
207 : : defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
208 : :
209 : 14 : psa_status_t mbedtls_psa_ecp_import_key(
210 : : const psa_key_attributes_t *attributes,
211 : : const uint8_t *data, size_t data_length,
212 : : uint8_t *key_buffer, size_t key_buffer_size,
213 : : size_t *key_buffer_length, size_t *bits)
214 : : {
215 : 14 : psa_status_t status;
216 : 14 : mbedtls_ecp_keypair *ecp = NULL;
217 : :
218 : : /* Parse input */
219 : 28 : status = mbedtls_psa_ecp_load_representation(attributes->type,
220 : 14 : attributes->bits,
221 : : data,
222 : : data_length,
223 : : &ecp);
224 [ - + ]: 14 : if (status != PSA_SUCCESS) {
225 : 0 : goto exit;
226 : : }
227 : :
228 [ + - - + ]: 14 : if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
229 : : PSA_ECC_FAMILY_MONTGOMERY) {
230 : 0 : *bits = ecp->grp.nbits + 1;
231 : : } else {
232 : 14 : *bits = ecp->grp.nbits;
233 : : }
234 : :
235 : : /* Re-export the data to PSA export format. There is currently no support
236 : : * for other input formats then the export format, so this is a 1-1
237 : : * copy operation. */
238 : 14 : status = mbedtls_psa_ecp_export_key(attributes->type,
239 : : ecp,
240 : : key_buffer,
241 : : key_buffer_size,
242 : : key_buffer_length);
243 : 14 : exit:
244 : : /* Always free the PK object (will also free contained ECP context) */
245 : 14 : mbedtls_ecp_keypair_free(ecp);
246 : 14 : mbedtls_free(ecp);
247 : :
248 : 14 : return status;
249 : : }
250 : :
251 : 14 : psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
252 : : mbedtls_ecp_keypair *ecp,
253 : : uint8_t *data,
254 : : size_t data_size,
255 : : size_t *data_length)
256 : : {
257 : 14 : psa_status_t status;
258 : :
259 [ + + ]: 14 : if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
260 : : /* Check whether the public part is loaded */
261 [ - + ]: 6 : if (mbedtls_ecp_is_zero(&ecp->Q)) {
262 : : /* Calculate the public key */
263 : 0 : status = mbedtls_to_psa_error(
264 : 0 : mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
265 : : mbedtls_psa_get_random,
266 : : MBEDTLS_PSA_RANDOM_STATE));
267 [ # # ]: 0 : if (status != PSA_SUCCESS) {
268 : : return status;
269 : : }
270 : : }
271 : :
272 : 6 : status = mbedtls_to_psa_error(
273 : 6 : mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
274 : : MBEDTLS_ECP_PF_UNCOMPRESSED,
275 : : data_length,
276 : : data,
277 : : data_size));
278 [ - + ]: 6 : if (status != PSA_SUCCESS) {
279 : 0 : memset(data, 0, data_size);
280 : : }
281 : :
282 : 6 : return status;
283 : : } else {
284 : 8 : status = mbedtls_to_psa_error(
285 : : mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
286 : 8 : return status;
287 : : }
288 : : }
289 : :
290 : 0 : psa_status_t mbedtls_psa_ecp_export_public_key(
291 : : const psa_key_attributes_t *attributes,
292 : : const uint8_t *key_buffer, size_t key_buffer_size,
293 : : uint8_t *data, size_t data_size, size_t *data_length)
294 : : {
295 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
296 : 0 : mbedtls_ecp_keypair *ecp = NULL;
297 : :
298 : 0 : status = mbedtls_psa_ecp_load_representation(
299 : 0 : attributes->type, attributes->bits,
300 : : key_buffer, key_buffer_size, &ecp);
301 [ # # ]: 0 : if (status != PSA_SUCCESS) {
302 : : return status;
303 : : }
304 : :
305 : 0 : status = mbedtls_psa_ecp_export_key(
306 [ # # ]: 0 : PSA_KEY_TYPE_ECC_PUBLIC_KEY(
307 : : PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
308 : : ecp, data, data_size, data_length);
309 : :
310 : 0 : mbedtls_ecp_keypair_free(ecp);
311 : 0 : mbedtls_free(ecp);
312 : :
313 : 0 : return status;
314 : : }
315 : : #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
316 : : * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
317 : : * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
318 : :
319 : : #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
320 : 0 : psa_status_t mbedtls_psa_ecp_generate_key(
321 : : const psa_key_attributes_t *attributes,
322 : : uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
323 : : {
324 [ # # ]: 0 : psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
325 : : attributes->type);
326 : 0 : mbedtls_ecp_group_id grp_id =
327 : 0 : mbedtls_ecc_group_from_psa(curve, attributes->bits);
328 [ # # ]: 0 : if (grp_id == MBEDTLS_ECP_DP_NONE) {
329 : : return PSA_ERROR_NOT_SUPPORTED;
330 : : }
331 : :
332 : 0 : mbedtls_ecp_keypair ecp;
333 : 0 : mbedtls_ecp_keypair_init(&ecp);
334 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
335 : :
336 : 0 : ret = mbedtls_ecp_group_load(&ecp.grp, grp_id);
337 [ # # ]: 0 : if (ret != 0) {
338 : 0 : goto exit;
339 : : }
340 : :
341 : 0 : ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d,
342 : : mbedtls_psa_get_random,
343 : : MBEDTLS_PSA_RANDOM_STATE);
344 [ # # ]: 0 : if (ret != 0) {
345 : 0 : goto exit;
346 : : }
347 : :
348 : 0 : ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
349 : : key_buffer, key_buffer_size);
350 : :
351 : 0 : exit:
352 : 0 : mbedtls_ecp_keypair_free(&ecp);
353 : 0 : return mbedtls_to_psa_error(ret);
354 : : }
355 : : #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
356 : :
357 : : /****************************************************************/
358 : : /* ECDSA sign/verify */
359 : : /****************************************************************/
360 : :
361 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
362 : : defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
363 : 4 : psa_status_t mbedtls_psa_ecdsa_sign_hash(
364 : : const psa_key_attributes_t *attributes,
365 : : const uint8_t *key_buffer, size_t key_buffer_size,
366 : : psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
367 : : uint8_t *signature, size_t signature_size, size_t *signature_length)
368 : : {
369 : 4 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
370 : 4 : mbedtls_ecp_keypair *ecp = NULL;
371 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372 : 4 : size_t curve_bytes;
373 : 4 : mbedtls_mpi r, s;
374 : :
375 : 8 : status = mbedtls_psa_ecp_load_representation(attributes->type,
376 : 4 : attributes->bits,
377 : : key_buffer,
378 : : key_buffer_size,
379 : : &ecp);
380 [ + - ]: 4 : if (status != PSA_SUCCESS) {
381 : : return status;
382 : : }
383 : :
384 : 4 : curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
385 : 4 : mbedtls_mpi_init(&r);
386 : 4 : mbedtls_mpi_init(&s);
387 : :
388 [ - + ]: 4 : if (signature_size < 2 * curve_bytes) {
389 : 0 : ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
390 : 0 : goto cleanup;
391 : : }
392 : :
393 [ - + ]: 4 : if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
394 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
395 : : psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
396 : : mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
397 : : MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
398 : : &ecp->grp, &r, &s,
399 : : &ecp->d, hash,
400 : : hash_length, md_alg,
401 : : mbedtls_psa_get_random,
402 : : MBEDTLS_PSA_RANDOM_STATE));
403 : : #else
404 : 0 : ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
405 : 0 : goto cleanup;
406 : : #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
407 : : } else {
408 : 4 : (void) alg;
409 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
410 : : hash, hash_length,
411 : : mbedtls_psa_get_random,
412 : : MBEDTLS_PSA_RANDOM_STATE));
413 : : }
414 : :
415 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
416 : : signature,
417 : : curve_bytes));
418 : 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
419 : : signature + curve_bytes,
420 : : curve_bytes));
421 : 4 : cleanup:
422 : 4 : mbedtls_mpi_free(&r);
423 : 4 : mbedtls_mpi_free(&s);
424 [ + - ]: 4 : if (ret == 0) {
425 : 4 : *signature_length = 2 * curve_bytes;
426 : : }
427 : :
428 : 4 : mbedtls_ecp_keypair_free(ecp);
429 : 4 : mbedtls_free(ecp);
430 : :
431 : 4 : return mbedtls_to_psa_error(ret);
432 : : }
433 : :
434 : 6 : psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
435 : : {
436 : 6 : int ret = 0;
437 : :
438 : : /* Check whether the public part is loaded. If not, load it. */
439 [ - + ]: 6 : if (mbedtls_ecp_is_zero(&ecp->Q)) {
440 : 0 : ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
441 : 0 : &ecp->d, &ecp->grp.G,
442 : : mbedtls_psa_get_random,
443 : : MBEDTLS_PSA_RANDOM_STATE);
444 : : }
445 : :
446 : 6 : return mbedtls_to_psa_error(ret);
447 : : }
448 : :
449 : 6 : psa_status_t mbedtls_psa_ecdsa_verify_hash(
450 : : const psa_key_attributes_t *attributes,
451 : : const uint8_t *key_buffer, size_t key_buffer_size,
452 : : psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
453 : : const uint8_t *signature, size_t signature_length)
454 : : {
455 : 6 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
456 : 6 : mbedtls_ecp_keypair *ecp = NULL;
457 : 6 : size_t curve_bytes;
458 : 6 : mbedtls_mpi r, s;
459 : :
460 : 6 : (void) alg;
461 : :
462 : 12 : status = mbedtls_psa_ecp_load_representation(attributes->type,
463 : 6 : attributes->bits,
464 : : key_buffer,
465 : : key_buffer_size,
466 : : &ecp);
467 [ + - ]: 6 : if (status != PSA_SUCCESS) {
468 : : return status;
469 : : }
470 : :
471 : 6 : curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
472 : 6 : mbedtls_mpi_init(&r);
473 : 6 : mbedtls_mpi_init(&s);
474 : :
475 [ - + ]: 6 : if (signature_length != 2 * curve_bytes) {
476 : 0 : status = PSA_ERROR_INVALID_SIGNATURE;
477 : 0 : goto cleanup;
478 : : }
479 : :
480 : 6 : status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
481 : : signature,
482 : : curve_bytes));
483 [ - + ]: 6 : if (status != PSA_SUCCESS) {
484 : 0 : goto cleanup;
485 : : }
486 : :
487 : 6 : status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
488 : 6 : signature + curve_bytes,
489 : : curve_bytes));
490 [ - + ]: 6 : if (status != PSA_SUCCESS) {
491 : 0 : goto cleanup;
492 : : }
493 : :
494 : 6 : status = mbedtls_psa_ecp_load_public_part(ecp);
495 [ - + ]: 6 : if (status != PSA_SUCCESS) {
496 : 0 : goto cleanup;
497 : : }
498 : :
499 : 6 : status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
500 : 6 : hash_length, &ecp->Q,
501 : : &r, &s));
502 : 6 : cleanup:
503 : 6 : mbedtls_mpi_free(&r);
504 : 6 : mbedtls_mpi_free(&s);
505 : 6 : mbedtls_ecp_keypair_free(ecp);
506 : 6 : mbedtls_free(ecp);
507 : :
508 : 6 : return status;
509 : : }
510 : :
511 : : #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
512 : : * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
513 : :
514 : : /****************************************************************/
515 : : /* ECDH Key Agreement */
516 : : /****************************************************************/
517 : :
518 : : #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
519 : 4 : psa_status_t mbedtls_psa_key_agreement_ecdh(
520 : : const psa_key_attributes_t *attributes,
521 : : const uint8_t *key_buffer, size_t key_buffer_size,
522 : : psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
523 : : uint8_t *shared_secret, size_t shared_secret_size,
524 : : size_t *shared_secret_length)
525 : : {
526 : 4 : psa_status_t status;
527 [ + - ]: 4 : if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||
528 [ + - ]: 4 : !PSA_ALG_IS_ECDH(alg)) {
529 : : return PSA_ERROR_INVALID_ARGUMENT;
530 : : }
531 : 4 : mbedtls_ecp_keypair *ecp = NULL;
532 : 8 : status = mbedtls_psa_ecp_load_representation(
533 : : attributes->type,
534 : 4 : attributes->bits,
535 : : key_buffer,
536 : : key_buffer_size,
537 : : &ecp);
538 [ + - ]: 4 : if (status != PSA_SUCCESS) {
539 : : return status;
540 : : }
541 : 4 : mbedtls_ecp_keypair *their_key = NULL;
542 : 4 : mbedtls_ecdh_context ecdh;
543 : 4 : size_t bits = 0;
544 : 4 : psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
545 : 4 : mbedtls_ecdh_init(&ecdh);
546 : :
547 : 8 : status = mbedtls_psa_ecp_load_representation(
548 : 4 : PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
549 : : bits,
550 : : peer_key,
551 : : peer_key_length,
552 : : &their_key);
553 [ - + ]: 4 : if (status != PSA_SUCCESS) {
554 : 0 : goto exit;
555 : : }
556 : :
557 : 4 : status = mbedtls_to_psa_error(
558 : : mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
559 [ - + ]: 4 : if (status != PSA_SUCCESS) {
560 : 0 : goto exit;
561 : : }
562 : 4 : status = mbedtls_to_psa_error(
563 : : mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
564 [ - + ]: 4 : if (status != PSA_SUCCESS) {
565 : 0 : goto exit;
566 : : }
567 : :
568 : 4 : status = mbedtls_to_psa_error(
569 : : mbedtls_ecdh_calc_secret(&ecdh,
570 : : shared_secret_length,
571 : : shared_secret, shared_secret_size,
572 : : mbedtls_psa_get_random,
573 : : MBEDTLS_PSA_RANDOM_STATE));
574 [ - + ]: 4 : if (status != PSA_SUCCESS) {
575 : 0 : goto exit;
576 : : }
577 [ + - ]: 4 : if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
578 : : status = PSA_ERROR_CORRUPTION_DETECTED;
579 : : }
580 : 4 : exit:
581 : 0 : if (status != PSA_SUCCESS) {
582 : 0 : mbedtls_platform_zeroize(shared_secret, shared_secret_size);
583 : : }
584 : 4 : mbedtls_ecdh_free(&ecdh);
585 : 4 : mbedtls_ecp_keypair_free(their_key);
586 : 4 : mbedtls_free(their_key);
587 : 4 : mbedtls_ecp_keypair_free(ecp);
588 : 4 : mbedtls_free(ecp);
589 : 4 : return status;
590 : : }
591 : : #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
592 : :
593 : :
594 : : #endif /* MBEDTLS_PSA_CRYPTO_C */
|