summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_prime.c
diff options
context:
space:
mode:
authorryker <>1998-10-05 20:13:14 +0000
committerryker <>1998-10-05 20:13:14 +0000
commitaeeae06a79815dc190061534d47236cec09f9e32 (patch)
tree851692b9c2f9c04f077666855641900f19fdb217 /src/lib/libcrypto/bn/bn_prime.c
parenta4f79641824cbf9f60ca9d1168d1fcc46717a82a (diff)
downloadopenbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.gz
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.tar.bz2
openbsd-aeeae06a79815dc190061534d47236cec09f9e32.zip
Import of SSLeay-0.9.0b with RSA and IDEA stubbed + OpenBSD build
functionality for shared libs. Note that routines such as sslv2_init and friends that use RSA will not work due to lack of RSA in this library. Needs documentation and help from ports for easy upgrade to full functionality where legally possible.
Diffstat (limited to 'src/lib/libcrypto/bn/bn_prime.c')
-rw-r--r--src/lib/libcrypto/bn/bn_prime.c473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/lib/libcrypto/bn/bn_prime.c b/src/lib/libcrypto/bn/bn_prime.c
new file mode 100644
index 0000000000..0c85f70b59
--- /dev/null
+++ b/src/lib/libcrypto/bn/bn_prime.c
@@ -0,0 +1,473 @@
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 "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#ifndef NOPROTO
72static int witness(BIGNUM *a, BIGNUM *n, BN_CTX *ctx,BN_CTX *ctx2,
73 BN_MONT_CTX *mont);
74static int probable_prime(BIGNUM *rnd, int bits);
75static int probable_prime_dh(BIGNUM *rnd, int bits,
76 BIGNUM *add, BIGNUM *rem, BN_CTX *ctx);
77static int probable_prime_dh_strong(BIGNUM *rnd, int bits,
78 BIGNUM *add, BIGNUM *rem, BN_CTX *ctx);
79#else
80static int witness();
81static int probable_prime();
82static int probable_prime_dh();
83static int probable_prime_dh_strong();
84#endif
85
86BIGNUM *BN_generate_prime(bits,strong,add,rem,callback,cb_arg)
87int bits;
88int strong;
89BIGNUM *add;
90BIGNUM *rem;
91void (*callback)(P_I_I_P);
92char *cb_arg;
93 {
94 BIGNUM *rnd=NULL;
95 BIGNUM *ret=NULL;
96 BIGNUM *t=NULL;
97 int i,j,c1=0;
98 BN_CTX *ctx;
99
100 ctx=BN_CTX_new();
101 if (ctx == NULL) goto err;
102 if ((rnd=BN_new()) == NULL) goto err;
103 if (strong)
104 if ((t=BN_new()) == NULL) goto err;
105loop:
106 /* make a random number and set the top and bottom bits */
107 if (add == NULL)
108 {
109 if (!probable_prime(rnd,bits)) goto err;
110 }
111 else
112 {
113 if (strong)
114 {
115 if (!probable_prime_dh_strong(rnd,bits,add,rem,ctx))
116 goto err;
117 }
118 else
119 {
120 if (!probable_prime_dh(rnd,bits,add,rem,ctx))
121 goto err;
122 }
123 }
124 /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */
125 if (callback != NULL) callback(0,c1++,cb_arg);
126
127 if (!strong)
128 {
129 i=BN_is_prime(rnd,BN_prime_checks,callback,ctx,cb_arg);
130 if (i == -1) goto err;
131 if (i == 0) goto loop;
132 }
133 else
134 {
135 /* for a strong prime generation,
136 * check that (p-1)/2 is prime.
137 * Since a prime is odd, We just
138 * need to divide by 2 */
139 if (!BN_rshift1(t,rnd)) goto err;
140
141 for (i=0; i<BN_prime_checks; i++)
142 {
143 j=BN_is_prime(rnd,1,callback,ctx,cb_arg);
144 if (j == -1) goto err;
145 if (j == 0) goto loop;
146
147 j=BN_is_prime(t,1,callback,ctx,cb_arg);
148 if (j == -1) goto err;
149 if (j == 0) goto loop;
150
151 if (callback != NULL) callback(2,c1-1,cb_arg);
152 /* We have a strong prime test pass */
153 }
154 }
155 /* we have a prime :-) */
156 ret=rnd;
157err:
158 if ((ret == NULL) && (rnd != NULL)) BN_free(rnd);
159 if (t != NULL) BN_free(t);
160 if (ctx != NULL) BN_CTX_free(ctx);
161 return(ret);
162 }
163
164int BN_is_prime(a,checks,callback,ctx_passed,cb_arg)
165BIGNUM *a;
166int checks;
167void (*callback)(P_I_I_P);
168BN_CTX *ctx_passed;
169char *cb_arg;
170 {
171 int i,j,c2=0,ret= -1;
172 BIGNUM *check;
173 BN_CTX *ctx=NULL,*ctx2=NULL;
174 BN_MONT_CTX *mont=NULL;
175
176 if (!BN_is_odd(a))
177 return(0);
178 if (ctx_passed != NULL)
179 ctx=ctx_passed;
180 else
181 if ((ctx=BN_CTX_new()) == NULL) goto err;
182
183 if ((ctx2=BN_CTX_new()) == NULL) goto err;
184 if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
185
186 check=ctx->bn[ctx->tos++];
187
188 /* Setup the montgomery structure */
189 if (!BN_MONT_CTX_set(mont,a,ctx2)) goto err;
190
191 for (i=0; i<checks; i++)
192 {
193 if (!BN_rand(check,BN_num_bits(a)-1,0,0)) goto err;
194 j=witness(check,a,ctx,ctx2,mont);
195 if (j == -1) goto err;
196 if (j)
197 {
198 ret=0;
199 goto err;
200 }
201 if (callback != NULL) callback(1,c2++,cb_arg);
202 }
203 ret=1;
204err:
205 ctx->tos--;
206 if ((ctx_passed == NULL) && (ctx != NULL))
207 BN_CTX_free(ctx);
208 if (ctx2 != NULL)
209 BN_CTX_free(ctx2);
210 if (mont != NULL) BN_MONT_CTX_free(mont);
211
212 return(ret);
213 }
214
215#define RECP_MUL_MOD
216
217static int witness(a,n,ctx,ctx2,mont)
218BIGNUM *a;
219BIGNUM *n;
220BN_CTX *ctx,*ctx2;
221BN_MONT_CTX *mont;
222 {
223 int k,i,ret= -1,good;
224 BIGNUM *d,*dd,*tmp,*d1,*d2,*n1;
225 BIGNUM *mont_one,*mont_n1,*mont_a;
226
227 d1=ctx->bn[ctx->tos];
228 d2=ctx->bn[ctx->tos+1];
229 n1=ctx->bn[ctx->tos+2];
230 ctx->tos+=3;
231
232 mont_one=ctx2->bn[ctx2->tos];
233 mont_n1=ctx2->bn[ctx2->tos+1];
234 mont_a=ctx2->bn[ctx2->tos+2];
235 ctx2->tos+=3;
236
237 d=d1;
238 dd=d2;
239 if (!BN_one(d)) goto err;
240 if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */
241 k=BN_num_bits(n1);
242
243 if (!BN_to_montgomery(mont_one,BN_value_one(),mont,ctx2)) goto err;
244 if (!BN_to_montgomery(mont_n1,n1,mont,ctx2)) goto err;
245 if (!BN_to_montgomery(mont_a,a,mont,ctx2)) goto err;
246
247 BN_copy(d,mont_one);
248 for (i=k-1; i>=0; i--)
249 {
250 if ( (BN_cmp(d,mont_one) != 0) &&
251 (BN_cmp(d,mont_n1) != 0))
252 good=1;
253 else
254 good=0;
255
256 BN_mod_mul_montgomery(dd,d,d,mont,ctx2);
257
258 if (good && (BN_cmp(dd,mont_one) == 0))
259 {
260 ret=1;
261 goto err;
262 }
263 if (BN_is_bit_set(n1,i))
264 {
265 BN_mod_mul_montgomery(d,dd,mont_a,mont,ctx2);
266 }
267 else
268 {
269 tmp=d;
270 d=dd;
271 dd=tmp;
272 }
273 }
274 if (BN_cmp(d,mont_one) == 0)
275 i=0;
276 else i=1;
277 ret=i;
278err:
279 ctx->tos-=3;
280 ctx2->tos-=3;
281 return(ret);
282 }
283
284static int probable_prime(rnd, bits)
285BIGNUM *rnd;
286int bits;
287 {
288 int i;
289 MS_STATIC BN_ULONG mods[NUMPRIMES];
290 BN_ULONG delta;
291
292 if (!BN_rand(rnd,bits,1,1)) return(0);
293 /* we now have a random number 'rand' to test. */
294 for (i=1; i<NUMPRIMES; i++)
295 mods[i]=BN_mod_word(rnd,(BN_ULONG)primes[i]);
296 delta=0;
297 loop: for (i=1; i<NUMPRIMES; i++)
298 {
299 /* check that rnd is not a prime and also
300 * that gcd(rnd-1,primes) == 1 (except for 2) */
301 if (((mods[i]+delta)%primes[i]) <= 1)
302 {
303 delta+=2;
304 /* perhaps need to check for overflow of
305 * delta (but delta can be upto 2^32) */
306 goto loop;
307 }
308 }
309 if (!BN_add_word(rnd,delta)) return(0);
310 return(1);
311 }
312
313static int probable_prime_dh(rnd, bits, add, rem,ctx)
314BIGNUM *rnd;
315int bits;
316BIGNUM *add;
317BIGNUM *rem;
318BN_CTX *ctx;
319 {
320 int i,ret=0;
321 BIGNUM *t1;
322
323 t1=ctx->bn[ctx->tos++];
324
325 if (!BN_rand(rnd,bits,0,1)) goto err;
326
327 /* we need ((rnd-rem) % add) == 0 */
328
329 if (!BN_mod(t1,rnd,add,ctx)) goto err;
330 if (!BN_sub(rnd,rnd,t1)) goto err;
331 if (rem == NULL)
332 { if (!BN_add_word(rnd,1)) goto err; }
333 else
334 { if (!BN_add(rnd,rnd,rem)) goto err; }
335
336 /* we now have a random number 'rand' to test. */
337
338 loop: for (i=1; i<NUMPRIMES; i++)
339 {
340 /* check that rnd is a prime */
341 if (BN_mod_word(rnd,(BN_LONG)primes[i]) <= 1)
342 {
343 if (!BN_add(rnd,rnd,add)) goto err;
344 goto loop;
345 }
346 }
347 ret=1;
348err:
349 ctx->tos--;
350 return(ret);
351 }
352
353static int probable_prime_dh_strong(p, bits, padd, rem,ctx)
354BIGNUM *p;
355int bits;
356BIGNUM *padd;
357BIGNUM *rem;
358BN_CTX *ctx;
359 {
360 int i,ret=0;
361 BIGNUM *t1,*qadd=NULL,*q=NULL;
362
363 bits--;
364 t1=ctx->bn[ctx->tos++];
365 q=ctx->bn[ctx->tos++];
366 qadd=ctx->bn[ctx->tos++];
367
368 if (!BN_rshift1(qadd,padd)) goto err;
369
370 if (!BN_rand(q,bits,0,1)) goto err;
371
372 /* we need ((rnd-rem) % add) == 0 */
373 if (!BN_mod(t1,q,qadd,ctx)) goto err;
374 if (!BN_sub(q,q,t1)) goto err;
375 if (rem == NULL)
376 { if (!BN_add_word(q,1)) goto err; }
377 else
378 {
379 if (!BN_rshift1(t1,rem)) goto err;
380 if (!BN_add(q,q,t1)) goto err;
381 }
382
383 /* we now have a random number 'rand' to test. */
384 if (!BN_lshift1(p,q)) goto err;
385 if (!BN_add_word(p,1)) goto err;
386
387 loop: for (i=1; i<NUMPRIMES; i++)
388 {
389 /* check that p and q are prime */
390 /* check that for p and q
391 * gcd(p-1,primes) == 1 (except for 2) */
392 if ( (BN_mod_word(p,(BN_LONG)primes[i]) == 0) ||
393 (BN_mod_word(q,(BN_LONG)primes[i]) == 0))
394 {
395 if (!BN_add(p,p,padd)) goto err;
396 if (!BN_add(q,q,qadd)) goto err;
397 goto loop;
398 }
399 }
400 ret=1;
401err:
402 ctx->tos-=3;
403 return(ret);
404 }
405
406#if 0
407static int witness(a, n,ctx)
408BIGNUM *a;
409BIGNUM *n;
410BN_CTX *ctx;
411 {
412 int k,i,nb,ret= -1;
413 BIGNUM *d,*dd,*tmp;
414 BIGNUM *d1,*d2,*x,*n1,*inv;
415
416 d1=ctx->bn[ctx->tos];
417 d2=ctx->bn[ctx->tos+1];
418 x=ctx->bn[ctx->tos+2];
419 n1=ctx->bn[ctx->tos+3];
420 inv=ctx->bn[ctx->tos+4];
421 ctx->tos+=5;
422
423 d=d1;
424 dd=d2;
425 if (!BN_one(d)) goto err;
426 if (!BN_sub(n1,n,d)) goto err; /* n1=n-1; */
427 k=BN_num_bits(n1);
428
429 /* i=BN_num_bits(n); */
430#ifdef RECP_MUL_MOD
431 nb=BN_reciprocal(inv,n,ctx); /**/
432 if (nb == -1) goto err;
433#endif
434
435 for (i=k-1; i>=0; i--)
436 {
437 if (BN_copy(x,d) == NULL) goto err;
438#ifndef RECP_MUL_MOD
439 if (!BN_mod_mul(dd,d,d,n,ctx)) goto err;
440#else
441 if (!BN_mod_mul_reciprocal(dd,d,d,n,inv,nb,ctx)) goto err;
442#endif
443 if ( BN_is_one(dd) &&
444 !BN_is_one(x) &&
445 (BN_cmp(x,n1) != 0))
446 {
447 ret=1;
448 goto err;
449 }
450 if (BN_is_bit_set(n1,i))
451 {
452#ifndef RECP_MUL_MOD
453 if (!BN_mod_mul(d,dd,a,n,ctx)) goto err;
454#else
455 if (!BN_mod_mul_reciprocal(d,dd,a,n,inv,nb,ctx)) goto err;
456#endif
457 }
458 else
459 {
460 tmp=d;
461 d=dd;
462 dd=tmp;
463 }
464 }
465 if (BN_is_one(d))
466 i=0;
467 else i=1;
468 ret=i;
469err:
470 ctx->tos-=5;
471 return(ret);
472 }
473#endif