• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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