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