1 | /* |
2 | * Public Key abstraction layer: wrapper functions |
3 | * |
4 | * Copyright The Mbed TLS Contributors |
5 | * SPDX-License-Identifier: Apache-2.0 |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
8 | * not use this file except in compliance with the License. |
9 | * You may obtain a copy of the License at |
10 | * |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | * |
13 | * Unless required by applicable law or agreed to in writing, software |
14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | * See the License for the specific language governing permissions and |
17 | * limitations under the License. |
18 | */ |
19 | |
20 | #include "common.h" |
21 | |
22 | #if defined(MBEDTLS_PK_C) |
23 | #include "mbedtls/pk_internal.h" |
24 | #include "mbedtls/error.h" |
25 | |
26 | /* Even if RSA not activated, for the sake of RSA-alt */ |
27 | #include "mbedtls/rsa.h" |
28 | |
29 | #include <string.h> |
30 | |
31 | #if defined(MBEDTLS_ECP_C) |
32 | #include "mbedtls/ecp.h" |
33 | #endif |
34 | |
35 | #if defined(MBEDTLS_ECDSA_C) |
36 | #include "mbedtls/ecdsa.h" |
37 | #endif |
38 | |
39 | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
40 | #include "mbedtls/asn1write.h" |
41 | #endif |
42 | |
43 | #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
44 | #include "mbedtls/platform_util.h" |
45 | #endif |
46 | |
47 | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
48 | #include "psa/crypto.h" |
49 | #include "mbedtls/psa_util.h" |
50 | #include "mbedtls/asn1.h" |
51 | #endif |
52 | |
53 | #include "mbedtls/platform.h" |
54 | |
55 | #include <limits.h> |
56 | #include <stdint.h> |
57 | |
58 | #if defined(MBEDTLS_RSA_C) |
59 | static int rsa_can_do(mbedtls_pk_type_t type) |
60 | { |
61 | return type == MBEDTLS_PK_RSA || |
62 | type == MBEDTLS_PK_RSASSA_PSS; |
63 | } |
64 | |
65 | static size_t rsa_get_bitlen(const void *ctx) |
66 | { |
67 | const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx; |
68 | return 8 * mbedtls_rsa_get_len(rsa); |
69 | } |
70 | |
71 | static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, |
72 | const unsigned char *hash, size_t hash_len, |
73 | const unsigned char *sig, size_t sig_len) |
74 | { |
75 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
76 | mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; |
77 | size_t rsa_len = mbedtls_rsa_get_len(rsa); |
78 | |
79 | #if SIZE_MAX > UINT_MAX |
80 | if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { |
81 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
82 | } |
83 | #endif /* SIZE_MAX > UINT_MAX */ |
84 | |
85 | if (sig_len < rsa_len) { |
86 | return MBEDTLS_ERR_RSA_VERIFY_FAILED; |
87 | } |
88 | |
89 | if ((ret = mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, |
90 | MBEDTLS_RSA_PUBLIC, md_alg, |
91 | (unsigned int) hash_len, hash, sig)) != 0) { |
92 | return ret; |
93 | } |
94 | |
95 | /* The buffer contains a valid signature followed by extra data. |
96 | * We have a special error code for that so that so that callers can |
97 | * use mbedtls_pk_verify() to check "Does the buffer start with a |
98 | * valid signature?" and not just "Does the buffer contain a valid |
99 | * signature?". */ |
100 | if (sig_len > rsa_len) { |
101 | return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; |
102 | } |
103 | |
104 | return 0; |
105 | } |
106 | |
107 | static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
108 | const unsigned char *hash, size_t hash_len, |
109 | unsigned char *sig, size_t *sig_len, |
110 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
111 | { |
112 | mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; |
113 | |
114 | #if SIZE_MAX > UINT_MAX |
115 | if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { |
116 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
117 | } |
118 | #endif /* SIZE_MAX > UINT_MAX */ |
119 | |
120 | *sig_len = mbedtls_rsa_get_len(rsa); |
121 | |
122 | return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, |
123 | md_alg, (unsigned int) hash_len, hash, sig); |
124 | } |
125 | |
126 | static int rsa_decrypt_wrap(void *ctx, |
127 | const unsigned char *input, size_t ilen, |
128 | unsigned char *output, size_t *olen, size_t osize, |
129 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
130 | { |
131 | mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; |
132 | |
133 | if (ilen != mbedtls_rsa_get_len(rsa)) { |
134 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
135 | } |
136 | |
137 | return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, |
138 | MBEDTLS_RSA_PRIVATE, olen, input, output, osize); |
139 | } |
140 | |
141 | static int rsa_encrypt_wrap(void *ctx, |
142 | const unsigned char *input, size_t ilen, |
143 | unsigned char *output, size_t *olen, size_t osize, |
144 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
145 | { |
146 | mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx; |
147 | *olen = mbedtls_rsa_get_len(rsa); |
148 | |
149 | if (*olen > osize) { |
150 | return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; |
151 | } |
152 | |
153 | return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, |
154 | ilen, input, output); |
155 | } |
156 | |
157 | static int rsa_check_pair_wrap(const void *pub, const void *prv) |
158 | { |
159 | return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub, |
160 | (const mbedtls_rsa_context *) prv); |
161 | } |
162 | |
163 | static void *rsa_alloc_wrap(void) |
164 | { |
165 | void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); |
166 | |
167 | if (ctx != NULL) { |
168 | mbedtls_rsa_init((mbedtls_rsa_context *) ctx, 0, 0); |
169 | } |
170 | |
171 | return ctx; |
172 | } |
173 | |
174 | static void rsa_free_wrap(void *ctx) |
175 | { |
176 | mbedtls_rsa_free((mbedtls_rsa_context *) ctx); |
177 | mbedtls_free(ctx); |
178 | } |
179 | |
180 | static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items) |
181 | { |
182 | items->type = MBEDTLS_PK_DEBUG_MPI; |
183 | items->name = "rsa.N" ; |
184 | items->value = &(((mbedtls_rsa_context *) ctx)->N); |
185 | |
186 | items++; |
187 | |
188 | items->type = MBEDTLS_PK_DEBUG_MPI; |
189 | items->name = "rsa.E" ; |
190 | items->value = &(((mbedtls_rsa_context *) ctx)->E); |
191 | } |
192 | |
193 | const mbedtls_pk_info_t mbedtls_rsa_info = { |
194 | MBEDTLS_PK_RSA, |
195 | "RSA" , |
196 | rsa_get_bitlen, |
197 | rsa_can_do, |
198 | rsa_verify_wrap, |
199 | rsa_sign_wrap, |
200 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
201 | NULL, |
202 | NULL, |
203 | #endif |
204 | rsa_decrypt_wrap, |
205 | rsa_encrypt_wrap, |
206 | rsa_check_pair_wrap, |
207 | rsa_alloc_wrap, |
208 | rsa_free_wrap, |
209 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
210 | NULL, |
211 | NULL, |
212 | #endif |
213 | rsa_debug, |
214 | }; |
215 | #endif /* MBEDTLS_RSA_C */ |
216 | |
217 | #if defined(MBEDTLS_ECP_C) |
218 | /* |
219 | * Generic EC key |
220 | */ |
221 | static int eckey_can_do(mbedtls_pk_type_t type) |
222 | { |
223 | return type == MBEDTLS_PK_ECKEY || |
224 | type == MBEDTLS_PK_ECKEY_DH || |
225 | type == MBEDTLS_PK_ECDSA; |
226 | } |
227 | |
228 | static size_t eckey_get_bitlen(const void *ctx) |
229 | { |
230 | return ((mbedtls_ecp_keypair *) ctx)->grp.pbits; |
231 | } |
232 | |
233 | #if defined(MBEDTLS_ECDSA_C) |
234 | /* Forward declarations */ |
235 | static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, |
236 | const unsigned char *hash, size_t hash_len, |
237 | const unsigned char *sig, size_t sig_len); |
238 | |
239 | static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
240 | const unsigned char *hash, size_t hash_len, |
241 | unsigned char *sig, size_t *sig_len, |
242 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); |
243 | |
244 | static int eckey_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, |
245 | const unsigned char *hash, size_t hash_len, |
246 | const unsigned char *sig, size_t sig_len) |
247 | { |
248 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
249 | mbedtls_ecdsa_context ecdsa; |
250 | |
251 | mbedtls_ecdsa_init(&ecdsa); |
252 | |
253 | if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) { |
254 | ret = ecdsa_verify_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len); |
255 | } |
256 | |
257 | mbedtls_ecdsa_free(&ecdsa); |
258 | |
259 | return ret; |
260 | } |
261 | |
262 | static int eckey_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
263 | const unsigned char *hash, size_t hash_len, |
264 | unsigned char *sig, size_t *sig_len, |
265 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
266 | { |
267 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
268 | mbedtls_ecdsa_context ecdsa; |
269 | |
270 | mbedtls_ecdsa_init(&ecdsa); |
271 | |
272 | if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) { |
273 | ret = ecdsa_sign_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len, |
274 | f_rng, p_rng); |
275 | } |
276 | |
277 | mbedtls_ecdsa_free(&ecdsa); |
278 | |
279 | return ret; |
280 | } |
281 | |
282 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
283 | /* Forward declarations */ |
284 | static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
285 | const unsigned char *hash, size_t hash_len, |
286 | const unsigned char *sig, size_t sig_len, |
287 | void *rs_ctx); |
288 | |
289 | static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
290 | const unsigned char *hash, size_t hash_len, |
291 | unsigned char *sig, size_t *sig_len, |
292 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
293 | void *rs_ctx); |
294 | |
295 | /* |
296 | * Restart context for ECDSA operations with ECKEY context |
297 | * |
298 | * We need to store an actual ECDSA context, as we need to pass the same to |
299 | * the underlying ecdsa function, so we can't create it on the fly every time. |
300 | */ |
301 | typedef struct { |
302 | mbedtls_ecdsa_restart_ctx ecdsa_rs; |
303 | mbedtls_ecdsa_context ecdsa_ctx; |
304 | } eckey_restart_ctx; |
305 | |
306 | static void *eckey_rs_alloc(void) |
307 | { |
308 | eckey_restart_ctx *rs_ctx; |
309 | |
310 | void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); |
311 | |
312 | if (ctx != NULL) { |
313 | rs_ctx = ctx; |
314 | mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); |
315 | mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); |
316 | } |
317 | |
318 | return ctx; |
319 | } |
320 | |
321 | static void eckey_rs_free(void *ctx) |
322 | { |
323 | eckey_restart_ctx *rs_ctx; |
324 | |
325 | if (ctx == NULL) { |
326 | return; |
327 | } |
328 | |
329 | rs_ctx = ctx; |
330 | mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); |
331 | mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); |
332 | |
333 | mbedtls_free(ctx); |
334 | } |
335 | |
336 | static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
337 | const unsigned char *hash, size_t hash_len, |
338 | const unsigned char *sig, size_t sig_len, |
339 | void *rs_ctx) |
340 | { |
341 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
342 | eckey_restart_ctx *rs = rs_ctx; |
343 | |
344 | /* Should never happen */ |
345 | if (rs == NULL) { |
346 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
347 | } |
348 | |
349 | /* set up our own sub-context if needed (that is, on first run) */ |
350 | if (rs->ecdsa_ctx.grp.pbits == 0) { |
351 | MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); |
352 | } |
353 | |
354 | MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx, |
355 | md_alg, hash, hash_len, |
356 | sig, sig_len, &rs->ecdsa_rs)); |
357 | |
358 | cleanup: |
359 | return ret; |
360 | } |
361 | |
362 | static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
363 | const unsigned char *hash, size_t hash_len, |
364 | unsigned char *sig, size_t *sig_len, |
365 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
366 | void *rs_ctx) |
367 | { |
368 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
369 | eckey_restart_ctx *rs = rs_ctx; |
370 | |
371 | /* Should never happen */ |
372 | if (rs == NULL) { |
373 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
374 | } |
375 | |
376 | /* set up our own sub-context if needed (that is, on first run) */ |
377 | if (rs->ecdsa_ctx.grp.pbits == 0) { |
378 | MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); |
379 | } |
380 | |
381 | MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg, |
382 | hash, hash_len, sig, sig_len, |
383 | f_rng, p_rng, &rs->ecdsa_rs)); |
384 | |
385 | cleanup: |
386 | return ret; |
387 | } |
388 | #endif /* MBEDTLS_ECP_RESTARTABLE */ |
389 | #endif /* MBEDTLS_ECDSA_C */ |
390 | |
391 | static int eckey_check_pair(const void *pub, const void *prv) |
392 | { |
393 | return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub, |
394 | (const mbedtls_ecp_keypair *) prv); |
395 | } |
396 | |
397 | static void *eckey_alloc_wrap(void) |
398 | { |
399 | void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); |
400 | |
401 | if (ctx != NULL) { |
402 | mbedtls_ecp_keypair_init(ctx); |
403 | } |
404 | |
405 | return ctx; |
406 | } |
407 | |
408 | static void eckey_free_wrap(void *ctx) |
409 | { |
410 | mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); |
411 | mbedtls_free(ctx); |
412 | } |
413 | |
414 | static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items) |
415 | { |
416 | items->type = MBEDTLS_PK_DEBUG_ECP; |
417 | items->name = "eckey.Q" ; |
418 | items->value = &(((mbedtls_ecp_keypair *) ctx)->Q); |
419 | } |
420 | |
421 | const mbedtls_pk_info_t mbedtls_eckey_info = { |
422 | MBEDTLS_PK_ECKEY, |
423 | "EC" , |
424 | eckey_get_bitlen, |
425 | eckey_can_do, |
426 | #if defined(MBEDTLS_ECDSA_C) |
427 | eckey_verify_wrap, |
428 | eckey_sign_wrap, |
429 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
430 | eckey_verify_rs_wrap, |
431 | eckey_sign_rs_wrap, |
432 | #endif |
433 | #else /* MBEDTLS_ECDSA_C */ |
434 | NULL, |
435 | NULL, |
436 | #endif /* MBEDTLS_ECDSA_C */ |
437 | NULL, |
438 | NULL, |
439 | eckey_check_pair, |
440 | eckey_alloc_wrap, |
441 | eckey_free_wrap, |
442 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
443 | eckey_rs_alloc, |
444 | eckey_rs_free, |
445 | #endif |
446 | eckey_debug, |
447 | }; |
448 | |
449 | /* |
450 | * EC key restricted to ECDH |
451 | */ |
452 | static int eckeydh_can_do(mbedtls_pk_type_t type) |
453 | { |
454 | return type == MBEDTLS_PK_ECKEY || |
455 | type == MBEDTLS_PK_ECKEY_DH; |
456 | } |
457 | |
458 | const mbedtls_pk_info_t mbedtls_eckeydh_info = { |
459 | MBEDTLS_PK_ECKEY_DH, |
460 | "EC_DH" , |
461 | eckey_get_bitlen, /* Same underlying key structure */ |
462 | eckeydh_can_do, |
463 | NULL, |
464 | NULL, |
465 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
466 | NULL, |
467 | NULL, |
468 | #endif |
469 | NULL, |
470 | NULL, |
471 | eckey_check_pair, |
472 | eckey_alloc_wrap, /* Same underlying key structure */ |
473 | eckey_free_wrap, /* Same underlying key structure */ |
474 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
475 | NULL, |
476 | NULL, |
477 | #endif |
478 | eckey_debug, /* Same underlying key structure */ |
479 | }; |
480 | #endif /* MBEDTLS_ECP_C */ |
481 | |
482 | #if defined(MBEDTLS_ECDSA_C) |
483 | static int ecdsa_can_do(mbedtls_pk_type_t type) |
484 | { |
485 | return type == MBEDTLS_PK_ECDSA; |
486 | } |
487 | |
488 | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
489 | /* |
490 | * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of |
491 | * those integers and convert it to the fixed-length encoding expected by PSA. |
492 | */ |
493 | static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, |
494 | unsigned char *to, size_t to_len) |
495 | { |
496 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
497 | size_t unpadded_len, padding_len; |
498 | |
499 | if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, |
500 | MBEDTLS_ASN1_INTEGER)) != 0) { |
501 | return ret; |
502 | } |
503 | |
504 | while (unpadded_len > 0 && **from == 0x00) { |
505 | (*from)++; |
506 | unpadded_len--; |
507 | } |
508 | |
509 | if (unpadded_len > to_len || unpadded_len == 0) { |
510 | return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; |
511 | } |
512 | |
513 | padding_len = to_len - unpadded_len; |
514 | memset(to, 0x00, padding_len); |
515 | memcpy(to + padding_len, *from, unpadded_len); |
516 | (*from) += unpadded_len; |
517 | |
518 | return 0; |
519 | } |
520 | |
521 | /* |
522 | * Convert a signature from an ASN.1 sequence of two integers |
523 | * to a raw {r,s} buffer. Note: the provided sig buffer must be at least |
524 | * twice as big as int_size. |
525 | */ |
526 | static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, |
527 | unsigned char *sig, size_t int_size) |
528 | { |
529 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
530 | size_t tmp_size; |
531 | |
532 | if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, |
533 | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { |
534 | return ret; |
535 | } |
536 | |
537 | /* Extract r */ |
538 | if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) { |
539 | return ret; |
540 | } |
541 | /* Extract s */ |
542 | if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) { |
543 | return ret; |
544 | } |
545 | |
546 | return 0; |
547 | } |
548 | |
549 | static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg, |
550 | const unsigned char *hash, size_t hash_len, |
551 | const unsigned char *sig, size_t sig_len) |
552 | { |
553 | mbedtls_ecdsa_context *ctx = ctx_arg; |
554 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
555 | psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
556 | psa_key_id_t key_id = 0; |
557 | psa_status_t status; |
558 | mbedtls_pk_context key; |
559 | int key_len; |
560 | /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ |
561 | unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; |
562 | unsigned char *p; |
563 | mbedtls_pk_info_t pk_info = mbedtls_eckey_info; |
564 | psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; |
565 | size_t curve_bits; |
566 | psa_ecc_family_t curve = |
567 | mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); |
568 | const size_t signature_part_size = (ctx->grp.nbits + 7) / 8; |
569 | ((void) md_alg); |
570 | |
571 | if (curve == 0) { |
572 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
573 | } |
574 | |
575 | /* mbedtls_pk_write_pubkey() expects a full PK context; |
576 | * re-construct one to make it happy */ |
577 | key.pk_info = &pk_info; |
578 | key.pk_ctx = ctx; |
579 | p = buf + sizeof(buf); |
580 | key_len = mbedtls_pk_write_pubkey(&p, buf, &key); |
581 | if (key_len <= 0) { |
582 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
583 | } |
584 | |
585 | psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); |
586 | psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); |
587 | psa_set_key_algorithm(&attributes, psa_sig_md); |
588 | |
589 | status = psa_import_key(&attributes, |
590 | buf + sizeof(buf) - key_len, key_len, |
591 | &key_id); |
592 | if (status != PSA_SUCCESS) { |
593 | ret = mbedtls_psa_err_translate_pk(status); |
594 | goto cleanup; |
595 | } |
596 | |
597 | /* We don't need the exported key anymore and can |
598 | * reuse its buffer for signature extraction. */ |
599 | if (2 * signature_part_size > sizeof(buf)) { |
600 | ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
601 | goto cleanup; |
602 | } |
603 | |
604 | p = (unsigned char *) sig; |
605 | if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf, |
606 | signature_part_size)) != 0) { |
607 | goto cleanup; |
608 | } |
609 | |
610 | if (psa_verify_hash(key_id, psa_sig_md, |
611 | hash, hash_len, |
612 | buf, 2 * signature_part_size) |
613 | != PSA_SUCCESS) { |
614 | ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; |
615 | goto cleanup; |
616 | } |
617 | |
618 | if (p != sig + sig_len) { |
619 | ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; |
620 | goto cleanup; |
621 | } |
622 | ret = 0; |
623 | |
624 | cleanup: |
625 | psa_destroy_key(key_id); |
626 | return ret; |
627 | } |
628 | #else /* MBEDTLS_USE_PSA_CRYPTO */ |
629 | static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, |
630 | const unsigned char *hash, size_t hash_len, |
631 | const unsigned char *sig, size_t sig_len) |
632 | { |
633 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
634 | ((void) md_alg); |
635 | |
636 | ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) ctx, |
637 | hash, hash_len, sig, sig_len); |
638 | |
639 | if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { |
640 | return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; |
641 | } |
642 | |
643 | return ret; |
644 | } |
645 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
646 | |
647 | static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
648 | const unsigned char *hash, size_t hash_len, |
649 | unsigned char *sig, size_t *sig_len, |
650 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
651 | { |
652 | return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) ctx, |
653 | md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng); |
654 | } |
655 | |
656 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
657 | static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
658 | const unsigned char *hash, size_t hash_len, |
659 | const unsigned char *sig, size_t sig_len, |
660 | void *rs_ctx) |
661 | { |
662 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
663 | ((void) md_alg); |
664 | |
665 | ret = mbedtls_ecdsa_read_signature_restartable( |
666 | (mbedtls_ecdsa_context *) ctx, |
667 | hash, hash_len, sig, sig_len, |
668 | (mbedtls_ecdsa_restart_ctx *) rs_ctx); |
669 | |
670 | if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { |
671 | return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; |
672 | } |
673 | |
674 | return ret; |
675 | } |
676 | |
677 | static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, |
678 | const unsigned char *hash, size_t hash_len, |
679 | unsigned char *sig, size_t *sig_len, |
680 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, |
681 | void *rs_ctx) |
682 | { |
683 | return mbedtls_ecdsa_write_signature_restartable( |
684 | (mbedtls_ecdsa_context *) ctx, |
685 | md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, |
686 | (mbedtls_ecdsa_restart_ctx *) rs_ctx); |
687 | |
688 | } |
689 | #endif /* MBEDTLS_ECP_RESTARTABLE */ |
690 | |
691 | static void *ecdsa_alloc_wrap(void) |
692 | { |
693 | void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_context)); |
694 | |
695 | if (ctx != NULL) { |
696 | mbedtls_ecdsa_init((mbedtls_ecdsa_context *) ctx); |
697 | } |
698 | |
699 | return ctx; |
700 | } |
701 | |
702 | static void ecdsa_free_wrap(void *ctx) |
703 | { |
704 | mbedtls_ecdsa_free((mbedtls_ecdsa_context *) ctx); |
705 | mbedtls_free(ctx); |
706 | } |
707 | |
708 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
709 | static void *ecdsa_rs_alloc(void) |
710 | { |
711 | void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); |
712 | |
713 | if (ctx != NULL) { |
714 | mbedtls_ecdsa_restart_init(ctx); |
715 | } |
716 | |
717 | return ctx; |
718 | } |
719 | |
720 | static void ecdsa_rs_free(void *ctx) |
721 | { |
722 | mbedtls_ecdsa_restart_free(ctx); |
723 | mbedtls_free(ctx); |
724 | } |
725 | #endif /* MBEDTLS_ECP_RESTARTABLE */ |
726 | |
727 | const mbedtls_pk_info_t mbedtls_ecdsa_info = { |
728 | MBEDTLS_PK_ECDSA, |
729 | "ECDSA" , |
730 | eckey_get_bitlen, /* Compatible key structures */ |
731 | ecdsa_can_do, |
732 | ecdsa_verify_wrap, |
733 | ecdsa_sign_wrap, |
734 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
735 | ecdsa_verify_rs_wrap, |
736 | ecdsa_sign_rs_wrap, |
737 | #endif |
738 | NULL, |
739 | NULL, |
740 | eckey_check_pair, /* Compatible key structures */ |
741 | ecdsa_alloc_wrap, |
742 | ecdsa_free_wrap, |
743 | #if defined(MBEDTLS_ECP_RESTARTABLE) |
744 | ecdsa_rs_alloc, |
745 | ecdsa_rs_free, |
746 | #endif |
747 | eckey_debug, /* Compatible key structures */ |
748 | }; |
749 | #endif /* MBEDTLS_ECDSA_C */ |
750 | |
751 | #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) |
752 | /* |
753 | * Support for alternative RSA-private implementations |
754 | */ |
755 | |
756 | static int rsa_alt_can_do(mbedtls_pk_type_t type) |
757 | { |
758 | return type == MBEDTLS_PK_RSA; |
759 | } |
760 | |
761 | static size_t rsa_alt_get_bitlen(const void *ctx) |
762 | { |
763 | const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; |
764 | |
765 | return 8 * rsa_alt->key_len_func(rsa_alt->key); |
766 | } |
767 | |
768 | static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
769 | const unsigned char *hash, size_t hash_len, |
770 | unsigned char *sig, size_t *sig_len, |
771 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
772 | { |
773 | mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; |
774 | |
775 | #if SIZE_MAX > UINT_MAX |
776 | if (UINT_MAX < hash_len) { |
777 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
778 | } |
779 | #endif /* SIZE_MAX > UINT_MAX */ |
780 | |
781 | *sig_len = rsa_alt->key_len_func(rsa_alt->key); |
782 | if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { |
783 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
784 | } |
785 | |
786 | return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, |
787 | md_alg, (unsigned int) hash_len, hash, sig); |
788 | } |
789 | |
790 | static int rsa_alt_decrypt_wrap(void *ctx, |
791 | const unsigned char *input, size_t ilen, |
792 | unsigned char *output, size_t *olen, size_t osize, |
793 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
794 | { |
795 | mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; |
796 | |
797 | ((void) f_rng); |
798 | ((void) p_rng); |
799 | |
800 | if (ilen != rsa_alt->key_len_func(rsa_alt->key)) { |
801 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
802 | } |
803 | |
804 | return rsa_alt->decrypt_func(rsa_alt->key, |
805 | MBEDTLS_RSA_PRIVATE, olen, input, output, osize); |
806 | } |
807 | |
808 | #if defined(MBEDTLS_RSA_C) |
809 | static int rsa_alt_check_pair(const void *pub, const void *prv) |
810 | { |
811 | unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; |
812 | unsigned char hash[32]; |
813 | size_t sig_len = 0; |
814 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
815 | |
816 | if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) { |
817 | return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
818 | } |
819 | |
820 | memset(hash, 0x2a, sizeof(hash)); |
821 | |
822 | if ((ret = rsa_alt_sign_wrap((void *) prv, MBEDTLS_MD_NONE, |
823 | hash, sizeof(hash), |
824 | sig, &sig_len, NULL, NULL)) != 0) { |
825 | return ret; |
826 | } |
827 | |
828 | if (rsa_verify_wrap((void *) pub, MBEDTLS_MD_NONE, |
829 | hash, sizeof(hash), sig, sig_len) != 0) { |
830 | return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; |
831 | } |
832 | |
833 | return 0; |
834 | } |
835 | #endif /* MBEDTLS_RSA_C */ |
836 | |
837 | static void *rsa_alt_alloc_wrap(void) |
838 | { |
839 | void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); |
840 | |
841 | if (ctx != NULL) { |
842 | memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); |
843 | } |
844 | |
845 | return ctx; |
846 | } |
847 | |
848 | static void rsa_alt_free_wrap(void *ctx) |
849 | { |
850 | mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context)); |
851 | mbedtls_free(ctx); |
852 | } |
853 | |
854 | const mbedtls_pk_info_t mbedtls_rsa_alt_info = { |
855 | MBEDTLS_PK_RSA_ALT, |
856 | "RSA-alt" , |
857 | rsa_alt_get_bitlen, |
858 | rsa_alt_can_do, |
859 | NULL, |
860 | rsa_alt_sign_wrap, |
861 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
862 | NULL, |
863 | NULL, |
864 | #endif |
865 | rsa_alt_decrypt_wrap, |
866 | NULL, |
867 | #if defined(MBEDTLS_RSA_C) |
868 | rsa_alt_check_pair, |
869 | #else |
870 | NULL, |
871 | #endif |
872 | rsa_alt_alloc_wrap, |
873 | rsa_alt_free_wrap, |
874 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
875 | NULL, |
876 | NULL, |
877 | #endif |
878 | NULL, |
879 | }; |
880 | |
881 | #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ |
882 | |
883 | #if defined(MBEDTLS_USE_PSA_CRYPTO) |
884 | |
885 | static void *pk_opaque_alloc_wrap(void) |
886 | { |
887 | void *ctx = mbedtls_calloc(1, sizeof(psa_key_id_t)); |
888 | |
889 | /* no _init() function to call, as calloc() already zeroized */ |
890 | |
891 | return ctx; |
892 | } |
893 | |
894 | static void pk_opaque_free_wrap(void *ctx) |
895 | { |
896 | mbedtls_platform_zeroize(ctx, sizeof(psa_key_id_t)); |
897 | mbedtls_free(ctx); |
898 | } |
899 | |
900 | static size_t pk_opaque_get_bitlen(const void *ctx) |
901 | { |
902 | const psa_key_id_t *key = (const psa_key_id_t *) ctx; |
903 | size_t bits; |
904 | psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
905 | |
906 | if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) { |
907 | return 0; |
908 | } |
909 | |
910 | bits = psa_get_key_bits(&attributes); |
911 | psa_reset_key_attributes(&attributes); |
912 | return bits; |
913 | } |
914 | |
915 | static int pk_opaque_can_do(mbedtls_pk_type_t type) |
916 | { |
917 | /* For now opaque PSA keys can only wrap ECC keypairs, |
918 | * as checked by setup_psa(). |
919 | * Also, ECKEY_DH does not really make sense with the current API. */ |
920 | return type == MBEDTLS_PK_ECKEY || |
921 | type == MBEDTLS_PK_ECDSA; |
922 | } |
923 | |
924 | #if defined(MBEDTLS_ECDSA_C) |
925 | |
926 | /* |
927 | * Simultaneously convert and move raw MPI from the beginning of a buffer |
928 | * to an ASN.1 MPI at the end of the buffer. |
929 | * See also mbedtls_asn1_write_mpi(). |
930 | * |
931 | * p: pointer to the end of the output buffer |
932 | * start: start of the output buffer, and also of the mpi to write at the end |
933 | * n_len: length of the mpi to read from start |
934 | */ |
935 | static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, |
936 | size_t n_len) |
937 | { |
938 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
939 | size_t len = 0; |
940 | |
941 | if ((size_t) (*p - start) < n_len) { |
942 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
943 | } |
944 | |
945 | len = n_len; |
946 | *p -= len; |
947 | memmove(*p, start, len); |
948 | |
949 | /* ASN.1 DER encoding requires minimal length, so skip leading 0s. |
950 | * Neither r nor s should be 0, but as a failsafe measure, still detect |
951 | * that rather than overflowing the buffer in case of a PSA error. */ |
952 | while (len > 0 && **p == 0x00) { |
953 | ++(*p); |
954 | --len; |
955 | } |
956 | |
957 | /* this is only reached if the signature was invalid */ |
958 | if (len == 0) { |
959 | return MBEDTLS_ERR_PK_HW_ACCEL_FAILED; |
960 | } |
961 | |
962 | /* if the msb is 1, ASN.1 requires that we prepend a 0. |
963 | * Neither r nor s can be 0, so we can assume len > 0 at all times. */ |
964 | if (**p & 0x80) { |
965 | if (*p - start < 1) { |
966 | return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; |
967 | } |
968 | |
969 | *--(*p) = 0x00; |
970 | len += 1; |
971 | } |
972 | |
973 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); |
974 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, |
975 | MBEDTLS_ASN1_INTEGER)); |
976 | |
977 | return (int) len; |
978 | } |
979 | |
980 | /* Transcode signature from PSA format to ASN.1 sequence. |
981 | * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of |
982 | * MPIs, and in-place. |
983 | * |
984 | * [in/out] sig: the signature pre- and post-transcoding |
985 | * [in/out] sig_len: signature length pre- and post-transcoding |
986 | * [int] buf_len: the available size the in/out buffer |
987 | */ |
988 | static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len, |
989 | size_t buf_len) |
990 | { |
991 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
992 | size_t len = 0; |
993 | const size_t rs_len = *sig_len / 2; |
994 | unsigned char *p = sig + buf_len; |
995 | |
996 | MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); |
997 | MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); |
998 | |
999 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); |
1000 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig, |
1001 | MBEDTLS_ASN1_CONSTRUCTED | |
1002 | MBEDTLS_ASN1_SEQUENCE)); |
1003 | |
1004 | memmove(sig, p, len); |
1005 | *sig_len = len; |
1006 | |
1007 | return 0; |
1008 | } |
1009 | |
1010 | #endif /* MBEDTLS_ECDSA_C */ |
1011 | |
1012 | static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, |
1013 | const unsigned char *hash, size_t hash_len, |
1014 | unsigned char *sig, size_t *sig_len, |
1015 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) |
1016 | { |
1017 | #if !defined(MBEDTLS_ECDSA_C) |
1018 | ((void) ctx); |
1019 | ((void) md_alg); |
1020 | ((void) hash); |
1021 | ((void) hash_len); |
1022 | ((void) sig); |
1023 | ((void) sig_len); |
1024 | ((void) f_rng); |
1025 | ((void) p_rng); |
1026 | return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; |
1027 | #else /* !MBEDTLS_ECDSA_C */ |
1028 | const psa_key_id_t *key = (const psa_key_id_t *) ctx; |
1029 | psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
1030 | psa_algorithm_t alg = PSA_ALG_ECDSA(mbedtls_psa_translate_md(md_alg)); |
1031 | size_t buf_len; |
1032 | psa_status_t status; |
1033 | |
1034 | /* PSA has its own RNG */ |
1035 | (void) f_rng; |
1036 | (void) p_rng; |
1037 | |
1038 | /* PSA needs an output buffer of known size, but our API doesn't provide |
1039 | * that information. Assume that the buffer is large enough for a |
1040 | * maximal-length signature with that key (otherwise the application is |
1041 | * buggy anyway). */ |
1042 | status = psa_get_key_attributes(*key, &attributes); |
1043 | if (status != PSA_SUCCESS) { |
1044 | return mbedtls_psa_err_translate_pk(status); |
1045 | } |
1046 | buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN(psa_get_key_bits(&attributes)); |
1047 | psa_reset_key_attributes(&attributes); |
1048 | if (buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { |
1049 | return MBEDTLS_ERR_PK_BAD_INPUT_DATA; |
1050 | } |
1051 | |
1052 | /* make the signature */ |
1053 | status = psa_sign_hash(*key, alg, hash, hash_len, |
1054 | sig, buf_len, sig_len); |
1055 | if (status != PSA_SUCCESS) { |
1056 | return mbedtls_psa_err_translate_pk(status); |
1057 | } |
1058 | |
1059 | /* transcode it to ASN.1 sequence */ |
1060 | return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, buf_len); |
1061 | #endif /* !MBEDTLS_ECDSA_C */ |
1062 | } |
1063 | |
1064 | const mbedtls_pk_info_t mbedtls_pk_opaque_info = { |
1065 | MBEDTLS_PK_OPAQUE, |
1066 | "Opaque" , |
1067 | pk_opaque_get_bitlen, |
1068 | pk_opaque_can_do, |
1069 | NULL, /* verify - will be done later */ |
1070 | pk_opaque_sign_wrap, |
1071 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
1072 | NULL, /* restartable verify - not relevant */ |
1073 | NULL, /* restartable sign - not relevant */ |
1074 | #endif |
1075 | NULL, /* decrypt - will be done later */ |
1076 | NULL, /* encrypt - will be done later */ |
1077 | NULL, /* check_pair - could be done later or left NULL */ |
1078 | pk_opaque_alloc_wrap, |
1079 | pk_opaque_free_wrap, |
1080 | #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) |
1081 | NULL, /* restart alloc - not relevant */ |
1082 | NULL, /* restart free - not relevant */ |
1083 | #endif |
1084 | NULL, /* debug - could be done later, or even left NULL */ |
1085 | }; |
1086 | |
1087 | #endif /* MBEDTLS_USE_PSA_CRYPTO */ |
1088 | |
1089 | #endif /* MBEDTLS_PK_C */ |
1090 | |