Branch data Line data Source code
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)
48 : 32 : 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 : 32 : mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
54 : 32 : psa_status_t status;
55 : 32 : mbedtls_ecp_keypair *ecp = NULL;
56 : 32 : size_t curve_bytes = data_length;
57 : 32 : int explicit_bits = ( curve_bits != 0 );
58 : :
59 [ + + ]: 32 : if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
60 [ + - + - ]: 16 : 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 [ + - ]: 16 : if( ( data_length & 1 ) == 0 )
69 : : return( PSA_ERROR_INVALID_ARGUMENT );
70 : 16 : 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 [ + + ]: 32 : if( explicit_bits )
80 : : {
81 : : /* With an explicit bit-size, the data must have the matching length. */
82 [ + - ]: 28 : 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 : 4 : curve_bits = PSA_BYTES_TO_BITS( curve_bytes );
91 : : }
92 : :
93 : : /* Allocate and initialize a key representation. */
94 : 32 : ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
95 [ + - ]: 32 : if( ecp == NULL )
96 : : return( PSA_ERROR_INSUFFICIENT_MEMORY );
97 : 32 : mbedtls_ecp_keypair_init( ecp );
98 : :
99 : : /* Load the group. */
100 [ + - ]: 32 : grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ),
101 : : curve_bits, !explicit_bits );
102 [ - + ]: 32 : 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 : 0 : status = PSA_ERROR_NOT_SUPPORTED;
111 : 0 : goto exit;
112 : : }
113 : :
114 : 32 : status = mbedtls_to_psa_error(
115 : : mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
116 [ - + ]: 32 : if( status != PSA_SUCCESS )
117 : 0 : goto exit;
118 : :
119 : : /* Load the key material. */
120 [ + + ]: 32 : if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
121 : : {
122 : : /* Load the public value. */
123 : 16 : status = mbedtls_to_psa_error(
124 : : mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
125 : : data,
126 : : data_length ) );
127 [ - + ]: 16 : if( status != PSA_SUCCESS )
128 : 0 : goto exit;
129 : :
130 : : /* Check that the point is on the curve. */
131 : 16 : status = mbedtls_to_psa_error(
132 : : mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) );
133 [ - + ]: 16 : if( status != PSA_SUCCESS )
134 : 0 : goto exit;
135 : : }
136 : : else
137 : : {
138 : : /* Load and validate the secret value. */
139 : 16 : status = mbedtls_to_psa_error(
140 : : mbedtls_ecp_read_key( ecp->grp.id,
141 : : ecp,
142 : : data,
143 : : data_length ) );
144 [ - + ]: 16 : if( status != PSA_SUCCESS )
145 : 0 : goto exit;
146 : : }
147 : :
148 : 32 : *p_ecp = ecp;
149 : 32 : exit:
150 [ - + ]: 32 : if( status != PSA_SUCCESS )
151 : : {
152 : 0 : mbedtls_ecp_keypair_free( ecp );
153 : 0 : 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 : :
167 : 14 : 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 : 14 : psa_status_t status;
174 : 14 : mbedtls_ecp_keypair *ecp = NULL;
175 : :
176 : : /* Parse input */
177 : 28 : status = mbedtls_psa_ecp_load_representation( attributes->core.type,
178 : 14 : attributes->core.bits,
179 : : data,
180 : : data_length,
181 : : &ecp );
182 [ - + ]: 14 : if( status != PSA_SUCCESS )
183 : 0 : goto exit;
184 : :
185 [ + - - + ]: 14 : if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ==
186 : : PSA_ECC_FAMILY_MONTGOMERY )
187 : 0 : *bits = ecp->grp.nbits + 1;
188 : : else
189 : 14 : *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 : 14 : status = mbedtls_psa_ecp_export_key( attributes->core.type,
195 : : ecp,
196 : : key_buffer,
197 : : key_buffer_size,
198 : : key_buffer_length );
199 : 14 : exit:
200 : : /* Always free the PK object (will also free contained ECP context) */
201 : 14 : mbedtls_ecp_keypair_free( ecp );
202 : 14 : mbedtls_free( ecp );
203 : :
204 : 14 : return( status );
205 : : }
206 : :
207 : 14 : 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 : 14 : psa_status_t status;
214 : :
215 [ + + ]: 14 : if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
216 : : {
217 : : /* Check whether the public part is loaded */
218 [ - + ]: 6 : if( mbedtls_ecp_is_zero( &ecp->Q ) )
219 : : {
220 : : /* Calculate the public key */
221 : 0 : status = mbedtls_to_psa_error(
222 : 0 : mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
223 : : mbedtls_psa_get_random,
224 : : MBEDTLS_PSA_RANDOM_STATE ) );
225 [ # # ]: 0 : if( status != PSA_SUCCESS )
226 : : return( status );
227 : : }
228 : :
229 : 6 : status = mbedtls_to_psa_error(
230 : 6 : mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q,
231 : : MBEDTLS_ECP_PF_UNCOMPRESSED,
232 : : data_length,
233 : : data,
234 : : data_size ) );
235 [ - + ]: 6 : if( status != PSA_SUCCESS )
236 : 0 : memset( data, 0, data_size );
237 : :
238 : 6 : return( status );
239 : : }
240 : : else
241 : : {
242 [ + - ]: 8 : if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) )
243 : : return( PSA_ERROR_BUFFER_TOO_SMALL );
244 : :
245 : 8 : status = mbedtls_to_psa_error(
246 : : mbedtls_ecp_write_key( ecp,
247 : : data,
248 : : PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) );
249 [ + - ]: 8 : if( status == PSA_SUCCESS )
250 : 8 : *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits );
251 : : else
252 : 0 : memset( data, 0, data_size );
253 : :
254 : 8 : return( status );
255 : : }
256 : : }
257 : :
258 : 0 : 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 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
264 : 0 : mbedtls_ecp_keypair *ecp = NULL;
265 : :
266 : 0 : status = mbedtls_psa_ecp_load_representation(
267 : 0 : attributes->core.type, attributes->core.bits,
268 : : key_buffer, key_buffer_size, &ecp );
269 [ # # ]: 0 : if( status != PSA_SUCCESS )
270 : : return( status );
271 : :
272 : 0 : status = mbedtls_psa_ecp_export_key(
273 [ # # ]: 0 : 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 : 0 : mbedtls_ecp_keypair_free( ecp );
278 : 0 : mbedtls_free( ecp );
279 : :
280 : 0 : 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)
286 : 0 : 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 : 0 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
291 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
292 : :
293 [ # # ]: 0 : psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
294 : : attributes->core.type );
295 : 0 : mbedtls_ecp_group_id grp_id =
296 : 0 : mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 );
297 : :
298 : 0 : const mbedtls_ecp_curve_info *curve_info =
299 : 0 : mbedtls_ecp_curve_info_from_grp_id( grp_id );
300 : 0 : mbedtls_ecp_keypair ecp;
301 : :
302 [ # # ]: 0 : if( attributes->domain_parameters_size != 0 )
303 : : return( PSA_ERROR_NOT_SUPPORTED );
304 : :
305 [ # # ]: 0 : if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
306 : : return( PSA_ERROR_NOT_SUPPORTED );
307 : :
308 : 0 : mbedtls_ecp_keypair_init( &ecp );
309 : 0 : ret = mbedtls_ecp_gen_key( grp_id, &ecp,
310 : : mbedtls_psa_get_random,
311 : : MBEDTLS_PSA_RANDOM_STATE );
312 [ # # ]: 0 : if( ret != 0 )
313 : : {
314 : 0 : mbedtls_ecp_keypair_free( &ecp );
315 : 0 : return( mbedtls_to_psa_error( ret ) );
316 : : }
317 : :
318 : 0 : status = mbedtls_to_psa_error(
319 : : mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) );
320 : :
321 : 0 : mbedtls_ecp_keypair_free( &ecp );
322 : :
323 [ # # ]: 0 : if( status == PSA_SUCCESS )
324 : 0 : *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)
336 : 4 : 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 : 4 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
343 : 4 : mbedtls_ecp_keypair *ecp = NULL;
344 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
345 : 4 : size_t curve_bytes;
346 : 4 : mbedtls_mpi r, s;
347 : :
348 : 8 : status = mbedtls_psa_ecp_load_representation( attributes->core.type,
349 : 4 : attributes->core.bits,
350 : : key_buffer,
351 : : key_buffer_size,
352 : : &ecp );
353 [ + - ]: 4 : if( status != PSA_SUCCESS )
354 : : return( status );
355 : :
356 : 4 : curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
357 : 4 : mbedtls_mpi_init( &r );
358 : 4 : mbedtls_mpi_init( &s );
359 : :
360 [ - + ]: 4 : if( signature_size < 2 * curve_bytes )
361 : : {
362 : 0 : ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
363 : 0 : goto cleanup;
364 : : }
365 : :
366 [ - + ]: 4 : 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 : 0 : ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
380 : 0 : goto cleanup;
381 : : #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
382 : : }
383 : : else
384 : : {
385 : 4 : (void) alg;
386 [ - + ]: 4 : 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 [ - + ]: 4 : MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
393 : : signature,
394 : : curve_bytes ) );
395 [ + - ]: 4 : MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
396 : : signature + curve_bytes,
397 : : curve_bytes ) );
398 : 4 : cleanup:
399 : 4 : mbedtls_mpi_free( &r );
400 : 4 : mbedtls_mpi_free( &s );
401 [ + - ]: 4 : if( ret == 0 )
402 : 4 : *signature_length = 2 * curve_bytes;
403 : :
404 : 4 : mbedtls_ecp_keypair_free( ecp );
405 : 4 : mbedtls_free( ecp );
406 : :
407 : 4 : return( mbedtls_to_psa_error( ret ) );
408 : : }
409 : :
410 : 6 : 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 : 6 : psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
417 : 6 : mbedtls_ecp_keypair *ecp = NULL;
418 : 6 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
419 : 6 : size_t curve_bytes;
420 : 6 : mbedtls_mpi r, s;
421 : :
422 : 6 : (void)alg;
423 : :
424 : 12 : status = mbedtls_psa_ecp_load_representation( attributes->core.type,
425 : 6 : attributes->core.bits,
426 : : key_buffer,
427 : : key_buffer_size,
428 : : &ecp );
429 [ + - ]: 6 : if( status != PSA_SUCCESS )
430 : : return( status );
431 : :
432 : 6 : curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
433 : 6 : mbedtls_mpi_init( &r );
434 : 6 : mbedtls_mpi_init( &s );
435 : :
436 [ - + ]: 6 : if( signature_length != 2 * curve_bytes )
437 : : {
438 : 0 : ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
439 : 0 : goto cleanup;
440 : : }
441 : :
442 [ - + ]: 6 : MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
443 : : signature,
444 : : curve_bytes ) );
445 [ - + ]: 6 : 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 [ - + ]: 6 : if( mbedtls_ecp_is_zero( &ecp->Q ) )
451 : : {
452 [ # # ]: 0 : 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 : 6 : ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length,
458 : : &ecp->Q, &r, &s );
459 : :
460 : 6 : cleanup:
461 : 6 : mbedtls_mpi_free( &r );
462 : 6 : mbedtls_mpi_free( &s );
463 : 6 : mbedtls_ecp_keypair_free( ecp );
464 : 6 : mbedtls_free( ecp );
465 : :
466 : 6 : 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 */
|