1*19261079SEd Maste /* $OpenBSD: dh.c,v 1.74 2021/04/03 06:18:40 djm Exp $ */
25b9b2fafSBrian Feldman /*
35b9b2fafSBrian Feldman * Copyright (c) 2000 Niels Provos. All rights reserved.
45b9b2fafSBrian Feldman *
55b9b2fafSBrian Feldman * Redistribution and use in source and binary forms, with or without
65b9b2fafSBrian Feldman * modification, are permitted provided that the following conditions
75b9b2fafSBrian Feldman * are met:
85b9b2fafSBrian Feldman * 1. Redistributions of source code must retain the above copyright
95b9b2fafSBrian Feldman * notice, this list of conditions and the following disclaimer.
105b9b2fafSBrian Feldman * 2. Redistributions in binary form must reproduce the above copyright
115b9b2fafSBrian Feldman * notice, this list of conditions and the following disclaimer in the
125b9b2fafSBrian Feldman * documentation and/or other materials provided with the distribution.
135b9b2fafSBrian Feldman *
145b9b2fafSBrian Feldman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
155b9b2fafSBrian Feldman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
165b9b2fafSBrian Feldman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
175b9b2fafSBrian Feldman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
185b9b2fafSBrian Feldman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
195b9b2fafSBrian Feldman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
205b9b2fafSBrian Feldman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
215b9b2fafSBrian Feldman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225b9b2fafSBrian Feldman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
235b9b2fafSBrian Feldman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245b9b2fafSBrian Feldman */
255b9b2fafSBrian Feldman
265b9b2fafSBrian Feldman #include "includes.h"
275b9b2fafSBrian Feldman
2847dd1d1bSDag-Erling Smørgrav #ifdef WITH_OPENSSL
295b9b2fafSBrian Feldman
30076ad2f8SDag-Erling Smørgrav #include <errno.h>
31761efaa7SDag-Erling Smørgrav #include <stdarg.h>
32761efaa7SDag-Erling Smørgrav #include <stdio.h>
33761efaa7SDag-Erling Smørgrav #include <stdlib.h>
34761efaa7SDag-Erling Smørgrav #include <string.h>
35bc5531deSDag-Erling Smørgrav #include <limits.h>
36761efaa7SDag-Erling Smørgrav
37*19261079SEd Maste #include <openssl/bn.h>
38*19261079SEd Maste #include <openssl/dh.h>
39*19261079SEd Maste
405b9b2fafSBrian Feldman #include "dh.h"
411e8db6e2SBrian Feldman #include "pathnames.h"
421e8db6e2SBrian Feldman #include "log.h"
431e8db6e2SBrian Feldman #include "misc.h"
44bc5531deSDag-Erling Smørgrav #include "ssherr.h"
455b9b2fafSBrian Feldman
462a01feabSEd Maste #include "openbsd-compat/openssl-compat.h"
472a01feabSEd Maste
48*19261079SEd Maste static const char *moduli_filename;
49*19261079SEd Maste
dh_set_moduli_file(const char * filename)50*19261079SEd Maste void dh_set_moduli_file(const char *filename)
51*19261079SEd Maste {
52*19261079SEd Maste moduli_filename = filename;
53*19261079SEd Maste }
54*19261079SEd Maste
get_moduli_filename(void)55*19261079SEd Maste static const char * get_moduli_filename(void)
56*19261079SEd Maste {
57*19261079SEd Maste return moduli_filename ? moduli_filename : _PATH_DH_MODULI;
58*19261079SEd Maste }
59*19261079SEd Maste
60ae1f160dSDag-Erling Smørgrav static int
parse_prime(int linenum,char * line,struct dhgroup * dhg)615b9b2fafSBrian Feldman parse_prime(int linenum, char *line, struct dhgroup *dhg)
625b9b2fafSBrian Feldman {
635b9b2fafSBrian Feldman char *cp, *arg;
645b9b2fafSBrian Feldman char *strsize, *gen, *prime;
65761efaa7SDag-Erling Smørgrav const char *errstr = NULL;
66d4af9e69SDag-Erling Smørgrav long long n;
675b9b2fafSBrian Feldman
68e4a9863fSDag-Erling Smørgrav dhg->p = dhg->g = NULL;
695b9b2fafSBrian Feldman cp = line;
70761efaa7SDag-Erling Smørgrav if ((arg = strdelim(&cp)) == NULL)
71761efaa7SDag-Erling Smørgrav return 0;
725b9b2fafSBrian Feldman /* Ignore leading whitespace */
735b9b2fafSBrian Feldman if (*arg == '\0')
745b9b2fafSBrian Feldman arg = strdelim(&cp);
754b17dab0SDag-Erling Smørgrav if (!arg || !*arg || *arg == '#')
765b9b2fafSBrian Feldman return 0;
775b9b2fafSBrian Feldman
785b9b2fafSBrian Feldman /* time */
795b9b2fafSBrian Feldman if (cp == NULL || *arg == '\0')
80e4a9863fSDag-Erling Smørgrav goto truncated;
815b9b2fafSBrian Feldman arg = strsep(&cp, " "); /* type */
825b9b2fafSBrian Feldman if (cp == NULL || *arg == '\0')
83e4a9863fSDag-Erling Smørgrav goto truncated;
84d4af9e69SDag-Erling Smørgrav /* Ensure this is a safe prime */
85d4af9e69SDag-Erling Smørgrav n = strtonum(arg, 0, 5, &errstr);
86e4a9863fSDag-Erling Smørgrav if (errstr != NULL || n != MODULI_TYPE_SAFE) {
87e4a9863fSDag-Erling Smørgrav error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
88d4af9e69SDag-Erling Smørgrav goto fail;
89e4a9863fSDag-Erling Smørgrav }
905b9b2fafSBrian Feldman arg = strsep(&cp, " "); /* tests */
915b9b2fafSBrian Feldman if (cp == NULL || *arg == '\0')
92e4a9863fSDag-Erling Smørgrav goto truncated;
93d4af9e69SDag-Erling Smørgrav /* Ensure prime has been tested and is not composite */
94d4af9e69SDag-Erling Smørgrav n = strtonum(arg, 0, 0x1f, &errstr);
95d4af9e69SDag-Erling Smørgrav if (errstr != NULL ||
96e4a9863fSDag-Erling Smørgrav (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
97e4a9863fSDag-Erling Smørgrav error("moduli:%d: invalid moduli tests flag", linenum);
98d4af9e69SDag-Erling Smørgrav goto fail;
99e4a9863fSDag-Erling Smørgrav }
1005b9b2fafSBrian Feldman arg = strsep(&cp, " "); /* tries */
1015b9b2fafSBrian Feldman if (cp == NULL || *arg == '\0')
102e4a9863fSDag-Erling Smørgrav goto truncated;
103d4af9e69SDag-Erling Smørgrav n = strtonum(arg, 0, 1<<30, &errstr);
104e4a9863fSDag-Erling Smørgrav if (errstr != NULL || n == 0) {
105e4a9863fSDag-Erling Smørgrav error("moduli:%d: invalid primality trial count", linenum);
106d4af9e69SDag-Erling Smørgrav goto fail;
107e4a9863fSDag-Erling Smørgrav }
1085b9b2fafSBrian Feldman strsize = strsep(&cp, " "); /* size */
1095b9b2fafSBrian Feldman if (cp == NULL || *strsize == '\0' ||
110b15c8340SDag-Erling Smørgrav (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
111e4a9863fSDag-Erling Smørgrav errstr) {
112e4a9863fSDag-Erling Smørgrav error("moduli:%d: invalid prime length", linenum);
1135b9b2fafSBrian Feldman goto fail;
114e4a9863fSDag-Erling Smørgrav }
1151e8db6e2SBrian Feldman /* The whole group is one bit larger */
1161e8db6e2SBrian Feldman dhg->size++;
1175b9b2fafSBrian Feldman gen = strsep(&cp, " "); /* gen */
1185b9b2fafSBrian Feldman if (cp == NULL || *gen == '\0')
119e4a9863fSDag-Erling Smørgrav goto truncated;
1205b9b2fafSBrian Feldman prime = strsep(&cp, " "); /* prime */
121e4a9863fSDag-Erling Smørgrav if (cp != NULL || *prime == '\0') {
122e4a9863fSDag-Erling Smørgrav truncated:
123e4a9863fSDag-Erling Smørgrav error("moduli:%d: truncated", linenum);
1245b9b2fafSBrian Feldman goto fail;
125e4a9863fSDag-Erling Smørgrav }
1265b9b2fafSBrian Feldman
127bc5531deSDag-Erling Smørgrav if ((dhg->g = BN_new()) == NULL ||
128bc5531deSDag-Erling Smørgrav (dhg->p = BN_new()) == NULL) {
129bc5531deSDag-Erling Smørgrav error("parse_prime: BN_new failed");
130bc5531deSDag-Erling Smørgrav goto fail;
131bc5531deSDag-Erling Smørgrav }
132e4a9863fSDag-Erling Smørgrav if (BN_hex2bn(&dhg->g, gen) == 0) {
133e4a9863fSDag-Erling Smørgrav error("moduli:%d: could not parse generator value", linenum);
134e4a9863fSDag-Erling Smørgrav goto fail;
135e4a9863fSDag-Erling Smørgrav }
136e4a9863fSDag-Erling Smørgrav if (BN_hex2bn(&dhg->p, prime) == 0) {
137e4a9863fSDag-Erling Smørgrav error("moduli:%d: could not parse prime value", linenum);
138e4a9863fSDag-Erling Smørgrav goto fail;
139e4a9863fSDag-Erling Smørgrav }
140e4a9863fSDag-Erling Smørgrav if (BN_num_bits(dhg->p) != dhg->size) {
141e4a9863fSDag-Erling Smørgrav error("moduli:%d: prime has wrong size: actual %d listed %d",
142e4a9863fSDag-Erling Smørgrav linenum, BN_num_bits(dhg->p), dhg->size - 1);
143e4a9863fSDag-Erling Smørgrav goto fail;
144e4a9863fSDag-Erling Smørgrav }
145e4a9863fSDag-Erling Smørgrav if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
146e4a9863fSDag-Erling Smørgrav error("moduli:%d: generator is invalid", linenum);
147e4a9863fSDag-Erling Smørgrav goto fail;
148e4a9863fSDag-Erling Smørgrav }
149e4a9863fSDag-Erling Smørgrav return 1;
1501e8db6e2SBrian Feldman
1515b9b2fafSBrian Feldman fail:
152e4a9863fSDag-Erling Smørgrav BN_clear_free(dhg->g);
153e4a9863fSDag-Erling Smørgrav BN_clear_free(dhg->p);
154e4a9863fSDag-Erling Smørgrav dhg->g = dhg->p = NULL;
155e4a9863fSDag-Erling Smørgrav return 0;
1565b9b2fafSBrian Feldman }
1575b9b2fafSBrian Feldman
1585b9b2fafSBrian Feldman DH *
choose_dh(int min,int wantbits,int max)1591e8db6e2SBrian Feldman choose_dh(int min, int wantbits, int max)
1605b9b2fafSBrian Feldman {
1615b9b2fafSBrian Feldman FILE *f;
162190cef3dSDag-Erling Smørgrav char *line = NULL;
163190cef3dSDag-Erling Smørgrav size_t linesize = 0;
164190cef3dSDag-Erling Smørgrav int best, bestcount, which, linenum;
1655b9b2fafSBrian Feldman struct dhgroup dhg;
1665b9b2fafSBrian Feldman
167*19261079SEd Maste if ((f = fopen(get_moduli_filename(), "r")) == NULL) {
168ca86bcf2SDag-Erling Smørgrav logit("WARNING: could not open %s (%s), using fixed modulus",
169*19261079SEd Maste get_moduli_filename(), strerror(errno));
170557f75e5SDag-Erling Smørgrav return (dh_new_group_fallback(max));
1715b9b2fafSBrian Feldman }
1725b9b2fafSBrian Feldman
1735b9b2fafSBrian Feldman linenum = 0;
1745b9b2fafSBrian Feldman best = bestcount = 0;
175190cef3dSDag-Erling Smørgrav while (getline(&line, &linesize, f) != -1) {
1765b9b2fafSBrian Feldman linenum++;
1775b9b2fafSBrian Feldman if (!parse_prime(linenum, line, &dhg))
1785b9b2fafSBrian Feldman continue;
179ae1f160dSDag-Erling Smørgrav BN_clear_free(dhg.g);
180ae1f160dSDag-Erling Smørgrav BN_clear_free(dhg.p);
1815b9b2fafSBrian Feldman
1821e8db6e2SBrian Feldman if (dhg.size > max || dhg.size < min)
1831e8db6e2SBrian Feldman continue;
1841e8db6e2SBrian Feldman
1851e8db6e2SBrian Feldman if ((dhg.size > wantbits && dhg.size < best) ||
1861e8db6e2SBrian Feldman (dhg.size > best && best < wantbits)) {
1875b9b2fafSBrian Feldman best = dhg.size;
1885b9b2fafSBrian Feldman bestcount = 0;
1895b9b2fafSBrian Feldman }
1905b9b2fafSBrian Feldman if (dhg.size == best)
1915b9b2fafSBrian Feldman bestcount++;
1925b9b2fafSBrian Feldman }
193190cef3dSDag-Erling Smørgrav free(line);
194190cef3dSDag-Erling Smørgrav line = NULL;
195190cef3dSDag-Erling Smørgrav linesize = 0;
196ae1f160dSDag-Erling Smørgrav rewind(f);
1975b9b2fafSBrian Feldman
1985b9b2fafSBrian Feldman if (bestcount == 0) {
199ae1f160dSDag-Erling Smørgrav fclose(f);
200*19261079SEd Maste logit("WARNING: no suitable primes in %s",
201*19261079SEd Maste get_moduli_filename());
202557f75e5SDag-Erling Smørgrav return (dh_new_group_fallback(max));
2035b9b2fafSBrian Feldman }
2042f513db7SEd Maste which = arc4random_uniform(bestcount);
2055b9b2fafSBrian Feldman
2065b9b2fafSBrian Feldman linenum = 0;
2072f513db7SEd Maste bestcount = 0;
208190cef3dSDag-Erling Smørgrav while (getline(&line, &linesize, f) != -1) {
2092f513db7SEd Maste linenum++;
2105b9b2fafSBrian Feldman if (!parse_prime(linenum, line, &dhg))
2115b9b2fafSBrian Feldman continue;
2121e8db6e2SBrian Feldman if ((dhg.size > max || dhg.size < min) ||
2131e8db6e2SBrian Feldman dhg.size != best ||
2142f513db7SEd Maste bestcount++ != which) {
215ae1f160dSDag-Erling Smørgrav BN_clear_free(dhg.g);
216ae1f160dSDag-Erling Smørgrav BN_clear_free(dhg.p);
2175b9b2fafSBrian Feldman continue;
2185b9b2fafSBrian Feldman }
2195b9b2fafSBrian Feldman break;
2205b9b2fafSBrian Feldman }
221190cef3dSDag-Erling Smørgrav free(line);
222190cef3dSDag-Erling Smørgrav line = NULL;
2235b9b2fafSBrian Feldman fclose(f);
2242f513db7SEd Maste if (bestcount != which + 1) {
2252f513db7SEd Maste logit("WARNING: selected prime disappeared in %s, giving up",
226*19261079SEd Maste get_moduli_filename());
227557f75e5SDag-Erling Smørgrav return (dh_new_group_fallback(max));
228bc5531deSDag-Erling Smørgrav }
2295b9b2fafSBrian Feldman
2305b9b2fafSBrian Feldman return (dh_new_group(dhg.g, dhg.p));
2315b9b2fafSBrian Feldman }
2321e8db6e2SBrian Feldman
233d74d50a8SDag-Erling Smørgrav /* diffie-hellman-groupN-sha1 */
2341e8db6e2SBrian Feldman
2351e8db6e2SBrian Feldman int
dh_pub_is_valid(const DH * dh,const BIGNUM * dh_pub)2362a01feabSEd Maste dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
2371e8db6e2SBrian Feldman {
2381e8db6e2SBrian Feldman int i;
2391e8db6e2SBrian Feldman int n = BN_num_bits(dh_pub);
2401e8db6e2SBrian Feldman int bits_set = 0;
241761efaa7SDag-Erling Smørgrav BIGNUM *tmp;
2422a01feabSEd Maste const BIGNUM *dh_p;
2431e8db6e2SBrian Feldman
2442a01feabSEd Maste DH_get0_pqg(dh, &dh_p, NULL, NULL);
2452a01feabSEd Maste
2462a01feabSEd Maste if (BN_is_negative(dh_pub)) {
247d4af9e69SDag-Erling Smørgrav logit("invalid public DH value: negative");
2481e8db6e2SBrian Feldman return 0;
2491e8db6e2SBrian Feldman }
250761efaa7SDag-Erling Smørgrav if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */
251761efaa7SDag-Erling Smørgrav logit("invalid public DH value: <= 1");
252761efaa7SDag-Erling Smørgrav return 0;
253761efaa7SDag-Erling Smørgrav }
254761efaa7SDag-Erling Smørgrav
255d4af9e69SDag-Erling Smørgrav if ((tmp = BN_new()) == NULL) {
256*19261079SEd Maste error_f("BN_new failed");
257d4af9e69SDag-Erling Smørgrav return 0;
258d4af9e69SDag-Erling Smørgrav }
2592a01feabSEd Maste if (!BN_sub(tmp, dh_p, BN_value_one()) ||
260761efaa7SDag-Erling Smørgrav BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */
261761efaa7SDag-Erling Smørgrav BN_clear_free(tmp);
262761efaa7SDag-Erling Smørgrav logit("invalid public DH value: >= p-1");
263761efaa7SDag-Erling Smørgrav return 0;
264761efaa7SDag-Erling Smørgrav }
265761efaa7SDag-Erling Smørgrav BN_clear_free(tmp);
266761efaa7SDag-Erling Smørgrav
2671e8db6e2SBrian Feldman for (i = 0; i <= n; i++)
2681e8db6e2SBrian Feldman if (BN_is_bit_set(dh_pub, i))
2691e8db6e2SBrian Feldman bits_set++;
2702a01feabSEd Maste debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p));
2711e8db6e2SBrian Feldman
272076ad2f8SDag-Erling Smørgrav /*
273076ad2f8SDag-Erling Smørgrav * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
274076ad2f8SDag-Erling Smørgrav */
275076ad2f8SDag-Erling Smørgrav if (bits_set < 4) {
276076ad2f8SDag-Erling Smørgrav logit("invalid public DH value (%d/%d)",
2772a01feabSEd Maste bits_set, BN_num_bits(dh_p));
2781e8db6e2SBrian Feldman return 0;
2791e8db6e2SBrian Feldman }
280076ad2f8SDag-Erling Smørgrav return 1;
281076ad2f8SDag-Erling Smørgrav }
2821e8db6e2SBrian Feldman
283bc5531deSDag-Erling Smørgrav int
dh_gen_key(DH * dh,int need)2841e8db6e2SBrian Feldman dh_gen_key(DH *dh, int need)
2851e8db6e2SBrian Feldman {
286f7167e0eSDag-Erling Smørgrav int pbits;
2872a01feabSEd Maste const BIGNUM *dh_p, *pub_key;
2881e8db6e2SBrian Feldman
2892a01feabSEd Maste DH_get0_pqg(dh, &dh_p, NULL, NULL);
2902a01feabSEd Maste
2912a01feabSEd Maste if (need < 0 || dh_p == NULL ||
2922a01feabSEd Maste (pbits = BN_num_bits(dh_p)) <= 0 ||
293557f75e5SDag-Erling Smørgrav need > INT_MAX / 2 || 2 * need > pbits)
294bc5531deSDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT;
295076ad2f8SDag-Erling Smørgrav if (need < 256)
296076ad2f8SDag-Erling Smørgrav need = 256;
297076ad2f8SDag-Erling Smørgrav /*
298076ad2f8SDag-Erling Smørgrav * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
299076ad2f8SDag-Erling Smørgrav * so double requested need here.
300076ad2f8SDag-Erling Smørgrav */
3012a01feabSEd Maste if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
302bc5531deSDag-Erling Smørgrav return SSH_ERR_LIBCRYPTO_ERROR;
3032a01feabSEd Maste
3042a01feabSEd Maste if (DH_generate_key(dh) == 0)
3052a01feabSEd Maste return SSH_ERR_LIBCRYPTO_ERROR;
3062a01feabSEd Maste DH_get0_key(dh, &pub_key, NULL);
3072a01feabSEd Maste if (!dh_pub_is_valid(dh, pub_key))
3082a01feabSEd Maste return SSH_ERR_INVALID_FORMAT;
309bc5531deSDag-Erling Smørgrav return 0;
3101e8db6e2SBrian Feldman }
3111e8db6e2SBrian Feldman
3121e8db6e2SBrian Feldman DH *
dh_new_group_asc(const char * gen,const char * modulus)3131e8db6e2SBrian Feldman dh_new_group_asc(const char *gen, const char *modulus)
3141e8db6e2SBrian Feldman {
3151e8db6e2SBrian Feldman DH *dh;
3162a01feabSEd Maste BIGNUM *dh_p = NULL, *dh_g = NULL;
3171e8db6e2SBrian Feldman
318ae1f160dSDag-Erling Smørgrav if ((dh = DH_new()) == NULL)
319bc5531deSDag-Erling Smørgrav return NULL;
3202a01feabSEd Maste if (BN_hex2bn(&dh_p, modulus) == 0 ||
3212a01feabSEd Maste BN_hex2bn(&dh_g, gen) == 0)
3222a01feabSEd Maste goto fail;
3232a01feabSEd Maste if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
3242a01feabSEd Maste goto fail;
3252a01feabSEd Maste return dh;
3262a01feabSEd Maste fail:
327bc5531deSDag-Erling Smørgrav DH_free(dh);
3282a01feabSEd Maste BN_clear_free(dh_p);
3292a01feabSEd Maste BN_clear_free(dh_g);
330bc5531deSDag-Erling Smørgrav return NULL;
331bc5531deSDag-Erling Smørgrav }
3321e8db6e2SBrian Feldman
3331e8db6e2SBrian Feldman /*
3341e8db6e2SBrian Feldman * This just returns the group, we still need to generate the exchange
3351e8db6e2SBrian Feldman * value.
3361e8db6e2SBrian Feldman */
3371e8db6e2SBrian Feldman DH *
dh_new_group(BIGNUM * gen,BIGNUM * modulus)3381e8db6e2SBrian Feldman dh_new_group(BIGNUM *gen, BIGNUM *modulus)
3391e8db6e2SBrian Feldman {
3401e8db6e2SBrian Feldman DH *dh;
3411e8db6e2SBrian Feldman
342ae1f160dSDag-Erling Smørgrav if ((dh = DH_new()) == NULL)
343bc5531deSDag-Erling Smørgrav return NULL;
3442a01feabSEd Maste if (!DH_set0_pqg(dh, modulus, NULL, gen)) {
3452a01feabSEd Maste DH_free(dh);
3462a01feabSEd Maste return NULL;
3472a01feabSEd Maste }
3481e8db6e2SBrian Feldman
3492a01feabSEd Maste return dh;
3501e8db6e2SBrian Feldman }
3511e8db6e2SBrian Feldman
352076ad2f8SDag-Erling Smørgrav /* rfc2409 "Second Oakley Group" (1024 bits) */
3531e8db6e2SBrian Feldman DH *
dh_new_group1(void)3541e8db6e2SBrian Feldman dh_new_group1(void)
3551e8db6e2SBrian Feldman {
3561e8db6e2SBrian Feldman static char *gen = "2", *group1 =
3571e8db6e2SBrian Feldman "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
3581e8db6e2SBrian Feldman "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
3591e8db6e2SBrian Feldman "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
3601e8db6e2SBrian Feldman "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
3611e8db6e2SBrian Feldman "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
3621e8db6e2SBrian Feldman "FFFFFFFF" "FFFFFFFF";
3631e8db6e2SBrian Feldman
3641e8db6e2SBrian Feldman return (dh_new_group_asc(gen, group1));
3651e8db6e2SBrian Feldman }
3661e8db6e2SBrian Feldman
367076ad2f8SDag-Erling Smørgrav /* rfc3526 group 14 "2048-bit MODP Group" */
368d74d50a8SDag-Erling Smørgrav DH *
dh_new_group14(void)369d74d50a8SDag-Erling Smørgrav dh_new_group14(void)
370d74d50a8SDag-Erling Smørgrav {
371d74d50a8SDag-Erling Smørgrav static char *gen = "2", *group14 =
372d74d50a8SDag-Erling Smørgrav "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
373d74d50a8SDag-Erling Smørgrav "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
374d74d50a8SDag-Erling Smørgrav "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
375d74d50a8SDag-Erling Smørgrav "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
376d74d50a8SDag-Erling Smørgrav "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
377d74d50a8SDag-Erling Smørgrav "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
378d74d50a8SDag-Erling Smørgrav "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
379d74d50a8SDag-Erling Smørgrav "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
380d74d50a8SDag-Erling Smørgrav "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
381d74d50a8SDag-Erling Smørgrav "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
382d74d50a8SDag-Erling Smørgrav "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
383d74d50a8SDag-Erling Smørgrav
384d74d50a8SDag-Erling Smørgrav return (dh_new_group_asc(gen, group14));
385d74d50a8SDag-Erling Smørgrav }
386d74d50a8SDag-Erling Smørgrav
387076ad2f8SDag-Erling Smørgrav /* rfc3526 group 16 "4096-bit MODP Group" */
388557f75e5SDag-Erling Smørgrav DH *
dh_new_group16(void)389076ad2f8SDag-Erling Smørgrav dh_new_group16(void)
390557f75e5SDag-Erling Smørgrav {
391557f75e5SDag-Erling Smørgrav static char *gen = "2", *group16 =
392557f75e5SDag-Erling Smørgrav "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
393557f75e5SDag-Erling Smørgrav "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
394557f75e5SDag-Erling Smørgrav "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
395557f75e5SDag-Erling Smørgrav "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
396557f75e5SDag-Erling Smørgrav "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
397557f75e5SDag-Erling Smørgrav "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
398557f75e5SDag-Erling Smørgrav "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
399557f75e5SDag-Erling Smørgrav "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
400557f75e5SDag-Erling Smørgrav "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
401557f75e5SDag-Erling Smørgrav "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
402557f75e5SDag-Erling Smørgrav "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
403557f75e5SDag-Erling Smørgrav "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
404557f75e5SDag-Erling Smørgrav "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
405557f75e5SDag-Erling Smørgrav "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
406557f75e5SDag-Erling Smørgrav "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
407557f75e5SDag-Erling Smørgrav "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
408557f75e5SDag-Erling Smørgrav "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
409557f75e5SDag-Erling Smørgrav "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
410557f75e5SDag-Erling Smørgrav "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
411557f75e5SDag-Erling Smørgrav "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
412557f75e5SDag-Erling Smørgrav "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
413557f75e5SDag-Erling Smørgrav "FFFFFFFF" "FFFFFFFF";
414557f75e5SDag-Erling Smørgrav
415557f75e5SDag-Erling Smørgrav return (dh_new_group_asc(gen, group16));
416557f75e5SDag-Erling Smørgrav }
417557f75e5SDag-Erling Smørgrav
418076ad2f8SDag-Erling Smørgrav /* rfc3526 group 18 "8192-bit MODP Group" */
419076ad2f8SDag-Erling Smørgrav DH *
dh_new_group18(void)420076ad2f8SDag-Erling Smørgrav dh_new_group18(void)
421076ad2f8SDag-Erling Smørgrav {
422*19261079SEd Maste static char *gen = "2", *group18 =
423076ad2f8SDag-Erling Smørgrav "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
424076ad2f8SDag-Erling Smørgrav "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
425076ad2f8SDag-Erling Smørgrav "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
426076ad2f8SDag-Erling Smørgrav "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
427076ad2f8SDag-Erling Smørgrav "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
428076ad2f8SDag-Erling Smørgrav "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
429076ad2f8SDag-Erling Smørgrav "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
430076ad2f8SDag-Erling Smørgrav "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
431076ad2f8SDag-Erling Smørgrav "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
432076ad2f8SDag-Erling Smørgrav "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
433076ad2f8SDag-Erling Smørgrav "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
434076ad2f8SDag-Erling Smørgrav "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
435076ad2f8SDag-Erling Smørgrav "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
436076ad2f8SDag-Erling Smørgrav "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
437076ad2f8SDag-Erling Smørgrav "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
438076ad2f8SDag-Erling Smørgrav "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
439076ad2f8SDag-Erling Smørgrav "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
440076ad2f8SDag-Erling Smørgrav "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
441076ad2f8SDag-Erling Smørgrav "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
442076ad2f8SDag-Erling Smørgrav "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
443076ad2f8SDag-Erling Smørgrav "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492"
444076ad2f8SDag-Erling Smørgrav "36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD"
445076ad2f8SDag-Erling Smørgrav "F8FF9406" "AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831"
446076ad2f8SDag-Erling Smørgrav "179727B0" "865A8918" "DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B"
447076ad2f8SDag-Erling Smørgrav "DB7F1447" "E6CC254B" "33205151" "2BD7AF42" "6FB8F401" "378CD2BF"
448076ad2f8SDag-Erling Smørgrav "5983CA01" "C64B92EC" "F032EA15" "D1721D03" "F482D7CE" "6E74FEF6"
449076ad2f8SDag-Erling Smørgrav "D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" "BEC7E8F3"
450076ad2f8SDag-Erling Smørgrav "23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA"
451076ad2f8SDag-Erling Smørgrav "CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328"
452076ad2f8SDag-Erling Smørgrav "06A1D58B" "B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C"
453076ad2f8SDag-Erling Smørgrav "DA56C9EC" "2EF29632" "387FE8D7" "6E3C0468" "043E8F66" "3F4860EE"
454076ad2f8SDag-Erling Smørgrav "12BF2D5B" "0B7474D6" "E694F91E" "6DBE1159" "74A3926F" "12FEE5E4"
455076ad2f8SDag-Erling Smørgrav "38777CB6" "A932DF8C" "D8BEC4D0" "73B931BA" "3BC832B6" "8D9DD300"
456076ad2f8SDag-Erling Smørgrav "741FA7BF" "8AFC47ED" "2576F693" "6BA42466" "3AAB639C" "5AE4F568"
457076ad2f8SDag-Erling Smørgrav "3423B474" "2BF1C978" "238F16CB" "E39D652D" "E3FDB8BE" "FC848AD9"
458076ad2f8SDag-Erling Smørgrav "22222E04" "A4037C07" "13EB57A8" "1A23F0C7" "3473FC64" "6CEA306B"
459076ad2f8SDag-Erling Smørgrav "4BCBC886" "2F8385DD" "FA9D4B7F" "A2C087E8" "79683303" "ED5BDD3A"
460076ad2f8SDag-Erling Smørgrav "062B3CF5" "B3A278A6" "6D2A13F8" "3F44F82D" "DF310EE0" "74AB6A36"
461076ad2f8SDag-Erling Smørgrav "4597E899" "A0255DC1" "64F31CC5" "0846851D" "F9AB4819" "5DED7EA1"
462076ad2f8SDag-Erling Smørgrav "B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92"
463076ad2f8SDag-Erling Smørgrav "4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47"
464076ad2f8SDag-Erling Smørgrav "9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71"
465076ad2f8SDag-Erling Smørgrav "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF";
466076ad2f8SDag-Erling Smørgrav
467*19261079SEd Maste return (dh_new_group_asc(gen, group18));
468076ad2f8SDag-Erling Smørgrav }
469076ad2f8SDag-Erling Smørgrav
470076ad2f8SDag-Erling Smørgrav /* Select fallback group used by DH-GEX if moduli file cannot be read. */
471076ad2f8SDag-Erling Smørgrav DH *
dh_new_group_fallback(int max)472076ad2f8SDag-Erling Smørgrav dh_new_group_fallback(int max)
473076ad2f8SDag-Erling Smørgrav {
474*19261079SEd Maste debug3_f("requested max size %d", max);
475076ad2f8SDag-Erling Smørgrav if (max < 3072) {
476076ad2f8SDag-Erling Smørgrav debug3("using 2k bit group 14");
477076ad2f8SDag-Erling Smørgrav return dh_new_group14();
478076ad2f8SDag-Erling Smørgrav } else if (max < 6144) {
479076ad2f8SDag-Erling Smørgrav debug3("using 4k bit group 16");
480076ad2f8SDag-Erling Smørgrav return dh_new_group16();
481076ad2f8SDag-Erling Smørgrav }
482076ad2f8SDag-Erling Smørgrav debug3("using 8k bit group 18");
483076ad2f8SDag-Erling Smørgrav return dh_new_group18();
484076ad2f8SDag-Erling Smørgrav }
485076ad2f8SDag-Erling Smørgrav
486557f75e5SDag-Erling Smørgrav /*
4871e8db6e2SBrian Feldman * Estimates the group order for a Diffie-Hellman group that has an
488f7167e0eSDag-Erling Smørgrav * attack complexity approximately the same as O(2**bits).
489f7167e0eSDag-Erling Smørgrav * Values from NIST Special Publication 800-57: Recommendation for Key
490f7167e0eSDag-Erling Smørgrav * Management Part 1 (rev 3) limited by the recommended maximum value
491f7167e0eSDag-Erling Smørgrav * from RFC4419 section 3.
4921e8db6e2SBrian Feldman */
493bc5531deSDag-Erling Smørgrav u_int
dh_estimate(int bits)4941e8db6e2SBrian Feldman dh_estimate(int bits)
4951e8db6e2SBrian Feldman {
496f7167e0eSDag-Erling Smørgrav if (bits <= 112)
497f7167e0eSDag-Erling Smørgrav return 2048;
498efcad6b7SDag-Erling Smørgrav if (bits <= 128)
499f7167e0eSDag-Erling Smørgrav return 3072;
500efcad6b7SDag-Erling Smørgrav if (bits <= 192)
501f7167e0eSDag-Erling Smørgrav return 7680;
502f7167e0eSDag-Erling Smørgrav return 8192;
5031e8db6e2SBrian Feldman }
50447dd1d1bSDag-Erling Smørgrav
50547dd1d1bSDag-Erling Smørgrav #endif /* WITH_OPENSSL */
506