xref: /optee_os/lib/libmbedtls/mbedtls/library/pk.c (revision cb03400251f98aed22a2664509e3ed9e183800b0)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Public Key abstraction layer
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5b0563631STom 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"
14b0563631STom 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"
21b0563631STom Van Eyck #include "rsa_internal.h"
22817466cbSJens Wiklander #endif
23b0563631STom 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 
30b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
31b0563631STom 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 
38b0563631STom Van Eyck #define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \
39b0563631STom Van Eyck     (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \
40b0563631STom Van Eyck     PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
41b0563631STom 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;
49b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
50b0563631STom Van Eyck     ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT;
51b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
52b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
53b0563631STom Van Eyck     memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw));
54b0563631STom Van Eyck     ctx->pub_raw_len = 0;
55b0563631STom Van Eyck     ctx->ec_family = 0;
56b0563631STom Van Eyck     ctx->ec_bits = 0;
57b0563631STom 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 
69b0563631STom 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 
73b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
74b0563631STom Van Eyck     /* The ownership of the priv_id key for opaque keys is external of the PK
75b0563631STom Van Eyck      * module. It's the user responsibility to clear it after use. */
76b0563631STom Van Eyck     if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) {
77b0563631STom Van Eyck         psa_destroy_key(ctx->priv_id);
78b0563631STom Van Eyck     }
79b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
80b0563631STom 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;
120b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
121b0563631STom 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;
126b0563631STom 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;
130b0563631STom 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 
146b0563631STom Van Eyck     if ((info->ctx_alloc_func != NULL) &&
147b0563631STom 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 
177b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
17832b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
179b0563631STom Van Eyck         info = &mbedtls_ecdsa_opaque_info;
180b0563631STom Van Eyck     } else
181b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
182b0563631STom Van Eyck     if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
183b0563631STom 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;
189b0563631STom 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 
321b0563631STom 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 
326b0563631STom Van Eyck     psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
327b0563631STom Van Eyck     /* Key's enrollment is available only when an Mbed TLS implementation of PSA
328b0563631STom Van Eyck      * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
329b0563631STom Van Eyck      * Even though we don't officially support using other implementations of PSA
330b0563631STom Van Eyck      * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
331b0563631STom Van Eyck      * separated. */
332b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
333b0563631STom Van Eyck     psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
334b0563631STom 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     /*
343b0563631STom 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
347b0563631STom Van Eyck      * a fixed hash on key_alg [or key_alg2].
34832b31808SJens Wiklander      */
349b0563631STom Van Eyck     if (alg == key_alg) {
35032b31808SJens Wiklander         return 1;
35132b31808SJens Wiklander     }
352b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
353b0563631STom Van Eyck     if (alg == key_alg2) {
354b0563631STom Van Eyck         return 1;
355b0563631STom Van Eyck     }
356b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_C */
35732b31808SJens Wiklander 
35832b31808SJens Wiklander     /*
359b0563631STom 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         }
369b0563631STom 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         }
375b0563631STom 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 
382b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
383b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
384b0563631STom Van Eyck static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
385b0563631STom Van Eyck                                              int want_crypt)
386b0563631STom Van Eyck {
387b0563631STom Van Eyck     if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
388b0563631STom Van Eyck         if (want_crypt) {
389b0563631STom Van Eyck             mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);
390b0563631STom Van Eyck             return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));
391b0563631STom Van Eyck         } else {
392b0563631STom Van Eyck             return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);
393b0563631STom Van Eyck         }
394b0563631STom Van Eyck     } else {
395b0563631STom Van Eyck         if (want_crypt) {
396b0563631STom Van Eyck             return PSA_ALG_RSA_PKCS1V15_CRYPT;
397b0563631STom Van Eyck         } else {
398b0563631STom Van Eyck             return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);
399b0563631STom Van Eyck         }
400b0563631STom Van Eyck     }
401b0563631STom Van Eyck }
402b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
403b0563631STom Van Eyck 
404b0563631STom Van Eyck int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
405b0563631STom Van Eyck                                   psa_key_usage_t usage,
406b0563631STom Van Eyck                                   psa_key_attributes_t *attributes)
407b0563631STom Van Eyck {
408b0563631STom Van Eyck     mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
409b0563631STom Van Eyck 
410b0563631STom Van Eyck     psa_key_usage_t more_usage = usage;
411b0563631STom Van Eyck     if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {
412b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
413b0563631STom Van Eyck     } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {
414b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_VERIFY_HASH;
415b0563631STom Van Eyck     } else if (usage == PSA_KEY_USAGE_DECRYPT) {
416b0563631STom Van Eyck         more_usage |= PSA_KEY_USAGE_ENCRYPT;
417b0563631STom Van Eyck     }
418b0563631STom Van Eyck     more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
419b0563631STom Van Eyck 
420b0563631STom Van Eyck     int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE ||
421b0563631STom Van Eyck                          usage == PSA_KEY_USAGE_VERIFY_HASH ||
422b0563631STom Van Eyck                          usage == PSA_KEY_USAGE_ENCRYPT);
423b0563631STom Van Eyck 
424b0563631STom Van Eyck     switch (pk_type) {
425b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
426b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
427b0563631STom Van Eyck         {
428b0563631STom Van Eyck             int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */
429b0563631STom Van Eyck             switch (usage) {
430b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
431b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
432b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
433b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
434b0563631STom Van Eyck                     /* Nothing to do. */
435b0563631STom Van Eyck                     break;
436b0563631STom Van Eyck                 case PSA_KEY_USAGE_DECRYPT:
437b0563631STom Van Eyck                 case PSA_KEY_USAGE_ENCRYPT:
438b0563631STom Van Eyck                     want_crypt = 1;
439b0563631STom Van Eyck                     break;
440b0563631STom Van Eyck                 default:
441b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
442b0563631STom Van Eyck             }
443b0563631STom Van Eyck             /* Detect the presence of a private key in a way that works both
444b0563631STom Van Eyck              * in CRT and non-CRT configurations. */
445b0563631STom Van Eyck             mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
446b0563631STom Van Eyck             int has_private = (mbedtls_rsa_check_privkey(rsa) == 0);
447b0563631STom Van Eyck             if (want_private && !has_private) {
448b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
449b0563631STom Van Eyck             }
450b0563631STom Van Eyck             psa_set_key_type(attributes, (want_private ?
451b0563631STom Van Eyck                                           PSA_KEY_TYPE_RSA_KEY_PAIR :
452b0563631STom Van Eyck                                           PSA_KEY_TYPE_RSA_PUBLIC_KEY));
453b0563631STom Van Eyck             psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk));
454b0563631STom Van Eyck             psa_set_key_algorithm(attributes,
455b0563631STom Van Eyck                                   psa_algorithm_for_rsa(rsa, want_crypt));
456b0563631STom Van Eyck             break;
457b0563631STom Van Eyck         }
458b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
459b0563631STom Van Eyck 
460b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
461b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
462b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
463b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
464b0563631STom Van Eyck         {
465b0563631STom Van Eyck             int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);
466b0563631STom Van Eyck             int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);
467b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
468b0563631STom Van Eyck             psa_ecc_family_t family = pk->ec_family;
469b0563631STom Van Eyck             size_t bits = pk->ec_bits;
470b0563631STom Van Eyck             int has_private = 0;
471b0563631STom Van Eyck             if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) {
472b0563631STom Van Eyck                 has_private = 1;
473b0563631STom Van Eyck             }
474b0563631STom Van Eyck #else
475b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
476b0563631STom Van Eyck             int has_private = (ec->d.n != 0);
477b0563631STom Van Eyck             size_t bits = 0;
478b0563631STom Van Eyck             psa_ecc_family_t family =
479b0563631STom Van Eyck                 mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
480b0563631STom Van Eyck #endif
481b0563631STom Van Eyck             psa_algorithm_t alg = 0;
482b0563631STom Van Eyck             switch (usage) {
483b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
484b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
485b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
486b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
487b0563631STom Van Eyck                     if (!sign_ok) {
488b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
489b0563631STom Van Eyck                     }
490b0563631STom Van Eyck #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
491b0563631STom Van Eyck                     alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
492b0563631STom Van Eyck #else
493b0563631STom Van Eyck                     alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
494b0563631STom Van Eyck #endif
495b0563631STom Van Eyck                     break;
496b0563631STom Van Eyck                 case PSA_KEY_USAGE_DERIVE:
497b0563631STom Van Eyck                     alg = PSA_ALG_ECDH;
498b0563631STom Van Eyck                     if (!derive_ok) {
499b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
500b0563631STom Van Eyck                     }
501b0563631STom Van Eyck                     break;
502b0563631STom Van Eyck                 default:
503b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
504b0563631STom Van Eyck             }
505b0563631STom Van Eyck             if (want_private && !has_private) {
506b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
507b0563631STom Van Eyck             }
508b0563631STom Van Eyck             psa_set_key_type(attributes, (want_private ?
509b0563631STom Van Eyck                                           PSA_KEY_TYPE_ECC_KEY_PAIR(family) :
510b0563631STom Van Eyck                                           PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));
511b0563631STom Van Eyck             psa_set_key_bits(attributes, bits);
512b0563631STom Van Eyck             psa_set_key_algorithm(attributes, alg);
513b0563631STom Van Eyck             break;
514b0563631STom Van Eyck         }
515b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
516b0563631STom Van Eyck 
517b0563631STom Van Eyck #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
518b0563631STom Van Eyck         case MBEDTLS_PK_RSA_ALT:
519b0563631STom Van Eyck             return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
520b0563631STom Van Eyck #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
521b0563631STom Van Eyck 
522b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
523b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
524b0563631STom Van Eyck         {
525b0563631STom Van Eyck             psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
526b0563631STom Van Eyck             psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
527b0563631STom Van Eyck             status = psa_get_key_attributes(pk->priv_id, &old_attributes);
528b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
529b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
530b0563631STom Van Eyck             }
531b0563631STom Van Eyck             psa_key_type_t old_type = psa_get_key_type(&old_attributes);
532b0563631STom Van Eyck             switch (usage) {
533b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_MESSAGE:
534b0563631STom Van Eyck                 case PSA_KEY_USAGE_SIGN_HASH:
535b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_MESSAGE:
536b0563631STom Van Eyck                 case PSA_KEY_USAGE_VERIFY_HASH:
537b0563631STom Van Eyck                     if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) ||
538b0563631STom Van Eyck                           old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) {
539b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
540b0563631STom Van Eyck                     }
541b0563631STom Van Eyck                     break;
542b0563631STom Van Eyck                 case PSA_KEY_USAGE_DECRYPT:
543b0563631STom Van Eyck                 case PSA_KEY_USAGE_ENCRYPT:
544b0563631STom Van Eyck                     if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) {
545b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
546b0563631STom Van Eyck                     }
547b0563631STom Van Eyck                     break;
548b0563631STom Van Eyck                 case PSA_KEY_USAGE_DERIVE:
549b0563631STom Van Eyck                     if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) {
550b0563631STom Van Eyck                         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
551b0563631STom Van Eyck                     }
552b0563631STom Van Eyck                     break;
553b0563631STom Van Eyck                 default:
554b0563631STom Van Eyck                     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
555b0563631STom Van Eyck             }
556b0563631STom Van Eyck             psa_key_type_t new_type = old_type;
557b0563631STom Van Eyck             /* Opaque keys are always key pairs, so we don't need a check
558b0563631STom Van Eyck              * on the input if the required usage is private. We just need
559b0563631STom Van Eyck              * to adjust the type correctly if the required usage is public. */
560b0563631STom Van Eyck             if (!want_private) {
561b0563631STom Van Eyck                 new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type);
562b0563631STom Van Eyck             }
563b0563631STom Van Eyck             more_usage = psa_get_key_usage_flags(&old_attributes);
564b0563631STom Van Eyck             if ((usage & more_usage) == 0) {
565b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
566b0563631STom Van Eyck             }
567b0563631STom Van Eyck             psa_set_key_type(attributes, new_type);
568b0563631STom Van Eyck             psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes));
569b0563631STom Van Eyck             psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes));
570b0563631STom Van Eyck             break;
571b0563631STom Van Eyck         }
572b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
573b0563631STom Van Eyck 
574b0563631STom Van Eyck         default:
575b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
576b0563631STom Van Eyck     }
577b0563631STom Van Eyck 
578b0563631STom Van Eyck     psa_set_key_usage_flags(attributes, more_usage);
579b0563631STom Van Eyck     /* Key's enrollment is available only when an Mbed TLS implementation of PSA
580b0563631STom Van Eyck      * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
581b0563631STom Van Eyck      * Even though we don't officially support using other implementations of PSA
582b0563631STom Van Eyck      * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
583b0563631STom Van Eyck      * separated. */
584b0563631STom Van Eyck #if defined(MBEDTLS_PSA_CRYPTO_C)
585b0563631STom Van Eyck     psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
586b0563631STom Van Eyck #endif
587b0563631STom Van Eyck 
588b0563631STom Van Eyck     return 0;
589b0563631STom Van Eyck }
590b0563631STom Van Eyck 
591b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
592b0563631STom Van Eyck static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
593b0563631STom Van Eyck                                            const psa_key_attributes_t *attributes,
594b0563631STom Van Eyck                                            mbedtls_svc_key_id_t *new_key_id)
595b0563631STom Van Eyck {
596b0563631STom Van Eyck     unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
597b0563631STom Van Eyck     size_t key_length = 0;
598b0563631STom Van Eyck     psa_status_t status = psa_export_key(old_key_id,
599b0563631STom Van Eyck                                          key_buffer, sizeof(key_buffer),
600b0563631STom Van Eyck                                          &key_length);
601b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
602b0563631STom Van Eyck         return status;
603b0563631STom Van Eyck     }
604b0563631STom Van Eyck     status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
605b0563631STom Van Eyck     mbedtls_platform_zeroize(key_buffer, key_length);
606b0563631STom Van Eyck     return status;
607b0563631STom Van Eyck }
608b0563631STom Van Eyck 
609b0563631STom Van Eyck static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
610b0563631STom Van Eyck                          const psa_key_attributes_t *attributes,
611b0563631STom Van Eyck                          mbedtls_svc_key_id_t *new_key_id)
612b0563631STom Van Eyck {
613b0563631STom Van Eyck     /* Normally, we prefer copying: it's more efficient and works even
614b0563631STom Van Eyck      * for non-exportable keys. */
615b0563631STom Van Eyck     psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
616b0563631STom Van Eyck     if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||
617b0563631STom Van Eyck         status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {
618b0563631STom Van Eyck         /* There are edge cases where copying won't work, but export+import
619b0563631STom Van Eyck          * might:
620b0563631STom Van Eyck          * - If the old key does not allow PSA_KEY_USAGE_COPY.
621b0563631STom Van Eyck          * - If the old key's usage does not allow what attributes wants.
622b0563631STom Van Eyck          *   Because the key was intended for use in the pk module, and may
623b0563631STom Van Eyck          *   have had a policy chosen solely for what pk needs rather than
624b0563631STom Van Eyck          *   based on a detailed understanding of PSA policies, we are a bit
625b0563631STom Van Eyck          *   more liberal than psa_copy_key() here.
626b0563631STom Van Eyck          */
627b0563631STom Van Eyck         /* Here we need to check that the types match, otherwise we risk
628b0563631STom Van Eyck          * importing nonsensical data. */
629b0563631STom Van Eyck         psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
630b0563631STom Van Eyck         status = psa_get_key_attributes(old_key_id, &old_attributes);
631b0563631STom Van Eyck         if (status != PSA_SUCCESS) {
632b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
633b0563631STom Van Eyck         }
634b0563631STom Van Eyck         psa_key_type_t old_type = psa_get_key_type(&old_attributes);
635b0563631STom Van Eyck         psa_reset_key_attributes(&old_attributes);
636b0563631STom Van Eyck         if (old_type != psa_get_key_type(attributes)) {
637b0563631STom Van Eyck             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
638b0563631STom Van Eyck         }
639b0563631STom Van Eyck         status = export_import_into_psa(old_key_id, attributes, new_key_id);
640b0563631STom Van Eyck     }
641b0563631STom Van Eyck     return PSA_PK_TO_MBEDTLS_ERR(status);
642b0563631STom Van Eyck }
643b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */
644b0563631STom Van Eyck 
645b0563631STom Van Eyck static int import_pair_into_psa(const mbedtls_pk_context *pk,
646b0563631STom Van Eyck                                 const psa_key_attributes_t *attributes,
647b0563631STom Van Eyck                                 mbedtls_svc_key_id_t *key_id)
648b0563631STom Van Eyck {
649b0563631STom Van Eyck     switch (mbedtls_pk_get_type(pk)) {
650b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
651b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
652b0563631STom Van Eyck         {
653b0563631STom Van Eyck             if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {
654b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
655b0563631STom Van Eyck             }
656b0563631STom Van Eyck             unsigned char key_buffer[
657b0563631STom Van Eyck                 PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];
658b0563631STom Van Eyck             unsigned char *const key_end = key_buffer + sizeof(key_buffer);
659b0563631STom Van Eyck             unsigned char *key_data = key_end;
660b0563631STom Van Eyck             int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),
661b0563631STom Van Eyck                                             key_buffer, &key_data);
662b0563631STom Van Eyck             if (ret < 0) {
663b0563631STom Van Eyck                 return ret;
664b0563631STom Van Eyck             }
665b0563631STom Van Eyck             size_t key_length = key_end - key_data;
666b0563631STom Van Eyck             ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
667b0563631STom Van Eyck                                                        key_data, key_length,
668b0563631STom Van Eyck                                                        key_id));
669b0563631STom Van Eyck             mbedtls_platform_zeroize(key_data, key_length);
670b0563631STom Van Eyck             return ret;
671b0563631STom Van Eyck         }
672b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
673b0563631STom Van Eyck 
674b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
675b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
676b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
677b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
678b0563631STom Van Eyck         {
679b0563631STom Van Eyck             /* We need to check the curve family, otherwise the import could
680b0563631STom Van Eyck              * succeed with nonsensical data.
681b0563631STom Van Eyck              * We don't check the bit-size: it's optional in attributes,
682b0563631STom Van Eyck              * and if it's specified, psa_import_key() will know from the key
683b0563631STom Van Eyck              * data length and will check that the bit-size matches. */
684b0563631STom Van Eyck             psa_key_type_t to_type = psa_get_key_type(attributes);
685b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
686b0563631STom Van Eyck             psa_ecc_family_t from_family = pk->ec_family;
687b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
688b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
689b0563631STom Van Eyck             size_t from_bits = 0;
690b0563631STom Van Eyck             psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
691b0563631STom Van Eyck                                                                     &from_bits);
692b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
693b0563631STom Van Eyck             if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {
694b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
695b0563631STom Van Eyck             }
696b0563631STom Van Eyck 
697b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
698b0563631STom Van Eyck             if (mbedtls_svc_key_id_is_null(pk->priv_id)) {
699b0563631STom Van Eyck                 /* We have a public key and want a key pair. */
700b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
701b0563631STom Van Eyck             }
702b0563631STom Van Eyck             return copy_into_psa(pk->priv_id, attributes, key_id);
703b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
704b0563631STom Van Eyck             if (ec->d.n == 0) {
705b0563631STom Van Eyck                 /* Private key not set. Assume the input is a public key only.
706b0563631STom Van Eyck                  * (The other possibility is that it's an incomplete object
707b0563631STom Van Eyck                  * where the group is set but neither the public key nor
708b0563631STom Van Eyck                  * the private key. This is not possible through ecp.h
709b0563631STom Van Eyck                  * functions, so we don't bother reporting a more suitable
710b0563631STom Van Eyck                  * error in that case.) */
711b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
712b0563631STom Van Eyck             }
713b0563631STom Van Eyck             unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
714b0563631STom Van Eyck             size_t key_length = 0;
715b0563631STom Van Eyck             int ret = mbedtls_ecp_write_key_ext(ec, &key_length,
716b0563631STom Van Eyck                                                 key_buffer, sizeof(key_buffer));
717b0563631STom Van Eyck             if (ret < 0) {
718b0563631STom Van Eyck                 return ret;
719b0563631STom Van Eyck             }
720b0563631STom Van Eyck             ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
721b0563631STom Van Eyck                                                        key_buffer, key_length,
722b0563631STom Van Eyck                                                        key_id));
723b0563631STom Van Eyck             mbedtls_platform_zeroize(key_buffer, key_length);
724b0563631STom Van Eyck             return ret;
725b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
726b0563631STom Van Eyck         }
727b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
728b0563631STom Van Eyck 
729b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
730b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
731b0563631STom Van Eyck             return copy_into_psa(pk->priv_id, attributes, key_id);
732b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
733b0563631STom Van Eyck 
734b0563631STom Van Eyck         default:
735b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
736b0563631STom Van Eyck     }
737b0563631STom Van Eyck }
738b0563631STom Van Eyck 
739b0563631STom Van Eyck static int import_public_into_psa(const mbedtls_pk_context *pk,
740b0563631STom Van Eyck                                   const psa_key_attributes_t *attributes,
741b0563631STom Van Eyck                                   mbedtls_svc_key_id_t *key_id)
742b0563631STom Van Eyck {
743b0563631STom Van Eyck     psa_key_type_t psa_type = psa_get_key_type(attributes);
744b0563631STom Van Eyck 
745b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C) ||                                           \
746b0563631STom Van Eyck     (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \
747b0563631STom Van Eyck     defined(MBEDTLS_USE_PSA_CRYPTO)
748b0563631STom Van Eyck     unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
749b0563631STom Van Eyck #endif
750b0563631STom Van Eyck     unsigned char *key_data = NULL;
751b0563631STom Van Eyck     size_t key_length = 0;
752b0563631STom Van Eyck 
753b0563631STom Van Eyck     switch (mbedtls_pk_get_type(pk)) {
754b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
755b0563631STom Van Eyck         case MBEDTLS_PK_RSA:
756b0563631STom Van Eyck         {
757b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
758b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
759b0563631STom Van Eyck             }
760b0563631STom Van Eyck             unsigned char *const key_end = key_buffer + sizeof(key_buffer);
761b0563631STom Van Eyck             key_data = key_end;
762b0563631STom Van Eyck             int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),
763b0563631STom Van Eyck                                                key_buffer, &key_data);
764b0563631STom Van Eyck             if (ret < 0) {
765b0563631STom Van Eyck                 return ret;
766b0563631STom Van Eyck             }
767b0563631STom Van Eyck             key_length = (size_t) ret;
768b0563631STom Van Eyck             break;
769b0563631STom Van Eyck         }
770b0563631STom Van Eyck #endif /*MBEDTLS_RSA_C */
771b0563631STom Van Eyck 
772b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
773b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY:
774b0563631STom Van Eyck         case MBEDTLS_PK_ECKEY_DH:
775b0563631STom Van Eyck         case MBEDTLS_PK_ECDSA:
776b0563631STom Van Eyck         {
777b0563631STom Van Eyck             /* We need to check the curve family, otherwise the import could
778b0563631STom Van Eyck              * succeed with nonsensical data.
779b0563631STom Van Eyck              * We don't check the bit-size: it's optional in attributes,
780b0563631STom Van Eyck              * and if it's specified, psa_import_key() will know from the key
781b0563631STom Van Eyck              * data length and will check that the bit-size matches. */
782b0563631STom Van Eyck #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
783b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {
784b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
785b0563631STom Van Eyck             }
786b0563631STom Van Eyck             key_data = (unsigned char *) pk->pub_raw;
787b0563631STom Van Eyck             key_length = pk->pub_raw_len;
788b0563631STom Van Eyck #else /* MBEDTLS_PK_USE_PSA_EC_DATA */
789b0563631STom Van Eyck             const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
790b0563631STom Van Eyck             size_t from_bits = 0;
791b0563631STom Van Eyck             psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
792b0563631STom Van Eyck                                                                     &from_bits);
793b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {
794b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
795b0563631STom Van Eyck             }
796b0563631STom Van Eyck             int ret = mbedtls_ecp_write_public_key(
797b0563631STom Van Eyck                 ec, MBEDTLS_ECP_PF_UNCOMPRESSED,
798b0563631STom Van Eyck                 &key_length, key_buffer, sizeof(key_buffer));
799b0563631STom Van Eyck             if (ret < 0) {
800b0563631STom Van Eyck                 return ret;
801b0563631STom Van Eyck             }
802b0563631STom Van Eyck             key_data = key_buffer;
803b0563631STom Van Eyck #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
804b0563631STom Van Eyck             break;
805b0563631STom Van Eyck         }
806b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
807b0563631STom Van Eyck 
808b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
809b0563631STom Van Eyck         case MBEDTLS_PK_OPAQUE:
810b0563631STom Van Eyck         {
811b0563631STom Van Eyck             psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
812b0563631STom Van Eyck             psa_status_t status =
813b0563631STom Van Eyck                 psa_get_key_attributes(pk->priv_id, &old_attributes);
814b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
815b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
816b0563631STom Van Eyck             }
817b0563631STom Van Eyck             psa_key_type_t old_type = psa_get_key_type(&old_attributes);
818b0563631STom Van Eyck             psa_reset_key_attributes(&old_attributes);
819b0563631STom Van Eyck             if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {
820b0563631STom Van Eyck                 return MBEDTLS_ERR_PK_TYPE_MISMATCH;
821b0563631STom Van Eyck             }
822b0563631STom Van Eyck             status = psa_export_public_key(pk->priv_id,
823b0563631STom Van Eyck                                            key_buffer, sizeof(key_buffer),
824b0563631STom Van Eyck                                            &key_length);
825b0563631STom Van Eyck             if (status != PSA_SUCCESS) {
826b0563631STom Van Eyck                 return PSA_PK_TO_MBEDTLS_ERR(status);
827b0563631STom Van Eyck             }
828b0563631STom Van Eyck             key_data = key_buffer;
829b0563631STom Van Eyck             break;
830b0563631STom Van Eyck         }
831b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
832b0563631STom Van Eyck 
833b0563631STom Van Eyck         default:
834b0563631STom Van Eyck             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
835b0563631STom Van Eyck     }
836b0563631STom Van Eyck 
837b0563631STom Van Eyck     return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
838b0563631STom Van Eyck                                                 key_data, key_length,
839b0563631STom Van Eyck                                                 key_id));
840b0563631STom Van Eyck }
841b0563631STom Van Eyck 
842b0563631STom Van Eyck int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
843b0563631STom Van Eyck                                const psa_key_attributes_t *attributes,
844b0563631STom Van Eyck                                mbedtls_svc_key_id_t *key_id)
845b0563631STom Van Eyck {
846b0563631STom Van Eyck     /* Set the output immediately so that it won't contain garbage even
847b0563631STom Van Eyck      * if we error out before calling psa_import_key(). */
848b0563631STom Van Eyck     *key_id = MBEDTLS_SVC_KEY_ID_INIT;
849b0563631STom Van Eyck 
850b0563631STom Van Eyck #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
851b0563631STom Van Eyck     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {
852b0563631STom Van Eyck         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
853b0563631STom Van Eyck     }
854b0563631STom Van Eyck #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
855b0563631STom Van Eyck 
856b0563631STom Van Eyck     int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));
857b0563631STom Van Eyck     if (want_public) {
858b0563631STom Van Eyck         return import_public_into_psa(pk, attributes, key_id);
859b0563631STom Van Eyck     } else {
860b0563631STom Van Eyck         return import_pair_into_psa(pk, attributes, key_id);
861b0563631STom Van Eyck     }
862b0563631STom Van Eyck }
863b0563631STom Van Eyck 
864b0563631STom Van Eyck static int copy_from_psa(mbedtls_svc_key_id_t key_id,
865b0563631STom Van Eyck                          mbedtls_pk_context *pk,
866b0563631STom Van Eyck                          int public_only)
867b0563631STom Van Eyck {
868b0563631STom Van Eyck     psa_status_t status;
869b0563631STom Van Eyck     psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
870b0563631STom Van Eyck     psa_key_type_t key_type;
871b0563631STom Van Eyck     size_t key_bits;
872b0563631STom Van Eyck     /* Use a buffer size large enough to contain either a key pair or public key. */
873b0563631STom Van Eyck     unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
874b0563631STom Van Eyck     size_t exp_key_len;
875b0563631STom Van Eyck     int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
876b0563631STom Van Eyck 
877b0563631STom Van Eyck     if (pk == NULL) {
878b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
879b0563631STom Van Eyck     }
880b0563631STom Van Eyck 
881b0563631STom Van Eyck     status = psa_get_key_attributes(key_id, &key_attr);
882b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
883b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
884b0563631STom Van Eyck     }
885b0563631STom Van Eyck 
886b0563631STom Van Eyck     if (public_only) {
887b0563631STom Van Eyck         status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
888b0563631STom Van Eyck     } else {
889b0563631STom Van Eyck         status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
890b0563631STom Van Eyck     }
891b0563631STom Van Eyck     if (status != PSA_SUCCESS) {
892b0563631STom Van Eyck         ret = PSA_PK_TO_MBEDTLS_ERR(status);
893b0563631STom Van Eyck         goto exit;
894b0563631STom Van Eyck     }
895b0563631STom Van Eyck 
896b0563631STom Van Eyck     key_type = psa_get_key_type(&key_attr);
897b0563631STom Van Eyck     if (public_only) {
898b0563631STom Van Eyck         key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
899b0563631STom Van Eyck     }
900b0563631STom Van Eyck     key_bits = psa_get_key_bits(&key_attr);
901b0563631STom Van Eyck 
902b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C)
903b0563631STom Van Eyck     if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
904b0563631STom Van Eyck         (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {
905b0563631STom Van Eyck 
906b0563631STom Van Eyck         ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
907b0563631STom Van Eyck         if (ret != 0) {
908b0563631STom Van Eyck             goto exit;
909b0563631STom Van Eyck         }
910b0563631STom Van Eyck 
911b0563631STom Van Eyck         if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
912b0563631STom Van Eyck             ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
913b0563631STom Van Eyck         } else {
914b0563631STom Van Eyck             ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
915b0563631STom Van Eyck         }
916b0563631STom Van Eyck         if (ret != 0) {
917b0563631STom Van Eyck             goto exit;
918b0563631STom Van Eyck         }
919b0563631STom Van Eyck 
920*cb034002SJerome Forissier         psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr);
921b0563631STom Van Eyck         mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
922b0563631STom Van Eyck         if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
923b0563631STom Van Eyck             md_type = mbedtls_md_type_from_psa_alg(alg_type);
924b0563631STom Van Eyck         }
925b0563631STom Van Eyck 
926b0563631STom Van Eyck         if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {
927b0563631STom Van Eyck             ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);
928b0563631STom Van Eyck         } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||
929b0563631STom Van Eyck                    alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {
930b0563631STom Van Eyck             ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);
931b0563631STom Van Eyck         }
932b0563631STom Van Eyck         if (ret != 0) {
933b0563631STom Van Eyck             goto exit;
934b0563631STom Van Eyck         }
935b0563631STom Van Eyck     } else
936b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C */
937b0563631STom Van Eyck #if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
938b0563631STom Van Eyck     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
939b0563631STom Van Eyck         PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {
940b0563631STom Van Eyck         mbedtls_ecp_group_id grp_id;
941b0563631STom Van Eyck 
942b0563631STom Van Eyck         ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
943b0563631STom Van Eyck         if (ret != 0) {
944b0563631STom Van Eyck             goto exit;
945b0563631STom Van Eyck         }
946b0563631STom Van Eyck 
947b0563631STom Van Eyck         grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);
948b0563631STom Van Eyck         ret = mbedtls_pk_ecc_set_group(pk, grp_id);
949b0563631STom Van Eyck         if (ret != 0) {
950b0563631STom Van Eyck             goto exit;
951b0563631STom Van Eyck         }
952b0563631STom Van Eyck 
953b0563631STom Van Eyck         if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
954b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);
955b0563631STom Van Eyck             if (ret != 0) {
956b0563631STom Van Eyck                 goto exit;
957b0563631STom Van Eyck             }
958b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,
959b0563631STom Van Eyck                                                      mbedtls_psa_get_random,
960b0563631STom Van Eyck                                                      MBEDTLS_PSA_RANDOM_STATE);
961b0563631STom Van Eyck         } else {
962b0563631STom Van Eyck             ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);
963b0563631STom Van Eyck         }
964b0563631STom Van Eyck         if (ret != 0) {
965b0563631STom Van Eyck             goto exit;
966b0563631STom Van Eyck         }
967b0563631STom Van Eyck     } else
968b0563631STom Van Eyck #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
969b0563631STom Van Eyck     {
970*cb034002SJerome Forissier         (void) key_bits;
971b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
972b0563631STom Van Eyck     }
973b0563631STom Van Eyck 
974b0563631STom Van Eyck exit:
975b0563631STom Van Eyck     psa_reset_key_attributes(&key_attr);
976b0563631STom Van Eyck     mbedtls_platform_zeroize(exp_key, sizeof(exp_key));
977b0563631STom Van Eyck 
978b0563631STom Van Eyck     return ret;
979b0563631STom Van Eyck }
980b0563631STom Van Eyck 
981b0563631STom Van Eyck int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
982b0563631STom Van Eyck                              mbedtls_pk_context *pk)
983b0563631STom Van Eyck {
984b0563631STom Van Eyck     return copy_from_psa(key_id, pk, 0);
985b0563631STom Van Eyck }
986b0563631STom Van Eyck 
987b0563631STom Van Eyck int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
988b0563631STom Van Eyck                                     mbedtls_pk_context *pk)
989b0563631STom Van Eyck {
990b0563631STom Van Eyck     return copy_from_psa(key_id, pk, 1);
991b0563631STom Van Eyck }
992b0563631STom Van Eyck #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
993b0563631STom 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 
1003b0563631STom 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 
1068b0563631STom 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 
1085b0563631STom 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 
1129b0563631STom Van Eyck     /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()
1130b0563631STom Van Eyck      * below would return a NULL pointer. */
1131b0563631STom Van Eyck     if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {
1132b0563631STom Van Eyck         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1133b0563631STom Van Eyck     }
1134b0563631STom 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 
1139b0563631STom 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     }
1143b0563631STom 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 
1160b0563631STom 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);
1165b0563631STom 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
1204b0563631STom 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 
1259b0563631STom 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 
1278b0563631STom 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 
1321b0563631STom Van Eyck #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
1322b0563631STom Van Eyck 
1323b0563631STom Van Eyck #if defined(MBEDTLS_USE_PSA_CRYPTO)
1324b0563631STom 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) {
133032b31808SJens Wiklander         psa_status_t status;
133132b31808SJens Wiklander 
1332*cb034002SJerome Forissier         /* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when
1333*cb034002SJerome Forissier          * performing a signature, but they are encoded differently. Instead of
1334*cb034002SJerome Forissier          * extracting the proper one from the wrapped key policy, just try both. */
1335*cb034002SJerome Forissier         status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
133632b31808SJens Wiklander                                hash, hash_len,
133732b31808SJens Wiklander                                sig, sig_size, sig_len);
1338*cb034002SJerome Forissier         if (status == PSA_ERROR_NOT_PERMITTED) {
1339*cb034002SJerome Forissier             status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg),
1340*cb034002SJerome Forissier                                    hash, hash_len,
1341*cb034002SJerome Forissier                                    sig, sig_size, sig_len);
1342*cb034002SJerome Forissier         }
134332b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
134432b31808SJens Wiklander     }
134532b31808SJens Wiklander 
134632b31808SJens Wiklander     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
134732b31808SJens Wiklander                                        ctx->pk_ctx, hash, hash_len,
134832b31808SJens Wiklander                                        sig, sig_size, sig_len);
1349b0563631STom Van Eyck #else /* MBEDTLS_USE_PSA_CRYPTO */
135032b31808SJens Wiklander 
1351b0563631STom Van Eyck     if (sig_size < mbedtls_pk_get_len(ctx)) {
1352b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
135332b31808SJens Wiklander     }
1354b0563631STom Van Eyck 
1355b0563631STom Van Eyck     if (pk_hashlen_helper(md_alg, &hash_len) != 0) {
1356b0563631STom Van Eyck         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1357b0563631STom Van Eyck     }
1358b0563631STom Van Eyck 
1359b0563631STom Van Eyck     mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx);
1360b0563631STom Van Eyck 
1361b0563631STom Van Eyck     const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg,
1362b0563631STom Van Eyck                                                               (unsigned int) hash_len, hash, sig);
1363b0563631STom Van Eyck     if (ret == 0) {
1364b0563631STom Van Eyck         *sig_len = rsa_ctx->len;
1365b0563631STom Van Eyck     }
1366b0563631STom Van Eyck     return ret;
1367b0563631STom Van Eyck 
1368b0563631STom Van Eyck #endif /* MBEDTLS_USE_PSA_CRYPTO */
1369b0563631STom Van Eyck 
1370b0563631STom Van Eyck #else
1371b0563631STom Van Eyck     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
1372b0563631STom Van Eyck #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
1373b0563631STom Van Eyck }
137432b31808SJens Wiklander 
1375817466cbSJens Wiklander /*
1376817466cbSJens Wiklander  * Decrypt message
1377817466cbSJens Wiklander  */
1378817466cbSJens Wiklander int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
1379817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
1380817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
1381817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1382817466cbSJens Wiklander {
138332b31808SJens Wiklander     if (ctx->pk_info == NULL) {
138432b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
138532b31808SJens Wiklander     }
13863d3b0591SJens Wiklander 
138732b31808SJens Wiklander     if (ctx->pk_info->decrypt_func == NULL) {
138832b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
138932b31808SJens Wiklander     }
1390817466cbSJens Wiklander 
1391b0563631STom Van Eyck     return ctx->pk_info->decrypt_func(ctx, input, ilen,
139232b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
1393817466cbSJens Wiklander }
1394817466cbSJens Wiklander 
1395817466cbSJens Wiklander /*
1396817466cbSJens Wiklander  * Encrypt message
1397817466cbSJens Wiklander  */
1398817466cbSJens Wiklander int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
1399817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
1400817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
1401817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1402817466cbSJens Wiklander {
140332b31808SJens Wiklander     if (ctx->pk_info == NULL) {
140432b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
140532b31808SJens Wiklander     }
14063d3b0591SJens Wiklander 
140732b31808SJens Wiklander     if (ctx->pk_info->encrypt_func == NULL) {
140832b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
140932b31808SJens Wiklander     }
1410817466cbSJens Wiklander 
1411b0563631STom Van Eyck     return ctx->pk_info->encrypt_func(ctx, input, ilen,
141232b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
1413817466cbSJens Wiklander }
1414817466cbSJens Wiklander 
1415817466cbSJens Wiklander /*
1416817466cbSJens Wiklander  * Check public-private key pair
1417817466cbSJens Wiklander  */
141832b31808SJens Wiklander int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
141932b31808SJens Wiklander                           const mbedtls_pk_context *prv,
142032b31808SJens Wiklander                           int (*f_rng)(void *, unsigned char *, size_t),
142132b31808SJens Wiklander                           void *p_rng)
1422817466cbSJens Wiklander {
14233d3b0591SJens Wiklander     if (pub->pk_info == NULL ||
142432b31808SJens Wiklander         prv->pk_info == NULL) {
142532b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1426817466cbSJens Wiklander     }
1427817466cbSJens Wiklander 
142832b31808SJens Wiklander     if (f_rng == NULL) {
142932b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
1430817466cbSJens Wiklander     }
1431817466cbSJens Wiklander 
143232b31808SJens Wiklander     if (prv->pk_info->check_pair_func == NULL) {
143332b31808SJens Wiklander         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
143432b31808SJens Wiklander     }
143532b31808SJens Wiklander 
143632b31808SJens Wiklander     if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {
143732b31808SJens Wiklander         if (pub->pk_info->type != MBEDTLS_PK_RSA) {
143832b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
143932b31808SJens Wiklander         }
144032b31808SJens Wiklander     } else {
1441b0563631STom Van Eyck         if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) &&
1442b0563631STom Van Eyck             (pub->pk_info != prv->pk_info)) {
144332b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
144432b31808SJens Wiklander         }
144532b31808SJens Wiklander     }
144632b31808SJens Wiklander 
1447b0563631STom Van Eyck     return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub,
1448b0563631STom Van Eyck                                          (mbedtls_pk_context *) prv,
1449b0563631STom Van Eyck                                          f_rng, p_rng);
1450817466cbSJens Wiklander }
1451817466cbSJens Wiklander 
1452817466cbSJens Wiklander /*
1453817466cbSJens Wiklander  * Get key size in bits
1454817466cbSJens Wiklander  */
1455817466cbSJens Wiklander size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
1456817466cbSJens Wiklander {
14573d3b0591SJens Wiklander     /* For backward compatibility, accept NULL or a context that
14583d3b0591SJens Wiklander      * isn't set up yet, and return a fake value that should be safe. */
145932b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
146032b31808SJens Wiklander         return 0;
146132b31808SJens Wiklander     }
1462817466cbSJens Wiklander 
1463b0563631STom Van Eyck     return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx);
1464817466cbSJens Wiklander }
1465817466cbSJens Wiklander 
1466817466cbSJens Wiklander /*
1467817466cbSJens Wiklander  * Export debug information
1468817466cbSJens Wiklander  */
1469817466cbSJens Wiklander int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
1470817466cbSJens Wiklander {
147132b31808SJens Wiklander     if (ctx->pk_info == NULL) {
147232b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
147332b31808SJens Wiklander     }
1474817466cbSJens Wiklander 
147532b31808SJens Wiklander     if (ctx->pk_info->debug_func == NULL) {
147632b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
147732b31808SJens Wiklander     }
1478817466cbSJens Wiklander 
1479b0563631STom Van Eyck     ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items);
148032b31808SJens Wiklander     return 0;
1481817466cbSJens Wiklander }
1482817466cbSJens Wiklander 
1483817466cbSJens Wiklander /*
1484817466cbSJens Wiklander  * Access the PK type name
1485817466cbSJens Wiklander  */
1486817466cbSJens Wiklander const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
1487817466cbSJens Wiklander {
148832b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
148932b31808SJens Wiklander         return "invalid PK";
149032b31808SJens Wiklander     }
1491817466cbSJens Wiklander 
149232b31808SJens Wiklander     return ctx->pk_info->name;
1493817466cbSJens Wiklander }
1494817466cbSJens Wiklander 
1495817466cbSJens Wiklander /*
1496817466cbSJens Wiklander  * Access the PK type
1497817466cbSJens Wiklander  */
1498817466cbSJens Wiklander mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
1499817466cbSJens Wiklander {
150032b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
150132b31808SJens Wiklander         return MBEDTLS_PK_NONE;
150232b31808SJens Wiklander     }
1503817466cbSJens Wiklander 
150432b31808SJens Wiklander     return ctx->pk_info->type;
1505817466cbSJens Wiklander }
1506817466cbSJens Wiklander 
1507817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
1508