blob: b00f558209cfa306441167d489b59bef51f3b7f9 [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 Rodgman7ff79652023-11-03 12:04:52 +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"
Steven Cooreman5f88e772021-03-15 11:07:12 +010017#include "psa_crypto_hash.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>
Ronald Cron00b7bfc2020-11-25 15:25:26 +010024#include <mbedtls/ecp.h>
25#include <mbedtls/error.h>
26
Ronald Croncfc3c7b2021-03-13 18:50:11 +010027#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
28 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
29 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
30 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +010031 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010032psa_status_t mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010033 psa_key_type_t type, size_t curve_bits,
34 const uint8_t *data, size_t data_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010035 mbedtls_ecp_keypair **p_ecp)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010036{
37 mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
38 psa_status_t status;
39 mbedtls_ecp_keypair *ecp = NULL;
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010040 size_t curve_bytes = data_length;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010041 int explicit_bits = (curve_bits != 0);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010042
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010043 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
44 PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +010045 /* A Weierstrass public key is represented as:
46 * - The byte 0x04;
47 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
48 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
49 * So its data length is 2m+1 where m is the curve size in bits.
50 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051 if ((data_length & 1) == 0) {
52 return PSA_ERROR_INVALID_ARGUMENT;
53 }
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010054 curve_bytes = data_length / 2;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010055
56 /* Montgomery public keys are represented in compressed format, meaning
Gilles Peskined88ccae2021-02-08 18:39:18 +010057 * their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010058
59 /* Private keys are represented in uncompressed private random integer
Gilles Peskined88ccae2021-02-08 18:39:18 +010060 * format, meaning their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010061 }
62
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 if (explicit_bits) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010064 /* With an explicit bit-size, the data must have the matching length. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010065 if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
66 return PSA_ERROR_INVALID_ARGUMENT;
67 }
68 } else {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010069 /* We need to infer the bit-size from the data. Since the only
70 * information we have is the length in bytes, the value of curve_bits
71 * at this stage is rounded up to the nearest multiple of 8. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072 curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010073 }
74
Ronald Cron00b7bfc2020-11-25 15:25:26 +010075 /* Allocate and initialize a key representation. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010076 ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
77 if (ecp == NULL) {
78 return PSA_ERROR_INSUFFICIENT_MEMORY;
79 }
80 mbedtls_ecp_keypair_init(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +010081
82 /* Load the group. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010083 grp_id = mbedtls_ecc_group_of_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
84 curve_bits, !explicit_bits);
85 if (grp_id == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010086 /* We can't distinguish between a nonsensical family/size combination
87 * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
88 * well-regarded curve that Mbed TLS just doesn't know about (which
89 * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
90 * curves that Mbed TLS knows about but for which support is disabled
91 * at build time, return NOT_SUPPORTED. */
92 status = PSA_ERROR_NOT_SUPPORTED;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010093 goto exit;
94 }
95
96 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010097 mbedtls_ecp_group_load(&ecp->grp, grp_id));
98 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +010099 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100100 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100101
102 /* Load the key material. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100104 /* Load the public value. */
105 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100106 mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
107 data,
108 data_length));
109 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100110 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100112
113 /* Check that the point is on the curve. */
114 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
116 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100117 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118 }
119 } else {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100120 /* Load and validate the secret value. */
121 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100122 mbedtls_ecp_read_key(ecp->grp.id,
123 ecp,
124 data,
125 data_length));
126 if (status != PSA_SUCCESS) {
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100127 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 }
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100129 }
130
131 *p_ecp = ecp;
132exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 if (status != PSA_SUCCESS) {
134 mbedtls_ecp_keypair_free(ecp);
135 mbedtls_free(ecp);
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100136 }
137
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100138 return status;
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100139}
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100140#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
141 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
142 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
143 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
Ronald Cronb5399a82020-12-10 09:35:33 +0100144 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100145
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100146#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
147 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
Ronald Crond6ec3032020-11-27 18:54:57 +0100148
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100149psa_status_t mbedtls_psa_ecp_import_key(
Ronald Crond6ec3032020-11-27 18:54:57 +0100150 const psa_key_attributes_t *attributes,
151 const uint8_t *data, size_t data_length,
152 uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100153 size_t *key_buffer_length, size_t *bits)
Ronald Crond6ec3032020-11-27 18:54:57 +0100154{
155 psa_status_t status;
156 mbedtls_ecp_keypair *ecp = NULL;
157
158 /* Parse input */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100159 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
160 attributes->core.bits,
161 data,
162 data_length,
163 &ecp);
164 if (status != PSA_SUCCESS) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100165 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100167
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) ==
169 PSA_ECC_FAMILY_MONTGOMERY) {
Ronald Crond6ec3032020-11-27 18:54:57 +0100170 *bits = ecp->grp.nbits + 1;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100171 } else {
Ronald Crond6ec3032020-11-27 18:54:57 +0100172 *bits = ecp->grp.nbits;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173 }
Ronald Crond6ec3032020-11-27 18:54:57 +0100174
175 /* Re-export the data to PSA export format. There is currently no support
176 * for other input formats then the export format, so this is a 1-1
177 * copy operation. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100178 status = mbedtls_psa_ecp_export_key(attributes->core.type,
179 ecp,
180 key_buffer,
181 key_buffer_size,
182 key_buffer_length);
Ronald Crond6ec3032020-11-27 18:54:57 +0100183exit:
184 /* Always free the PK object (will also free contained ECP context) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100185 mbedtls_ecp_keypair_free(ecp);
186 mbedtls_free(ecp);
Ronald Crond6ec3032020-11-27 18:54:57 +0100187
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100188 return status;
Ronald Crond6ec3032020-11-27 18:54:57 +0100189}
190
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100191psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
192 mbedtls_ecp_keypair *ecp,
193 uint8_t *data,
194 size_t data_size,
195 size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100196{
197 psa_status_t status;
198
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100199 if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100200 /* Check whether the public part is loaded */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 if (mbedtls_ecp_is_zero(&ecp->Q)) {
Ronald Crone5ca3d82020-11-26 16:36:16 +0100202 /* Calculate the public key */
203 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100204 mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
205 mbedtls_psa_get_random,
206 MBEDTLS_PSA_RANDOM_STATE));
207 if (status != PSA_SUCCESS) {
208 return status;
209 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100210 }
211
212 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100213 mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
214 MBEDTLS_ECP_PF_UNCOMPRESSED,
215 data_length,
216 data,
217 data_size));
218 if (status != PSA_SUCCESS) {
219 memset(data, 0, data_size);
220 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100221
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 return status;
223 } else {
224 if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) {
225 return PSA_ERROR_BUFFER_TOO_SMALL;
226 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100227
228 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100229 mbedtls_ecp_write_key(ecp,
230 data,
231 PSA_BITS_TO_BYTES(ecp->grp.nbits)));
232 if (status == PSA_SUCCESS) {
233 *data_length = PSA_BITS_TO_BYTES(ecp->grp.nbits);
234 } else {
235 memset(data, 0, data_size);
236 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100237
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100238 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100239 }
240}
241
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100242psa_status_t mbedtls_psa_ecp_export_public_key(
Ronald Crone5ca3d82020-11-26 16:36:16 +0100243 const psa_key_attributes_t *attributes,
244 const uint8_t *key_buffer, size_t key_buffer_size,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100245 uint8_t *data, size_t data_size, size_t *data_length)
Ronald Crone5ca3d82020-11-26 16:36:16 +0100246{
247 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
248 mbedtls_ecp_keypair *ecp = NULL;
249
250 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100251 attributes->core.type, attributes->core.bits,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252 key_buffer, key_buffer_size, &ecp);
253 if (status != PSA_SUCCESS) {
254 return status;
255 }
Ronald Crone5ca3d82020-11-26 16:36:16 +0100256
257 status = mbedtls_psa_ecp_export_key(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 PSA_KEY_TYPE_ECC_PUBLIC_KEY(
259 PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)),
260 ecp, data, data_size, data_length);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100261
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100262 mbedtls_ecp_keypair_free(ecp);
263 mbedtls_free(ecp);
Ronald Crone5ca3d82020-11-26 16:36:16 +0100264
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265 return status;
Ronald Crone5ca3d82020-11-26 16:36:16 +0100266}
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100267#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
268 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
Ronald Cronf1057d32020-11-26 19:19:10 +0100269
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100270#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
271psa_status_t mbedtls_psa_ecp_generate_key(
Ronald Cron7023db52020-11-20 18:17:42 +0100272 const psa_key_attributes_t *attributes,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100273 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
Ronald Cron7023db52020-11-20 18:17:42 +0100274{
275 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
276 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277
278 psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100279 attributes->core.type);
Ronald Cron7023db52020-11-20 18:17:42 +0100280 mbedtls_ecp_group_id grp_id =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100281 mbedtls_ecc_group_of_psa(curve, attributes->core.bits, 0);
Ronald Cron7023db52020-11-20 18:17:42 +0100282
283 const mbedtls_ecp_curve_info *curve_info =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 mbedtls_ecp_curve_info_from_grp_id(grp_id);
Ronald Cron7023db52020-11-20 18:17:42 +0100285 mbedtls_ecp_keypair ecp;
286
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100287 if (attributes->domain_parameters_size != 0) {
288 return PSA_ERROR_NOT_SUPPORTED;
289 }
Ronald Cron7023db52020-11-20 18:17:42 +0100290
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291 if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
292 return PSA_ERROR_NOT_SUPPORTED;
293 }
Ronald Cron7023db52020-11-20 18:17:42 +0100294
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100295 mbedtls_ecp_keypair_init(&ecp);
296 ret = mbedtls_ecp_gen_key(grp_id, &ecp,
297 mbedtls_psa_get_random,
298 MBEDTLS_PSA_RANDOM_STATE);
299 if (ret != 0) {
300 mbedtls_ecp_keypair_free(&ecp);
301 return mbedtls_to_psa_error(ret);
Ronald Cron7023db52020-11-20 18:17:42 +0100302 }
303
304 status = mbedtls_to_psa_error(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size));
Ronald Cron7023db52020-11-20 18:17:42 +0100306
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100307 mbedtls_ecp_keypair_free(&ecp);
Ronald Cron7023db52020-11-20 18:17:42 +0100308
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 if (status == PSA_SUCCESS) {
Ronald Cron7023db52020-11-20 18:17:42 +0100310 *key_buffer_length = key_buffer_size;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 }
Ronald Cron7023db52020-11-20 18:17:42 +0100312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 return status;
Ronald Cron7023db52020-11-20 18:17:42 +0100314}
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100315#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
Ronald Cron7023db52020-11-20 18:17:42 +0100316
Ronald Cron072722c2020-12-09 16:36:19 +0100317/****************************************************************/
318/* ECDSA sign/verify */
319/****************************************************************/
320
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100321#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
322 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
323psa_status_t mbedtls_psa_ecdsa_sign_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100324 const psa_key_attributes_t *attributes,
325 const uint8_t *key_buffer, size_t key_buffer_size,
326 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100327 uint8_t *signature, size_t signature_size, size_t *signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100328{
329 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
330 mbedtls_ecp_keypair *ecp = NULL;
331 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
332 size_t curve_bytes;
333 mbedtls_mpi r, s;
334
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100335 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
336 attributes->core.bits,
337 key_buffer,
338 key_buffer_size,
339 &ecp);
340 if (status != PSA_SUCCESS) {
341 return status;
342 }
Ronald Cron072722c2020-12-09 16:36:19 +0100343
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
345 mbedtls_mpi_init(&r);
346 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100347
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348 if (signature_size < 2 * curve_bytes) {
Ronald Cron072722c2020-12-09 16:36:19 +0100349 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
350 goto cleanup;
351 }
352
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100354#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100355 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
356 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa(hash_alg);
357 mbedtls_md_type_t md_alg = mbedtls_md_get_type(md_info);
358 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
359 &ecp->grp, &r, &s,
360 &ecp->d, hash,
361 hash_length, md_alg,
362 mbedtls_psa_get_random,
363 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron9103d492021-03-04 11:26:03 +0100364#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
366 goto cleanup;
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100367#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 } else {
Ronald Cron072722c2020-12-09 16:36:19 +0100369 (void) alg;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100370 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
371 hash, hash_length,
372 mbedtls_psa_get_random,
373 MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron072722c2020-12-09 16:36:19 +0100374 }
375
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
377 signature,
378 curve_bytes));
379 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
380 signature + curve_bytes,
381 curve_bytes));
Ronald Cron072722c2020-12-09 16:36:19 +0100382cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 mbedtls_mpi_free(&r);
384 mbedtls_mpi_free(&s);
385 if (ret == 0) {
Ronald Cron072722c2020-12-09 16:36:19 +0100386 *signature_length = 2 * curve_bytes;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100387 }
Ronald Cron072722c2020-12-09 16:36:19 +0100388
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100389 mbedtls_ecp_keypair_free(ecp);
390 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100391
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100392 return mbedtls_to_psa_error(ret);
Ronald Cron072722c2020-12-09 16:36:19 +0100393}
394
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100395psa_status_t mbedtls_psa_ecdsa_verify_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100396 const psa_key_attributes_t *attributes,
397 const uint8_t *key_buffer, size_t key_buffer_size,
398 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100399 const uint8_t *signature, size_t signature_length)
Ronald Cron072722c2020-12-09 16:36:19 +0100400{
401 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
402 mbedtls_ecp_keypair *ecp = NULL;
403 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
404 size_t curve_bytes;
405 mbedtls_mpi r, s;
406
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 (void) alg;
Ronald Cron072722c2020-12-09 16:36:19 +0100408
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100409 status = mbedtls_psa_ecp_load_representation(attributes->core.type,
410 attributes->core.bits,
411 key_buffer,
412 key_buffer_size,
413 &ecp);
414 if (status != PSA_SUCCESS) {
415 return status;
416 }
Ronald Cron072722c2020-12-09 16:36:19 +0100417
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100418 curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
419 mbedtls_mpi_init(&r);
420 mbedtls_mpi_init(&s);
Ronald Cron072722c2020-12-09 16:36:19 +0100421
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 if (signature_length != 2 * curve_bytes) {
Ronald Cron072722c2020-12-09 16:36:19 +0100423 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
424 goto cleanup;
425 }
426
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r,
428 signature,
429 curve_bytes));
430 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&s,
431 signature + curve_bytes,
432 curve_bytes));
Ronald Cron072722c2020-12-09 16:36:19 +0100433
434 /* Check whether the public part is loaded. If not, load it. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100435 if (mbedtls_ecp_is_zero(&ecp->Q)) {
Ronald Cron072722c2020-12-09 16:36:19 +0100436 MBEDTLS_MPI_CHK(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
438 mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE));
Ronald Cron072722c2020-12-09 16:36:19 +0100439 }
440
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100441 ret = mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length,
442 &ecp->Q, &r, &s);
Ronald Cron072722c2020-12-09 16:36:19 +0100443
444cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100445 mbedtls_mpi_free(&r);
446 mbedtls_mpi_free(&s);
447 mbedtls_ecp_keypair_free(ecp);
448 mbedtls_free(ecp);
Ronald Cron072722c2020-12-09 16:36:19 +0100449
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100450 return mbedtls_to_psa_error(ret);
Ronald Cron072722c2020-12-09 16:36:19 +0100451}
452
Ronald Croncfc3c7b2021-03-13 18:50:11 +0100453#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +0100454 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
455
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100456#endif /* MBEDTLS_PSA_CRYPTO_C */