]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Public Key abstraction layer | |
3 | * | |
4 | * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved | |
5 | * SPDX-License-Identifier: GPL-2.0 | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 | * | |
21 | * This file is part of mbed TLS (https://tls.mbed.org) | |
22 | */ | |
23 | ||
24 | #if !defined(MBEDTLS_CONFIG_FILE) | |
25 | #include "mbedtls/config.h" | |
26 | #else | |
27 | #include MBEDTLS_CONFIG_FILE | |
28 | #endif | |
29 | ||
30 | #if defined(MBEDTLS_PK_C) | |
31 | #include "mbedtls/pk.h" | |
32 | #include "mbedtls/pk_internal.h" | |
33 | ||
34 | #include "mbedtls/platform_util.h" | |
35 | ||
36 | #if defined(MBEDTLS_RSA_C) | |
37 | #include "mbedtls/rsa.h" | |
38 | #endif | |
39 | #if defined(MBEDTLS_ECP_C) | |
40 | #include "mbedtls/ecp.h" | |
41 | #endif | |
42 | #if defined(MBEDTLS_ECDSA_C) | |
43 | #include "mbedtls/ecdsa.h" | |
44 | #endif | |
45 | ||
46 | #include <limits.h> | |
47 | #include <stdint.h> | |
48 | ||
49 | /* | |
50 | * Initialise a mbedtls_pk_context | |
51 | */ | |
52 | void mbedtls_pk_init( mbedtls_pk_context *ctx ) | |
53 | { | |
54 | if( ctx == NULL ) | |
55 | return; | |
56 | ||
57 | ctx->pk_info = NULL; | |
58 | ctx->pk_ctx = NULL; | |
59 | } | |
60 | ||
61 | /* | |
62 | * Free (the components of) a mbedtls_pk_context | |
63 | */ | |
64 | void mbedtls_pk_free( mbedtls_pk_context *ctx ) | |
65 | { | |
66 | if( ctx == NULL || ctx->pk_info == NULL ) | |
67 | return; | |
68 | ||
69 | ctx->pk_info->ctx_free_func( ctx->pk_ctx ); | |
70 | ||
71 | mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); | |
72 | } | |
73 | ||
74 | /* | |
75 | * Get pk_info structure from type | |
76 | */ | |
77 | const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) | |
78 | { | |
79 | switch( pk_type ) { | |
80 | #if defined(MBEDTLS_RSA_C) | |
81 | case MBEDTLS_PK_RSA: | |
82 | return( &mbedtls_rsa_info ); | |
83 | #endif | |
84 | #if defined(MBEDTLS_ECP_C) | |
85 | case MBEDTLS_PK_ECKEY: | |
86 | return( &mbedtls_eckey_info ); | |
87 | case MBEDTLS_PK_ECKEY_DH: | |
88 | return( &mbedtls_eckeydh_info ); | |
89 | #endif | |
90 | #if defined(MBEDTLS_ECDSA_C) | |
91 | case MBEDTLS_PK_ECDSA: | |
92 | return( &mbedtls_ecdsa_info ); | |
93 | #endif | |
94 | /* MBEDTLS_PK_RSA_ALT omitted on purpose */ | |
95 | default: | |
96 | return( NULL ); | |
97 | } | |
98 | } | |
99 | ||
100 | /* | |
101 | * Initialise context | |
102 | */ | |
103 | int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) | |
104 | { | |
105 | if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) | |
106 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
107 | ||
108 | if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) | |
109 | return( MBEDTLS_ERR_PK_ALLOC_FAILED ); | |
110 | ||
111 | ctx->pk_info = info; | |
112 | ||
113 | return( 0 ); | |
114 | } | |
115 | ||
116 | #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) | |
117 | /* | |
118 | * Initialize an RSA-alt context | |
119 | */ | |
120 | int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, | |
121 | mbedtls_pk_rsa_alt_decrypt_func decrypt_func, | |
122 | mbedtls_pk_rsa_alt_sign_func sign_func, | |
123 | mbedtls_pk_rsa_alt_key_len_func key_len_func ) | |
124 | { | |
125 | mbedtls_rsa_alt_context *rsa_alt; | |
126 | const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; | |
127 | ||
128 | if( ctx == NULL || ctx->pk_info != NULL ) | |
129 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
130 | ||
131 | if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) | |
132 | return( MBEDTLS_ERR_PK_ALLOC_FAILED ); | |
133 | ||
134 | ctx->pk_info = info; | |
135 | ||
136 | rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; | |
137 | ||
138 | rsa_alt->key = key; | |
139 | rsa_alt->decrypt_func = decrypt_func; | |
140 | rsa_alt->sign_func = sign_func; | |
141 | rsa_alt->key_len_func = key_len_func; | |
142 | ||
143 | return( 0 ); | |
144 | } | |
145 | #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ | |
146 | ||
147 | /* | |
148 | * Tell if a PK can do the operations of the given type | |
149 | */ | |
150 | int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) | |
151 | { | |
152 | /* null or NONE context can't do anything */ | |
153 | if( ctx == NULL || ctx->pk_info == NULL ) | |
154 | return( 0 ); | |
155 | ||
156 | return( ctx->pk_info->can_do( type ) ); | |
157 | } | |
158 | ||
159 | /* | |
160 | * Helper for mbedtls_pk_sign and mbedtls_pk_verify | |
161 | */ | |
162 | static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) | |
163 | { | |
164 | const mbedtls_md_info_t *md_info; | |
165 | ||
166 | if( *hash_len != 0 ) | |
167 | return( 0 ); | |
168 | ||
169 | if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) | |
170 | return( -1 ); | |
171 | ||
172 | *hash_len = mbedtls_md_get_size( md_info ); | |
173 | return( 0 ); | |
174 | } | |
175 | ||
176 | /* | |
177 | * Verify a signature | |
178 | */ | |
179 | int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, | |
180 | const unsigned char *hash, size_t hash_len, | |
181 | const unsigned char *sig, size_t sig_len ) | |
182 | { | |
183 | if( ctx == NULL || ctx->pk_info == NULL || | |
184 | pk_hashlen_helper( md_alg, &hash_len ) != 0 ) | |
185 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
186 | ||
187 | if( ctx->pk_info->verify_func == NULL ) | |
188 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
189 | ||
190 | return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, | |
191 | sig, sig_len ) ); | |
192 | } | |
193 | ||
194 | /* | |
195 | * Verify a signature with options | |
196 | */ | |
197 | int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, | |
198 | mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, | |
199 | const unsigned char *hash, size_t hash_len, | |
200 | const unsigned char *sig, size_t sig_len ) | |
201 | { | |
202 | if( ctx == NULL || ctx->pk_info == NULL ) | |
203 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
204 | ||
205 | if( ! mbedtls_pk_can_do( ctx, type ) ) | |
206 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
207 | ||
208 | if( type == MBEDTLS_PK_RSASSA_PSS ) | |
209 | { | |
210 | #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) | |
211 | int ret; | |
212 | const mbedtls_pk_rsassa_pss_options *pss_opts; | |
213 | ||
214 | #if SIZE_MAX > UINT_MAX | |
215 | if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) | |
216 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
217 | #endif /* SIZE_MAX > UINT_MAX */ | |
218 | ||
219 | if( options == NULL ) | |
220 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
221 | ||
222 | pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; | |
223 | ||
224 | if( sig_len < mbedtls_pk_get_len( ctx ) ) | |
225 | return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); | |
226 | ||
227 | ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), | |
228 | NULL, NULL, MBEDTLS_RSA_PUBLIC, | |
229 | md_alg, (unsigned int) hash_len, hash, | |
230 | pss_opts->mgf1_hash_id, | |
231 | pss_opts->expected_salt_len, | |
232 | sig ); | |
233 | if( ret != 0 ) | |
234 | return( ret ); | |
235 | ||
236 | if( sig_len > mbedtls_pk_get_len( ctx ) ) | |
237 | return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); | |
238 | ||
239 | return( 0 ); | |
240 | #else | |
241 | return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); | |
242 | #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ | |
243 | } | |
244 | ||
245 | /* General case: no options */ | |
246 | if( options != NULL ) | |
247 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
248 | ||
249 | return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); | |
250 | } | |
251 | ||
252 | /* | |
253 | * Make a signature | |
254 | */ | |
255 | int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, | |
256 | const unsigned char *hash, size_t hash_len, | |
257 | unsigned char *sig, size_t *sig_len, | |
258 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
259 | { | |
260 | if( ctx == NULL || ctx->pk_info == NULL || | |
261 | pk_hashlen_helper( md_alg, &hash_len ) != 0 ) | |
262 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
263 | ||
264 | if( ctx->pk_info->sign_func == NULL ) | |
265 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
266 | ||
267 | return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, | |
268 | sig, sig_len, f_rng, p_rng ) ); | |
269 | } | |
270 | ||
271 | /* | |
272 | * Decrypt message | |
273 | */ | |
274 | int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, | |
275 | const unsigned char *input, size_t ilen, | |
276 | unsigned char *output, size_t *olen, size_t osize, | |
277 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
278 | { | |
279 | if( ctx == NULL || ctx->pk_info == NULL ) | |
280 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
281 | ||
282 | if( ctx->pk_info->decrypt_func == NULL ) | |
283 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
284 | ||
285 | return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, | |
286 | output, olen, osize, f_rng, p_rng ) ); | |
287 | } | |
288 | ||
289 | /* | |
290 | * Encrypt message | |
291 | */ | |
292 | int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, | |
293 | const unsigned char *input, size_t ilen, | |
294 | unsigned char *output, size_t *olen, size_t osize, | |
295 | int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) | |
296 | { | |
297 | if( ctx == NULL || ctx->pk_info == NULL ) | |
298 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
299 | ||
300 | if( ctx->pk_info->encrypt_func == NULL ) | |
301 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
302 | ||
303 | return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, | |
304 | output, olen, osize, f_rng, p_rng ) ); | |
305 | } | |
306 | ||
307 | /* | |
308 | * Check public-private key pair | |
309 | */ | |
310 | int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) | |
311 | { | |
312 | if( pub == NULL || pub->pk_info == NULL || | |
313 | prv == NULL || prv->pk_info == NULL || | |
314 | prv->pk_info->check_pair_func == NULL ) | |
315 | { | |
316 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
317 | } | |
318 | ||
319 | if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) | |
320 | { | |
321 | if( pub->pk_info->type != MBEDTLS_PK_RSA ) | |
322 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
323 | } | |
324 | else | |
325 | { | |
326 | if( pub->pk_info != prv->pk_info ) | |
327 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
328 | } | |
329 | ||
330 | return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); | |
331 | } | |
332 | ||
333 | /* | |
334 | * Get key size in bits | |
335 | */ | |
336 | size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) | |
337 | { | |
338 | if( ctx == NULL || ctx->pk_info == NULL ) | |
339 | return( 0 ); | |
340 | ||
341 | return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); | |
342 | } | |
343 | ||
344 | /* | |
345 | * Export debug information | |
346 | */ | |
347 | int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) | |
348 | { | |
349 | if( ctx == NULL || ctx->pk_info == NULL ) | |
350 | return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); | |
351 | ||
352 | if( ctx->pk_info->debug_func == NULL ) | |
353 | return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); | |
354 | ||
355 | ctx->pk_info->debug_func( ctx->pk_ctx, items ); | |
356 | return( 0 ); | |
357 | } | |
358 | ||
359 | /* | |
360 | * Access the PK type name | |
361 | */ | |
362 | const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) | |
363 | { | |
364 | if( ctx == NULL || ctx->pk_info == NULL ) | |
365 | return( "invalid PK" ); | |
366 | ||
367 | return( ctx->pk_info->name ); | |
368 | } | |
369 | ||
370 | /* | |
371 | * Access the PK type | |
372 | */ | |
373 | mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) | |
374 | { | |
375 | if( ctx == NULL || ctx->pk_info == NULL ) | |
376 | return( MBEDTLS_PK_NONE ); | |
377 | ||
378 | return( ctx->pk_info->type ); | |
379 | } | |
380 | ||
381 | #endif /* MBEDTLS_PK_C */ |