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