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