1 /*
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"
28 #include "psa_crypto_random_impl.h"
29 #include "psa_crypto_hash.h"
30
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
39 #include <mbedtls/ecdsa.h>
40 #include <mbedtls/ecp.h>
41 #include <mbedtls/error.h>
42
43 #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) || \
47 defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
mbedtls_psa_ecp_load_representation(psa_key_type_t type,size_t curve_bits,const uint8_t * data,size_t data_length,mbedtls_ecp_keypair ** p_ecp)48 psa_status_t mbedtls_psa_ecp_load_representation(
49 psa_key_type_t type, size_t curve_bits,
50 const uint8_t *data, size_t data_length,
51 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;
56 size_t curve_bytes = data_length;
57 int explicit_bits = ( curve_bits != 0 );
58
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 );
70 curve_bytes = data_length / 2;
71
72 /* Montgomery public keys are represented in compressed format, meaning
73 * their curve_bytes is equal to the amount of input. */
74
75 /* Private keys are represented in uncompressed private random integer
76 * format, meaning their curve_bytes is equal to the amount of input. */
77 }
78
79 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
93 /* 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 ),
101 curve_bits, !explicit_bits );
102 if( grp_id == MBEDTLS_ECP_DP_NONE )
103 {
104 /* 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;
111 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;
149 exit:
150 if( status != PSA_SUCCESS )
151 {
152 mbedtls_ecp_keypair_free( ecp );
153 mbedtls_free( ecp );
154 }
155
156 return( status );
157 }
158 #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) ||
162 * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
163
164 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
165 defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
166
mbedtls_psa_ecp_import_key(const psa_key_attributes_t * attributes,const uint8_t * data,size_t data_length,uint8_t * key_buffer,size_t key_buffer_size,size_t * key_buffer_length,size_t * bits)167 psa_status_t mbedtls_psa_ecp_import_key(
168 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,
178 attributes->core.bits,
179 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 );
199 exit:
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
mbedtls_psa_ecp_export_key(psa_key_type_t type,mbedtls_ecp_keypair * ecp,uint8_t * data,size_t data_size,size_t * data_length)207 psa_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
mbedtls_psa_ecp_export_public_key(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,uint8_t * data,size_t data_size,size_t * data_length)258 psa_status_t mbedtls_psa_ecp_export_public_key(
259 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(
267 attributes->core.type, attributes->core.bits,
268 key_buffer, key_buffer_size, &ecp );
269 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 }
282 #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
283 * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
284
285 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
mbedtls_psa_ecp_generate_key(const psa_key_attributes_t * attributes,uint8_t * key_buffer,size_t key_buffer_size,size_t * key_buffer_length)286 psa_status_t mbedtls_psa_ecp_generate_key(
287 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 }
328 #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
329
330 /****************************************************************/
331 /* ECDSA sign/verify */
332 /****************************************************************/
333
334 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
335 defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
mbedtls_psa_ecdsa_sign_hash(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * hash,size_t hash_length,uint8_t * signature,size_t signature_size,size_t * signature_length)336 psa_status_t mbedtls_psa_ecdsa_sign_hash(
337 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
366 if( PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) )
367 {
368 #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
369 psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
370 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg );
371 mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
372 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext(
373 &ecp->grp, &r, &s,
374 &ecp->d, hash,
375 hash_length, md_alg,
376 mbedtls_psa_get_random,
377 MBEDTLS_PSA_RANDOM_STATE ) );
378 #else
379 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
380 goto cleanup;
381 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
382 }
383 else
384 {
385 (void) alg;
386 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
387 hash, hash_length,
388 mbedtls_psa_get_random,
389 MBEDTLS_PSA_RANDOM_STATE ) );
390 }
391
392 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
393 signature,
394 curve_bytes ) );
395 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
396 signature + curve_bytes,
397 curve_bytes ) );
398 cleanup:
399 mbedtls_mpi_free( &r );
400 mbedtls_mpi_free( &s );
401 if( ret == 0 )
402 *signature_length = 2 * curve_bytes;
403
404 mbedtls_ecp_keypair_free( ecp );
405 mbedtls_free( ecp );
406
407 return( mbedtls_to_psa_error( ret ) );
408 }
409
mbedtls_psa_ecdsa_verify_hash(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * hash,size_t hash_length,const uint8_t * signature,size_t signature_length)410 psa_status_t mbedtls_psa_ecdsa_verify_hash(
411 const psa_key_attributes_t *attributes,
412 const uint8_t *key_buffer, size_t key_buffer_size,
413 psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
414 const uint8_t *signature, size_t signature_length )
415 {
416 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
417 mbedtls_ecp_keypair *ecp = NULL;
418 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
419 size_t curve_bytes;
420 mbedtls_mpi r, s;
421
422 (void)alg;
423
424 status = mbedtls_psa_ecp_load_representation( attributes->core.type,
425 attributes->core.bits,
426 key_buffer,
427 key_buffer_size,
428 &ecp );
429 if( status != PSA_SUCCESS )
430 return( status );
431
432 curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
433 mbedtls_mpi_init( &r );
434 mbedtls_mpi_init( &s );
435
436 if( signature_length != 2 * curve_bytes )
437 {
438 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
439 goto cleanup;
440 }
441
442 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
443 signature,
444 curve_bytes ) );
445 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
446 signature + curve_bytes,
447 curve_bytes ) );
448
449 /* Check whether the public part is loaded. If not, load it. */
450 if( mbedtls_ecp_is_zero( &ecp->Q ) )
451 {
452 MBEDTLS_MPI_CHK(
453 mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
454 mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) );
455 }
456
457 ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
458 &ecp->Q, &r, &s );
459
460 cleanup:
461 mbedtls_mpi_free( &r );
462 mbedtls_mpi_free( &s );
463 mbedtls_ecp_keypair_free( ecp );
464 mbedtls_free( ecp );
465
466 return( mbedtls_to_psa_error( ret ) );
467 }
468
469 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
470 * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
471
472 #endif /* MBEDTLS_PSA_CRYPTO_C */
473