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