1ebfedea0SLionel Sambuc /* crypto/rsa/rsa_gen.c */
2ebfedea0SLionel Sambuc /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3ebfedea0SLionel Sambuc * All rights reserved.
4ebfedea0SLionel Sambuc *
5ebfedea0SLionel Sambuc * This package is an SSL implementation written
6ebfedea0SLionel Sambuc * by Eric Young (eay@cryptsoft.com).
7ebfedea0SLionel Sambuc * The implementation was written so as to conform with Netscapes SSL.
8ebfedea0SLionel Sambuc *
9ebfedea0SLionel Sambuc * This library is free for commercial and non-commercial use as long as
10ebfedea0SLionel Sambuc * the following conditions are aheared to. The following conditions
11ebfedea0SLionel Sambuc * apply to all code found in this distribution, be it the RC4, RSA,
12ebfedea0SLionel Sambuc * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13ebfedea0SLionel Sambuc * included with this distribution is covered by the same copyright terms
14ebfedea0SLionel Sambuc * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15ebfedea0SLionel Sambuc *
16ebfedea0SLionel Sambuc * Copyright remains Eric Young's, and as such any Copyright notices in
17ebfedea0SLionel Sambuc * the code are not to be removed.
18ebfedea0SLionel Sambuc * If this package is used in a product, Eric Young should be given attribution
19ebfedea0SLionel Sambuc * as the author of the parts of the library used.
20ebfedea0SLionel Sambuc * This can be in the form of a textual message at program startup or
21ebfedea0SLionel Sambuc * in documentation (online or textual) provided with the package.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
24ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
25ebfedea0SLionel Sambuc * are met:
26ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the copyright
27ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
28ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
29ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
30ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
31ebfedea0SLionel Sambuc * 3. All advertising materials mentioning features or use of this software
32ebfedea0SLionel Sambuc * must display the following acknowledgement:
33ebfedea0SLionel Sambuc * "This product includes cryptographic software written by
34ebfedea0SLionel Sambuc * Eric Young (eay@cryptsoft.com)"
35ebfedea0SLionel Sambuc * The word 'cryptographic' can be left out if the rouines from the library
36ebfedea0SLionel Sambuc * being used are not cryptographic related :-).
37ebfedea0SLionel Sambuc * 4. If you include any Windows specific code (or a derivative thereof) from
38ebfedea0SLionel Sambuc * the apps directory (application code) you must include an acknowledgement:
39ebfedea0SLionel Sambuc * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40ebfedea0SLionel Sambuc *
41ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51ebfedea0SLionel Sambuc * SUCH DAMAGE.
52ebfedea0SLionel Sambuc *
53ebfedea0SLionel Sambuc * The licence and distribution terms for any publically available version or
54ebfedea0SLionel Sambuc * derivative of this code cannot be changed. i.e. this code cannot simply be
55ebfedea0SLionel Sambuc * copied and put under another distribution licence
56ebfedea0SLionel Sambuc * [including the GNU Public Licence.]
57ebfedea0SLionel Sambuc */
58ebfedea0SLionel Sambuc
59*0a6a1f1dSLionel Sambuc /*
60*0a6a1f1dSLionel Sambuc * NB: these functions have been "upgraded", the deprecated versions (which
61*0a6a1f1dSLionel Sambuc * are compatibility wrappers using these functions) are in rsa_depr.c. -
62*0a6a1f1dSLionel Sambuc * Geoff
63ebfedea0SLionel Sambuc */
64ebfedea0SLionel Sambuc
65ebfedea0SLionel Sambuc #include <stdio.h>
66ebfedea0SLionel Sambuc #include <time.h>
67ebfedea0SLionel Sambuc #include "cryptlib.h"
68ebfedea0SLionel Sambuc #include <openssl/bn.h>
69ebfedea0SLionel Sambuc #include <openssl/rsa.h>
70ebfedea0SLionel Sambuc #ifdef OPENSSL_FIPS
71ebfedea0SLionel Sambuc # include <openssl/fips.h>
72ebfedea0SLionel Sambuc #endif
73ebfedea0SLionel Sambuc
74*0a6a1f1dSLionel Sambuc static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
75*0a6a1f1dSLionel Sambuc BN_GENCB *cb);
76ebfedea0SLionel Sambuc
77*0a6a1f1dSLionel Sambuc /*
78*0a6a1f1dSLionel Sambuc * NB: this wrapper would normally be placed in rsa_lib.c and the static
79*0a6a1f1dSLionel Sambuc * implementation would probably be in rsa_eay.c. Nonetheless, is kept here
80*0a6a1f1dSLionel Sambuc * so that we don't introduce a new linker dependency. Eg. any application
81*0a6a1f1dSLionel Sambuc * that wasn't previously linking object code related to key-generation won't
82*0a6a1f1dSLionel Sambuc * have to now just because key-generation is part of RSA_METHOD.
83*0a6a1f1dSLionel Sambuc */
RSA_generate_key_ex(RSA * rsa,int bits,BIGNUM * e_value,BN_GENCB * cb)84ebfedea0SLionel Sambuc int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
85ebfedea0SLionel Sambuc {
86ebfedea0SLionel Sambuc #ifdef OPENSSL_FIPS
87ebfedea0SLionel Sambuc if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
88*0a6a1f1dSLionel Sambuc && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)) {
89ebfedea0SLionel Sambuc RSAerr(RSA_F_RSA_GENERATE_KEY_EX, RSA_R_NON_FIPS_RSA_METHOD);
90ebfedea0SLionel Sambuc return 0;
91ebfedea0SLionel Sambuc }
92ebfedea0SLionel Sambuc #endif
93ebfedea0SLionel Sambuc if (rsa->meth->rsa_keygen)
94ebfedea0SLionel Sambuc return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
95ebfedea0SLionel Sambuc #ifdef OPENSSL_FIPS
96ebfedea0SLionel Sambuc if (FIPS_mode())
97ebfedea0SLionel Sambuc return FIPS_rsa_generate_key_ex(rsa, bits, e_value, cb);
98ebfedea0SLionel Sambuc #endif
99ebfedea0SLionel Sambuc return rsa_builtin_keygen(rsa, bits, e_value, cb);
100ebfedea0SLionel Sambuc }
101ebfedea0SLionel Sambuc
rsa_builtin_keygen(RSA * rsa,int bits,BIGNUM * e_value,BN_GENCB * cb)102*0a6a1f1dSLionel Sambuc static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value,
103*0a6a1f1dSLionel Sambuc BN_GENCB *cb)
104ebfedea0SLionel Sambuc {
105ebfedea0SLionel Sambuc BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
106ebfedea0SLionel Sambuc BIGNUM local_r0, local_d, local_p;
107ebfedea0SLionel Sambuc BIGNUM *pr0, *d, *p;
108ebfedea0SLionel Sambuc int bitsp, bitsq, ok = -1, n = 0;
109ebfedea0SLionel Sambuc BN_CTX *ctx = NULL;
110ebfedea0SLionel Sambuc
111ebfedea0SLionel Sambuc ctx = BN_CTX_new();
112*0a6a1f1dSLionel Sambuc if (ctx == NULL)
113*0a6a1f1dSLionel Sambuc goto err;
114ebfedea0SLionel Sambuc BN_CTX_start(ctx);
115ebfedea0SLionel Sambuc r0 = BN_CTX_get(ctx);
116ebfedea0SLionel Sambuc r1 = BN_CTX_get(ctx);
117ebfedea0SLionel Sambuc r2 = BN_CTX_get(ctx);
118ebfedea0SLionel Sambuc r3 = BN_CTX_get(ctx);
119*0a6a1f1dSLionel Sambuc if (r3 == NULL)
120*0a6a1f1dSLionel Sambuc goto err;
121ebfedea0SLionel Sambuc
122ebfedea0SLionel Sambuc bitsp = (bits + 1) / 2;
123ebfedea0SLionel Sambuc bitsq = bits - bitsp;
124ebfedea0SLionel Sambuc
125ebfedea0SLionel Sambuc /* We need the RSA components non-NULL */
126*0a6a1f1dSLionel Sambuc if (!rsa->n && ((rsa->n = BN_new()) == NULL))
127*0a6a1f1dSLionel Sambuc goto err;
128*0a6a1f1dSLionel Sambuc if (!rsa->d && ((rsa->d = BN_new()) == NULL))
129*0a6a1f1dSLionel Sambuc goto err;
130*0a6a1f1dSLionel Sambuc if (!rsa->e && ((rsa->e = BN_new()) == NULL))
131*0a6a1f1dSLionel Sambuc goto err;
132*0a6a1f1dSLionel Sambuc if (!rsa->p && ((rsa->p = BN_new()) == NULL))
133*0a6a1f1dSLionel Sambuc goto err;
134*0a6a1f1dSLionel Sambuc if (!rsa->q && ((rsa->q = BN_new()) == NULL))
135*0a6a1f1dSLionel Sambuc goto err;
136*0a6a1f1dSLionel Sambuc if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
137*0a6a1f1dSLionel Sambuc goto err;
138*0a6a1f1dSLionel Sambuc if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
139*0a6a1f1dSLionel Sambuc goto err;
140*0a6a1f1dSLionel Sambuc if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
141*0a6a1f1dSLionel Sambuc goto err;
142ebfedea0SLionel Sambuc
143ebfedea0SLionel Sambuc BN_copy(rsa->e, e_value);
144ebfedea0SLionel Sambuc
145ebfedea0SLionel Sambuc /* generate p and q */
146*0a6a1f1dSLionel Sambuc for (;;) {
147ebfedea0SLionel Sambuc if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
148ebfedea0SLionel Sambuc goto err;
149*0a6a1f1dSLionel Sambuc if (!BN_sub(r2, rsa->p, BN_value_one()))
150*0a6a1f1dSLionel Sambuc goto err;
151*0a6a1f1dSLionel Sambuc if (!BN_gcd(r1, r2, rsa->e, ctx))
152*0a6a1f1dSLionel Sambuc goto err;
153*0a6a1f1dSLionel Sambuc if (BN_is_one(r1))
154*0a6a1f1dSLionel Sambuc break;
155ebfedea0SLionel Sambuc if (!BN_GENCB_call(cb, 2, n++))
156ebfedea0SLionel Sambuc goto err;
157ebfedea0SLionel Sambuc }
158ebfedea0SLionel Sambuc if (!BN_GENCB_call(cb, 3, 0))
159ebfedea0SLionel Sambuc goto err;
160*0a6a1f1dSLionel Sambuc for (;;) {
161*0a6a1f1dSLionel Sambuc /*
162*0a6a1f1dSLionel Sambuc * When generating ridiculously small keys, we can get stuck
163*0a6a1f1dSLionel Sambuc * continually regenerating the same prime values. Check for this and
164*0a6a1f1dSLionel Sambuc * bail if it happens 3 times.
165*0a6a1f1dSLionel Sambuc */
166ebfedea0SLionel Sambuc unsigned int degenerate = 0;
167*0a6a1f1dSLionel Sambuc do {
168ebfedea0SLionel Sambuc if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL, cb))
169ebfedea0SLionel Sambuc goto err;
170ebfedea0SLionel Sambuc } while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
171*0a6a1f1dSLionel Sambuc if (degenerate == 3) {
172ebfedea0SLionel Sambuc ok = 0; /* we set our own err */
173ebfedea0SLionel Sambuc RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
174ebfedea0SLionel Sambuc goto err;
175ebfedea0SLionel Sambuc }
176*0a6a1f1dSLionel Sambuc if (!BN_sub(r2, rsa->q, BN_value_one()))
177*0a6a1f1dSLionel Sambuc goto err;
178*0a6a1f1dSLionel Sambuc if (!BN_gcd(r1, r2, rsa->e, ctx))
179*0a6a1f1dSLionel Sambuc goto err;
180ebfedea0SLionel Sambuc if (BN_is_one(r1))
181ebfedea0SLionel Sambuc break;
182ebfedea0SLionel Sambuc if (!BN_GENCB_call(cb, 2, n++))
183ebfedea0SLionel Sambuc goto err;
184ebfedea0SLionel Sambuc }
185ebfedea0SLionel Sambuc if (!BN_GENCB_call(cb, 3, 1))
186ebfedea0SLionel Sambuc goto err;
187*0a6a1f1dSLionel Sambuc if (BN_cmp(rsa->p, rsa->q) < 0) {
188ebfedea0SLionel Sambuc tmp = rsa->p;
189ebfedea0SLionel Sambuc rsa->p = rsa->q;
190ebfedea0SLionel Sambuc rsa->q = tmp;
191ebfedea0SLionel Sambuc }
192ebfedea0SLionel Sambuc
193ebfedea0SLionel Sambuc /* calculate n */
194*0a6a1f1dSLionel Sambuc if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
195*0a6a1f1dSLionel Sambuc goto err;
196ebfedea0SLionel Sambuc
197ebfedea0SLionel Sambuc /* calculate d */
198*0a6a1f1dSLionel Sambuc if (!BN_sub(r1, rsa->p, BN_value_one()))
199*0a6a1f1dSLionel Sambuc goto err; /* p-1 */
200*0a6a1f1dSLionel Sambuc if (!BN_sub(r2, rsa->q, BN_value_one()))
201*0a6a1f1dSLionel Sambuc goto err; /* q-1 */
202*0a6a1f1dSLionel Sambuc if (!BN_mul(r0, r1, r2, ctx))
203*0a6a1f1dSLionel Sambuc goto err; /* (p-1)(q-1) */
204*0a6a1f1dSLionel Sambuc if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
205ebfedea0SLionel Sambuc pr0 = &local_r0;
206ebfedea0SLionel Sambuc BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
207*0a6a1f1dSLionel Sambuc } else
208ebfedea0SLionel Sambuc pr0 = r0;
209*0a6a1f1dSLionel Sambuc if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx))
210*0a6a1f1dSLionel Sambuc goto err; /* d */
211ebfedea0SLionel Sambuc
212ebfedea0SLionel Sambuc /* set up d for correct BN_FLG_CONSTTIME flag */
213*0a6a1f1dSLionel Sambuc if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
214ebfedea0SLionel Sambuc d = &local_d;
215ebfedea0SLionel Sambuc BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
216*0a6a1f1dSLionel Sambuc } else
217ebfedea0SLionel Sambuc d = rsa->d;
218ebfedea0SLionel Sambuc
219ebfedea0SLionel Sambuc /* calculate d mod (p-1) */
220*0a6a1f1dSLionel Sambuc if (!BN_mod(rsa->dmp1, d, r1, ctx))
221*0a6a1f1dSLionel Sambuc goto err;
222ebfedea0SLionel Sambuc
223ebfedea0SLionel Sambuc /* calculate d mod (q-1) */
224*0a6a1f1dSLionel Sambuc if (!BN_mod(rsa->dmq1, d, r2, ctx))
225*0a6a1f1dSLionel Sambuc goto err;
226ebfedea0SLionel Sambuc
227ebfedea0SLionel Sambuc /* calculate inverse of q mod p */
228*0a6a1f1dSLionel Sambuc if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) {
229ebfedea0SLionel Sambuc p = &local_p;
230ebfedea0SLionel Sambuc BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
231*0a6a1f1dSLionel Sambuc } else
232ebfedea0SLionel Sambuc p = rsa->p;
233*0a6a1f1dSLionel Sambuc if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx))
234*0a6a1f1dSLionel Sambuc goto err;
235ebfedea0SLionel Sambuc
236ebfedea0SLionel Sambuc ok = 1;
237ebfedea0SLionel Sambuc err:
238*0a6a1f1dSLionel Sambuc if (ok == -1) {
239ebfedea0SLionel Sambuc RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
240ebfedea0SLionel Sambuc ok = 0;
241ebfedea0SLionel Sambuc }
242*0a6a1f1dSLionel Sambuc if (ctx != NULL) {
243ebfedea0SLionel Sambuc BN_CTX_end(ctx);
244ebfedea0SLionel Sambuc BN_CTX_free(ctx);
245ebfedea0SLionel Sambuc }
246ebfedea0SLionel Sambuc
247ebfedea0SLionel Sambuc return ok;
248ebfedea0SLionel Sambuc }
249