Coverage Report

Created: 2024-11-21 07:03

/src/mbedtls/library/psa_crypto_ecp.c
Line
Count
Source (jump to first uncovered line)
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
static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)
41
0
{
42
0
    switch (family) {
43
0
        case PSA_ECC_FAMILY_SECP_R1:
44
0
            switch (*bits) {
45
0
                case 192:
46
0
                case 224:
47
0
                case 256:
48
0
                case 384:
49
0
                case 521:
50
0
                    return PSA_SUCCESS;
51
0
                case 528:
52
0
                    *bits = 521;
53
0
                    return PSA_SUCCESS;
54
0
            }
55
0
            break;
56
57
0
        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
58
0
            switch (*bits) {
59
0
                case 256:
60
0
                case 384:
61
0
                case 512:
62
0
                    return PSA_SUCCESS;
63
0
            }
64
0
            break;
65
66
0
        case PSA_ECC_FAMILY_MONTGOMERY:
67
0
            switch (*bits) {
68
0
                case 448:
69
0
                case 255:
70
0
                    return PSA_SUCCESS;
71
0
                case 256:
72
0
                    *bits = 255;
73
0
                    return PSA_SUCCESS;
74
0
            }
75
0
            break;
76
77
0
        case PSA_ECC_FAMILY_SECP_K1:
78
0
            switch (*bits) {
79
0
                case 192:
80
                /* secp224k1 is not and will not be supported in PSA (#3541). */
81
0
                case 256:
82
0
                    return PSA_SUCCESS;
83
0
            }
84
0
            break;
85
0
    }
86
87
0
    return PSA_ERROR_INVALID_ARGUMENT;
88
0
}
89
90
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
0
{
95
0
    mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
96
0
    psa_status_t status;
97
0
    mbedtls_ecp_keypair *ecp = NULL;
98
0
    size_t curve_bytes = data_length;
99
0
    int explicit_bits = (curve_bits != 0);
100
101
0
    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
102
0
        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
0
        if ((data_length & 1) == 0) {
110
0
            return PSA_ERROR_INVALID_ARGUMENT;
111
0
        }
112
0
        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
0
    }
120
121
0
    if (explicit_bits) {
122
        /* With an explicit bit-size, the data must have the matching length. */
123
0
        if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
124
0
            return PSA_ERROR_INVALID_ARGUMENT;
125
0
        }
126
0
    } 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
0
        curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
131
0
    }
132
133
    /* Allocate and initialize a key representation. */
134
0
    ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
135
0
    if (ecp == NULL) {
136
0
        return PSA_ERROR_INSUFFICIENT_MEMORY;
137
0
    }
138
0
    mbedtls_ecp_keypair_init(ecp);
139
140
0
    status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);
141
0
    if (status != PSA_SUCCESS) {
142
0
        goto exit;
143
0
    }
144
145
    /* Load the group. */
146
0
    grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
147
0
                                        curve_bits);
148
0
    if (grp_id == MBEDTLS_ECP_DP_NONE) {
149
0
        status = PSA_ERROR_NOT_SUPPORTED;
150
0
        goto exit;
151
0
    }
152
153
0
    status = mbedtls_to_psa_error(
154
0
        mbedtls_ecp_group_load(&ecp->grp, grp_id));
155
0
    if (status != PSA_SUCCESS) {
156
0
        goto exit;
157
0
    }
158
159
    /* Load the key material. */
160
0
    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
161
        /* Load the public value. */
162
0
        status = mbedtls_to_psa_error(
163
0
            mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
164
0
                                          data,
165
0
                                          data_length));
166
0
        if (status != PSA_SUCCESS) {
167
0
            goto exit;
168
0
        }
169
170
        /* Check that the point is on the curve. */
171
0
        status = mbedtls_to_psa_error(
172
0
            mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
173
0
        if (status != PSA_SUCCESS) {
174
0
            goto exit;
175
0
        }
176
0
    } else {
177
        /* Load and validate the secret value. */
178
0
        status = mbedtls_to_psa_error(
179
0
            mbedtls_ecp_read_key(ecp->grp.id,
180
0
                                 ecp,
181
0
                                 data,
182
0
                                 data_length));
183
0
        if (status != PSA_SUCCESS) {
184
0
            goto exit;
185
0
        }
186
0
    }
187
188
0
    *p_ecp = ecp;
189
0
exit:
190
0
    if (status != PSA_SUCCESS) {
191
0
        mbedtls_ecp_keypair_free(ecp);
192
0
        mbedtls_free(ecp);
193
0
    }
194
195
0
    return status;
