blob: 41641549c9baf6d1aedbb33142af385218d1a278 [file] [log] [blame]
Ronald Cron00b7bfc2020-11-25 15:25:26 +01001/*
2 * PSA ECP layer on top of Mbed TLS crypto
3 */
4/*
5 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00006 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Ronald Cron00b7bfc2020-11-25 15:25:26 +01007 */
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"
Ronald Crone5ca3d82020-11-26 16:36:16 +010016#include "psa_crypto_random_impl.h"
Valerio Setti384fbde2024-01-02 13:26:40 +010017#include "mbedtls/psa_util.h"
Ronald Cron00b7bfc2020-11-25 15:25:26 +010018
19#include <stdlib.h>
20#include <string.h>
21#include "mbedtls/platform.h"
Ronald Cron00b7bfc2020-11-25 15:25:26 +010022
Ronald Cron072722c2020-12-09 16:36:19 +010023#include <mbedtls/ecdsa.h>
Aditya Deshpande3f1606a2022-11-04 16:55:57 +000024#include <mbedtls/ecdh.h>
Ronald Cron00b7bfc2020-11-25 15:25:26 +010025#include <mbedtls/ecp.h>
26#include <mbedtls/error.h>
27
Valerio Setti27c501a2023-06-27 16:58:52 +020028#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) || \
Ronald Cron0266cfe2021-03-13 18:50:11 +010031 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
32 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
33 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +010034 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010035psa_status_t mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010036 psa_key_type_t type, size_t curve_bits,
37 const uint8_t *data, size_t data_length,
Gilles Peskine449bd832023-01-11 14:50:10 +010038 mbedtls_ecp_keypair **p_ecp)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010039{
40 mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
41 psa_status_t status;
42 mbedtls_ecp_keypair *ecp = NULL;
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010043 size_t curve_bytes = data_length;
Gilles Peskine449bd832023-01-11 14:50:10 +010044 int explicit_bits = (curve_bits != 0);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010045
Gilles Peskine449bd832023-01-11 14:50:10 +010046 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
47 PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +010048 /* A Weierstrass public key is represented as:
49 * - The byte 0x04;
50 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
51 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
52 * So its data length is 2m+1 where m is the curve size in bits.
53 */
Gilles Peskine449bd832023-01-11 14:50:10 +010054 if ((data_length & 1) == 0) {
55 return PSA_ERROR_INVALID_ARGUMENT;
56 }
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010057 curve_bytes = data_length / 2;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010058
59 /* Montgomery public keys are represented in compressed format, meaning
Gilles Peskined88ccae2021-02-08 18:39:18 +010060 * their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010061
62 /* Private keys are represented in uncompressed private random integer
Gilles Peskined88ccae2021-02-08 18:39:18 +010063 * format, meaning their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010064 }
65
Gilles Peskine449bd832023-01-11 14:50:10 +010066 if (explicit_bits) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010067 /* With an explicit bit-size, the data must have the matching length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010068 if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
69 return PSA_ERROR_INVALID_ARGUMENT;
70 }
71 } else {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010072 /* We need to infer the bit-size from the data. Since the only
73 * information we have is the length in bytes, the value of curve_bits
74 * at this stage is rounded up to the nearest multiple of 8. */
Gilles Peskine449bd832023-01-11 14:50:10 +010075 curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010076 }
77
Ronald Cron00b7bfc2020-11-25 15:25:26 +010078 /* Allocate and initialize a key representation. */
Gilles Peskine449bd832023-01-11 14:50:10 +010079 ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
80 if (ecp == NULL) {
81 return PSA_ERROR_INSUFFICIENT_MEMORY;
82 }
83 mbedtls_ecp_keypair_init(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010084
85 /* Load the group. */
Gilles Peskine449bd832023-01-11 14:50:10 +010086 grp_id = mbedtls_ecc_group_of_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
87 curve_bits, !explicit_bits);
88 if (grp_id == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010089 /* We can't distinguish between a nonsensical family/size combination
90 * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
91 * well-regarded curve that Mbed TLS just doesn't know about (which
92 * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
93 * curves that Mbed TLS knows about but for which support is disabled
94 * at build time, return NOT_SUPPORTED. */
95 status = PSA_ERROR_NOT_SUPPORTED;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010096 goto exit;
97 }
98
99 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 mbedtls_ecp_group_load(&ecp->grp, grp_id));
101 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100102 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100104
105 /* Load the key material. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100107 /* Load the public value. */
108 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
110 data,
111 data_length));
112 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100113 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100115
116 /* Check that the point is on the curve. */
117 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
119 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100120 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 }
122 } else {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100123 /* Load and validate the secret value. */
124 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 mbedtls_ecp_read_key(ecp->grp.id,
126 ecp,
127 data,
128 data_length));
129 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100130 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100132 }
133
134 *p_ecp = ecp;
135exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 if (status != PSA_SUCCESS) {
137 mbedtls_ecp_keypair_free(ecp);
138 mbedtls_free(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100139 }
140
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 return status;
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100142}
Valerio Setti27c501a2023-06-27 16:58:52 +0200143#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) ||
144 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
145 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
Ronald Cron0266cfe2021-03-13 18:50:11 +0100146 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
147 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
148 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
Ronald Cronb5399a82020-12-10 09:35:33 +0100149 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100150
Valerio Setti27c501a2023-06-27 16:58:52 +0200151#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
152 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
Ronald Cron0266cfe2021-03-13 18:50:11 +0100153 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
Ronald Crond6ec3032020-11-27 18:54:57 +0100154
Ronald Cron0266cfe2021-03-13 18:50:11 +0100155psa_status_t mbedtls_psa_ecp_import_key(
Ronald Crond6ec3032020-11-27 18:54:57 +0100156 const psa_key_attributes_t *attributes,
157 const uint8_t *data, size_t data_length,
158 uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 size_t *key_buffer_length, size_t *bits)
Ronald Crond6ec3032020-11-27 18:54:57 +0100160{
161 psa_status_t status;
162 mbedtls_ecp_keypair *ecp = NULL;
163
164 /* Parse input */
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
166 attributes->core.bits,
167 data,
168 data_length,
169 &ecp);
170 if (status != PSA_SUCCESS) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100171 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100172 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100173
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) ==
175 PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100176 *bits = ecp->grp.nbits + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 } else {
Ronald Crond6ec3032020-11-27 18:54:57 +0100178 *bits = ecp->grp.nbits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100179 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100180
181 /* Re-export the data to PSA export format. There is currently no support
182 * for other input formats then the export format, so this is a 1-1
183 * copy operation. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 status = mbedtls_psa_ecp_export_key(attributes->core.type,
185 ecp,
186 key_buffer,
187 key_buffer_size,
188 key_buffer_length);
Ronald Crond6ec3032020-11-27 18:54:57 +0100189exit:
190 /* Always free the PK object (will also free contained ECP context) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 mbedtls_ecp_keypair_free(ecp);
192 mbedtls_free(ecp);
Ronald Crond6ec3032020-11-27 18:54:57 +0100193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 return status;
Ronald Crond6ec3032020-11-27 18:54:57 +0100195}
196
Gilles Peskine449bd832023-01-11 14:50:10 +0100197psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
198 mbedtls_ecp_keypair *ecp,
199 uint8_t *data,
200 size_t data_size,
201 size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100202{
203 psa_status_t status;
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100206 /* Check whether the public part is loaded */
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 if (mbedtls_ecp_is_zero(&ecp->Q)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100208 /* Calculate the public key */
209 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
211 mbedtls_psa_get_random,
212 MBEDTLS_PSA_RANDOM_STATE));
213 if (status != PSA_SUCCESS) {
214 return status;
215 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100216 }
217
218 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100219 mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
220 MBEDTLS_ECP_PF_UNCOMPRESSED,
221 data_length,
222 data,
223 data_size));
224 if (status != PSA_SUCCESS) {
225 memset(data, 0, data_size);
226 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100227
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 return status;
229 } else {
230 if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) {
231 return PSA_ERROR_BUFFER_TOO_SMALL;
232 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100233
234 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 mbedtls_ecp_write_key(ecp,
236 data,
237 PSA_BITS_TO_BYTES(ecp->grp.nbits)));
238 if (status == PSA_SUCCESS) {
239 *data_length = PSA_BITS_TO_BYTES(ecp->grp.nbits);
240 } else {
241 memset(data, 0, data_size);
242 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100243
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100245 }
246}
247
Ronald Cron0266cfe2021-03-13 18:50:11 +0100248psa_status_t mbedtls_psa_ecp_export_public_key(
Ronald Crone5ca3d82020-11-26 16:36:16 +0100249 const psa_key_attributes_t *attributes,
250 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 uint8_t *data, size_t data_size, size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100252{
253 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
254 mbedtls_ecp_keypair *ecp = NULL;
255
256 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100257 attributes->core.type, attributes->core.bits,
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 key_buffer, key_buffer_size, &ecp);
259 if (status != PSA_SUCCESS) {
260 return status;
261 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100262
263 status = mbedtls_psa_ecp_export_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 PSA_KEY_TYPE_ECC_PUBLIC_KEY(
265 PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)),
266 ecp, data, data_size, data_length);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100267
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 mbedtls_ecp_keypair_free(ecp);
269 mbedtls_free(ecp);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100272}
Valerio Setti27c501a2023-06-27 16:58:52 +0200273#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
274 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
Ronald Cron0266cfe2021-03-13 18:50:11 +0100275 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
Ronald Cronf1057d32020-11-26 19:19:10 +0100276
Valerio Setti4c0174d2023-06-26 10:05:50 +0200277#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
Ronald Cron0266cfe2021-03-13 18:50:11 +0100278psa_status_t mbedtls_psa_ecp_generate_key(
Ronald Cron7023db52020-11-20 18:17:42 +0100279 const psa_key_attributes_t *attributes,
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
Ronald Cron7023db52020-11-20 18:17:42 +0100281{
282 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
283 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
284
285 psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 attributes->core.type);
Ronald Cron7023db52020-11-20 18:17:42 +0100287 mbedtls_ecp_group_id grp_id =
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 mbedtls_ecc_group_of_psa(curve, attributes->core.bits, 0);
Ronald Cron7023db52020-11-20 18:17:42 +0100289
290 const mbedtls_ecp_curve_info *curve_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 mbedtls_ecp_curve_info_from_grp_id(grp_id);
Ronald Cron7023db52020-11-20 18:17:42 +0100292 mbedtls_ecp_keypair ecp;
293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 if (attributes->domain_parameters_size != 0) {
295 return PSA_ERROR_NOT_SUPPORTED;
296 }
Ronald Cron7023db52020-11-20 18:17:42 +0100297
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
299 return PSA_ERROR_NOT_SUPPORTED;
300 }
Ronald Cron7023db52020-11-20 18:17:42 +0100301
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 mbedtls_ecp_keypair_init(&ecp);
303 ret = mbedtls_ecp_gen_key(grp_id, &ecp,
304 mbedtls_psa_get_random,
305 MBEDTLS_PSA_RANDOM_STATE);
306 if (ret != 0) {
307 mbedtls_ecp_keypair_free(&ecp);
308 return mbedtls_to_psa_error(ret);
Ronald Cron7023db52020-11-20 18:17:42 +0100309 }
310
311 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size));
Ronald Cron7023db52020-11-20 18:17:42 +0100313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 mbedtls_ecp_keypair_free(&ecp);
Ronald Cron7023db52020-11-20 18:17:42 +0100315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 if (status == PSA_SUCCESS) {
Ronald Cron7023db52020-11-20 18:17:42 +0100317 *key_buffer_length = key_buffer_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 }
Ronald Cron7023db52020-11-20 18:17:42 +0100319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 return status;
Ronald Cron7023db52020-11-20 18:17:42 +0100321}
Valerio Setti4c0174d2023-06-26 10:05:50 +0200322#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
Ronald Cron7023db52020-11-20 18:17:42 +0100323
Ronald Cron072722c2020-12-09 16:36:19 +0100324/****************************************************************/
325/* ECDSA sign/verify */
326/****************************************************************/
327
Ronald Cron0266cfe2021-03-13 18:50:11 +0100328#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
329 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
330psa_status_t mbedtls_psa_ecdsa_sign_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100331 const psa_key_attributes_t *attributes,
332 const uint8_t *key_buffer, size_t key_buffer_size,
333 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 uint8_t *signature, size_t signature_size, size_t *signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100335{
336 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
337 mbedtls_ecp_keypair *ecp = NULL;
338 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
339 size_t curve_bytes;
340 mbedtls_mpi r, s;
341
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
343 attributes->core.bits,
344 key_buffer,
345 key_buffer_size,
346 &ecp);
347 if (status != PSA_SUCCESS) {
348 return status;
349 }
Ronald Cron072722c2020-12-09 16:36:19 +0100350
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
352 mbedtls_mpi_init(&r);
353 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100354
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 if (signature_size < 2 * curve_bytes) {
Ronald Cron072722c2020-12-09 16:36:19 +0100356 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
357 goto cleanup;
358 }
359
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
Ronald Cron0266cfe2021-03-13 18:50:11 +0100361#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
Manuel Pégourié-Gonnard2d6d9932023-03-28 11:38:08 +0200363 mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
365 &ecp->grp, &r, &s,
366 &ecp->d, hash,
367 hash_length, md_alg,
368 mbedtls_psa_get_random,
369 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron9103d492021-03-04 11:26:03 +0100370#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
372 goto cleanup;
Ronald Cron0266cfe2021-03-13 18:50:11 +0100373#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100374 } else {
Ronald Cron072722c2020-12-09 16:36:19 +0100375 (void) alg;
Gilles Peskine449bd832023-01-11 14:50:10 +0100376 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
377 hash, hash_length,
378 mbedtls_psa_get_random,
379 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron072722c2020-12-09 16:36:19 +0100380 }
381
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
383 signature,
384 curve_bytes));
385 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
386 signature + curve_bytes,
387 curve_bytes));
Ronald Cron072722c2020-12-09 16:36:19 +0100388cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 mbedtls_mpi_free(&r);
390 mbedtls_mpi_free(&s);
391 if (ret == 0) {
Ronald Cron072722c2020-12-09 16:36:19 +0100392 *signature_length = 2 * curve_bytes;
Gilles Peskine449bd832023-01-11 14:50:10 +0100393 }
Ronald Cron072722c2020-12-09 16:36:19 +0100394
Gilles Peskine449bd832023-01-11 14:50:10 +0100395 mbedtls_ecp_keypair_free(ecp);
396 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100397
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 return mbedtls_to_psa_error(ret);
Ronald Cron072722c2020-12-09 16:36:19 +0100399}
400
Paul Elliott2c9843f2023-02-15 17:32:42 +0000401psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
Paul Elliotteefe4722023-02-06 15:59:09 +0000402{
403 int ret = 0;
404
405 /* Check whether the public part is loaded. If not, load it. */
406 if (mbedtls_ecp_is_zero(&ecp->Q)) {
407 ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
408 &ecp->d, &ecp->grp.G,
409 mbedtls_psa_get_random,
410 MBEDTLS_PSA_RANDOM_STATE);
411 }
412
Paul Elliott2c9843f2023-02-15 17:32:42 +0000413 return mbedtls_to_psa_error(ret);
Paul Elliotteefe4722023-02-06 15:59:09 +0000414}
415
Ronald Cron0266cfe2021-03-13 18:50:11 +0100416psa_status_t mbedtls_psa_ecdsa_verify_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100417 const psa_key_attributes_t *attributes,
418 const uint8_t *key_buffer, size_t key_buffer_size,
419 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100420 const uint8_t *signature, size_t signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100421{
422 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
423 mbedtls_ecp_keypair *ecp = NULL;
Ronald Cron072722c2020-12-09 16:36:19 +0100424 size_t curve_bytes;
425 mbedtls_mpi r, s;
426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 (void) alg;
Ronald Cron072722c2020-12-09 16:36:19 +0100428
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
430 attributes->core.bits,
431 key_buffer,
432 key_buffer_size,
433 &ecp);
434 if (status != PSA_SUCCESS) {
435 return status;
436 }
Ronald Cron072722c2020-12-09 16:36:19 +0100437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
439 mbedtls_mpi_init(&r);
440 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100441
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 if (signature_length != 2 * curve_bytes) {
Paul Elliott2c9843f2023-02-15 17:32:42 +0000443 status = PSA_ERROR_INVALID_SIGNATURE;
Ronald Cron072722c2020-12-09 16:36:19 +0100444 goto cleanup;
445 }
446
Paul Elliott2c9843f2023-02-15 17:32:42 +0000447 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
448 signature,
449 curve_bytes));
450 if (status != PSA_SUCCESS) {
451 goto cleanup;
452 }
Ronald Cron072722c2020-12-09 16:36:19 +0100453
Paul Elliott2c9843f2023-02-15 17:32:42 +0000454 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
455 signature + curve_bytes,
456 curve_bytes));
457 if (status != PSA_SUCCESS) {
458 goto cleanup;
459 }
Paul Elliotteefe4722023-02-06 15:59:09 +0000460
Paul Elliott2c9843f2023-02-15 17:32:42 +0000461 status = mbedtls_psa_ecp_load_public_part(ecp);
462 if (status != PSA_SUCCESS) {
463 goto cleanup;
464 }
Ronald Cron072722c2020-12-09 16:36:19 +0100465
Paul Elliott2c9843f2023-02-15 17:32:42 +0000466 status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
467 hash_length, &ecp->Q,
468 &r, &s));
Ronald Cron072722c2020-12-09 16:36:19 +0100469cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 mbedtls_mpi_free(&r);
471 mbedtls_mpi_free(&s);
472 mbedtls_ecp_keypair_free(ecp);
473 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100474
Paul Elliott2c9843f2023-02-15 17:32:42 +0000475 return status;
Ronald Cron072722c2020-12-09 16:36:19 +0100476}
477
Ronald Cron0266cfe2021-03-13 18:50:11 +0100478#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +0100479 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
480
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000481/****************************************************************/
482/* ECDH Key Agreement */
483/****************************************************************/
Aditya Deshpande5567c662022-11-07 10:43:29 +0000484
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000485#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Aditya Deshpande5567c662022-11-07 10:43:29 +0000486psa_status_t mbedtls_psa_key_agreement_ecdh(
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000487 const psa_key_attributes_t *attributes,
488 const uint8_t *key_buffer, size_t key_buffer_size,
489 psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
490 uint8_t *shared_secret, size_t shared_secret_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 size_t *shared_secret_length)
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000492{
Aditya Deshpandeb6bc7522022-11-29 16:53:29 +0000493 psa_status_t status;
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->core.type) ||
495 !PSA_ALG_IS_ECDH(alg)) {
496 return PSA_ERROR_INVALID_ARGUMENT;
497 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000498 mbedtls_ecp_keypair *ecp = NULL;
Aditya Deshpandeb6bc7522022-11-29 16:53:29 +0000499 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 attributes->core.type,
501 attributes->core.bits,
502 key_buffer,
503 key_buffer_size,
504 &ecp);
505 if (status != PSA_SUCCESS) {
506 return status;
507 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000508 mbedtls_ecp_keypair *their_key = NULL;
509 mbedtls_ecdh_context ecdh;
510 size_t bits = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
512 mbedtls_ecdh_init(&ecdh);
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000513
514 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
516 bits,
517 peer_key,
518 peer_key_length,
519 &their_key);
520 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000521 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000523
524 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
526 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000527 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100528 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000529 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100530 mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
531 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000532 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000534
535 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 mbedtls_ecdh_calc_secret(&ecdh,
537 shared_secret_length,
538 shared_secret, shared_secret_size,
539 mbedtls_psa_get_random,
540 MBEDTLS_PSA_RANDOM_STATE));
541 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000542 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 }
544 if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000545 status = PSA_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100546 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000547exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 if (status != PSA_SUCCESS) {
549 mbedtls_platform_zeroize(shared_secret, shared_secret_size);
550 }
551 mbedtls_ecdh_free(&ecdh);
552 mbedtls_ecp_keypair_free(their_key);
553 mbedtls_free(their_key);
554 mbedtls_ecp_keypair_free(ecp);
555 mbedtls_free(ecp);
556 return status;
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000557}
558#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
559
560
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100561#endif /* MBEDTLS_PSA_CRYPTO_C */