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 #include "../bn/internal.h"
69 #include "../service_indicator/internal.h"
70 #include "internal.h"
71
72
73 #define OPENSSL_DH_MAX_MODULUS_BITS 10000
74
DH_new(void)75 DH *DH_new(void) {
76 DH *dh = OPENSSL_malloc(sizeof(DH));
77 if (dh == NULL) {
78 OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
79 return NULL;
80 }
81
82 OPENSSL_memset(dh, 0, sizeof(DH));
83
84 CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
85
86 dh->references = 1;
87
88 return dh;
89 }
90
DH_free(DH * dh)91 void DH_free(DH *dh) {
92 if (dh == NULL) {
93 return;
94 }
95
96 if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
97 return;
98 }
99
100 BN_MONT_CTX_free(dh->method_mont_p);
101 BN_clear_free(dh->p);
102 BN_clear_free(dh->g);
103 BN_clear_free(dh->q);
104 BN_clear_free(dh->j);
105 OPENSSL_free(dh->seed);
106 BN_clear_free(dh->counter);
107 BN_clear_free(dh->pub_key);
108 BN_clear_free(dh->priv_key);
109 CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
110
111 OPENSSL_free(dh);
112 }
113
DH_get0_pub_key(const DH * dh)114 const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
115
DH_get0_priv_key(const DH * dh)116 const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
117
DH_get0_p(const DH * dh)118 const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
119
DH_get0_q(const DH * dh)120 const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
121
DH_get0_g(const DH * dh)122 const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
123
DH_get0_key(const DH * dh,const BIGNUM ** out_pub_key,const BIGNUM ** out_priv_key)124 void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
125 const BIGNUM **out_priv_key) {
126 if (out_pub_key != NULL) {
127 *out_pub_key = dh->pub_key;
128 }
129 if (out_priv_key != NULL) {
130 *out_priv_key = dh->priv_key;
131 }
132 }
133
DH_set0_key(DH * dh,BIGNUM * pub_key,BIGNUM * priv_key)134 int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
135 if (pub_key != NULL) {
136 BN_free(dh->pub_key);
137 dh->pub_key = pub_key;
138 }
139
140 if (priv_key != NULL) {
141 BN_free(dh->priv_key);
142 dh->priv_key = priv_key;
143 }
144
145 return 1;
146 }
147
DH_get0_pqg(const DH * dh,const BIGNUM ** out_p,const BIGNUM ** out_q,const BIGNUM ** out_g)148 void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
149 const BIGNUM **out_g) {
150 if (out_p != NULL) {
151 *out_p = dh->p;
152 }
153 if (out_q != NULL) {
154 *out_q = dh->q;
155 }
156 if (out_g != NULL) {
157 *out_g = dh->g;
158 }
159 }
160
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)161 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
162 if ((dh->p == NULL && p == NULL) ||
163 (dh->g == NULL && g == NULL)) {
164 return 0;
165 }
166
167 if (p != NULL) {
168 BN_free(dh->p);
169 dh->p = p;
170 }
171
172 if (q != NULL) {
173 BN_free(dh->q);
174 dh->q = q;
175 }
176
177 if (g != NULL) {
178 BN_free(dh->g);
179 dh->g = g;
180 }
181
182 return 1;
183 }
184
DH_set_length(DH * dh,unsigned priv_length)185 int DH_set_length(DH *dh, unsigned priv_length) {
186 dh->priv_length = priv_length;
187 return 1;
188 }
189
DH_generate_key(DH * dh)190 int DH_generate_key(DH *dh) {
191 boringssl_ensure_ffdh_self_test();
192
193 int ok = 0;
194 int generate_new_key = 0;
195 BN_CTX *ctx = NULL;
196 BIGNUM *pub_key = NULL, *priv_key = NULL;
197
198 if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
199 OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
200 goto err;
201 }
202
203 ctx = BN_CTX_new();
204 if (ctx == NULL) {
205 goto err;
206 }
207
208 if (dh->priv_key == NULL) {
209 priv_key = BN_new();
210 if (priv_key == NULL) {
211 goto err;
212 }
213 generate_new_key = 1;
214 } else {
215 priv_key = dh->priv_key;
216 }
217
218 if (dh->pub_key == NULL) {
219 pub_key = BN_new();
220 if (pub_key == NULL) {
221 goto err;
222 }
223 } else {
224 pub_key = dh->pub_key;
225 }
226
227 if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
228 dh->p, ctx)) {
229 goto err;
230 }
231
232 if (generate_new_key) {
233 if (dh->q) {
234 if (!BN_rand_range_ex(priv_key, 2, dh->q)) {
235 goto err;
236 }
237 } else {
238 // secret exponent length
239 unsigned priv_bits = dh->priv_length;
240 if (priv_bits == 0) {
241 const unsigned p_bits = BN_num_bits(dh->p);
242 if (p_bits == 0) {
243 goto err;
244 }
245
246 priv_bits = p_bits - 1;
247 }
248
249 if (!BN_rand(priv_key, priv_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
250 goto err;
251 }
252 }
253 }
254
255 if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
256 dh->method_mont_p)) {
257 goto err;
258 }
259
260 dh->pub_key = pub_key;
261 dh->priv_key = priv_key;
262 ok = 1;
263
264 err:
265 if (ok != 1) {
266 OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
267 }
268
269 if (dh->pub_key == NULL) {
270 BN_free(pub_key);
271 }
272 if (dh->priv_key == NULL) {
273 BN_free(priv_key);
274 }
275 BN_CTX_free(ctx);
276 return ok;
277 }
278
dh_compute_key(DH * dh,BIGNUM * out_shared_key,const BIGNUM * peers_key,BN_CTX * ctx)279 static int dh_compute_key(DH *dh, BIGNUM *out_shared_key,
280 const BIGNUM *peers_key, BN_CTX *ctx) {
281 if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
282 OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
283 return 0;
284 }
285
286 if (dh->priv_key == NULL) {
287 OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
288 return 0;
289 }
290
291 int check_result;
292 if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
293 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
294 return 0;
295 }
296
297 int ret = 0;
298 BN_CTX_start(ctx);
299 BIGNUM *p_minus_1 = BN_CTX_get(ctx);
300
301 if (!p_minus_1 ||
302 !BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
303 dh->p, ctx)) {
304 goto err;
305 }
306
307 if (!BN_mod_exp_mont_consttime(out_shared_key, peers_key, dh->priv_key, dh->p,
308 ctx, dh->method_mont_p) ||
309 !BN_copy(p_minus_1, dh->p) ||
310 !BN_sub_word(p_minus_1, 1)) {
311 OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
312 goto err;
313 }
314
315 // This performs the check required by SP 800-56Ar3 section 5.7.1.1 step two.
316 if (BN_cmp_word(out_shared_key, 1) <= 0 ||
317 BN_cmp(out_shared_key, p_minus_1) == 0) {
318 OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
319 goto err;
320 }
321
322 ret = 1;
323
324 err:
325 BN_CTX_end(ctx);
326 return ret;
327 }
328
dh_compute_key_padded_no_self_test(unsigned char * out,const BIGNUM * peers_key,DH * dh)329 int dh_compute_key_padded_no_self_test(unsigned char *out,
330 const BIGNUM *peers_key, DH *dh) {
331 BN_CTX *ctx = BN_CTX_new();
332 if (ctx == NULL) {
333 return -1;
334 }
335 BN_CTX_start(ctx);
336
337 int dh_size = DH_size(dh);
338 int ret = -1;
339 BIGNUM *shared_key = BN_CTX_get(ctx);
340 if (shared_key &&
341 dh_compute_key(dh, shared_key, peers_key, ctx) &&
342 BN_bn2bin_padded(out, dh_size, shared_key)) {
343 ret = dh_size;
344 }
345
346 BN_CTX_end(ctx);
347 BN_CTX_free(ctx);
348 return ret;
349 }
350
DH_compute_key_padded(unsigned char * out,const BIGNUM * peers_key,DH * dh)351 int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
352 boringssl_ensure_ffdh_self_test();
353
354 return dh_compute_key_padded_no_self_test(out, peers_key, dh);
355 }
356
DH_compute_key(unsigned char * out,const BIGNUM * peers_key,DH * dh)357 int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
358 boringssl_ensure_ffdh_self_test();
359
360 BN_CTX *ctx = BN_CTX_new();
361 if (ctx == NULL) {
362 return -1;
363 }
364 BN_CTX_start(ctx);
365
366 int ret = -1;
367 BIGNUM *shared_key = BN_CTX_get(ctx);
368 if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
369 ret = BN_bn2bin(shared_key, out);
370 }
371
372 BN_CTX_end(ctx);
373 BN_CTX_free(ctx);
374 return ret;
375 }
376
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)377 int DH_compute_key_hashed(DH *dh, uint8_t *out, size_t *out_len,
378 size_t max_out_len, const BIGNUM *peers_key,
379 const EVP_MD *digest) {
380 *out_len = (size_t)-1;
381
382 const size_t digest_len = EVP_MD_size(digest);
383 if (digest_len > max_out_len) {
384 return 0;
385 }
386
387 FIPS_service_indicator_lock_state();
388
389 int ret = 0;
390 const size_t dh_len = DH_size(dh);
391 uint8_t *shared_bytes = OPENSSL_malloc(dh_len);
392 unsigned out_len_unsigned;
393 if (!shared_bytes ||
394 // SP 800-56A is ambiguous about whether the output should be padded prior
395 // to revision three. But revision three, section C.1, awkwardly specifies
396 // padding to the length of p.
397 //
398 // Also, padded output avoids side-channels, so is always strongly
399 // advisable.
400 DH_compute_key_padded(shared_bytes, peers_key, dh) != (int)dh_len ||
401 !EVP_Digest(shared_bytes, dh_len, out, &out_len_unsigned, digest, NULL) ||
402 out_len_unsigned != digest_len) {
403 goto err;
404 }
405
406 *out_len = digest_len;
407 ret = 1;
408
409 err:
410 FIPS_service_indicator_unlock_state();
411 OPENSSL_free(shared_bytes);
412 return ret;
413 }
414
DH_size(const DH * dh)415 int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
416
DH_num_bits(const DH * dh)417 unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
418
DH_up_ref(DH * dh)419 int DH_up_ref(DH *dh) {
420 CRYPTO_refcount_inc(&dh->references);
421 return 1;
422 }
423
DH_get_rfc7919_2048(void)424 DH *DH_get_rfc7919_2048(void) {
425 // This is the prime from https://tools.ietf.org/html/rfc7919#appendix-A.1,
426 // which is specifically approved for FIPS in appendix D of SP 800-56Ar3.
427 static const BN_ULONG kFFDHE2048Data[] = {
428 TOBN(0xffffffff, 0xffffffff), TOBN(0x886b4238, 0x61285c97),
429 TOBN(0xc6f34a26, 0xc1b2effa), TOBN(0xc58ef183, 0x7d1683b2),
430 TOBN(0x3bb5fcbc, 0x2ec22005), TOBN(0xc3fe3b1b, 0x4c6fad73),
431 TOBN(0x8e4f1232, 0xeef28183), TOBN(0x9172fe9c, 0xe98583ff),
432 TOBN(0xc03404cd, 0x28342f61), TOBN(0x9e02fce1, 0xcdf7e2ec),
433 TOBN(0x0b07a7c8, 0xee0a6d70), TOBN(0xae56ede7, 0x6372bb19),
434 TOBN(0x1d4f42a3, 0xde394df4), TOBN(0xb96adab7, 0x60d7f468),
435 TOBN(0xd108a94b, 0xb2c8e3fb), TOBN(0xbc0ab182, 0xb324fb61),
436 TOBN(0x30acca4f, 0x483a797a), TOBN(0x1df158a1, 0x36ade735),
437 TOBN(0xe2a689da, 0xf3efe872), TOBN(0x984f0c70, 0xe0e68b77),
438 TOBN(0xb557135e, 0x7f57c935), TOBN(0x85636555, 0x3ded1af3),
439 TOBN(0x2433f51f, 0x5f066ed0), TOBN(0xd3df1ed5, 0xd5fd6561),
440 TOBN(0xf681b202, 0xaec4617a), TOBN(0x7d2fe363, 0x630c75d8),
441 TOBN(0xcc939dce, 0x249b3ef9), TOBN(0xa9e13641, 0x146433fb),
442 TOBN(0xd8b9c583, 0xce2d3695), TOBN(0xafdc5620, 0x273d3cf1),
443 TOBN(0xadf85458, 0xa2bb4a9a), TOBN(0xffffffff, 0xffffffff),
444 };
445
446 BIGNUM *const ffdhe2048_p = BN_new();
447 BIGNUM *const ffdhe2048_q = BN_new();
448 BIGNUM *const ffdhe2048_g = BN_new();
449 DH *const dh = DH_new();
450
451 if (!ffdhe2048_p || !ffdhe2048_q || !ffdhe2048_g || !dh) {
452 goto err;
453 }
454
455 bn_set_static_words(ffdhe2048_p, kFFDHE2048Data,
456 OPENSSL_ARRAY_SIZE(kFFDHE2048Data));
457
458 if (!BN_rshift1(ffdhe2048_q, ffdhe2048_p) ||
459 !BN_set_word(ffdhe2048_g, 2) ||
460 !DH_set0_pqg(dh, ffdhe2048_p, ffdhe2048_q, ffdhe2048_g)) {
461 goto err;
462 }
463
464 return dh;
465
466 err:
467 BN_free(ffdhe2048_p);
468 BN_free(ffdhe2048_q);
469 BN_free(ffdhe2048_g);
470 DH_free(dh);
471 return NULL;
472 }
473