xref: /freebsd/crypto/openssh/dh.c (revision b15c83408cb1e9b86c1895af0f097de05fc92ccf)
1b15c8340SDag-Erling Smørgrav /* $OpenBSD: dh.c,v 1.48 2009/10/01 11:37:33 grunk 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 
28761efaa7SDag-Erling Smørgrav #include <sys/param.h>
295b9b2fafSBrian Feldman 
305b9b2fafSBrian Feldman #include <openssl/bn.h>
315b9b2fafSBrian Feldman #include <openssl/dh.h>
325b9b2fafSBrian Feldman 
33761efaa7SDag-Erling Smørgrav #include <stdarg.h>
34761efaa7SDag-Erling Smørgrav #include <stdio.h>
35761efaa7SDag-Erling Smørgrav #include <stdlib.h>
36761efaa7SDag-Erling Smørgrav #include <string.h>
37761efaa7SDag-Erling Smørgrav 
385b9b2fafSBrian Feldman #include "dh.h"
391e8db6e2SBrian Feldman #include "pathnames.h"
401e8db6e2SBrian Feldman #include "log.h"
411e8db6e2SBrian Feldman #include "misc.h"
425b9b2fafSBrian Feldman 
43ae1f160dSDag-Erling Smørgrav static int
445b9b2fafSBrian Feldman parse_prime(int linenum, char *line, struct dhgroup *dhg)
455b9b2fafSBrian Feldman {
465b9b2fafSBrian Feldman 	char *cp, *arg;
475b9b2fafSBrian Feldman 	char *strsize, *gen, *prime;
48761efaa7SDag-Erling Smørgrav 	const char *errstr = NULL;
49d4af9e69SDag-Erling Smørgrav 	long long n;
505b9b2fafSBrian Feldman 
515b9b2fafSBrian Feldman 	cp = line;
52761efaa7SDag-Erling Smørgrav 	if ((arg = strdelim(&cp)) == NULL)
53761efaa7SDag-Erling Smørgrav 		return 0;
545b9b2fafSBrian Feldman 	/* Ignore leading whitespace */
555b9b2fafSBrian Feldman 	if (*arg == '\0')
565b9b2fafSBrian Feldman 		arg = strdelim(&cp);
574b17dab0SDag-Erling Smørgrav 	if (!arg || !*arg || *arg == '#')
585b9b2fafSBrian Feldman 		return 0;
595b9b2fafSBrian Feldman 
605b9b2fafSBrian Feldman 	/* time */
615b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
625b9b2fafSBrian Feldman 		goto fail;
635b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* type */
645b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
655b9b2fafSBrian Feldman 		goto fail;
66d4af9e69SDag-Erling Smørgrav 	/* Ensure this is a safe prime */
67d4af9e69SDag-Erling Smørgrav 	n = strtonum(arg, 0, 5, &errstr);
68d4af9e69SDag-Erling Smørgrav 	if (errstr != NULL || n != MODULI_TYPE_SAFE)
69d4af9e69SDag-Erling Smørgrav 		goto fail;
705b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* tests */
715b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
725b9b2fafSBrian Feldman 		goto fail;
73d4af9e69SDag-Erling Smørgrav 	/* Ensure prime has been tested and is not composite */
74d4af9e69SDag-Erling Smørgrav 	n = strtonum(arg, 0, 0x1f, &errstr);
75d4af9e69SDag-Erling Smørgrav 	if (errstr != NULL ||
76d4af9e69SDag-Erling Smørgrav 	    (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE))
77d4af9e69SDag-Erling Smørgrav 		goto fail;
785b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* tries */
795b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
805b9b2fafSBrian Feldman 		goto fail;
81d4af9e69SDag-Erling Smørgrav 	n = strtonum(arg, 0, 1<<30, &errstr);
82d4af9e69SDag-Erling Smørgrav 	if (errstr != NULL || n == 0)
83d4af9e69SDag-Erling Smørgrav 		goto fail;
845b9b2fafSBrian Feldman 	strsize = strsep(&cp, " "); /* size */
855b9b2fafSBrian Feldman 	if (cp == NULL || *strsize == '\0' ||
86b15c8340SDag-Erling Smørgrav 	    (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
87761efaa7SDag-Erling Smørgrav 	    errstr)
885b9b2fafSBrian Feldman 		goto fail;
891e8db6e2SBrian Feldman 	/* The whole group is one bit larger */
901e8db6e2SBrian Feldman 	dhg->size++;
915b9b2fafSBrian Feldman 	gen = strsep(&cp, " "); /* gen */
925b9b2fafSBrian Feldman 	if (cp == NULL || *gen == '\0')
935b9b2fafSBrian Feldman 		goto fail;
945b9b2fafSBrian Feldman 	prime = strsep(&cp, " "); /* prime */
955b9b2fafSBrian Feldman 	if (cp != NULL || *prime == '\0')
965b9b2fafSBrian Feldman 		goto fail;
975b9b2fafSBrian Feldman 
98ae1f160dSDag-Erling Smørgrav 	if ((dhg->g = BN_new()) == NULL)
99ae1f160dSDag-Erling Smørgrav 		fatal("parse_prime: BN_new failed");
100ae1f160dSDag-Erling Smørgrav 	if ((dhg->p = BN_new()) == NULL)
101ae1f160dSDag-Erling Smørgrav 		fatal("parse_prime: BN_new failed");
1021e8db6e2SBrian Feldman 	if (BN_hex2bn(&dhg->g, gen) == 0)
1031e8db6e2SBrian Feldman 		goto failclean;
1041e8db6e2SBrian Feldman 
1051e8db6e2SBrian Feldman 	if (BN_hex2bn(&dhg->p, prime) == 0)
1061e8db6e2SBrian Feldman 		goto failclean;
1071e8db6e2SBrian Feldman 
1081e8db6e2SBrian Feldman 	if (BN_num_bits(dhg->p) != dhg->size)
1091e8db6e2SBrian Feldman 		goto failclean;
1105b9b2fafSBrian Feldman 
11152028650SDag-Erling Smørgrav 	if (BN_is_zero(dhg->g) || BN_is_one(dhg->g))
11252028650SDag-Erling Smørgrav 		goto failclean;
11352028650SDag-Erling Smørgrav 
1145b9b2fafSBrian Feldman 	return (1);
1151e8db6e2SBrian Feldman 
1161e8db6e2SBrian Feldman  failclean:
117ae1f160dSDag-Erling Smørgrav 	BN_clear_free(dhg->g);
118ae1f160dSDag-Erling Smørgrav 	BN_clear_free(dhg->p);
1195b9b2fafSBrian Feldman  fail:
1201e8db6e2SBrian Feldman 	error("Bad prime description in line %d", linenum);
1215b9b2fafSBrian Feldman 	return (0);
1225b9b2fafSBrian Feldman }
1235b9b2fafSBrian Feldman 
1245b9b2fafSBrian Feldman DH *
1251e8db6e2SBrian Feldman choose_dh(int min, int wantbits, int max)
1265b9b2fafSBrian Feldman {
1275b9b2fafSBrian Feldman 	FILE *f;
12852028650SDag-Erling Smørgrav 	char line[4096];
1295b9b2fafSBrian Feldman 	int best, bestcount, which;
1305b9b2fafSBrian Feldman 	int linenum;
1315b9b2fafSBrian Feldman 	struct dhgroup dhg;
1325b9b2fafSBrian Feldman 
133ae1f160dSDag-Erling Smørgrav 	if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
134ae1f160dSDag-Erling Smørgrav 	    (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
135d74d50a8SDag-Erling Smørgrav 		logit("WARNING: %s does not exist, using fixed modulus",
136d74d50a8SDag-Erling Smørgrav 		    _PATH_DH_MODULI);
137d74d50a8SDag-Erling Smørgrav 		return (dh_new_group14());
1385b9b2fafSBrian Feldman 	}
1395b9b2fafSBrian Feldman 
1405b9b2fafSBrian Feldman 	linenum = 0;
1415b9b2fafSBrian Feldman 	best = bestcount = 0;
1425b9b2fafSBrian Feldman 	while (fgets(line, sizeof(line), f)) {
1435b9b2fafSBrian Feldman 		linenum++;
1445b9b2fafSBrian Feldman 		if (!parse_prime(linenum, line, &dhg))
1455b9b2fafSBrian Feldman 			continue;
146ae1f160dSDag-Erling Smørgrav 		BN_clear_free(dhg.g);
147ae1f160dSDag-Erling Smørgrav 		BN_clear_free(dhg.p);
1485b9b2fafSBrian Feldman 
1491e8db6e2SBrian Feldman 		if (dhg.size > max || dhg.size < min)
1501e8db6e2SBrian Feldman 			continue;
1511e8db6e2SBrian Feldman 
1521e8db6e2SBrian Feldman 		if ((dhg.size > wantbits && dhg.size < best) ||
1531e8db6e2SBrian Feldman 		    (dhg.size > best && best < wantbits)) {
1545b9b2fafSBrian Feldman 			best = dhg.size;
1555b9b2fafSBrian Feldman 			bestcount = 0;
1565b9b2fafSBrian Feldman 		}
1575b9b2fafSBrian Feldman 		if (dhg.size == best)
1585b9b2fafSBrian Feldman 			bestcount++;
1595b9b2fafSBrian Feldman 	}
160ae1f160dSDag-Erling Smørgrav 	rewind(f);
1615b9b2fafSBrian Feldman 
1625b9b2fafSBrian Feldman 	if (bestcount == 0) {
163ae1f160dSDag-Erling Smørgrav 		fclose(f);
164d95e11bfSDag-Erling Smørgrav 		logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
165d74d50a8SDag-Erling Smørgrav 		return (dh_new_group14());
1665b9b2fafSBrian Feldman 	}
1675b9b2fafSBrian Feldman 
1685b9b2fafSBrian Feldman 	linenum = 0;
169d4af9e69SDag-Erling Smørgrav 	which = arc4random_uniform(bestcount);
1705b9b2fafSBrian Feldman 	while (fgets(line, sizeof(line), f)) {
1715b9b2fafSBrian Feldman 		if (!parse_prime(linenum, line, &dhg))
1725b9b2fafSBrian Feldman 			continue;
1731e8db6e2SBrian Feldman 		if ((dhg.size > max || dhg.size < min) ||
1741e8db6e2SBrian Feldman 		    dhg.size != best ||
1751e8db6e2SBrian Feldman 		    linenum++ != which) {
176ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dhg.g);
177ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dhg.p);
1785b9b2fafSBrian Feldman 			continue;
1795b9b2fafSBrian Feldman 		}
1805b9b2fafSBrian Feldman 		break;
1815b9b2fafSBrian Feldman 	}
1825b9b2fafSBrian Feldman 	fclose(f);
1831e8db6e2SBrian Feldman 	if (linenum != which+1)
1841e8db6e2SBrian Feldman 		fatal("WARNING: line %d disappeared in %s, giving up",
1851e8db6e2SBrian Feldman 		    which, _PATH_DH_PRIMES);
1865b9b2fafSBrian Feldman 
1875b9b2fafSBrian Feldman 	return (dh_new_group(dhg.g, dhg.p));
1885b9b2fafSBrian Feldman }
1891e8db6e2SBrian Feldman 
190d74d50a8SDag-Erling Smørgrav /* diffie-hellman-groupN-sha1 */
1911e8db6e2SBrian Feldman 
1921e8db6e2SBrian Feldman int
1931e8db6e2SBrian Feldman dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
1941e8db6e2SBrian Feldman {
1951e8db6e2SBrian Feldman 	int i;
1961e8db6e2SBrian Feldman 	int n = BN_num_bits(dh_pub);
1971e8db6e2SBrian Feldman 	int bits_set = 0;
198761efaa7SDag-Erling Smørgrav 	BIGNUM *tmp;
1991e8db6e2SBrian Feldman 
2001e8db6e2SBrian Feldman 	if (dh_pub->neg) {
201d4af9e69SDag-Erling Smørgrav 		logit("invalid public DH value: negative");
2021e8db6e2SBrian Feldman 		return 0;
2031e8db6e2SBrian Feldman 	}
204761efaa7SDag-Erling Smørgrav 	if (BN_cmp(dh_pub, BN_value_one()) != 1) {	/* pub_exp <= 1 */
205761efaa7SDag-Erling Smørgrav 		logit("invalid public DH value: <= 1");
206761efaa7SDag-Erling Smørgrav 		return 0;
207761efaa7SDag-Erling Smørgrav 	}
208761efaa7SDag-Erling Smørgrav 
209d4af9e69SDag-Erling Smørgrav 	if ((tmp = BN_new()) == NULL) {
210d4af9e69SDag-Erling Smørgrav 		error("%s: BN_new failed", __func__);
211d4af9e69SDag-Erling Smørgrav 		return 0;
212d4af9e69SDag-Erling Smørgrav 	}
213761efaa7SDag-Erling Smørgrav 	if (!BN_sub(tmp, dh->p, BN_value_one()) ||
214761efaa7SDag-Erling Smørgrav 	    BN_cmp(dh_pub, tmp) != -1) {		/* pub_exp > p-2 */
215761efaa7SDag-Erling Smørgrav 		BN_clear_free(tmp);
216761efaa7SDag-Erling Smørgrav 		logit("invalid public DH value: >= p-1");
217761efaa7SDag-Erling Smørgrav 		return 0;
218761efaa7SDag-Erling Smørgrav 	}
219761efaa7SDag-Erling Smørgrav 	BN_clear_free(tmp);
220761efaa7SDag-Erling Smørgrav 
2211e8db6e2SBrian Feldman 	for (i = 0; i <= n; i++)
2221e8db6e2SBrian Feldman 		if (BN_is_bit_set(dh_pub, i))
2231e8db6e2SBrian Feldman 			bits_set++;
224d0c8c0bcSDag-Erling Smørgrav 	debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
2251e8db6e2SBrian Feldman 
2261e8db6e2SBrian Feldman 	/* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
227761efaa7SDag-Erling Smørgrav 	if (bits_set > 1)
2281e8db6e2SBrian Feldman 		return 1;
229761efaa7SDag-Erling Smørgrav 
230d95e11bfSDag-Erling Smørgrav 	logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
2311e8db6e2SBrian Feldman 	return 0;
2321e8db6e2SBrian Feldman }
2331e8db6e2SBrian Feldman 
2341e8db6e2SBrian Feldman void
2351e8db6e2SBrian Feldman dh_gen_key(DH *dh, int need)
2361e8db6e2SBrian Feldman {
23752028650SDag-Erling Smørgrav 	int i, bits_set, tries = 0;
2381e8db6e2SBrian Feldman 
2391e8db6e2SBrian Feldman 	if (dh->p == NULL)
2401e8db6e2SBrian Feldman 		fatal("dh_gen_key: dh->p == NULL");
241efcad6b7SDag-Erling Smørgrav 	if (need > INT_MAX / 2 || 2 * need >= BN_num_bits(dh->p))
2421e8db6e2SBrian Feldman 		fatal("dh_gen_key: group too small: %d (2*need %d)",
2431e8db6e2SBrian Feldman 		    BN_num_bits(dh->p), 2*need);
2441e8db6e2SBrian Feldman 	do {
2451e8db6e2SBrian Feldman 		if (dh->priv_key != NULL)
246ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dh->priv_key);
247ae1f160dSDag-Erling Smørgrav 		if ((dh->priv_key = BN_new()) == NULL)
2481e8db6e2SBrian Feldman 			fatal("dh_gen_key: BN_new failed");
2491e8db6e2SBrian Feldman 		/* generate a 2*need bits random private exponent */
2501e8db6e2SBrian Feldman 		if (!BN_rand(dh->priv_key, 2*need, 0, 0))
2511e8db6e2SBrian Feldman 			fatal("dh_gen_key: BN_rand failed");
2521e8db6e2SBrian Feldman 		if (DH_generate_key(dh) == 0)
2531e8db6e2SBrian Feldman 			fatal("DH_generate_key");
25452028650SDag-Erling Smørgrav 		for (i = 0, bits_set = 0; i <= BN_num_bits(dh->priv_key); i++)
2551e8db6e2SBrian Feldman 			if (BN_is_bit_set(dh->priv_key, i))
2561e8db6e2SBrian Feldman 				bits_set++;
257d0c8c0bcSDag-Erling Smørgrav 		debug2("dh_gen_key: priv key bits set: %d/%d",
2581e8db6e2SBrian Feldman 		    bits_set, BN_num_bits(dh->priv_key));
2591e8db6e2SBrian Feldman 		if (tries++ > 10)
2601e8db6e2SBrian Feldman 			fatal("dh_gen_key: too many bad keys: giving up");
2611e8db6e2SBrian Feldman 	} while (!dh_pub_is_valid(dh, dh->pub_key));
2621e8db6e2SBrian Feldman }
2631e8db6e2SBrian Feldman 
2641e8db6e2SBrian Feldman DH *
2651e8db6e2SBrian Feldman dh_new_group_asc(const char *gen, const char *modulus)
2661e8db6e2SBrian Feldman {
2671e8db6e2SBrian Feldman 	DH *dh;
2681e8db6e2SBrian Feldman 
269ae1f160dSDag-Erling Smørgrav 	if ((dh = DH_new()) == NULL)
270ae1f160dSDag-Erling Smørgrav 		fatal("dh_new_group_asc: DH_new");
2711e8db6e2SBrian Feldman 
2721e8db6e2SBrian Feldman 	if (BN_hex2bn(&dh->p, modulus) == 0)
2731e8db6e2SBrian Feldman 		fatal("BN_hex2bn p");
2741e8db6e2SBrian Feldman 	if (BN_hex2bn(&dh->g, gen) == 0)
2751e8db6e2SBrian Feldman 		fatal("BN_hex2bn g");
2761e8db6e2SBrian Feldman 
2771e8db6e2SBrian Feldman 	return (dh);
2781e8db6e2SBrian Feldman }
2791e8db6e2SBrian Feldman 
2801e8db6e2SBrian Feldman /*
2811e8db6e2SBrian Feldman  * This just returns the group, we still need to generate the exchange
2821e8db6e2SBrian Feldman  * value.
2831e8db6e2SBrian Feldman  */
2841e8db6e2SBrian Feldman 
2851e8db6e2SBrian Feldman DH *
2861e8db6e2SBrian Feldman dh_new_group(BIGNUM *gen, BIGNUM *modulus)
2871e8db6e2SBrian Feldman {
2881e8db6e2SBrian Feldman 	DH *dh;
2891e8db6e2SBrian Feldman 
290ae1f160dSDag-Erling Smørgrav 	if ((dh = DH_new()) == NULL)
291ae1f160dSDag-Erling Smørgrav 		fatal("dh_new_group: DH_new");
2921e8db6e2SBrian Feldman 	dh->p = modulus;
2931e8db6e2SBrian Feldman 	dh->g = gen;
2941e8db6e2SBrian Feldman 
2951e8db6e2SBrian Feldman 	return (dh);
2961e8db6e2SBrian Feldman }
2971e8db6e2SBrian Feldman 
2981e8db6e2SBrian Feldman DH *
2991e8db6e2SBrian Feldman dh_new_group1(void)
3001e8db6e2SBrian Feldman {
3011e8db6e2SBrian Feldman 	static char *gen = "2", *group1 =
3021e8db6e2SBrian Feldman 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
3031e8db6e2SBrian Feldman 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
3041e8db6e2SBrian Feldman 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
3051e8db6e2SBrian Feldman 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
3061e8db6e2SBrian Feldman 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
3071e8db6e2SBrian Feldman 	    "FFFFFFFF" "FFFFFFFF";
3081e8db6e2SBrian Feldman 
3091e8db6e2SBrian Feldman 	return (dh_new_group_asc(gen, group1));
3101e8db6e2SBrian Feldman }
3111e8db6e2SBrian Feldman 
312d74d50a8SDag-Erling Smørgrav DH *
313d74d50a8SDag-Erling Smørgrav dh_new_group14(void)
314d74d50a8SDag-Erling Smørgrav {
315d74d50a8SDag-Erling Smørgrav 	static char *gen = "2", *group14 =
316d74d50a8SDag-Erling Smørgrav 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
317d74d50a8SDag-Erling Smørgrav 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
318d74d50a8SDag-Erling Smørgrav 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
319d74d50a8SDag-Erling Smørgrav 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
320d74d50a8SDag-Erling Smørgrav 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
321d74d50a8SDag-Erling Smørgrav 	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
322d74d50a8SDag-Erling Smørgrav 	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
323d74d50a8SDag-Erling Smørgrav 	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
324d74d50a8SDag-Erling Smørgrav 	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
325d74d50a8SDag-Erling Smørgrav 	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
326d74d50a8SDag-Erling Smørgrav 	    "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
327d74d50a8SDag-Erling Smørgrav 
328d74d50a8SDag-Erling Smørgrav 	return (dh_new_group_asc(gen, group14));
329d74d50a8SDag-Erling Smørgrav }
330d74d50a8SDag-Erling Smørgrav 
3311e8db6e2SBrian Feldman /*
3321e8db6e2SBrian Feldman  * Estimates the group order for a Diffie-Hellman group that has an
3331e8db6e2SBrian Feldman  * attack complexity approximately the same as O(2**bits).  Estimate
3341e8db6e2SBrian Feldman  * with:  O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
3351e8db6e2SBrian Feldman  */
3361e8db6e2SBrian Feldman 
3371e8db6e2SBrian Feldman int
3381e8db6e2SBrian Feldman dh_estimate(int bits)
3391e8db6e2SBrian Feldman {
3401e8db6e2SBrian Feldman 
341efcad6b7SDag-Erling Smørgrav 	if (bits <= 128)
3421e8db6e2SBrian Feldman 		return (1024);	/* O(2**86) */
343efcad6b7SDag-Erling Smørgrav 	if (bits <= 192)
3441e8db6e2SBrian Feldman 		return (2048);	/* O(2**116) */
3451e8db6e2SBrian Feldman 	return (4096);		/* O(2**156) */
3461e8db6e2SBrian Feldman }
347