• 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 OR GPL-2.0-or-later
7  */
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"
16 #include "psa_crypto_random_impl.h"
17 #include "psa_crypto_hash.h"
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include "mbedtls/platform.h"
22 
23 #include <mbedtls/ecdsa.h>
24 #include <mbedtls/ecp.h>
25 #include <mbedtls/error.h>
26 
27 #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) || \
31     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)32 psa_status_t mbedtls_psa_ecp_load_representation(
33     psa_key_type_t type, size_t curve_bits,
34     const uint8_t *data, size_t data_length,
35     mbedtls_ecp_keypair **p_ecp)
36 {
37     mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
38     psa_status_t status;
39     mbedtls_ecp_keypair *ecp = NULL;
40     size_t curve_bytes = data_length;
41     int explicit_bits = (curve_bits != 0);
42 
43     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
44         PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
45         /* 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          */
51         if ((data_length & 1) == 0) {
52             return PSA_ERROR_INVALID_ARGUMENT;
53         }
54         curve_bytes = data_length / 2;
55 
56         /* Montgomery public keys are represented in compressed format, meaning
57          * their curve_bytes is equal to the amount of input. */
58 
59         /* Private keys are represented in uncompressed private random integer
60          * format, meaning their curve_bytes is equal to the amount of input. */
61     }
62 
63     if (explicit_bits) {
64         /* With an explicit bit-size, the data must have the matching length. */
65         if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
66             return PSA_ERROR_INVALID_ARGUMENT;
67         }
68     } else {
69         /* 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. */
72         curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
73     }
74 
75     /* Allocate and initialize a key representation. */
76     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);
81 
82     /* Load the group. */
83     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) {
86         /* 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;
93         goto exit;
94     }
95 
96     status = mbedtls_to_psa_error(
97         mbedtls_ecp_group_load(&ecp->grp, grp_id));
98     if (status != PSA_SUCCESS) {
99         goto exit;
100     }
101 
102     /* Load the key material. */
103     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
104         /* Load the public value. */
105         status = mbedtls_to_psa_error(
106             mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
107                                           data,
108                                           data_length));
109         if (status != PSA_SUCCESS) {
110             goto exit;
111         }
112 
113         /* Check that the point is on the curve. */
114         status = mbedtls_to_psa_error(
115             mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
116         if (status != PSA_SUCCESS) {
117             goto exit;
118         }
119     } else {
120         /* Load and validate the secret value. */
121         status = mbedtls_to_psa_error(
122             mbedtls_ecp_read_key(ecp->grp.id,
123                                  ecp,
124                                  data,
125                                  data_length));
126         if (status != PSA_SUCCESS) {
127             goto exit;
128         }
129     }
130 
131     *p_ecp = ecp;
132 exit:
133     if (status != PSA_SUCCESS) {
134         mbedtls_ecp_keypair_free(ecp);
135         mbedtls_free(ecp);
136     }
137 
138     return status;
139 }
140 #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) ||
144         * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
145 
146 #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
147     defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
148 
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)149 psa_status_t mbedtls_psa_ecp_import_key(
150     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,
153     size_t *key_buffer_length, size_t *bits)
154 {
155     psa_status_t status;
156     mbedtls_ecp_keypair *ecp = NULL;
157 
158     /* Parse input */
159     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) {
165         goto exit;
166     }
167 
168     if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) ==
169         PSA_ECC_FAMILY_MONTGOMERY) {
170         *bits = ecp->grp.nbits + 1;
171     } else {
172         *bits = ecp->grp.nbits;
173     }
174 
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. */
178     status = mbedtls_psa_ecp_export_key(attributes->core.type,
179                                         ecp,
180                                         key_buffer,
181                                         key_buffer_size,
182                                         key_buffer_length);
183 exit:
184     /* Always free the PK object (will also free contained ECP context) */
185     mbedtls_ecp_keypair_free(ecp);
186     mbedtls_free(ecp);
187 
188     return status;
189 }
190 
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)191 psa_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)
196 {
197     psa_status_t status;
198 
199     if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
200         /* Check whether the public part is loaded */
201         if (mbedtls_ecp_is_zero(&ecp->Q)) {
202             /* Calculate the public key */
203             status = mbedtls_to_psa_error(
204                 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             }
210         }
211 
212         status = mbedtls_to_psa_error(
213             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         }
221 
222         return status;
223     } else {
224         if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) {
225             return PSA_ERROR_BUFFER_TOO_SMALL;
226         }
227 
228         status = mbedtls_to_psa_error(
229             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         }
237 
238         return status;
239     }
240 }
241 
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)242 psa_status_t mbedtls_psa_ecp_export_public_key(
243     const psa_key_attributes_t *attributes,
244     const uint8_t *key_buffer, size_t key_buffer_size,
245     uint8_t *data, size_t data_size, size_t *data_length)
246 {
247     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
248     mbedtls_ecp_keypair *ecp = NULL;
249 
250     status = mbedtls_psa_ecp_load_representation(
251         attributes->core.type, attributes->core.bits,
252         key_buffer, key_buffer_size, &ecp);
253     if (status != PSA_SUCCESS) {
254         return status;
255     }
256 
257     status = mbedtls_psa_ecp_export_key(
258         PSA_KEY_TYPE_ECC_PUBLIC_KEY(
259             PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)),
260         ecp, data, data_size, data_length);
261 
262     mbedtls_ecp_keypair_free(ecp);
263     mbedtls_free(ecp);
264 
265     return status;
266 }
267 #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
268         * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
269 
270 #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)271 psa_status_t mbedtls_psa_ecp_generate_key(
272     const psa_key_attributes_t *attributes,
273     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
274 {
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(
279         attributes->core.type);
280     mbedtls_ecp_group_id grp_id =
281         mbedtls_ecc_group_of_psa(curve, attributes->core.bits, 0);
282 
283     const mbedtls_ecp_curve_info *curve_info =
284         mbedtls_ecp_curve_info_from_grp_id(grp_id);
285     mbedtls_ecp_keypair ecp;
286 
287     if (attributes->domain_parameters_size != 0) {
288         return PSA_ERROR_NOT_SUPPORTED;
289     }
290 
291     if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
292         return PSA_ERROR_NOT_SUPPORTED;
293     }
294 
295     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);
302     }
303 
304     status = mbedtls_to_psa_error(
305         mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size));
306 
307     mbedtls_ecp_keypair_free(&ecp);
308 
309     if (status == PSA_SUCCESS) {
310         *key_buffer_length = key_buffer_size;
311     }
312 
313     return status;
314 }
315 #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
316 
317 /****************************************************************/
318 /* ECDSA sign/verify */
319 /****************************************************************/
320 
321 #if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
322     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)323 psa_status_t mbedtls_psa_ecdsa_sign_hash(
324     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,
327     uint8_t *signature, size_t signature_size, size_t *signature_length)
328 {
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 
335     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     }
343 
344     curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
345     mbedtls_mpi_init(&r);
346     mbedtls_mpi_init(&s);
347 
348     if (signature_size < 2 * curve_bytes) {
349         ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
350         goto cleanup;
351     }
352 
353     if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
354 #if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
355         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));
364 #else
365         ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
366         goto cleanup;
367 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
368     } else {
369         (void) alg;
370         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));
374     }
375 
376     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));
382 cleanup:
383     mbedtls_mpi_free(&r);
384     mbedtls_mpi_free(&s);
385     if (ret == 0) {
386         *signature_length = 2 * curve_bytes;
387     }
388 
389     mbedtls_ecp_keypair_free(ecp);
390     mbedtls_free(ecp);
391 
392     return mbedtls_to_psa_error(ret);
393 }
394 
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)395 psa_status_t mbedtls_psa_ecdsa_verify_hash(
396     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,
399     const uint8_t *signature, size_t signature_length)
400 {
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 
407     (void) alg;
408 
409     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     }
417 
418     curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
419     mbedtls_mpi_init(&r);
420     mbedtls_mpi_init(&s);
421 
422     if (signature_length != 2 * curve_bytes) {
423         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
424         goto cleanup;
425     }
426 
427     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));
433 
434     /* Check whether the public part is loaded. If not, load it. */
435     if (mbedtls_ecp_is_zero(&ecp->Q)) {
436         MBEDTLS_MPI_CHK(
437             mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
438                             mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE));
439     }
440 
441     ret = mbedtls_ecdsa_verify(&ecp->grp, hash, hash_length,
442                                &ecp->Q, &r, &s);
443 
444 cleanup:
445     mbedtls_mpi_free(&r);
446     mbedtls_mpi_free(&s);
447     mbedtls_ecp_keypair_free(ecp);
448     mbedtls_free(ecp);
449 
450     return mbedtls_to_psa_error(ret);
451 }
452 
453 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
454         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
455 
456 #endif /* MBEDTLS_PSA_CRYPTO_C */
457