xref: /optee_os/lib/libmbedtls/mbedtls/library/pk.c (revision 3d3b05918ec9052ba13de82fbcaba204766eb636)
1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0
2817466cbSJens Wiklander /*
3817466cbSJens Wiklander  *  Public Key abstraction layer
4817466cbSJens Wiklander  *
5817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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  *  This file is part of mbed TLS (https://tls.mbed.org)
20817466cbSJens Wiklander  */
21817466cbSJens Wiklander 
22817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
23817466cbSJens Wiklander #include "mbedtls/config.h"
24817466cbSJens Wiklander #else
25817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
26817466cbSJens Wiklander #endif
27817466cbSJens Wiklander 
28817466cbSJens Wiklander #if defined(MBEDTLS_PK_C)
29817466cbSJens Wiklander #include "mbedtls/pk.h"
30817466cbSJens Wiklander #include "mbedtls/pk_internal.h"
31817466cbSJens Wiklander 
32*3d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
35817466cbSJens Wiklander #include "mbedtls/rsa.h"
36817466cbSJens Wiklander #endif
37817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
38817466cbSJens Wiklander #include "mbedtls/ecp.h"
39817466cbSJens Wiklander #endif
40817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
41817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
42817466cbSJens Wiklander #endif
43817466cbSJens Wiklander 
44817466cbSJens Wiklander #include <limits.h>
45*3d3b0591SJens Wiklander #include <stdint.h>
46817466cbSJens Wiklander 
47*3d3b0591SJens Wiklander /* Parameter validation macros based on platform_util.h */
48*3d3b0591SJens Wiklander #define PK_VALIDATE_RET( cond )    \
49*3d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
50*3d3b0591SJens Wiklander #define PK_VALIDATE( cond )        \
51*3d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
52817466cbSJens Wiklander 
53817466cbSJens Wiklander /*
54817466cbSJens Wiklander  * Initialise a mbedtls_pk_context
55817466cbSJens Wiklander  */
56817466cbSJens Wiklander void mbedtls_pk_init( mbedtls_pk_context *ctx )
57817466cbSJens Wiklander {
58*3d3b0591SJens Wiklander     PK_VALIDATE( ctx != NULL );
59817466cbSJens Wiklander 
60817466cbSJens Wiklander     ctx->pk_info = NULL;
61817466cbSJens Wiklander     ctx->pk_ctx = NULL;
62817466cbSJens Wiklander }
63817466cbSJens Wiklander 
64817466cbSJens Wiklander /*
65817466cbSJens Wiklander  * Free (the components of) a mbedtls_pk_context
66817466cbSJens Wiklander  */
67817466cbSJens Wiklander void mbedtls_pk_free( mbedtls_pk_context *ctx )
68817466cbSJens Wiklander {
69*3d3b0591SJens Wiklander     if( ctx == NULL )
70817466cbSJens Wiklander         return;
71817466cbSJens Wiklander 
72*3d3b0591SJens Wiklander     if ( ctx->pk_info != NULL )
73817466cbSJens Wiklander         ctx->pk_info->ctx_free_func( ctx->pk_ctx );
74817466cbSJens Wiklander 
75*3d3b0591SJens Wiklander     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
76817466cbSJens Wiklander }
77817466cbSJens Wiklander 
78*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
79*3d3b0591SJens Wiklander /*
80*3d3b0591SJens Wiklander  * Initialize a restart context
81*3d3b0591SJens Wiklander  */
82*3d3b0591SJens Wiklander void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
83*3d3b0591SJens Wiklander {
84*3d3b0591SJens Wiklander     PK_VALIDATE( ctx != NULL );
85*3d3b0591SJens Wiklander     ctx->pk_info = NULL;
86*3d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
87*3d3b0591SJens Wiklander }
88*3d3b0591SJens Wiklander 
89*3d3b0591SJens Wiklander /*
90*3d3b0591SJens Wiklander  * Free the components of a restart context
91*3d3b0591SJens Wiklander  */
92*3d3b0591SJens Wiklander void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
93*3d3b0591SJens Wiklander {
94*3d3b0591SJens Wiklander     if( ctx == NULL || ctx->pk_info == NULL ||
95*3d3b0591SJens Wiklander         ctx->pk_info->rs_free_func == NULL )
96*3d3b0591SJens Wiklander     {
97*3d3b0591SJens Wiklander         return;
98*3d3b0591SJens Wiklander     }
99*3d3b0591SJens Wiklander 
100*3d3b0591SJens Wiklander     ctx->pk_info->rs_free_func( ctx->rs_ctx );
101*3d3b0591SJens Wiklander 
102*3d3b0591SJens Wiklander     ctx->pk_info = NULL;
103*3d3b0591SJens Wiklander     ctx->rs_ctx = NULL;
104*3d3b0591SJens Wiklander }
105*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
106*3d3b0591SJens Wiklander 
107817466cbSJens Wiklander /*
108817466cbSJens Wiklander  * Get pk_info structure from type
109817466cbSJens Wiklander  */
110817466cbSJens Wiklander const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
111817466cbSJens Wiklander {
112817466cbSJens Wiklander     switch( pk_type ) {
113817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C)
114817466cbSJens Wiklander         case MBEDTLS_PK_RSA:
115817466cbSJens Wiklander             return( &mbedtls_rsa_info );
116817466cbSJens Wiklander #endif
117817466cbSJens Wiklander #if defined(MBEDTLS_ECP_C)
118817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY:
119817466cbSJens Wiklander             return( &mbedtls_eckey_info );
120817466cbSJens Wiklander         case MBEDTLS_PK_ECKEY_DH:
121817466cbSJens Wiklander             return( &mbedtls_eckeydh_info );
122817466cbSJens Wiklander #endif
123817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
124817466cbSJens Wiklander         case MBEDTLS_PK_ECDSA:
125817466cbSJens Wiklander             return( &mbedtls_ecdsa_info );
126817466cbSJens Wiklander #endif
127817466cbSJens Wiklander         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
128817466cbSJens Wiklander         default:
129817466cbSJens Wiklander             return( NULL );
130817466cbSJens Wiklander     }
131817466cbSJens Wiklander }
132817466cbSJens Wiklander 
133817466cbSJens Wiklander /*
134817466cbSJens Wiklander  * Initialise context
135817466cbSJens Wiklander  */
136817466cbSJens Wiklander int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
137817466cbSJens Wiklander {
138*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
139*3d3b0591SJens Wiklander     if( info == NULL || ctx->pk_info != NULL )
140817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
141817466cbSJens Wiklander 
142817466cbSJens Wiklander     if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
143817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
144817466cbSJens Wiklander 
145817466cbSJens Wiklander     ctx->pk_info = info;
146817466cbSJens Wiklander 
147817466cbSJens Wiklander     return( 0 );
148817466cbSJens Wiklander }
149817466cbSJens Wiklander 
150817466cbSJens Wiklander #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
151817466cbSJens Wiklander /*
152817466cbSJens Wiklander  * Initialize an RSA-alt context
153817466cbSJens Wiklander  */
154817466cbSJens Wiklander int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
155817466cbSJens Wiklander                          mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
156817466cbSJens Wiklander                          mbedtls_pk_rsa_alt_sign_func sign_func,
157817466cbSJens Wiklander                          mbedtls_pk_rsa_alt_key_len_func key_len_func )
158817466cbSJens Wiklander {
159817466cbSJens Wiklander     mbedtls_rsa_alt_context *rsa_alt;
160817466cbSJens Wiklander     const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
161817466cbSJens Wiklander 
162*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
163*3d3b0591SJens Wiklander     if( ctx->pk_info != NULL )
164817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
165817466cbSJens Wiklander 
166817466cbSJens Wiklander     if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
167817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
168817466cbSJens Wiklander 
169817466cbSJens Wiklander     ctx->pk_info = info;
170817466cbSJens Wiklander 
171817466cbSJens Wiklander     rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx;
172817466cbSJens Wiklander 
173817466cbSJens Wiklander     rsa_alt->key = key;
174817466cbSJens Wiklander     rsa_alt->decrypt_func = decrypt_func;
175817466cbSJens Wiklander     rsa_alt->sign_func = sign_func;
176817466cbSJens Wiklander     rsa_alt->key_len_func = key_len_func;
177817466cbSJens Wiklander 
178817466cbSJens Wiklander     return( 0 );
179817466cbSJens Wiklander }
180817466cbSJens Wiklander #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
181817466cbSJens Wiklander 
182817466cbSJens Wiklander /*
183817466cbSJens Wiklander  * Tell if a PK can do the operations of the given type
184817466cbSJens Wiklander  */
185817466cbSJens Wiklander int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
186817466cbSJens Wiklander {
187*3d3b0591SJens Wiklander     /* A context with null pk_info is not set up yet and can't do anything.
188*3d3b0591SJens Wiklander      * For backward compatibility, also accept NULL instead of a context
189*3d3b0591SJens Wiklander      * pointer. */
190817466cbSJens Wiklander     if( ctx == NULL || ctx->pk_info == NULL )
191817466cbSJens Wiklander         return( 0 );
192817466cbSJens Wiklander 
193817466cbSJens Wiklander     return( ctx->pk_info->can_do( type ) );
194817466cbSJens Wiklander }
195817466cbSJens Wiklander 
196817466cbSJens Wiklander /*
197817466cbSJens Wiklander  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
198817466cbSJens Wiklander  */
199817466cbSJens Wiklander static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
200817466cbSJens Wiklander {
201817466cbSJens Wiklander     const mbedtls_md_info_t *md_info;
202817466cbSJens Wiklander 
203817466cbSJens Wiklander     if( *hash_len != 0 )
204817466cbSJens Wiklander         return( 0 );
205817466cbSJens Wiklander 
206817466cbSJens Wiklander     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
207817466cbSJens Wiklander         return( -1 );
208817466cbSJens Wiklander 
209817466cbSJens Wiklander     *hash_len = mbedtls_md_get_size( md_info );
210817466cbSJens Wiklander     return( 0 );
211817466cbSJens Wiklander }
212817466cbSJens Wiklander 
213*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
214*3d3b0591SJens Wiklander /*
215*3d3b0591SJens Wiklander  * Helper to set up a restart context if needed
216*3d3b0591SJens Wiklander  */
217*3d3b0591SJens Wiklander static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
218*3d3b0591SJens Wiklander                              const mbedtls_pk_info_t *info )
219*3d3b0591SJens Wiklander {
220*3d3b0591SJens Wiklander     /* Don't do anything if already set up or invalid */
221*3d3b0591SJens Wiklander     if( ctx == NULL || ctx->pk_info != NULL )
222*3d3b0591SJens Wiklander         return( 0 );
223*3d3b0591SJens Wiklander 
224*3d3b0591SJens Wiklander     /* Should never happen when we're called */
225*3d3b0591SJens Wiklander     if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
226*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
227*3d3b0591SJens Wiklander 
228*3d3b0591SJens Wiklander     if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
229*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_ALLOC_FAILED );
230*3d3b0591SJens Wiklander 
231*3d3b0591SJens Wiklander     ctx->pk_info = info;
232*3d3b0591SJens Wiklander 
233*3d3b0591SJens Wiklander     return( 0 );
234*3d3b0591SJens Wiklander }
235*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
236*3d3b0591SJens Wiklander 
237*3d3b0591SJens Wiklander /*
238*3d3b0591SJens Wiklander  * Verify a signature (restartable)
239*3d3b0591SJens Wiklander  */
240*3d3b0591SJens Wiklander int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
241*3d3b0591SJens Wiklander                mbedtls_md_type_t md_alg,
242*3d3b0591SJens Wiklander                const unsigned char *hash, size_t hash_len,
243*3d3b0591SJens Wiklander                const unsigned char *sig, size_t sig_len,
244*3d3b0591SJens Wiklander                mbedtls_pk_restart_ctx *rs_ctx )
245*3d3b0591SJens Wiklander {
246*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
247*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
248*3d3b0591SJens Wiklander                      hash != NULL );
249*3d3b0591SJens Wiklander     PK_VALIDATE_RET( sig != NULL );
250*3d3b0591SJens Wiklander 
251*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL ||
252*3d3b0591SJens Wiklander         pk_hashlen_helper( md_alg, &hash_len ) != 0 )
253*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
254*3d3b0591SJens Wiklander 
255*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
256*3d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
257*3d3b0591SJens Wiklander     if( rs_ctx != NULL &&
258*3d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
259*3d3b0591SJens Wiklander         ctx->pk_info->verify_rs_func != NULL )
260*3d3b0591SJens Wiklander     {
261*3d3b0591SJens Wiklander         int ret;
262*3d3b0591SJens Wiklander 
263*3d3b0591SJens Wiklander         if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
264*3d3b0591SJens Wiklander             return( ret );
265*3d3b0591SJens Wiklander 
266*3d3b0591SJens Wiklander         ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
267*3d3b0591SJens Wiklander                    md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
268*3d3b0591SJens Wiklander 
269*3d3b0591SJens Wiklander         if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
270*3d3b0591SJens Wiklander             mbedtls_pk_restart_free( rs_ctx );
271*3d3b0591SJens Wiklander 
272*3d3b0591SJens Wiklander         return( ret );
273*3d3b0591SJens Wiklander     }
274*3d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
275*3d3b0591SJens Wiklander     (void) rs_ctx;
276*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
277*3d3b0591SJens Wiklander 
278*3d3b0591SJens Wiklander     if( ctx->pk_info->verify_func == NULL )
279*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
280*3d3b0591SJens Wiklander 
281*3d3b0591SJens Wiklander     return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
282*3d3b0591SJens Wiklander                                        sig, sig_len ) );
283*3d3b0591SJens Wiklander }
284*3d3b0591SJens Wiklander 
285817466cbSJens Wiklander /*
286817466cbSJens Wiklander  * Verify a signature
287817466cbSJens Wiklander  */
288817466cbSJens Wiklander int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
289817466cbSJens Wiklander                const unsigned char *hash, size_t hash_len,
290817466cbSJens Wiklander                const unsigned char *sig, size_t sig_len )
291817466cbSJens Wiklander {
292*3d3b0591SJens Wiklander     return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
293*3d3b0591SJens Wiklander                                            sig, sig_len, NULL ) );
294817466cbSJens Wiklander }
295817466cbSJens Wiklander 
296817466cbSJens Wiklander /*
297817466cbSJens Wiklander  * Verify a signature with options
298817466cbSJens Wiklander  */
299817466cbSJens Wiklander int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
300817466cbSJens Wiklander                    mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
301817466cbSJens Wiklander                    const unsigned char *hash, size_t hash_len,
302817466cbSJens Wiklander                    const unsigned char *sig, size_t sig_len )
303817466cbSJens Wiklander {
304*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
305*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
306*3d3b0591SJens Wiklander                      hash != NULL );
307*3d3b0591SJens Wiklander     PK_VALIDATE_RET( sig != NULL );
308*3d3b0591SJens Wiklander 
309*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL )
310817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
311817466cbSJens Wiklander 
312817466cbSJens Wiklander     if( ! mbedtls_pk_can_do( ctx, type ) )
313817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
314817466cbSJens Wiklander 
315817466cbSJens Wiklander     if( type == MBEDTLS_PK_RSASSA_PSS )
316817466cbSJens Wiklander     {
317817466cbSJens Wiklander #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
318817466cbSJens Wiklander         int ret;
319817466cbSJens Wiklander         const mbedtls_pk_rsassa_pss_options *pss_opts;
320817466cbSJens Wiklander 
321*3d3b0591SJens Wiklander #if SIZE_MAX > UINT_MAX
322817466cbSJens Wiklander         if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
323817466cbSJens Wiklander             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
324*3d3b0591SJens Wiklander #endif /* SIZE_MAX > UINT_MAX */
325817466cbSJens Wiklander 
326817466cbSJens Wiklander         if( options == NULL )
327817466cbSJens Wiklander             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
328817466cbSJens Wiklander 
329817466cbSJens Wiklander         pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
330817466cbSJens Wiklander 
331817466cbSJens Wiklander         if( sig_len < mbedtls_pk_get_len( ctx ) )
332817466cbSJens Wiklander             return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
333817466cbSJens Wiklander 
334817466cbSJens Wiklander         ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ),
335817466cbSJens Wiklander                 NULL, NULL, MBEDTLS_RSA_PUBLIC,
336817466cbSJens Wiklander                 md_alg, (unsigned int) hash_len, hash,
337817466cbSJens Wiklander                 pss_opts->mgf1_hash_id,
338817466cbSJens Wiklander                 pss_opts->expected_salt_len,
339817466cbSJens Wiklander                 sig );
340817466cbSJens Wiklander         if( ret != 0 )
341817466cbSJens Wiklander             return( ret );
342817466cbSJens Wiklander 
343817466cbSJens Wiklander         if( sig_len > mbedtls_pk_get_len( ctx ) )
344817466cbSJens Wiklander             return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
345817466cbSJens Wiklander 
346817466cbSJens Wiklander         return( 0 );
347817466cbSJens Wiklander #else
348817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
349817466cbSJens Wiklander #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
350817466cbSJens Wiklander     }
351817466cbSJens Wiklander 
352817466cbSJens Wiklander     /* General case: no options */
353817466cbSJens Wiklander     if( options != NULL )
354817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
355817466cbSJens Wiklander 
356817466cbSJens Wiklander     return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
357817466cbSJens Wiklander }
358817466cbSJens Wiklander 
359817466cbSJens Wiklander /*
360*3d3b0591SJens Wiklander  * Make a signature (restartable)
361*3d3b0591SJens Wiklander  */
362*3d3b0591SJens Wiklander int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
363*3d3b0591SJens Wiklander              mbedtls_md_type_t md_alg,
364*3d3b0591SJens Wiklander              const unsigned char *hash, size_t hash_len,
365*3d3b0591SJens Wiklander              unsigned char *sig, size_t *sig_len,
366*3d3b0591SJens Wiklander              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
367*3d3b0591SJens Wiklander              mbedtls_pk_restart_ctx *rs_ctx )
368*3d3b0591SJens Wiklander {
369*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
370*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
371*3d3b0591SJens Wiklander                      hash != NULL );
372*3d3b0591SJens Wiklander     PK_VALIDATE_RET( sig != NULL );
373*3d3b0591SJens Wiklander 
374*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL ||
375*3d3b0591SJens Wiklander         pk_hashlen_helper( md_alg, &hash_len ) != 0 )
376*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
377*3d3b0591SJens Wiklander 
378*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
379*3d3b0591SJens Wiklander     /* optimization: use non-restartable version if restart disabled */
380*3d3b0591SJens Wiklander     if( rs_ctx != NULL &&
381*3d3b0591SJens Wiklander         mbedtls_ecp_restart_is_enabled() &&
382*3d3b0591SJens Wiklander         ctx->pk_info->sign_rs_func != NULL )
383*3d3b0591SJens Wiklander     {
384*3d3b0591SJens Wiklander         int ret;
385*3d3b0591SJens Wiklander 
386*3d3b0591SJens Wiklander         if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
387*3d3b0591SJens Wiklander             return( ret );
388*3d3b0591SJens Wiklander 
389*3d3b0591SJens Wiklander         ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
390*3d3b0591SJens Wiklander                 hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
391*3d3b0591SJens Wiklander 
392*3d3b0591SJens Wiklander         if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
393*3d3b0591SJens Wiklander             mbedtls_pk_restart_free( rs_ctx );
394*3d3b0591SJens Wiklander 
395*3d3b0591SJens Wiklander         return( ret );
396*3d3b0591SJens Wiklander     }
397*3d3b0591SJens Wiklander #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
398*3d3b0591SJens Wiklander     (void) rs_ctx;
399*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
400*3d3b0591SJens Wiklander 
401*3d3b0591SJens Wiklander     if( ctx->pk_info->sign_func == NULL )
402*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
403*3d3b0591SJens Wiklander 
404*3d3b0591SJens Wiklander     return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
405*3d3b0591SJens Wiklander                                      sig, sig_len, f_rng, p_rng ) );
406*3d3b0591SJens Wiklander }
407*3d3b0591SJens Wiklander 
408*3d3b0591SJens Wiklander /*
409817466cbSJens Wiklander  * Make a signature
410817466cbSJens Wiklander  */
411817466cbSJens Wiklander int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
412817466cbSJens Wiklander              const unsigned char *hash, size_t hash_len,
413817466cbSJens Wiklander              unsigned char *sig, size_t *sig_len,
414817466cbSJens Wiklander              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
415817466cbSJens Wiklander {
416*3d3b0591SJens Wiklander     return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
417*3d3b0591SJens Wiklander                                          sig, sig_len, f_rng, p_rng, NULL ) );
418817466cbSJens Wiklander }
419817466cbSJens Wiklander 
420817466cbSJens Wiklander /*
421817466cbSJens Wiklander  * Decrypt message
422817466cbSJens Wiklander  */
423817466cbSJens Wiklander int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
424817466cbSJens Wiklander                 const unsigned char *input, size_t ilen,
425817466cbSJens Wiklander                 unsigned char *output, size_t *olen, size_t osize,
426817466cbSJens Wiklander                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
427817466cbSJens Wiklander {
428*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
429*3d3b0591SJens Wiklander     PK_VALIDATE_RET( input != NULL || ilen == 0 );
430*3d3b0591SJens Wiklander     PK_VALIDATE_RET( output != NULL || osize == 0 );
431*3d3b0591SJens Wiklander     PK_VALIDATE_RET( olen != NULL );
432*3d3b0591SJens Wiklander 
433*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL )
434817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
435817466cbSJens Wiklander 
436817466cbSJens Wiklander     if( ctx->pk_info->decrypt_func == NULL )
437817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
438817466cbSJens Wiklander 
439817466cbSJens Wiklander     return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
440817466cbSJens Wiklander                 output, olen, osize, f_rng, p_rng ) );
441817466cbSJens Wiklander }
442817466cbSJens Wiklander 
443817466cbSJens Wiklander /*
444817466cbSJens Wiklander  * Encrypt message
445817466cbSJens Wiklander  */
446817466cbSJens Wiklander int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
447817466cbSJens Wiklander                 const unsigned char *input, size_t ilen,
448817466cbSJens Wiklander                 unsigned char *output, size_t *olen, size_t osize,
449817466cbSJens Wiklander                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
450817466cbSJens Wiklander {
451*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
452*3d3b0591SJens Wiklander     PK_VALIDATE_RET( input != NULL || ilen == 0 );
453*3d3b0591SJens Wiklander     PK_VALIDATE_RET( output != NULL || osize == 0 );
454*3d3b0591SJens Wiklander     PK_VALIDATE_RET( olen != NULL );
455*3d3b0591SJens Wiklander 
456*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL )
457817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
458817466cbSJens Wiklander 
459817466cbSJens Wiklander     if( ctx->pk_info->encrypt_func == NULL )
460817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
461817466cbSJens Wiklander 
462817466cbSJens Wiklander     return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
463817466cbSJens Wiklander                 output, olen, osize, f_rng, p_rng ) );
464817466cbSJens Wiklander }
465817466cbSJens Wiklander 
466817466cbSJens Wiklander /*
467817466cbSJens Wiklander  * Check public-private key pair
468817466cbSJens Wiklander  */
469817466cbSJens Wiklander int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
470817466cbSJens Wiklander {
471*3d3b0591SJens Wiklander     PK_VALIDATE_RET( pub != NULL );
472*3d3b0591SJens Wiklander     PK_VALIDATE_RET( prv != NULL );
473*3d3b0591SJens Wiklander 
474*3d3b0591SJens Wiklander     if( pub->pk_info == NULL ||
475*3d3b0591SJens Wiklander         prv->pk_info == NULL ||
476817466cbSJens Wiklander         prv->pk_info->check_pair_func == NULL )
477817466cbSJens Wiklander     {
478817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
479817466cbSJens Wiklander     }
480817466cbSJens Wiklander 
481817466cbSJens Wiklander     if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
482817466cbSJens Wiklander     {
483817466cbSJens Wiklander         if( pub->pk_info->type != MBEDTLS_PK_RSA )
484817466cbSJens Wiklander             return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
485817466cbSJens Wiklander     }
486817466cbSJens Wiklander     else
487817466cbSJens Wiklander     {
488817466cbSJens Wiklander         if( pub->pk_info != prv->pk_info )
489817466cbSJens Wiklander             return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
490817466cbSJens Wiklander     }
491817466cbSJens Wiklander 
492817466cbSJens Wiklander     return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
493817466cbSJens Wiklander }
494817466cbSJens Wiklander 
495817466cbSJens Wiklander /*
496817466cbSJens Wiklander  * Get key size in bits
497817466cbSJens Wiklander  */
498817466cbSJens Wiklander size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
499817466cbSJens Wiklander {
500*3d3b0591SJens Wiklander     /* For backward compatibility, accept NULL or a context that
501*3d3b0591SJens Wiklander      * isn't set up yet, and return a fake value that should be safe. */
502817466cbSJens Wiklander     if( ctx == NULL || ctx->pk_info == NULL )
503817466cbSJens Wiklander         return( 0 );
504817466cbSJens Wiklander 
505817466cbSJens Wiklander     return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
506817466cbSJens Wiklander }
507817466cbSJens Wiklander 
508817466cbSJens Wiklander /*
509817466cbSJens Wiklander  * Export debug information
510817466cbSJens Wiklander  */
511817466cbSJens Wiklander int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
512817466cbSJens Wiklander {
513*3d3b0591SJens Wiklander     PK_VALIDATE_RET( ctx != NULL );
514*3d3b0591SJens Wiklander     if( ctx->pk_info == NULL )
515817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
516817466cbSJens Wiklander 
517817466cbSJens Wiklander     if( ctx->pk_info->debug_func == NULL )
518817466cbSJens Wiklander         return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
519817466cbSJens Wiklander 
520817466cbSJens Wiklander     ctx->pk_info->debug_func( ctx->pk_ctx, items );
521817466cbSJens Wiklander     return( 0 );
522817466cbSJens Wiklander }
523817466cbSJens Wiklander 
524817466cbSJens Wiklander /*
525817466cbSJens Wiklander  * Access the PK type name
526817466cbSJens Wiklander  */
527817466cbSJens Wiklander const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx )
528817466cbSJens Wiklander {
529817466cbSJens Wiklander     if( ctx == NULL || ctx->pk_info == NULL )
530817466cbSJens Wiklander         return( "invalid PK" );
531817466cbSJens Wiklander 
532817466cbSJens Wiklander     return( ctx->pk_info->name );
533817466cbSJens Wiklander }
534817466cbSJens Wiklander 
535817466cbSJens Wiklander /*
536817466cbSJens Wiklander  * Access the PK type
537817466cbSJens Wiklander  */
538817466cbSJens Wiklander mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
539817466cbSJens Wiklander {
540817466cbSJens Wiklander     if( ctx == NULL || ctx->pk_info == NULL )
541817466cbSJens Wiklander         return( MBEDTLS_PK_NONE );
542817466cbSJens Wiklander 
543817466cbSJens Wiklander     return( ctx->pk_info->type );
544817466cbSJens Wiklander }
545817466cbSJens Wiklander 
546817466cbSJens Wiklander #endif /* MBEDTLS_PK_C */
547