196
0
}
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
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
0
{
215
0
    psa_status_t status;
216
0
    mbedtls_ecp_keypair *ecp = NULL;
217
218
    /* Parse input */
219
0
    status = mbedtls_psa_ecp_load_representation(attributes->type,
220
0
                                                 attributes->bits,
221
0
                                                 data,
222
0
                                                 data_length,
223
0
                                                 &ecp);
224
0
    if (status != PSA_SUCCESS) {
225
0
        goto exit;
226
0
    }
227
228
0
    if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
229
0
        PSA_ECC_FAMILY_MONTGOMERY) {
230
0
        *bits = ecp->grp.nbits + 1;
231
0
    } else {
232
0
        *bits = ecp->grp.nbits;
233
0
    }
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
0
    status = mbedtls_psa_ecp_export_key(attributes->type,
239
0
                                        ecp,
240
0
                                        key_buffer,
241
0
                                        key_buffer_size,
242
0
                                        key_buffer_length);
243
0
exit:
244
    /* Always free the PK object (will also free contained ECP context) */
245
0
    mbedtls_ecp_keypair_free(ecp);
246
0
    mbedtls_free(ecp);
247
248
0
    return status;
249
0
}
250
251
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
0
{
257
0
    psa_status_t status;
258
259
0
    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
260
        /* Check whether the public part is loaded */
261
0
        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
0
                                mbedtls_psa_get_random,
266
0
                                MBEDTLS_PSA_RANDOM_STATE));
267
0
            if (status != PSA_SUCCESS) {
268
0
                return status;
269
0
            }
270
0
        }
271
272
0
        status = mbedtls_to_psa_error(
273
0
            mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
274
0
                                           MBEDTLS_ECP_PF_UNCOMPRESSED,
275
0
                                           data_length,
276
0
                                           data,
277
0
                                           data_size));
278
0
        if (status != PSA_SUCCESS) {
279
0
            memset(data, 0, data_size);
280
0
        }
281
282
0
        return status;
283
0
    } else {
284
0
        status = mbedtls_to_psa_error(
285
0
            mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
286
0
        return status;
287
0
    }
288
0
}
289
290
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
0
{
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
0
        key_buffer, key_buffer_size, &ecp);
301
0
    if (status != PSA_SUCCESS) {
302
0
        return status;
303
0
    }
304
305
0
    status = mbedtls_psa_ecp_export_key(
306
0
        PSA_KEY_TYPE_ECC_PUBLIC_KEY(
307
0
            PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
308
0
        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
0
}
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
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
0
{
324
0
    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
325
0
        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
0
        return PSA_ERROR_NOT_SUPPORTED;
330
0
    }
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
0
    }
340
341
0
    ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d,
342
0
                                  mbedtls_psa_get_random,
343
0
                                  MBEDTLS_PSA_RANDOM_STATE);
344
0
    if (ret != 0) {
345
0
        goto exit;
346
0
    }
347
348
0
    ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
349
0
                                    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
0
}
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
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
0
{
369
0
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
370
0
    mbedtls_ecp_keypair *ecp = NULL;
371
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
372
0
    size_t curve_bytes;
373
0
    mbedtls_mpi r, s;
374
375
0
    status = mbedtls_psa_ecp_load_representation(attributes->type,
376
0
                                                 attributes->bits,
377
0
                                                 key_buffer,
378
0
                                                 key_buffer_size,
379
0
                                                 &ecp);
380
0
    if (status != PSA_SUCCESS) {
381
0
        return status;
382
0
    }
383
384
0
    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
385
0
    mbedtls_mpi_init(&r);
386
0
    mbedtls_mpi_init(&s);
387
388
0
    if (signature_size < 2 * curve_bytes) {
389
0
        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
390
0
        goto cleanup;
391
0
    }
392
393
0
    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
394
0
#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
395
0
        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
396
0
        mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
397
0
        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
398
0
                            &ecp->grp, &r, &s,
399
0
                            &ecp->d, hash,
400
0
                            hash_length, md_alg,
401
0
                            mbedtls_psa_get_random,
402
0
                            MBEDTLS_PSA_RANDOM_STATE));
403
#else
404
        ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
405
        goto cleanup;
406
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
407
0
    } else {
408
0
        (void) alg;
409
0
        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
410
0
                                           hash, hash_length,
411
0
                                           mbedtls_psa_get_random,
412
0
                                           MBEDTLS_PSA_RANDOM_STATE));
413
0
    }
414
415
0
    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
416
0
                                             signature,
417
0
                                             curve_bytes));
418
0
    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
419
0
                                             signature + curve_bytes,
420
0
                                             curve_bytes));
421
0
cleanup:
422
0
    mbedtls_mpi_free(&r);
423
0
    mbedtls_mpi_free(&s);
424
0
    if (ret == 0) {
425
0
        *signature_length = 2 * curve_bytes;
426
0
    }
427
428
0
    mbedtls_ecp_keypair_free(ecp);
429
0
    mbedtls_free(ecp);
430
431
0
    return mbedtls_to_psa_error(ret);
