1145516Sdarrenr/* crypto/dh/dh_gen.c */
2255332Scy/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3145516Sdarrenr * All rights reserved.
4145516Sdarrenr *
5145516Sdarrenr * This package is an SSL implementation written
6145516Sdarrenr * by Eric Young (eay@cryptsoft.com).
7145516Sdarrenr * The implementation was written so as to conform with Netscapes SSL.
8145516Sdarrenr *
9145516Sdarrenr * This library is free for commercial and non-commercial use as long as
10145516Sdarrenr * the following conditions are aheared to.  The following conditions
11145516Sdarrenr * apply to all code found in this distribution, be it the RC4, RSA,
12145516Sdarrenr * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13145516Sdarrenr * included with this distribution is covered by the same copyright terms
14145516Sdarrenr * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15145516Sdarrenr *
16145516Sdarrenr * Copyright remains Eric Young's, and as such any Copyright notices in
17145516Sdarrenr * the code are not to be removed.
18145516Sdarrenr * If this package is used in a product, Eric Young should be given attribution
19145516Sdarrenr * as the author of the parts of the library used.
20145516Sdarrenr * This can be in the form of a textual message at program startup or
21145516Sdarrenr * in documentation (online or textual) provided with the package.
22145516Sdarrenr *
23145516Sdarrenr * Redistribution and use in source and binary forms, with or without
24344833Scy * modification, are permitted provided that the following conditions
25145516Sdarrenr * are met:
26145516Sdarrenr * 1. Redistributions of source code must retain the copyright
27145516Sdarrenr *    notice, this list of conditions and the following disclaimer.
28145516Sdarrenr * 2. Redistributions in binary form must reproduce the above copyright
29145516Sdarrenr *    notice, this list of conditions and the following disclaimer in the
30145516Sdarrenr *    documentation and/or other materials provided with the distribution.
31145516Sdarrenr * 3. All advertising materials mentioning features or use of this software
32145516Sdarrenr *    must display the following acknowledgement:
33145516Sdarrenr *    "This product includes cryptographic software written by
34145516Sdarrenr *     Eric Young (eay@cryptsoft.com)"
35145516Sdarrenr *    The word 'cryptographic' can be left out if the rouines from the library
36145516Sdarrenr *    being used are not cryptographic related :-).
37145516Sdarrenr * 4. If you include any Windows specific code (or a derivative thereof) from
38145516Sdarrenr *    the apps directory (application code) you must include an acknowledgement:
39145516Sdarrenr *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40145516Sdarrenr *
41145516Sdarrenr * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42145516Sdarrenr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43145516Sdarrenr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44145516Sdarrenr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45145516Sdarrenr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46145516Sdarrenr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47145516Sdarrenr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48145516Sdarrenr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49145516Sdarrenr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50145516Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51145516Sdarrenr * SUCH DAMAGE.
52145516Sdarrenr *
53255332Scy * The licence and distribution terms for any publically available version or
54145516Sdarrenr * derivative of this code cannot be changed.  i.e. this code cannot simply be
55145516Sdarrenr * copied and put under another distribution licence
56145516Sdarrenr * [including the GNU Public Licence.]
57145516Sdarrenr */
58145516Sdarrenr
59255332Scy/* NB: These functions have been upgraded - the previous prototypes are in
60255332Scy * dh_depr.c as wrappers to these ones.
61255332Scy *  - Geoff
62145516Sdarrenr */
63255332Scy
64145516Sdarrenr#include <stdio.h>
65145516Sdarrenr#include "cryptlib.h"
66145516Sdarrenr#include <openssl/bn.h>
67145516Sdarrenr#include <openssl/dh.h>
68145516Sdarrenr
69145516Sdarrenr#ifdef OPENSSL_FIPS
70145516Sdarrenr#include <openssl/fips.h>
71145516Sdarrenr#endif
72369245Sgit2svn
73369245Sgit2svnstatic int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb);
74369245Sgit2svn
75369245Sgit2svnint DH_generate_parameters_ex(DH *ret, int prime_len, int generator, BN_GENCB *cb)
76369245Sgit2svn	{
77369245Sgit2svn#ifdef OPENSSL_FIPS
78145516Sdarrenr	if (FIPS_mode() && !(ret->meth->flags & DH_FLAG_FIPS_METHOD)
79255332Scy			&& !(ret->flags & DH_FLAG_NON_FIPS_ALLOW))
80145516Sdarrenr		{
81145516Sdarrenr		DHerr(DH_F_DH_GENERATE_PARAMETERS_EX, DH_R_NON_FIPS_METHOD);
82255332Scy		return 0;
83255332Scy		}
84145516Sdarrenr#endif
85255332Scy	if(ret->meth->generate_params)
86255332Scy		return ret->meth->generate_params(ret, prime_len, generator, cb);
87145516Sdarrenr#ifdef OPENSSL_FIPS
88145516Sdarrenr	if (FIPS_mode())
89145516Sdarrenr		return FIPS_dh_generate_parameters_ex(ret, prime_len,
90145516Sdarrenr							generator, cb);
91255332Scy#endif
92255332Scy	return dh_builtin_genparams(ret, prime_len, generator, cb);
93145516Sdarrenr	}
94255332Scy
95255332Scy/* We generate DH parameters as follows
96255332Scy * find a prime q which is prime_len/2 bits long.
97161351Sguido * p=(2*q)+1 or (p-1)/2 = q
98145516Sdarrenr * For this case, g is a generator if
99145516Sdarrenr * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
100145516Sdarrenr * Since the factors of p-1 are q and 2, we just need to check
101255332Scy * g^2 mod p != 1 and g^q mod p != 1.
102255332Scy *
103255332Scy * Having said all that,
104145516Sdarrenr * there is another special case method for the generators 2, 3 and 5.
105145516Sdarrenr * for 2, p mod 24 == 11
106145516Sdarrenr * for 3, p mod 12 == 5  <<<<< does not work for safe primes.
107145516Sdarrenr * for 5, p mod 10 == 3 or 7
108145516Sdarrenr *
109255332Scy * Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
110255332Scy * special generators and for answering some of my questions.
111145516Sdarrenr *
112255332Scy * I've implemented the second simple method :-).
113145516Sdarrenr * Since DH should be using a safe prime (both p and q are prime),
114145516Sdarrenr * this generator function can take a very very long time to run.
115170263Sdarrenr */
116170263Sdarrenr/* Actually there is no reason to insist that 'generator' be a generator.
117145516Sdarrenr * It's just as OK (and in some sense better) to use a generator of the
118170263Sdarrenr * order-q subgroup.
119145516Sdarrenr */
120255332Scystatic int dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
121145516Sdarrenr	{
122255332Scy	BIGNUM *t1,*t2;
123255332Scy	int g,ok= -1;
124255332Scy	BN_CTX *ctx=NULL;
125145516Sdarrenr
126255332Scy	ctx=BN_CTX_new();
127145516Sdarrenr	if (ctx == NULL) goto err;
128145516Sdarrenr	BN_CTX_start(ctx);
129145516Sdarrenr	t1 = BN_CTX_get(ctx);
130255332Scy	t2 = BN_CTX_get(ctx);
131255332Scy	if (t1 == NULL || t2 == NULL) goto err;
132255332Scy
133255332Scy	/* Make sure 'ret' has the necessary elements */
134145516Sdarrenr	if(!ret->p && ((ret->p = BN_new()) == NULL)) goto err;
135255332Scy	if(!ret->g && ((ret->g = BN_new()) == NULL)) goto err;
136255332Scy
137255332Scy	if (generator <= 1)
138145516Sdarrenr		{
139145516Sdarrenr		DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
140145516Sdarrenr		goto err;
141145516Sdarrenr		}
142145516Sdarrenr	if (generator == DH_GENERATOR_2)
143145516Sdarrenr		{
144145516Sdarrenr		if (!BN_set_word(t1,24)) goto err;
145145516Sdarrenr		if (!BN_set_word(t2,11)) goto err;
146255332Scy		g=2;
147255332Scy		}
148145516Sdarrenr#if 0 /* does not work for safe primes */
149145516Sdarrenr	else if (generator == DH_GENERATOR_3)
150145516Sdarrenr		{
151145516Sdarrenr		if (!BN_set_word(t1,12)) goto err;
152255332Scy		if (!BN_set_word(t2,5)) goto err;
153255332Scy		g=3;
154255332Scy		}
155145516Sdarrenr#endif
156145516Sdarrenr	else if (generator == DH_GENERATOR_5)
157145516Sdarrenr		{
158145516Sdarrenr		if (!BN_set_word(t1,10)) goto err;
159145516Sdarrenr		if (!BN_set_word(t2,3)) goto err;
160145516Sdarrenr		/* BN_set_word(t3,7); just have to miss
161145516Sdarrenr		 * out on these ones :-( */
162145516Sdarrenr		g=5;
163255332Scy		}
164145516Sdarrenr	else
165255332Scy		{
166145516Sdarrenr		/* in the general case, don't worry if 'generator' is a
167145516Sdarrenr		 * generator or not: since we are using safe primes,
168145516Sdarrenr		 * it will generate either an order-q or an order-2q group,
169145516Sdarrenr		 * which both is OK */
170255332Scy		if (!BN_set_word(t1,2)) goto err;
171255332Scy		if (!BN_set_word(t2,1)) goto err;
172145516Sdarrenr		g=generator;
173145516Sdarrenr		}
174145516Sdarrenr
175145516Sdarrenr	if(!BN_generate_prime_ex(ret->p,prime_len,1,t1,t2,cb)) goto err;
176145516Sdarrenr	if(!BN_GENCB_call(cb, 3, 0)) goto err;
177145516Sdarrenr	if (!BN_set_word(ret->g,g)) goto err;
178145516Sdarrenr	ok=1;
179255332Scyerr:
180255332Scy	if (ok == -1)
181145516Sdarrenr		{
182255332Scy		DHerr(DH_F_DH_BUILTIN_GENPARAMS,ERR_R_BN_LIB);
183145516Sdarrenr		ok=0;
184145516Sdarrenr		}
185255332Scy
186145516Sdarrenr	if (ctx != NULL)
187145516Sdarrenr		{
188255332Scy		BN_CTX_end(ctx);
189145516Sdarrenr		BN_CTX_free(ctx);
190145516Sdarrenr		}
191145516Sdarrenr	return ok;
192145516Sdarrenr	}
193255332Scy