• 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 
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