432
0
}
433
434
psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
435
0
{
436
0
    int ret = 0;
437
438
    /* Check whether the public part is loaded. If not, load it. */
439
0
    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
0
                              mbedtls_psa_get_random,
443
0
                              MBEDTLS_PSA_RANDOM_STATE);
444
0
    }
445
446
0
    return mbedtls_to_psa_error(ret);
447
0
}
448
449
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
0
{
455
0
    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
456
0
    mbedtls_ecp_keypair *ecp = NULL;
457
0
    size_t curve_bytes;
458
0
    mbedtls_mpi r, s;
459
460
0
    (void) alg;
461
462
0
    status = mbedtls_psa_ecp_load_representation(attributes->type,
463
0
                                                 attributes->bits,
464
0
                                                 key_buffer,
465
0
                                                 key_buffer_size,
466
0
                                                 &ecp);
467
0
    if (status != PSA_SUCCESS) {
468
0
        return status;
469
0
    }
470
471
0
    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
472
0
    mbedtls_mpi_init(&r);
473
0
    mbedtls_mpi_init(&s);
474
475
0
    if (signature_length != 2 * curve_bytes) {
476
0
        status = PSA_ERROR_INVALID_SIGNATURE;
477
0
        goto cleanup;
478
0
    }
479
480
0
    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
481
0
                                                          signature,
482
0
                                                          curve_bytes));
483
0
    if (status != PSA_SUCCESS) {
484
0
        goto cleanup;
485
0
    }
486
487
0
    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
488
0
                                                          signature + curve_bytes,
489
0
                                                          curve_bytes));
490
0
    if (status != PSA_SUCCESS) {
491
0
        goto cleanup;
492
0
    }
493
494
0
    status = mbedtls_psa_ecp_load_public_part(ecp);
495
0
    if (status != PSA_SUCCESS) {
496
0
        goto cleanup;
497
0
    }
498
499
0
    status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
500
0
                                                       hash_length, &ecp->Q,
501
0
                                                       &r, &s));
502
0
cleanup:
503
0
    mbedtls_mpi_free(&r);
504
0
    mbedtls_mpi_free(&s);
505
0
    mbedtls_ecp_keypair_free(ecp);
506
0
    mbedtls_free(ecp);
507
508
0
    return status;
509
0
}
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
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
0
{
526
0
    psa_status_t status;
527
0
    if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||
528
0
        !PSA_ALG_IS_ECDH(alg)) {
529
0
        return PSA_ERROR_INVALID_ARGUMENT;
530
0
    }
531
0
    mbedtls_ecp_keypair *ecp = NULL;
532
0
    status = mbedtls_psa_ecp_load_representation(
533
0
        attributes->type,
534
0
        attributes->bits,
535
0
        key_buffer,
536
0
        key_buffer_size,
537
0
        &ecp);
538
0
    if (status != PSA_SUCCESS) {
539
0
        return status;
540
0
    }
541
0
    mbedtls_ecp_keypair *their_key = NULL;
542
0
    mbedtls_ecdh_context ecdh;
543
0
    size_t bits = 0;
544
0
    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
545
0
    mbedtls_ecdh_init(&ecdh);
546
547
0
    status = mbedtls_psa_ecp_load_representation(
548
0
        PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
549
0
        bits,
550
0
        peer_key,
551
0
        peer_key_length,
552
0
        &their_key);
553
0
    if (status != PSA_SUCCESS) {
554
0
        goto exit;
555
0
    }
556
557
0
    status = mbedtls_to_psa_error(
558
0
        mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
559
0
    if (status != PSA_SUCCESS) {
560
0
        goto exit;
561
0
    }
562
0
    status = mbedtls_to_psa_error(
563
0
        mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
564
0
    if (status != PSA_SUCCESS) {
565
0
        goto exit;
566
0
    }
567
568
0
    status = mbedtls_to_psa_error(
569
0
        mbedtls_ecdh_calc_secret(&ecdh,
570
0
                                 shared_secret_length,
571
0
                                 shared_secret, shared_secret_size,
572
0
                                 mbedtls_psa_get_random,
573
0
                                 MBEDTLS_PSA_RANDOM_STATE));
574
0
    if (status != PSA_SUCCESS) {
575
0
        goto exit;
576
0
    }
577
0
    if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
578
0
        status = PSA_ERROR_CORRUPTION_DETECTED;
579
0
    }
580
0
exit:
581
0
    if (status != PSA_SUCCESS) {
582
0
        mbedtls_platform_zeroize(shared_secret, shared_secret_size);
583
0
    }
584
0
    mbedtls_ecdh_free(&ecdh);
585
0
    mbedtls_ecp_keypair_free(their_key);
586
0
    mbedtls_free(their_key);
587
0
    mbedtls_ecp_keypair_free(ecp);
588
0
    mbedtls_free(ecp);
589
0
    return status;
590
0
}
591
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
592
593
594
#endif /* MBEDTLS_PSA_CRYPTO_C */