xref: /minix3/crypto/external/bsd/openssl/dist/crypto/rsa/rsa_gen.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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