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
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h"
69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../internal.h"
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
72fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley#define OPENSSL_DH_MAX_MODULUS_BITS 10000
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
76fad6327e4112082b1e77e89a995723f26bd5a9aaAdam LangleyDH *DH_new(void) {
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  DH *dh = (DH *)OPENSSL_malloc(sizeof(DH));
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (dh == NULL) {
79b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  memset(dh, 0, sizeof(DH));
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  dh->references = 1;
884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  CRYPTO_new_ex_data(&dh->ex_data);
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return dh;
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid DH_free(DH *dh) {
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (dh == NULL) {
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
98f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return;
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_free_ex_data(&g_ex_data_class, dh, &dh->ex_data);
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
104e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_MONT_CTX_free(dh->method_mont_p);
105e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->p);
106e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->g);
107e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->q);
108e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->j);
109e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  OPENSSL_free(dh->seed);
110e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->counter);
111e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->pub_key);
112e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root  BN_clear_free(dh->priv_key);
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  OPENSSL_free(dh);
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
119fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* We generate DH parameters as follows
120fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * find a prime q which is prime_bits/2 bits long.
121fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * p=(2*q)+1 or (p-1)/2 = q
122fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * For this case, g is a generator if
123fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
124fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Since the factors of p-1 are q and 2, we just need to check
125fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * g^2 mod p != 1 and g^q mod p != 1.
126fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
127fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Having said all that,
128fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * there is another special case method for the generators 2, 3 and 5.
129fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 2, p mod 24 == 11
130fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 3, p mod 12 == 5  <<<<< does not work for safe primes.
131fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * for 5, p mod 10 == 3 or 7
132fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
133fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Thanks to Phil Karn <karn@qualcomm.com> for the pointers about the
134fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * special generators and for answering some of my questions.
135fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   *
136fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * I've implemented the second simple method :-).
137fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * Since DH should be using a safe prime (both p and q are prime),
138fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * this generator function can take a very very long time to run.
139fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   */
140fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
141fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* Actually there is no reason to insist that 'generator' be a generator.
142fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * It's just as OK (and in some sense better) to use a generator of the
143fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   * order-q subgroup.
144fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley   */
145fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
146fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *t1, *t2;
147fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int g, ok = 0;
148fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX *ctx = NULL;
149fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
150fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
151fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
152fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
153fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
154fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_start(ctx);
155fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  t1 = BN_CTX_get(ctx);
156fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  t2 = BN_CTX_get(ctx);
157fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (t1 == NULL || t2 == NULL) {
158fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
159fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
160fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
161fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  /* Make sure |dh| has the necessary elements */
162fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->p == NULL) {
163fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    dh->p = BN_new();
164fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->p == NULL) {
165fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
166fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
167fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
168fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->g == NULL) {
169fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    dh->g = BN_new();
170fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->g == NULL) {
171fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
172fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
173fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
174fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
175fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generator <= 1) {
176fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_BAD_GENERATOR);
177fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
178fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
179fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generator == DH_GENERATOR_2) {
180fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 24)) {
181fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
182fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
183fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 11)) {
184fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
185fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
186fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = 2;
187fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else if (generator == DH_GENERATOR_5) {
188fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 10)) {
189fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
190fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
191fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 3)) {
192fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
193fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
194fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    /* BN_set_word(t3,7); just have to miss
195fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * out on these ones :-( */
196fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = 5;
197fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
198fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    /* in the general case, don't worry if 'generator' is a
199fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * generator or not: since we are using safe primes,
200fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * it will generate either an order-q or an order-2q group,
201fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley     * which both is OK */
202fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t1, 2)) {
203fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
204fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
205fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (!BN_set_word(t2, 1)) {
206fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
207fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
208fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    g = generator;
209fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
210fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
211fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_generate_prime_ex(dh->p, prime_bits, 1, t1, t2, cb)) {
212fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
213fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
214fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_GENCB_call(cb, 3, 0)) {
215fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
216fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
217fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_set_word(dh->g, g)) {
218fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
219fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
220fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ok = 1;
221fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
222fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
223fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!ok) {
224fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
225fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
226fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
227fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx != NULL) {
228fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_end(ctx);
229fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_free(ctx);
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
231fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ok;
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_generate_key(DH *dh) {
235fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int ok = 0;
236fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int generate_new_key = 0;
237fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  unsigned l;
2384139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  BN_CTX *ctx = NULL;
239fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_MONT_CTX *mont = NULL;
240fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *pub_key = NULL, *priv_key = NULL;
241fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM local_priv;
242fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
2434139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
2444139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
2454139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    goto err;
2464139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  }
2474139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley
248fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
249fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
250fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
252fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
253fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
254fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    priv_key = BN_new();
255fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (priv_key == NULL) {
256fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
257fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
258fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    generate_new_key = 1;
259fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
260fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    priv_key = dh->priv_key;
261fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
262fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
263fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->pub_key == NULL) {
264fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    pub_key = BN_new();
265fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (pub_key == NULL) {
266fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      goto err;
267fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
268fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  } else {
269fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    pub_key = dh->pub_key;
270fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
271fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
272fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
273fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                dh->p, ctx);
274fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!mont) {
275fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
276fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
277fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
278fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (generate_new_key) {
279fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    if (dh->q) {
280fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      do {
281fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley        if (!BN_rand_range(priv_key, dh->q)) {
282fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley          goto err;
283fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley        }
284fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      } while (BN_is_zero(priv_key) || BN_is_one(priv_key));
285fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    } else {
286fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      /* secret exponent length */
287fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      DH_check_standard_parameters(dh);
288fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1;
289fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      if (!BN_rand(priv_key, l, 0, 0)) {
290fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley        goto err;
291fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley      }
292fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    }
293fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
294fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
295fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
296fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) {
297fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
298fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
299fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
300fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  dh->pub_key = pub_key;
301fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  dh->priv_key = priv_key;
302fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ok = 1;
303fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
304fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
305fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ok != 1) {
306fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
307fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
308fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
309fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->pub_key == NULL) {
310fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_free(pub_key);
311fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
312fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
313fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_free(priv_key);
314fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
315fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_free(ctx);
316fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ok;
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
320fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX *ctx = NULL;
321fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_MONT_CTX *mont = NULL;
322fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM *shared_key;
323fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int ret = -1;
324fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  int check_result;
325fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BIGNUM local_priv;
326fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
327fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
328fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
329fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
330fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
331fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
332fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ctx = BN_CTX_new();
333fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx == NULL) {
334fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
336fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_CTX_start(ctx);
337fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  shared_key = BN_CTX_get(ctx);
338fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (shared_key == NULL) {
339fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
340fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
341fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
342fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (dh->priv_key == NULL) {
343fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
344fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
345fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
346fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
347fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
348fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                                dh->p, ctx);
349fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!mont) {
350fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
351fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
352fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
353fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
354fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
355fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
356fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
357fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
358fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
359fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (!BN_mod_exp_mont(shared_key, peers_key, &local_priv, dh->p, ctx,
360fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley                       mont)) {
361fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
362fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    goto err;
363fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
364fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
365fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  ret = BN_bn2bin(shared_key, out);
366fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
367fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langleyerr:
368fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  if (ctx != NULL) {
369fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_end(ctx);
370fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley    BN_CTX_free(ctx);
371fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  }
372fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley
373fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return ret;
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
378f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyunsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
379f4e427204234da139fd0585def4b4e22502e33f0Adam Langley
380f4e427204234da139fd0585def4b4e22502e33f0Adam Langleyint DH_up_ref(DH *dh) {
381f4e427204234da139fd0585def4b4e22502e33f0Adam Langley  CRYPTO_refcount_inc(&dh->references);
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int int_dh_bn_cpy(BIGNUM **dst, const BIGNUM *src) {
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  BIGNUM *a = NULL;
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (src) {
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    a = BN_dup(src);
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!a) {
391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
392d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
395e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  BN_free(*dst);
396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  *dst = a;
397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
398d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
400d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int int_dh_param_copy(DH *to, const DH *from, int is_x942) {
401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (is_x942 == -1) {
402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    is_x942 = !!from->q;
403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_bn_cpy(&to->p, from->p) ||
405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !int_dh_bn_cpy(&to->g, from->g)) {
406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!is_x942) {
410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 1;
411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
412d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_bn_cpy(&to->q, from->q) ||
414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      !int_dh_bn_cpy(&to->j, from->j)) {
415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
418e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  OPENSSL_free(to->seed);
419e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  to->seed = NULL;
420e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  to->seedlen = 0;
421e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
422d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (from->seed) {
423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    to->seed = BUF_memdup(from->seed, from->seedlen);
424d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (!to->seed) {
425d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
426d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
427d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    to->seedlen = from->seedlen;
428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
429d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
431d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
433d9e397b599b13d642138480a28c14db7a136bf0Adam LangleyDH *DHparams_dup(const DH *dh) {
434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  DH *ret = DH_new();
435d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!ret) {
436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
437d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!int_dh_param_copy(ret, dh, -1)) {
440d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    DH_free(ret);
441d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
443d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
444d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return ret;
445d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
446d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
4474139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langleyint DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
448d9e397b599b13d642138480a28c14db7a136bf0Adam Langley                        CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
449e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  int index;
4504139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func,
4514139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley                               free_func)) {
452e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return -1;
453e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
454e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return index;
455d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
456d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
457d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint DH_set_ex_data(DH *d, int idx, void *arg) {
458fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
459d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
460d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
461d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *DH_get_ex_data(DH *d, int idx) {
462fad6327e4112082b1e77e89a995723f26bd5a9aaAdam Langley  return CRYPTO_get_ex_data(&d->ex_data, idx);
463d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
464