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