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