• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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