blob: 59c3a0e9af2792314cb5e07403e34655f491b2ad [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"
Ronald Cron00b7bfc2020-11-25 15:25:26 +010030
31#include <stdlib.h>
32#include <string.h>
33#include "mbedtls/platform.h"
34#if !defined(MBEDTLS_PLATFORM_C)
35#define mbedtls_calloc calloc
36#define mbedtls_free free
37#endif
38
Ronald Cron072722c2020-12-09 16:36:19 +010039#include <mbedtls/ecdsa.h>
Ronald Cron00b7bfc2020-11-25 15:25:26 +010040#include <mbedtls/ecp.h>
41#include <mbedtls/error.h>
42
Ronald Cron0266cfe2021-03-13 18:50:11 +010043#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
44 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
45 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
46 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +010047 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
Ronald Cron00b7bfc2020-11-25 15:25:26 +010048psa_status_t mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010049 psa_key_type_t type, size_t curve_bits,
50 const uint8_t *data, size_t data_length,
Ronald Cron00b7bfc2020-11-25 15:25:26 +010051 mbedtls_ecp_keypair **p_ecp )
52{
53 mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
54 psa_status_t status;
55 mbedtls_ecp_keypair *ecp = NULL;
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010056 size_t curve_bytes = data_length;
57 int explicit_bits = ( curve_bits != 0 );
Ronald Cron00b7bfc2020-11-25 15:25:26 +010058
59 if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
60 PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY )
61 {
62 /* A Weierstrass public key is represented as:
63 * - The byte 0x04;
64 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
65 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
66 * So its data length is 2m+1 where m is the curve size in bits.
67 */
68 if( ( data_length & 1 ) == 0 )
69 return( PSA_ERROR_INVALID_ARGUMENT );
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010070 curve_bytes = data_length / 2;
Ronald Cron00b7bfc2020-11-25 15:25:26 +010071
72 /* Montgomery public keys are represented in compressed format, meaning
Gilles Peskined88ccae2021-02-08 18:39:18 +010073 * their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010074
75 /* Private keys are represented in uncompressed private random integer
Gilles Peskined88ccae2021-02-08 18:39:18 +010076 * format, meaning their curve_bytes is equal to the amount of input. */
Ronald Cron00b7bfc2020-11-25 15:25:26 +010077 }
78
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +010079 if( explicit_bits )
80 {
81 /* With an explicit bit-size, the data must have the matching length. */
82 if( curve_bytes != PSA_BITS_TO_BYTES( curve_bits ) )
83 return( PSA_ERROR_INVALID_ARGUMENT );
84 }
85 else
86 {
87 /* We need to infer the bit-size from the data. Since the only
88 * information we have is the length in bytes, the value of curve_bits
89 * at this stage is rounded up to the nearest multiple of 8. */
90 curve_bits = PSA_BYTES_TO_BITS( curve_bytes );
91 }
92
Ronald Cron00b7bfc2020-11-25 15:25:26 +010093 /* Allocate and initialize a key representation. */
94 ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
95 if( ecp == NULL )
96 return( PSA_ERROR_INSUFFICIENT_MEMORY );
97 mbedtls_ecp_keypair_init( ecp );
98
99 /* Load the group. */
100 grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100101 curve_bits, !explicit_bits );
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100102 if( grp_id == MBEDTLS_ECP_DP_NONE )
103 {
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100104 /* We can't distinguish between a nonsensical family/size combination
105 * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a
106 * well-regarded curve that Mbed TLS just doesn't know about (which
107 * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how
108 * curves that Mbed TLS knows about but for which support is disabled
109 * at build time, return NOT_SUPPORTED. */
110 status = PSA_ERROR_NOT_SUPPORTED;
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100111 goto exit;
112 }
113
114 status = mbedtls_to_psa_error(
115 mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
116 if( status != PSA_SUCCESS )
117 goto exit;
118
119 /* Load the key material. */
120 if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
121 {
122 /* Load the public value. */
123 status = mbedtls_to_psa_error(
124 mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
125 data,
126 data_length ) );
127 if( status != PSA_SUCCESS )
128 goto exit;
129
130 /* Check that the point is on the curve. */
131 status = mbedtls_to_psa_error(
132 mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) );
133 if( status != PSA_SUCCESS )
134 goto exit;
135 }
136 else
137 {
138 /* Load and validate the secret value. */
139 status = mbedtls_to_psa_error(
140 mbedtls_ecp_read_key( ecp->grp.id,
141 ecp,
142 data,
143 data_length ) );
144 if( status != PSA_SUCCESS )
145 goto exit;
146 }
147
148 *p_ecp = ecp;
149exit:
150 if( status != PSA_SUCCESS )
151 {
152 mbedtls_ecp_keypair_free( ecp );
153 mbedtls_free( ecp );
154 }
155
156 return( status );
157}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100158#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
159 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
160 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
161 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
Ronald Cronb5399a82020-12-10 09:35:33 +0100162 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100163
Ronald Cron0266cfe2021-03-13 18:50:11 +0100164#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
165 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
Ronald Crond6ec3032020-11-27 18:54:57 +0100166
Ronald Cron0266cfe2021-03-13 18:50:11 +0100167psa_status_t mbedtls_psa_ecp_import_key(
Ronald Crond6ec3032020-11-27 18:54:57 +0100168 const psa_key_attributes_t *attributes,
169 const uint8_t *data, size_t data_length,
170 uint8_t *key_buffer, size_t key_buffer_size,
171 size_t *key_buffer_length, size_t *bits )
172{
173 psa_status_t status;
174 mbedtls_ecp_keypair *ecp = NULL;
175
176 /* Parse input */
177 status = mbedtls_psa_ecp_load_representation( attributes->core.type,
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100178 attributes->core.bits,
Ronald Crond6ec3032020-11-27 18:54:57 +0100179 data,
180 data_length,
181 &ecp );
182 if( status != PSA_SUCCESS )
183 goto exit;
184
185 if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ==
186 PSA_ECC_FAMILY_MONTGOMERY )
187 *bits = ecp->grp.nbits + 1;
188 else
189 *bits = ecp->grp.nbits;
190
191 /* Re-export the data to PSA export format. There is currently no support
192 * for other input formats then the export format, so this is a 1-1
193 * copy operation. */
194 status = mbedtls_psa_ecp_export_key( attributes->core.type,
195 ecp,
196 key_buffer,
197 key_buffer_size,
198 key_buffer_length );
199exit:
200 /* Always free the PK object (will also free contained ECP context) */
201 mbedtls_ecp_keypair_free( ecp );
202 mbedtls_free( ecp );
203
204 return( status );
205}
206
Ronald Crone5ca3d82020-11-26 16:36:16 +0100207psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type,
208 mbedtls_ecp_keypair *ecp,
209 uint8_t *data,
210 size_t data_size,
211 size_t *data_length )
212{
213 psa_status_t status;
214
215 if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
216 {
217 /* Check whether the public part is loaded */
218 if( mbedtls_ecp_is_zero( &ecp->Q ) )
219 {
220 /* Calculate the public key */
221 status = mbedtls_to_psa_error(
222 mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
223 mbedtls_psa_get_random,
224 MBEDTLS_PSA_RANDOM_STATE ) );
225 if( status != PSA_SUCCESS )
226 return( status );
227 }
228
229 status = mbedtls_to_psa_error(
230 mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q,
231 MBEDTLS_ECP_PF_UNCOMPRESSED,
232 data_length,
233 data,
234 data_size ) );
235 if( status != PSA_SUCCESS )
236 memset( data, 0, data_size );
237
238 return( status );
239 }
240 else
241 {
242 if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) )
243 return( PSA_ERROR_BUFFER_TOO_SMALL );
244
245 status = mbedtls_to_psa_error(
246 mbedtls_ecp_write_key( ecp,
247 data,
248 PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) );
249 if( status == PSA_SUCCESS )
250 *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits );
251 else
252 memset( data, 0, data_size );
253
254 return( status );
255 }
256}
257
Ronald Cron0266cfe2021-03-13 18:50:11 +0100258psa_status_t mbedtls_psa_ecp_export_public_key(
Ronald Crone5ca3d82020-11-26 16:36:16 +0100259 const psa_key_attributes_t *attributes,
260 const uint8_t *key_buffer, size_t key_buffer_size,
261 uint8_t *data, size_t data_size, size_t *data_length )
262{
263 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
264 mbedtls_ecp_keypair *ecp = NULL;
265
266 status = mbedtls_psa_ecp_load_representation(
Gilles Peskine2fa6b5f2021-01-27 15:44:45 +0100267 attributes->core.type, attributes->core.bits,
268 key_buffer, key_buffer_size, &ecp );
Ronald Crone5ca3d82020-11-26 16:36:16 +0100269 if( status != PSA_SUCCESS )
270 return( status );
271
272 status = mbedtls_psa_ecp_export_key(
273 PSA_KEY_TYPE_ECC_PUBLIC_KEY(
274 PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ),
275 ecp, data, data_size, data_length );
276
277 mbedtls_ecp_keypair_free( ecp );
278 mbedtls_free( ecp );
279
280 return( status );
281}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100282#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
283 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
Ronald Cronf1057d32020-11-26 19:19:10 +0100284
Ronald Cron0266cfe2021-03-13 18:50:11 +0100285#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
286psa_status_t mbedtls_psa_ecp_generate_key(
Ronald Cron7023db52020-11-20 18:17:42 +0100287 const psa_key_attributes_t *attributes,
288 uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
289{
290 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
292
293 psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
294 attributes->core.type );
295 mbedtls_ecp_group_id grp_id =
296 mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 );
297
298 const mbedtls_ecp_curve_info *curve_info =
299 mbedtls_ecp_curve_info_from_grp_id( grp_id );
300 mbedtls_ecp_keypair ecp;
301
302 if( attributes->domain_parameters_size != 0 )
303 return( PSA_ERROR_NOT_SUPPORTED );
304
305 if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
306 return( PSA_ERROR_NOT_SUPPORTED );
307
308 mbedtls_ecp_keypair_init( &ecp );
309 ret = mbedtls_ecp_gen_key( grp_id, &ecp,
310 mbedtls_psa_get_random,
311 MBEDTLS_PSA_RANDOM_STATE );
312 if( ret != 0 )
313 {
314 mbedtls_ecp_keypair_free( &ecp );
315 return( mbedtls_to_psa_error( ret ) );
316 }
317
318 status = mbedtls_to_psa_error(
319 mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) );
320
321 mbedtls_ecp_keypair_free( &ecp );
322
323 if( status == PSA_SUCCESS )
324 *key_buffer_length = key_buffer_size;
325
326 return( status );
327}
Ronald Cron0266cfe2021-03-13 18:50:11 +0100328#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
Ronald Cron7023db52020-11-20 18:17:42 +0100329
Ronald Cron072722c2020-12-09 16:36:19 +0100330/****************************************************************/
331/* ECDSA sign/verify */
332/****************************************************************/
333
Ronald Cron0266cfe2021-03-13 18:50:11 +0100334#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
335 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
336psa_status_t mbedtls_psa_ecdsa_sign_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100337 const psa_key_attributes_t *attributes,
338 const uint8_t *key_buffer, size_t key_buffer_size,
339 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
340 uint8_t *signature, size_t signature_size, size_t *signature_length )
341{
342 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
343 mbedtls_ecp_keypair *ecp = NULL;
344 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
345 size_t curve_bytes;
346 mbedtls_mpi r, s;
347
348 status = mbedtls_psa_ecp_load_representation( attributes->core.type,
349 attributes->core.bits,
350 key_buffer,
351 key_buffer_size,
352 &ecp );
353 if( status != PSA_SUCCESS )
354 return( status );
355
356 curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
357 mbedtls_mpi_init( &r );
358 mbedtls_mpi_init( &s );
359
360 if( signature_size < 2 * curve_bytes )
361 {
362 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
363 goto cleanup;
364 }
365
Ronald Cron9103d492021-03-04 11:26:03 +0100366 if( PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) )
Ronald Cron072722c2020-12-09 16:36:19 +0100367 {
Ronald Cron0266cfe2021-03-13 18:50:11 +0100368#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
Ronald Cron072722c2020-12-09 16:36:19 +0100369 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
Manuel Pégourié-Gonnardd82a9ed2022-07-18 15:21:37 +0200370 mbedtls_md_type_t md_alg = mbedtls_hash_info_md_from_psa( hash_alg );
Ronald Cron072722c2020-12-09 16:36:19 +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
Ronald Cronbb9cbc72021-03-04 17:09:00 +0100378 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Ronald Cron9103d492021-03-04 11:26:03 +0100379 goto cleanup;
Ronald Cron0266cfe2021-03-13 18:50:11 +0100380#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
Ronald Cron072722c2020-12-09 16:36:19 +0100381 }
382 else
Ronald Cron072722c2020-12-09 16:36:19 +0100383 {
384 (void) alg;
385 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
386 hash, hash_length,
387 mbedtls_psa_get_random,
388 MBEDTLS_PSA_RANDOM_STATE ) );
389 }
390
391 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
392 signature,
393 curve_bytes ) );
394 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
395 signature + curve_bytes,
396 curve_bytes ) );
397cleanup:
398 mbedtls_mpi_free( &r );
399 mbedtls_mpi_free( &s );
400 if( ret == 0 )
401 *signature_length = 2 * curve_bytes;
402
403 mbedtls_ecp_keypair_free( ecp );
404 mbedtls_free( ecp );
405
406 return( mbedtls_to_psa_error( ret ) );
407}
408
Ronald Cron0266cfe2021-03-13 18:50:11 +0100409psa_status_t mbedtls_psa_ecdsa_verify_hash(
Ronald Cron072722c2020-12-09 16:36:19 +0100410 const psa_key_attributes_t *attributes,
411 const uint8_t *key_buffer, size_t key_buffer_size,
412 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
413 const uint8_t *signature, size_t signature_length )
414{
415 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
416 mbedtls_ecp_keypair *ecp = NULL;
417 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
418 size_t curve_bytes;
419 mbedtls_mpi r, s;
420
421 (void)alg;
422
423 status = mbedtls_psa_ecp_load_representation( attributes->core.type,
424 attributes->core.bits,
425 key_buffer,
426 key_buffer_size,
427 &ecp );
428 if( status != PSA_SUCCESS )
429 return( status );
430
431 curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
432 mbedtls_mpi_init( &r );
433 mbedtls_mpi_init( &s );
434
435 if( signature_length != 2 * curve_bytes )
436 {
437 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
438 goto cleanup;
439 }
440
441 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
442 signature,
443 curve_bytes ) );
444 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
445 signature + curve_bytes,
446 curve_bytes ) );
447
448 /* Check whether the public part is loaded. If not, load it. */
449 if( mbedtls_ecp_is_zero( &ecp->Q ) )
450 {
451 MBEDTLS_MPI_CHK(
452 mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
453 mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
454 }
455
456 ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
457 &ecp->Q, &r, &s );
458
459cleanup:
460 mbedtls_mpi_free( &r );
461 mbedtls_mpi_free( &s );
462 mbedtls_ecp_keypair_free( ecp );
463 mbedtls_free( ecp );
464
465 return( mbedtls_to_psa_error( ret ) );
466}
467
Ronald Cron0266cfe2021-03-13 18:50:11 +0100468#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
Ronald Cronb5399a82020-12-10 09:35:33 +0100469 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
470
Ronald Cron00b7bfc2020-11-25 15:25:26 +0100471#endif /* MBEDTLS_PSA_CRYPTO_C */