xref: /freebsd/crypto/openssh/dh.c (revision d74d50a84bda49cca847afc2f65bf790d6af7361)
15b9b2fafSBrian Feldman /*
25b9b2fafSBrian Feldman  * Copyright (c) 2000 Niels Provos.  All rights reserved.
35b9b2fafSBrian Feldman  *
45b9b2fafSBrian Feldman  * Redistribution and use in source and binary forms, with or without
55b9b2fafSBrian Feldman  * modification, are permitted provided that the following conditions
65b9b2fafSBrian Feldman  * are met:
75b9b2fafSBrian Feldman  * 1. Redistributions of source code must retain the above copyright
85b9b2fafSBrian Feldman  *    notice, this list of conditions and the following disclaimer.
95b9b2fafSBrian Feldman  * 2. Redistributions in binary form must reproduce the above copyright
105b9b2fafSBrian Feldman  *    notice, this list of conditions and the following disclaimer in the
115b9b2fafSBrian Feldman  *    documentation and/or other materials provided with the distribution.
125b9b2fafSBrian Feldman  *
135b9b2fafSBrian Feldman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
145b9b2fafSBrian Feldman  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
155b9b2fafSBrian Feldman  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
165b9b2fafSBrian Feldman  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
175b9b2fafSBrian Feldman  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
185b9b2fafSBrian Feldman  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
195b9b2fafSBrian Feldman  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
205b9b2fafSBrian Feldman  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
215b9b2fafSBrian Feldman  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
225b9b2fafSBrian Feldman  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
235b9b2fafSBrian Feldman  */
245b9b2fafSBrian Feldman 
255b9b2fafSBrian Feldman #include "includes.h"
26d74d50a8SDag-Erling Smørgrav RCSID("$OpenBSD: dh.c,v 1.31 2004/08/04 10:37:52 djm Exp $");
275b9b2fafSBrian Feldman 
285b9b2fafSBrian Feldman #include "xmalloc.h"
295b9b2fafSBrian Feldman 
305b9b2fafSBrian Feldman #include <openssl/bn.h>
315b9b2fafSBrian Feldman #include <openssl/dh.h>
325b9b2fafSBrian Feldman #include <openssl/evp.h>
335b9b2fafSBrian Feldman 
345b9b2fafSBrian Feldman #include "buffer.h"
351e8db6e2SBrian Feldman #include "cipher.h"
365b9b2fafSBrian Feldman #include "kex.h"
375b9b2fafSBrian Feldman #include "dh.h"
381e8db6e2SBrian Feldman #include "pathnames.h"
391e8db6e2SBrian Feldman #include "log.h"
401e8db6e2SBrian Feldman #include "misc.h"
415b9b2fafSBrian Feldman 
42ae1f160dSDag-Erling Smørgrav static int
435b9b2fafSBrian Feldman parse_prime(int linenum, char *line, struct dhgroup *dhg)
445b9b2fafSBrian Feldman {
455b9b2fafSBrian Feldman 	char *cp, *arg;
465b9b2fafSBrian Feldman 	char *strsize, *gen, *prime;
475b9b2fafSBrian Feldman 
485b9b2fafSBrian Feldman 	cp = line;
495b9b2fafSBrian Feldman 	arg = strdelim(&cp);
505b9b2fafSBrian Feldman 	/* Ignore leading whitespace */
515b9b2fafSBrian Feldman 	if (*arg == '\0')
525b9b2fafSBrian Feldman 		arg = strdelim(&cp);
534b17dab0SDag-Erling Smørgrav 	if (!arg || !*arg || *arg == '#')
545b9b2fafSBrian Feldman 		return 0;
555b9b2fafSBrian Feldman 
565b9b2fafSBrian Feldman 	/* time */
575b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
585b9b2fafSBrian Feldman 		goto fail;
595b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* type */
605b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
615b9b2fafSBrian Feldman 		goto fail;
625b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* tests */
635b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
645b9b2fafSBrian Feldman 		goto fail;
655b9b2fafSBrian Feldman 	arg = strsep(&cp, " "); /* tries */
665b9b2fafSBrian Feldman 	if (cp == NULL || *arg == '\0')
675b9b2fafSBrian Feldman 		goto fail;
685b9b2fafSBrian Feldman 	strsize = strsep(&cp, " "); /* size */
695b9b2fafSBrian Feldman 	if (cp == NULL || *strsize == '\0' ||
705b9b2fafSBrian Feldman 	    (dhg->size = atoi(strsize)) == 0)
715b9b2fafSBrian Feldman 		goto fail;
721e8db6e2SBrian Feldman 	/* The whole group is one bit larger */
731e8db6e2SBrian Feldman 	dhg->size++;
745b9b2fafSBrian Feldman 	gen = strsep(&cp, " "); /* gen */
755b9b2fafSBrian Feldman 	if (cp == NULL || *gen == '\0')
765b9b2fafSBrian Feldman 		goto fail;
775b9b2fafSBrian Feldman 	prime = strsep(&cp, " "); /* prime */
785b9b2fafSBrian Feldman 	if (cp != NULL || *prime == '\0')
795b9b2fafSBrian Feldman 		goto fail;
805b9b2fafSBrian Feldman 
81ae1f160dSDag-Erling Smørgrav 	if ((dhg->g = BN_new()) == NULL)
82ae1f160dSDag-Erling Smørgrav 		fatal("parse_prime: BN_new failed");
83ae1f160dSDag-Erling Smørgrav 	if ((dhg->p = BN_new()) == NULL)
84ae1f160dSDag-Erling Smørgrav 		fatal("parse_prime: BN_new failed");
851e8db6e2SBrian Feldman 	if (BN_hex2bn(&dhg->g, gen) == 0)
861e8db6e2SBrian Feldman 		goto failclean;
871e8db6e2SBrian Feldman 
881e8db6e2SBrian Feldman 	if (BN_hex2bn(&dhg->p, prime) == 0)
891e8db6e2SBrian Feldman 		goto failclean;
901e8db6e2SBrian Feldman 
911e8db6e2SBrian Feldman 	if (BN_num_bits(dhg->p) != dhg->size)
921e8db6e2SBrian Feldman 		goto failclean;
935b9b2fafSBrian Feldman 
9452028650SDag-Erling Smørgrav 	if (BN_is_zero(dhg->g) || BN_is_one(dhg->g))
9552028650SDag-Erling Smørgrav 		goto failclean;
9652028650SDag-Erling Smørgrav 
975b9b2fafSBrian Feldman 	return (1);
981e8db6e2SBrian Feldman 
991e8db6e2SBrian Feldman  failclean:
100ae1f160dSDag-Erling Smørgrav 	BN_clear_free(dhg->g);
101ae1f160dSDag-Erling Smørgrav 	BN_clear_free(dhg->p);
1025b9b2fafSBrian Feldman  fail:
1031e8db6e2SBrian Feldman 	error("Bad prime description in line %d", linenum);
1045b9b2fafSBrian Feldman 	return (0);
1055b9b2fafSBrian Feldman }
1065b9b2fafSBrian Feldman 
1075b9b2fafSBrian Feldman DH *
1081e8db6e2SBrian Feldman choose_dh(int min, int wantbits, int max)
1095b9b2fafSBrian Feldman {
1105b9b2fafSBrian Feldman 	FILE *f;
11152028650SDag-Erling Smørgrav 	char line[4096];
1125b9b2fafSBrian Feldman 	int best, bestcount, which;
1135b9b2fafSBrian Feldman 	int linenum;
1145b9b2fafSBrian Feldman 	struct dhgroup dhg;
1155b9b2fafSBrian Feldman 
116ae1f160dSDag-Erling Smørgrav 	if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
117ae1f160dSDag-Erling Smørgrav 	    (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
118d74d50a8SDag-Erling Smørgrav 		logit("WARNING: %s does not exist, using fixed modulus",
119d74d50a8SDag-Erling Smørgrav 		    _PATH_DH_MODULI);
120d74d50a8SDag-Erling Smørgrav 		return (dh_new_group14());
1215b9b2fafSBrian Feldman 	}
1225b9b2fafSBrian Feldman 
1235b9b2fafSBrian Feldman 	linenum = 0;
1245b9b2fafSBrian Feldman 	best = bestcount = 0;
1255b9b2fafSBrian Feldman 	while (fgets(line, sizeof(line), f)) {
1265b9b2fafSBrian Feldman 		linenum++;
1275b9b2fafSBrian Feldman 		if (!parse_prime(linenum, line, &dhg))
1285b9b2fafSBrian Feldman 			continue;
129ae1f160dSDag-Erling Smørgrav 		BN_clear_free(dhg.g);
130ae1f160dSDag-Erling Smørgrav 		BN_clear_free(dhg.p);
1315b9b2fafSBrian Feldman 
1321e8db6e2SBrian Feldman 		if (dhg.size > max || dhg.size < min)
1331e8db6e2SBrian Feldman 			continue;
1341e8db6e2SBrian Feldman 
1351e8db6e2SBrian Feldman 		if ((dhg.size > wantbits && dhg.size < best) ||
1361e8db6e2SBrian Feldman 		    (dhg.size > best && best < wantbits)) {
1375b9b2fafSBrian Feldman 			best = dhg.size;
1385b9b2fafSBrian Feldman 			bestcount = 0;
1395b9b2fafSBrian Feldman 		}
1405b9b2fafSBrian Feldman 		if (dhg.size == best)
1415b9b2fafSBrian Feldman 			bestcount++;
1425b9b2fafSBrian Feldman 	}
143ae1f160dSDag-Erling Smørgrav 	rewind(f);
1445b9b2fafSBrian Feldman 
1455b9b2fafSBrian Feldman 	if (bestcount == 0) {
146ae1f160dSDag-Erling Smørgrav 		fclose(f);
147d95e11bfSDag-Erling Smørgrav 		logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
148d74d50a8SDag-Erling Smørgrav 		return (dh_new_group14());
1495b9b2fafSBrian Feldman 	}
1505b9b2fafSBrian Feldman 
1515b9b2fafSBrian Feldman 	linenum = 0;
1525b9b2fafSBrian Feldman 	which = arc4random() % bestcount;
1535b9b2fafSBrian Feldman 	while (fgets(line, sizeof(line), f)) {
1545b9b2fafSBrian Feldman 		if (!parse_prime(linenum, line, &dhg))
1555b9b2fafSBrian Feldman 			continue;
1561e8db6e2SBrian Feldman 		if ((dhg.size > max || dhg.size < min) ||
1571e8db6e2SBrian Feldman 		    dhg.size != best ||
1581e8db6e2SBrian Feldman 		    linenum++ != which) {
159ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dhg.g);
160ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dhg.p);
1615b9b2fafSBrian Feldman 			continue;
1625b9b2fafSBrian Feldman 		}
1635b9b2fafSBrian Feldman 		break;
1645b9b2fafSBrian Feldman 	}
1655b9b2fafSBrian Feldman 	fclose(f);
1661e8db6e2SBrian Feldman 	if (linenum != which+1)
1671e8db6e2SBrian Feldman 		fatal("WARNING: line %d disappeared in %s, giving up",
1681e8db6e2SBrian Feldman 		    which, _PATH_DH_PRIMES);
1695b9b2fafSBrian Feldman 
1705b9b2fafSBrian Feldman 	return (dh_new_group(dhg.g, dhg.p));
1715b9b2fafSBrian Feldman }
1721e8db6e2SBrian Feldman 
173d74d50a8SDag-Erling Smørgrav /* diffie-hellman-groupN-sha1 */
1741e8db6e2SBrian Feldman 
1751e8db6e2SBrian Feldman int
1761e8db6e2SBrian Feldman dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
1771e8db6e2SBrian Feldman {
1781e8db6e2SBrian Feldman 	int i;
1791e8db6e2SBrian Feldman 	int n = BN_num_bits(dh_pub);
1801e8db6e2SBrian Feldman 	int bits_set = 0;
1811e8db6e2SBrian Feldman 
1821e8db6e2SBrian Feldman 	if (dh_pub->neg) {
183d95e11bfSDag-Erling Smørgrav 		logit("invalid public DH value: negativ");
1841e8db6e2SBrian Feldman 		return 0;
1851e8db6e2SBrian Feldman 	}
1861e8db6e2SBrian Feldman 	for (i = 0; i <= n; i++)
1871e8db6e2SBrian Feldman 		if (BN_is_bit_set(dh_pub, i))
1881e8db6e2SBrian Feldman 			bits_set++;
189d0c8c0bcSDag-Erling Smørgrav 	debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
1901e8db6e2SBrian Feldman 
1911e8db6e2SBrian Feldman 	/* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
1921e8db6e2SBrian Feldman 	if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1))
1931e8db6e2SBrian Feldman 		return 1;
194d95e11bfSDag-Erling Smørgrav 	logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
1951e8db6e2SBrian Feldman 	return 0;
1961e8db6e2SBrian Feldman }
1971e8db6e2SBrian Feldman 
1981e8db6e2SBrian Feldman void
1991e8db6e2SBrian Feldman dh_gen_key(DH *dh, int need)
2001e8db6e2SBrian Feldman {
20152028650SDag-Erling Smørgrav 	int i, bits_set, tries = 0;
2021e8db6e2SBrian Feldman 
2031e8db6e2SBrian Feldman 	if (dh->p == NULL)
2041e8db6e2SBrian Feldman 		fatal("dh_gen_key: dh->p == NULL");
205efcad6b7SDag-Erling Smørgrav 	if (need > INT_MAX / 2 || 2 * need >= BN_num_bits(dh->p))
2061e8db6e2SBrian Feldman 		fatal("dh_gen_key: group too small: %d (2*need %d)",
2071e8db6e2SBrian Feldman 		    BN_num_bits(dh->p), 2*need);
2081e8db6e2SBrian Feldman 	do {
2091e8db6e2SBrian Feldman 		if (dh->priv_key != NULL)
210ae1f160dSDag-Erling Smørgrav 			BN_clear_free(dh->priv_key);
211ae1f160dSDag-Erling Smørgrav 		if ((dh->priv_key = BN_new()) == NULL)
2121e8db6e2SBrian Feldman 			fatal("dh_gen_key: BN_new failed");
2131e8db6e2SBrian Feldman 		/* generate a 2*need bits random private exponent */
2141e8db6e2SBrian Feldman 		if (!BN_rand(dh->priv_key, 2*need, 0, 0))
2151e8db6e2SBrian Feldman 			fatal("dh_gen_key: BN_rand failed");
2161e8db6e2SBrian Feldman 		if (DH_generate_key(dh) == 0)
2171e8db6e2SBrian Feldman 			fatal("DH_generate_key");
21852028650SDag-Erling Smørgrav 		for (i = 0, bits_set = 0; i <= BN_num_bits(dh->priv_key); i++)
2191e8db6e2SBrian Feldman 			if (BN_is_bit_set(dh->priv_key, i))
2201e8db6e2SBrian Feldman 				bits_set++;
221d0c8c0bcSDag-Erling Smørgrav 		debug2("dh_gen_key: priv key bits set: %d/%d",
2221e8db6e2SBrian Feldman 		    bits_set, BN_num_bits(dh->priv_key));
2231e8db6e2SBrian Feldman 		if (tries++ > 10)
2241e8db6e2SBrian Feldman 			fatal("dh_gen_key: too many bad keys: giving up");
2251e8db6e2SBrian Feldman 	} while (!dh_pub_is_valid(dh, dh->pub_key));
2261e8db6e2SBrian Feldman }
2271e8db6e2SBrian Feldman 
2281e8db6e2SBrian Feldman DH *
2291e8db6e2SBrian Feldman dh_new_group_asc(const char *gen, const char *modulus)
2301e8db6e2SBrian Feldman {
2311e8db6e2SBrian Feldman 	DH *dh;
2321e8db6e2SBrian Feldman 
233ae1f160dSDag-Erling Smørgrav 	if ((dh = DH_new()) == NULL)
234ae1f160dSDag-Erling Smørgrav 		fatal("dh_new_group_asc: DH_new");
2351e8db6e2SBrian Feldman 
2361e8db6e2SBrian Feldman 	if (BN_hex2bn(&dh->p, modulus) == 0)
2371e8db6e2SBrian Feldman 		fatal("BN_hex2bn p");
2381e8db6e2SBrian Feldman 	if (BN_hex2bn(&dh->g, gen) == 0)
2391e8db6e2SBrian Feldman 		fatal("BN_hex2bn g");
2401e8db6e2SBrian Feldman 
2411e8db6e2SBrian Feldman 	return (dh);
2421e8db6e2SBrian Feldman }
2431e8db6e2SBrian Feldman 
2441e8db6e2SBrian Feldman /*
2451e8db6e2SBrian Feldman  * This just returns the group, we still need to generate the exchange
2461e8db6e2SBrian Feldman  * value.
2471e8db6e2SBrian Feldman  */
2481e8db6e2SBrian Feldman 
2491e8db6e2SBrian Feldman DH *
2501e8db6e2SBrian Feldman dh_new_group(BIGNUM *gen, BIGNUM *modulus)
2511e8db6e2SBrian Feldman {
2521e8db6e2SBrian Feldman 	DH *dh;
2531e8db6e2SBrian Feldman 
254ae1f160dSDag-Erling Smørgrav 	if ((dh = DH_new()) == NULL)
255ae1f160dSDag-Erling Smørgrav 		fatal("dh_new_group: DH_new");
2561e8db6e2SBrian Feldman 	dh->p = modulus;
2571e8db6e2SBrian Feldman 	dh->g = gen;
2581e8db6e2SBrian Feldman 
2591e8db6e2SBrian Feldman 	return (dh);
2601e8db6e2SBrian Feldman }
2611e8db6e2SBrian Feldman 
2621e8db6e2SBrian Feldman DH *
2631e8db6e2SBrian Feldman dh_new_group1(void)
2641e8db6e2SBrian Feldman {
2651e8db6e2SBrian Feldman 	static char *gen = "2", *group1 =
2661e8db6e2SBrian Feldman 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
2671e8db6e2SBrian Feldman 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
2681e8db6e2SBrian Feldman 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
2691e8db6e2SBrian Feldman 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
2701e8db6e2SBrian Feldman 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
2711e8db6e2SBrian Feldman 	    "FFFFFFFF" "FFFFFFFF";
2721e8db6e2SBrian Feldman 
2731e8db6e2SBrian Feldman 	return (dh_new_group_asc(gen, group1));
2741e8db6e2SBrian Feldman }
2751e8db6e2SBrian Feldman 
276d74d50a8SDag-Erling Smørgrav DH *
277d74d50a8SDag-Erling Smørgrav dh_new_group14(void)
278d74d50a8SDag-Erling Smørgrav {
279d74d50a8SDag-Erling Smørgrav 	static char *gen = "2", *group14 =
280d74d50a8SDag-Erling Smørgrav 	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
281d74d50a8SDag-Erling Smørgrav 	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
282d74d50a8SDag-Erling Smørgrav 	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
283d74d50a8SDag-Erling Smørgrav 	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
284d74d50a8SDag-Erling Smørgrav 	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
285d74d50a8SDag-Erling Smørgrav 	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
286d74d50a8SDag-Erling Smørgrav 	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
287d74d50a8SDag-Erling Smørgrav 	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
288d74d50a8SDag-Erling Smørgrav 	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
289d74d50a8SDag-Erling Smørgrav 	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
290d74d50a8SDag-Erling Smørgrav 	    "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
291d74d50a8SDag-Erling Smørgrav 
292d74d50a8SDag-Erling Smørgrav 	return (dh_new_group_asc(gen, group14));
293d74d50a8SDag-Erling Smørgrav }
294d74d50a8SDag-Erling Smørgrav 
2951e8db6e2SBrian Feldman /*
2961e8db6e2SBrian Feldman  * Estimates the group order for a Diffie-Hellman group that has an
2971e8db6e2SBrian Feldman  * attack complexity approximately the same as O(2**bits).  Estimate
2981e8db6e2SBrian Feldman  * with:  O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3)))
2991e8db6e2SBrian Feldman  */
3001e8db6e2SBrian Feldman 
3011e8db6e2SBrian Feldman int
3021e8db6e2SBrian Feldman dh_estimate(int bits)
3031e8db6e2SBrian Feldman {
3041e8db6e2SBrian Feldman 
305efcad6b7SDag-Erling Smørgrav 	if (bits <= 128)
3061e8db6e2SBrian Feldman 		return (1024);	/* O(2**86) */
307efcad6b7SDag-Erling Smørgrav 	if (bits <= 192)
3081e8db6e2SBrian Feldman 		return (2048);	/* O(2**116) */
3091e8db6e2SBrian Feldman 	return (4096);		/* O(2**156) */
3101e8db6e2SBrian Feldman }
311