blob: bf2cae82b2b6079adf8ad517becc2d56a47e766d [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
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21#include "common.h"
22
23#if defined(MBEDTLS_PSA_CRYPTO_C)
24
25#include <psa/crypto.h>
26#include "psa_crypto_core.h"
27#include "psa_crypto_ecp.h"
Ronald Crone5ca3d82020-11-26 16:36:16 +010028#include "psa_crypto_random_impl.h"
Manuel Pégourié-Gonnardd82a9ed2022-07-18 15:21:37 +020029#include "hash_info.h"
Manuel Pégourié-Gonnard2d6d9932023-03-28 11:38:08 +020030#include "md_psa.h"
Ronald Cron00b7bfc2020-11-25 15:25:26 +010031
32#include <stdlib.h>
33#include <string.h>
34#include "mbedtls/platform.h"
Ronald Cron00b7bfc2020-11-25 15:25:26 +010035
Ronald Cron072722c2020-12-09 16:36:19 +010036#include <mbedtls/ecdsa.h>
Aditya Deshpande3f1606a2022-11-04 16:55:57 +000037#include <mbedtls/ecdh.h>
Ronald Cron00b7bfc2020-11-25 15:25:26 +010038#include <mbedtls/ecp.h>
39#include <mbedtls/error.h>
40
Ronald Cron0266cfe2021-03-13 18:50:11 +010041#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
42 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
43 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
44 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +010045 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010046psa_status_t mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010047 psa_key_type_t type, size_t curve_bits,
48 const uint8_t *data, size_t data_length,
Gilles Peskine449bd832023-01-11 14:50:10 +010049 mbedtls_ecp_keypair **p_ecp)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010050{
51 mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
52 psa_status_t status;
53 mbedtls_ecp_keypair *ecp = NULL;
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010054 size_t curve_bytes = data_length;
Gilles Peskine449bd832023-01-11 14:50:10 +010055 int explicit_bits = (curve_bits != 0);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010056
Gilles Peskine449bd832023-01-11 14:50:10 +010057 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
58 PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +010059 /* A Weierstrass public key is represented as:
60 * - The byte 0x04;
61 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
62 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
63 * So its data length is 2m+1 where m is the curve size in bits.
64 */
Gilles Peskine449bd832023-01-11 14:50:10 +010065 if ((data_length & 1) == 0) {
66 return PSA_ERROR_INVALID_ARGUMENT;
67 }
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010068 curve_bytes = data_length / 2;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010069
70 /* Montgomery public keys are represented in compressed format, meaning
Gilles Peskined88ccae2021-02-08 18:39:18 +010071 * their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010072
73 /* Private keys are represented in uncompressed private random integer
Gilles Peskined88ccae2021-02-08 18:39:18 +010074 * format, meaning their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010075 }
76
Gilles Peskine449bd832023-01-11 14:50:10 +010077 if (explicit_bits) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010078 /* With an explicit bit-size, the data must have the matching length. */
Gilles Peskine449bd832023-01-11 14:50:10 +010079 if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
80 return PSA_ERROR_INVALID_ARGUMENT;
81 }
82 } else {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010083 /* We need to infer the bit-size from the data. Since the only
84 * information we have is the length in bytes, the value of curve_bits
85 * at this stage is rounded up to the nearest multiple of 8. */
Gilles Peskine449bd832023-01-11 14:50:10 +010086 curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010087 }
88
Ronald Cron00b7bfc2020-11-25 15:25:26 +010089 /* Allocate and initialize a key representation. */
Gilles Peskine449bd832023-01-11 14:50:10 +010090 ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
91 if (ecp == NULL) {
92 return PSA_ERROR_INSUFFICIENT_MEMORY;
93 }
94 mbedtls_ecp_keypair_init(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010095
96 /* Load the group. */
Gilles Peskine449bd832023-01-11 14:50:10 +010097 grp_id = mbedtls_ecc_group_of_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
98 curve_bits, !explicit_bits);
99 if (grp_id == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100100 /* We can't distinguish between a nonsensical family/size combination
101 * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
102 * well-regarded curve that Mbed TLS just doesn't know about (which
103 * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
104 * curves that Mbed TLS knows about but for which support is disabled
105 * at build time, return NOT_SUPPORTED. */
106 status = PSA_ERROR_NOT_SUPPORTED;
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100107 goto exit;
108 }
109
110 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 mbedtls_ecp_group_load(&ecp->grp, grp_id));
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 /* Load the key material. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100118 /* Load the public value. */
119 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
121 data,
122 data_length));
123 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100124 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100126
127 /* Check that the point is on the curve. */
128 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
130 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100131 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 }
133 } else {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100134 /* Load and validate the secret value. */
135 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 mbedtls_ecp_read_key(ecp->grp.id,
137 ecp,
138 data,
139 data_length));
140 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100141 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100143 }
144
145 *p_ecp = ecp;
146exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 if (status != PSA_SUCCESS) {
148 mbedtls_ecp_keypair_free(ecp);
149 mbedtls_free(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100150 }
151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 return status;
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100153}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100154#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
155 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
156 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
157 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
Ronald Cronb5399a82020-12-10 09:35:33 +0100158 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100159
Ronald Cron0266cfe2021-03-13 18:50:11 +0100160#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
161 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
Ronald Crond6ec3032020-11-27 18:54:57 +0100162
Ronald Cron0266cfe2021-03-13 18:50:11 +0100163psa_status_t mbedtls_psa_ecp_import_key(
Ronald Crond6ec3032020-11-27 18:54:57 +0100164 const psa_key_attributes_t *attributes,
165 const uint8_t *data, size_t data_length,
166 uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 size_t *key_buffer_length, size_t *bits)
Ronald Crond6ec3032020-11-27 18:54:57 +0100168{
169 psa_status_t status;
170 mbedtls_ecp_keypair *ecp = NULL;
171
172 /* Parse input */
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
174 attributes->core.bits,
175 data,
176 data_length,
177 &ecp);
178 if (status != PSA_SUCCESS) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100179 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) ==
183 PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100184 *bits = ecp->grp.nbits + 1;
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 } else {
Ronald Crond6ec3032020-11-27 18:54:57 +0100186 *bits = ecp->grp.nbits;
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100188
189 /* Re-export the data to PSA export format. There is currently no support
190 * for other input formats then the export format, so this is a 1-1
191 * copy operation. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 status = mbedtls_psa_ecp_export_key(attributes->core.type,
193 ecp,
194 key_buffer,
195 key_buffer_size,
196 key_buffer_length);
Ronald Crond6ec3032020-11-27 18:54:57 +0100197exit:
198 /* Always free the PK object (will also free contained ECP context) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 mbedtls_ecp_keypair_free(ecp);
200 mbedtls_free(ecp);
Ronald Crond6ec3032020-11-27 18:54:57 +0100201
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 return status;
Ronald Crond6ec3032020-11-27 18:54:57 +0100203}
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
206 mbedtls_ecp_keypair *ecp,
207 uint8_t *data,
208 size_t data_size,
209 size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100210{
211 psa_status_t status;
212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100214 /* Check whether the public part is loaded */
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 if (mbedtls_ecp_is_zero(&ecp->Q)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100216 /* Calculate the public key */
217 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
219 mbedtls_psa_get_random,
220 MBEDTLS_PSA_RANDOM_STATE));
221 if (status != PSA_SUCCESS) {
222 return status;
223 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100224 }
225
226 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
228 MBEDTLS_ECP_PF_UNCOMPRESSED,
229 data_length,
230 data,
231 data_size));
232 if (status != PSA_SUCCESS) {
233 memset(data, 0, data_size);
234 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 return status;
237 } else {
238 if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) {
239 return PSA_ERROR_BUFFER_TOO_SMALL;
240 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100241
242 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 mbedtls_ecp_write_key(ecp,
244 data,
245 PSA_BITS_TO_BYTES(ecp->grp.nbits)));
246 if (status == PSA_SUCCESS) {
247 *data_length = PSA_BITS_TO_BYTES(ecp->grp.nbits);
248 } else {
249 memset(data, 0, data_size);
250 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100251
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100253 }
254}
255
Ronald Cron0266cfe2021-03-13 18:50:11 +0100256psa_status_t mbedtls_psa_ecp_export_public_key(
Ronald Crone5ca3d82020-11-26 16:36:16 +0100257 const psa_key_attributes_t *attributes,
258 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 uint8_t *data, size_t data_size, size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100260{
261 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
262 mbedtls_ecp_keypair *ecp = NULL;
263
264 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100265 attributes->core.type, attributes->core.bits,
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 key_buffer, key_buffer_size, &ecp);
267 if (status != PSA_SUCCESS) {
268 return status;
269 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100270
271 status = mbedtls_psa_ecp_export_key(
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 PSA_KEY_TYPE_ECC_PUBLIC_KEY(
273 PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)),
274 ecp, data, data_size, data_length);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 mbedtls_ecp_keypair_free(ecp);
277 mbedtls_free(ecp);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100280}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100281#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
282 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
Ronald Cronf1057d32020-11-26 19:19:10 +0100283
Ronald Cron0266cfe2021-03-13 18:50:11 +0100284#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
285psa_status_t mbedtls_psa_ecp_generate_key(
Ronald Cron7023db52020-11-20 18:17:42 +0100286 const psa_key_attributes_t *attributes,
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
Ronald Cron7023db52020-11-20 18:17:42 +0100288{
289 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
290 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
291
292 psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 attributes->core.type);
Ronald Cron7023db52020-11-20 18:17:42 +0100294 mbedtls_ecp_group_id grp_id =
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 mbedtls_ecc_group_of_psa(curve, attributes->core.bits, 0);
Ronald Cron7023db52020-11-20 18:17:42 +0100296
297 const mbedtls_ecp_curve_info *curve_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 mbedtls_ecp_curve_info_from_grp_id(grp_id);
Ronald Cron7023db52020-11-20 18:17:42 +0100299 mbedtls_ecp_keypair ecp;
300
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 if (attributes->domain_parameters_size != 0) {
302 return PSA_ERROR_NOT_SUPPORTED;
303 }
Ronald Cron7023db52020-11-20 18:17:42 +0100304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
306 return PSA_ERROR_NOT_SUPPORTED;
307 }
Ronald Cron7023db52020-11-20 18:17:42 +0100308
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 mbedtls_ecp_keypair_init(&ecp);
310 ret = mbedtls_ecp_gen_key(grp_id, &ecp,
311 mbedtls_psa_get_random,
312 MBEDTLS_PSA_RANDOM_STATE);
313 if (ret != 0) {
314 mbedtls_ecp_keypair_free(&ecp);
315 return mbedtls_to_psa_error(ret);
Ronald Cron7023db52020-11-20 18:17:42 +0100316 }
317
318 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size));
Ronald Cron7023db52020-11-20 18:17:42 +0100320
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 mbedtls_ecp_keypair_free(&ecp);
Ronald Cron7023db52020-11-20 18:17:42 +0100322
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 if (status == PSA_SUCCESS) {
Ronald Cron7023db52020-11-20 18:17:42 +0100324 *key_buffer_length = key_buffer_size;
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 }
Ronald Cron7023db52020-11-20 18:17:42 +0100326
Gilles Peskine449bd832023-01-11 14:50:10 +0100327 return status;
Ronald Cron7023db52020-11-20 18:17:42 +0100328}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100329#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
Ronald Cron7023db52020-11-20 18:17:42 +0100330
Ronald Cron072722c2020-12-09 16:36:19 +0100331/****************************************************************/
332/* ECDSA sign/verify */
333/****************************************************************/
334
Ronald Cron0266cfe2021-03-13 18:50:11 +0100335#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
336 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
337psa_status_t mbedtls_psa_ecdsa_sign_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100338 const psa_key_attributes_t *attributes,
339 const uint8_t *key_buffer, size_t key_buffer_size,
340 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 uint8_t *signature, size_t signature_size, size_t *signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100342{
343 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
344 mbedtls_ecp_keypair *ecp = NULL;
345 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
346 size_t curve_bytes;
347 mbedtls_mpi r, s;
348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
350 attributes->core.bits,
351 key_buffer,
352 key_buffer_size,
353 &ecp);
354 if (status != PSA_SUCCESS) {
355 return status;
356 }
Ronald Cron072722c2020-12-09 16:36:19 +0100357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
359 mbedtls_mpi_init(&r);
360 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100361
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 if (signature_size < 2 * curve_bytes) {
Ronald Cron072722c2020-12-09 16:36:19 +0100363 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
364 goto cleanup;
365 }
366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
Ronald Cron0266cfe2021-03-13 18:50:11 +0100368#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
Manuel Pégourié-Gonnard2d6d9932023-03-28 11:38:08 +0200370 mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
372 &ecp->grp, &r, &s,
373 &ecp->d, hash,
374 hash_length, md_alg,
375 mbedtls_psa_get_random,
376 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron9103d492021-03-04 11:26:03 +0100377#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
379 goto cleanup;
Ronald Cron0266cfe2021-03-13 18:50:11 +0100380#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 } else {
Ronald Cron072722c2020-12-09 16:36:19 +0100382 (void) alg;
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
384 hash, hash_length,
385 mbedtls_psa_get_random,
386 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron072722c2020-12-09 16:36:19 +0100387 }
388
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
390 signature,
391 curve_bytes));
392 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
393 signature + curve_bytes,
394 curve_bytes));
Ronald Cron072722c2020-12-09 16:36:19 +0100395cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 mbedtls_mpi_free(&r);
397 mbedtls_mpi_free(&s);
398 if (ret == 0) {
Ronald Cron072722c2020-12-09 16:36:19 +0100399 *signature_length = 2 * curve_bytes;
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 }
Ronald Cron072722c2020-12-09 16:36:19 +0100401
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 mbedtls_ecp_keypair_free(ecp);
403 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 return mbedtls_to_psa_error(ret);
Ronald Cron072722c2020-12-09 16:36:19 +0100406}
407
Paul Elliott2c9843f2023-02-15 17:32:42 +0000408psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
Paul Elliotteefe4722023-02-06 15:59:09 +0000409{
410 int ret = 0;
411
412 /* Check whether the public part is loaded. If not, load it. */
413 if (mbedtls_ecp_is_zero(&ecp->Q)) {
414 ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
415 &ecp->d, &ecp->grp.G,
416 mbedtls_psa_get_random,
417 MBEDTLS_PSA_RANDOM_STATE);
418 }
419
Paul Elliott2c9843f2023-02-15 17:32:42 +0000420 return mbedtls_to_psa_error(ret);
Paul Elliotteefe4722023-02-06 15:59:09 +0000421}
422
Ronald Cron0266cfe2021-03-13 18:50:11 +0100423psa_status_t mbedtls_psa_ecdsa_verify_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100424 const psa_key_attributes_t *attributes,
425 const uint8_t *key_buffer, size_t key_buffer_size,
426 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 const uint8_t *signature, size_t signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100428{
429 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
430 mbedtls_ecp_keypair *ecp = NULL;
Ronald Cron072722c2020-12-09 16:36:19 +0100431 size_t curve_bytes;
432 mbedtls_mpi r, s;
433
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 (void) alg;
Ronald Cron072722c2020-12-09 16:36:19 +0100435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
437 attributes->core.bits,
438 key_buffer,
439 key_buffer_size,
440 &ecp);
441 if (status != PSA_SUCCESS) {
442 return status;
443 }
Ronald Cron072722c2020-12-09 16:36:19 +0100444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
446 mbedtls_mpi_init(&r);
447 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100448
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 if (signature_length != 2 * curve_bytes) {
Paul Elliott2c9843f2023-02-15 17:32:42 +0000450 status = PSA_ERROR_INVALID_SIGNATURE;
Ronald Cron072722c2020-12-09 16:36:19 +0100451 goto cleanup;
452 }
453
Paul Elliott2c9843f2023-02-15 17:32:42 +0000454 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
455 signature,
456 curve_bytes));
457 if (status != PSA_SUCCESS) {
458 goto cleanup;
459 }
Ronald Cron072722c2020-12-09 16:36:19 +0100460
Paul Elliott2c9843f2023-02-15 17:32:42 +0000461 status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
462 signature + curve_bytes,
463 curve_bytes));
464 if (status != PSA_SUCCESS) {
465 goto cleanup;
466 }
Paul Elliotteefe4722023-02-06 15:59:09 +0000467
Paul Elliott2c9843f2023-02-15 17:32:42 +0000468 status = mbedtls_psa_ecp_load_public_part(ecp);
469 if (status != PSA_SUCCESS) {
470 goto cleanup;
471 }
Ronald Cron072722c2020-12-09 16:36:19 +0100472
Paul Elliott2c9843f2023-02-15 17:32:42 +0000473 status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
474 hash_length, &ecp->Q,
475 &r, &s));
Ronald Cron072722c2020-12-09 16:36:19 +0100476cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100477 mbedtls_mpi_free(&r);
478 mbedtls_mpi_free(&s);
479 mbedtls_ecp_keypair_free(ecp);
480 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100481
Paul Elliott2c9843f2023-02-15 17:32:42 +0000482 return status;
Ronald Cron072722c2020-12-09 16:36:19 +0100483}
484
Ronald Cron0266cfe2021-03-13 18:50:11 +0100485#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +0100486 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
487
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000488/****************************************************************/
489/* ECDH Key Agreement */
490/****************************************************************/
Aditya Deshpande5567c662022-11-07 10:43:29 +0000491
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000492#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Aditya Deshpande5567c662022-11-07 10:43:29 +0000493psa_status_t mbedtls_psa_key_agreement_ecdh(
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000494 const psa_key_attributes_t *attributes,
495 const uint8_t *key_buffer, size_t key_buffer_size,
496 psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
497 uint8_t *shared_secret, size_t shared_secret_size,
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 size_t *shared_secret_length)
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000499{
Aditya Deshpandeb6bc7522022-11-29 16:53:29 +0000500 psa_status_t status;
Gilles Peskine449bd832023-01-11 14:50:10 +0100501 if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->core.type) ||
502 !PSA_ALG_IS_ECDH(alg)) {
503 return PSA_ERROR_INVALID_ARGUMENT;
504 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000505 mbedtls_ecp_keypair *ecp = NULL;
Aditya Deshpandeb6bc7522022-11-29 16:53:29 +0000506 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 attributes->core.type,
508 attributes->core.bits,
509 key_buffer,
510 key_buffer_size,
511 &ecp);
512 if (status != PSA_SUCCESS) {
513 return status;
514 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000515 mbedtls_ecp_keypair *their_key = NULL;
516 mbedtls_ecdh_context ecdh;
517 size_t bits = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
519 mbedtls_ecdh_init(&ecdh);
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000520
521 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
523 bits,
524 peer_key,
525 peer_key_length,
526 &their_key);
527 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000528 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000530
531 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
533 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000534 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100535 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000536 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
538 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000539 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000541
542 status = mbedtls_to_psa_error(
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 mbedtls_ecdh_calc_secret(&ecdh,
544 shared_secret_length,
545 shared_secret, shared_secret_size,
546 mbedtls_psa_get_random,
547 MBEDTLS_PSA_RANDOM_STATE));
548 if (status != PSA_SUCCESS) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000549 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 }
551 if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000552 status = PSA_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 }
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000554exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 if (status != PSA_SUCCESS) {
556 mbedtls_platform_zeroize(shared_secret, shared_secret_size);
557 }
558 mbedtls_ecdh_free(&ecdh);
559 mbedtls_ecp_keypair_free(their_key);
560 mbedtls_free(their_key);
561 mbedtls_ecp_keypair_free(ecp);
562 mbedtls_free(ecp);
563 return status;
Aditya Deshpande3f1606a2022-11-04 16:55:57 +0000564}
565#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
566
567
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100568#endif /* MBEDTLS_PSA_CRYPTO_C */