blob: 6a3c86044f4f1299e338f017ed9deeea6cd94da8 [file] [log] [blame]
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +02001/*
2 * Public Key abstraction layer
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020018 */
19
Gilles Peskinedb09ef62020-06-03 01:43:33 +020020#include "common.h"
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if defined(MBEDTLS_PK_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000023#include "mbedtls/pk.h"
Chris Jonesdaacb592021-03-09 17:03:29 +000024#include "pk_wrap.h"
Neil Armstrongca5b55f2022-03-15 15:00:55 +010025#include "pkwrite.h"
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020026
Manuel Pégourié-Gonnard47728842022-07-18 13:00:40 +020027#include "hash_info.h"
Manuel Pégourié-Gonnarda370e062022-07-05 11:55:20 +020028
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050029#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000030#include "mbedtls/error.h"
Andres AG72849872017-01-19 11:24:33 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/rsa.h"
Manuel Pégourié-Gonnard81c313c2013-07-09 10:35:54 +020034#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_ECP_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000036#include "mbedtls/ecp.h"
Manuel Pégourié-Gonnard81c313c2013-07-09 10:35:54 +020037#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_ECDSA_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/ecdsa.h"
Manuel Pégourié-Gonnard7c5819e2013-07-10 12:29:57 +020040#endif
Manuel Pégourié-Gonnard81c313c2013-07-09 10:35:54 +020041
Jerry Yub02ee182022-03-16 10:30:41 +080042#if defined(MBEDTLS_PSA_CRYPTO_C)
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +010043#include "mbedtls/psa_util.h"
44#endif
45
Andres AG72849872017-01-19 11:24:33 +000046#include <limits.h>
Andres Amaya Garcia7c02c502017-08-04 13:32:15 +010047#include <stdint.h>
Paul Bakker34617722014-06-13 17:20:13 +020048
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050049/* Parameter validation macros based on platform_util.h */
50#define PK_VALIDATE_RET( cond ) \
51 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
52#define PK_VALIDATE( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE( cond )
54
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020055/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056 * Initialise a mbedtls_pk_context
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058void mbedtls_pk_init( mbedtls_pk_context *ctx )
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020059{
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020060
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +020061 ctx->pk_info = NULL;
62 ctx->pk_ctx = NULL;
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020063}
64
65/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066 * Free (the components of) a mbedtls_pk_context
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020067 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068void mbedtls_pk_free( mbedtls_pk_context *ctx )
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020069{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050070 if( ctx == NULL )
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +020071 return;
72
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050073 if ( ctx->pk_info != NULL )
74 ctx->pk_info->ctx_free_func( ctx->pk_ctx );
Manuel Pégourié-Gonnard1f73a652013-07-09 10:26:41 +020075
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050076 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +020077}
78
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +020079#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +020080/*
81 * Initialize a restart context
82 */
83void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
84{
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +020085 ctx->pk_info = NULL;
86 ctx->rs_ctx = NULL;
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +020087}
88
89/*
90 * Free the components of a restart context
91 */
92void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
93{
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +020094 if( ctx == NULL || ctx->pk_info == NULL ||
95 ctx->pk_info->rs_free_func == NULL )
96 {
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +020097 return;
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +020098 }
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +020099
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200100 ctx->pk_info->rs_free_func( ctx->rs_ctx );
101
102 ctx->pk_info = NULL;
103 ctx->rs_ctx = NULL;
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +0200104}
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200105#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +0200106
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200107/*
108 * Get pk_info structure from type
109 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200111{
112 switch( pk_type ) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113#if defined(MBEDTLS_RSA_C)
114 case MBEDTLS_PK_RSA:
115 return( &mbedtls_rsa_info );
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200116#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117#if defined(MBEDTLS_ECP_C)
118 case MBEDTLS_PK_ECKEY:
119 return( &mbedtls_eckey_info );
120 case MBEDTLS_PK_ECKEY_DH:
121 return( &mbedtls_eckeydh_info );
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200122#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123#if defined(MBEDTLS_ECDSA_C)
124 case MBEDTLS_PK_ECDSA:
125 return( &mbedtls_ecdsa_info );
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200126#endif
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 /* MBEDTLS_PK_RSA_ALT omitted on purpose */
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200128 default:
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200129 return( NULL );
Manuel Pégourié-Gonnard765db072013-08-14 15:00:27 +0200130 }
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200131}
132
133/*
Manuel Pégourié-Gonnardab466942013-08-15 11:30:27 +0200134 * Initialise context
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200135 */
Manuel Pégourié-Gonnardd9e6a3a2015-05-14 19:41:36 +0200136int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200137{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500138 if( info == NULL || ctx->pk_info != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200140
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200141 if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200142 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200143
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200144 ctx->pk_info = info;
Manuel Pégourié-Gonnard12e0ed92013-07-04 13:31:32 +0200145
146 return( 0 );
147}
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200148
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200149#if defined(MBEDTLS_USE_PSA_CRYPTO)
150/*
151 * Initialise a PSA-wrapping context
152 */
Ronald Croncf56a0a2020-08-04 09:51:30 +0200153int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
Andrzej Kurek03e01462022-01-03 12:53:24 +0100154 const mbedtls_svc_key_id_t key )
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200155{
Neil Armstrongeabbf9d2022-03-15 12:01:26 +0100156 const mbedtls_pk_info_t *info = NULL;
Gilles Peskined2d45c12019-05-27 14:53:13 +0200157 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kurek03e01462022-01-03 12:53:24 +0100158 mbedtls_svc_key_id_t *pk_ctx;
Manuel Pégourié-Gonnard920c0632018-10-31 10:57:29 +0100159 psa_key_type_t type;
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200160
161 if( ctx == NULL || ctx->pk_info != NULL )
162 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
163
Gilles Peskined2d45c12019-05-27 14:53:13 +0200164 if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) )
Manuel Pégourié-Gonnard920c0632018-10-31 10:57:29 +0100165 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Gilles Peskined2d45c12019-05-27 14:53:13 +0200166 type = psa_get_key_type( &attributes );
167 psa_reset_key_attributes( &attributes );
Manuel Pégourié-Gonnard920c0632018-10-31 10:57:29 +0100168
Neil Armstrongeabbf9d2022-03-15 12:01:26 +0100169 if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
170 info = &mbedtls_pk_ecdsa_opaque_info;
Neil Armstrongeccf88f2022-04-08 15:11:50 +0200171 else if( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
Neil Armstrongeabbf9d2022-03-15 12:01:26 +0100172 info = &mbedtls_pk_rsa_opaque_info;
173 else
174 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
Manuel Pégourié-Gonnard920c0632018-10-31 10:57:29 +0100175
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200176 if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
177 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
178
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200179 ctx->pk_info = info;
180
Andrzej Kurek03e01462022-01-03 12:53:24 +0100181 pk_ctx = (mbedtls_svc_key_id_t *) ctx->pk_ctx;
Manuel Pégourié-Gonnard7b5fe042018-10-31 09:57:45 +0100182 *pk_ctx = key;
183
Manuel Pégourié-Gonnard20678b22018-10-22 12:11:15 +0200184 return( 0 );
185}
186#endif /* MBEDTLS_USE_PSA_CRYPTO */
187
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
Manuel Pégourié-Gonnardb4fae572014-01-20 11:22:25 +0100189/*
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200190 * Initialize an RSA-alt context
191 */
Manuel Pégourié-Gonnardd9e6a3a2015-05-14 19:41:36 +0200192int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
194 mbedtls_pk_rsa_alt_sign_func sign_func,
195 mbedtls_pk_rsa_alt_key_len_func key_len_func )
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200196{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 mbedtls_rsa_alt_context *rsa_alt;
198 const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200199
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500200 if( ctx->pk_info != NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200202
203 if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200204 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200205
206 ctx->pk_info = info;
207
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200208 rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200209
210 rsa_alt->key = key;
211 rsa_alt->decrypt_func = decrypt_func;
212 rsa_alt->sign_func = sign_func;
213 rsa_alt->key_len_func = key_len_func;
214
215 return( 0 );
216}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200217#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
Manuel Pégourié-Gonnard12c1ff02013-08-21 12:28:31 +0200218
219/*
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200220 * Tell if a PK can do the operations of the given type
221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200223{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500224 /* A context with null pk_info is not set up yet and can't do anything.
225 * For backward compatibility, also accept NULL instead of a context
226 * pointer. */
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200227 if( ctx == NULL || ctx->pk_info == NULL )
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200228 return( 0 );
229
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200230 return( ctx->pk_info->can_do( type ) );
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200231}
232
Neil Armstronga88b1582022-05-11 14:11:25 +0200233#if defined(MBEDTLS_USE_PSA_CRYPTO)
234/*
235 * Tell if a PK can do the operations of the given PSA algorithm
236 */
Neil Armstrong408f6a62022-05-17 14:23:20 +0200237int mbedtls_pk_can_do_ext( const mbedtls_pk_context *ctx, psa_algorithm_t alg,
238 psa_key_usage_t usage )
Neil Armstronga88b1582022-05-11 14:11:25 +0200239{
Neil Armstrong408f6a62022-05-17 14:23:20 +0200240 psa_key_usage_t key_usage;
241
Neil Armstronga88b1582022-05-11 14:11:25 +0200242 /* A context with null pk_info is not set up yet and can't do anything.
243 * For backward compatibility, also accept NULL instead of a context
244 * pointer. */
245 if( ctx == NULL || ctx->pk_info == NULL )
246 return( 0 );
247
248 /* Filter out non allowed algorithms */
249 if( PSA_ALG_IS_ECDSA( alg ) == 0 &&
250 PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) == 0 &&
251 PSA_ALG_IS_RSA_PSS( alg ) == 0 &&
252 alg != PSA_ALG_RSA_PKCS1V15_CRYPT &&
253 PSA_ALG_IS_ECDH( alg ) == 0 )
254 return( 0 );
255
Neil Armstrong408f6a62022-05-17 14:23:20 +0200256 /* Filter out non allowed usage flags */
Neil Armstrong81d391f2022-05-20 09:26:16 +0200257 if( usage == 0 ||
258 ( usage & ~( PSA_KEY_USAGE_SIGN_HASH |
Neil Armstrong408f6a62022-05-17 14:23:20 +0200259 PSA_KEY_USAGE_DECRYPT |
260 PSA_KEY_USAGE_DERIVE ) ) != 0 )
261 return( 0 );
262
Neil Armstronga88b1582022-05-11 14:11:25 +0200263 /* Wildcard hash is not allowed */
264 if( PSA_ALG_IS_SIGN_HASH( alg ) &&
265 PSA_ALG_SIGN_GET_HASH( alg ) == PSA_ALG_ANY_HASH )
266 return( 0 );
267
268 if( mbedtls_pk_get_type( ctx ) != MBEDTLS_PK_OPAQUE )
269 {
270 mbedtls_pk_type_t type;
271
272 if( PSA_ALG_IS_ECDSA( alg ) || PSA_ALG_IS_ECDH( alg ) )
273 type = MBEDTLS_PK_ECKEY;
Neil Armstrong084338d2022-05-19 16:22:40 +0200274 else if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ||
275 alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
Neil Armstronga88b1582022-05-11 14:11:25 +0200276 type = MBEDTLS_PK_RSA;
277 else if( PSA_ALG_IS_RSA_PSS( alg ) )
278 type = MBEDTLS_PK_RSASSA_PSS;
279 else
280 return( 0 );
281
Neil Armstrong084338d2022-05-19 16:22:40 +0200282 if( ctx->pk_info->can_do( type ) == 0 )
Neil Armstrong408f6a62022-05-17 14:23:20 +0200283 return( 0 );
284
Neil Armstrong084338d2022-05-19 16:22:40 +0200285 switch( type )
286 {
287 case MBEDTLS_PK_ECKEY:
288 key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
289 break;
290 case MBEDTLS_PK_RSA:
291 case MBEDTLS_PK_RSASSA_PSS:
292 key_usage = PSA_KEY_USAGE_SIGN_HASH |
293 PSA_KEY_USAGE_SIGN_MESSAGE |
294 PSA_KEY_USAGE_DECRYPT;
295 break;
296 default:
Neil Armstrongb80785f2022-05-20 09:25:55 +0200297 /* Should never happen */
Neil Armstrong084338d2022-05-19 16:22:40 +0200298 return( 0 );
299 }
300
301 return( ( key_usage & usage ) == usage );
Neil Armstronga88b1582022-05-11 14:11:25 +0200302 }
303
304 const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
305 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
306 psa_algorithm_t key_alg, key_alg2;
307 psa_status_t status;
308
309 status = psa_get_key_attributes( *key, &attributes );
310 if( status != PSA_SUCCESS )
311 return( 0 );
312
313 key_alg = psa_get_key_algorithm( &attributes );
314 key_alg2 = psa_get_key_enrollment_algorithm( &attributes );
Neil Armstrong408f6a62022-05-17 14:23:20 +0200315 key_usage = psa_get_key_usage_flags( &attributes );
Neil Armstronga88b1582022-05-11 14:11:25 +0200316 psa_reset_key_attributes( &attributes );
317
Neil Armstrong408f6a62022-05-17 14:23:20 +0200318 if( ( key_usage & usage ) != usage )
319 return( 0 );
320
Neil Armstronga88b1582022-05-11 14:11:25 +0200321 /*
Neil Armstrongdab56ba2022-05-17 11:56:55 +0200322 * Common case: the key alg or alg2 only allows alg.
Neil Armstronga88b1582022-05-11 14:11:25 +0200323 * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
324 * directly.
325 * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
326 * a fixed hash on key_alg/key_alg2.
327 */
328 if( alg == key_alg || alg == key_alg2 )
329 return( 1 );
330
331 /*
Neil Armstrongbbb8b752022-05-17 14:58:27 +0200332 * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash,
333 * and alg is the same hash-and-sign family with any hash,
Neil Armstronga88b1582022-05-11 14:11:25 +0200334 * then alg is compliant with this key alg
335 */
336 if( PSA_ALG_IS_SIGN_HASH( alg ) )
337 {
338
339 if( PSA_ALG_IS_SIGN_HASH( key_alg ) &&
340 PSA_ALG_SIGN_GET_HASH( key_alg ) == PSA_ALG_ANY_HASH &&
341 ( alg & ~PSA_ALG_HASH_MASK ) == ( key_alg & ~PSA_ALG_HASH_MASK ) )
342 return( 1 );
343
344 if( PSA_ALG_IS_SIGN_HASH( key_alg2 ) &&
345 PSA_ALG_SIGN_GET_HASH( key_alg2 ) == PSA_ALG_ANY_HASH &&
346 ( alg & ~PSA_ALG_HASH_MASK ) == ( key_alg2 & ~PSA_ALG_HASH_MASK ) )
347 return( 1 );
348 }
349
350 return( 0 );
351}
352#endif /* MBEDTLS_USE_PSA_CRYPTO */
353
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200354/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 * Helper for mbedtls_pk_sign and mbedtls_pk_verify
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200358{
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200359 if( *hash_len != 0 )
360 return( 0 );
361
Manuel Pégourié-Gonnard47728842022-07-18 13:00:40 +0200362 *hash_len = mbedtls_hash_info_get_size( md_alg );
Manuel Pégourié-Gonnarda370e062022-07-05 11:55:20 +0200363
364 if( *hash_len == 0 )
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200365 return( -1 );
366
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200367 return( 0 );
368}
369
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200370#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200371/*
372 * Helper to set up a restart context if needed
373 */
374static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200375 const mbedtls_pk_info_t *info )
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200376{
Manuel Pégourié-Gonnardc8c12b62018-07-02 13:09:39 +0200377 /* Don't do anything if already set up or invalid */
378 if( ctx == NULL || ctx->pk_info != NULL )
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200379 return( 0 );
380
381 /* Should never happen when we're called */
382 if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
383 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
384
385 if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
386 return( MBEDTLS_ERR_PK_ALLOC_FAILED );
387
388 ctx->pk_info = info;
389
390 return( 0 );
391}
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200392#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200393
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200394/*
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200395 * Verify a signature (restartable)
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200396 */
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200397int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
398 mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnardf73da022013-08-17 14:36:32 +0200399 const unsigned char *hash, size_t hash_len,
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200400 const unsigned char *sig, size_t sig_len,
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +0200401 mbedtls_pk_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200402{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500403 PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
404 hash != NULL );
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500405
406 if( ctx->pk_info == NULL ||
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200407 pk_hashlen_helper( md_alg, &hash_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200409
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200410#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnardd55f7762017-08-18 17:40:15 +0200411 /* optimization: use non-restartable version if restart disabled */
412 if( rs_ctx != NULL &&
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200413 mbedtls_ecp_restart_is_enabled() &&
Manuel Pégourié-Gonnardd55f7762017-08-18 17:40:15 +0200414 ctx->pk_info->verify_rs_func != NULL )
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200415 {
Janos Follath24eed8d2019-11-22 13:21:35 +0000416 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200417
418 if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
419 return( ret );
420
421 ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
422 md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
423
424 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
425 mbedtls_pk_restart_free( rs_ctx );
426
427 return( ret );
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200428 }
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200429#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200430 (void) rs_ctx;
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200431#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200432
Manuel Pégourié-Gonnardfff80f82013-08-17 15:20:06 +0200433 if( ctx->pk_info->verify_func == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnardfff80f82013-08-17 15:20:06 +0200435
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200436 return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
Manuel Pégourié-Gonnardf73da022013-08-17 14:36:32 +0200437 sig, sig_len ) );
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200438}
439
440/*
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200441 * Verify a signature
442 */
443int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
444 const unsigned char *hash, size_t hash_len,
445 const unsigned char *sig, size_t sig_len )
446{
447 return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
448 sig, sig_len, NULL ) );
449}
450
451/*
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200452 * Verify a signature with options
453 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
455 mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200456 const unsigned char *hash, size_t hash_len,
457 const unsigned char *sig, size_t sig_len )
458{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500459 PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
460 hash != NULL );
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500461
462 if( ctx->pk_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 if( ! mbedtls_pk_can_do( ctx, type ) )
466 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200467
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500468 if( type != MBEDTLS_PK_RSASSA_PSS )
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200469 {
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500470 /* General case: no options */
471 if( options != NULL )
472 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
473
474 return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
475 }
476
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500478 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
479 const mbedtls_pk_rsassa_pss_options *pss_opts;
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200480
Andres Amaya Garcia7c02c502017-08-04 13:32:15 +0100481#if SIZE_MAX > UINT_MAX
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500482 if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
483 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Andres Amaya Garcia7c02c502017-08-04 13:32:15 +0100484#endif /* SIZE_MAX > UINT_MAX */
Andres AG72849872017-01-19 11:24:33 +0000485
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500486 if( options == NULL )
487 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200488
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500489 pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200490
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500491#if defined(MBEDTLS_USE_PSA_CRYPTO)
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500492 if( pss_opts->mgf1_hash_id == md_alg &&
493 ( (size_t) pss_opts->expected_salt_len == hash_len ||
494 pss_opts->expected_salt_len == MBEDTLS_RSA_SALT_LEN_ANY ) )
495 {
496 /* see RSA_PUB_DER_MAX_BYTES in pkwrite.c */
497 unsigned char buf[ 38 + 2 * MBEDTLS_MPI_MAX_SIZE ];
498 unsigned char *p;
Andrzej Kurek59550532022-02-16 07:46:42 -0500499 int key_len;
500 size_t signature_length;
Andrzej Kurekd70fa0e2022-02-17 10:51:15 -0500501 psa_status_t status = PSA_ERROR_DATA_CORRUPT;
502 psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;
Andrzej Kurek59550532022-02-16 07:46:42 -0500503
Manuel Pégourié-Gonnardabac0372022-07-18 13:41:11 +0200504 psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md( md_alg );
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500505 mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
506 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
Andrzej Kurek90ba2cb2022-02-15 08:18:44 -0500507 psa_algorithm_t psa_sig_alg =
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500508 ( pss_opts->expected_salt_len == MBEDTLS_RSA_SALT_LEN_ANY ?
509 PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg) :
510 PSA_ALG_RSA_PSS(psa_md_alg) );
511 p = buf + sizeof( buf );
512 key_len = mbedtls_pk_write_pubkey( &p, buf, ctx );
513
514 if( key_len < 0 )
515 return( key_len );
516
517 psa_set_key_type( &attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY );
518 psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
Andrzej Kurek90ba2cb2022-02-15 08:18:44 -0500519 psa_set_key_algorithm( &attributes, psa_sig_alg );
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500520
521 status = psa_import_key( &attributes,
522 buf + sizeof( buf ) - key_len, key_len,
523 &key_id );
524 if( status != PSA_SUCCESS )
525 {
526 psa_destroy_key( key_id );
Neil Armstrong19915c22022-03-01 15:21:02 +0100527 return( mbedtls_pk_error_from_psa( status ) );
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500528 }
529
Andrzej Kurek4a953cd2022-02-16 06:13:35 -0500530 /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH
531 * on a valid signature with trailing data in a buffer, but
532 * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact,
533 * so for this reason the passed sig_len is overwritten. Smaller
534 * signature lengths should not be accepted for verification. */
535 signature_length = sig_len > mbedtls_pk_get_len( ctx ) ?
536 mbedtls_pk_get_len( ctx ) : sig_len;
Andrzej Kurek90ba2cb2022-02-15 08:18:44 -0500537 status = psa_verify_hash( key_id, psa_sig_alg, hash,
Andrzej Kurek4a953cd2022-02-16 06:13:35 -0500538 hash_len, sig, signature_length );
Andrzej Kurekd70fa0e2022-02-17 10:51:15 -0500539 destruction_status = psa_destroy_key( key_id );
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500540
Andrzej Kurek8666df62022-02-15 08:23:02 -0500541 if( status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len( ctx ) )
542 return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
543
Andrzej Kurekd70fa0e2022-02-17 10:51:15 -0500544 if( status == PSA_SUCCESS )
545 status = destruction_status;
546
Neil Armstrong19915c22022-03-01 15:21:02 +0100547 return( mbedtls_pk_error_from_psa_rsa( status ) );
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500548 }
549 else
550#endif
551 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 if( sig_len < mbedtls_pk_get_len( ctx ) )
553 return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ),
Thomas Daubney782a7f52021-05-19 12:27:35 +0100556 md_alg, (unsigned int) hash_len, hash,
557 pss_opts->mgf1_hash_id,
558 pss_opts->expected_salt_len,
559 sig );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200560 if( ret != 0 )
561 return( ret );
562
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563 if( sig_len > mbedtls_pk_get_len( ctx ) )
564 return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
Andrzej Kurek90ba2cb2022-02-15 08:18:44 -0500565
566 return( 0 );
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200567 }
Andrzej Kurek7db1b782022-02-09 14:13:44 -0500568#else
569 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
570#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
Manuel Pégourié-Gonnard20422e92014-06-05 13:41:44 +0200571}
572
573/*
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200574 * Make a signature (restartable)
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200575 */
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200576int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
577 mbedtls_md_type_t md_alg,
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200578 const unsigned char *hash, size_t hash_len,
Gilles Peskinef00f1522021-06-22 00:09:00 +0200579 unsigned char *sig, size_t sig_size, size_t *sig_len,
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200580 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
Manuel Pégourié-Gonnard15d7df22017-08-17 14:33:31 +0200581 mbedtls_pk_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200582{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500583 PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
584 hash != NULL );
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500585
586 if( ctx->pk_info == NULL ||
Manuel Pégourié-Gonnardbfe32ef2013-08-22 14:55:30 +0200587 pk_hashlen_helper( md_alg, &hash_len ) != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200589
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200590#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnardd55f7762017-08-18 17:40:15 +0200591 /* optimization: use non-restartable version if restart disabled */
592 if( rs_ctx != NULL &&
Manuel Pégourié-Gonnardb843b152018-10-16 10:41:31 +0200593 mbedtls_ecp_restart_is_enabled() &&
Manuel Pégourié-Gonnardd55f7762017-08-18 17:40:15 +0200594 ctx->pk_info->sign_rs_func != NULL )
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200595 {
Janos Follath24eed8d2019-11-22 13:21:35 +0000596 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200597
598 if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
599 return( ret );
600
601 ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
Gilles Peskinef00f1522021-06-22 00:09:00 +0200602 hash, hash_len,
603 sig, sig_size, sig_len,
604 f_rng, p_rng, rs_ctx->rs_ctx );
Manuel Pégourié-Gonnard0bbc66c2017-08-18 16:22:06 +0200605
606 if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
607 mbedtls_pk_restart_free( rs_ctx );
608
609 return( ret );
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200610 }
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200611#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200612 (void) rs_ctx;
Manuel Pégourié-Gonnardaaa98142017-08-18 17:30:37 +0200613#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard1f596062017-05-09 10:42:40 +0200614
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200615 if( ctx->pk_info->sign_func == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200617
Gilles Peskinef00f1522021-06-22 00:09:00 +0200618 return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg,
619 hash, hash_len,
620 sig, sig_size, sig_len,
621 f_rng, p_rng ) );
Manuel Pégourié-Gonnard8df27692013-08-21 10:34:38 +0200622}
623
624/*
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200625 * Make a signature
626 */
627int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
628 const unsigned char *hash, size_t hash_len,
Gilles Peskinef00f1522021-06-22 00:09:00 +0200629 unsigned char *sig, size_t sig_size, size_t *sig_len,
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200630 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
631{
632 return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
Gilles Peskinef00f1522021-06-22 00:09:00 +0200633 sig, sig_size, sig_len,
634 f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200635}
636
Jerry Yu1d172a32022-03-12 19:12:05 +0800637#if defined(MBEDTLS_PSA_CRYPTO_C)
Manuel Pégourié-Gonnard82cb27b2017-05-03 10:59:45 +0200638/*
Jerry Yufb0621d2022-03-23 11:42:06 +0800639 * Make a signature given a signature type.
Jerry Yud69439a2022-02-24 15:52:15 +0800640 */
Jerry Yu718a9b42022-03-12 22:43:01 +0800641int mbedtls_pk_sign_ext( mbedtls_pk_type_t pk_type,
Jerry Yu8beb9e12022-03-12 16:23:53 +0800642 mbedtls_pk_context *ctx,
643 mbedtls_md_type_t md_alg,
644 const unsigned char *hash, size_t hash_len,
645 unsigned char *sig, size_t sig_size, size_t *sig_len,
646 int (*f_rng)(void *, unsigned char *, size_t),
647 void *p_rng )
Jerry Yud69439a2022-02-24 15:52:15 +0800648{
Jerry Yufb0621d2022-03-23 11:42:06 +0800649#if defined(MBEDTLS_RSA_C)
650 psa_algorithm_t psa_md_alg;
651#endif /* MBEDTLS_RSA_C */
Jerry Yud69439a2022-02-24 15:52:15 +0800652 *sig_len = 0;
Jerry Yu1d172a32022-03-12 19:12:05 +0800653
Jerry Yud69439a2022-02-24 15:52:15 +0800654 if( ctx->pk_info == NULL )
655 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
656
Jerry Yu718a9b42022-03-12 22:43:01 +0800657 if( ! mbedtls_pk_can_do( ctx, pk_type ) )
Jerry Yud69439a2022-02-24 15:52:15 +0800658 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
659
Jerry Yu718a9b42022-03-12 22:43:01 +0800660 if( pk_type != MBEDTLS_PK_RSASSA_PSS )
Jerry Yud69439a2022-02-24 15:52:15 +0800661 {
Jerry Yu1d172a32022-03-12 19:12:05 +0800662 return( mbedtls_pk_sign( ctx, md_alg, hash, hash_len,
663 sig, sig_size, sig_len, f_rng, p_rng ) );
Jerry Yud69439a2022-02-24 15:52:15 +0800664 }
Neil Armstrong13e76be2022-04-21 12:08:52 +0200665
Jerry Yu89107d12022-03-22 14:20:15 +0800666#if defined(MBEDTLS_RSA_C)
Manuel Pégourié-Gonnardabac0372022-07-18 13:41:11 +0200667 psa_md_alg = mbedtls_hash_info_psa_from_md( md_alg );
Jerry Yufb0621d2022-03-23 11:42:06 +0800668 if( psa_md_alg == 0 )
669 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Neil Armstrong13e76be2022-04-21 12:08:52 +0200670
671 if( mbedtls_pk_get_type( ctx ) == MBEDTLS_PK_OPAQUE )
672 {
673 const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
674 psa_status_t status;
675
676 status = psa_sign_hash( *key, PSA_ALG_RSA_PSS( psa_md_alg ),
677 hash, hash_len,
678 sig, sig_size, sig_len );
679 return( mbedtls_pk_error_from_psa_rsa( status ) );
680 }
681
Jerry Yufb0621d2022-03-23 11:42:06 +0800682 return( mbedtls_pk_psa_rsa_sign_ext( PSA_ALG_RSA_PSS( psa_md_alg ),
Jerry Yu89107d12022-03-22 14:20:15 +0800683 ctx->pk_ctx, hash, hash_len,
684 sig, sig_size, sig_len ) );
685#else /* MBEDTLS_RSA_C */
686 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
687#endif /* !MBEDTLS_RSA_C */
Jerry Yud69439a2022-02-24 15:52:15 +0800688
689}
Jerry Yu1d172a32022-03-12 19:12:05 +0800690#endif /* MBEDTLS_PSA_CRYPTO_C */
Jerry Yud69439a2022-02-24 15:52:15 +0800691
692/*
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200693 * Decrypt message
694 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200696 const unsigned char *input, size_t ilen,
697 unsigned char *output, size_t *olen, size_t osize,
698 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
699{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500700
701 if( ctx->pk_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200703
704 if( ctx->pk_info->decrypt_func == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200706
707 return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
708 output, olen, osize, f_rng, p_rng ) );
709}
710
711/*
712 * Encrypt message
713 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200715 const unsigned char *input, size_t ilen,
716 unsigned char *output, size_t *olen, size_t osize,
717 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
718{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500719
720 if( ctx->pk_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200722
723 if( ctx->pk_info->encrypt_func == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnarda2d3f222013-08-21 11:51:08 +0200725
726 return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
727 output, olen, osize, f_rng, p_rng ) );
728}
729
730/*
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100731 * Check public-private key pair
732 */
Manuel Pégourié-Gonnard39be1412021-06-15 11:29:26 +0200733int mbedtls_pk_check_pair( const mbedtls_pk_context *pub,
734 const mbedtls_pk_context *prv,
735 int (*f_rng)(void *, unsigned char *, size_t),
736 void *p_rng )
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100737{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500738
739 if( pub->pk_info == NULL ||
Andrzej Kurekefed3232019-02-05 05:09:05 -0500740 prv->pk_info == NULL )
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100741 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100743 }
744
Manuel Pégourié-Gonnard39be1412021-06-15 11:29:26 +0200745 if( f_rng == NULL )
746 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
747
Manuel Pégourié-Gonnardeaeb7b22018-10-24 12:37:44 +0200748 if( prv->pk_info->check_pair_func == NULL )
749 return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100752 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753 if( pub->pk_info->type != MBEDTLS_PK_RSA )
754 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnarda1efcb02014-11-08 17:08:08 +0100755 }
756 else
757 {
758 if( pub->pk_info != prv->pk_info )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100760 }
761
Manuel Pégourié-Gonnard39be1412021-06-15 11:29:26 +0200762 return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx, f_rng, p_rng ) );
Manuel Pégourié-Gonnard70bdadf2014-11-06 16:51:20 +0100763}
764
765/*
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200766 * Get key size in bits
767 */
Manuel Pégourié-Gonnard097c7bb2015-06-18 16:43:38 +0200768size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200769{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500770 /* For backward compatibility, accept NULL or a context that
771 * isn't set up yet, and return a fake value that should be safe. */
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200772 if( ctx == NULL || ctx->pk_info == NULL )
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200773 return( 0 );
774
Manuel Pégourié-Gonnard39a48f42015-06-18 16:06:55 +0200775 return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
Manuel Pégourié-Gonnardb3d91872013-08-14 15:56:19 +0200776}
Manuel Pégourié-Gonnardc6ac8872013-08-14 18:04:18 +0200777
778/*
779 * Export debug information
780 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200781int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
Manuel Pégourié-Gonnardc6ac8872013-08-14 18:04:18 +0200782{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500783 if( ctx->pk_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200784 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardc6ac8872013-08-14 18:04:18 +0200785
Manuel Pégourié-Gonnard01488752014-04-03 22:09:18 +0200786 if( ctx->pk_info->debug_func == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200787 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnard01488752014-04-03 22:09:18 +0200788
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200789 ctx->pk_info->debug_func( ctx->pk_ctx, items );
Manuel Pégourié-Gonnardc6ac8872013-08-14 18:04:18 +0200790 return( 0 );
791}
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200792
793/*
794 * Access the PK type name
795 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200796const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx )
Manuel Pégourié-Gonnard3fb5c5e2013-08-14 18:26:41 +0200797{
798 if( ctx == NULL || ctx->pk_info == NULL )
799 return( "invalid PK" );
800
801 return( ctx->pk_info->name );
802}
Manuel Pégourié-Gonnardc40b4c32013-08-22 13:29:31 +0200803
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200804/*
805 * Access the PK type
806 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200807mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200808{
809 if( ctx == NULL || ctx->pk_info == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200810 return( MBEDTLS_PK_NONE );
Manuel Pégourié-Gonnard8053da42013-09-11 22:28:30 +0200811
812 return( ctx->pk_info->type );
813}
814
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100815#if defined(MBEDTLS_USE_PSA_CRYPTO)
816/*
817 * Load the key to a PSA key slot,
818 * then turn the PK context into a wrapper for that key slot.
819 *
Neil Armstrong56e71d42022-04-08 15:12:42 +0200820 * Currently only works for EC & RSA private keys.
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100821 */
822int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
Andrzej Kurek03e01462022-01-03 12:53:24 +0100823 mbedtls_svc_key_id_t *key,
Neil Armstronga1fc18f2022-04-22 13:57:14 +0200824 psa_algorithm_t alg,
825 psa_key_usage_t usage,
826 psa_algorithm_t alg2 )
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100827{
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100828#if !defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_RSA_C)
John Durkopf35069a2020-08-17 22:05:14 -0700829 ((void) pk);
Ronald Croncf56a0a2020-08-04 09:51:30 +0200830 ((void) key);
Neil Armstronga1fc18f2022-04-22 13:57:14 +0200831 ((void) alg);
832 ((void) usage);
833 ((void) alg2);
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100834#else
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100835#if defined(MBEDTLS_ECP_C)
836 if( mbedtls_pk_get_type( pk ) == MBEDTLS_PK_ECKEY )
837 {
838 const mbedtls_ecp_keypair *ec;
839 unsigned char d[MBEDTLS_ECP_MAX_BYTES];
840 size_t d_len;
841 psa_ecc_family_t curve_id;
842 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
843 psa_key_type_t key_type;
844 size_t bits;
845 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Neil Armstrongc1152e42022-03-22 10:29:06 +0100846 psa_status_t status;
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100847
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100848 /* export the private key material in the format PSA wants */
849 ec = mbedtls_pk_ec( *pk );
Neil Armstrong7e1b4a42022-03-22 10:25:14 +0100850 d_len = PSA_BITS_TO_BYTES( ec->grp.nbits );
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100851 if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
852 return( ret );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100853
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100854 curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits );
855 key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100856
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100857 /* prepare the key attributes */
858 psa_set_key_type( &attributes, key_type );
859 psa_set_key_bits( &attributes, bits );
Neil Armstronga1fc18f2022-04-22 13:57:14 +0200860 psa_set_key_usage_flags( &attributes, usage );
861 psa_set_key_algorithm( &attributes, alg );
862 if( alg2 != PSA_ALG_NONE )
863 psa_set_key_enrollment_algorithm( &attributes, alg2 );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100864
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100865 /* import private key into PSA */
Neil Armstrongc1152e42022-03-22 10:29:06 +0100866 status = psa_import_key( &attributes, d, d_len, key );
867 if( status != PSA_SUCCESS )
868 return( mbedtls_pk_error_from_psa( status ) );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100869
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100870 /* make PK context wrap the key slot */
871 mbedtls_pk_free( pk );
872 mbedtls_pk_init( pk );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100873
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100874 return( mbedtls_pk_setup_opaque( pk, *key ) );
875 }
876 else
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100877#endif /* MBEDTLS_ECP_C */
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100878#if defined(MBEDTLS_RSA_C)
879 if( mbedtls_pk_get_type( pk ) == MBEDTLS_PK_RSA )
880 {
881 unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
882 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
883 int key_len;
884 psa_status_t status;
885
886 /* export the private key material in the format PSA wants */
887 key_len = mbedtls_pk_write_key_der( pk, buf, sizeof( buf ) );
888 if( key_len <= 0 )
889 return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
890
891 /* prepare the key attributes */
892 psa_set_key_type( &attributes, PSA_KEY_TYPE_RSA_KEY_PAIR );
893 psa_set_key_bits( &attributes, mbedtls_pk_get_bitlen( pk ) );
Neil Armstronga1fc18f2022-04-22 13:57:14 +0200894 psa_set_key_usage_flags( &attributes, usage );
895 psa_set_key_algorithm( &attributes, alg );
896 if( alg2 != PSA_ALG_NONE )
897 psa_set_key_enrollment_algorithm( &attributes, alg2 );
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100898
899 /* import private key into PSA */
900 status = psa_import_key( &attributes,
901 buf + sizeof( buf ) - key_len,
902 key_len, key);
903
904 mbedtls_platform_zeroize( buf, sizeof( buf ) );
905
906 if( status != PSA_SUCCESS )
Neil Armstrongc1152e42022-03-22 10:29:06 +0100907 return( mbedtls_pk_error_from_psa( status ) );
Neil Armstrongca5b55f2022-03-15 15:00:55 +0100908
909 /* make PK context wrap the key slot */
910 mbedtls_pk_free( pk );
911 mbedtls_pk_init( pk );
912
913 return( mbedtls_pk_setup_opaque( pk, *key ) );
914 }
915 else
916#endif /* MBEDTLS_RSA_C */
917#endif /* !MBEDTLS_ECP_C && !MBEDTLS_RSA_C */
918 return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
Manuel Pégourié-Gonnard347a00e2018-11-19 12:25:37 +0100919}
920#endif /* MBEDTLS_USE_PSA_CRYPTO */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200921#endif /* MBEDTLS_PK_C */