|
1 /* crypto/rsa/rsa_lib.c */ |
|
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
|
3 * All rights reserved. |
|
4 * |
|
5 * This package is an SSL implementation written |
|
6 * by Eric Young (eay@cryptsoft.com). |
|
7 * The implementation was written so as to conform with Netscapes SSL. |
|
8 * |
|
9 * This library is free for commercial and non-commercial use as long as |
|
10 * the following conditions are aheared to. The following conditions |
|
11 * apply to all code found in this distribution, be it the RC4, RSA, |
|
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation |
|
13 * included with this distribution is covered by the same copyright terms |
|
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). |
|
15 * |
|
16 * Copyright remains Eric Young's, and as such any Copyright notices in |
|
17 * the code are not to be removed. |
|
18 * If this package is used in a product, Eric Young should be given attribution |
|
19 * as the author of the parts of the library used. |
|
20 * This can be in the form of a textual message at program startup or |
|
21 * in documentation (online or textual) provided with the package. |
|
22 * |
|
23 * Redistribution and use in source and binary forms, with or without |
|
24 * modification, are permitted provided that the following conditions |
|
25 * are met: |
|
26 * 1. Redistributions of source code must retain the copyright |
|
27 * notice, this list of conditions and the following disclaimer. |
|
28 * 2. Redistributions in binary form must reproduce the above copyright |
|
29 * notice, this list of conditions and the following disclaimer in the |
|
30 * documentation and/or other materials provided with the distribution. |
|
31 * 3. All advertising materials mentioning features or use of this software |
|
32 * must display the following acknowledgement: |
|
33 * "This product includes cryptographic software written by |
|
34 * Eric Young (eay@cryptsoft.com)" |
|
35 * The word 'cryptographic' can be left out if the rouines from the library |
|
36 * being used are not cryptographic related :-). |
|
37 * 4. If you include any Windows specific code (or a derivative thereof) from |
|
38 * the apps directory (application code) you must include an acknowledgement: |
|
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
|
40 * |
|
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
|
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
|
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
51 * SUCH DAMAGE. |
|
52 * |
|
53 * The licence and distribution terms for any publically available version or |
|
54 * derivative of this code cannot be changed. i.e. this code cannot simply be |
|
55 * copied and put under another distribution licence |
|
56 * [including the GNU Public Licence.] |
|
57 */ |
|
58 /* |
|
59 © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. |
|
60 */ |
|
61 |
|
62 #include <stdio.h> |
|
63 #include <openssl/crypto.h> |
|
64 #include "cryptlib.h" |
|
65 #include <openssl/lhash.h> |
|
66 #include <openssl/bn.h> |
|
67 #include <openssl/rsa.h> |
|
68 #include <openssl/rand.h> |
|
69 #ifndef OPENSSL_NO_ENGINE |
|
70 #include <openssl/engine.h> |
|
71 #endif |
|
72 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__))) |
|
73 #include "libcrypto_wsd_macros.h" |
|
74 #include "libcrypto_wsd.h" |
|
75 #endif |
|
76 |
|
77 |
|
78 const char RSA_version[]="RSA" OPENSSL_VERSION_PTEXT; |
|
79 |
|
80 #ifndef EMULATOR |
|
81 static const RSA_METHOD *default_RSA_meth=NULL; |
|
82 #else |
|
83 GET_STATIC_VAR_FROM_TLS(default_RSA_meth,rsa_lib,const RSA_METHOD *) |
|
84 #define default_RSA_meth (*GET_WSD_VAR_NAME(default_RSA_meth,rsa_lib, s)()) |
|
85 #endif |
|
86 |
|
87 EXPORT_C RSA *RSA_new(void) |
|
88 { |
|
89 RSA *r=RSA_new_method(NULL); |
|
90 |
|
91 return r; |
|
92 } |
|
93 |
|
94 EXPORT_C void RSA_set_default_method(const RSA_METHOD *meth) |
|
95 { |
|
96 default_RSA_meth = meth; |
|
97 } |
|
98 |
|
99 EXPORT_C const RSA_METHOD *RSA_get_default_method(void) |
|
100 { |
|
101 if (default_RSA_meth == NULL) |
|
102 { |
|
103 #ifdef RSA_NULL |
|
104 default_RSA_meth=RSA_null_method(); |
|
105 #else |
|
106 #if 0 /* was: #ifdef RSAref */ |
|
107 default_RSA_meth=RSA_PKCS1_RSAref(); |
|
108 #else |
|
109 default_RSA_meth=RSA_PKCS1_SSLeay(); |
|
110 #endif |
|
111 #endif |
|
112 } |
|
113 |
|
114 return default_RSA_meth; |
|
115 } |
|
116 |
|
117 EXPORT_C const RSA_METHOD *RSA_get_method(const RSA *rsa) |
|
118 { |
|
119 return rsa->meth; |
|
120 } |
|
121 |
|
122 EXPORT_C int RSA_set_method(RSA *rsa, const RSA_METHOD *meth) |
|
123 { |
|
124 /* NB: The caller is specifically setting a method, so it's not up to us |
|
125 * to deal with which ENGINE it comes from. */ |
|
126 const RSA_METHOD *mtmp; |
|
127 mtmp = rsa->meth; |
|
128 if (mtmp->finish) mtmp->finish(rsa); |
|
129 #ifndef OPENSSL_NO_ENGINE |
|
130 if (rsa->engine) |
|
131 { |
|
132 ENGINE_finish(rsa->engine); |
|
133 rsa->engine = NULL; |
|
134 } |
|
135 #endif |
|
136 rsa->meth = meth; |
|
137 if (meth->init) meth->init(rsa); |
|
138 return 1; |
|
139 } |
|
140 |
|
141 EXPORT_C RSA *RSA_new_method(ENGINE *engine) |
|
142 { |
|
143 RSA *ret; |
|
144 |
|
145 ret=(RSA *)OPENSSL_malloc(sizeof(RSA)); |
|
146 if (ret == NULL) |
|
147 { |
|
148 RSAerr(RSA_F_RSA_NEW_METHOD,ERR_R_MALLOC_FAILURE); |
|
149 return NULL; |
|
150 } |
|
151 |
|
152 ret->meth = RSA_get_default_method(); |
|
153 #ifndef OPENSSL_NO_ENGINE |
|
154 if (engine) |
|
155 { |
|
156 if (!ENGINE_init(engine)) |
|
157 { |
|
158 RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB); |
|
159 OPENSSL_free(ret); |
|
160 return NULL; |
|
161 } |
|
162 ret->engine = engine; |
|
163 } |
|
164 else |
|
165 ret->engine = ENGINE_get_default_RSA(); |
|
166 if(ret->engine) |
|
167 { |
|
168 ret->meth = ENGINE_get_RSA(ret->engine); |
|
169 if(!ret->meth) |
|
170 { |
|
171 RSAerr(RSA_F_RSA_NEW_METHOD, |
|
172 ERR_R_ENGINE_LIB); |
|
173 ENGINE_finish(ret->engine); |
|
174 OPENSSL_free(ret); |
|
175 return NULL; |
|
176 } |
|
177 } |
|
178 #endif |
|
179 |
|
180 ret->pad=0; |
|
181 ret->version=0; |
|
182 ret->n=NULL; |
|
183 ret->e=NULL; |
|
184 ret->d=NULL; |
|
185 ret->p=NULL; |
|
186 ret->q=NULL; |
|
187 ret->dmp1=NULL; |
|
188 ret->dmq1=NULL; |
|
189 ret->iqmp=NULL; |
|
190 ret->references=1; |
|
191 ret->_method_mod_n=NULL; |
|
192 ret->_method_mod_p=NULL; |
|
193 ret->_method_mod_q=NULL; |
|
194 ret->blinding=NULL; |
|
195 ret->mt_blinding=NULL; |
|
196 ret->bignum_data=NULL; |
|
197 ret->flags=ret->meth->flags; |
|
198 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); |
|
199 if ((ret->meth->init != NULL) && !ret->meth->init(ret)) |
|
200 { |
|
201 #ifndef OPENSSL_NO_ENGINE |
|
202 if (ret->engine) |
|
203 ENGINE_finish(ret->engine); |
|
204 #endif |
|
205 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); |
|
206 OPENSSL_free(ret); |
|
207 ret=NULL; |
|
208 } |
|
209 return(ret); |
|
210 } |
|
211 |
|
212 EXPORT_C void RSA_free(RSA *r) |
|
213 { |
|
214 int i; |
|
215 |
|
216 if (r == NULL) return; |
|
217 |
|
218 i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA); |
|
219 #ifdef REF_PRINT |
|
220 REF_PRINT("RSA",r); |
|
221 #endif |
|
222 if (i > 0) return; |
|
223 #ifdef REF_CHECK |
|
224 if (i < 0) |
|
225 { |
|
226 fprintf(stderr,"RSA_free, bad reference count\n"); |
|
227 abort(); |
|
228 } |
|
229 #endif |
|
230 |
|
231 if (r->meth->finish) |
|
232 r->meth->finish(r); |
|
233 #ifndef OPENSSL_NO_ENGINE |
|
234 if (r->engine) |
|
235 ENGINE_finish(r->engine); |
|
236 #endif |
|
237 |
|
238 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data); |
|
239 |
|
240 if (r->n != NULL) BN_clear_free(r->n); |
|
241 if (r->e != NULL) BN_clear_free(r->e); |
|
242 if (r->d != NULL) BN_clear_free(r->d); |
|
243 if (r->p != NULL) BN_clear_free(r->p); |
|
244 if (r->q != NULL) BN_clear_free(r->q); |
|
245 if (r->dmp1 != NULL) BN_clear_free(r->dmp1); |
|
246 if (r->dmq1 != NULL) BN_clear_free(r->dmq1); |
|
247 if (r->iqmp != NULL) BN_clear_free(r->iqmp); |
|
248 if (r->blinding != NULL) BN_BLINDING_free(r->blinding); |
|
249 if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding); |
|
250 if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data); |
|
251 OPENSSL_free(r); |
|
252 } |
|
253 |
|
254 EXPORT_C int RSA_up_ref(RSA *r) |
|
255 { |
|
256 int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA); |
|
257 #ifdef REF_PRINT |
|
258 REF_PRINT("RSA",r); |
|
259 #endif |
|
260 #ifdef REF_CHECK |
|
261 if (i < 2) |
|
262 { |
|
263 fprintf(stderr, "RSA_up_ref, bad reference count\n"); |
|
264 abort(); |
|
265 } |
|
266 #endif |
|
267 return ((i > 1) ? 1 : 0); |
|
268 } |
|
269 |
|
270 EXPORT_C int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, |
|
271 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) |
|
272 { |
|
273 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp, |
|
274 new_func, dup_func, free_func); |
|
275 } |
|
276 |
|
277 EXPORT_C int RSA_set_ex_data(RSA *r, int idx, void *arg) |
|
278 { |
|
279 return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); |
|
280 } |
|
281 |
|
282 EXPORT_C void *RSA_get_ex_data(const RSA *r, int idx) |
|
283 { |
|
284 return(CRYPTO_get_ex_data(&r->ex_data,idx)); |
|
285 } |
|
286 |
|
287 EXPORT_C int RSA_size(const RSA *r) |
|
288 { |
|
289 return(BN_num_bytes(r->n)); |
|
290 } |
|
291 |
|
292 EXPORT_C int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, |
|
293 RSA *rsa, int padding) |
|
294 { |
|
295 return(rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding)); |
|
296 } |
|
297 |
|
298 EXPORT_C int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to, |
|
299 RSA *rsa, int padding) |
|
300 { |
|
301 return(rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding)); |
|
302 } |
|
303 |
|
304 EXPORT_C int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, |
|
305 RSA *rsa, int padding) |
|
306 { |
|
307 return(rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding)); |
|
308 } |
|
309 |
|
310 EXPORT_C int RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to, |
|
311 RSA *rsa, int padding) |
|
312 { |
|
313 return(rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding)); |
|
314 } |
|
315 |
|
316 EXPORT_C int RSA_flags(const RSA *r) |
|
317 { |
|
318 return((r == NULL)?0:r->meth->flags); |
|
319 } |
|
320 |
|
321 EXPORT_C void RSA_blinding_off(RSA *rsa) |
|
322 { |
|
323 if (rsa->blinding != NULL) |
|
324 { |
|
325 BN_BLINDING_free(rsa->blinding); |
|
326 rsa->blinding=NULL; |
|
327 } |
|
328 rsa->flags &= ~RSA_FLAG_BLINDING; |
|
329 rsa->flags |= RSA_FLAG_NO_BLINDING; |
|
330 } |
|
331 |
|
332 EXPORT_C int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) |
|
333 { |
|
334 int ret=0; |
|
335 |
|
336 if (rsa->blinding != NULL) |
|
337 RSA_blinding_off(rsa); |
|
338 |
|
339 rsa->blinding = RSA_setup_blinding(rsa, ctx); |
|
340 if (rsa->blinding == NULL) |
|
341 goto err; |
|
342 |
|
343 rsa->flags |= RSA_FLAG_BLINDING; |
|
344 rsa->flags &= ~RSA_FLAG_NO_BLINDING; |
|
345 ret=1; |
|
346 err: |
|
347 return(ret); |
|
348 } |
|
349 |
|
350 static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, |
|
351 const BIGNUM *q, BN_CTX *ctx) |
|
352 { |
|
353 BIGNUM *ret = NULL, *r0, *r1, *r2; |
|
354 |
|
355 if (d == NULL || p == NULL || q == NULL) |
|
356 return NULL; |
|
357 |
|
358 BN_CTX_start(ctx); |
|
359 r0 = BN_CTX_get(ctx); |
|
360 r1 = BN_CTX_get(ctx); |
|
361 r2 = BN_CTX_get(ctx); |
|
362 if (r2 == NULL) |
|
363 goto err; |
|
364 |
|
365 if (!BN_sub(r1, p, BN_value_one())) goto err; |
|
366 if (!BN_sub(r2, q, BN_value_one())) goto err; |
|
367 if (!BN_mul(r0, r1, r2, ctx)) goto err; |
|
368 |
|
369 ret = BN_mod_inverse(NULL, d, r0, ctx); |
|
370 err: |
|
371 BN_CTX_end(ctx); |
|
372 return ret; |
|
373 } |
|
374 |
|
375 EXPORT_C BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) |
|
376 { |
|
377 BIGNUM local_n; |
|
378 BIGNUM *e,*n; |
|
379 BN_CTX *ctx; |
|
380 BN_BLINDING *ret = NULL; |
|
381 |
|
382 if (in_ctx == NULL) |
|
383 { |
|
384 if ((ctx = BN_CTX_new()) == NULL) return 0; |
|
385 } |
|
386 else |
|
387 ctx = in_ctx; |
|
388 |
|
389 BN_CTX_start(ctx); |
|
390 e = BN_CTX_get(ctx); |
|
391 if (e == NULL) |
|
392 { |
|
393 RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); |
|
394 goto err; |
|
395 } |
|
396 |
|
397 if (rsa->e == NULL) |
|
398 { |
|
399 e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); |
|
400 if (e == NULL) |
|
401 { |
|
402 RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT); |
|
403 goto err; |
|
404 } |
|
405 } |
|
406 else |
|
407 e = rsa->e; |
|
408 |
|
409 |
|
410 if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) |
|
411 { |
|
412 /* if PRNG is not properly seeded, resort to secret |
|
413 * exponent as unpredictable seed */ |
|
414 RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0); |
|
415 } |
|
416 |
|
417 if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) |
|
418 { |
|
419 /* Set BN_FLG_CONSTTIME flag */ |
|
420 n = &local_n; |
|
421 BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME); |
|
422 } |
|
423 else |
|
424 n = rsa->n; |
|
425 |
|
426 ret = BN_BLINDING_create_param(NULL, e, n, ctx, |
|
427 rsa->meth->bn_mod_exp, rsa->_method_mod_n); |
|
428 if (ret == NULL) |
|
429 { |
|
430 RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB); |
|
431 goto err; |
|
432 } |
|
433 BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id()); |
|
434 err: |
|
435 BN_CTX_end(ctx); |
|
436 if (in_ctx == NULL) |
|
437 BN_CTX_free(ctx); |
|
438 if(rsa->e == NULL) |
|
439 BN_free(e); |
|
440 |
|
441 return ret; |
|
442 } |
|
443 |
|
444 EXPORT_C int RSA_memory_lock(RSA *r) |
|
445 { |
|
446 int i,j,k,off; |
|
447 char *p; |
|
448 BIGNUM *bn,**t[6],*b; |
|
449 BN_ULONG *ul; |
|
450 |
|
451 if (r->d == NULL) return(1); |
|
452 t[0]= &r->d; |
|
453 t[1]= &r->p; |
|
454 t[2]= &r->q; |
|
455 t[3]= &r->dmp1; |
|
456 t[4]= &r->dmq1; |
|
457 t[5]= &r->iqmp; |
|
458 k=sizeof(BIGNUM)*6; |
|
459 off=k/sizeof(BN_ULONG)+1; |
|
460 j=1; |
|
461 for (i=0; i<6; i++) |
|
462 j+= (*t[i])->top; |
|
463 if ((p=OPENSSL_malloc_locked((off+j)*sizeof(BN_ULONG))) == NULL) |
|
464 { |
|
465 RSAerr(RSA_F_RSA_MEMORY_LOCK,ERR_R_MALLOC_FAILURE); |
|
466 return(0); |
|
467 } |
|
468 bn=(BIGNUM *)p; |
|
469 ul=(BN_ULONG *)&(p[off]); |
|
470 for (i=0; i<6; i++) |
|
471 { |
|
472 b= *(t[i]); |
|
473 *(t[i])= &(bn[i]); |
|
474 memcpy((char *)&(bn[i]),(char *)b,sizeof(BIGNUM)); |
|
475 bn[i].flags=BN_FLG_STATIC_DATA; |
|
476 bn[i].d=ul; |
|
477 memcpy((char *)ul,b->d,sizeof(BN_ULONG)*b->top); |
|
478 ul+=b->top; |
|
479 BN_clear_free(b); |
|
480 } |
|
481 |
|
482 /* I should fix this so it can still be done */ |
|
483 r->flags&= ~(RSA_FLAG_CACHE_PRIVATE|RSA_FLAG_CACHE_PUBLIC); |
|
484 |
|
485 r->bignum_data=p; |
|
486 return(1); |
|
487 } |