1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57 #include <openssl/dh.h>
58
59 #include <string.h>
60
61 #include <openssl/bn.h>
62 #include <openssl/err.h>
63 #include <openssl/digest.h>
64 #include <openssl/mem.h>
65 #include <openssl/thread.h>
66
67 #include "../../internal.h"
68
69
70 #define OPENSSL_DH_MAX_MODULUS_BITS 10000
71
DH_new(void)72 DH *DH_new(void) {
73 DH *dh = OPENSSL_malloc(sizeof(DH));
74 if (dh == NULL) {
75 OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
76 return NULL;
77 }
78
79 OPENSSL_memset(dh, 0, sizeof(DH));
80
81 CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
82
83 dh->references = 1;
84
85 return dh;
86 }
87
DH_free(DH * dh)88 void DH_free(DH *dh) {
89 if (dh == NULL) {
90 return;
91 }
92
93 if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
94 return;
95 }
96
97 BN_MONT_CTX_free(dh->method_mont_p);
98 BN_clear_free(dh->p);
99 BN_clear_free(dh->g);
100 BN_clear_free(dh->q);
101 BN_clear_free(dh->j);
102 OPENSSL_free(dh->seed);
103 BN_clear_free(dh->counter);
104 BN_clear_free(dh->pub_key);
105 BN_clear_free(dh->priv_key);
106 CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
107
108 OPENSSL_free(dh);
109 }
110
DH_get0_pub_key(const DH * dh)111 const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
112
DH_get0_priv_key(const DH * dh)113 const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
114
DH_get0_p(const DH * dh)115 const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
116
DH_get0_q(const DH * dh)117 const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
118
DH_get0_g(const DH * dh)119 const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
120
DH_get0_key(const DH * dh,const BIGNUM ** out_pub_key,const BIGNUM ** out_priv_key)121 void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
122 const BIGNUM **out_priv_key) {
123 if (out_pub_key != NULL) {
124 *out_pub_key = dh->pub_key;
125 }
126 if (out_priv_key != NULL) {
127 *out_priv_key = dh->priv_key;
128 }
129 }
130
DH_set0_key(DH * dh,BIGNUM * pub_key,BIGNUM * priv_key)131 int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
132 if (pub_key != NULL) {
133 BN_free(dh->pub_key);
134 dh->pub_key = pub_key;
135 }
136
137 if (priv_key != NULL) {
138 BN_free(dh->priv_key);
139 dh->priv_key = priv_key;
140 }
141
142 return 1;
143 }
144
DH_get0_pqg(const DH * dh,const BIGNUM ** out_p,const BIGNUM ** out_q,const BIGNUM ** out_g)145 void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
146 const BIGNUM **out_g) {
147 if (out_p != NULL) {
148 *out_p = dh->p;
149 }
150 if (out_q != NULL) {
151 *out_q = dh->q;
152 }
153 if (out_g != NULL) {
154 *out_g = dh->g;
155 }
156 }
157
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)158 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
159 if ((dh->p == NULL && p == NULL) ||
160 (dh->g == NULL && g == NULL)) {
161 return 0;
162 }
163
164 if (p != NULL) {
165 BN_free(dh->p);
166 dh->p = p;
167 }
168
169 if (q != NULL) {
170 BN_free(dh->q);
171 dh->q = q;
172 }
173
174 if (g != NULL) {
175 BN_free(dh->g);
176 dh->g = g;
177 }
178
179 return 1;
180 }
181
DH_set_length(DH * dh,unsigned priv_length)182 int DH_set_length(DH *dh, unsigned priv_length) {
183 dh->priv_length = priv_length;
184 return 1;
185 }
186
DH_generate_key(DH * dh)187 int DH_generate_key(DH *dh) {
188 int ok = 0;
189 int generate_new_key = 0;
190 BN_CTX *ctx = NULL;
191 BIGNUM *pub_key = NULL, *priv_key = NULL;
192
193 if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
194 OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
195 goto err;
196 }
197
198 ctx = BN_CTX_new();
199 if (ctx == NULL) {
200 goto err;
201 }
202
203 if (dh->priv_key == NULL) {
204 priv_key = BN_new();
205 if (priv_key == NULL) {
206 goto err;
207 }
208 generate_new_key = 1;
209 } else {
210 priv_key = dh->priv_key;
211 }
212
213 if (dh->pub_key == NULL) {
214 pub_key = BN_new();
215 if (pub_key == NULL) {
216 goto err;
217 }
218 } else {
219 pub_key = dh->pub_key;
220 }
221
222 if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
223 dh->p, ctx)) {
224 goto err;
225 }
226
227 if (generate_new_key) {
228 if (dh->q) {
229 if (!BN_rand_range_ex(priv_key, 2, dh->q)) {
230 goto err;
231 }
232 } else {
233 // secret exponent length
234 unsigned priv_bits = dh->priv_length;
235 if (priv_bits == 0) {
236 const unsigned p_bits = BN_num_bits(dh->p);
237 if (p_bits == 0) {
238 goto err;
239 }
240
241 priv_bits = p_bits - 1;
242 }
243
244 if (!BN_rand(priv_key, priv_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
245 goto err;
246 }
247 }
248 }
249
250 if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
251 dh->method_mont_p)) {
252 goto err;
253 }
254
255 dh->pub_key = pub_key;
256 dh->priv_key = priv_key;
257 ok = 1;
258
259 err:
260 if (ok != 1) {
261 OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
262 }
263
264 if (dh->pub_key == NULL) {
265 BN_free(pub_key);
266 }
267 if (dh->priv_key == NULL) {
268 BN_free(priv_key);
269 }
270 BN_CTX_free(ctx);
271 return ok;
272 }
273
dh_compute_key(DH * dh,BIGNUM * out_shared_key,const BIGNUM * peers_key,BN_CTX * ctx)274 static int dh_compute_key(DH *dh, BIGNUM *out_shared_key,
275 const BIGNUM *peers_key, BN_CTX *ctx) {
276 if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
277 OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
278 return 0;
279 }
280
281 if (dh->priv_key == NULL) {
282 OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
283 return 0;
284 }
285
286 int check_result;
287 if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
288 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
289 return 0;
290 }
291
292 int ret = 0;
293 BN_CTX_start(ctx);
294 BIGNUM *p_minus_1 = BN_CTX_get(ctx);
295
296 if (!p_minus_1 ||
297 !BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
298 dh->p, ctx)) {
299 goto err;
300 }
301
302 if (!BN_mod_exp_mont_consttime(out_shared_key, peers_key, dh->priv_key, dh->p,
303 ctx, dh->method_mont_p) ||
304 !BN_copy(p_minus_1, dh->p) ||
305 !BN_sub_word(p_minus_1, 1)) {
306 OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
307 goto err;
308 }
309
310 // This performs the check required by SP 800-56Ar3 section 5.7.1.1 step two.
311 if (BN_cmp_word(out_shared_key, 1) <= 0 ||
312 BN_cmp(out_shared_key, p_minus_1) == 0) {
313 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
314 goto err;
315 }
316
317 ret = 1;
318
319 err:
320 BN_CTX_end(ctx);
321 return ret;
322 }
323
DH_compute_key_padded(unsigned char * out,const BIGNUM * peers_key,DH * dh)324 int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
325 BN_CTX *ctx = BN_CTX_new();
326 if (ctx == NULL) {
327 return -1;
328 }
329 BN_CTX_start(ctx);
330
331 int dh_size = DH_size(dh);
332 int ret = -1;
333 BIGNUM *shared_key = BN_CTX_get(ctx);
334 if (shared_key &&
335 dh_compute_key(dh, shared_key, peers_key, ctx) &&
336 BN_bn2bin_padded(out, dh_size, shared_key)) {
337 ret = dh_size;
338 }
339
340 BN_CTX_end(ctx);
341 BN_CTX_free(ctx);
342 return ret;
343 }
344
DH_compute_key(unsigned char * out,const BIGNUM * peers_key,DH * dh)345 int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
346 BN_CTX *ctx = BN_CTX_new();
347 if (ctx == NULL) {
348 return -1;
349 }
350 BN_CTX_start(ctx);
351
352 int ret = -1;
353 BIGNUM *shared_key = BN_CTX_get(ctx);
354 if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
355 ret = BN_bn2bin(shared_key, out);
356 }
357
358 BN_CTX_end(ctx);
359 BN_CTX_free(ctx);
360 return ret;
361 }
362
DH_compute_key_hashed(DH * dh,uint8_t * out,size_t * out_len,size_t max_out_len,const BIGNUM * peers_key,const EVP_MD * digest)363 int DH_compute_key_hashed(DH *dh, uint8_t *out, size_t *out_len,
364 size_t max_out_len, const BIGNUM *peers_key,
365 const EVP_MD *digest) {
366 *out_len = (size_t)-1;
367
368 const size_t digest_len = EVP_MD_size(digest);
369 if (digest_len > max_out_len) {
370 return 0;
371 }
372
373 int ret = 0;
374 const size_t dh_len = DH_size(dh);
375 uint8_t *shared_bytes = OPENSSL_malloc(dh_len);
376 unsigned out_len_unsigned;
377 if (!shared_bytes ||
378 // SP 800-56A is ambiguous about whether the output should be padded prior
379 // to revision three. But revision three, section C.1, awkwardly specifies
380 // padding to the length of p.
381 //
382 // Also, padded output avoids side-channels, so is always strongly
383 // advisable.
384 DH_compute_key_padded(shared_bytes, peers_key, dh) != (int)dh_len ||
385 !EVP_Digest(shared_bytes, dh_len, out, &out_len_unsigned, digest, NULL) ||
386 out_len_unsigned != digest_len) {
387 goto err;
388 }
389
390 *out_len = digest_len;
391 ret = 1;
392
393 err:
394 OPENSSL_free(shared_bytes);
395 return ret;
396 }
397
DH_size(const DH * dh)398 int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
399
DH_num_bits(const DH * dh)400 unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
401
DH_up_ref(DH * dh)402 int DH_up_ref(DH *dh) {
403 CRYPTO_refcount_inc(&dh->references);
404 return 1;
405 }
406