xref: /optee_os/lib/libmbedtls/mbedtls/library/pk.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Public Key abstraction layer
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
207901324dSJerome Forissier #include "common.h"
21817466cbSJens Wiklander 
22817466cbSJens Wiklander #if defined(MBEDTLS_PK_C)
23817466cbSJens Wiklander #include "mbedtls/pk.h"
24*32b31808SJens Wiklander #include "pk_wrap.h"
25*32b31808SJens Wiklander #include "pkwrite.h"
26*32b31808SJens Wiklander 
27*32b31808SJens Wiklander #include "hash_info.h"
28817466cbSJens Wiklander 
293d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3011fa71b9SJerome Forissier #include "mbedtls/error.h"
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
33817466cbSJens Wiklander #include "mbedtls/rsa.h"
34817466cbSJens Wiklander #endif
35817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
36817466cbSJens Wiklander #include "mbedtls/ecp.h"
37817466cbSJens Wiklander #endif
38817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
39817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
40817466cbSJens Wiklander #endif
41817466cbSJens Wiklander 
42*32b31808SJens Wiklander #if defined(MBEDTLS_PSA_CRYPTO_C)
4311fa71b9SJerome Forissier #include "mbedtls/psa_util.h"
44*32b31808SJens Wiklander #define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
45*32b31808SJens Wiklander #define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
46*32b31808SJens Wiklander                                                                   psa_to_pk_rsa_errors,            \
47*32b31808SJens Wiklander                                                                   psa_pk_status_to_mbedtls)
48*32b31808SJens Wiklander #define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
49*32b31808SJens Wiklander                                                                     psa_to_pk_ecdsa_errors,        \
50*32b31808SJens Wiklander                                                                     psa_pk_status_to_mbedtls)
5111fa71b9SJerome Forissier #endif
5211fa71b9SJerome Forissier 
53817466cbSJens Wiklander #include <limits.h>
543d3b0591SJens Wiklander #include <stdint.h>
55817466cbSJens Wiklander 
56817466cbSJens Wiklander /*
57817466cbSJens Wiklander  * Initialise a mbedtls_pk_context
58817466cbSJens Wiklander  */
59817466cbSJens Wiklander void mbedtls_pk_init(mbedtls_pk_context *ctx)
60817466cbSJens Wiklander {
61817466cbSJens Wiklander     ctx->pk_info = NULL;
62817466cbSJens Wiklander     ctx->pk_ctx = NULL;
63817466cbSJens Wiklander }
64817466cbSJens Wiklander 
65817466cbSJens Wiklander /*
66817466cbSJens Wiklander  * Free (the components of) a mbedtls_pk_context
67817466cbSJens Wiklander  */
68817466cbSJens Wiklander void mbedtls_pk_free(mbedtls_pk_context *ctx)
69817466cbSJens Wiklander {
70*32b31808SJens Wiklander     if (ctx == NULL) {
71817466cbSJens Wiklander         return;
72*32b31808SJens Wiklander     }
73817466cbSJens Wiklander 
74*32b31808SJens Wiklander     if (ctx->pk_info != NULL) {
75817466cbSJens Wiklander         ctx->pk_info->ctx_free_func(ctx->pk_ctx);
76*32b31808SJens Wiklander     }
77817466cbSJens Wiklander 
783d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));
79817466cbSJens Wiklander }
80817466cbSJens Wiklander 
813d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
823d3b0591SJens Wiklander /*
833d3b0591SJens Wiklander  * Initialize a restart context
843d3b0591SJens Wiklander  */
853d3b0591SJens Wiklander void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx)
863d3b0591SJens Wiklander {
873d3b0591SJens Wiklander     ctx->pk_info = NULL;
883d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
893d3b0591SJens Wiklander }
903d3b0591SJens Wiklander 
913d3b0591SJens Wiklander /*
923d3b0591SJens Wiklander  * Free the components of a restart context
933d3b0591SJens Wiklander  */
943d3b0591SJens Wiklander void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx)
953d3b0591SJens Wiklander {
963d3b0591SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL ||
97*32b31808SJens Wiklander         ctx->pk_info->rs_free_func == NULL) {
983d3b0591SJens Wiklander         return;
993d3b0591SJens Wiklander     }
1003d3b0591SJens Wiklander 
1013d3b0591SJens Wiklander     ctx->pk_info->rs_free_func(ctx->rs_ctx);
1023d3b0591SJens Wiklander 
1033d3b0591SJens Wiklander     ctx->pk_info = NULL;
1043d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
1053d3b0591SJens Wiklander }
1063d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
1073d3b0591SJens Wiklander 
108817466cbSJens Wiklander /*
109817466cbSJens Wiklander  * Get pk_info structure from type
110817466cbSJens Wiklander  */
111817466cbSJens Wiklander const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
112817466cbSJens Wiklander {
113817466cbSJens Wiklander     switch (pk_type) {
114817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
115817466cbSJens Wiklander         case MBEDTLS_PK_RSA:
116*32b31808SJens Wiklander             return &mbedtls_rsa_info;
117817466cbSJens Wiklander #endif
118817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
119817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY:
120*32b31808SJens Wiklander             return &mbedtls_eckey_info;
121817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY_DH:
122*32b31808SJens Wiklander             return &mbedtls_eckeydh_info;
123817466cbSJens Wiklander #endif
124*32b31808SJens Wiklander #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
125817466cbSJens Wiklander         case MBEDTLS_PK_ECDSA:
126*32b31808SJens Wiklander             return &mbedtls_ecdsa_info;
127817466cbSJens Wiklander #endif
128817466cbSJens Wiklander         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
129817466cbSJens Wiklander         default:
130*32b31808SJens Wiklander             return NULL;
131817466cbSJens Wiklander     }
132817466cbSJens Wiklander }
133817466cbSJens Wiklander 
134817466cbSJens Wiklander /*
135817466cbSJens Wiklander  * Initialise context
136817466cbSJens Wiklander  */
137817466cbSJens Wiklander int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
138817466cbSJens Wiklander {
139*32b31808SJens Wiklander     if (info == NULL || ctx->pk_info != NULL) {
140*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
141*32b31808SJens Wiklander     }
142817466cbSJens Wiklander 
143*32b31808SJens Wiklander     if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
144*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
145*32b31808SJens Wiklander     }
146817466cbSJens Wiklander 
147817466cbSJens Wiklander     ctx->pk_info = info;
148817466cbSJens Wiklander 
149*32b31808SJens Wiklander     return 0;
150817466cbSJens Wiklander }
151817466cbSJens Wiklander 
15211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
15311fa71b9SJerome Forissier /*
15411fa71b9SJerome Forissier  * Initialise a PSA-wrapping context
15511fa71b9SJerome Forissier  */
1567901324dSJerome Forissier int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
157*32b31808SJens Wiklander                             const mbedtls_svc_key_id_t key)
15811fa71b9SJerome Forissier {
159*32b31808SJens Wiklander     const mbedtls_pk_info_t *info = NULL;
16011fa71b9SJerome Forissier     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
161*32b31808SJens Wiklander     mbedtls_svc_key_id_t *pk_ctx;
16211fa71b9SJerome Forissier     psa_key_type_t type;
16311fa71b9SJerome Forissier 
164*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info != NULL) {
165*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
166*32b31808SJens Wiklander     }
16711fa71b9SJerome Forissier 
168*32b31808SJens Wiklander     if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) {
169*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
170*32b31808SJens Wiklander     }
17111fa71b9SJerome Forissier     type = psa_get_key_type(&attributes);
17211fa71b9SJerome Forissier     psa_reset_key_attributes(&attributes);
17311fa71b9SJerome Forissier 
174*32b31808SJens Wiklander     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
175*32b31808SJens Wiklander         info = &mbedtls_pk_ecdsa_opaque_info;
176*32b31808SJens Wiklander     } else if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
177*32b31808SJens Wiklander         info = &mbedtls_pk_rsa_opaque_info;
178*32b31808SJens Wiklander     } else {
179*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
180*32b31808SJens Wiklander     }
18111fa71b9SJerome Forissier 
182*32b31808SJens Wiklander     if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
183*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
184*32b31808SJens Wiklander     }
18511fa71b9SJerome Forissier 
18611fa71b9SJerome Forissier     ctx->pk_info = info;
18711fa71b9SJerome Forissier 
188*32b31808SJens Wiklander     pk_ctx = (mbedtls_svc_key_id_t *) ctx->pk_ctx;
18911fa71b9SJerome Forissier     *pk_ctx = key;
19011fa71b9SJerome Forissier 
191*32b31808SJens 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 
207*32b31808SJens Wiklander     if (ctx->pk_info != NULL) {
208*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
209*32b31808SJens Wiklander     }
210817466cbSJens Wiklander 
211*32b31808SJens Wiklander     if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
212*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
213*32b31808SJens 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 
224*32b31808SJens 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. */
236*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
237*32b31808SJens Wiklander         return 0;
238817466cbSJens Wiklander     }
239817466cbSJens Wiklander 
240*32b31808SJens Wiklander     return ctx->pk_info->can_do(type);
241*32b31808SJens Wiklander }
242*32b31808SJens Wiklander 
243*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
244*32b31808SJens Wiklander /*
245*32b31808SJens Wiklander  * Tell if a PK can do the operations of the given PSA algorithm
246*32b31808SJens Wiklander  */
247*32b31808SJens Wiklander int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
248*32b31808SJens Wiklander                           psa_key_usage_t usage)
249*32b31808SJens Wiklander {
250*32b31808SJens Wiklander     psa_key_usage_t key_usage;
251*32b31808SJens Wiklander 
252*32b31808SJens Wiklander     /* A context with null pk_info is not set up yet and can't do anything.
253*32b31808SJens Wiklander      * For backward compatibility, also accept NULL instead of a context
254*32b31808SJens Wiklander      * pointer. */
255*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
256*32b31808SJens Wiklander         return 0;
257*32b31808SJens Wiklander     }
258*32b31808SJens Wiklander 
259*32b31808SJens Wiklander     /* Filter out non allowed algorithms */
260*32b31808SJens Wiklander     if (PSA_ALG_IS_ECDSA(alg) == 0 &&
261*32b31808SJens Wiklander         PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 &&
262*32b31808SJens Wiklander         PSA_ALG_IS_RSA_PSS(alg) == 0 &&
263*32b31808SJens Wiklander         alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
264*32b31808SJens Wiklander         PSA_ALG_IS_ECDH(alg) == 0) {
265*32b31808SJens Wiklander         return 0;
266*32b31808SJens Wiklander     }
267*32b31808SJens Wiklander 
268*32b31808SJens Wiklander     /* Filter out non allowed usage flags */
269*32b31808SJens Wiklander     if (usage == 0 ||
270*32b31808SJens Wiklander         (usage & ~(PSA_KEY_USAGE_SIGN_HASH |
271*32b31808SJens Wiklander                    PSA_KEY_USAGE_DECRYPT |
272*32b31808SJens Wiklander                    PSA_KEY_USAGE_DERIVE)) != 0) {
273*32b31808SJens Wiklander         return 0;
274*32b31808SJens Wiklander     }
275*32b31808SJens Wiklander 
276*32b31808SJens Wiklander     /* Wildcard hash is not allowed */
277*32b31808SJens Wiklander     if (PSA_ALG_IS_SIGN_HASH(alg) &&
278*32b31808SJens Wiklander         PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) {
279*32b31808SJens Wiklander         return 0;
280*32b31808SJens Wiklander     }
281*32b31808SJens Wiklander 
282*32b31808SJens Wiklander     if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) {
283*32b31808SJens Wiklander         mbedtls_pk_type_t type;
284*32b31808SJens Wiklander 
285*32b31808SJens Wiklander         if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) {
286*32b31808SJens Wiklander             type = MBEDTLS_PK_ECKEY;
287*32b31808SJens Wiklander         } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
288*32b31808SJens Wiklander                    alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
289*32b31808SJens Wiklander             type = MBEDTLS_PK_RSA;
290*32b31808SJens Wiklander         } else if (PSA_ALG_IS_RSA_PSS(alg)) {
291*32b31808SJens Wiklander             type = MBEDTLS_PK_RSASSA_PSS;
292*32b31808SJens Wiklander         } else {
293*32b31808SJens Wiklander             return 0;
294*32b31808SJens Wiklander         }
295*32b31808SJens Wiklander 
296*32b31808SJens Wiklander         if (ctx->pk_info->can_do(type) == 0) {
297*32b31808SJens Wiklander             return 0;
298*32b31808SJens Wiklander         }
299*32b31808SJens Wiklander 
300*32b31808SJens Wiklander         switch (type) {
301*32b31808SJens Wiklander             case MBEDTLS_PK_ECKEY:
302*32b31808SJens Wiklander                 key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
303*32b31808SJens Wiklander                 break;
304*32b31808SJens Wiklander             case MBEDTLS_PK_RSA:
305*32b31808SJens Wiklander             case MBEDTLS_PK_RSASSA_PSS:
306*32b31808SJens Wiklander                 key_usage = PSA_KEY_USAGE_SIGN_HASH |
307*32b31808SJens Wiklander                             PSA_KEY_USAGE_SIGN_MESSAGE |
308*32b31808SJens Wiklander                             PSA_KEY_USAGE_DECRYPT;
309*32b31808SJens Wiklander                 break;
310*32b31808SJens Wiklander             default:
311*32b31808SJens Wiklander                 /* Should never happen */
312*32b31808SJens Wiklander                 return 0;
313*32b31808SJens Wiklander         }
314*32b31808SJens Wiklander 
315*32b31808SJens Wiklander         return (key_usage & usage) == usage;
316*32b31808SJens Wiklander     }
317*32b31808SJens Wiklander 
318*32b31808SJens Wiklander     const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
319*32b31808SJens Wiklander     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
320*32b31808SJens Wiklander     psa_algorithm_t key_alg, key_alg2;
321*32b31808SJens Wiklander     psa_status_t status;
322*32b31808SJens Wiklander 
323*32b31808SJens Wiklander     status = psa_get_key_attributes(*key, &attributes);
324*32b31808SJens Wiklander     if (status != PSA_SUCCESS) {
325*32b31808SJens Wiklander         return 0;
326*32b31808SJens Wiklander     }
327*32b31808SJens Wiklander 
328*32b31808SJens Wiklander     key_alg = psa_get_key_algorithm(&attributes);
329*32b31808SJens Wiklander     key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
330*32b31808SJens Wiklander     key_usage = psa_get_key_usage_flags(&attributes);
331*32b31808SJens Wiklander     psa_reset_key_attributes(&attributes);
332*32b31808SJens Wiklander 
333*32b31808SJens Wiklander     if ((key_usage & usage) != usage) {
334*32b31808SJens Wiklander         return 0;
335*32b31808SJens Wiklander     }
336*32b31808SJens Wiklander 
337*32b31808SJens Wiklander     /*
338*32b31808SJens Wiklander      * Common case: the key alg or alg2 only allows alg.
339*32b31808SJens Wiklander      * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
340*32b31808SJens Wiklander      * directly.
341*32b31808SJens Wiklander      * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
342*32b31808SJens Wiklander      * a fixed hash on key_alg/key_alg2.
343*32b31808SJens Wiklander      */
344*32b31808SJens Wiklander     if (alg == key_alg || alg == key_alg2) {
345*32b31808SJens Wiklander         return 1;
346*32b31808SJens Wiklander     }
347*32b31808SJens Wiklander 
348*32b31808SJens Wiklander     /*
349*32b31808SJens Wiklander      * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash,
350*32b31808SJens Wiklander      * and alg is the same hash-and-sign family with any hash,
351*32b31808SJens Wiklander      * then alg is compliant with this key alg
352*32b31808SJens Wiklander      */
353*32b31808SJens Wiklander     if (PSA_ALG_IS_SIGN_HASH(alg)) {
354*32b31808SJens Wiklander 
355*32b31808SJens Wiklander         if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
356*32b31808SJens Wiklander             PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
357*32b31808SJens Wiklander             (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
358*32b31808SJens Wiklander             return 1;
359*32b31808SJens Wiklander         }
360*32b31808SJens Wiklander 
361*32b31808SJens Wiklander         if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
362*32b31808SJens Wiklander             PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
363*32b31808SJens Wiklander             (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
364*32b31808SJens Wiklander             return 1;
365*32b31808SJens Wiklander         }
366*32b31808SJens Wiklander     }
367*32b31808SJens Wiklander 
368*32b31808SJens Wiklander     return 0;
369*32b31808SJens Wiklander }
370*32b31808SJens Wiklander #endif /* MBEDTLS_USE_PSA_CRYPTO */
371*32b31808SJens Wiklander 
372817466cbSJens Wiklander /*
373817466cbSJens Wiklander  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
374817466cbSJens Wiklander  */
375817466cbSJens Wiklander static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
376817466cbSJens Wiklander {
377*32b31808SJens Wiklander     if (*hash_len != 0) {
378*32b31808SJens Wiklander         return 0;
379*32b31808SJens Wiklander     }
380817466cbSJens Wiklander 
381*32b31808SJens Wiklander     *hash_len = mbedtls_hash_info_get_size(md_alg);
382817466cbSJens Wiklander 
383*32b31808SJens Wiklander     if (*hash_len == 0) {
384*32b31808SJens Wiklander         return -1;
385*32b31808SJens Wiklander     }
386817466cbSJens Wiklander 
387*32b31808SJens Wiklander     return 0;
388817466cbSJens Wiklander }
389817466cbSJens Wiklander 
3903d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
3913d3b0591SJens Wiklander /*
3923d3b0591SJens Wiklander  * Helper to set up a restart context if needed
3933d3b0591SJens Wiklander  */
3943d3b0591SJens Wiklander static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx,
3953d3b0591SJens Wiklander                             const mbedtls_pk_info_t *info)
3963d3b0591SJens Wiklander {
3973d3b0591SJens Wiklander     /* Don't do anything if already set up or invalid */
398*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info != NULL) {
399*32b31808SJens Wiklander         return 0;
400*32b31808SJens Wiklander     }
4013d3b0591SJens Wiklander 
4023d3b0591SJens Wiklander     /* Should never happen when we're called */
403*32b31808SJens Wiklander     if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) {
404*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
405*32b31808SJens Wiklander     }
4063d3b0591SJens Wiklander 
407*32b31808SJens Wiklander     if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) {
408*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_ALLOC_FAILED;
409*32b31808SJens Wiklander     }
4103d3b0591SJens Wiklander 
4113d3b0591SJens Wiklander     ctx->pk_info = info;
4123d3b0591SJens Wiklander 
413*32b31808SJens Wiklander     return 0;
4143d3b0591SJens Wiklander }
4153d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
4163d3b0591SJens Wiklander 
4173d3b0591SJens Wiklander /*
4183d3b0591SJens Wiklander  * Verify a signature (restartable)
4193d3b0591SJens Wiklander  */
4203d3b0591SJens Wiklander int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
4213d3b0591SJens Wiklander                                   mbedtls_md_type_t md_alg,
4223d3b0591SJens Wiklander                                   const unsigned char *hash, size_t hash_len,
4233d3b0591SJens Wiklander                                   const unsigned char *sig, size_t sig_len,
4243d3b0591SJens Wiklander                                   mbedtls_pk_restart_ctx *rs_ctx)
4253d3b0591SJens Wiklander {
426*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
427*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
428*32b31808SJens Wiklander     }
4293d3b0591SJens Wiklander 
4303d3b0591SJens Wiklander     if (ctx->pk_info == NULL ||
431*32b31808SJens Wiklander         pk_hashlen_helper(md_alg, &hash_len) != 0) {
432*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
433*32b31808SJens Wiklander     }
4343d3b0591SJens Wiklander 
4353d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
4363d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
4373d3b0591SJens Wiklander     if (rs_ctx != NULL &&
4383d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
439*32b31808SJens Wiklander         ctx->pk_info->verify_rs_func != NULL) {
44011fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4413d3b0591SJens Wiklander 
442*32b31808SJens Wiklander         if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
443*32b31808SJens Wiklander             return ret;
444*32b31808SJens Wiklander         }
4453d3b0591SJens Wiklander 
4463d3b0591SJens Wiklander         ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx,
4473d3b0591SJens Wiklander                                            md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);
4483d3b0591SJens Wiklander 
449*32b31808SJens Wiklander         if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
4503d3b0591SJens Wiklander             mbedtls_pk_restart_free(rs_ctx);
451*32b31808SJens Wiklander         }
4523d3b0591SJens Wiklander 
453*32b31808SJens Wiklander         return ret;
4543d3b0591SJens Wiklander     }
4553d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
4563d3b0591SJens Wiklander     (void) rs_ctx;
4573d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
4583d3b0591SJens Wiklander 
459*32b31808SJens Wiklander     if (ctx->pk_info->verify_func == NULL) {
460*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
461*32b31808SJens Wiklander     }
4623d3b0591SJens Wiklander 
463*32b31808SJens Wiklander     return ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len,
464*32b31808SJens Wiklander                                      sig, sig_len);
4653d3b0591SJens Wiklander }
4663d3b0591SJens Wiklander 
467817466cbSJens Wiklander /*
468817466cbSJens Wiklander  * Verify a signature
469817466cbSJens Wiklander  */
470817466cbSJens Wiklander int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
471817466cbSJens Wiklander                       const unsigned char *hash, size_t hash_len,
472817466cbSJens Wiklander                       const unsigned char *sig, size_t sig_len)
473817466cbSJens Wiklander {
474*32b31808SJens Wiklander     return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len,
475*32b31808SJens Wiklander                                          sig, sig_len, NULL);
476817466cbSJens Wiklander }
477817466cbSJens Wiklander 
478817466cbSJens Wiklander /*
479817466cbSJens Wiklander  * Verify a signature with options
480817466cbSJens Wiklander  */
481817466cbSJens Wiklander int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
482817466cbSJens Wiklander                           mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
483817466cbSJens Wiklander                           const unsigned char *hash, size_t hash_len,
484817466cbSJens Wiklander                           const unsigned char *sig, size_t sig_len)
485817466cbSJens Wiklander {
486*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
487*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
488*32b31808SJens Wiklander     }
4893d3b0591SJens Wiklander 
490*32b31808SJens Wiklander     if (ctx->pk_info == NULL) {
491*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
492*32b31808SJens Wiklander     }
493817466cbSJens Wiklander 
494*32b31808SJens Wiklander     if (!mbedtls_pk_can_do(ctx, type)) {
495*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
496*32b31808SJens Wiklander     }
497817466cbSJens Wiklander 
498*32b31808SJens Wiklander     if (type != MBEDTLS_PK_RSASSA_PSS) {
499*32b31808SJens Wiklander         /* General case: no options */
500*32b31808SJens Wiklander         if (options != NULL) {
501*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
502*32b31808SJens Wiklander         }
503*32b31808SJens Wiklander 
504*32b31808SJens Wiklander         return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
505*32b31808SJens Wiklander     }
506*32b31808SJens Wiklander 
507817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
50811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
509817466cbSJens Wiklander     const mbedtls_pk_rsassa_pss_options *pss_opts;
510817466cbSJens Wiklander 
511*32b31808SJens Wiklander     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
512*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
513*32b31808SJens Wiklander     }
514817466cbSJens Wiklander 
515*32b31808SJens Wiklander     if (options == NULL) {
516*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
517*32b31808SJens Wiklander     }
518817466cbSJens Wiklander 
519817466cbSJens Wiklander     pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
520817466cbSJens Wiklander 
521*32b31808SJens Wiklander #if defined(MBEDTLS_USE_PSA_CRYPTO)
522*32b31808SJens Wiklander     if (pss_opts->mgf1_hash_id == md_alg) {
523*32b31808SJens Wiklander         unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
524*32b31808SJens Wiklander         unsigned char *p;
525*32b31808SJens Wiklander         int key_len;
526*32b31808SJens Wiklander         size_t signature_length;
527*32b31808SJens Wiklander         psa_status_t status = PSA_ERROR_DATA_CORRUPT;
528*32b31808SJens Wiklander         psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;
529*32b31808SJens Wiklander 
530*32b31808SJens Wiklander         psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
531*32b31808SJens Wiklander         mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
532*32b31808SJens Wiklander         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
533*32b31808SJens Wiklander         psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);
534*32b31808SJens Wiklander         p = buf + sizeof(buf);
535*32b31808SJens Wiklander         key_len = mbedtls_pk_write_pubkey(&p, buf, ctx);
536*32b31808SJens Wiklander 
537*32b31808SJens Wiklander         if (key_len < 0) {
538*32b31808SJens Wiklander             return key_len;
539*32b31808SJens Wiklander         }
540*32b31808SJens Wiklander 
541*32b31808SJens Wiklander         psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
542*32b31808SJens Wiklander         psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
543*32b31808SJens Wiklander         psa_set_key_algorithm(&attributes, psa_sig_alg);
544*32b31808SJens Wiklander 
545*32b31808SJens Wiklander         status = psa_import_key(&attributes,
546*32b31808SJens Wiklander                                 buf + sizeof(buf) - key_len, key_len,
547*32b31808SJens Wiklander                                 &key_id);
548*32b31808SJens Wiklander         if (status != PSA_SUCCESS) {
549*32b31808SJens Wiklander             psa_destroy_key(key_id);
550*32b31808SJens Wiklander             return PSA_PK_TO_MBEDTLS_ERR(status);
551*32b31808SJens Wiklander         }
552*32b31808SJens Wiklander 
553*32b31808SJens Wiklander         /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH
554*32b31808SJens Wiklander          * on a valid signature with trailing data in a buffer, but
555*32b31808SJens Wiklander          * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact,
556*32b31808SJens Wiklander          * so for this reason the passed sig_len is overwritten. Smaller
557*32b31808SJens Wiklander          * signature lengths should not be accepted for verification. */
558*32b31808SJens Wiklander         signature_length = sig_len > mbedtls_pk_get_len(ctx) ?
559*32b31808SJens Wiklander                            mbedtls_pk_get_len(ctx) : sig_len;
560*32b31808SJens Wiklander         status = psa_verify_hash(key_id, psa_sig_alg, hash,
561*32b31808SJens Wiklander                                  hash_len, sig, signature_length);
562*32b31808SJens Wiklander         destruction_status = psa_destroy_key(key_id);
563*32b31808SJens Wiklander 
564*32b31808SJens Wiklander         if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) {
565*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
566*32b31808SJens Wiklander         }
567*32b31808SJens Wiklander 
568*32b31808SJens Wiklander         if (status == PSA_SUCCESS) {
569*32b31808SJens Wiklander             status = destruction_status;
570*32b31808SJens Wiklander         }
571*32b31808SJens Wiklander 
572*32b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
573*32b31808SJens Wiklander     } else
574*32b31808SJens Wiklander #endif
575*32b31808SJens Wiklander     {
576*32b31808SJens Wiklander         if (sig_len < mbedtls_pk_get_len(ctx)) {
577*32b31808SJens Wiklander             return MBEDTLS_ERR_RSA_VERIFY_FAILED;
578*32b31808SJens Wiklander         }
579817466cbSJens Wiklander 
580817466cbSJens Wiklander         ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx),
581817466cbSJens Wiklander                                                 md_alg, (unsigned int) hash_len, hash,
582817466cbSJens Wiklander                                                 pss_opts->mgf1_hash_id,
583817466cbSJens Wiklander                                                 pss_opts->expected_salt_len,
584817466cbSJens Wiklander                                                 sig);
585*32b31808SJens Wiklander         if (ret != 0) {
586*32b31808SJens Wiklander             return ret;
587817466cbSJens Wiklander         }
588817466cbSJens Wiklander 
589*32b31808SJens Wiklander         if (sig_len > mbedtls_pk_get_len(ctx)) {
590*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
591*32b31808SJens Wiklander         }
592817466cbSJens Wiklander 
593*32b31808SJens Wiklander         return 0;
594*32b31808SJens Wiklander     }
595*32b31808SJens Wiklander #else
596*32b31808SJens Wiklander     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
597*32b31808SJens Wiklander #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
598817466cbSJens Wiklander }
599817466cbSJens Wiklander 
600817466cbSJens Wiklander /*
6013d3b0591SJens Wiklander  * Make a signature (restartable)
6023d3b0591SJens Wiklander  */
6033d3b0591SJens Wiklander int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
6043d3b0591SJens Wiklander                                 mbedtls_md_type_t md_alg,
6053d3b0591SJens Wiklander                                 const unsigned char *hash, size_t hash_len,
606*32b31808SJens Wiklander                                 unsigned char *sig, size_t sig_size, size_t *sig_len,
6073d3b0591SJens Wiklander                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
6083d3b0591SJens Wiklander                                 mbedtls_pk_restart_ctx *rs_ctx)
6093d3b0591SJens Wiklander {
610*32b31808SJens Wiklander     if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) {
611*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
612*32b31808SJens Wiklander     }
6133d3b0591SJens Wiklander 
614*32b31808SJens Wiklander     if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) {
615*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
616*32b31808SJens Wiklander     }
6173d3b0591SJens Wiklander 
6183d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
6193d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
6203d3b0591SJens Wiklander     if (rs_ctx != NULL &&
6213d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
622*32b31808SJens Wiklander         ctx->pk_info->sign_rs_func != NULL) {
62311fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6243d3b0591SJens Wiklander 
625*32b31808SJens Wiklander         if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) {
626*32b31808SJens Wiklander             return ret;
627*32b31808SJens Wiklander         }
6283d3b0591SJens Wiklander 
6293d3b0591SJens Wiklander         ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg,
630*32b31808SJens Wiklander                                          hash, hash_len,
631*32b31808SJens Wiklander                                          sig, sig_size, sig_len,
632*32b31808SJens Wiklander                                          f_rng, p_rng, rs_ctx->rs_ctx);
6333d3b0591SJens Wiklander 
634*32b31808SJens Wiklander         if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
6353d3b0591SJens Wiklander             mbedtls_pk_restart_free(rs_ctx);
636*32b31808SJens Wiklander         }
6373d3b0591SJens Wiklander 
638*32b31808SJens Wiklander         return ret;
6393d3b0591SJens Wiklander     }
6403d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
6413d3b0591SJens Wiklander     (void) rs_ctx;
6423d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
6433d3b0591SJens Wiklander 
644*32b31808SJens Wiklander     if (ctx->pk_info->sign_func == NULL) {
645*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
646*32b31808SJens Wiklander     }
6473d3b0591SJens Wiklander 
648*32b31808SJens Wiklander     return ctx->pk_info->sign_func(ctx->pk_ctx, md_alg,
649*32b31808SJens Wiklander                                    hash, hash_len,
650*32b31808SJens Wiklander                                    sig, sig_size, sig_len,
651*32b31808SJens Wiklander                                    f_rng, p_rng);
6523d3b0591SJens Wiklander }
6533d3b0591SJens Wiklander 
6543d3b0591SJens Wiklander /*
655817466cbSJens Wiklander  * Make a signature
656817466cbSJens Wiklander  */
657817466cbSJens Wiklander int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
658817466cbSJens Wiklander                     const unsigned char *hash, size_t hash_len,
659*32b31808SJens Wiklander                     unsigned char *sig, size_t sig_size, size_t *sig_len,
660817466cbSJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
661817466cbSJens Wiklander {
662*32b31808SJens Wiklander     return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len,
663*32b31808SJens Wiklander                                        sig, sig_size, sig_len,
664*32b31808SJens Wiklander                                        f_rng, p_rng, NULL);
665817466cbSJens Wiklander }
666817466cbSJens Wiklander 
667*32b31808SJens Wiklander #if defined(MBEDTLS_PSA_CRYPTO_C)
668*32b31808SJens Wiklander /*
669*32b31808SJens Wiklander  * Make a signature given a signature type.
670*32b31808SJens Wiklander  */
671*32b31808SJens Wiklander int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
672*32b31808SJens Wiklander                         mbedtls_pk_context *ctx,
673*32b31808SJens Wiklander                         mbedtls_md_type_t md_alg,
674*32b31808SJens Wiklander                         const unsigned char *hash, size_t hash_len,
675*32b31808SJens Wiklander                         unsigned char *sig, size_t sig_size, size_t *sig_len,
676*32b31808SJens Wiklander                         int (*f_rng)(void *, unsigned char *, size_t),
677*32b31808SJens Wiklander                         void *p_rng)
678*32b31808SJens Wiklander {
679*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C)
680*32b31808SJens Wiklander     psa_algorithm_t psa_md_alg;
681*32b31808SJens Wiklander #endif /* MBEDTLS_RSA_C */
682*32b31808SJens Wiklander     *sig_len = 0;
683*32b31808SJens Wiklander 
684*32b31808SJens Wiklander     if (ctx->pk_info == NULL) {
685*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
686*32b31808SJens Wiklander     }
687*32b31808SJens Wiklander 
688*32b31808SJens Wiklander     if (!mbedtls_pk_can_do(ctx, pk_type)) {
689*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
690*32b31808SJens Wiklander     }
691*32b31808SJens Wiklander 
692*32b31808SJens Wiklander     if (pk_type != MBEDTLS_PK_RSASSA_PSS) {
693*32b31808SJens Wiklander         return mbedtls_pk_sign(ctx, md_alg, hash, hash_len,
694*32b31808SJens Wiklander                                sig, sig_size, sig_len, f_rng, p_rng);
695*32b31808SJens Wiklander     }
696*32b31808SJens Wiklander 
697*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C)
698*32b31808SJens Wiklander     psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
699*32b31808SJens Wiklander     if (psa_md_alg == 0) {
700*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
701*32b31808SJens Wiklander     }
702*32b31808SJens Wiklander 
703*32b31808SJens Wiklander     if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
704*32b31808SJens Wiklander         const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
705*32b31808SJens Wiklander         psa_status_t status;
706*32b31808SJens Wiklander 
707*32b31808SJens Wiklander         status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg),
708*32b31808SJens Wiklander                                hash, hash_len,
709*32b31808SJens Wiklander                                sig, sig_size, sig_len);
710*32b31808SJens Wiklander         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
711*32b31808SJens Wiklander     }
712*32b31808SJens Wiklander 
713*32b31808SJens Wiklander     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
714*32b31808SJens Wiklander                                        ctx->pk_ctx, hash, hash_len,
715*32b31808SJens Wiklander                                        sig, sig_size, sig_len);
716*32b31808SJens Wiklander #else /* MBEDTLS_RSA_C */
717*32b31808SJens Wiklander     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
718*32b31808SJens Wiklander #endif /* !MBEDTLS_RSA_C */
719*32b31808SJens Wiklander 
720*32b31808SJens Wiklander }
721*32b31808SJens Wiklander #endif /* MBEDTLS_PSA_CRYPTO_C */
722*32b31808SJens Wiklander 
723817466cbSJens Wiklander /*
724817466cbSJens Wiklander  * Decrypt message
725817466cbSJens Wiklander  */
726817466cbSJens Wiklander int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
727817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
728817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
729817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
730817466cbSJens Wiklander {
731*32b31808SJens Wiklander     if (ctx->pk_info == NULL) {
732*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
733*32b31808SJens Wiklander     }
7343d3b0591SJens Wiklander 
735*32b31808SJens Wiklander     if (ctx->pk_info->decrypt_func == NULL) {
736*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
737*32b31808SJens Wiklander     }
738817466cbSJens Wiklander 
739*32b31808SJens Wiklander     return ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen,
740*32b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
741817466cbSJens Wiklander }
742817466cbSJens Wiklander 
743817466cbSJens Wiklander /*
744817466cbSJens Wiklander  * Encrypt message
745817466cbSJens Wiklander  */
746817466cbSJens Wiklander int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
747817466cbSJens Wiklander                        const unsigned char *input, size_t ilen,
748817466cbSJens Wiklander                        unsigned char *output, size_t *olen, size_t osize,
749817466cbSJens Wiklander                        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
750817466cbSJens Wiklander {
751*32b31808SJens Wiklander     if (ctx->pk_info == NULL) {
752*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
753*32b31808SJens Wiklander     }
7543d3b0591SJens Wiklander 
755*32b31808SJens Wiklander     if (ctx->pk_info->encrypt_func == NULL) {
756*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
757*32b31808SJens Wiklander     }
758817466cbSJens Wiklander 
759*32b31808SJens Wiklander     return ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen,
760*32b31808SJens Wiklander                                       output, olen, osize, f_rng, p_rng);
761817466cbSJens Wiklander }
762817466cbSJens Wiklander 
763817466cbSJens Wiklander /*
764817466cbSJens Wiklander  * Check public-private key pair
765817466cbSJens Wiklander  */
766*32b31808SJens Wiklander int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
767*32b31808SJens Wiklander                           const mbedtls_pk_context *prv,
768*32b31808SJens Wiklander                           int (*f_rng)(void *, unsigned char *, size_t),
769*32b31808SJens Wiklander                           void *p_rng)
770817466cbSJens Wiklander {
7713d3b0591SJens Wiklander     if (pub->pk_info == NULL ||
772*32b31808SJens Wiklander         prv->pk_info == NULL) {
773*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
774817466cbSJens Wiklander     }
775817466cbSJens Wiklander 
776*32b31808SJens Wiklander     if (f_rng == NULL) {
777*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
778817466cbSJens Wiklander     }
779817466cbSJens Wiklander 
780*32b31808SJens Wiklander     if (prv->pk_info->check_pair_func == NULL) {
781*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
782*32b31808SJens Wiklander     }
783*32b31808SJens Wiklander 
784*32b31808SJens Wiklander     if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) {
785*32b31808SJens Wiklander         if (pub->pk_info->type != MBEDTLS_PK_RSA) {
786*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
787*32b31808SJens Wiklander         }
788*32b31808SJens Wiklander     } else {
789*32b31808SJens Wiklander         if (pub->pk_info != prv->pk_info) {
790*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
791*32b31808SJens Wiklander         }
792*32b31808SJens Wiklander     }
793*32b31808SJens Wiklander 
794*32b31808SJens Wiklander     return prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx, f_rng, p_rng);
795817466cbSJens Wiklander }
796817466cbSJens Wiklander 
797817466cbSJens Wiklander /*
798817466cbSJens Wiklander  * Get key size in bits
799817466cbSJens Wiklander  */
800817466cbSJens Wiklander size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
801817466cbSJens Wiklander {
8023d3b0591SJens Wiklander     /* For backward compatibility, accept NULL or a context that
8033d3b0591SJens Wiklander      * isn't set up yet, and return a fake value that should be safe. */
804*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
805*32b31808SJens Wiklander         return 0;
806*32b31808SJens Wiklander     }
807817466cbSJens Wiklander 
808*32b31808SJens Wiklander     return ctx->pk_info->get_bitlen(ctx->pk_ctx);
809817466cbSJens Wiklander }
810817466cbSJens Wiklander 
811817466cbSJens Wiklander /*
812817466cbSJens Wiklander  * Export debug information
813817466cbSJens Wiklander  */
814817466cbSJens Wiklander int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items)
815817466cbSJens Wiklander {
816*32b31808SJens Wiklander     if (ctx->pk_info == NULL) {
817*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
818*32b31808SJens Wiklander     }
819817466cbSJens Wiklander 
820*32b31808SJens Wiklander     if (ctx->pk_info->debug_func == NULL) {
821*32b31808SJens Wiklander         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
822*32b31808SJens Wiklander     }
823817466cbSJens Wiklander 
824817466cbSJens Wiklander     ctx->pk_info->debug_func(ctx->pk_ctx, items);
825*32b31808SJens Wiklander     return 0;
826817466cbSJens Wiklander }
827817466cbSJens Wiklander 
828817466cbSJens Wiklander /*
829817466cbSJens Wiklander  * Access the PK type name
830817466cbSJens Wiklander  */
831817466cbSJens Wiklander const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx)
832817466cbSJens Wiklander {
833*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
834*32b31808SJens Wiklander         return "invalid PK";
835*32b31808SJens Wiklander     }
836817466cbSJens Wiklander 
837*32b31808SJens Wiklander     return ctx->pk_info->name;
838817466cbSJens Wiklander }
839817466cbSJens Wiklander 
840817466cbSJens Wiklander /*
841817466cbSJens Wiklander  * Access the PK type
842817466cbSJens Wiklander  */
843817466cbSJens Wiklander mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
844817466cbSJens Wiklander {
845*32b31808SJens Wiklander     if (ctx == NULL || ctx->pk_info == NULL) {
846*32b31808SJens Wiklander         return MBEDTLS_PK_NONE;
847*32b31808SJens Wiklander     }
848817466cbSJens Wiklander 
849*32b31808SJens Wiklander     return ctx->pk_info->type;
850817466cbSJens Wiklander }
851817466cbSJens Wiklander 
85211fa71b9SJerome Forissier #if defined(MBEDTLS_USE_PSA_CRYPTO)
85311fa71b9SJerome Forissier /*
85411fa71b9SJerome Forissier  * Load the key to a PSA key slot,
85511fa71b9SJerome Forissier  * then turn the PK context into a wrapper for that key slot.
85611fa71b9SJerome Forissier  *
857*32b31808SJens Wiklander  * Currently only works for EC & RSA private keys.
85811fa71b9SJerome Forissier  */
85911fa71b9SJerome Forissier int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
860*32b31808SJens Wiklander                               mbedtls_svc_key_id_t *key,
861*32b31808SJens Wiklander                               psa_algorithm_t alg,
862*32b31808SJens Wiklander                               psa_key_usage_t usage,
863*32b31808SJens Wiklander                               psa_algorithm_t alg2)
86411fa71b9SJerome Forissier {
865*32b31808SJens Wiklander #if !defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_RSA_C)
8667901324dSJerome Forissier     ((void) pk);
8677901324dSJerome Forissier     ((void) key);
868*32b31808SJens Wiklander     ((void) alg);
869*32b31808SJens Wiklander     ((void) usage);
870*32b31808SJens Wiklander     ((void) alg2);
87111fa71b9SJerome Forissier #else
872*32b31808SJens Wiklander #if defined(MBEDTLS_ECP_C)
873*32b31808SJens Wiklander     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
87411fa71b9SJerome Forissier         const mbedtls_ecp_keypair *ec;
87511fa71b9SJerome Forissier         unsigned char d[MBEDTLS_ECP_MAX_BYTES];
87611fa71b9SJerome Forissier         size_t d_len;
8777901324dSJerome Forissier         psa_ecc_family_t curve_id;
87811fa71b9SJerome Forissier         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
87911fa71b9SJerome Forissier         psa_key_type_t key_type;
88011fa71b9SJerome Forissier         size_t bits;
88111fa71b9SJerome Forissier         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
882*32b31808SJens Wiklander         psa_status_t status;
88311fa71b9SJerome Forissier 
88411fa71b9SJerome Forissier         /* export the private key material in the format PSA wants */
88511fa71b9SJerome Forissier         ec = mbedtls_pk_ec(*pk);
886*32b31808SJens Wiklander         d_len = PSA_BITS_TO_BYTES(ec->grp.nbits);
887*32b31808SJens Wiklander         if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) {
888*32b31808SJens Wiklander             return ret;
889*32b31808SJens Wiklander         }
89011fa71b9SJerome Forissier 
89111fa71b9SJerome Forissier         curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
89211fa71b9SJerome Forissier         key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id);
89311fa71b9SJerome Forissier 
89411fa71b9SJerome Forissier         /* prepare the key attributes */
89511fa71b9SJerome Forissier         psa_set_key_type(&attributes, key_type);
89611fa71b9SJerome Forissier         psa_set_key_bits(&attributes, bits);
897*32b31808SJens Wiklander         psa_set_key_usage_flags(&attributes, usage);
898*32b31808SJens Wiklander         psa_set_key_algorithm(&attributes, alg);
899*32b31808SJens Wiklander         if (alg2 != PSA_ALG_NONE) {
900*32b31808SJens Wiklander             psa_set_key_enrollment_algorithm(&attributes, alg2);
901*32b31808SJens Wiklander         }
90211fa71b9SJerome Forissier 
90311fa71b9SJerome Forissier         /* import private key into PSA */
904*32b31808SJens Wiklander         status = psa_import_key(&attributes, d, d_len, key);
905*32b31808SJens Wiklander         if (status != PSA_SUCCESS) {
906*32b31808SJens Wiklander             return PSA_PK_TO_MBEDTLS_ERR(status);
907*32b31808SJens Wiklander         }
90811fa71b9SJerome Forissier 
90911fa71b9SJerome Forissier         /* make PK context wrap the key slot */
91011fa71b9SJerome Forissier         mbedtls_pk_free(pk);
91111fa71b9SJerome Forissier         mbedtls_pk_init(pk);
91211fa71b9SJerome Forissier 
913*32b31808SJens Wiklander         return mbedtls_pk_setup_opaque(pk, *key);
914*32b31808SJens Wiklander     } else
91511fa71b9SJerome Forissier #endif /* MBEDTLS_ECP_C */
916*32b31808SJens Wiklander #if defined(MBEDTLS_RSA_C)
917*32b31808SJens Wiklander     if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
918*32b31808SJens Wiklander         unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
919*32b31808SJens Wiklander         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
920*32b31808SJens Wiklander         int key_len;
921*32b31808SJens Wiklander         psa_status_t status;
922*32b31808SJens Wiklander 
923*32b31808SJens Wiklander         /* export the private key material in the format PSA wants */
924*32b31808SJens Wiklander         key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf));
925*32b31808SJens Wiklander         if (key_len <= 0) {
926*32b31808SJens Wiklander             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
927*32b31808SJens Wiklander         }
928*32b31808SJens Wiklander 
929*32b31808SJens Wiklander         /* prepare the key attributes */
930*32b31808SJens Wiklander         psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
931*32b31808SJens Wiklander         psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk));
932*32b31808SJens Wiklander         psa_set_key_usage_flags(&attributes, usage);
933*32b31808SJens Wiklander         psa_set_key_algorithm(&attributes, alg);
934*32b31808SJens Wiklander         if (alg2 != PSA_ALG_NONE) {
935*32b31808SJens Wiklander             psa_set_key_enrollment_algorithm(&attributes, alg2);
936*32b31808SJens Wiklander         }
937*32b31808SJens Wiklander 
938*32b31808SJens Wiklander         /* import private key into PSA */
939*32b31808SJens Wiklander         status = psa_import_key(&attributes,
940*32b31808SJens Wiklander                                 buf + sizeof(buf) - key_len,
941*32b31808SJens Wiklander                                 key_len, key);
942*32b31808SJens Wiklander 
943*32b31808SJens Wiklander         mbedtls_platform_zeroize(buf, sizeof(buf));
944*32b31808SJens Wiklander 
945*32b31808SJens Wiklander         if (status != PSA_SUCCESS) {
946*32b31808SJens Wiklander             return PSA_PK_TO_MBEDTLS_ERR(status);
947*32b31808SJens Wiklander         }
948*32b31808SJens Wiklander 
949*32b31808SJens Wiklander         /* make PK context wrap the key slot */
950*32b31808SJens Wiklander         mbedtls_pk_free(pk);
951*32b31808SJens Wiklander         mbedtls_pk_init(pk);
952*32b31808SJens Wiklander 
953*32b31808SJens Wiklander         return mbedtls_pk_setup_opaque(pk, *key);
954*32b31808SJens Wiklander     } else
955*32b31808SJens Wiklander #endif /* MBEDTLS_RSA_C */
956*32b31808SJens Wiklander #endif /* !MBEDTLS_ECP_C && !MBEDTLS_RSA_C */
957*32b31808SJens Wiklander     return MBEDTLS_ERR_PK_TYPE_MISMATCH;
95811fa71b9SJerome Forissier }
95911fa71b9SJerome Forissier #endif /* MBEDTLS_USE_PSA_CRYPTO */
960817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
961