Home | History | Annotate | Line # | Download | only in dist
      1 /*	$NetBSD: dh.c,v 1.22 2026/04/08 18:58:40 christos Exp $	*/
      2 /* $OpenBSD: dh.c,v 1.76 2026/02/08 19:54:31 dtucker Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2000 Niels Provos.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "includes.h"
     29 __RCSID("$NetBSD: dh.c,v 1.22 2026/04/08 18:58:40 christos Exp $");
     30 
     31 #include <errno.h>
     32 #include <stdarg.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <string.h>
     36 #include <time.h>
     37 #include <limits.h>
     38 
     39 #include <openssl/bn.h>
     40 #include <openssl/dh.h>
     41 
     42 #include "dh.h"
     43 #include "pathnames.h"
     44 #include "log.h"
     45 #include "misc.h"
     46 #include "random.h"
     47 #include "ssherr.h"
     48 
     49 static const char *moduli_filename;
     50 
     51 void dh_set_moduli_file(const char *filename)
     52 {
     53 	moduli_filename = filename;
     54 }
     55 
     56 static const char * get_moduli_filename(void)
     57 {
     58 	return moduli_filename ? moduli_filename : _PATH_DH_MODULI;
     59 }
     60 
     61 static int
     62 parse_prime(int linenum, char *line, struct dhgroup *dhg)
     63 {
     64 	char *cp, *arg;
     65 	char *strsize, *gen, *prime;
     66 	const char *errstr = NULL;
     67 	long long n;
     68 
     69 	dhg->p = dhg->g = NULL;
     70 	cp = line;
     71 	if ((arg = strdelim(&cp)) == NULL)
     72 		return 0;
     73 	/* Ignore leading whitespace */
     74 	if (*arg == '\0')
     75 		arg = strdelim(&cp);
     76 	if (!arg || !*arg || *arg == '#')
     77 		return 0;
     78 
     79 	/* time */
     80 	if (cp == NULL || *arg == '\0')
     81 		goto truncated;
     82 	arg = strsep(&cp, " "); /* type */
     83 	if (cp == NULL || *arg == '\0')
     84 		goto truncated;
     85 	/* Ensure this is a safe prime */
     86 	n = strtonum(arg, 0, 5, &errstr);
     87 	if (errstr != NULL || n != MODULI_TYPE_SAFE) {
     88 		error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
     89 		goto fail;
     90 	}
     91 	arg = strsep(&cp, " "); /* tests */
     92 	if (cp == NULL || *arg == '\0')
     93 		goto truncated;
     94 	/* Ensure prime has been tested and is not composite */
     95 	n = strtonum(arg, 0, 0x1f, &errstr);
     96 	if (errstr != NULL ||
     97 	    (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
     98 		error("moduli:%d: invalid moduli tests flag", linenum);
     99 		goto fail;
    100 	}
    101 	arg = strsep(&cp, " "); /* tries */
    102 	if (cp == NULL || *arg == '\0')
    103 		goto truncated;
    104 	n = strtonum(arg, 0, 1<<30, &errstr);
    105 	if (errstr != NULL || n == 0) {
    106 		error("moduli:%d: invalid primality trial count", linenum);
    107 		goto fail;
    108 	}
    109 	strsize = strsep(&cp, " "); /* size */
    110 	if (cp == NULL || *strsize == '\0' ||
    111 	    (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
    112 	    errstr) {
    113 		error("moduli:%d: invalid prime length", linenum);
    114 		goto fail;
    115 	}
    116 	/* The whole group is one bit larger */
    117 	dhg->size++;
    118 	gen = strsep(&cp, " "); /* gen */
    119 	if (cp == NULL || *gen == '\0')
    120 		goto truncated;
    121 	prime = strsep(&cp, " "); /* prime */
    122 	if (cp != NULL || *prime == '\0') {
    123  truncated:
    124 		error("moduli:%d: truncated", linenum);
    125 		goto fail;
    126 	}
    127 
    128 	if ((dhg->g = BN_new()) == NULL ||
    129 	    (dhg->p = BN_new()) == NULL) {
    130 		error("parse_prime: BN_new failed");
    131 		goto fail;
    132 	}
    133 	if (BN_hex2bn(&dhg->g, gen) == 0) {
    134 		error("moduli:%d: could not parse generator value", linenum);
    135 		goto fail;
    136 	}
    137 	if (BN_hex2bn(&dhg->p, prime) == 0) {
    138 		error("moduli:%d: could not parse prime value", linenum);
    139 		goto fail;
    140 	}
    141 	if (BN_num_bits(dhg->p) != dhg->size) {
    142 		error("moduli:%d: prime has wrong size: actual %d listed %d",
    143 		    linenum, BN_num_bits(dhg->p), dhg->size - 1);
    144 		goto fail;
    145 	}
    146 	if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
    147 		error("moduli:%d: generator is invalid", linenum);
    148 		goto fail;
    149 	}
    150 	return 1;
    151 
    152  fail:
    153 	BN_clear_free(dhg->g);
    154 	BN_clear_free(dhg->p);
    155 	dhg->g = dhg->p = NULL;
    156 	return 0;
    157 }
    158 
    159 DH *
    160 choose_dh(int min, int wantbits, int max)
    161 {
    162 	FILE *f;
    163 	char *line = NULL;
    164 	size_t linesize = 0;
    165 	int best, bestcount, which, linenum;
    166 	struct dhgroup dhg;
    167 
    168 	if ((f = fopen(get_moduli_filename(), "r")) == NULL) {
    169 		logit("WARNING: could not open %s (%s), using fixed modulus",
    170 		    get_moduli_filename(), strerror(errno));
    171 		return (dh_new_group_fallback(max));
    172 	}
    173 
    174 	linenum = 0;
    175 	best = bestcount = 0;
    176 	while (getline(&line, &linesize, f) != -1) {
    177 		linenum++;
    178 		if (!parse_prime(linenum, line, &dhg))
    179 			continue;
    180 		BN_clear_free(dhg.g);
    181 		BN_clear_free(dhg.p);
    182 
    183 		if (dhg.size > max || dhg.size < min)
    184 			continue;
    185 
    186 		if ((dhg.size > wantbits && dhg.size < best) ||
    187 		    (dhg.size > best && best < wantbits)) {
    188 			best = dhg.size;
    189 			bestcount = 0;
    190 		}
    191 		if (dhg.size == best)
    192 			bestcount++;
    193 	}
    194 	free(line);
    195 	line = NULL;
    196 	linesize = 0;
    197 	rewind(f);
    198 
    199 	if (bestcount == 0) {
    200 		fclose(f);
    201 		logit("WARNING: no suitable primes (size %d/%d/%d) in %s",
    202 		    min, wantbits, max, get_moduli_filename());
    203 		return NULL;
    204 	}
    205 	which = arc4random_uniform(bestcount);
    206 
    207 	linenum = 0;
    208 	bestcount = 0;
    209 	while (getline(&line, &linesize, f) != -1) {
    210 		linenum++;
    211 		if (!parse_prime(linenum, line, &dhg))
    212 			continue;
    213 		if ((dhg.size > max || dhg.size < min) ||
    214 		    dhg.size != best ||
    215 		    bestcount++ != which) {
    216 			BN_clear_free(dhg.g);
    217 			BN_clear_free(dhg.p);
    218 			continue;
    219 		}
    220 		break;
    221 	}
    222 	free(line);
    223 	line = NULL;
    224 	fclose(f);
    225 	if (bestcount != which + 1) {
    226 		logit("WARNING: selected prime disappeared in %s, giving up",
    227 		    get_moduli_filename());
    228 		return (dh_new_group_fallback(max));
    229 	}
    230 
    231 	return (dh_new_group(dhg.g, dhg.p));
    232 }
    233 
    234 /* diffie-hellman-groupN-sha1 */
    235 
    236 int
    237 dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
    238 {
    239 	int i;
    240 	int n = BN_num_bits(dh_pub);
    241 	int bits_set = 0;
    242 	BIGNUM *tmp;
    243 	const BIGNUM *dh_p;
    244 
    245 	DH_get0_pqg(dh, &dh_p, NULL, NULL);
    246 
    247 	if (BN_is_negative(dh_pub)) {
    248 		logit("invalid public DH value: negative");
    249 		return 0;
    250 	}
    251 	if (BN_cmp(dh_pub, BN_value_one()) != 1) {	/* pub_exp <= 1 */
    252 		logit("invalid public DH value: <= 1");
    253 		return 0;
    254 	}
    255 
    256 	if ((tmp = BN_new()) == NULL) {
    257 		error_f("BN_new failed");
    258 		return 0;
    259 	}
    260 	if (!BN_sub(tmp, dh_p, BN_value_one()) ||
    261 	    BN_cmp(dh_pub, tmp) != -1) {		/* pub_exp > p-2 */
    262 		BN_clear_free(tmp);
    263 		logit("invalid public DH value: >= p-1");
    264 		return 0;
    265 	}
    266 	BN_clear_free(tmp);
    267 
    268 	for (i = 0; i <= n; i++)
    269 		if (BN_is_bit_set(dh_pub, i))
    270 			bits_set++;
    271 	debug2("bits set: %d/%d", bits_set, BN_num_bits(dh_p));
    272 
    273 	/*
    274 	 * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
    275 	 */
    276 	if (bits_set < 4) {
    277 		logit("invalid public DH value (%d/%d)",
    278 		    bits_set, BN_num_bits(dh_p));
    279 		return 0;
    280 	}
    281 	return 1;
    282 }
    283 
    284 int
    285 dh_gen_key(DH *dh, int need)
    286 {
    287 	int pbits;
    288 	const BIGNUM *dh_p, *pub_key;
    289 
    290 	DH_get0_pqg(dh, &dh_p, NULL, NULL);
    291 
    292 	if (need < 0 || dh_p == NULL ||
    293 	    (pbits = BN_num_bits(dh_p)) <= 0 ||
    294 	    need > INT_MAX / 2 || 2 * need > pbits)
    295 		return SSH_ERR_INVALID_ARGUMENT;
    296 	if (need < 256)
    297 		need = 256;
    298 	/*
    299 	 * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
    300 	 * so double requested need here.
    301 	 */
    302 	if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
    303 		return SSH_ERR_LIBCRYPTO_ERROR;
    304 
    305 	if (DH_generate_key(dh) == 0)
    306 		return SSH_ERR_LIBCRYPTO_ERROR;
    307 	DH_get0_key(dh, &pub_key, NULL);
    308 	if (!dh_pub_is_valid(dh, pub_key))
    309 		return SSH_ERR_INVALID_FORMAT;
    310 	return 0;
    311 }
    312 
    313 DH *
    314 dh_new_group_asc(const char *gen, const char *modulus)
    315 {
    316 	DH *dh;
    317 	BIGNUM *dh_p = NULL, *dh_g = NULL;
    318 
    319 	if ((dh = DH_new()) == NULL)
    320 		return NULL;
    321 	if (BN_hex2bn(&dh_p, modulus) == 0 ||
    322 	    BN_hex2bn(&dh_g, gen) == 0)
    323 		goto fail;
    324 	if (!DH_set0_pqg(dh, dh_p, NULL, dh_g))
    325 		goto fail;
    326 	return dh;
    327  fail:
    328 	DH_free(dh);
    329 	BN_clear_free(dh_p);
    330 	BN_clear_free(dh_g);
    331 	return NULL;
    332 }
    333 
    334 /*
    335  * This just returns the group, we still need to generate the exchange
    336  * value.
    337  */
    338 DH *
    339 dh_new_group(BIGNUM *gen, BIGNUM *modulus)
    340 {
    341 	DH *dh;
    342 
    343 	if ((dh = DH_new()) == NULL)
    344 		return NULL;
    345 	if (!DH_set0_pqg(dh, modulus, NULL, gen)) {
    346 		DH_free(dh);
    347 		return NULL;
    348 	}
    349 
    350 	return dh;
    351 }
    352 
    353 /* rfc2409 "Second Oakley Group" (1024 bits) */
    354 DH *
    355 dh_new_group1(void)
    356 {
    357 	static const char *gen = "2", *group1 =
    358 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
    359 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
    360 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
    361 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
    362 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
    363 	    "FFFFFFFF" "FFFFFFFF";
    364 
    365 	return (dh_new_group_asc(gen, group1));
    366 }
    367 
    368 /* rfc3526 group 14 "2048-bit MODP Group" */
    369 DH *
    370 dh_new_group14(void)
    371 {
    372 	static const char *gen = "2", *group14 =
    373 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
    374 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
    375 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
    376 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
    377 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
    378 	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
    379 	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
    380 	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
    381 	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
    382 	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
    383 	    "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
    384 
    385 	return (dh_new_group_asc(gen, group14));
    386 }
    387 
    388 /* rfc3526 group 16 "4096-bit MODP Group" */
    389 DH *
    390 dh_new_group16(void)
    391 {
    392 	static const char *gen = "2", *group16 =
    393 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
    394 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
    395 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
    396 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
    397 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
    398 	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
    399 	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
    400 	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
    401 	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
    402 	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
    403 	    "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
    404 	    "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
    405 	    "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
    406 	    "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
    407 	    "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
    408 	    "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
    409 	    "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
    410 	    "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
    411 	    "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
    412 	    "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
    413 	    "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
    414 	    "FFFFFFFF" "FFFFFFFF";
    415 
    416 	return (dh_new_group_asc(gen, group16));
    417 }
    418 
    419 /* rfc3526 group 18 "8192-bit MODP Group" */
    420 DH *
    421 dh_new_group18(void)
    422 {
    423 	static const char *gen = "2", *group18 =
    424 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
    425 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
    426 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
    427 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
    428 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
    429 	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
    430 	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
    431 	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
    432 	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
    433 	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
    434 	    "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
    435 	    "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
    436 	    "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
    437 	    "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
    438 	    "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
    439 	    "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
    440 	    "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
    441 	    "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
    442 	    "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
    443 	    "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
    444 	    "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34028492"
    445 	    "36C3FAB4" "D27C7026" "C1D4DCB2" "602646DE" "C9751E76" "3DBA37BD"
    446 	    "F8FF9406" "AD9E530E" "E5DB382F" "413001AE" "B06A53ED" "9027D831"
    447 	    "179727B0" "865A8918" "DA3EDBEB" "CF9B14ED" "44CE6CBA" "CED4BB1B"
    448 	    "DB7F1447" "E6CC254B" "33205151" "2BD7AF42" "6FB8F401" "378CD2BF"
    449 	    "5983CA01" "C64B92EC" "F032EA15" "D1721D03" "F482D7CE" "6E74FEF6"
    450 	    "D55E702F" "46980C82" "B5A84031" "900B1C9E" "59E7C97F" "BEC7E8F3"
    451 	    "23A97A7E" "36CC88BE" "0F1D45B7" "FF585AC5" "4BD407B2" "2B4154AA"
    452 	    "CC8F6D7E" "BF48E1D8" "14CC5ED2" "0F8037E0" "A79715EE" "F29BE328"
    453 	    "06A1D58B" "B7C5DA76" "F550AA3D" "8A1FBFF0" "EB19CCB1" "A313D55C"
    454 	    "DA56C9EC" "2EF29632" "387FE8D7" "6E3C0468" "043E8F66" "3F4860EE"
    455 	    "12BF2D5B" "0B7474D6" "E694F91E" "6DBE1159" "74A3926F" "12FEE5E4"
    456 	    "38777CB6" "A932DF8C" "D8BEC4D0" "73B931BA" "3BC832B6" "8D9DD300"
    457 	    "741FA7BF" "8AFC47ED" "2576F693" "6BA42466" "3AAB639C" "5AE4F568"
    458 	    "3423B474" "2BF1C978" "238F16CB" "E39D652D" "E3FDB8BE" "FC848AD9"
    459 	    "22222E04" "A4037C07" "13EB57A8" "1A23F0C7" "3473FC64" "6CEA306B"
    460 	    "4BCBC886" "2F8385DD" "FA9D4B7F" "A2C087E8" "79683303" "ED5BDD3A"
    461 	    "062B3CF5" "B3A278A6" "6D2A13F8" "3F44F82D" "DF310EE0" "74AB6A36"
    462 	    "4597E899" "A0255DC1" "64F31CC5" "0846851D" "F9AB4819" "5DED7EA1"
    463 	    "B1D510BD" "7EE74D73" "FAF36BC3" "1ECFA268" "359046F4" "EB879F92"
    464 	    "4009438B" "481C6CD7" "889A002E" "D5EE382B" "C9190DA6" "FC026E47"
    465 	    "9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71"
    466 	    "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF";
    467 
    468 	return (dh_new_group_asc(gen, group18));
    469 }
    470 
    471 /* Select fallback group used by DH-GEX if moduli file cannot be read. */
    472 DH *
    473 dh_new_group_fallback(int max)
    474 {
    475 	debug3_f("requested max size %d", max);
    476 	if (max < 3072) {
    477 		debug3("using 2k bit group 14");
    478 		return dh_new_group14();
    479 	} else if (max < 6144) {
    480 		debug3("using 4k bit group 16");
    481 		return dh_new_group16();
    482 	}
    483 	debug3("using 8k bit group 18");
    484 	return dh_new_group18();
    485 }
    486 
    487 /*
    488  * Estimates the group order for a Diffie-Hellman group that has an
    489  * attack complexity approximately the same as O(2**bits).
    490  * Values from NIST Special Publication 800-57: Recommendation for Key
    491  * Management Part 1 (rev 3) limited by the recommended maximum value
    492  * from RFC4419 section 3.
    493  */
    494 u_int
    495 dh_estimate(int bits)
    496 {
    497 	if (bits <= 112)
    498 		return 2048;
    499 	if (bits <= 128)
    500 		return 3072;
    501 	if (bits <= 192)
    502 		return 7680;
    503 	return 8192;
    504 }
    505