1 /*
2 * Public Key abstraction layer
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 */
7
8 #include "common.h"
9
10 #if defined(MBEDTLS_PK_C)
11 #include "mbedtls/pk.h"
12 #include "mbedtls/pk_internal.h"
13
14 #include "mbedtls/platform_util.h"
15 #include "mbedtls/error.h"
16
17 #if defined(MBEDTLS_RSA_C)
18 #include "mbedtls/rsa.h"
19 #endif
20 #if defined(MBEDTLS_ECP_C)
21 #include "mbedtls/ecp.h"
22 #endif
23 #if defined(MBEDTLS_ECDSA_C)
24 #include "mbedtls/ecdsa.h"
25 #endif
26
27 #if defined(MBEDTLS_USE_PSA_CRYPTO)
28 #include "mbedtls/psa_util.h"
29 #endif
30
31 #include <limits.h>
32 #include <stdint.h>
33
34 /* Parameter validation macros based on platform_util.h */
35 #define PK_VALIDATE_RET(cond) \
36 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA)
37 #define PK_VALIDATE(cond) \
38 MBEDTLS_INTERNAL_VALIDATE(cond)
39
40 /*
41 * Initialise a mbedtls_pk_context
42 */
mbedtls_pk_init(mbedtls_pk_context * ctx)43 void mbedtls_pk_init(mbedtls_pk_context *ctx)
44 {
45 PK_VALIDATE(ctx != NULL);
46
47 ctx->pk_info = NULL;
48 ctx->pk_ctx = NULL;
49 }
50
51 /*
52 * Free (the components of) a mbedtls_pk_context
53 */
mbedtls_pk_free(mbedtls_pk_context * ctx)54 void mbedtls_pk_free(mbedtls_pk_context *ctx)
55 {
56 if (ctx == NULL) {
57 return;
58 }
59
60 if (ctx->pk_info != NULL) {
61 ctx->pk_info->ctx_free_func(ctx->pk_ctx);
62 }
63
64 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));
65 }
66
67 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
68 /*
69 * Initialize a restart context
70 */
mbedtls_pk_restart_init(mbedtls_pk_restart_ctx * ctx)71 void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)
72 {
73 PK_VALIDATE(ctx != NULL);
74 ctx->pk_info = NULL;
75 ctx->rs_ctx = NULL;
76 }
77
78 /*
79 * Free the components of a restart context
80 */
mbedtls_pk_restart_free(mbedtls_pk_restart_ctx * ctx)81 void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)
82 {
83 if (ctx == NULL || ctx->pk_info == NULL ||
84 ctx->pk_info->rs_free_func == NULL) {
85 return;
86 }
87
88 ctx->pk_info->rs_free_func(ctx->rs_ctx);
89
90 ctx->pk_info = NULL;
91 ctx->rs_ctx = NULL;
92 }
93 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
94
95 /*
96 * Get pk_info structure from type
97 */
mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)98 const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
99 {
100 switch (pk_type) {
101 #if defined(MBEDTLS_RSA_C)
102 case MBEDTLS_PK_RSA:
103 return &mbedtls_rsa_info;
104 #endif
105 #if defined(MBEDTLS_ECP_C)
106 case MBEDTLS_PK_ECKEY:
107 return &mbedtls_eckey_info;
108 case MBEDTLS_PK_ECKEY_DH:
109 return &mbedtls_eckeydh_info;
110 #endif
111 #if defined(MBEDTLS_ECDSA_C)
112 case MBEDTLS_PK_ECDSA:
113 return &mbedtls_ecdsa_info;
114 #endif
115 /* MBEDTLS_PK_RSA_ALT omitted on purpose */
116 default:
117 return NULL;
118 }
119 }
120
121 /*
122 * Initialise context
123 */
mbedtls_pk_setup(mbedtls_pk_context * ctx,const mbedtls_pk_info_t * info)124 int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
125 {
126 PK_VALIDATE_RET(ctx != NULL);
127 if (info == NULL || ctx->pk_info != NULL) {
128 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
129 }
130
131 if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
132 return MBEDTLS_ERR_PK_ALLOC_FAILED;
133 }
134
135 ctx->pk_info = info;
136
137 return 0;
138 }
139
140 #if defined(MBEDTLS_USE_PSA_CRYPTO)
141 /*
142 * Initialise a PSA-wrapping context
143 */
mbedtls_pk_setup_opaque(mbedtls_pk_context * ctx,const psa_key_id_t key)144 int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
145 const psa_key_id_t key)
146 {
147 const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
148 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
149 psa_key_id_t *pk_ctx;
150 psa_key_type_t type;
151
152 if (ctx == NULL || ctx->pk_info != NULL) {
153 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
154 }
155
156 if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {
157 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
158 }
159 type = psa_get_key_type(&attributes);
160 psa_reset_key_attributes(&attributes);
161
162 /* Current implementation of can_do() relies on this. */
163 if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
164 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
165 }
166
167 if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
168 return MBEDTLS_ERR_PK_ALLOC_FAILED;
169 }
170
171 ctx->pk_info = info;
172
173 pk_ctx = (psa_key_id_t *) ctx->pk_ctx;
174 *pk_ctx = key;
175
176 return 0;
177 }
178 #endif /* MBEDTLS_USE_PSA_CRYPTO */
179
180 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
181 /*
182 * Initialize an RSA-alt context
183 */
mbedtls_pk_setup_rsa_alt(mbedtls_pk_context * ctx,void * key,mbedtls_pk_rsa_alt_decrypt_func decrypt_func,mbedtls_pk_rsa_alt_sign_func sign_func,mbedtls_pk_rsa_alt_key_len_func key_len_func)184 int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,
185 mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
186 mbedtls_pk_rsa_alt_sign_func sign_func,
187 mbedtls_pk_rsa_alt_key_len_func key_len_func)
188 {
189 mbedtls_rsa_alt_context *rsa_alt;
190 const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
191
192 PK_VALIDATE_RET(ctx != NULL);
193 if (ctx->pk_info != NULL) {
194 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
195 }
196
197 if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
198 return MBEDTLS_ERR_PK_ALLOC_FAILED;
199 }
200
201 ctx->pk_info = info;
202
203 rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;
204
205 rsa_alt->key = key;
206 rsa_alt->decrypt_func = decrypt_func;
207 rsa_alt->sign_func = sign_func;
208 rsa_alt->key_len_func = key_len_func;
209
210 return 0;
211 }
212 #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
213
214 /*
215 * Tell if a PK can do the operations of the given type
216 */
mbedtls_pk_can_do(const mbedtls_pk_context * ctx,mbedtls_pk_type_t type)217 int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type)
218 {
219 /* A context with null pk_info is not set up yet and can't do anything.
220 * For backward compatibility, also accept NULL instead of a context
221 * pointer. */
222 if (ctx == NULL || ctx->pk_info == NULL) {
223 return 0;
224 }
225
226 return ctx->pk_info->can_do(type);
227 }
228
229 /*
230 * Helper for mbedtls_pk_sign and mbedtls_pk_verify
231 */
pk_hashlen_helper(mbedtls_md_type_t md_alg,size_t * hash_len)232 static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
233 {
234 const mbedtls_md_info_t *md_info;
235
236 if (*hash_len != 0 && md_alg == MBEDTLS_MD_NONE) {
237 return 0;
238 }
239
240 if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {
241 return -1;
242 }
243
244 if (*hash_len != 0 && *hash_len != mbedtls_md_get_size(md_info)) {
245 return -1;
246 }
247
248 *hash_len = mbedtls_md_get_size(md_info);
249 return 0;
250 }
251
252 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
253 /*
254 * Helper to set up a restart context if needed
255 */
pk_restart_setup(mbedtls_pk_restart_ctx * ctx,const mbedtls_pk_info_t * info)256 static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,
257 const mbedtls_pk_info_t *info)
258 {
259 /* Don't do anything if already set up or invalid */
260 if (ctx == NULL || ctx->pk_info != NULL) {
261 return 0;
262 }
263
264 /* Should never happen when we're called */
265 if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {
266 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
267 }
268
269 if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {
270 return MBEDTLS_ERR_PK_ALLOC_FAILED;
271 }
272
273 ctx->pk_info = info;
274
275 return 0;
276 }
277 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
278
279 /*
280 * Verify a signature (restartable)
281 */
mbedtls_pk_verify_restartable(mbedtls_pk_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hash_len,const unsigned char * sig,size_t sig_len,mbedtls_pk_restart_ctx * rs_ctx)282 int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
283 mbedtls_md_type_t md_alg,
284 const unsigned char *hash, size_t hash_len,
285 const unsigned char *sig, size_t sig_len,
286 mbedtls_pk_restart_ctx *rs_ctx)
287 {
288 PK_VALIDATE_RET(ctx != NULL);
289 PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) ||
290 hash != NULL);
291 PK_VALIDATE_RET(sig != NULL);
292
293 if (ctx->pk_info == NULL ||
294 pk_hashlen_helper(md_alg, &hash_len) != 0) {
295 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
296 }
297
298 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
299 /* optimization: use non-restartable version if restart disabled */
300 if (rs_ctx != NULL &&
301 mbedtls_ecp_restart_is_enabled() &&
302 ctx->pk_info->verify_rs_func != NULL) {
303 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
304
305 if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
306 return ret;
307 }
308
309 ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx,
310 md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);
311
312 if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
313 mbedtls_pk_restart_free(rs_ctx);
314 }
315
316 return ret;
317 }
318 #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
319 (void) rs_ctx;
320 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
321
322 if (ctx->pk_info->verify_func == NULL) {
323 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
324 }
325
326 return ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len,
327 sig, sig_len);
328 }
329
330 /*
331 * Verify a signature
332 */
mbedtls_pk_verify(mbedtls_pk_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hash_len,const unsigned char * sig,size_t sig_len)333 int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
334 const unsigned char *hash, size_t hash_len,
335 const unsigned char *sig, size_t sig_len)
336 {
337 return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len,
338 sig, sig_len, NULL);
339 }
340
341 /*
342 * Verify a signature with options
343 */
mbedtls_pk_verify_ext(mbedtls_pk_type_t type,const void * options,mbedtls_pk_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hash_len,const unsigned char * sig,size_t sig_len)344 int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
345 mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
346 const unsigned char *hash, size_t hash_len,
347 const unsigned char *sig, size_t sig_len)
348 {
349 PK_VALIDATE_RET(ctx != NULL);
350 PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) ||
351 hash != NULL);
352 PK_VALIDATE_RET(sig != NULL);
353
354 if (ctx->pk_info == NULL) {
355 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
356 }
357
358 if (!mbedtls_pk_can_do(ctx, type)) {
359 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
360 }
361
362 if (type == MBEDTLS_PK_RSASSA_PSS) {
363 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
364 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
365 const mbedtls_pk_rsassa_pss_options *pss_opts;
366
367 #if SIZE_MAX > UINT_MAX
368 if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
369 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
370 }
371 #endif /* SIZE_MAX > UINT_MAX */
372
373 if (options == NULL) {
374 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
375 }
376
377 pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
378
379 if (sig_len < mbedtls_pk_get_len(ctx)) {
380 return MBEDTLS_ERR_RSA_VERIFY_FAILED;
381 }
382
383 ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx),
384 NULL, NULL, MBEDTLS_RSA_PUBLIC,
385 md_alg, (unsigned int) hash_len, hash,
386 pss_opts->mgf1_hash_id,
387 pss_opts->expected_salt_len,
388 sig);
389 if (ret != 0) {
390 return ret;
391 }
392
393 if (sig_len > mbedtls_pk_get_len(ctx)) {
394 return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
395 }
396
397 return 0;
398 #else
399 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
400 #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
401 }
402
403 /* General case: no options */
404 if (options != NULL) {
405 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
406 }
407
408 return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
409 }
410
411 /*
412 * Make a signature (restartable)
413 */
mbedtls_pk_sign_restartable(mbedtls_pk_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hash_len,unsigned char * sig,size_t * sig_len,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_pk_restart_ctx * rs_ctx)414 int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
415 mbedtls_md_type_t md_alg,
416 const unsigned char *hash, size_t hash_len,
417 unsigned char *sig, size_t *sig_len,
418 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
419 mbedtls_pk_restart_ctx *rs_ctx)
420 {
421 PK_VALIDATE_RET(ctx != NULL);
422 PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) ||
423 hash != NULL);
424 PK_VALIDATE_RET(sig != NULL);
425
426 if (ctx->pk_info == NULL ||
427 pk_hashlen_helper(md_alg, &hash_len) != 0) {
428 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
429 }
430
431 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
432 /* optimization: use non-restartable version if restart disabled */
433 if (rs_ctx != NULL &&
434 mbedtls_ecp_restart_is_enabled() &&
435 ctx->pk_info->sign_rs_func != NULL) {
436 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
437
438 if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
439 return ret;
440 }
441
442 ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg,
443 hash, hash_len, sig, sig_len, f_rng, p_rng,
444 rs_ctx->rs_ctx);
445
446 if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
447 mbedtls_pk_restart_free(rs_ctx);
448 }
449
450 return ret;
451 }
452 #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
453 (void) rs_ctx;
454 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
455
456 if (ctx->pk_info->sign_func == NULL) {
457 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
458 }
459
460 return ctx->pk_info->sign_func(ctx->pk_ctx, md_alg, hash, hash_len,
461 sig, sig_len, f_rng, p_rng);
462 }
463
464 /*
465 * Make a signature
466 */
mbedtls_pk_sign(mbedtls_pk_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hash_len,unsigned char * sig,size_t * sig_len,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)467 int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
468 const unsigned char *hash, size_t hash_len,
469 unsigned char *sig, size_t *sig_len,
470 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
471 {
472 return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len,
473 sig, sig_len, f_rng, p_rng, NULL);
474 }
475
476 /*
477 * Decrypt message
478 */
mbedtls_pk_decrypt(mbedtls_pk_context * ctx,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen,size_t osize,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)479 int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
480 const unsigned char *input, size_t ilen,
481 unsigned char *output, size_t *olen, size_t osize,
482 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
483 {
484 PK_VALIDATE_RET(ctx != NULL);
485 PK_VALIDATE_RET(input != NULL || ilen == 0);
486 PK_VALIDATE_RET(output != NULL || osize == 0);
487 PK_VALIDATE_RET(olen != NULL);
488
489 if (ctx->pk_info == NULL) {
490 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
491 }
492
493 if (ctx->pk_info->decrypt_func == NULL) {
494 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
495 }
496
497 return ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen,
498 output, olen, osize, f_rng, p_rng);
499 }
500
501 /*
502 * Encrypt message
503 */
mbedtls_pk_encrypt(mbedtls_pk_context * ctx,const unsigned char * input,size_t ilen,unsigned char * output,size_t * olen,size_t osize,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)504 int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
505 const unsigned char *input, size_t ilen,
506 unsigned char *output, size_t *olen, size_t osize,
507 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
508 {
509 PK_VALIDATE_RET(ctx != NULL);
510 PK_VALIDATE_RET(input != NULL || ilen == 0);
511 PK_VALIDATE_RET(output != NULL || osize == 0);
512 PK_VALIDATE_RET(olen != NULL);
513
514 if (ctx->pk_info == NULL) {
515 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
516 }
517
518 if (ctx->pk_info->encrypt_func == NULL) {
519 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
520 }
521
522 return ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen,
523 output, olen, osize, f_rng, p_rng);
524 }
525
526 /*
527 * Check public-private key pair
528 */
mbedtls_pk_check_pair(const mbedtls_pk_context * pub,const mbedtls_pk_context * prv)529 int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv)
530 {
531 PK_VALIDATE_RET(pub != NULL);
532 PK_VALIDATE_RET(prv != NULL);
533
534 if (pub->pk_info == NULL ||
535 prv->pk_info == NULL) {
536 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
537 }
538
539 if (prv->pk_info->check_pair_func == NULL) {
540 return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
541 }
542
543 if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {
544 if (pub->pk_info->type != MBEDTLS_PK_RSA) {
545 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
546 }
547 } else {
548 if (pub->pk_info != prv->pk_info) {
549 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
550 }
551 }
552
553 return prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx);
554 }
555
556 /*
557 * Get key size in bits
558 */
mbedtls_pk_get_bitlen(const mbedtls_pk_context * ctx)559 size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
560 {
561 /* For backward compatibility, accept NULL or a context that
562 * isn't set up yet, and return a fake value that should be safe. */
563 if (ctx == NULL || ctx->pk_info == NULL) {
564 return 0;
565 }
566
567 return ctx->pk_info->get_bitlen(ctx->pk_ctx);
568 }
569
570 /*
571 * Export debug information
572 */
mbedtls_pk_debug(const mbedtls_pk_context * ctx,mbedtls_pk_debug_item * items)573 int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
574 {
575 PK_VALIDATE_RET(ctx != NULL);
576 if (ctx->pk_info == NULL) {
577 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
578 }
579
580 if (ctx->pk_info->debug_func == NULL) {
581 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
582 }
583
584 ctx->pk_info->debug_func(ctx->pk_ctx, items);
585 return 0;
586 }
587
588 /*
589 * Access the PK type name
590 */
mbedtls_pk_get_name(const mbedtls_pk_context * ctx)591 const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
592 {
593 if (ctx == NULL || ctx->pk_info == NULL) {
594 return "invalid PK";
595 }
596
597 return ctx->pk_info->name;
598 }
599
600 /*
601 * Access the PK type
602 */
mbedtls_pk_get_type(const mbedtls_pk_context * ctx)603 mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
604 {
605 if (ctx == NULL || ctx->pk_info == NULL) {
606 return MBEDTLS_PK_NONE;
607 }
608
609 return ctx->pk_info->type;
610 }
611
612 #if defined(MBEDTLS_USE_PSA_CRYPTO)
613 /*
614 * Load the key to a PSA key slot,
615 * then turn the PK context into a wrapper for that key slot.
616 *
617 * Currently only works for EC private keys.
618 */
mbedtls_pk_wrap_as_opaque(mbedtls_pk_context * pk,psa_key_id_t * key,psa_algorithm_t hash_alg)619 int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
620 psa_key_id_t *key,
621 psa_algorithm_t hash_alg)
622 {
623 #if !defined(MBEDTLS_ECP_C)
624 ((void) pk);
625 ((void) key);
626 ((void) hash_alg);
627 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
628 #else
629 const mbedtls_ecp_keypair *ec;
630 unsigned char d[MBEDTLS_ECP_MAX_BYTES];
631 size_t d_len;
632 psa_ecc_family_t curve_id;
633 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
634 psa_key_type_t key_type;
635 size_t bits;
636 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
637 psa_status_t status;
638
639 /* export the private key material in the format PSA wants */
640 if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECKEY) {
641 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
642 }
643
644 ec = mbedtls_pk_ec(*pk);
645 d_len = (ec->grp.nbits + 7) / 8;
646 if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) {
647 return ret;
648 }
649
650 curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
651 key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id);
652
653 /* prepare the key attributes */
654 psa_set_key_type(&attributes, key_type);
655 psa_set_key_bits(&attributes, bits);
656 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
657 psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(hash_alg));
658
659 /* import private key into PSA */
660 status = psa_import_key(&attributes, d, d_len, key);
661 mbedtls_platform_zeroize(d, sizeof(d));
662 if (status != PSA_SUCCESS) {
663 return MBEDTLS_ERR_PK_HW_ACCEL_FAILED;
664 }
665
666 /* make PK context wrap the key slot */
667 mbedtls_pk_free(pk);
668 mbedtls_pk_init(pk);
669
670 return mbedtls_pk_setup_opaque(pk, *key);
671 #endif /* MBEDTLS_ECP_C */
672 }
673 #endif /* MBEDTLS_USE_PSA_CRYPTO */
674 #endif /* MBEDTLS_PK_C */
675