xref: /optee_os/lib/libmbedtls/mbedtls/library/pk.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Public Key abstraction layer
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander  */
7817466cbSJens Wiklander 
87901324dSJerome Forissier #include "common.h"
9817466cbSJens Wiklander 
10817466cbSJens Wiklander #if defined(MBEDTLS_PK_C)
11817466cbSJens Wiklander #include "mbedtls/pk.h"
1232b31808SJens Wiklander #include "pk_wrap.h"
1332b31808SJens Wiklander #include "pkwrite.h"
14*b0563631STom Van Eyck #include "pk_internal.h"
15817466cbSJens Wiklander 
163d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
1711fa71b9SJerome Forissier #include "mbedtls/error.h"
18817466cbSJens Wiklander 
19817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
20817466cbSJens Wiklander #include "mbedtls/rsa.h"
21*b0563631STom Van Eyck #include "rsa_internal.h"
22817466cbSJens Wiklander #endif
23*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
24817466cbSJens Wiklander #include "mbedtls/ecp.h"
25817466cbSJens Wiklander #endif
26817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
27817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
28817466cbSJens Wiklander #endif
29817466cbSJens Wiklander 
30*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
31*b0563631STom Van Eyck #include "psa_util_internal.h"
3211fa71b9SJerome Forissier #include "mbedtls/psa_util.h"
3311fa71b9SJerome Forissier #endif
3411fa71b9SJerome Forissier 
35817466cbSJens Wiklander #include <limits.h>
363d3b0591SJens Wiklander #include <stdint.h>
37817466cbSJens Wiklander 
38*b0563631STom Van Eyck #define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \
39*b0563631STom Van Eyck     (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \
40*b0563631STom Van Eyck     PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
41*b0563631STom Van Eyck 
42817466cbSJens Wiklander /*
43817466cbSJens Wiklander  * Initialise a mbedtls_pk_context
44817466cbSJens Wiklander  */
45817466cbSJens Wiklander void mbedtls_pk_init(mbedtls_pk_context *ctx)
46817466cbSJens Wiklander {
47817466cbSJens Wiklander     ctx->pk_info = NULL;
48817466cbSJens Wiklander     ctx->pk_ctx = NULL;
49*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
50*b0563631STom Van Eyck     ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT;
51*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
52*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
53*b0563631STom Van Eyck     memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw));
54*b0563631STom Van Eyck     ctx->pub_raw_len = 0;
55*b0563631STom Van Eyck     ctx->ec_family = 0;
56*b0563631STom Van Eyck     ctx->ec_bits = 0;
57*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
58817466cbSJens Wiklander }
59817466cbSJens Wiklander 
60817466cbSJens Wiklander /*
61817466cbSJens Wiklander  * Free (the components of) a mbedtls_pk_context
62817466cbSJens Wiklander  */
63817466cbSJens Wiklander void mbedtls_pk_free(mbedtls_pk_context *ctx)
64817466cbSJens Wiklander {
6532b31808SJens Wiklander     if (ctx == NULL) {
66817466cbSJens Wiklander         return;
6732b31808SJens Wiklander     }
68817466cbSJens Wiklander 
69*b0563631STom Van Eyck     if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) {
70817466cbSJens Wiklander         ctx->pk_info->ctx_free_func(ctx->pk_ctx);
7132b31808SJens Wiklander     }
72817466cbSJens Wiklander 
73*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
74*b0563631STom Van Eyck     /* The ownership of the priv_id key for opaque keys is external of the PK
75*b0563631STom Van Eyck      * module. It's the user responsibility to clear it after use. */
76*b0563631STom Van Eyck     if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) {
77*b0563631STom Van Eyck         psa_destroy_key(ctx->priv_id);
78*b0563631STom Van Eyck     }
79*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
80*b0563631STom Van Eyck 
813d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));
82817466cbSJens Wiklander }
83817466cbSJens Wiklander 
843d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
853d3b0591SJens Wiklander /*
863d3b0591SJens Wiklander  * Initialize a restart context
873d3b0591SJens Wiklander  */
883d3b0591SJens Wiklander void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)
893d3b0591SJens Wiklander {
903d3b0591SJens Wiklander     ctx->pk_info = NULL;
913d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
923d3b0591SJens Wiklander }
933d3b0591SJens Wiklander 
943d3b0591SJens Wiklander /*
953d3b0591SJens Wiklander  * Free the components of a restart context
963d3b0591SJens Wiklander  */
973d3b0591SJens Wiklander void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)
983d3b0591SJens Wiklander {
993d3b0591SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL ||
10032b31808SJens Wiklander         ctx->pk_info->rs_free_func == NULL) {
1013d3b0591SJens Wiklander         return;
1023d3b0591SJens Wiklander     }
1033d3b0591SJens Wiklander 
1043d3b0591SJens Wiklander     ctx->pk_info->rs_free_func(ctx->rs_ctx);
1053d3b0591SJens Wiklander 
1063d3b0591SJens Wiklander     ctx->pk_info = NULL;
1073d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
1083d3b0591SJens Wiklander }
1093d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
1103d3b0591SJens Wiklander 
111817466cbSJens Wiklander /*
112817466cbSJens Wiklander  * Get pk_info structure from type
113817466cbSJens Wiklander  */
114817466cbSJens Wiklander const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
115817466cbSJens Wiklander {
116817466cbSJens Wiklander     switch (pk_type) {
117817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
118817466cbSJens Wiklander         case MBEDTLS_PK_RSA:
11932b31808SJens Wiklander             return &mbedtls_rsa_info;
120*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
121*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
122817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY:
12332b31808SJens Wiklander             return &mbedtls_eckey_info;
124817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY_DH:
12532b31808SJens Wiklander             return &mbedtls_eckeydh_info;
126*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
12732b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
128817466cbSJens Wiklander         case MBEDTLS_PK_ECDSA:
12932b31808SJens Wiklander             return &mbedtls_ecdsa_info;
130*b0563631STom Van Eyck #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
131817466cbSJens Wiklander         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
132817466cbSJens Wiklander         default:
13332b31808SJens Wiklander             return NULL;
134817466cbSJens Wiklander     }
135817466cbSJens Wiklander }
136817466cbSJens Wiklander 
137817466cbSJens Wiklander /*
138817466cbSJens Wiklander  * Initialise context
139817466cbSJens Wiklander  */
140817466cbSJens Wiklander int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
141817466cbSJens Wiklander {
14232b31808SJens Wiklander     if (info == NULL || ctx->pk_info != NULL) {
14332b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
14432b31808SJens Wiklander     }
145817466cbSJens Wiklander 
146*b0563631STom Van Eyck     if ((info->ctx_alloc_func != NULL) &&
147*b0563631STom Van Eyck         ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) {
14832b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
14932b31808SJens Wiklander     }
150817466cbSJens Wiklander 
151817466cbSJens Wiklander     ctx->pk_info = info;
152817466cbSJens Wiklander 
15332b31808SJens Wiklander     return 0;
154817466cbSJens Wiklander }
155817466cbSJens Wiklander 
15611fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
15711fa71b9SJerome Forissier /*
15811fa71b9SJerome Forissier  * Initialise a PSA-wrapping context
15911fa71b9SJerome Forissier  */
1607901324dSJerome Forissier int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
16132b31808SJens Wiklander                             const mbedtls_svc_key_id_t key)
16211fa71b9SJerome Forissier {
16332b31808SJens Wiklander     const mbedtls_pk_info_t *info = NULL;
16411fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
16511fa71b9SJerome Forissier     psa_key_type_t type;
16611fa71b9SJerome Forissier 
16732b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info != NULL) {
16832b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
16932b31808SJens Wiklander     }
17011fa71b9SJerome Forissier 
17132b31808SJens Wiklander     if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {
17232b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
17332b31808SJens Wiklander     }
17411fa71b9SJerome Forissier     type = psa_get_key_type(&attributes);
17511fa71b9SJerome Forissier     psa_reset_key_attributes(&attributes);
17611fa71b9SJerome Forissier 
177*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
17832b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
179*b0563631STom Van Eyck         info = &mbedtls_ecdsa_opaque_info;
180*b0563631STom Van Eyck     } else
181*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
182*b0563631STom Van Eyck     if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
183*b0563631STom Van Eyck         info = &mbedtls_rsa_opaque_info;
18432b31808SJens Wiklander     } else {
18532b31808SJens Wiklander         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
18632b31808SJens Wiklander     }
18711fa71b9SJerome Forissier 
18811fa71b9SJerome Forissier     ctx->pk_info = info;
189*b0563631STom Van Eyck     ctx->priv_id = key;
19011fa71b9SJerome Forissier 
19132b31808SJens Wiklander     return 0;
19211fa71b9SJerome Forissier }
19311fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
19411fa71b9SJerome Forissier 
195817466cbSJens Wiklander #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
196817466cbSJens Wiklander /*
197817466cbSJens Wiklander  * Initialize an RSA-alt context
198817466cbSJens Wiklander  */
199817466cbSJens Wiklander int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,
200817466cbSJens Wiklander                              mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
201817466cbSJens Wiklander                              mbedtls_pk_rsa_alt_sign_func sign_func,
202817466cbSJens Wiklander                              mbedtls_pk_rsa_alt_key_len_func key_len_func)
203817466cbSJens Wiklander {
204817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt;
205817466cbSJens Wiklander     const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
206817466cbSJens Wiklander 
20732b31808SJens Wiklander     if (ctx->pk_info != NULL) {
20832b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
20932b31808SJens Wiklander     }
210817466cbSJens Wiklander 
21132b31808SJens Wiklander     if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
21232b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
21332b31808SJens Wiklander     }
214817466cbSJens Wiklander 
215817466cbSJens Wiklander     ctx->pk_info = info;
216817466cbSJens Wiklander 
217817466cbSJens Wiklander     rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;
218817466cbSJens Wiklander 
219817466cbSJens Wiklander     rsa_alt->key = key;
220817466cbSJens Wiklander     rsa_alt->decrypt_func = decrypt_func;
221817466cbSJens Wiklander     rsa_alt->sign_func = sign_func;
222817466cbSJens Wiklander     rsa_alt->key_len_func = key_len_func;
223817466cbSJens Wiklander 
22432b31808SJens Wiklander     return 0;
225817466cbSJens Wiklander }
226817466cbSJens Wiklander #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
227817466cbSJens Wiklander 
228817466cbSJens Wiklander /*
229817466cbSJens Wiklander  * Tell if a PK can do the operations of the given type
230817466cbSJens Wiklander  */
231817466cbSJens Wiklander int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type)
232817466cbSJens Wiklander {
2333d3b0591SJens Wiklander     /* A context with null pk_info is not set up yet and can't do anything.
2343d3b0591SJens Wiklander      * For backward compatibility, also accept NULL instead of a context
2353d3b0591SJens Wiklander      * pointer. */
23632b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
23732b31808SJens Wiklander         return 0;
238817466cbSJens Wiklander     }
239817466cbSJens Wiklander 
24032b31808SJens Wiklander     return ctx->pk_info->can_do(type);
24132b31808SJens Wiklander }
24232b31808SJens Wiklander 
24332b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
24432b31808SJens Wiklander /*
24532b31808SJens Wiklander  * Tell if a PK can do the operations of the given PSA algorithm
24632b31808SJens Wiklander  */
24732b31808SJens Wiklander int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
24832b31808SJens Wiklander                           psa_key_usage_t usage)
24932b31808SJens Wiklander {
25032b31808SJens Wiklander     psa_key_usage_t key_usage;
25132b31808SJens Wiklander 
25232b31808SJens Wiklander     /* A context with null pk_info is not set up yet and can't do anything.
25332b31808SJens Wiklander      * For backward compatibility, also accept NULL instead of a context
25432b31808SJens Wiklander      * pointer. */
25532b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
25632b31808SJens Wiklander         return 0;
25732b31808SJens Wiklander     }
25832b31808SJens Wiklander 
25932b31808SJens Wiklander     /* Filter out non allowed algorithms */
26032b31808SJens Wiklander     if (PSA_ALG_IS_ECDSA(alg) == 0 &&
26132b31808SJens Wiklander         PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 &&
26232b31808SJens Wiklander         PSA_ALG_IS_RSA_PSS(alg) == 0 &&
26332b31808SJens Wiklander         alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
26432b31808SJens Wiklander         PSA_ALG_IS_ECDH(alg) == 0) {
26532b31808SJens Wiklander         return 0;
26632b31808SJens Wiklander     }
26732b31808SJens Wiklander 
26832b31808SJens Wiklander     /* Filter out non allowed usage flags */
26932b31808SJens Wiklander     if (usage == 0 ||
27032b31808SJens Wiklander         (usage & ~(PSA_KEY_USAGE_SIGN_HASH |
27132b31808SJens Wiklander                    PSA_KEY_USAGE_DECRYPT |
27232b31808SJens Wiklander                    PSA_KEY_USAGE_DERIVE)) != 0) {
27332b31808SJens Wiklander         return 0;
27432b31808SJens Wiklander     }
27532b31808SJens Wiklander 
27632b31808SJens Wiklander     /* Wildcard hash is not allowed */
27732b31808SJens Wiklander     if (PSA_ALG_IS_SIGN_HASH(alg) &&
27832b31808SJens Wiklander         PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) {
27932b31808SJens Wiklander         return 0;
28032b31808SJens Wiklander     }
28132b31808SJens Wiklander 
28232b31808SJens Wiklander     if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) {
28332b31808SJens Wiklander         mbedtls_pk_type_t type;
28432b31808SJens Wiklander 
28532b31808SJens Wiklander         if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) {
28632b31808SJens Wiklander             type = MBEDTLS_PK_ECKEY;
28732b31808SJens Wiklander         } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
28832b31808SJens Wiklander                    alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
28932b31808SJens Wiklander             type = MBEDTLS_PK_RSA;
29032b31808SJens Wiklander         } else if (PSA_ALG_IS_RSA_PSS(alg)) {
29132b31808SJens Wiklander             type = MBEDTLS_PK_RSASSA_PSS;
29232b31808SJens Wiklander         } else {
29332b31808SJens Wiklander             return 0;
29432b31808SJens Wiklander         }
29532b31808SJens Wiklander 
29632b31808SJens Wiklander         if (ctx->pk_info->can_do(type) == 0) {
29732b31808SJens Wiklander             return 0;
29832b31808SJens Wiklander         }
29932b31808SJens Wiklander 
30032b31808SJens Wiklander         switch (type) {
30132b31808SJens Wiklander             case MBEDTLS_PK_ECKEY:
30232b31808SJens Wiklander                 key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
30332b31808SJens Wiklander                 break;
30432b31808SJens Wiklander             case MBEDTLS_PK_RSA:
30532b31808SJens Wiklander             case MBEDTLS_PK_RSASSA_PSS:
30632b31808SJens Wiklander                 key_usage = PSA_KEY_USAGE_SIGN_HASH |
30732b31808SJens Wiklander                             PSA_KEY_USAGE_SIGN_MESSAGE |
30832b31808SJens Wiklander                             PSA_KEY_USAGE_DECRYPT;
30932b31808SJens Wiklander                 break;
31032b31808SJens Wiklander             default:
31132b31808SJens Wiklander                 /* Should never happen */
31232b31808SJens Wiklander                 return 0;
31332b31808SJens Wiklander         }
31432b31808SJens Wiklander 
31532b31808SJens Wiklander         return (key_usage & usage) == usage;
31632b31808SJens Wiklander     }
31732b31808SJens Wiklander 
31832b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
31932b31808SJens Wiklander     psa_status_t status;
32032b31808SJens Wiklander 
321*b0563631STom Van Eyck     status = psa_get_key_attributes(ctx->priv_id, &attributes);
32232b31808SJens Wiklander     if (status != PSA_SUCCESS) {
32332b31808SJens Wiklander         return 0;
32432b31808SJens Wiklander     }
32532b31808SJens Wiklander 
326*b0563631STom Van Eyck     psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
327*b0563631STom Van Eyck     /* Key's enrollment is available only when an Mbed TLS implementation of PSA
328*b0563631STom Van Eyck      * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
329*b0563631STom Van Eyck      * Even though we don't officially support using other implementations of PSA
330*b0563631STom Van Eyck      * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
331*b0563631STom Van Eyck      * separated. */
332*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
333*b0563631STom Van Eyck     psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
334*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
33532b31808SJens Wiklander     key_usage = psa_get_key_usage_flags(&attributes);
33632b31808SJens Wiklander     psa_reset_key_attributes(&attributes);
33732b31808SJens Wiklander 
33832b31808SJens Wiklander     if ((key_usage & usage) != usage) {
33932b31808SJens Wiklander         return 0;
34032b31808SJens Wiklander     }
34132b31808SJens Wiklander 
34232b31808SJens Wiklander     /*
343*b0563631STom Van Eyck      * Common case: the key alg [or alg2] only allows alg.
34432b31808SJens Wiklander      * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
34532b31808SJens Wiklander      * directly.
34632b31808SJens Wiklander      * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
347*b0563631STom Van Eyck      * a fixed hash on key_alg [or key_alg2].
34832b31808SJens Wiklander      */
349*b0563631STom Van Eyck     if (alg == key_alg) {
35032b31808SJens Wiklander         return 1;
35132b31808SJens Wiklander     }
352*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
353*b0563631STom Van Eyck     if (alg == key_alg2) {
354*b0563631STom Van Eyck         return 1;
355*b0563631STom Van Eyck     }
356*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
35732b31808SJens Wiklander 
35832b31808SJens Wiklander     /*
359*b0563631STom Van Eyck      * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash,
36032b31808SJens Wiklander      * and alg is the same hash-and-sign family with any hash,
36132b31808SJens Wiklander      * then alg is compliant with this key alg
36232b31808SJens Wiklander      */
36332b31808SJens Wiklander     if (PSA_ALG_IS_SIGN_HASH(alg)) {
36432b31808SJens Wiklander         if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
36532b31808SJens Wiklander             PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
36632b31808SJens Wiklander             (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
36732b31808SJens Wiklander             return 1;
36832b31808SJens Wiklander         }
369*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
37032b31808SJens Wiklander         if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
37132b31808SJens Wiklander             PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
37232b31808SJens Wiklander             (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
37332b31808SJens Wiklander             return 1;
37432b31808SJens Wiklander         }
375*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
37632b31808SJens Wiklander     }
37732b31808SJens Wiklander 
37832b31808SJens Wiklander     return 0;
37932b31808SJens Wiklander }
38032b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */
38132b31808SJens Wiklander 
382*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
383*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
384*b0563631STom Van Eyck static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
385*b0563631STom Van Eyck                                              int want_crypt)
386*b0563631STom Van Eyck {
387*b0563631STom Van Eyck     if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
388*b0563631STom Van Eyck         if (want_crypt) {
389*b0563631STom Van Eyck             mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);
390*b0563631STom Van Eyck             return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));
391*b0563631STom Van Eyck         } else {
392*b0563631STom Van Eyck             return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);
393*b0563631STom Van Eyck         }
394*b0563631STom Van Eyck     } else {
395*b0563631STom Van Eyck         if (want_crypt) {
396*b0563631STom Van Eyck             return PSA_ALG_RSA_PKCS1V15_CRYPT;
397*b0563631STom Van Eyck         } else {
398*b0563631STom Van Eyck             return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);
399*b0563631STom Van Eyck         }
400*b0563631STom Van Eyck     }
401*b0563631STom Van Eyck }
402*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
403*b0563631STom Van Eyck 
404*b0563631STom Van Eyck int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
405*b0563631STom Van Eyck                                   psa_key_usage_t usage,
406*b0563631STom Van Eyck                                   psa_key_attributes_t *attributes)
407*b0563631STom Van Eyck {
408*b0563631STom Van Eyck     mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
409*b0563631STom Van Eyck 
410*b0563631STom Van Eyck     psa_key_usage_t more_usage = usage;
411*b0563631STom Van Eyck     if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {
412*b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
413*b0563631STom Van Eyck     } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {
414*b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_VERIFY_HASH;
415*b0563631STom Van Eyck     } else if (usage == PSA_KEY_USAGE_DECRYPT) {
416*b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_ENCRYPT;
417*b0563631STom Van Eyck     }
418*b0563631STom Van Eyck     more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
419*b0563631STom Van Eyck 
420*b0563631STom Van Eyck     int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE ||
421*b0563631STom Van Eyck                          usage == PSA_KEY_USAGE_VERIFY_HASH ||
422*b0563631STom Van Eyck                          usage == PSA_KEY_USAGE_ENCRYPT);
423*b0563631STom Van Eyck 
424*b0563631STom Van Eyck     switch (pk_type) {
425*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
426*b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
427*b0563631STom Van Eyck         {
428*b0563631STom Van Eyck             int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */
429*b0563631STom Van Eyck             switch (usage) {
430*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
431*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
432*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
433*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
434*b0563631STom Van Eyck                     /* Nothing to do. */
435*b0563631STom Van Eyck                     break;
436*b0563631STom Van Eyck                 case PSA_KEY_USAGE_DECRYPT:
437*b0563631STom Van Eyck                 case PSA_KEY_USAGE_ENCRYPT:
438*b0563631STom Van Eyck                     want_crypt = 1;
439*b0563631STom Van Eyck                     break;
440*b0563631STom Van Eyck                 default:
441*b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
442*b0563631STom Van Eyck             }
443*b0563631STom Van Eyck             /* Detect the presence of a private key in a way that works both
444*b0563631STom Van Eyck              * in CRT and non-CRT configurations. */
445*b0563631STom Van Eyck             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
446*b0563631STom Van Eyck             int has_private = (mbedtls_rsa_check_privkey(rsa) == 0);
447*b0563631STom Van Eyck             if (want_private && !has_private) {
448*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
449*b0563631STom Van Eyck             }
450*b0563631STom Van Eyck             psa_set_key_type(attributes, (want_private ?
451*b0563631STom Van Eyck                                           PSA_KEY_TYPE_RSA_KEY_PAIR :
452*b0563631STom Van Eyck                                           PSA_KEY_TYPE_RSA_PUBLIC_KEY));
453*b0563631STom Van Eyck             psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk));
454*b0563631STom Van Eyck             psa_set_key_algorithm(attributes,
455*b0563631STom Van Eyck                                   psa_algorithm_for_rsa(rsa, want_crypt));
456*b0563631STom Van Eyck             break;
457*b0563631STom Van Eyck         }
458*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
459*b0563631STom Van Eyck 
460*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
461*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
462*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
463*b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
464*b0563631STom Van Eyck         {
465*b0563631STom Van Eyck             int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);
466*b0563631STom Van Eyck             int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);
467*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
468*b0563631STom Van Eyck             psa_ecc_family_t family = pk->ec_family;
469*b0563631STom Van Eyck             size_t bits = pk->ec_bits;
470*b0563631STom Van Eyck             int has_private = 0;
471*b0563631STom Van Eyck             if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) {
472*b0563631STom Van Eyck                 has_private = 1;
473*b0563631STom Van Eyck             }
474*b0563631STom Van Eyck #else
475*b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
476*b0563631STom Van Eyck             int has_private = (ec->d.n != 0);
477*b0563631STom Van Eyck             size_t bits = 0;
478*b0563631STom Van Eyck             psa_ecc_family_t family =
479*b0563631STom Van Eyck                 mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
480*b0563631STom Van Eyck #endif
481*b0563631STom Van Eyck             psa_algorithm_t alg = 0;
482*b0563631STom Van Eyck             switch (usage) {
483*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
484*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
485*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
486*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
487*b0563631STom Van Eyck                     if (!sign_ok) {
488*b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
489*b0563631STom Van Eyck                     }
490*b0563631STom Van Eyck #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
491*b0563631STom Van Eyck                     alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
492*b0563631STom Van Eyck #else
493*b0563631STom Van Eyck                     alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
494*b0563631STom Van Eyck #endif
495*b0563631STom Van Eyck                     break;
496*b0563631STom Van Eyck                 case PSA_KEY_USAGE_DERIVE:
497*b0563631STom Van Eyck                     alg = PSA_ALG_ECDH;
498*b0563631STom Van Eyck                     if (!derive_ok) {
499*b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
500*b0563631STom Van Eyck                     }
501*b0563631STom Van Eyck                     break;
502*b0563631STom Van Eyck                 default:
503*b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
504*b0563631STom Van Eyck             }
505*b0563631STom Van Eyck             if (want_private && !has_private) {
506*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
507*b0563631STom Van Eyck             }
508*b0563631STom Van Eyck             psa_set_key_type(attributes, (want_private ?
509*b0563631STom Van Eyck                                           PSA_KEY_TYPE_ECC_KEY_PAIR(family) :
510*b0563631STom Van Eyck                                           PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));
511*b0563631STom Van Eyck             psa_set_key_bits(attributes, bits);
512*b0563631STom Van Eyck             psa_set_key_algorithm(attributes, alg);
513*b0563631STom Van Eyck             break;
514*b0563631STom Van Eyck         }
515*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
516*b0563631STom Van Eyck 
517*b0563631STom Van Eyck #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
518*b0563631STom Van Eyck         case MBEDTLS_PK_RSA_ALT:
519*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
520*b0563631STom Van Eyck #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
521*b0563631STom Van Eyck 
522*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
523*b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
524*b0563631STom Van Eyck         {
525*b0563631STom Van Eyck             psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
526*b0563631STom Van Eyck             psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
527*b0563631STom Van Eyck             status = psa_get_key_attributes(pk->priv_id, &old_attributes);
528*b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
529*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
530*b0563631STom Van Eyck             }
531*b0563631STom Van Eyck             psa_key_type_t old_type = psa_get_key_type(&old_attributes);
532*b0563631STom Van Eyck             switch (usage) {
533*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
534*b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
535*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
536*b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
537*b0563631STom Van Eyck                     if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) ||
538*b0563631STom Van Eyck                           old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) {
539*b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
540*b0563631STom Van Eyck                     }
541*b0563631STom Van Eyck                     break;
542*b0563631STom Van Eyck                 case PSA_KEY_USAGE_DECRYPT:
543*b0563631STom Van Eyck                 case PSA_KEY_USAGE_ENCRYPT:
544*b0563631STom Van Eyck                     if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) {
545*b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
546*b0563631STom Van Eyck                     }
547*b0563631STom Van Eyck                     break;
548*b0563631STom Van Eyck                 case PSA_KEY_USAGE_DERIVE:
549*b0563631STom Van Eyck                     if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) {
550*b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
551*b0563631STom Van Eyck                     }
552*b0563631STom Van Eyck                     break;
553*b0563631STom Van Eyck                 default:
554*b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
555*b0563631STom Van Eyck             }
556*b0563631STom Van Eyck             psa_key_type_t new_type = old_type;
557*b0563631STom Van Eyck             /* Opaque keys are always key pairs, so we don't need a check
558*b0563631STom Van Eyck              * on the input if the required usage is private. We just need
559*b0563631STom Van Eyck              * to adjust the type correctly if the required usage is public. */
560*b0563631STom Van Eyck             if (!want_private) {
561*b0563631STom Van Eyck                 new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type);
562*b0563631STom Van Eyck             }
563*b0563631STom Van Eyck             more_usage = psa_get_key_usage_flags(&old_attributes);
564*b0563631STom Van Eyck             if ((usage & more_usage) == 0) {
565*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
566*b0563631STom Van Eyck             }
567*b0563631STom Van Eyck             psa_set_key_type(attributes, new_type);
568*b0563631STom Van Eyck             psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes));
569*b0563631STom Van Eyck             psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes));
570*b0563631STom Van Eyck             break;
571*b0563631STom Van Eyck         }
572*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
573*b0563631STom Van Eyck 
574*b0563631STom Van Eyck         default:
575*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
576*b0563631STom Van Eyck     }
577*b0563631STom Van Eyck 
578*b0563631STom Van Eyck     psa_set_key_usage_flags(attributes, more_usage);
579*b0563631STom Van Eyck     /* Key's enrollment is available only when an Mbed TLS implementation of PSA
580*b0563631STom Van Eyck      * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
581*b0563631STom Van Eyck      * Even though we don't officially support using other implementations of PSA
582*b0563631STom Van Eyck      * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
583*b0563631STom Van Eyck      * separated. */
584*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
585*b0563631STom Van Eyck     psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
586*b0563631STom Van Eyck #endif
587*b0563631STom Van Eyck 
588*b0563631STom Van Eyck     return 0;
589*b0563631STom Van Eyck }
590*b0563631STom Van Eyck 
591*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
592*b0563631STom Van Eyck static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
593*b0563631STom Van Eyck                                            const psa_key_attributes_t *attributes,
594*b0563631STom Van Eyck                                            mbedtls_svc_key_id_t *new_key_id)
595*b0563631STom Van Eyck {
596*b0563631STom Van Eyck     unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
597*b0563631STom Van Eyck     size_t key_length = 0;
598*b0563631STom Van Eyck     psa_status_t status = psa_export_key(old_key_id,
599*b0563631STom Van Eyck                                          key_buffer, sizeof(key_buffer),
600*b0563631STom Van Eyck                                          &key_length);
601*b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
602*b0563631STom Van Eyck         return status;
603*b0563631STom Van Eyck     }
604*b0563631STom Van Eyck     status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
605*b0563631STom Van Eyck     mbedtls_platform_zeroize(key_buffer, key_length);
606*b0563631STom Van Eyck     return status;
607*b0563631STom Van Eyck }
608*b0563631STom Van Eyck 
609*b0563631STom Van Eyck static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
610*b0563631STom Van Eyck                          const psa_key_attributes_t *attributes,
611*b0563631STom Van Eyck                          mbedtls_svc_key_id_t *new_key_id)
612*b0563631STom Van Eyck {
613*b0563631STom Van Eyck     /* Normally, we prefer copying: it's more efficient and works even
614*b0563631STom Van Eyck      * for non-exportable keys. */
615*b0563631STom Van Eyck     psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
616*b0563631STom Van Eyck     if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||
617*b0563631STom Van Eyck         status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {
618*b0563631STom Van Eyck         /* There are edge cases where copying won't work, but export+import
619*b0563631STom Van Eyck          * might:
620*b0563631STom Van Eyck          * - If the old key does not allow PSA_KEY_USAGE_COPY.
621*b0563631STom Van Eyck          * - If the old key's usage does not allow what attributes wants.
622*b0563631STom Van Eyck          *   Because the key was intended for use in the pk module, and may
623*b0563631STom Van Eyck          *   have had a policy chosen solely for what pk needs rather than
624*b0563631STom Van Eyck          *   based on a detailed understanding of PSA policies, we are a bit
625*b0563631STom Van Eyck          *   more liberal than psa_copy_key() here.
626*b0563631STom Van Eyck          */
627*b0563631STom Van Eyck         /* Here we need to check that the types match, otherwise we risk
628*b0563631STom Van Eyck          * importing nonsensical data. */
629*b0563631STom Van Eyck         psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
630*b0563631STom Van Eyck         status = psa_get_key_attributes(old_key_id, &old_attributes);
631*b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
632*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
633*b0563631STom Van Eyck         }
634*b0563631STom Van Eyck         psa_key_type_t old_type = psa_get_key_type(&old_attributes);
635*b0563631STom Van Eyck         psa_reset_key_attributes(&old_attributes);
636*b0563631STom Van Eyck         if (old_type != psa_get_key_type(attributes)) {
637*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
638*b0563631STom Van Eyck         }
639*b0563631STom Van Eyck         status = export_import_into_psa(old_key_id, attributes, new_key_id);
640*b0563631STom Van Eyck     }
641*b0563631STom Van Eyck     return PSA_PK_TO_MBEDTLS_ERR(status);
642*b0563631STom Van Eyck }
643*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */
644*b0563631STom Van Eyck 
645*b0563631STom Van Eyck static int import_pair_into_psa(const mbedtls_pk_context *pk,
646*b0563631STom Van Eyck                                 const psa_key_attributes_t *attributes,
647*b0563631STom Van Eyck                                 mbedtls_svc_key_id_t *key_id)
648*b0563631STom Van Eyck {
649*b0563631STom Van Eyck     switch (mbedtls_pk_get_type(pk)) {
650*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
651*b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
652*b0563631STom Van Eyck         {
653*b0563631STom Van Eyck             if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {
654*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
655*b0563631STom Van Eyck             }
656*b0563631STom Van Eyck             unsigned char key_buffer[
657*b0563631STom Van Eyck                 PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];
658*b0563631STom Van Eyck             unsigned char *const key_end = key_buffer + sizeof(key_buffer);
659*b0563631STom Van Eyck             unsigned char *key_data = key_end;
660*b0563631STom Van Eyck             int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),
661*b0563631STom Van Eyck                                             key_buffer, &key_data);
662*b0563631STom Van Eyck             if (ret < 0) {
663*b0563631STom Van Eyck                 return ret;
664*b0563631STom Van Eyck             }
665*b0563631STom Van Eyck             size_t key_length = key_end - key_data;
666*b0563631STom Van Eyck             ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
667*b0563631STom Van Eyck                                                        key_data, key_length,
668*b0563631STom Van Eyck                                                        key_id));
669*b0563631STom Van Eyck             mbedtls_platform_zeroize(key_data, key_length);
670*b0563631STom Van Eyck             return ret;
671*b0563631STom Van Eyck         }
672*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
673*b0563631STom Van Eyck 
674*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
675*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
676*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
677*b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
678*b0563631STom Van Eyck         {
679*b0563631STom Van Eyck             /* We need to check the curve family, otherwise the import could
680*b0563631STom Van Eyck              * succeed with nonsensical data.
681*b0563631STom Van Eyck              * We don't check the bit-size: it's optional in attributes,
682*b0563631STom Van Eyck              * and if it's specified, psa_import_key() will know from the key
683*b0563631STom Van Eyck              * data length and will check that the bit-size matches. */
684*b0563631STom Van Eyck             psa_key_type_t to_type = psa_get_key_type(attributes);
685*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
686*b0563631STom Van Eyck             psa_ecc_family_t from_family = pk->ec_family;
687*b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
688*b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
689*b0563631STom Van Eyck             size_t from_bits = 0;
690*b0563631STom Van Eyck             psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
691*b0563631STom Van Eyck                                                                     &from_bits);
692*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
693*b0563631STom Van Eyck             if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {
694*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
695*b0563631STom Van Eyck             }
696*b0563631STom Van Eyck 
697*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
698*b0563631STom Van Eyck             if (mbedtls_svc_key_id_is_null(pk->priv_id)) {
699*b0563631STom Van Eyck                 /* We have a public key and want a key pair. */
700*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
701*b0563631STom Van Eyck             }
702*b0563631STom Van Eyck             return copy_into_psa(pk->priv_id, attributes, key_id);
703*b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
704*b0563631STom Van Eyck             if (ec->d.n == 0) {
705*b0563631STom Van Eyck                 /* Private key not set. Assume the input is a public key only.
706*b0563631STom Van Eyck                  * (The other possibility is that it's an incomplete object
707*b0563631STom Van Eyck                  * where the group is set but neither the public key nor
708*b0563631STom Van Eyck                  * the private key. This is not possible through ecp.h
709*b0563631STom Van Eyck                  * functions, so we don't bother reporting a more suitable
710*b0563631STom Van Eyck                  * error in that case.) */
711*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
712*b0563631STom Van Eyck             }
713*b0563631STom Van Eyck             unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
714*b0563631STom Van Eyck             size_t key_length = 0;
715*b0563631STom Van Eyck             int ret = mbedtls_ecp_write_key_ext(ec, &key_length,
716*b0563631STom Van Eyck                                                 key_buffer, sizeof(key_buffer));
717*b0563631STom Van Eyck             if (ret < 0) {
718*b0563631STom Van Eyck                 return ret;
719*b0563631STom Van Eyck             }
720*b0563631STom Van Eyck             ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
721*b0563631STom Van Eyck                                                        key_buffer, key_length,
722*b0563631STom Van Eyck                                                        key_id));
723*b0563631STom Van Eyck             mbedtls_platform_zeroize(key_buffer, key_length);
724*b0563631STom Van Eyck             return ret;
725*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
726*b0563631STom Van Eyck         }
727*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
728*b0563631STom Van Eyck 
729*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
730*b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
731*b0563631STom Van Eyck             return copy_into_psa(pk->priv_id, attributes, key_id);
732*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
733*b0563631STom Van Eyck 
734*b0563631STom Van Eyck         default:
735*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
736*b0563631STom Van Eyck     }
737*b0563631STom Van Eyck }
738*b0563631STom Van Eyck 
739*b0563631STom Van Eyck static int import_public_into_psa(const mbedtls_pk_context *pk,
740*b0563631STom Van Eyck                                   const psa_key_attributes_t *attributes,
741*b0563631STom Van Eyck                                   mbedtls_svc_key_id_t *key_id)
742*b0563631STom Van Eyck {
743*b0563631STom Van Eyck     psa_key_type_t psa_type = psa_get_key_type(attributes);
744*b0563631STom Van Eyck 
745*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C) ||                                           \
746*b0563631STom Van Eyck     (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \
747*b0563631STom Van Eyck     defined(MBEDTLS_USE_PSA_CRYPTO)
748*b0563631STom Van Eyck     unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
749*b0563631STom Van Eyck #endif
750*b0563631STom Van Eyck     unsigned char *key_data = NULL;
751*b0563631STom Van Eyck     size_t key_length = 0;
752*b0563631STom Van Eyck 
753*b0563631STom Van Eyck     switch (mbedtls_pk_get_type(pk)) {
754*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
755*b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
756*b0563631STom Van Eyck         {
757*b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
758*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
759*b0563631STom Van Eyck             }
760*b0563631STom Van Eyck             unsigned char *const key_end = key_buffer + sizeof(key_buffer);
761*b0563631STom Van Eyck             key_data = key_end;
762*b0563631STom Van Eyck             int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),
763*b0563631STom Van Eyck                                                key_buffer, &key_data);
764*b0563631STom Van Eyck             if (ret < 0) {
765*b0563631STom Van Eyck                 return ret;
766*b0563631STom Van Eyck             }
767*b0563631STom Van Eyck             key_length = (size_t) ret;
768*b0563631STom Van Eyck             break;
769*b0563631STom Van Eyck         }
770*b0563631STom Van Eyck #endif /*MBEDTLS_RSA_C */
771*b0563631STom Van Eyck 
772*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
773*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
774*b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
775*b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
776*b0563631STom Van Eyck         {
777*b0563631STom Van Eyck             /* We need to check the curve family, otherwise the import could
778*b0563631STom Van Eyck              * succeed with nonsensical data.
779*b0563631STom Van Eyck              * We don't check the bit-size: it's optional in attributes,
780*b0563631STom Van Eyck              * and if it's specified, psa_import_key() will know from the key
781*b0563631STom Van Eyck              * data length and will check that the bit-size matches. */
782*b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
783*b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {
784*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
785*b0563631STom Van Eyck             }
786*b0563631STom Van Eyck             key_data = (unsigned char *) pk->pub_raw;
787*b0563631STom Van Eyck             key_length = pk->pub_raw_len;
788*b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
789*b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
790*b0563631STom Van Eyck             size_t from_bits = 0;
791*b0563631STom Van Eyck             psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
792*b0563631STom Van Eyck                                                                     &from_bits);
793*b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {
794*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
795*b0563631STom Van Eyck             }
796*b0563631STom Van Eyck             int ret = mbedtls_ecp_write_public_key(
797*b0563631STom Van Eyck                 ec, MBEDTLS_ECP_PF_UNCOMPRESSED,
798*b0563631STom Van Eyck                 &key_length, key_buffer, sizeof(key_buffer));
799*b0563631STom Van Eyck             if (ret < 0) {
800*b0563631STom Van Eyck                 return ret;
801*b0563631STom Van Eyck             }
802*b0563631STom Van Eyck             key_data = key_buffer;
803*b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
804*b0563631STom Van Eyck             break;
805*b0563631STom Van Eyck         }
806*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
807*b0563631STom Van Eyck 
808*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
809*b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
810*b0563631STom Van Eyck         {
811*b0563631STom Van Eyck             psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
812*b0563631STom Van Eyck             psa_status_t status =
813*b0563631STom Van Eyck                 psa_get_key_attributes(pk->priv_id, &old_attributes);
814*b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
815*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
816*b0563631STom Van Eyck             }
817*b0563631STom Van Eyck             psa_key_type_t old_type = psa_get_key_type(&old_attributes);
818*b0563631STom Van Eyck             psa_reset_key_attributes(&old_attributes);
819*b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {
820*b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
821*b0563631STom Van Eyck             }
822*b0563631STom Van Eyck             status = psa_export_public_key(pk->priv_id,
823*b0563631STom Van Eyck                                            key_buffer, sizeof(key_buffer),
824*b0563631STom Van Eyck                                            &key_length);
825*b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
826*b0563631STom Van Eyck                 return PSA_PK_TO_MBEDTLS_ERR(status);
827*b0563631STom Van Eyck             }
828*b0563631STom Van Eyck             key_data = key_buffer;
829*b0563631STom Van Eyck             break;
830*b0563631STom Van Eyck         }
831*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
832*b0563631STom Van Eyck 
833*b0563631STom Van Eyck         default:
834*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
835*b0563631STom Van Eyck     }
836*b0563631STom Van Eyck 
837*b0563631STom Van Eyck     return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
838*b0563631STom Van Eyck                                                 key_data, key_length,
839*b0563631STom Van Eyck                                                 key_id));
840*b0563631STom Van Eyck }
841*b0563631STom Van Eyck 
842*b0563631STom Van Eyck int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
843*b0563631STom Van Eyck                                const psa_key_attributes_t *attributes,
844*b0563631STom Van Eyck                                mbedtls_svc_key_id_t *key_id)
845*b0563631STom Van Eyck {
846*b0563631STom Van Eyck     /* Set the output immediately so that it won't contain garbage even
847*b0563631STom Van Eyck      * if we error out before calling psa_import_key(). */
848*b0563631STom Van Eyck     *key_id = MBEDTLS_SVC_KEY_ID_INIT;
849*b0563631STom Van Eyck 
850*b0563631STom Van Eyck #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
851*b0563631STom Van Eyck     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {
852*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
853*b0563631STom Van Eyck     }
854*b0563631STom Van Eyck #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
855*b0563631STom Van Eyck 
856*b0563631STom Van Eyck     int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));
857*b0563631STom Van Eyck     if (want_public) {
858*b0563631STom Van Eyck         return import_public_into_psa(pk, attributes, key_id);
859*b0563631STom Van Eyck     } else {
860*b0563631STom Van Eyck         return import_pair_into_psa(pk, attributes, key_id);
861*b0563631STom Van Eyck     }
862*b0563631STom Van Eyck }
863*b0563631STom Van Eyck 
864*b0563631STom Van Eyck static int copy_from_psa(mbedtls_svc_key_id_t key_id,
865*b0563631STom Van Eyck                          mbedtls_pk_context *pk,
866*b0563631STom Van Eyck                          int public_only)
867*b0563631STom Van Eyck {
868*b0563631STom Van Eyck     psa_status_t status;
869*b0563631STom Van Eyck     psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
870*b0563631STom Van Eyck     psa_key_type_t key_type;
871*b0563631STom Van Eyck     psa_algorithm_t alg_type;
872*b0563631STom Van Eyck     size_t key_bits;
873*b0563631STom Van Eyck     /* Use a buffer size large enough to contain either a key pair or public key. */
874*b0563631STom Van Eyck     unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
875*b0563631STom Van Eyck     size_t exp_key_len;
876*b0563631STom Van Eyck     int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
877*b0563631STom Van Eyck 
878*b0563631STom Van Eyck     if (pk == NULL) {
879*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
880*b0563631STom Van Eyck     }
881*b0563631STom Van Eyck 
882*b0563631STom Van Eyck     status = psa_get_key_attributes(key_id, &key_attr);
883*b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
884*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
885*b0563631STom Van Eyck     }
886*b0563631STom Van Eyck 
887*b0563631STom Van Eyck     if (public_only) {
888*b0563631STom Van Eyck         status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
889*b0563631STom Van Eyck     } else {
890*b0563631STom Van Eyck         status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
891*b0563631STom Van Eyck     }
892*b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
893*b0563631STom Van Eyck         ret = PSA_PK_TO_MBEDTLS_ERR(status);
894*b0563631STom Van Eyck         goto exit;
895*b0563631STom Van Eyck     }
896*b0563631STom Van Eyck 
897*b0563631STom Van Eyck     key_type = psa_get_key_type(&key_attr);
898*b0563631STom Van Eyck     if (public_only) {
899*b0563631STom Van Eyck         key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
900*b0563631STom Van Eyck     }
901*b0563631STom Van Eyck     key_bits = psa_get_key_bits(&key_attr);
902*b0563631STom Van Eyck     alg_type = psa_get_key_algorithm(&key_attr);
903*b0563631STom Van Eyck 
904*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
905*b0563631STom Van Eyck     if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
906*b0563631STom Van Eyck         (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {
907*b0563631STom Van Eyck 
908*b0563631STom Van Eyck         ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
909*b0563631STom Van Eyck         if (ret != 0) {
910*b0563631STom Van Eyck             goto exit;
911*b0563631STom Van Eyck         }
912*b0563631STom Van Eyck 
913*b0563631STom Van Eyck         if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
914*b0563631STom Van Eyck             ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
915*b0563631STom Van Eyck         } else {
916*b0563631STom Van Eyck             ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
917*b0563631STom Van Eyck         }
918*b0563631STom Van Eyck         if (ret != 0) {
919*b0563631STom Van Eyck             goto exit;
920*b0563631STom Van Eyck         }
921*b0563631STom Van Eyck 
922*b0563631STom Van Eyck         mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
923*b0563631STom Van Eyck         if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
924*b0563631STom Van Eyck             md_type = mbedtls_md_type_from_psa_alg(alg_type);
925*b0563631STom Van Eyck         }
926*b0563631STom Van Eyck 
927*b0563631STom Van Eyck         if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {
928*b0563631STom Van Eyck             ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);
929*b0563631STom Van Eyck         } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||
930*b0563631STom Van Eyck                    alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {
931*b0563631STom Van Eyck             ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);
932*b0563631STom Van Eyck         }
933*b0563631STom Van Eyck         if (ret != 0) {
934*b0563631STom Van Eyck             goto exit;
935*b0563631STom Van Eyck         }
936*b0563631STom Van Eyck     } else
937*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
938*b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
939*b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
940*b0563631STom Van Eyck         PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {
941*b0563631STom Van Eyck         mbedtls_ecp_group_id grp_id;
942*b0563631STom Van Eyck 
943*b0563631STom Van Eyck         ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
944*b0563631STom Van Eyck         if (ret != 0) {
945*b0563631STom Van Eyck             goto exit;
946*b0563631STom Van Eyck         }
947*b0563631STom Van Eyck 
948*b0563631STom Van Eyck         grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);
949*b0563631STom Van Eyck         ret = mbedtls_pk_ecc_set_group(pk, grp_id);
950*b0563631STom Van Eyck         if (ret != 0) {
951*b0563631STom Van Eyck             goto exit;
952*b0563631STom Van Eyck         }
953*b0563631STom Van Eyck 
954*b0563631STom Van Eyck         if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
955*b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);
956*b0563631STom Van Eyck             if (ret != 0) {
957*b0563631STom Van Eyck                 goto exit;
958*b0563631STom Van Eyck             }
959*b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,
960*b0563631STom Van Eyck                                                      mbedtls_psa_get_random,
961*b0563631STom Van Eyck                                                      MBEDTLS_PSA_RANDOM_STATE);
962*b0563631STom Van Eyck         } else {
963*b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);
964*b0563631STom Van Eyck         }
965*b0563631STom Van Eyck         if (ret != 0) {
966*b0563631STom Van Eyck             goto exit;
967*b0563631STom Van Eyck         }
968*b0563631STom Van Eyck     } else
969*b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
970*b0563631STom Van Eyck     {
971*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
972*b0563631STom Van Eyck     }
973*b0563631STom Van Eyck 
974*b0563631STom Van Eyck exit:
975*b0563631STom Van Eyck     psa_reset_key_attributes(&key_attr);
976*b0563631STom Van Eyck     mbedtls_platform_zeroize(exp_key, sizeof(exp_key));
977*b0563631STom Van Eyck 
978*b0563631STom Van Eyck     return ret;
979*b0563631STom Van Eyck }
980*b0563631STom Van Eyck 
981*b0563631STom Van Eyck int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
982*b0563631STom Van Eyck                              mbedtls_pk_context *pk)
983*b0563631STom Van Eyck {
984*b0563631STom Van Eyck     return copy_from_psa(key_id, pk, 0);
985*b0563631STom Van Eyck }
986*b0563631STom Van Eyck 
987*b0563631STom Van Eyck int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
988*b0563631STom Van Eyck                                     mbedtls_pk_context *pk)
989*b0563631STom Van Eyck {
990*b0563631STom Van Eyck     return copy_from_psa(key_id, pk, 1);
991*b0563631STom Van Eyck }
992*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
993*b0563631STom Van Eyck 
994817466cbSJens Wiklander /*
995817466cbSJens Wiklander  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
996817466cbSJens Wiklander  */
997817466cbSJens Wiklander static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
998817466cbSJens Wiklander {
99932b31808SJens Wiklander     if (*hash_len != 0) {
100032b31808SJens Wiklander         return 0;
100132b31808SJens Wiklander     }
1002817466cbSJens Wiklander 
1003*b0563631STom Van Eyck     *hash_len = mbedtls_md_get_size_from_type(md_alg);
1004817466cbSJens Wiklander 
100532b31808SJens Wiklander     if (*hash_len == 0) {
100632b31808SJens Wiklander         return -1;
100732b31808SJens Wiklander     }
1008817466cbSJens Wiklander 
100932b31808SJens Wiklander     return 0;
1010817466cbSJens Wiklander }
1011817466cbSJens Wiklander 
10123d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
10133d3b0591SJens Wiklander /*
10143d3b0591SJens Wiklander  * Helper to set up a restart context if needed
10153d3b0591SJens Wiklander  */
10163d3b0591SJens Wiklander static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,
10173d3b0591SJens Wiklander                             const mbedtls_pk_info_t *info)
10183d3b0591SJens Wiklander {
10193d3b0591SJens Wiklander     /* Don't do anything if already set up or invalid */
102032b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info != NULL) {
102132b31808SJens Wiklander         return 0;
102232b31808SJens Wiklander     }
10233d3b0591SJens Wiklander 
10243d3b0591SJens Wiklander     /* Should never happen when we're called */
102532b31808SJens Wiklander     if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {
102632b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
102732b31808SJens Wiklander     }
10283d3b0591SJens Wiklander 
102932b31808SJens Wiklander     if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {
103032b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
103132b31808SJens Wiklander     }
10323d3b0591SJens Wiklander 
10333d3b0591SJens Wiklander     ctx->pk_info = info;
10343d3b0591SJens Wiklander 
103532b31808SJens Wiklander     return 0;
10363d3b0591SJens Wiklander }
10373d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
10383d3b0591SJens Wiklander 
10393d3b0591SJens Wiklander /*
10403d3b0591SJens Wiklander  * Verify a signature (restartable)
10413d3b0591SJens Wiklander  */
10423d3b0591SJens Wiklander int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
10433d3b0591SJens Wiklander                                   mbedtls_md_type_t md_alg,
10443d3b0591SJens Wiklander                                   const unsigned char *hash, size_t hash_len,
10453d3b0591SJens Wiklander                                   const unsigned char *sig, size_t sig_len,
10463d3b0591SJens Wiklander                                   mbedtls_pk_restart_ctx *rs_ctx)
10473d3b0591SJens Wiklander {
104832b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
104932b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
105032b31808SJens Wiklander     }
10513d3b0591SJens Wiklander 
10523d3b0591SJens Wiklander     if (ctx->pk_info == NULL ||
105332b31808SJens Wiklander         pk_hashlen_helper(md_alg, &hash_len) != 0) {
105432b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
105532b31808SJens Wiklander     }
10563d3b0591SJens Wiklander 
10573d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
10583d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
10593d3b0591SJens Wiklander     if (rs_ctx != NULL &&
10603d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
106132b31808SJens Wiklander         ctx->pk_info->verify_rs_func != NULL) {
106211fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
10633d3b0591SJens Wiklander 
106432b31808SJens Wiklander         if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
106532b31808SJens Wiklander             return ret;
106632b31808SJens Wiklander         }
10673d3b0591SJens Wiklander 
1068*b0563631STom Van Eyck         ret = ctx->pk_info->verify_rs_func(ctx,
10693d3b0591SJens Wiklander                                            md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);
10703d3b0591SJens Wiklander 
107132b31808SJens Wiklander         if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
10723d3b0591SJens Wiklander             mbedtls_pk_restart_free(rs_ctx);
107332b31808SJens Wiklander         }
10743d3b0591SJens Wiklander 
107532b31808SJens Wiklander         return ret;
10763d3b0591SJens Wiklander     }
10773d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
10783d3b0591SJens Wiklander     (void) rs_ctx;
10793d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
10803d3b0591SJens Wiklander 
108132b31808SJens Wiklander     if (ctx->pk_info->verify_func == NULL) {
108232b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
108332b31808SJens Wiklander     }
10843d3b0591SJens Wiklander 
1085*b0563631STom Van Eyck     return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len,
108632b31808SJens Wiklander                                      sig, sig_len);
10873d3b0591SJens Wiklander }
10883d3b0591SJens Wiklander 
1089817466cbSJens Wiklander /*
1090817466cbSJens Wiklander  * Verify a signature
1091817466cbSJens Wiklander  */
1092817466cbSJens Wiklander int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
1093817466cbSJens Wiklander                       const unsigned char *hash, size_t hash_len,
1094817466cbSJens Wiklander                       const unsigned char *sig, size_t sig_len)
1095817466cbSJens Wiklander {
109632b31808SJens Wiklander     return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len,
109732b31808SJens Wiklander                                          sig, sig_len, NULL);
1098817466cbSJens Wiklander }
1099817466cbSJens Wiklander 
1100817466cbSJens Wiklander /*
1101817466cbSJens Wiklander  * Verify a signature with options
1102817466cbSJens Wiklander  */
1103817466cbSJens Wiklander int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
1104817466cbSJens Wiklander                           mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
1105817466cbSJens Wiklander                           const unsigned char *hash, size_t hash_len,
1106817466cbSJens Wiklander                           const unsigned char *sig, size_t sig_len)
1107817466cbSJens Wiklander {
110832b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
110932b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
111032b31808SJens Wiklander     }
11113d3b0591SJens Wiklander 
111232b31808SJens Wiklander     if (ctx->pk_info == NULL) {
111332b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
111432b31808SJens Wiklander     }
1115817466cbSJens Wiklander 
111632b31808SJens Wiklander     if (!mbedtls_pk_can_do(ctx, type)) {
111732b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
111832b31808SJens Wiklander     }
1119817466cbSJens Wiklander 
112032b31808SJens Wiklander     if (type != MBEDTLS_PK_RSASSA_PSS) {
112132b31808SJens Wiklander         /* General case: no options */
112232b31808SJens Wiklander         if (options != NULL) {
112332b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
112432b31808SJens Wiklander         }
112532b31808SJens Wiklander 
112632b31808SJens Wiklander         return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
112732b31808SJens Wiklander     }
112832b31808SJens Wiklander 
1129*b0563631STom Van Eyck     /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()
1130*b0563631STom Van Eyck      * below would return a NULL pointer. */
1131*b0563631STom Van Eyck     if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {
1132*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1133*b0563631STom Van Eyck     }
1134*b0563631STom Van Eyck 
1135817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
113611fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1137817466cbSJens Wiklander     const mbedtls_pk_rsassa_pss_options *pss_opts;
1138817466cbSJens Wiklander 
1139*b0563631STom Van Eyck #if SIZE_MAX > UINT_MAX
114032b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
114132b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
114232b31808SJens Wiklander     }
1143*b0563631STom Van Eyck #endif
1144817466cbSJens Wiklander 
114532b31808SJens Wiklander     if (options == NULL) {
114632b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
114732b31808SJens Wiklander     }
1148817466cbSJens Wiklander 
1149817466cbSJens Wiklander     pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
1150817466cbSJens Wiklander 
115132b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
115232b31808SJens Wiklander     if (pss_opts->mgf1_hash_id == md_alg) {
115332b31808SJens Wiklander         unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
115432b31808SJens Wiklander         unsigned char *p;
115532b31808SJens Wiklander         int key_len;
115632b31808SJens Wiklander         size_t signature_length;
115732b31808SJens Wiklander         psa_status_t status = PSA_ERROR_DATA_CORRUPT;
115832b31808SJens Wiklander         psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;
115932b31808SJens Wiklander 
1160*b0563631STom Van Eyck         psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
116132b31808SJens Wiklander         mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
116232b31808SJens Wiklander         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
116332b31808SJens Wiklander         psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);
116432b31808SJens Wiklander         p = buf + sizeof(buf);
1165*b0563631STom Van Eyck         key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p);
116632b31808SJens Wiklander 
116732b31808SJens Wiklander         if (key_len < 0) {
116832b31808SJens Wiklander             return key_len;
116932b31808SJens Wiklander         }
117032b31808SJens Wiklander 
117132b31808SJens Wiklander         psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
117232b31808SJens Wiklander         psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
117332b31808SJens Wiklander         psa_set_key_algorithm(&attributes, psa_sig_alg);
117432b31808SJens Wiklander 
117532b31808SJens Wiklander         status = psa_import_key(&attributes,
117632b31808SJens Wiklander                                 buf + sizeof(buf) - key_len, key_len,
117732b31808SJens Wiklander                                 &key_id);
117832b31808SJens Wiklander         if (status != PSA_SUCCESS) {
117932b31808SJens Wiklander             psa_destroy_key(key_id);
118032b31808SJens Wiklander             return PSA_PK_TO_MBEDTLS_ERR(status);
118132b31808SJens Wiklander         }
118232b31808SJens Wiklander 
118332b31808SJens Wiklander         /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH
118432b31808SJens Wiklander          * on a valid signature with trailing data in a buffer, but
118532b31808SJens Wiklander          * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact,
118632b31808SJens Wiklander          * so for this reason the passed sig_len is overwritten. Smaller
118732b31808SJens Wiklander          * signature lengths should not be accepted for verification. */
118832b31808SJens Wiklander         signature_length = sig_len > mbedtls_pk_get_len(ctx) ?
118932b31808SJens Wiklander                            mbedtls_pk_get_len(ctx) : sig_len;
119032b31808SJens Wiklander         status = psa_verify_hash(key_id, psa_sig_alg, hash,
119132b31808SJens Wiklander                                  hash_len, sig, signature_length);
119232b31808SJens Wiklander         destruction_status = psa_destroy_key(key_id);
119332b31808SJens Wiklander 
119432b31808SJens Wiklander         if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) {
119532b31808SJens Wiklander             return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
119632b31808SJens Wiklander         }
119732b31808SJens Wiklander 
119832b31808SJens Wiklander         if (status == PSA_SUCCESS) {
119932b31808SJens Wiklander             status = destruction_status;
120032b31808SJens Wiklander         }
120132b31808SJens Wiklander 
120232b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
120332b31808SJens Wiklander     } else
1204*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
120532b31808SJens Wiklander     {
120632b31808SJens Wiklander         if (sig_len < mbedtls_pk_get_len(ctx)) {
120732b31808SJens Wiklander             return MBEDTLS_ERR_RSA_VERIFY_FAILED;
120832b31808SJens Wiklander         }
1209817466cbSJens Wiklander 
1210817466cbSJens Wiklander         ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx),
1211817466cbSJens Wiklander                                                 md_alg, (unsigned int) hash_len, hash,
1212817466cbSJens Wiklander                                                 pss_opts->mgf1_hash_id,
1213817466cbSJens Wiklander                                                 pss_opts->expected_salt_len,
1214817466cbSJens Wiklander                                                 sig);
121532b31808SJens Wiklander         if (ret != 0) {
121632b31808SJens Wiklander             return ret;
1217817466cbSJens Wiklander         }
1218817466cbSJens Wiklander 
121932b31808SJens Wiklander         if (sig_len > mbedtls_pk_get_len(ctx)) {
122032b31808SJens Wiklander             return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
122132b31808SJens Wiklander         }
1222817466cbSJens Wiklander 
122332b31808SJens Wiklander         return 0;
122432b31808SJens Wiklander     }
122532b31808SJens Wiklander #else
122632b31808SJens Wiklander     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
122732b31808SJens Wiklander #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
1228817466cbSJens Wiklander }
1229817466cbSJens Wiklander 
1230817466cbSJens Wiklander /*
12313d3b0591SJens Wiklander  * Make a signature (restartable)
12323d3b0591SJens Wiklander  */
12333d3b0591SJens Wiklander int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
12343d3b0591SJens Wiklander                                 mbedtls_md_type_t md_alg,
12353d3b0591SJens Wiklander                                 const unsigned char *hash, size_t hash_len,
123632b31808SJens Wiklander                                 unsigned char *sig, size_t sig_size, size_t *sig_len,
12373d3b0591SJens Wiklander                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
12383d3b0591SJens Wiklander                                 mbedtls_pk_restart_ctx *rs_ctx)
12393d3b0591SJens Wiklander {
124032b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
124132b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
124232b31808SJens Wiklander     }
12433d3b0591SJens Wiklander 
124432b31808SJens Wiklander     if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) {
124532b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
124632b31808SJens Wiklander     }
12473d3b0591SJens Wiklander 
12483d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
12493d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
12503d3b0591SJens Wiklander     if (rs_ctx != NULL &&
12513d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
125232b31808SJens Wiklander         ctx->pk_info->sign_rs_func != NULL) {
125311fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
12543d3b0591SJens Wiklander 
125532b31808SJens Wiklander         if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
125632b31808SJens Wiklander             return ret;
125732b31808SJens Wiklander         }
12583d3b0591SJens Wiklander 
1259*b0563631STom Van Eyck         ret = ctx->pk_info->sign_rs_func(ctx, md_alg,
126032b31808SJens Wiklander                                          hash, hash_len,
126132b31808SJens Wiklander                                          sig, sig_size, sig_len,
126232b31808SJens Wiklander                                          f_rng, p_rng, rs_ctx->rs_ctx);
12633d3b0591SJens Wiklander 
126432b31808SJens Wiklander         if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
12653d3b0591SJens Wiklander             mbedtls_pk_restart_free(rs_ctx);
126632b31808SJens Wiklander         }
12673d3b0591SJens Wiklander 
126832b31808SJens Wiklander         return ret;
12693d3b0591SJens Wiklander     }
12703d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
12713d3b0591SJens Wiklander     (void) rs_ctx;
12723d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
12733d3b0591SJens Wiklander 
127432b31808SJens Wiklander     if (ctx->pk_info->sign_func == NULL) {
127532b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
127632b31808SJens Wiklander     }
12773d3b0591SJens Wiklander 
1278*b0563631STom Van Eyck     return ctx->pk_info->sign_func(ctx, md_alg,
127932b31808SJens Wiklander                                    hash, hash_len,
128032b31808SJens Wiklander                                    sig, sig_size, sig_len,
128132b31808SJens Wiklander                                    f_rng, p_rng);
12823d3b0591SJens Wiklander }
12833d3b0591SJens Wiklander 
12843d3b0591SJens Wiklander /*
1285817466cbSJens Wiklander  * Make a signature
1286817466cbSJens Wiklander  */
1287817466cbSJens Wiklander int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
1288817466cbSJens Wiklander                     const unsigned char *hash, size_t hash_len,
128932b31808SJens Wiklander                     unsigned char *sig, size_t sig_size, size_t *sig_len,
1290817466cbSJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1291817466cbSJens Wiklander {
129232b31808SJens Wiklander     return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len,
129332b31808SJens Wiklander                                        sig, sig_size, sig_len,
129432b31808SJens Wiklander                                        f_rng, p_rng, NULL);
1295817466cbSJens Wiklander }
1296817466cbSJens Wiklander 
129732b31808SJens Wiklander /*
129832b31808SJens Wiklander  * Make a signature given a signature type.
129932b31808SJens Wiklander  */
130032b31808SJens Wiklander int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
130132b31808SJens Wiklander                         mbedtls_pk_context *ctx,
130232b31808SJens Wiklander                         mbedtls_md_type_t md_alg,
130332b31808SJens Wiklander                         const unsigned char *hash, size_t hash_len,
130432b31808SJens Wiklander                         unsigned char *sig, size_t sig_size, size_t *sig_len,
130532b31808SJens Wiklander                         int (*f_rng)(void *, unsigned char *, size_t),
130632b31808SJens Wiklander                         void *p_rng)
130732b31808SJens Wiklander {
130832b31808SJens Wiklander     if (ctx->pk_info == NULL) {
130932b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
131032b31808SJens Wiklander     }
131132b31808SJens Wiklander 
131232b31808SJens Wiklander     if (!mbedtls_pk_can_do(ctx, pk_type)) {
131332b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
131432b31808SJens Wiklander     }
131532b31808SJens Wiklander 
131632b31808SJens Wiklander     if (pk_type != MBEDTLS_PK_RSASSA_PSS) {
131732b31808SJens Wiklander         return mbedtls_pk_sign(ctx, md_alg, hash, hash_len,
131832b31808SJens Wiklander                                sig, sig_size, sig_len, f_rng, p_rng);
131932b31808SJens Wiklander     }
132032b31808SJens Wiklander 
1321*b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
1322*b0563631STom Van Eyck 
1323*b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
1324*b0563631STom Van Eyck     const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
132532b31808SJens Wiklander     if (psa_md_alg == 0) {
132632b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
132732b31808SJens Wiklander     }
132832b31808SJens Wiklander 
132932b31808SJens Wiklander     if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
1330*b0563631STom Van Eyck         psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
1331*b0563631STom Van Eyck         psa_algorithm_t psa_alg, sign_alg;
1332*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
1333*b0563631STom Van Eyck         psa_algorithm_t psa_enrollment_alg;
1334*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
133532b31808SJens Wiklander         psa_status_t status;
133632b31808SJens Wiklander 
1337*b0563631STom Van Eyck         status = psa_get_key_attributes(ctx->priv_id, &key_attr);
1338*b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
1339*b0563631STom Van Eyck             return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
1340*b0563631STom Van Eyck         }
1341*b0563631STom Van Eyck         psa_alg = psa_get_key_algorithm(&key_attr);
1342*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
1343*b0563631STom Van Eyck         psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
1344*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
1345*b0563631STom Van Eyck         psa_reset_key_attributes(&key_attr);
1346*b0563631STom Van Eyck 
1347*b0563631STom Van Eyck         /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between
1348*b0563631STom Van Eyck          * alg and enrollment alg should be of type RSA_PSS. */
1349*b0563631STom Van Eyck         if (PSA_ALG_IS_RSA_PSS(psa_alg)) {
1350*b0563631STom Van Eyck             sign_alg = psa_alg;
1351*b0563631STom Van Eyck         }
1352*b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
1353*b0563631STom Van Eyck         else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
1354*b0563631STom Van Eyck             sign_alg = psa_enrollment_alg;
1355*b0563631STom Van Eyck         }
1356*b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
1357*b0563631STom Van Eyck         else {
1358*b0563631STom Van Eyck             /* The opaque key has no RSA PSS algorithm associated. */
1359*b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1360*b0563631STom Van Eyck         }
1361*b0563631STom Van Eyck         /* Adjust the hashing algorithm. */
1362*b0563631STom Van Eyck         sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg);
1363*b0563631STom Van Eyck 
1364*b0563631STom Van Eyck         status = psa_sign_hash(ctx->priv_id, sign_alg,
136532b31808SJens Wiklander                                hash, hash_len,
136632b31808SJens Wiklander                                sig, sig_size, sig_len);
136732b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
136832b31808SJens Wiklander     }
136932b31808SJens Wiklander 
137032b31808SJens Wiklander     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
137132b31808SJens Wiklander                                        ctx->pk_ctx, hash, hash_len,
137232b31808SJens Wiklander                                        sig, sig_size, sig_len);
1373*b0563631STom Van Eyck #else /* MBEDTLS_USE_PSA_CRYPTO */
137432b31808SJens Wiklander 
1375*b0563631STom Van Eyck     if (sig_size < mbedtls_pk_get_len(ctx)) {
1376*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
137732b31808SJens Wiklander     }
1378*b0563631STom Van Eyck 
1379*b0563631STom Van Eyck     if (pk_hashlen_helper(md_alg, &hash_len) != 0) {
1380*b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1381*b0563631STom Van Eyck     }
1382*b0563631STom Van Eyck 
1383*b0563631STom Van Eyck     mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx);
1384*b0563631STom Van Eyck 
1385*b0563631STom Van Eyck     const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg,
1386*b0563631STom Van Eyck                                                               (unsigned int) hash_len, hash, sig);
1387*b0563631STom Van Eyck     if (ret == 0) {
1388*b0563631STom Van Eyck         *sig_len = rsa_ctx->len;
1389*b0563631STom Van Eyck     }
1390*b0563631STom Van Eyck     return ret;
1391*b0563631STom Van Eyck 
1392*b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
1393*b0563631STom Van Eyck 
1394*b0563631STom Van Eyck #else
1395*b0563631STom Van Eyck     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1396*b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
1397*b0563631STom Van Eyck }
139832b31808SJens Wiklander 
1399817466cbSJens Wiklander /*
1400817466cbSJens Wiklander  * Decrypt message
1401817466cbSJens Wiklander  */
1402817466cbSJens Wiklander int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
1403817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
1404817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
1405817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1406817466cbSJens Wiklander {
140732b31808SJens Wiklander     if (ctx->pk_info == NULL) {
140832b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
140932b31808SJens Wiklander     }
14103d3b0591SJens Wiklander 
141132b31808SJens Wiklander     if (ctx->pk_info->decrypt_func == NULL) {
141232b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
141332b31808SJens Wiklander     }
1414817466cbSJens Wiklander 
1415*b0563631STom Van Eyck     return ctx->pk_info->decrypt_func(ctx, input, ilen,
141632b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
1417817466cbSJens Wiklander }
1418817466cbSJens Wiklander 
1419817466cbSJens Wiklander /*
1420817466cbSJens Wiklander  * Encrypt message
1421817466cbSJens Wiklander  */
1422817466cbSJens Wiklander int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
1423817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
1424817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
1425817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1426817466cbSJens Wiklander {
142732b31808SJens Wiklander     if (ctx->pk_info == NULL) {
142832b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
142932b31808SJens Wiklander     }
14303d3b0591SJens Wiklander 
143132b31808SJens Wiklander     if (ctx->pk_info->encrypt_func == NULL) {
143232b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
143332b31808SJens Wiklander     }
1434817466cbSJens Wiklander 
1435*b0563631STom Van Eyck     return ctx->pk_info->encrypt_func(ctx, input, ilen,
143632b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
1437817466cbSJens Wiklander }
1438817466cbSJens Wiklander 
1439817466cbSJens Wiklander /*
1440817466cbSJens Wiklander  * Check public-private key pair
1441817466cbSJens Wiklander  */
144232b31808SJens Wiklander int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
144332b31808SJens Wiklander                           const mbedtls_pk_context *prv,
144432b31808SJens Wiklander                           int (*f_rng)(void *, unsigned char *, size_t),
144532b31808SJens Wiklander                           void *p_rng)
1446817466cbSJens Wiklander {
14473d3b0591SJens Wiklander     if (pub->pk_info == NULL ||
144832b31808SJens Wiklander         prv->pk_info == NULL) {
144932b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1450817466cbSJens Wiklander     }
1451817466cbSJens Wiklander 
145232b31808SJens Wiklander     if (f_rng == NULL) {
145332b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1454817466cbSJens Wiklander     }
1455817466cbSJens Wiklander 
145632b31808SJens Wiklander     if (prv->pk_info->check_pair_func == NULL) {
145732b31808SJens Wiklander         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
145832b31808SJens Wiklander     }
145932b31808SJens Wiklander 
146032b31808SJens Wiklander     if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {
146132b31808SJens Wiklander         if (pub->pk_info->type != MBEDTLS_PK_RSA) {
146232b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
146332b31808SJens Wiklander         }
146432b31808SJens Wiklander     } else {
1465*b0563631STom Van Eyck         if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) &&
1466*b0563631STom Van Eyck             (pub->pk_info != prv->pk_info)) {
146732b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
146832b31808SJens Wiklander         }
146932b31808SJens Wiklander     }
147032b31808SJens Wiklander 
1471*b0563631STom Van Eyck     return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub,
1472*b0563631STom Van Eyck                                          (mbedtls_pk_context *) prv,
1473*b0563631STom Van Eyck                                          f_rng, p_rng);
1474817466cbSJens Wiklander }
1475817466cbSJens Wiklander 
1476817466cbSJens Wiklander /*
1477817466cbSJens Wiklander  * Get key size in bits
1478817466cbSJens Wiklander  */
1479817466cbSJens Wiklander size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
1480817466cbSJens Wiklander {
14813d3b0591SJens Wiklander     /* For backward compatibility, accept NULL or a context that
14823d3b0591SJens Wiklander      * isn't set up yet, and return a fake value that should be safe. */
148332b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
148432b31808SJens Wiklander         return 0;
148532b31808SJens Wiklander     }
1486817466cbSJens Wiklander 
1487*b0563631STom Van Eyck     return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx);
1488817466cbSJens Wiklander }
1489817466cbSJens Wiklander 
1490817466cbSJens Wiklander /*
1491817466cbSJens Wiklander  * Export debug information
1492817466cbSJens Wiklander  */
1493817466cbSJens Wiklander int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
1494817466cbSJens Wiklander {
149532b31808SJens Wiklander     if (ctx->pk_info == NULL) {
149632b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
149732b31808SJens Wiklander     }
1498817466cbSJens Wiklander 
149932b31808SJens Wiklander     if (ctx->pk_info->debug_func == NULL) {
150032b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
150132b31808SJens Wiklander     }
1502817466cbSJens Wiklander 
1503*b0563631STom Van Eyck     ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items);
150432b31808SJens Wiklander     return 0;
1505817466cbSJens Wiklander }
1506817466cbSJens Wiklander 
1507817466cbSJens Wiklander /*
1508817466cbSJens Wiklander  * Access the PK type name
1509817466cbSJens Wiklander  */
1510817466cbSJens Wiklander const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
1511817466cbSJens Wiklander {
151232b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
151332b31808SJens Wiklander         return "invalid PK";
151432b31808SJens Wiklander     }
1515817466cbSJens Wiklander 
151632b31808SJens Wiklander     return ctx->pk_info->name;
1517817466cbSJens Wiklander }
1518817466cbSJens Wiklander 
1519817466cbSJens Wiklander /*
1520817466cbSJens Wiklander  * Access the PK type
1521817466cbSJens Wiklander  */
1522817466cbSJens Wiklander mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
1523817466cbSJens Wiklander {
152432b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
152532b31808SJens Wiklander         return MBEDTLS_PK_NONE;
152632b31808SJens Wiklander     }
1527817466cbSJens Wiklander 
152832b31808SJens Wiklander     return ctx->pk_info->type;
1529817466cbSJens Wiklander }
1530817466cbSJens Wiklander 
1531817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
1532