xref: /openbsd-src/lib/libcrypto/bn/bn_prime.c (revision 050d837a6cf064b603a4b238874fb149634381d3)
1*050d837aStb /* $OpenBSD: bn_prime.c,v 1.34 2023/07/20 06:26:27 tb Exp $ */
25b37fcf3Sryker /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
35b37fcf3Sryker  * All rights reserved.
45b37fcf3Sryker  *
55b37fcf3Sryker  * This package is an SSL implementation written
65b37fcf3Sryker  * by Eric Young (eay@cryptsoft.com).
75b37fcf3Sryker  * The implementation was written so as to conform with Netscapes SSL.
85b37fcf3Sryker  *
95b37fcf3Sryker  * This library is free for commercial and non-commercial use as long as
105b37fcf3Sryker  * the following conditions are aheared to.  The following conditions
115b37fcf3Sryker  * apply to all code found in this distribution, be it the RC4, RSA,
125b37fcf3Sryker  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
135b37fcf3Sryker  * included with this distribution is covered by the same copyright terms
145b37fcf3Sryker  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
155b37fcf3Sryker  *
165b37fcf3Sryker  * Copyright remains Eric Young's, and as such any Copyright notices in
175b37fcf3Sryker  * the code are not to be removed.
185b37fcf3Sryker  * If this package is used in a product, Eric Young should be given attribution
195b37fcf3Sryker  * as the author of the parts of the library used.
205b37fcf3Sryker  * This can be in the form of a textual message at program startup or
215b37fcf3Sryker  * in documentation (online or textual) provided with the package.
225b37fcf3Sryker  *
235b37fcf3Sryker  * Redistribution and use in source and binary forms, with or without
245b37fcf3Sryker  * modification, are permitted provided that the following conditions
255b37fcf3Sryker  * are met:
265b37fcf3Sryker  * 1. Redistributions of source code must retain the copyright
275b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer.
285b37fcf3Sryker  * 2. Redistributions in binary form must reproduce the above copyright
295b37fcf3Sryker  *    notice, this list of conditions and the following disclaimer in the
305b37fcf3Sryker  *    documentation and/or other materials provided with the distribution.
315b37fcf3Sryker  * 3. All advertising materials mentioning features or use of this software
325b37fcf3Sryker  *    must display the following acknowledgement:
335b37fcf3Sryker  *    "This product includes cryptographic software written by
345b37fcf3Sryker  *     Eric Young (eay@cryptsoft.com)"
355b37fcf3Sryker  *    The word 'cryptographic' can be left out if the rouines from the library
365b37fcf3Sryker  *    being used are not cryptographic related :-).
375b37fcf3Sryker  * 4. If you include any Windows specific code (or a derivative thereof) from
385b37fcf3Sryker  *    the apps directory (application code) you must include an acknowledgement:
395b37fcf3Sryker  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
405b37fcf3Sryker  *
415b37fcf3Sryker  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
425b37fcf3Sryker  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
435b37fcf3Sryker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
445b37fcf3Sryker  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
455b37fcf3Sryker  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
465b37fcf3Sryker  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
475b37fcf3Sryker  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485b37fcf3Sryker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495b37fcf3Sryker  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
505b37fcf3Sryker  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
515b37fcf3Sryker  * SUCH DAMAGE.
525b37fcf3Sryker  *
535b37fcf3Sryker  * The licence and distribution terms for any publically available version or
545b37fcf3Sryker  * derivative of this code cannot be changed.  i.e. this code cannot simply be
555b37fcf3Sryker  * copied and put under another distribution licence
565b37fcf3Sryker  * [including the GNU Public Licence.]
575b37fcf3Sryker  */
58ba5406e9Sbeck /* ====================================================================
59da347917Sbeck  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60ba5406e9Sbeck  *
61ba5406e9Sbeck  * Redistribution and use in source and binary forms, with or without
62ba5406e9Sbeck  * modification, are permitted provided that the following conditions
63ba5406e9Sbeck  * are met:
64ba5406e9Sbeck  *
65ba5406e9Sbeck  * 1. Redistributions of source code must retain the above copyright
66ba5406e9Sbeck  *    notice, this list of conditions and the following disclaimer.
67ba5406e9Sbeck  *
68ba5406e9Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
69ba5406e9Sbeck  *    notice, this list of conditions and the following disclaimer in
70ba5406e9Sbeck  *    the documentation and/or other materials provided with the
71ba5406e9Sbeck  *    distribution.
72ba5406e9Sbeck  *
73ba5406e9Sbeck  * 3. All advertising materials mentioning features or use of this
74ba5406e9Sbeck  *    software must display the following acknowledgment:
75ba5406e9Sbeck  *    "This product includes software developed by the OpenSSL Project
76ba5406e9Sbeck  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77ba5406e9Sbeck  *
78ba5406e9Sbeck  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79ba5406e9Sbeck  *    endorse or promote products derived from this software without
80ba5406e9Sbeck  *    prior written permission. For written permission, please contact
81ba5406e9Sbeck  *    openssl-core@openssl.org.
82ba5406e9Sbeck  *
83ba5406e9Sbeck  * 5. Products derived from this software may not be called "OpenSSL"
84ba5406e9Sbeck  *    nor may "OpenSSL" appear in their names without prior written
85ba5406e9Sbeck  *    permission of the OpenSSL Project.
86ba5406e9Sbeck  *
87ba5406e9Sbeck  * 6. Redistributions of any form whatsoever must retain the following
88ba5406e9Sbeck  *    acknowledgment:
89ba5406e9Sbeck  *    "This product includes software developed by the OpenSSL Project
90ba5406e9Sbeck  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91ba5406e9Sbeck  *
92ba5406e9Sbeck  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93ba5406e9Sbeck  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94ba5406e9Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95ba5406e9Sbeck  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96ba5406e9Sbeck  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97ba5406e9Sbeck  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98ba5406e9Sbeck  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99ba5406e9Sbeck  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100ba5406e9Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101ba5406e9Sbeck  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102ba5406e9Sbeck  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103ba5406e9Sbeck  * OF THE POSSIBILITY OF SUCH DAMAGE.
104ba5406e9Sbeck  * ====================================================================
105ba5406e9Sbeck  *
106ba5406e9Sbeck  * This product includes cryptographic software written by Eric Young
107ba5406e9Sbeck  * (eay@cryptsoft.com).  This product includes software written by Tim
108ba5406e9Sbeck  * Hudson (tjh@cryptsoft.com).
109ba5406e9Sbeck  *
110ba5406e9Sbeck  */
1115b37fcf3Sryker 
1125b37fcf3Sryker #include <stdio.h>
1135b37fcf3Sryker #include <time.h>
114b6ab114eSjsing 
115e123f381Smiod #include <openssl/err.h>
116e123f381Smiod 
117c9675a23Stb #include "bn_local.h"
118b6ab114eSjsing 
119ba5406e9Sbeck /* The quick sieve algorithm approach to weeding out primes is
1205b37fcf3Sryker  * Philip Zimmermann's, as implemented in PGP.  I have had a read of
1215b37fcf3Sryker  * his comments and implemented my own version.
1225b37fcf3Sryker  */
1235b37fcf3Sryker #include "bn_prime.h"
1245b37fcf3Sryker 
1255b37fcf3Sryker static int probable_prime(BIGNUM *rnd, int bits);
1265b37fcf3Sryker static int probable_prime_dh(BIGNUM *rnd, int bits,
127da347917Sbeck     const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
128ba5406e9Sbeck static int probable_prime_dh_safe(BIGNUM *rnd, int bits,
129da347917Sbeck     const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
130ba5406e9Sbeck 
1312bd9bb84Sjsing int
BN_GENCB_call(BN_GENCB * cb,int a,int b)1322bd9bb84Sjsing BN_GENCB_call(BN_GENCB *cb, int a, int b)
1335b37fcf3Sryker {
1344fcf65c5Sdjm 	/* No callback means continue */
1352bd9bb84Sjsing 	if (!cb)
1362bd9bb84Sjsing 		return 1;
1372bd9bb84Sjsing 	switch (cb->ver) {
1384fcf65c5Sdjm 	case 1:
1394fcf65c5Sdjm 		/* Deprecated-style callbacks */
1404fcf65c5Sdjm 		if (!cb->cb.cb_1)
1414fcf65c5Sdjm 			return 1;
1424fcf65c5Sdjm 		cb->cb.cb_1(a, b, cb->arg);
1434fcf65c5Sdjm 		return 1;
1444fcf65c5Sdjm 	case 2:
1454fcf65c5Sdjm 		/* New-style callbacks */
1464fcf65c5Sdjm 		return cb->cb.cb_2(a, b, cb);
1474fcf65c5Sdjm 	default:
1484fcf65c5Sdjm 		break;
1494fcf65c5Sdjm 	}
1504fcf65c5Sdjm 	/* Unrecognised callback type */
1514fcf65c5Sdjm 	return 0;
1524fcf65c5Sdjm }
153ca1d80d6Sbeck LCRYPTO_ALIAS(BN_GENCB_call);
1544fcf65c5Sdjm 
1552bd9bb84Sjsing int
BN_generate_prime_ex(BIGNUM * ret,int bits,int safe,const BIGNUM * add,const BIGNUM * rem,BN_GENCB * cb)1562bd9bb84Sjsing BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
1572bd9bb84Sjsing     const BIGNUM *rem, BN_GENCB *cb)
1584fcf65c5Sdjm {
1595b37fcf3Sryker 	BN_CTX *ctx;
1609d12f35aStb 	BIGNUM *p;
1619d12f35aStb 	int is_prime;
1629d12f35aStb 	int loops = 0;
1639d12f35aStb 	int found = 0;
164e123f381Smiod 
165e123f381Smiod 	if (bits < 2 || (bits == 2 && safe)) {
166e123f381Smiod 		/*
167e123f381Smiod 		 * There are no prime numbers smaller than 2, and the smallest
168e123f381Smiod 		 * safe prime (7) spans three bits.
169e123f381Smiod 		 */
1705067ae9fSbeck 		BNerror(BN_R_BITS_TOO_SMALL);
171e123f381Smiod 		return 0;
172e123f381Smiod 	}
1735b37fcf3Sryker 
174d99b4544Stb 	if ((ctx = BN_CTX_new()) == NULL)
1752bd9bb84Sjsing 		goto err;
1764fcf65c5Sdjm 	BN_CTX_start(ctx);
1779d12f35aStb 	if ((p = BN_CTX_get(ctx)) == NULL)
1782bd9bb84Sjsing 		goto err;
179e123f381Smiod 
1805b37fcf3Sryker  loop:
1819d12f35aStb 	/* Make a random number and set the top and bottom bits. */
1822bd9bb84Sjsing 	if (add == NULL) {
1832bd9bb84Sjsing 		if (!probable_prime(ret, bits))
1842bd9bb84Sjsing 			goto err;
1852bd9bb84Sjsing 	} else {
1862bd9bb84Sjsing 		if (safe) {
1874fcf65c5Sdjm 			if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
1885b37fcf3Sryker 				goto err;
1892bd9bb84Sjsing 		} else {
1904fcf65c5Sdjm 			if (!probable_prime_dh(ret, bits, add, rem, ctx))
1915b37fcf3Sryker 				goto err;
1925b37fcf3Sryker 		}
1935b37fcf3Sryker 	}
194d99b4544Stb 
195d99b4544Stb 	if (!BN_GENCB_call(cb, 0, loops++))
1964fcf65c5Sdjm 		goto err;
1975b37fcf3Sryker 
1982bd9bb84Sjsing 	if (!safe) {
1994e5c7375Stb 		if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
2002bd9bb84Sjsing 			goto err;
2019d12f35aStb 		if (!is_prime)
2022bd9bb84Sjsing 			goto loop;
2032bd9bb84Sjsing 	} else {
2044e5c7375Stb 		if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
2052bd9bb84Sjsing 			goto err;
2069d12f35aStb 		if (!is_prime)
2072bd9bb84Sjsing 			goto loop;
2085b37fcf3Sryker 
2099d12f35aStb 		/*
2109d12f35aStb 		 * For safe prime generation, check that p = (ret-1)/2 is prime.
2119d12f35aStb 		 * Since this prime has >= 3 bits, it is odd, and we can simply
2129d12f35aStb 		 * divide by 2.
2139d12f35aStb 		 */
2149d12f35aStb 		if (!BN_rshift1(p, ret))
2152bd9bb84Sjsing 			goto err;
2169d12f35aStb 
2174e5c7375Stb 		if (!bn_is_prime_bpsw(&is_prime, p, ctx, 1))
2189d12f35aStb 			goto err;
2199d12f35aStb 		if (!is_prime)
2202bd9bb84Sjsing 			goto loop;
2215b37fcf3Sryker 
222d99b4544Stb 		if (!BN_GENCB_call(cb, 2, loops - 1))
2234fcf65c5Sdjm 			goto err;
2245b37fcf3Sryker 	}
225d99b4544Stb 
226ba5406e9Sbeck 	found = 1;
2272bd9bb84Sjsing 
2285b37fcf3Sryker  err:
2294fcf65c5Sdjm 	BN_CTX_end(ctx);
2304fcf65c5Sdjm 	BN_CTX_free(ctx);
231d99b4544Stb 
2324fcf65c5Sdjm 	return found;
233ba5406e9Sbeck }
234ca1d80d6Sbeck LCRYPTO_ALIAS(BN_generate_prime_ex);
2355b37fcf3Sryker 
2362bd9bb84Sjsing int
BN_is_prime_ex(const BIGNUM * a,int checks,BN_CTX * ctx_passed,BN_GENCB * cb)2372bd9bb84Sjsing BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, BN_GENCB *cb)
2384fcf65c5Sdjm {
2394fcf65c5Sdjm 	return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb);
2404fcf65c5Sdjm }
241ca1d80d6Sbeck LCRYPTO_ALIAS(BN_is_prime_ex);
2424fcf65c5Sdjm 
243*050d837aStb #define BN_PRIME_MAXIMUM_BITS (32 * 1024)
244*050d837aStb 
2452bd9bb84Sjsing int
BN_is_prime_fasttest_ex(const BIGNUM * a,int checks,BN_CTX * ctx_passed,int do_trial_division,BN_GENCB * cb)2462bd9bb84Sjsing BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
2474fcf65c5Sdjm     int do_trial_division, BN_GENCB *cb)
248ba5406e9Sbeck {
2490cc5b3fcStb 	int is_prime;
2500cc5b3fcStb 
2514e5c7375Stb 	if (checks < 0)
2524e5c7375Stb 		return -1;
2534e5c7375Stb 
254*050d837aStb 	/*
255*050d837aStb 	 * Prime numbers this large do not appear in everyday cryptography
256*050d837aStb 	 * and checking such numbers for primality is very expensive.
257*050d837aStb 	 */
258*050d837aStb 	if (BN_num_bits(a) > BN_PRIME_MAXIMUM_BITS) {
259*050d837aStb 		BNerror(BN_R_BIGNUM_TOO_LONG);
260*050d837aStb 		return -1;
261*050d837aStb 	}
262*050d837aStb 
2634e5c7375Stb 	if (checks == BN_prime_checks)
2644e5c7375Stb 		checks = BN_prime_checks_for_size(BN_num_bits(a));
2654e5c7375Stb 
2660cc5b3fcStb 	/* XXX - tickle BN_GENCB in bn_is_prime_bpsw(). */
2674e5c7375Stb 	if (!bn_is_prime_bpsw(&is_prime, a, ctx_passed, checks))
2680cc5b3fcStb 		return -1;
2690cc5b3fcStb 
2700cc5b3fcStb 	return is_prime;
2715b37fcf3Sryker }
272ca1d80d6Sbeck LCRYPTO_ALIAS(BN_is_prime_fasttest_ex);
2735b37fcf3Sryker 
2742bd9bb84Sjsing static int
probable_prime(BIGNUM * rnd,int bits)2752bd9bb84Sjsing probable_prime(BIGNUM *rnd, int bits)
2765b37fcf3Sryker {
2775b37fcf3Sryker 	int i;
27854ce1b6bStb 	BN_ULONG mods[NUMPRIMES];
2794fcf65c5Sdjm 	BN_ULONG delta, maxdelta;
2805b37fcf3Sryker 
281913ec974Sbeck again:
2822bd9bb84Sjsing 	if (!BN_rand(rnd, bits, 1, 1))
2832bd9bb84Sjsing 		return (0);
2845b37fcf3Sryker 	/* we now have a random number 'rand' to test. */
285c17ab57aSbcook 	for (i = 1; i < NUMPRIMES; i++) {
28654ce1b6bStb 		BN_ULONG mod = BN_mod_word(rnd, primes[i]);
287c17ab57aSbcook 		if (mod == (BN_ULONG)-1)
288c17ab57aSbcook 			return (0);
28954ce1b6bStb 		mods[i] = mod;
290c17ab57aSbcook 	}
2914fcf65c5Sdjm 	maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
2925b37fcf3Sryker 	delta = 0;
2932bd9bb84Sjsing loop:
2942bd9bb84Sjsing 	for (i = 1; i < NUMPRIMES; i++) {
2955b37fcf3Sryker 		/* check that rnd is not a prime and also
2965b37fcf3Sryker 		 * that gcd(rnd-1,primes) == 1 (except for 2) */
2972bd9bb84Sjsing 		if (((mods[i] + delta) % primes[i]) <= 1) {
2985b37fcf3Sryker 			delta += 2;
2992bd9bb84Sjsing 			if (delta > maxdelta)
3002bd9bb84Sjsing 				goto again;
3015b37fcf3Sryker 			goto loop;
3025b37fcf3Sryker 		}
3035b37fcf3Sryker 	}
3042bd9bb84Sjsing 	if (!BN_add_word(rnd, delta))
3052bd9bb84Sjsing 		return (0);
3065b37fcf3Sryker 	return (1);
3075b37fcf3Sryker }
3085b37fcf3Sryker 
3092bd9bb84Sjsing static int
probable_prime_dh(BIGNUM * rnd,int bits,const BIGNUM * add,const BIGNUM * rem,BN_CTX * ctx)3102bd9bb84Sjsing probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem,
3112bd9bb84Sjsing     BN_CTX *ctx)
3125b37fcf3Sryker {
3135b37fcf3Sryker 	int i, ret = 0;
3145b37fcf3Sryker 	BIGNUM *t1;
3155b37fcf3Sryker 
316ba5406e9Sbeck 	BN_CTX_start(ctx);
3172bd9bb84Sjsing 	if ((t1 = BN_CTX_get(ctx)) == NULL)
3182bd9bb84Sjsing 		goto err;
3195b37fcf3Sryker 
3202bd9bb84Sjsing 	if (!BN_rand(rnd, bits, 0, 1))
3212bd9bb84Sjsing 		goto err;
3225b37fcf3Sryker 
3235b37fcf3Sryker 	/* we need ((rnd-rem) % add) == 0 */
3245b37fcf3Sryker 
32544adc1eaSbeck 	if (!BN_mod_ct(t1, rnd, add, ctx))
3262bd9bb84Sjsing 		goto err;
3272bd9bb84Sjsing 	if (!BN_sub(rnd, rnd, t1))
3282bd9bb84Sjsing 		goto err;
3292bd9bb84Sjsing 	if (rem == NULL) {
3302bd9bb84Sjsing 		if (!BN_add_word(rnd, 1))
3312bd9bb84Sjsing 			goto err;
3322bd9bb84Sjsing 	} else {
3332bd9bb84Sjsing 		if (!BN_add(rnd, rnd, rem))
3342bd9bb84Sjsing 			goto err;
3352bd9bb84Sjsing 	}
3365b37fcf3Sryker 
3375b37fcf3Sryker 	/* we now have a random number 'rand' to test. */
3385b37fcf3Sryker 
3392bd9bb84Sjsing loop:
3402bd9bb84Sjsing 	for (i = 1; i < NUMPRIMES; i++) {
3415b37fcf3Sryker 		/* check that rnd is a prime */
34254ce1b6bStb 		BN_LONG mod = BN_mod_word(rnd, primes[i]);
343c17ab57aSbcook 		if (mod == (BN_ULONG)-1)
344c17ab57aSbcook 			goto err;
345c17ab57aSbcook 		if (mod <= 1) {
3462bd9bb84Sjsing 			if (!BN_add(rnd, rnd, add))
3472bd9bb84Sjsing 				goto err;
3485b37fcf3Sryker 			goto loop;
3495b37fcf3Sryker 		}
3505b37fcf3Sryker 	}
3515b37fcf3Sryker 	ret = 1;
3522bd9bb84Sjsing 
3535b37fcf3Sryker err:
354ba5406e9Sbeck 	BN_CTX_end(ctx);
3555b37fcf3Sryker 	return (ret);
3565b37fcf3Sryker }
3575b37fcf3Sryker 
3582bd9bb84Sjsing static int
probable_prime_dh_safe(BIGNUM * p,int bits,const BIGNUM * padd,const BIGNUM * rem,BN_CTX * ctx)3592bd9bb84Sjsing probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
360da347917Sbeck     const BIGNUM *rem, BN_CTX *ctx)
3615b37fcf3Sryker {
3625b37fcf3Sryker 	int i, ret = 0;
363ba5406e9Sbeck 	BIGNUM *t1, *qadd, *q;
3645b37fcf3Sryker 
3655b37fcf3Sryker 	bits--;
366ba5406e9Sbeck 	BN_CTX_start(ctx);
367aa389b8cSjsing 	if ((t1 = BN_CTX_get(ctx)) == NULL)
368aa389b8cSjsing 		goto err;
369aa389b8cSjsing 	if ((q = BN_CTX_get(ctx)) == NULL)
370aa389b8cSjsing 		goto err;
371aa389b8cSjsing 	if ((qadd = BN_CTX_get(ctx)) == NULL)
3722bd9bb84Sjsing 		goto err;
3735b37fcf3Sryker 
3742bd9bb84Sjsing 	if (!BN_rshift1(qadd, padd))
3752bd9bb84Sjsing 		goto err;
3765b37fcf3Sryker 
3772bd9bb84Sjsing 	if (!BN_rand(q, bits, 0, 1))
3782bd9bb84Sjsing 		goto err;
3795b37fcf3Sryker 
3805b37fcf3Sryker 	/* we need ((rnd-rem) % add) == 0 */
38144adc1eaSbeck 	if (!BN_mod_ct(t1, q,qadd, ctx))
3822bd9bb84Sjsing 		goto err;
3832bd9bb84Sjsing 	if (!BN_sub(q, q, t1))
3842bd9bb84Sjsing 		goto err;
3852bd9bb84Sjsing 	if (rem == NULL) {
3862bd9bb84Sjsing 		if (!BN_add_word(q, 1))
3872bd9bb84Sjsing 			goto err;
3882bd9bb84Sjsing 	} else {
3892bd9bb84Sjsing 		if (!BN_rshift1(t1, rem))
3902bd9bb84Sjsing 			goto err;
3912bd9bb84Sjsing 		if (!BN_add(q, q, t1))
3922bd9bb84Sjsing 			goto err;
3935b37fcf3Sryker 	}
3945b37fcf3Sryker 
3955b37fcf3Sryker 	/* we now have a random number 'rand' to test. */
3962bd9bb84Sjsing 	if (!BN_lshift1(p, q))
3972bd9bb84Sjsing 		goto err;
3982bd9bb84Sjsing 	if (!BN_add_word(p, 1))
3992bd9bb84Sjsing 		goto err;
4005b37fcf3Sryker 
4012bd9bb84Sjsing loop:
4022bd9bb84Sjsing 	for (i = 1; i < NUMPRIMES; i++) {
4035b37fcf3Sryker 		/* check that p and q are prime */
4045b37fcf3Sryker 		/* check that for p and q
4055b37fcf3Sryker 		 * gcd(p-1,primes) == 1 (except for 2) */
40654ce1b6bStb 		BN_ULONG pmod = BN_mod_word(p, primes[i]);
40754ce1b6bStb 		BN_ULONG qmod = BN_mod_word(q, primes[i]);
408c17ab57aSbcook 		if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1)
409c17ab57aSbcook 			goto err;
410c17ab57aSbcook 		if (pmod == 0 || qmod == 0) {
4112bd9bb84Sjsing 			if (!BN_add(p, p, padd))
4122bd9bb84Sjsing 				goto err;
4132bd9bb84Sjsing 			if (!BN_add(q, q, qadd))
4142bd9bb84Sjsing 				goto err;
4155b37fcf3Sryker 			goto loop;
4165b37fcf3Sryker 		}
4175b37fcf3Sryker 	}
4185b37fcf3Sryker 	ret = 1;
4192bd9bb84Sjsing 
4205b37fcf3Sryker err:
421ba5406e9Sbeck 	BN_CTX_end(ctx);
4225b37fcf3Sryker 	return (ret);
4235b37fcf3Sryker }
424