156083Skris/* crypto/rsa/rsa_lib.c */
256083Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
356083Skris * All rights reserved.
456083Skris *
556083Skris * This package is an SSL implementation written
656083Skris * by Eric Young (eay@cryptsoft.com).
756083Skris * The implementation was written so as to conform with Netscapes SSL.
856083Skris *
956083Skris * This library is free for commercial and non-commercial use as long as
1056083Skris * the following conditions are aheared to.  The following conditions
1156083Skris * apply to all code found in this distribution, be it the RC4, RSA,
1256083Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1356083Skris * included with this distribution is covered by the same copyright terms
1456083Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1556083Skris *
1656083Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1756083Skris * the code are not to be removed.
1856083Skris * If this package is used in a product, Eric Young should be given attribution
1956083Skris * as the author of the parts of the library used.
2056083Skris * This can be in the form of a textual message at program startup or
2156083Skris * in documentation (online or textual) provided with the package.
2256083Skris *
2356083Skris * Redistribution and use in source and binary forms, with or without
2456083Skris * modification, are permitted provided that the following conditions
2556083Skris * are met:
2656083Skris * 1. Redistributions of source code must retain the copyright
2756083Skris *    notice, this list of conditions and the following disclaimer.
2856083Skris * 2. Redistributions in binary form must reproduce the above copyright
2956083Skris *    notice, this list of conditions and the following disclaimer in the
3056083Skris *    documentation and/or other materials provided with the distribution.
3156083Skris * 3. All advertising materials mentioning features or use of this software
3256083Skris *    must display the following acknowledgement:
3356083Skris *    "This product includes cryptographic software written by
3456083Skris *     Eric Young (eay@cryptsoft.com)"
3556083Skris *    The word 'cryptographic' can be left out if the rouines from the library
3656083Skris *    being used are not cryptographic related :-).
3756083Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3856083Skris *    the apps directory (application code) you must include an acknowledgement:
3956083Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4056083Skris *
4156083Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4256083Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4356083Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4456083Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4556083Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4656083Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4756083Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4856083Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4956083Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5056083Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5156083Skris * SUCH DAMAGE.
5256083Skris *
5356083Skris * The licence and distribution terms for any publically available version or
5456083Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5556083Skris * copied and put under another distribution licence
5656083Skris * [including the GNU Public Licence.]
5756083Skris */
5856083Skris
5956083Skris#include <stdio.h>
6056083Skris#include <openssl/crypto.h>
6156083Skris#include "cryptlib.h"
6256083Skris#include <openssl/lhash.h>
6356083Skris#include <openssl/bn.h>
6456083Skris#include <openssl/rsa.h>
65120635Snectar#include <openssl/rand.h>
66111150Snectar#ifndef OPENSSL_NO_ENGINE
67110007Smarkm#include <openssl/engine.h>
68111150Snectar#endif
6956083Skris
70238405Sjkim#ifdef OPENSSL_FIPS
71238405Sjkim#include <openssl/fips.h>
72238405Sjkim#endif
73238405Sjkim
74238405Sjkimconst char RSA_version[]="RSA" OPENSSL_VERSION_PTEXT;
75238405Sjkim
76238405Sjkimstatic const RSA_METHOD *default_RSA_meth=NULL;
77238405Sjkim
78238405SjkimRSA *RSA_new(void)
7956083Skris	{
80238405Sjkim	RSA *r=RSA_new_method(NULL);
81238405Sjkim
82238405Sjkim	return r;
8356083Skris	}
8456083Skris
85238405Sjkimvoid RSA_set_default_method(const RSA_METHOD *meth)
8656083Skris	{
87238405Sjkim	default_RSA_meth = meth;
88238405Sjkim	}
89238405Sjkim
90238405Sjkimconst RSA_METHOD *RSA_get_default_method(void)
91238405Sjkim	{
92238405Sjkim	if (default_RSA_meth == NULL)
93238405Sjkim		{
94194206Ssimon#ifdef OPENSSL_FIPS
95238405Sjkim		if (FIPS_mode())
96238405Sjkim			return FIPS_rsa_pkcs1_ssleay();
97238405Sjkim		else
98238405Sjkim			return RSA_PKCS1_SSLeay();
99238405Sjkim#else
100238405Sjkim#ifdef RSA_NULL
101238405Sjkim		default_RSA_meth=RSA_null_method();
102238405Sjkim#else
103238405Sjkim		default_RSA_meth=RSA_PKCS1_SSLeay();
104238405Sjkim#endif
105238405Sjkim#endif
106194206Ssimon		}
107238405Sjkim
108238405Sjkim	return default_RSA_meth;
10956083Skris	}
11056083Skris
111238405Sjkimconst RSA_METHOD *RSA_get_method(const RSA *rsa)
11256083Skris	{
113238405Sjkim	return rsa->meth;
11456083Skris	}
11556083Skris
116238405Sjkimint RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
11756083Skris	{
118238405Sjkim	/* NB: The caller is specifically setting a method, so it's not up to us
119238405Sjkim	 * to deal with which ENGINE it comes from. */
120238405Sjkim	const RSA_METHOD *mtmp;
121238405Sjkim	mtmp = rsa->meth;
122238405Sjkim	if (mtmp->finish) mtmp->finish(rsa);
123238405Sjkim#ifndef OPENSSL_NO_ENGINE
124238405Sjkim	if (rsa->engine)
125194206Ssimon		{
126238405Sjkim		ENGINE_finish(rsa->engine);
127238405Sjkim		rsa->engine = NULL;
128194206Ssimon		}
129194206Ssimon#endif
130238405Sjkim	rsa->meth = meth;
131238405Sjkim	if (meth->init) meth->init(rsa);
132238405Sjkim	return 1;
13356083Skris	}
13456083Skris
135238405SjkimRSA *RSA_new_method(ENGINE *engine)
13656083Skris	{
137238405Sjkim	RSA *ret;
13856083Skris
139238405Sjkim	ret=(RSA *)OPENSSL_malloc(sizeof(RSA));
140238405Sjkim	if (ret == NULL)
14156083Skris		{
142238405Sjkim		RSAerr(RSA_F_RSA_NEW_METHOD,ERR_R_MALLOC_FAILURE);
143238405Sjkim		return NULL;
14456083Skris		}
14556083Skris
146238405Sjkim	ret->meth = RSA_get_default_method();
147238405Sjkim#ifndef OPENSSL_NO_ENGINE
148238405Sjkim	if (engine)
149238405Sjkim		{
150238405Sjkim		if (!ENGINE_init(engine))
151238405Sjkim			{
152238405Sjkim			RSAerr(RSA_F_RSA_NEW_METHOD, ERR_R_ENGINE_LIB);
153238405Sjkim			OPENSSL_free(ret);
154238405Sjkim			return NULL;
155238405Sjkim			}
156238405Sjkim		ret->engine = engine;
157238405Sjkim		}
158238405Sjkim	else
159238405Sjkim		ret->engine = ENGINE_get_default_RSA();
160238405Sjkim	if(ret->engine)
161238405Sjkim		{
162238405Sjkim		ret->meth = ENGINE_get_RSA(ret->engine);
163238405Sjkim		if(!ret->meth)
164238405Sjkim			{
165238405Sjkim			RSAerr(RSA_F_RSA_NEW_METHOD,
166238405Sjkim				ERR_R_ENGINE_LIB);
167238405Sjkim			ENGINE_finish(ret->engine);
168238405Sjkim			OPENSSL_free(ret);
169238405Sjkim			return NULL;
170238405Sjkim			}
171238405Sjkim		}
172238405Sjkim#endif
17356083Skris
174238405Sjkim	ret->pad=0;
175238405Sjkim	ret->version=0;
176238405Sjkim	ret->n=NULL;
177238405Sjkim	ret->e=NULL;
178238405Sjkim	ret->d=NULL;
179238405Sjkim	ret->p=NULL;
180238405Sjkim	ret->q=NULL;
181238405Sjkim	ret->dmp1=NULL;
182238405Sjkim	ret->dmq1=NULL;
183238405Sjkim	ret->iqmp=NULL;
184238405Sjkim	ret->references=1;
185238405Sjkim	ret->_method_mod_n=NULL;
186238405Sjkim	ret->_method_mod_p=NULL;
187238405Sjkim	ret->_method_mod_q=NULL;
188238405Sjkim	ret->blinding=NULL;
189238405Sjkim	ret->mt_blinding=NULL;
190238405Sjkim	ret->bignum_data=NULL;
191238405Sjkim	ret->flags=ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
192238405Sjkim	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
193238405Sjkim		{
194238405Sjkim#ifndef OPENSSL_NO_ENGINE
195238405Sjkim	if (ret->engine)
196238405Sjkim		ENGINE_finish(ret->engine);
197238405Sjkim#endif
198238405Sjkim		OPENSSL_free(ret);
199238405Sjkim		return(NULL);
200238405Sjkim		}
201160817Ssimon
202238405Sjkim	if ((ret->meth->init != NULL) && !ret->meth->init(ret))
203238405Sjkim		{
204238405Sjkim#ifndef OPENSSL_NO_ENGINE
205238405Sjkim		if (ret->engine)
206238405Sjkim			ENGINE_finish(ret->engine);
207238405Sjkim#endif
208238405Sjkim		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
209238405Sjkim		OPENSSL_free(ret);
210238405Sjkim		ret=NULL;
211238405Sjkim		}
212160817Ssimon	return(ret);
213160817Ssimon	}
214160817Ssimon
215238405Sjkimvoid RSA_free(RSA *r)
216238405Sjkim	{
217238405Sjkim	int i;
218160817Ssimon
219238405Sjkim	if (r == NULL) return;
220160817Ssimon
221238405Sjkim	i=CRYPTO_add(&r->references,-1,CRYPTO_LOCK_RSA);
222238405Sjkim#ifdef REF_PRINT
223238405Sjkim	REF_PRINT("RSA",r);
224238405Sjkim#endif
225238405Sjkim	if (i > 0) return;
226238405Sjkim#ifdef REF_CHECK
227238405Sjkim	if (i < 0)
228238405Sjkim		{
229238405Sjkim		fprintf(stderr,"RSA_free, bad reference count\n");
230238405Sjkim		abort();
231238405Sjkim		}
232238405Sjkim#endif
233160817Ssimon
234238405Sjkim	if (r->meth->finish)
235238405Sjkim		r->meth->finish(r);
236238405Sjkim#ifndef OPENSSL_NO_ENGINE
237238405Sjkim	if (r->engine)
238238405Sjkim		ENGINE_finish(r->engine);
239238405Sjkim#endif
240160817Ssimon
241238405Sjkim	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
242160817Ssimon
243238405Sjkim	if (r->n != NULL) BN_clear_free(r->n);
244238405Sjkim	if (r->e != NULL) BN_clear_free(r->e);
245238405Sjkim	if (r->d != NULL) BN_clear_free(r->d);
246238405Sjkim	if (r->p != NULL) BN_clear_free(r->p);
247238405Sjkim	if (r->q != NULL) BN_clear_free(r->q);
248238405Sjkim	if (r->dmp1 != NULL) BN_clear_free(r->dmp1);
249238405Sjkim	if (r->dmq1 != NULL) BN_clear_free(r->dmq1);
250238405Sjkim	if (r->iqmp != NULL) BN_clear_free(r->iqmp);
251238405Sjkim	if (r->blinding != NULL) BN_BLINDING_free(r->blinding);
252238405Sjkim	if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding);
253238405Sjkim	if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data);
254238405Sjkim	OPENSSL_free(r);
255238405Sjkim	}
256160817Ssimon
257238405Sjkimint RSA_up_ref(RSA *r)
258238405Sjkim	{
259238405Sjkim	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA);
260238405Sjkim#ifdef REF_PRINT
261238405Sjkim	REF_PRINT("RSA",r);
262238405Sjkim#endif
263238405Sjkim#ifdef REF_CHECK
264238405Sjkim	if (i < 2)
26556083Skris		{
266238405Sjkim		fprintf(stderr, "RSA_up_ref, bad reference count\n");
267238405Sjkim		abort();
26856083Skris		}
269238405Sjkim#endif
270238405Sjkim	return ((i > 1) ? 1 : 0);
271238405Sjkim	}
27256083Skris
273238405Sjkimint RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
274238405Sjkim	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
275238405Sjkim        {
276238405Sjkim	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
277238405Sjkim				new_func, dup_func, free_func);
278238405Sjkim        }
27956083Skris
280238405Sjkimint RSA_set_ex_data(RSA *r, int idx, void *arg)
281238405Sjkim	{
282238405Sjkim	return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
283238405Sjkim	}
284160817Ssimon
285238405Sjkimvoid *RSA_get_ex_data(const RSA *r, int idx)
286238405Sjkim	{
287238405Sjkim	return(CRYPTO_get_ex_data(&r->ex_data,idx));
288238405Sjkim	}
28956083Skris
290238405Sjkimint RSA_memory_lock(RSA *r)
291238405Sjkim	{
292238405Sjkim	int i,j,k,off;
293238405Sjkim	char *p;
294238405Sjkim	BIGNUM *bn,**t[6],*b;
295238405Sjkim	BN_ULONG *ul;
296238405Sjkim
297238405Sjkim	if (r->d == NULL) return(1);
298238405Sjkim	t[0]= &r->d;
299238405Sjkim	t[1]= &r->p;
300238405Sjkim	t[2]= &r->q;
301238405Sjkim	t[3]= &r->dmp1;
302238405Sjkim	t[4]= &r->dmq1;
303238405Sjkim	t[5]= &r->iqmp;
304238405Sjkim	k=sizeof(BIGNUM)*6;
305238405Sjkim	off=k/sizeof(BN_ULONG)+1;
306238405Sjkim	j=1;
307238405Sjkim	for (i=0; i<6; i++)
308238405Sjkim		j+= (*t[i])->top;
309238405Sjkim	if ((p=OPENSSL_malloc_locked((off+j)*sizeof(BN_ULONG))) == NULL)
310194206Ssimon		{
311238405Sjkim		RSAerr(RSA_F_RSA_MEMORY_LOCK,ERR_R_MALLOC_FAILURE);
312238405Sjkim		return(0);
313194206Ssimon		}
314238405Sjkim	bn=(BIGNUM *)p;
315238405Sjkim	ul=(BN_ULONG *)&(p[off]);
316238405Sjkim	for (i=0; i<6; i++)
317160817Ssimon		{
318238405Sjkim		b= *(t[i]);
319238405Sjkim		*(t[i])= &(bn[i]);
320238405Sjkim		memcpy((char *)&(bn[i]),(char *)b,sizeof(BIGNUM));
321238405Sjkim		bn[i].flags=BN_FLG_STATIC_DATA;
322238405Sjkim		bn[i].d=ul;
323238405Sjkim		memcpy((char *)ul,b->d,sizeof(BN_ULONG)*b->top);
324238405Sjkim		ul+=b->top;
325238405Sjkim		BN_clear_free(b);
326160817Ssimon		}
327238405Sjkim
328238405Sjkim	/* I should fix this so it can still be done */
329238405Sjkim	r->flags&= ~(RSA_FLAG_CACHE_PRIVATE|RSA_FLAG_CACHE_PUBLIC);
33056083Skris
331238405Sjkim	r->bignum_data=p;
332238405Sjkim	return(1);
333238405Sjkim	}
334