1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com).
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to.  The following conditions
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed.
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package.
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in the
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    documentation and/or other materials provided with the distribution.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    must display the following acknowledgement:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes cryptographic software written by
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *     Eric Young (eay@cryptsoft.com)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    being used are not cryptographic related :-).
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE.
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/dh.h>
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h>
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/buf.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ex_data.h>
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/thread.h>
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../internal.h"
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
71fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley#define OPENSSL_DH_MAX_MODULUS_BITS 10000
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
73e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
75fad6327e4112082b1e77e89a995723f26bd5a9aaAdam LangleyDH *DH_new(void) {
764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  DH *dh = OPENSSL_malloc(sizeof(DH));
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (dh == NULL) {
78b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
8269939df2891f62f7f00ff2ac275f1cd81a67454cRobert Sloan  OPENSSL_memset(dh, 0, sizeof(DH));
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dh->references = 1;
874139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  CRYPTO_new_ex_data(&dh->ex_data);
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return dh;
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid DH_free(DH *dh) {
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (dh == NULL) {
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
97f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data);
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
103e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_MONT_CTX_free(dh->method_mont_p);
104e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->p);
105e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->g);
106e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->q);
107e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->j);
108e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  OPENSSL_free(dh->seed);
109e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->counter);
110e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->pub_key);
111e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->priv_key);
112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  OPENSSL_free(dh);
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
117c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminvoid DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
118c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin                 const BIGNUM **out_priv_key) {
119c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (out_pub_key != NULL) {
120c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    *out_pub_key = dh->pub_key;
121c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
122c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (out_priv_key != NULL) {
123c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    *out_priv_key = dh->priv_key;
124c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
125c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin}
126c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
127c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjaminvoid DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
128c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin                 const BIGNUM **out_g) {
129c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (out_p != NULL) {
130c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    *out_p = dh->p;
131c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
132c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (out_q != NULL) {
133c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    *out_q = dh->q;
134c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
135c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  if (out_g != NULL) {
136c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin    *out_g = dh->g;
137c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin  }
138c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin}
139c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
141fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* We generate DH parameters as follows
142fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * find a prime q which is prime_bits/2 bits long.
143fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * p=(2*q)+1 or (p-1)/2 = q
144fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * For this case, g is a generator if
145fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
146fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Since the factors of p-1 are q and 2, we just need to check
147fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * g^2 mod p != 1 and g^q mod p != 1.
148fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
149fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Having said all that,
150fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * there is another special case method for the generators 2, 3 and 5.
151fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 2, p mod 24 == 11
152fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 3, p mod 12 == 5  <<<<< does not work for safe primes.
153fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 5, p mod 10 == 3 or 7
154fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
155fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
156fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * special generators and for answering some of my questions.
157fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
158fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * I've implemented the second simple method :-).
159fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Since DH should be using a safe prime (both p and q are prime),
160fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * this generator function can take a very very long time to run.
161fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   */
162fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
163fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* Actually there is no reason to insist that 'generator' be a generator.
164fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * It's just as OK (and in some sense better) to use a generator of the
165fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * order-q subgroup.
166fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   */
167fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
168fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *t1, *t2;
169fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int g, ok = 0;
170fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX *ctx = NULL;
171fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
172fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
173fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
174fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
175fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
176fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_start(ctx);
177fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  t1 = BN_CTX_get(ctx);
178fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  t2 = BN_CTX_get(ctx);
179fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (t1 == NULL || t2 == NULL) {
180fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
181fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
182fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
183fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* Make sure |dh| has the necessary elements */
184fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->p == NULL) {
185fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    dh->p = BN_new();
186fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->p == NULL) {
187fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
188fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
189fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
190fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->g == NULL) {
191fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    dh->g = BN_new();
192fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->g == NULL) {
193fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
194fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
195fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
196fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
197fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generator <= 1) {
198fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR);
199fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
200fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
201fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generator == DH_GENERATOR_2) {
202fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 24)) {
203fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
204fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
205fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 11)) {
206fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
207fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
208fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = 2;
209fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else if (generator == DH_GENERATOR_5) {
210fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 10)) {
211fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
212fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
213fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 3)) {
214fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
215fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
216fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    /* BN_set_word(t3,7); just have to miss
217fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * out on these ones :-( */
218fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = 5;
219fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
220fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    /* in the general case, don't worry if 'generator' is a
221fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * generator or not: since we are using safe primes,
222fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * it will generate either an order-q or an order-2q group,
223fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * which both is OK */
224fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 2)) {
225fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
226fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
227fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 1)) {
228fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
229fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
230fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = generator;
231fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
232fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
233fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) {
234fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
235fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
236fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_GENCB_call(cb, 3, 0)) {
237fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
238fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
239fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_set_word(dh->g, g)) {
240fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
241fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
242fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ok = 1;
243fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
244fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
245fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!ok) {
246fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
247fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
248fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
249fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx != NULL) {
250fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_end(ctx);
251fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_free(ctx);
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
253fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ok;
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_generate_key(DH *dh) {
257fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int ok = 0;
258fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int generate_new_key = 0;
2594139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  BN_CTX *ctx = NULL;
260fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *pub_key = NULL, *priv_key = NULL;
261fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
2624139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
2634139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
2644139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    goto err;
2654139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
2664139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
267fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
268fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
269fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
271fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
272fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
273fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    priv_key = BN_new();
274fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (priv_key == NULL) {
275fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
276fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
277fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    generate_new_key = 1;
278fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
279fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    priv_key = dh->priv_key;
280fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
281fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
282fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->pub_key == NULL) {
283fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    pub_key = BN_new();
284fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (pub_key == NULL) {
285fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
286fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
287fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
288fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    pub_key = dh->pub_key;
289fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
290fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
2914969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
2924969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                              dh->p, ctx)) {
293fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
294fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
295fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
296fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generate_new_key) {
297fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->q) {
298c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (!BN_rand_range_ex(priv_key, 2, dh->q)) {
299c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        goto err;
300c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      }
301fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    } else {
302fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      /* secret exponent length */
303c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      unsigned priv_bits = dh->priv_length;
304c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      if (priv_bits == 0) {
305c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        const unsigned p_bits = BN_num_bits(dh->p);
306c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        if (p_bits == 0) {
307c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin          goto err;
308c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        }
309c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
310c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin        priv_bits = p_bits - 1;
311c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin      }
312c895d6b1c580258e72e1ed3fcc86d38970ded9e1David Benjamin
313f0c4a6c4bbde5229ceb86740703243fe5c436aadDavid Benjamin      if (!BN_rand(priv_key, priv_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
314fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley        goto err;
315fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      }
316fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
317fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
318fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
319b0b45c63bbbf16b7f5ff3cbe3f1d0905108038aaSteven Valdez  if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
320d316cba52b5aeac660e03068e65dd873669ce1dbDavid Benjamin                                 dh->method_mont_p)) {
321fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
322fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
323fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
324fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  dh->pub_key = pub_key;
325fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  dh->priv_key = priv_key;
326fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ok = 1;
327fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
328fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
329fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ok != 1) {
330fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
331fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
332fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
333fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->pub_key == NULL) {
334fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_free(pub_key);
335fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
336fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
337fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_free(priv_key);
338fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
339fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_free(ctx);
340fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ok;
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
344fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX *ctx = NULL;
345fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *shared_key;
346fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int ret = -1;
347fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int check_result;
348fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
349fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
350fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
351fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
352fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
353fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
354fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
355fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
356fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
358fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_start(ctx);
359fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  shared_key = BN_CTX_get(ctx);
360fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (shared_key == NULL) {
361fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
362fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
363fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
364fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
365fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
366fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
367fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
368fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
3694969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
3704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin                              dh->p, ctx)) {
371fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
372fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
373fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
374fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
375fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
376fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
377fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
378fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
379b0b45c63bbbf16b7f5ff3cbe3f1d0905108038aaSteven Valdez  if (!BN_mod_exp_mont_consttime(shared_key, peers_key, dh->priv_key, dh->p,
380b0b45c63bbbf16b7f5ff3cbe3f1d0905108038aaSteven Valdez                                 ctx, dh->method_mont_p)) {
381fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
382fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
383fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
384fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
385fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ret = BN_bn2bin(shared_key, out);
386fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
387fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
388fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx != NULL) {
389fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_end(ctx);
390fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_free(ctx);
391fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
392fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
393fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ret;
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
396d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
398f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyunsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
399f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
400f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyint DH_up_ref(DH *dh) {
401f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  CRYPTO_refcount_inc(&dh->references);
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIGNUM *a = NULL;
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (src) {
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a = BN_dup(src);
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!a) {
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
415e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_free(*dst);
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *dst = a;
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
419d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
420d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (is_x942 == -1) {
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    is_x942 = !!from->q;
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_bn_cpy(&to->p, from->p) ||
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !int_dh_bn_cpy(&to->g, from->g)) {
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!is_x942) {
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
433d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_bn_cpy(&to->q, from->q) ||
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !int_dh_bn_cpy(&to->j, from->j)) {
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
438e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  OPENSSL_free(to->seed);
439e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  to->seed = NULL;
440e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  to->seedlen = 0;
441e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (from->seed) {
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    to->seed = BUF_memdup(from->seed, from->seedlen);
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!to->seed) {
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
447d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    to->seedlen = from->seedlen;
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
449d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
450d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
451d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
452d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
453d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyDH *DHparams_dup(const DH *dh) {
454d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  DH *ret = DH_new();
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ret) {
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
458d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_param_copy(ret, dh, -1)) {
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    DH_free(ret);
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
462d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
464d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
466d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4674139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
4688ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                        CRYPTO_EX_dup *dup_unused, CRYPTO_EX_free *free_func) {
469e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int index;
4708ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
4714139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                               free_func)) {
472e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return -1;
473e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
474e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return index;
475d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
476d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
477d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_set_ex_data(DH *d, int idx, void *arg) {
478fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
479d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
481d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *DH_get_ex_data(DH *d, int idx) {
482fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return CRYPTO_get_ex_data(&d->ex_data, idx);
483d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
484