57305c7273b5b271665a0d9d29e0453b2849d1d8
[openssl.git] / crypto / bn / bn_prime.c
1 /* crypto/bn/bn_prime.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 #include <stdio.h>
60 #include <time.h>
61 #include "cryptlib.h"
62 #include "bn_lcl.h"
63 #include <openssl/rand.h>
64
65 /* The quick seive algorithm approach to weeding out primes is
66  * Philip Zimmermann's, as implemented in PGP.  I have had a read of
67  * his comments and implemented my own version.
68  */
69 #include "bn_prime.h"
70
71 static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx,BN_CTX *ctx2,
72         BN_MONT_CTX *mont);
73 static int probable_prime(BIGNUM *rnd, int bits);
74 static int probable_prime_dh(BIGNUM *rnd, int bits,
75         BIGNUM *add, BIGNUM *rem, BN_CTX *ctx);
76 static int probable_prime_dh_safe(BIGNUM *rnd, int bits,
77         BIGNUM *add, BIGNUM *rem, BN_CTX *ctx);
78 BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add,
79              BIGNUM *rem, void (*callback)(int,int,void *), void *cb_arg)
80         {
81         BIGNUM *rnd=NULL;
82         BIGNUM t;
83         int i,j,c1=0;
84         BN_CTX *ctx;
85         int checks = BN_prime_checks(bits);
86
87         ctx=BN_CTX_new();
88         if (ctx == NULL) goto err;
89         if (ret == NULL)
90                 {
91                 if ((rnd=BN_new()) == NULL) goto err;
92                 }
93         else
94                 rnd=ret;
95         BN_init(&t);
96 loop: 
97         /* make a random number and set the top and bottom bits */
98         if (add == NULL)
99                 {
100                 if (!probable_prime(rnd,bits)) goto err;
101                 }
102         else
103                 {
104                 if (safe)
105                         {
106                         if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx))
107                                  goto err;
108                         }
109                 else
110                         {
111                         if (!probable_prime_dh(rnd,bits,add,rem,ctx))
112                                 goto err;
113                         }
114                 }
115         /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */
116         if (callback != NULL) callback(0,c1++,cb_arg);
117
118         if (!safe)
119                 {
120                 i=BN_is_prime(rnd,checks,callback,ctx,cb_arg);
121                 if (i == -1) goto err;
122                 if (i == 0) goto loop;
123                 }
124         else
125                 {
126                 /* for "safe prime" generation,
127                  * check that (p-1)/2 is prime.
128                  * Since a prime is odd, We just
129                  * need to divide by 2 */
130                 if (!BN_rshift1(&t,rnd)) goto err;
131
132                 for (i=0; i<checks; i++)
133                         {
134                         j=BN_is_prime(rnd,1,callback,ctx,cb_arg);
135                         if (j == -1) goto err;
136                         if (j == 0) goto loop;
137
138                         j=BN_is_prime(&t,1,callback,ctx,cb_arg);
139                         if (j == -1) goto err;
140                         if (j == 0) goto loop;
141
142                         if (callback != NULL) callback(2,c1-1,cb_arg);
143                         /* We have a safe prime test pass */
144                         }
145                 }
146         /* we have a prime :-) */
147         ret=rnd;
148 err:
149         if ((ret == NULL) && (rnd != NULL)) BN_free(rnd);
150         BN_free(&t);
151         if (ctx != NULL) BN_CTX_free(ctx);
152         return(ret);
153         }
154
155 int BN_is_prime(BIGNUM *a, int checks, void (*callback)(int,int,void *),
156              BN_CTX *ctx_passed, void *cb_arg)
157         {
158         int i,j,c2=0,ret= -1;
159         BIGNUM *check;
160         BN_CTX *ctx=NULL,*ctx2=NULL;
161         BN_MONT_CTX *mont=NULL;
162
163         if (!BN_is_odd(a))
164                 return(0);
165         if (ctx_passed != NULL)
166                 ctx=ctx_passed;
167         else
168                 if ((ctx=BN_CTX_new()) == NULL) goto err;
169
170         if ((ctx2=BN_CTX_new()) == NULL) goto err;
171         if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
172
173         check= &(ctx->bn[ctx->tos++]);
174
175         /* Setup the montgomery structure */
176         if (!BN_MONT_CTX_set(mont,a,ctx2)) goto err;
177
178         for (i=0; i<checks; i++)
179                 {
180                 if (!BN_rand(check,BN_num_bits(a)-1,0,0)) goto err;
181                 j=witness(check,a,ctx,ctx2,mont);
182                 if (j == -1) goto err;
183                 if (j)
184                         {
185                         ret=0;
186                         goto err;
187                         }
188                 if (callback != NULL) callback(1,c2++,cb_arg);
189                 }
190         ret=1;
191 err:
192         ctx->tos--;
193         if ((ctx_passed == NULL) && (ctx != NULL))
194                 BN_CTX_free(ctx);
195         if (ctx2 != NULL)
196                 BN_CTX_free(ctx2);
197         if (mont != NULL) BN_MONT_CTX_free(mont);
198                 
199         return(ret);
200         }
201
202 #define RECP_MUL_MOD
203
204 static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx, BN_CTX *ctx2,
205              BN_MONT_CTX *mont)
206         {
207         int k,i,ret= -1,good;
208         BIGNUM *d,*dd,*tmp,*d1,*d2,*n1;
209         BIGNUM *mont_one,*mont_n1,*mont_a;
210
211         d1= &(ctx->bn[ctx->tos]);
212         d2= &(ctx->bn[ctx->tos+1]);
213         n1= &(ctx->bn[ctx->tos+2]);
214         ctx->tos+=3;
215
216         mont_one= &(ctx2->bn[ctx2->tos]);
217         mont_n1= &(ctx2->bn[ctx2->tos+1]);
218         mont_a= &(ctx2->bn[ctx2->tos+2]);
219         ctx2->tos+=3;
220
221         d=d1;
222         dd=d2;
223         if (!BN_one(d)) goto err;
224         if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */
225         k=BN_num_bits(n1);
226
227         if (!BN_to_montgomery(mont_one,BN_value_one(),mont,ctx2)) goto err;
228         if (!BN_to_montgomery(mont_n1,n1,mont,ctx2)) goto err;
229         if (!BN_to_montgomery(mont_a,a,mont,ctx2)) goto err;
230
231         BN_copy(d,mont_one);
232         for (i=k-1; i>=0; i--)
233                 {
234                 if (    (BN_cmp(d,mont_one) != 0) &&
235                         (BN_cmp(d,mont_n1) != 0))
236                         good=1;
237                 else
238                         good=0;
239
240                 BN_mod_mul_montgomery(dd,d,d,mont,ctx2);
241
242                 if (good && (BN_cmp(dd,mont_one) == 0))
243                         {
244                         ret=1;
245                         goto err;
246                         }
247                 if (BN_is_bit_set(n1,i))
248                         {
249                         BN_mod_mul_montgomery(d,dd,mont_a,mont,ctx2);
250                         }
251                 else
252                         {
253                         tmp=d;
254                         d=dd;
255                         dd=tmp;
256                         }
257                 }
258         if (BN_cmp(d,mont_one) == 0)
259                 i=0;
260         else    i=1;
261         ret=i;
262 err:
263         ctx->tos-=3;
264         ctx2->tos-=3;
265         return(ret);
266         }
267
268 static int probable_prime(BIGNUM *rnd, int bits)
269         {
270         int i;
271         MS_STATIC BN_ULONG mods[NUMPRIMES];
272         BN_ULONG delta,d;
273
274 again:
275         if (!BN_rand(rnd,bits,1,1)) return(0);
276         /* we now have a random number 'rand' to test. */
277         for (i=1; i<NUMPRIMES; i++)
278                 mods[i]=BN_mod_word(rnd,(BN_ULONG)primes[i]);
279         delta=0;
280         loop: for (i=1; i<NUMPRIMES; i++)
281                 {
282                 /* check that rnd is not a prime and also
283                  * that gcd(rnd-1,primes) == 1 (except for 2) */
284                 if (((mods[i]+delta)%primes[i]) <= 1)
285                         {
286                         d=delta;
287                         delta+=2;
288                         /* perhaps need to check for overflow of
289                          * delta (but delta can be upto 2^32)
290                          * 21-May-98 eay - added overflow check */
291                         if (delta < d) goto again;
292                         goto loop;
293                         }
294                 }
295         if (!BN_add_word(rnd,delta)) return(0);
296         return(1);
297         }
298
299 static int probable_prime_dh(BIGNUM *rnd, int bits, BIGNUM *add, BIGNUM *rem,
300              BN_CTX *ctx)
301         {
302         int i,ret=0;
303         BIGNUM *t1;
304
305         t1= &(ctx->bn[ctx->tos++]);
306
307         if (!BN_rand(rnd,bits,0,1)) goto err;
308
309         /* we need ((rnd-rem) % add) == 0 */
310
311         if (!BN_mod(t1,rnd,add,ctx)) goto err;
312         if (!BN_sub(rnd,rnd,t1)) goto err;
313         if (rem == NULL)
314                 { if (!BN_add_word(rnd,1)) goto err; }
315         else
316                 { if (!BN_add(rnd,rnd,rem)) goto err; }
317
318         /* we now have a random number 'rand' to test. */
319
320         loop: for (i=1; i<NUMPRIMES; i++)
321                 {
322                 /* check that rnd is a prime */
323                 if (BN_mod_word(rnd,(BN_ULONG)primes[i]) <= 1)
324                         {
325                         if (!BN_add(rnd,rnd,add)) goto err;
326                         goto loop;
327                         }
328                 }
329         ret=1;
330 err:
331         ctx->tos--;
332         return(ret);
333         }
334
335 static int probable_prime_dh_safe(BIGNUM *p, int bits, BIGNUM *padd,
336              BIGNUM *rem, BN_CTX *ctx)
337         {
338         int i,ret=0;
339         BIGNUM *t1,*qadd=NULL,*q=NULL;
340
341         bits--;
342         t1= &(ctx->bn[ctx->tos++]);
343         q= &(ctx->bn[ctx->tos++]);
344         qadd= &(ctx->bn[ctx->tos++]);
345
346         if (!BN_rshift1(qadd,padd)) goto err;
347                 
348         if (!BN_rand(q,bits,0,1)) goto err;
349
350         /* we need ((rnd-rem) % add) == 0 */
351         if (!BN_mod(t1,q,qadd,ctx)) goto err;
352         if (!BN_sub(q,q,t1)) goto err;
353         if (rem == NULL)
354                 { if (!BN_add_word(q,1)) goto err; }
355         else
356                 {
357                 if (!BN_rshift1(t1,rem)) goto err;
358                 if (!BN_add(q,q,t1)) goto err;
359                 }
360
361         /* we now have a random number 'rand' to test. */
362         if (!BN_lshift1(p,q)) goto err;
363         if (!BN_add_word(p,1)) goto err;
364
365         loop: for (i=1; i<NUMPRIMES; i++)
366                 {
367                 /* check that p and q are prime */
368                 /* check that for p and q
369                  * gcd(p-1,primes) == 1 (except for 2) */
370                 if (    (BN_mod_word(p,(BN_ULONG)primes[i]) == 0) ||
371                         (BN_mod_word(q,(BN_ULONG)primes[i]) == 0))
372                         {
373                         if (!BN_add(p,p,padd)) goto err;
374                         if (!BN_add(q,q,qadd)) goto err;
375                         goto loop;
376                         }
377                 }
378         ret=1;
379 err:
380         ctx->tos-=3;
381         return(ret);
382         }
383
384 #if 0
385 static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx)
386         {
387         int k,i,nb,ret= -1;
388         BIGNUM *d,*dd,*tmp;
389         BIGNUM *d1,*d2,*x,*n1,*inv;
390
391         d1= &(ctx->bn[ctx->tos]);
392         d2= &(ctx->bn[ctx->tos+1]);
393         x=  &(ctx->bn[ctx->tos+2]);
394         n1= &(ctx->bn[ctx->tos+3]);
395         inv=&(ctx->bn[ctx->tos+4]);
396         ctx->tos+=5;
397
398         d=d1;
399         dd=d2;
400         if (!BN_one(d)) goto err;
401         if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */
402         k=BN_num_bits(n1);
403
404         /* i=BN_num_bits(n); */
405 #ifdef RECP_MUL_MOD
406         nb=BN_reciprocal(inv,n,ctx); /**/
407         if (nb == -1) goto err;
408 #endif
409
410         for (i=k-1; i>=0; i--)
411                 {
412                 if (BN_copy(x,d) == NULL) goto err;
413 #ifndef RECP_MUL_MOD
414                 if (!BN_mod_mul(dd,d,d,n,ctx)) goto err;
415 #else
416                 if (!BN_mod_mul_reciprocal(dd,d,d,n,inv,nb,ctx)) goto err;
417 #endif
418                 if (    BN_is_one(dd) &&
419                         !BN_is_one(x) &&
420                         (BN_cmp(x,n1) != 0))
421                         {
422                         ret=1;
423                         goto err;
424                         }
425                 if (BN_is_bit_set(n1,i))
426                         {
427 #ifndef RECP_MUL_MOD
428                         if (!BN_mod_mul(d,dd,a,n,ctx)) goto err;
429 #else
430                         if (!BN_mod_mul_reciprocal(d,dd,a,n,inv,nb,ctx)) goto err; 
431 #endif
432                         }
433                 else
434                         {
435                         tmp=d;
436                         d=dd;
437                         dd=tmp;
438                         }
439                 }
440         if (BN_is_one(d))
441                 i=0;
442         else    i=1;
443         ret=i;
444 err:
445         ctx->tos-=5;
446         return(ret);
447         }
448 #endif