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