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