xref: /onnv-gate/usr/src/common/openssl/crypto/dsa/dsa_gen.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/dsa/dsa_gen.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #undef GENUINE_DSA
600Sstevel@tonic-gate 
610Sstevel@tonic-gate #ifdef GENUINE_DSA
620Sstevel@tonic-gate /* Parameter generation follows the original release of FIPS PUB 186,
630Sstevel@tonic-gate  * Appendix 2.2 (i.e. use SHA as defined in FIPS PUB 180) */
640Sstevel@tonic-gate #define HASH    EVP_sha()
650Sstevel@tonic-gate #else
660Sstevel@tonic-gate /* Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
670Sstevel@tonic-gate  * also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in
680Sstevel@tonic-gate  * FIPS PUB 180-1) */
690Sstevel@tonic-gate #define HASH    EVP_sha1()
700Sstevel@tonic-gate #endif
710Sstevel@tonic-gate 
72*2139Sjp161948 #include <openssl/opensslconf.h> /* To see if OPENSSL_NO_SHA is defined */
73*2139Sjp161948 
740Sstevel@tonic-gate #ifndef OPENSSL_NO_SHA
750Sstevel@tonic-gate 
760Sstevel@tonic-gate #include <stdio.h>
770Sstevel@tonic-gate #include <time.h>
780Sstevel@tonic-gate #include "cryptlib.h"
790Sstevel@tonic-gate #include <openssl/evp.h>
800Sstevel@tonic-gate #include <openssl/bn.h>
810Sstevel@tonic-gate #include <openssl/dsa.h>
820Sstevel@tonic-gate #include <openssl/rand.h>
830Sstevel@tonic-gate #include <openssl/sha.h>
840Sstevel@tonic-gate 
85*2139Sjp161948 static int dsa_builtin_paramgen(DSA *ret, int bits,
86*2139Sjp161948 		unsigned char *seed_in, int seed_len,
87*2139Sjp161948 		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
88*2139Sjp161948 
DSA_generate_parameters_ex(DSA * ret,int bits,unsigned char * seed_in,int seed_len,int * counter_ret,unsigned long * h_ret,BN_GENCB * cb)89*2139Sjp161948 int DSA_generate_parameters_ex(DSA *ret, int bits,
900Sstevel@tonic-gate 		unsigned char *seed_in, int seed_len,
91*2139Sjp161948 		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
92*2139Sjp161948 	{
93*2139Sjp161948 	if(ret->meth->dsa_paramgen)
94*2139Sjp161948 		return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len,
95*2139Sjp161948 				counter_ret, h_ret, cb);
96*2139Sjp161948 	return dsa_builtin_paramgen(ret, bits, seed_in, seed_len,
97*2139Sjp161948 			counter_ret, h_ret, cb);
98*2139Sjp161948 	}
99*2139Sjp161948 
dsa_builtin_paramgen(DSA * ret,int bits,unsigned char * seed_in,int seed_len,int * counter_ret,unsigned long * h_ret,BN_GENCB * cb)100*2139Sjp161948 static int dsa_builtin_paramgen(DSA *ret, int bits,
101*2139Sjp161948 		unsigned char *seed_in, int seed_len,
102*2139Sjp161948 		int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
1030Sstevel@tonic-gate 	{
1040Sstevel@tonic-gate 	int ok=0;
1050Sstevel@tonic-gate 	unsigned char seed[SHA_DIGEST_LENGTH];
1060Sstevel@tonic-gate 	unsigned char md[SHA_DIGEST_LENGTH];
1070Sstevel@tonic-gate 	unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
1080Sstevel@tonic-gate 	BIGNUM *r0,*W,*X,*c,*test;
1090Sstevel@tonic-gate 	BIGNUM *g=NULL,*q=NULL,*p=NULL;
1100Sstevel@tonic-gate 	BN_MONT_CTX *mont=NULL;
1110Sstevel@tonic-gate 	int k,n=0,i,b,m=0;
1120Sstevel@tonic-gate 	int counter=0;
1130Sstevel@tonic-gate 	int r=0;
114*2139Sjp161948 	BN_CTX *ctx=NULL;
1150Sstevel@tonic-gate 	unsigned int h=2;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	if (bits < 512) bits=512;
1180Sstevel@tonic-gate 	bits=(bits+63)/64*64;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if (seed_len < 20)
1210Sstevel@tonic-gate 		seed_in = NULL; /* seed buffer too small -- ignore */
1220Sstevel@tonic-gate 	if (seed_len > 20)
1230Sstevel@tonic-gate 		seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
1240Sstevel@tonic-gate 		                * but our internal buffers are restricted to 160 bits*/
1250Sstevel@tonic-gate 	if ((seed_in != NULL) && (seed_len == 20))
1260Sstevel@tonic-gate 		memcpy(seed,seed_in,seed_len);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	if ((ctx=BN_CTX_new()) == NULL) goto err;
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
1310Sstevel@tonic-gate 
132*2139Sjp161948 	BN_CTX_start(ctx);
133*2139Sjp161948 	r0 = BN_CTX_get(ctx);
134*2139Sjp161948 	g = BN_CTX_get(ctx);
135*2139Sjp161948 	W = BN_CTX_get(ctx);
136*2139Sjp161948 	q = BN_CTX_get(ctx);
137*2139Sjp161948 	X = BN_CTX_get(ctx);
138*2139Sjp161948 	c = BN_CTX_get(ctx);
139*2139Sjp161948 	p = BN_CTX_get(ctx);
140*2139Sjp161948 	test = BN_CTX_get(ctx);
1410Sstevel@tonic-gate 
142*2139Sjp161948 	if (!BN_lshift(test,BN_value_one(),bits-1))
143*2139Sjp161948 		goto err;
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	for (;;)
1460Sstevel@tonic-gate 		{
1470Sstevel@tonic-gate 		for (;;) /* find q */
1480Sstevel@tonic-gate 			{
1490Sstevel@tonic-gate 			int seed_is_random;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 			/* step 1 */
152*2139Sjp161948 			if(!BN_GENCB_call(cb, 0, m++))
153*2139Sjp161948 				goto err;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 			if (!seed_len)
1560Sstevel@tonic-gate 				{
1570Sstevel@tonic-gate 				RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH);
1580Sstevel@tonic-gate 				seed_is_random = 1;
1590Sstevel@tonic-gate 				}
1600Sstevel@tonic-gate 			else
1610Sstevel@tonic-gate 				{
1620Sstevel@tonic-gate 				seed_is_random = 0;
1630Sstevel@tonic-gate 				seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/
1640Sstevel@tonic-gate 				}
1650Sstevel@tonic-gate 			memcpy(buf,seed,SHA_DIGEST_LENGTH);
1660Sstevel@tonic-gate 			memcpy(buf2,seed,SHA_DIGEST_LENGTH);
1670Sstevel@tonic-gate 			/* precompute "SEED + 1" for step 7: */
1680Sstevel@tonic-gate 			for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
1690Sstevel@tonic-gate 				{
1700Sstevel@tonic-gate 				buf[i]++;
1710Sstevel@tonic-gate 				if (buf[i] != 0) break;
1720Sstevel@tonic-gate 				}
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 			/* step 2 */
1750Sstevel@tonic-gate 			EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
1760Sstevel@tonic-gate 			EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL);
1770Sstevel@tonic-gate 			for (i=0; i<SHA_DIGEST_LENGTH; i++)
1780Sstevel@tonic-gate 				md[i]^=buf2[i];
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 			/* step 3 */
1810Sstevel@tonic-gate 			md[0]|=0x80;
1820Sstevel@tonic-gate 			md[SHA_DIGEST_LENGTH-1]|=0x01;
1830Sstevel@tonic-gate 			if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,q)) goto err;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 			/* step 4 */
186*2139Sjp161948 			r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
187*2139Sjp161948 					seed_is_random, cb);
1880Sstevel@tonic-gate 			if (r > 0)
1890Sstevel@tonic-gate 				break;
1900Sstevel@tonic-gate 			if (r != 0)
1910Sstevel@tonic-gate 				goto err;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 			/* do a callback call */
1940Sstevel@tonic-gate 			/* step 5 */
1950Sstevel@tonic-gate 			}
1960Sstevel@tonic-gate 
197*2139Sjp161948 		if(!BN_GENCB_call(cb, 2, 0)) goto err;
198*2139Sjp161948 		if(!BN_GENCB_call(cb, 3, 0)) goto err;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		/* step 6 */
2010Sstevel@tonic-gate 		counter=0;
2020Sstevel@tonic-gate 		/* "offset = 2" */
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 		n=(bits-1)/160;
2050Sstevel@tonic-gate 		b=(bits-1)-n*160;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 		for (;;)
2080Sstevel@tonic-gate 			{
209*2139Sjp161948 			if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
210*2139Sjp161948 				goto err;
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 			/* step 7 */
2130Sstevel@tonic-gate 			BN_zero(W);
2140Sstevel@tonic-gate 			/* now 'buf' contains "SEED + offset - 1" */
2150Sstevel@tonic-gate 			for (k=0; k<=n; k++)
2160Sstevel@tonic-gate 				{
2170Sstevel@tonic-gate 				/* obtain "SEED + offset + k" by incrementing: */
2180Sstevel@tonic-gate 				for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
2190Sstevel@tonic-gate 					{
2200Sstevel@tonic-gate 					buf[i]++;
2210Sstevel@tonic-gate 					if (buf[i] != 0) break;
2220Sstevel@tonic-gate 					}
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 				EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 				/* step 8 */
2270Sstevel@tonic-gate 				if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0))
2280Sstevel@tonic-gate 					goto err;
229*2139Sjp161948 				if (!BN_lshift(r0,r0,160*k)) goto err;
230*2139Sjp161948 				if (!BN_add(W,W,r0)) goto err;
2310Sstevel@tonic-gate 				}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 			/* more of step 8 */
234*2139Sjp161948 			if (!BN_mask_bits(W,bits-1)) goto err;
235*2139Sjp161948 			if (!BN_copy(X,W)) goto err;
236*2139Sjp161948 			if (!BN_add(X,X,test)) goto err;
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 			/* step 9 */
239*2139Sjp161948 			if (!BN_lshift1(r0,q)) goto err;
240*2139Sjp161948 			if (!BN_mod(c,X,r0,ctx)) goto err;
241*2139Sjp161948 			if (!BN_sub(r0,c,BN_value_one())) goto err;
242*2139Sjp161948 			if (!BN_sub(p,X,r0)) goto err;
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 			/* step 10 */
2450Sstevel@tonic-gate 			if (BN_cmp(p,test) >= 0)
2460Sstevel@tonic-gate 				{
2470Sstevel@tonic-gate 				/* step 11 */
248*2139Sjp161948 				r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
249*2139Sjp161948 						ctx, 1, cb);
2500Sstevel@tonic-gate 				if (r > 0)
2510Sstevel@tonic-gate 						goto end; /* found it */
2520Sstevel@tonic-gate 				if (r != 0)
2530Sstevel@tonic-gate 					goto err;
2540Sstevel@tonic-gate 				}
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 			/* step 13 */
2570Sstevel@tonic-gate 			counter++;
2580Sstevel@tonic-gate 			/* "offset = offset + n + 1" */
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 			/* step 14 */
2610Sstevel@tonic-gate 			if (counter >= 4096) break;
2620Sstevel@tonic-gate 			}
2630Sstevel@tonic-gate 		}
2640Sstevel@tonic-gate end:
265*2139Sjp161948 	if(!BN_GENCB_call(cb, 2, 1))
266*2139Sjp161948 		goto err;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	/* We now need to generate g */
2690Sstevel@tonic-gate 	/* Set r0=(p-1)/q */
270*2139Sjp161948 	if (!BN_sub(test,p,BN_value_one())) goto err;
271*2139Sjp161948 	if (!BN_div(r0,NULL,test,q,ctx)) goto err;
2720Sstevel@tonic-gate 
273*2139Sjp161948 	if (!BN_set_word(test,h)) goto err;
274*2139Sjp161948 	if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	for (;;)
2770Sstevel@tonic-gate 		{
2780Sstevel@tonic-gate 		/* g=test^r0%p */
279*2139Sjp161948 		if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
2800Sstevel@tonic-gate 		if (!BN_is_one(g)) break;
281*2139Sjp161948 		if (!BN_add(test,test,BN_value_one())) goto err;
2820Sstevel@tonic-gate 		h++;
2830Sstevel@tonic-gate 		}
2840Sstevel@tonic-gate 
285*2139Sjp161948 	if(!BN_GENCB_call(cb, 3, 1))
286*2139Sjp161948 		goto err;
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	ok=1;
2890Sstevel@tonic-gate err:
290*2139Sjp161948 	if (ok)
2910Sstevel@tonic-gate 		{
292*2139Sjp161948 		if(ret->p) BN_free(ret->p);
293*2139Sjp161948 		if(ret->q) BN_free(ret->q);
294*2139Sjp161948 		if(ret->g) BN_free(ret->g);
2950Sstevel@tonic-gate 		ret->p=BN_dup(p);
2960Sstevel@tonic-gate 		ret->q=BN_dup(q);
2970Sstevel@tonic-gate 		ret->g=BN_dup(g);
298*2139Sjp161948 		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
299*2139Sjp161948 			{
300*2139Sjp161948 			ok=0;
301*2139Sjp161948 			goto err;
302*2139Sjp161948 			}
3030Sstevel@tonic-gate 		if ((m > 1) && (seed_in != NULL)) memcpy(seed_in,seed,20);
3040Sstevel@tonic-gate 		if (counter_ret != NULL) *counter_ret=counter;
3050Sstevel@tonic-gate 		if (h_ret != NULL) *h_ret=h;
3060Sstevel@tonic-gate 		}
307*2139Sjp161948 	if(ctx)
3080Sstevel@tonic-gate 		{
309*2139Sjp161948 		BN_CTX_end(ctx);
310*2139Sjp161948 		BN_CTX_free(ctx);
3110Sstevel@tonic-gate 		}
3120Sstevel@tonic-gate 	if (mont != NULL) BN_MONT_CTX_free(mont);
313*2139Sjp161948 	return ok;
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate #endif
316