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 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. 60 * 61 * Redistribution and use in source and binary forms, with or without 62 * modification, are permitted provided that the following conditions 63 * are met: 64 * 65 * 1. Redistributions of source code must retain the above copyright 66 * notice, this list of conditions and the following disclaimer. 67 * 68 * 2. Redistributions in binary form must reproduce the above copyright 69 * notice, this list of conditions and the following disclaimer in 70 * the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3. All advertising materials mentioning features or use of this 74 * software must display the following acknowledgment: 75 * "This product includes software developed by the OpenSSL Project 76 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 77 * 78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 79 * endorse or promote products derived from this software without 80 * prior written permission. For written permission, please contact 81 * openssl-core@openssl.org. 82 * 83 * 5. Products derived from this software may not be called "OpenSSL" 84 * nor may "OpenSSL" appear in their names without prior written 85 * permission of the OpenSSL Project. 86 * 87 * 6. Redistributions of any form whatsoever must retain the following 88 * acknowledgment: 89 * "This product includes software developed by the OpenSSL Project 90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 95 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 103 * OF THE POSSIBILITY OF SUCH DAMAGE. 104 * ==================================================================== 105 * 106 * This product includes cryptographic software written by Eric Young 107 * (eay@cryptsoft.com). This product includes software written by Tim 108 * Hudson (tjh@cryptsoft.com). 109 * 110 */ 111 112 #include <stdio.h> 113 #include <time.h> 114 #include "cryptlib.h" 115 #include "bn_lcl.h" 116 #include <openssl/rand.h> 117 118 /* The quick sieve algorithm approach to weeding out primes is 119 * Philip Zimmermann's, as implemented in PGP. I have had a read of 120 * his comments and implemented my own version. 121 */ 122 #include "bn_prime.h" 123 124 static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, 125 const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont); 126 static int probable_prime(BIGNUM *rnd, int bits); 127 static int probable_prime_dh(BIGNUM *rnd, int bits, 128 BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); 129 static int probable_prime_dh_safe(BIGNUM *rnd, int bits, 130 BIGNUM *add, BIGNUM *rem, BN_CTX *ctx); 131 132 BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe, BIGNUM *add, 133 BIGNUM *rem, void (*callback)(int,int,void *), void *cb_arg) 134 { 135 BIGNUM *rnd=NULL; 136 BIGNUM t; 137 int found=0; 138 int i,j,c1=0; 139 BN_CTX *ctx; 140 int checks = BN_prime_checks_for_size(bits); 141 142 ctx=BN_CTX_new(); 143 if (ctx == NULL) goto err; 144 if (ret == NULL) 145 { 146 if ((rnd=BN_new()) == NULL) goto err; 147 } 148 else 149 rnd=ret; 150 BN_init(&t); 151 loop: 152 /* make a random number and set the top and bottom bits */ 153 if (add == NULL) 154 { 155 if (!probable_prime(rnd,bits)) goto err; 156 } 157 else 158 { 159 if (safe) 160 { 161 if (!probable_prime_dh_safe(rnd,bits,add,rem,ctx)) 162 goto err; 163 } 164 else 165 { 166 if (!probable_prime_dh(rnd,bits,add,rem,ctx)) 167 goto err; 168 } 169 } 170 /* if (BN_mod_word(rnd,(BN_ULONG)3) == 1) goto loop; */ 171 if (callback != NULL) callback(0,c1++,cb_arg); 172 173 if (!safe) 174 { 175 i=BN_is_prime_fasttest(rnd,checks,callback,ctx,cb_arg,0); 176 if (i == -1) goto err; 177 if (i == 0) goto loop; 178 } 179 else 180 { 181 /* for "safe prime" generation, 182 * check that (p-1)/2 is prime. 183 * Since a prime is odd, We just 184 * need to divide by 2 */ 185 if (!BN_rshift1(&t,rnd)) goto err; 186 187 for (i=0; i<checks; i++) 188 { 189 j=BN_is_prime_fasttest(rnd,1,callback,ctx,cb_arg,0); 190 if (j == -1) goto err; 191 if (j == 0) goto loop; 192 193 j=BN_is_prime_fasttest(&t,1,callback,ctx,cb_arg,0); 194 if (j == -1) goto err; 195 if (j == 0) goto loop; 196 197 if (callback != NULL) callback(2,c1-1,cb_arg); 198 /* We have a safe prime test pass */ 199 } 200 } 201 /* we have a prime :-) */ 202 found = 1; 203 err: 204 if (!found && (ret == NULL) && (rnd != NULL)) BN_free(rnd); 205 BN_free(&t); 206 if (ctx != NULL) BN_CTX_free(ctx); 207 return(found ? rnd : NULL); 208 } 209 210 int BN_is_prime(const BIGNUM *a, int checks, void (*callback)(int,int,void *), 211 BN_CTX *ctx_passed, void *cb_arg) 212 { 213 return BN_is_prime_fasttest(a, checks, callback, ctx_passed, cb_arg, 0); 214 } 215 216 int BN_is_prime_fasttest(const BIGNUM *a, int checks, 217 void (*callback)(int,int,void *), 218 BN_CTX *ctx_passed, void *cb_arg, 219 int do_trial_division) 220 { 221 int i, j, ret = -1; 222 int k; 223 BN_CTX *ctx = NULL; 224 BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ 225 BN_MONT_CTX *mont = NULL; 226 const BIGNUM *A = NULL; 227 228 if (checks == BN_prime_checks) 229 checks = BN_prime_checks_for_size(BN_num_bits(a)); 230 231 /* first look for small factors */ 232 if (!BN_is_odd(a)) 233 return(0); 234 if (do_trial_division) 235 { 236 for (i = 1; i < NUMPRIMES; i++) 237 if (BN_mod_word(a, primes[i]) == 0) 238 return 0; 239 if (callback != NULL) callback(1, -1, cb_arg); 240 } 241 242 if (ctx_passed != NULL) 243 ctx = ctx_passed; 244 else 245 if ((ctx=BN_CTX_new()) == NULL) 246 goto err; 247 BN_CTX_start(ctx); 248 249 /* A := abs(a) */ 250 if (a->neg) 251 { 252 BIGNUM *t; 253 if ((t = BN_CTX_get(ctx)) == NULL) goto err; 254 BN_copy(t, a); 255 t->neg = 0; 256 A = t; 257 } 258 else 259 A = a; 260 A1 = BN_CTX_get(ctx); 261 A1_odd = BN_CTX_get(ctx); 262 check = BN_CTX_get(ctx); 263 if (check == NULL) goto err; 264 265 /* compute A1 := A - 1 */ 266 if (!BN_copy(A1, A)) 267 goto err; 268 if (!BN_sub_word(A1, 1)) 269 goto err; 270 if (BN_is_zero(A1)) 271 { 272 ret = 0; 273 goto err; 274 } 275 276 /* write A1 as A1_odd * 2^k */ 277 k = 1; 278 while (!BN_is_bit_set(A1, k)) 279 k++; 280 if (!BN_rshift(A1_odd, A1, k)) 281 goto err; 282 283 /* Montgomery setup for computations mod A */ 284 mont = BN_MONT_CTX_new(); 285 if (mont == NULL) 286 goto err; 287 if (!BN_MONT_CTX_set(mont, A, ctx)) 288 goto err; 289 290 for (i = 0; i < checks; i++) 291 { 292 if (!BN_pseudo_rand(check, BN_num_bits(A1), 0, 0)) 293 goto err; 294 if (BN_cmp(check, A1) >= 0) 295 if (!BN_sub(check, check, A1)) 296 goto err; 297 if (!BN_add_word(check, 1)) 298 goto err; 299 /* now 1 <= check < A */ 300 301 j = witness(check, A, A1, A1_odd, k, ctx, mont); 302 if (j == -1) goto err; 303 if (j) 304 { 305 ret=0; 306 goto err; 307 } 308 if (callback != NULL) callback(1,i,cb_arg); 309 } 310 ret=1; 311 err: 312 if (ctx != NULL) 313 { 314 BN_CTX_end(ctx); 315 if (ctx_passed == NULL) 316 BN_CTX_free(ctx); 317 } 318 if (mont != NULL) 319 BN_MONT_CTX_free(mont); 320 321 return(ret); 322 } 323 324 static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1, 325 const BIGNUM *a1_odd, int k, BN_CTX *ctx, BN_MONT_CTX *mont) 326 { 327 if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */ 328 return -1; 329 if (BN_is_one(w)) 330 return 0; /* probably prime */ 331 if (BN_cmp(w, a1) == 0) 332 return 0; /* w == -1 (mod a), 'a' is probably prime */ 333 while (--k) 334 { 335 if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */ 336 return -1; 337 if (BN_is_one(w)) 338 return 1; /* 'a' is composite, otherwise a previous 'w' would 339 * have been == -1 (mod 'a') */ 340 if (BN_cmp(w, a1) == 0) 341 return 0; /* w == -1 (mod a), 'a' is probably prime */ 342 } 343 /* If we get here, 'w' is the (a-1)/2-th power of the original 'w', 344 * and it is neither -1 nor +1 -- so 'a' cannot be prime */ 345 return 1; 346 } 347 348 static int probable_prime(BIGNUM *rnd, int bits) 349 { 350 int i; 351 BN_ULONG mods[NUMPRIMES]; 352 BN_ULONG delta,d; 353 354 again: 355 if (!BN_rand(rnd,bits,1,1)) return(0); 356 /* we now have a random number 'rand' to test. */ 357 for (i=1; i<NUMPRIMES; i++) 358 mods[i]=BN_mod_word(rnd,(BN_ULONG)primes[i]); 359 delta=0; 360 loop: for (i=1; i<NUMPRIMES; i++) 361 { 362 /* check that rnd is not a prime and also 363 * that gcd(rnd-1,primes) == 1 (except for 2) */ 364 if (((mods[i]+delta)%primes[i]) <= 1) 365 { 366 d=delta; 367 delta+=2; 368 /* perhaps need to check for overflow of 369 * delta (but delta can be up to 2^32) 370 * 21-May-98 eay - added overflow check */ 371 if (delta < d) goto again; 372 goto loop; 373 } 374 } 375 if (!BN_add_word(rnd,delta)) return(0); 376 return(1); 377 } 378 379 static int probable_prime_dh(BIGNUM *rnd, int bits, BIGNUM *add, BIGNUM *rem, 380 BN_CTX *ctx) 381 { 382 int i,ret=0; 383 BIGNUM *t1; 384 385 BN_CTX_start(ctx); 386 if ((t1 = BN_CTX_get(ctx)) == NULL) goto err; 387 388 if (!BN_rand(rnd,bits,0,1)) goto err; 389 390 /* we need ((rnd-rem) % add) == 0 */ 391 392 if (!BN_mod(t1,rnd,add,ctx)) goto err; 393 if (!BN_sub(rnd,rnd,t1)) goto err; 394 if (rem == NULL) 395 { if (!BN_add_word(rnd,1)) goto err; } 396 else 397 { if (!BN_add(rnd,rnd,rem)) goto err; } 398 399 /* we now have a random number 'rand' to test. */ 400 401 loop: for (i=1; i<NUMPRIMES; i++) 402 { 403 /* check that rnd is a prime */ 404 if (BN_mod_word(rnd,(BN_ULONG)primes[i]) <= 1) 405 { 406 if (!BN_add(rnd,rnd,add)) goto err; 407 goto loop; 408 } 409 } 410 ret=1; 411 err: 412 BN_CTX_end(ctx); 413 return(ret); 414 } 415 416 static int probable_prime_dh_safe(BIGNUM *p, int bits, BIGNUM *padd, 417 BIGNUM *rem, BN_CTX *ctx) 418 { 419 int i,ret=0; 420 BIGNUM *t1,*qadd,*q; 421 422 bits--; 423 BN_CTX_start(ctx); 424 t1 = BN_CTX_get(ctx); 425 q = BN_CTX_get(ctx); 426 qadd = BN_CTX_get(ctx); 427 if (qadd == NULL) goto err; 428 429 if (!BN_rshift1(qadd,padd)) goto err; 430 431 if (!BN_rand(q,bits,0,1)) goto err; 432 433 /* we need ((rnd-rem) % add) == 0 */ 434 if (!BN_mod(t1,q,qadd,ctx)) goto err; 435 if (!BN_sub(q,q,t1)) goto err; 436 if (rem == NULL) 437 { if (!BN_add_word(q,1)) goto err; } 438 else 439 { 440 if (!BN_rshift1(t1,rem)) goto err; 441 if (!BN_add(q,q,t1)) goto err; 442 } 443 444 /* we now have a random number 'rand' to test. */ 445 if (!BN_lshift1(p,q)) goto err; 446 if (!BN_add_word(p,1)) goto err; 447 448 loop: for (i=1; i<NUMPRIMES; i++) 449 { 450 /* check that p and q are prime */ 451 /* check that for p and q 452 * gcd(p-1,primes) == 1 (except for 2) */ 453 if ( (BN_mod_word(p,(BN_ULONG)primes[i]) == 0) || 454 (BN_mod_word(q,(BN_ULONG)primes[i]) == 0)) 455 { 456 if (!BN_add(p,p,padd)) goto err; 457 if (!BN_add(q,q,qadd)) goto err; 458 goto loop; 459 } 460 } 461 ret=1; 462 err: 463 BN_CTX_end(ctx); 464 return(ret); 465 } 466