Line data Source code
1 : /* crypto/dh/dh_key.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 : #include <stdio.h>
60 : #include "cryptlib.h"
61 : #include <openssl/bn.h>
62 : #include <openssl/rand.h>
63 : #include <openssl/dh.h>
64 :
65 : static int generate_key(DH *dh);
66 : static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
67 : static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
68 : const BIGNUM *a, const BIGNUM *p,
69 : const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
70 : static int dh_init(DH *dh);
71 : static int dh_finish(DH *dh);
72 :
73 0 : int DH_generate_key(DH *dh)
74 : {
75 : #ifdef OPENSSL_FIPS
76 : if (FIPS_mode() && !(dh->meth->flags & DH_FLAG_FIPS_METHOD)
77 : && !(dh->flags & DH_FLAG_NON_FIPS_ALLOW)) {
78 : DHerr(DH_F_DH_GENERATE_KEY, DH_R_NON_FIPS_METHOD);
79 : return 0;
80 : }
81 : #endif
82 0 : return dh->meth->generate_key(dh);
83 : }
84 :
85 0 : int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
86 : {
87 : #ifdef OPENSSL_FIPS
88 : if (FIPS_mode() && !(dh->meth->flags & DH_FLAG_FIPS_METHOD)
89 : && !(dh->flags & DH_FLAG_NON_FIPS_ALLOW)) {
90 : DHerr(DH_F_DH_COMPUTE_KEY, DH_R_NON_FIPS_METHOD);
91 : return 0;
92 : }
93 : #endif
94 0 : return dh->meth->compute_key(key, pub_key, dh);
95 : }
96 :
97 0 : int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
98 : {
99 : int rv, pad;
100 0 : rv = dh->meth->compute_key(key, pub_key, dh);
101 0 : if (rv <= 0)
102 : return rv;
103 0 : pad = BN_num_bytes(dh->p) - rv;
104 0 : if (pad > 0) {
105 0 : memmove(key + pad, key, rv);
106 : memset(key, 0, pad);
107 : }
108 0 : return rv + pad;
109 : }
110 :
111 : static DH_METHOD dh_ossl = {
112 : "OpenSSL DH Method",
113 : generate_key,
114 : compute_key,
115 : dh_bn_mod_exp,
116 : dh_init,
117 : dh_finish,
118 : 0,
119 : NULL,
120 : NULL
121 : };
122 :
123 0 : const DH_METHOD *DH_OpenSSL(void)
124 : {
125 0 : return &dh_ossl;
126 : }
127 :
128 0 : static int generate_key(DH *dh)
129 : {
130 : int ok = 0;
131 : int generate_new_key = 0;
132 : unsigned l;
133 : BN_CTX *ctx;
134 : BN_MONT_CTX *mont = NULL;
135 : BIGNUM *pub_key = NULL, *priv_key = NULL;
136 :
137 0 : ctx = BN_CTX_new();
138 0 : if (ctx == NULL)
139 : goto err;
140 :
141 0 : if (dh->priv_key == NULL) {
142 0 : priv_key = BN_new();
143 0 : if (priv_key == NULL)
144 : goto err;
145 : generate_new_key = 1;
146 : } else
147 : priv_key = dh->priv_key;
148 :
149 0 : if (dh->pub_key == NULL) {
150 0 : pub_key = BN_new();
151 0 : if (pub_key == NULL)
152 : goto err;
153 : } else
154 : pub_key = dh->pub_key;
155 :
156 0 : if (dh->flags & DH_FLAG_CACHE_MONT_P) {
157 0 : mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
158 0 : CRYPTO_LOCK_DH, dh->p, ctx);
159 0 : if (!mont)
160 : goto err;
161 : }
162 :
163 0 : if (generate_new_key) {
164 0 : if (dh->q) {
165 : do {
166 0 : if (!BN_rand_range(priv_key, dh->q))
167 : goto err;
168 : }
169 0 : while (BN_is_zero(priv_key) || BN_is_one(priv_key));
170 : } else {
171 : /* secret exponent length */
172 0 : l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
173 0 : if (!BN_rand(priv_key, l, 0, 0))
174 : goto err;
175 : }
176 : }
177 :
178 : {
179 : BIGNUM local_prk;
180 : BIGNUM *prk;
181 :
182 0 : if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
183 0 : BN_init(&local_prk);
184 : prk = &local_prk;
185 0 : BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
186 : } else
187 : prk = priv_key;
188 :
189 0 : if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont))
190 : goto err;
191 : }
192 :
193 0 : dh->pub_key = pub_key;
194 0 : dh->priv_key = priv_key;
195 : ok = 1;
196 : err:
197 0 : if (ok != 1)
198 0 : DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
199 :
200 0 : if ((pub_key != NULL) && (dh->pub_key == NULL))
201 0 : BN_free(pub_key);
202 0 : if ((priv_key != NULL) && (dh->priv_key == NULL))
203 0 : BN_free(priv_key);
204 0 : BN_CTX_free(ctx);
205 0 : return (ok);
206 : }
207 :
208 0 : static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
209 : {
210 : BN_CTX *ctx = NULL;
211 : BN_MONT_CTX *mont = NULL;
212 : BIGNUM *tmp;
213 : int ret = -1;
214 : int check_result;
215 :
216 0 : if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
217 0 : DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
218 0 : goto err;
219 : }
220 :
221 0 : ctx = BN_CTX_new();
222 0 : if (ctx == NULL)
223 : goto err;
224 0 : BN_CTX_start(ctx);
225 0 : tmp = BN_CTX_get(ctx);
226 :
227 0 : if (dh->priv_key == NULL) {
228 0 : DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
229 0 : goto err;
230 : }
231 :
232 0 : if (dh->flags & DH_FLAG_CACHE_MONT_P) {
233 0 : mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
234 0 : CRYPTO_LOCK_DH, dh->p, ctx);
235 0 : if ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) == 0) {
236 : /* XXX */
237 0 : BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
238 : }
239 0 : if (!mont)
240 : goto err;
241 : }
242 :
243 0 : if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
244 0 : DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
245 0 : goto err;
246 : }
247 :
248 0 : if (!dh->
249 0 : meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
250 0 : DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
251 0 : goto err;
252 : }
253 :
254 0 : ret = BN_bn2bin(tmp, key);
255 : err:
256 0 : if (ctx != NULL) {
257 0 : BN_CTX_end(ctx);
258 0 : BN_CTX_free(ctx);
259 : }
260 0 : return (ret);
261 : }
262 :
263 0 : static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
264 : const BIGNUM *a, const BIGNUM *p,
265 : const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
266 : {
267 : /*
268 : * If a is only one word long and constant time is false, use the faster
269 : * exponenentiation function.
270 : */
271 0 : if (a->top == 1 && ((dh->flags & DH_FLAG_NO_EXP_CONSTTIME) != 0)) {
272 0 : BN_ULONG A = a->d[0];
273 0 : return BN_mod_exp_mont_word(r, A, p, m, ctx, m_ctx);
274 : } else
275 0 : return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
276 : }
277 :
278 0 : static int dh_init(DH *dh)
279 : {
280 0 : dh->flags |= DH_FLAG_CACHE_MONT_P;
281 0 : return (1);
282 : }
283 :
284 0 : static int dh_finish(DH *dh)
285 : {
286 0 : if (dh->method_mont_p)
287 0 : BN_MONT_CTX_free(dh->method_mont_p);
288 0 : return (1);
289 : }
|