1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: dh.c,v 1.55 2015/01/20 23:14:00 deraadt Exp $ */
2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2000 Niels Provos.  All rights reserved.
4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without
6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions
7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met:
8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright
9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer.
10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright
11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    notice, this list of conditions and the following disclaimer in the
12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *    documentation and/or other materials provided with the distribution.
13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h"
27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
28d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <sys/param.h>	/* MIN */
29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <openssl/bn.h>
31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <openssl/dh.h>
32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h>
34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h>
35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h>
36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h>
37d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h>
38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "dh.h"
40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "pathnames.h"
41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h"
42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h"
43d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "ssherr.h"
44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int
46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanparse_prime(int linenum, char *line, struct dhgroup *dhg)
47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	char *cp, *arg;
49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	char *strsize, *gen, *prime;
50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	const char *errstr = NULL;
51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	long long n;
52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
53d059297112922cabb0c674840589be8db821fd9aAdam Langley	dhg->p = dhg->g = NULL;
54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	cp = line;
55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if ((arg = strdelim(&cp)) == NULL)
56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Ignore leading whitespace */
58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (*arg == '\0')
59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		arg = strdelim(&cp);
60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!arg || !*arg || *arg == '#')
61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* time */
64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *arg == '\0')
65d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto truncated;
66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	arg = strsep(&cp, " "); /* type */
67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *arg == '\0')
68d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto truncated;
69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Ensure this is a safe prime */
70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	n = strtonum(arg, 0, 5, &errstr);
71d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (errstr != NULL || n != MODULI_TYPE_SAFE) {
72d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		goto fail;
74d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	arg = strsep(&cp, " "); /* tests */
76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *arg == '\0')
77d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto truncated;
78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* Ensure prime has been tested and is not composite */
79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	n = strtonum(arg, 0, 0x1f, &errstr);
80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (errstr != NULL ||
81d059297112922cabb0c674840589be8db821fd9aAdam Langley	    (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
82d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: invalid moduli tests flag", linenum);
83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		goto fail;
84d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	arg = strsep(&cp, " "); /* tries */
86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *arg == '\0')
87d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto truncated;
88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	n = strtonum(arg, 0, 1<<30, &errstr);
89d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (errstr != NULL || n == 0) {
90d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: invalid primality trial count", linenum);
91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		goto fail;
92d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	strsize = strsep(&cp, " "); /* size */
94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *strsize == '\0' ||
95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
96d059297112922cabb0c674840589be8db821fd9aAdam Langley	    errstr) {
97d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: invalid prime length", linenum);
98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		goto fail;
99d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* The whole group is one bit larger */
101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dhg->size++;
102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	gen = strsep(&cp, " "); /* gen */
103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (cp == NULL || *gen == '\0')
104d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto truncated;
105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	prime = strsep(&cp, " "); /* prime */
106d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (cp != NULL || *prime == '\0') {
107d059297112922cabb0c674840589be8db821fd9aAdam Langley truncated:
108d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: truncated", linenum);
109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		goto fail;
110d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
112d059297112922cabb0c674840589be8db821fd9aAdam Langley	if ((dhg->g = BN_new()) == NULL ||
113d059297112922cabb0c674840589be8db821fd9aAdam Langley	    (dhg->p = BN_new()) == NULL) {
114d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("parse_prime: BN_new failed");
115d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto fail;
116d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
117d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (BN_hex2bn(&dhg->g, gen) == 0) {
118d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: could not parse generator value", linenum);
119d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto fail;
120d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
121d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (BN_hex2bn(&dhg->p, prime) == 0) {
122d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: could not parse prime value", linenum);
123d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto fail;
124d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
125d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (BN_num_bits(dhg->p) != dhg->size) {
126d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: prime has wrong size: actual %d listed %d",
127d059297112922cabb0c674840589be8db821fd9aAdam Langley		    linenum, BN_num_bits(dhg->p), dhg->size - 1);
128d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto fail;
129d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
130d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
131d059297112922cabb0c674840589be8db821fd9aAdam Langley		error("moduli:%d: generator is invalid", linenum);
132d059297112922cabb0c674840589be8db821fd9aAdam Langley		goto fail;
133d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
134d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 1;
135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fail:
137d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (dhg->g != NULL)
138d059297112922cabb0c674840589be8db821fd9aAdam Langley		BN_clear_free(dhg->g);
139d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (dhg->p != NULL)
140d059297112922cabb0c674840589be8db821fd9aAdam Langley		BN_clear_free(dhg->p);
141d059297112922cabb0c674840589be8db821fd9aAdam Langley	dhg->g = dhg->p = NULL;
142d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH *
146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchoose_dh(int min, int wantbits, int max)
147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	FILE *f;
149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	char line[4096];
150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int best, bestcount, which;
151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int linenum;
152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	struct dhgroup dhg;
153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("WARNING: %s does not exist, using fixed modulus",
157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    _PATH_DH_MODULI);
158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (dh_new_group14());
159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	linenum = 0;
162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	best = bestcount = 0;
163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	while (fgets(line, sizeof(line), f)) {
164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		linenum++;
165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (!parse_prime(linenum, line, &dhg))
166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			continue;
167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		BN_clear_free(dhg.g);
168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		BN_clear_free(dhg.p);
169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (dhg.size > max || dhg.size < min)
171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			continue;
172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if ((dhg.size > wantbits && dhg.size < best) ||
174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    (dhg.size > best && best < wantbits)) {
175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			best = dhg.size;
176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			bestcount = 0;
177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (dhg.size == best)
179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			bestcount++;
180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	rewind(f);
182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (bestcount == 0) {
184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		fclose(f);
185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return (dh_new_group14());
187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	linenum = 0;
190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	which = arc4random_uniform(bestcount);
191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	while (fgets(line, sizeof(line), f)) {
192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (!parse_prime(linenum, line, &dhg))
193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			continue;
194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if ((dhg.size > max || dhg.size < min) ||
195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    dhg.size != best ||
196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    linenum++ != which) {
197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			BN_clear_free(dhg.g);
198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			BN_clear_free(dhg.p);
199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			continue;
200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		}
201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		break;
202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	fclose(f);
204d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (linenum != which+1) {
205d059297112922cabb0c674840589be8db821fd9aAdam Langley		logit("WARNING: line %d disappeared in %s, giving up",
206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		    which, _PATH_DH_PRIMES);
207d059297112922cabb0c674840589be8db821fd9aAdam Langley		return (dh_new_group14());
208d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (dh_new_group(dhg.g, dhg.p));
211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* diffie-hellman-groupN-sha1 */
214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint
216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int i;
219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int n = BN_num_bits(dh_pub);
220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int bits_set = 0;
221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	BIGNUM *tmp;
222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (dh_pub->neg) {
224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("invalid public DH value: negative");
225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (BN_cmp(dh_pub, BN_value_one()) != 1) {	/* pub_exp <= 1 */
228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("invalid public DH value: <= 1");
229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if ((tmp = BN_new()) == NULL) {
233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		error("%s: BN_new failed", __func__);
234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (!BN_sub(tmp, dh->p, BN_value_one()) ||
237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    BN_cmp(dh_pub, tmp) != -1) {		/* pub_exp > p-2 */
238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		BN_clear_free(tmp);
239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		logit("invalid public DH value: >= p-1");
240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 0;
241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	}
242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	BN_clear_free(tmp);
243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	for (i = 0; i <= n; i++)
245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		if (BN_is_bit_set(dh_pub, i))
246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman			bits_set++;
247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	/* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (bits_set > 1)
251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman		return 1;
252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return 0;
255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
257d059297112922cabb0c674840589be8db821fd9aAdam Langleyint
258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_gen_key(DH *dh, int need)
259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
260d059297112922cabb0c674840589be8db821fd9aAdam Langley	int pbits;
261d059297112922cabb0c674840589be8db821fd9aAdam Langley
262d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (need < 0 || dh->p == NULL ||
263d059297112922cabb0c674840589be8db821fd9aAdam Langley	    (pbits = BN_num_bits(dh->p)) <= 0 ||
264d059297112922cabb0c674840589be8db821fd9aAdam Langley	    need > INT_MAX / 2 || 2 * need >= pbits)
265d059297112922cabb0c674840589be8db821fd9aAdam Langley		return SSH_ERR_INVALID_ARGUMENT;
266d059297112922cabb0c674840589be8db821fd9aAdam Langley#if !defined(OPENSSL_IS_BORINGSSL)
267d059297112922cabb0c674840589be8db821fd9aAdam Langley	/* BoringSSL renamed |length| to |priv_length| to better reflect its
268d059297112922cabb0c674840589be8db821fd9aAdam Langley	 * actual use. Also, BoringSSL recognises common groups and chooses the
269d059297112922cabb0c674840589be8db821fd9aAdam Langley	 * length of the private exponent accoringly. */
270d059297112922cabb0c674840589be8db821fd9aAdam Langley	dh->length = MIN(need * 2, pbits - 1);
271d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif
272d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (DH_generate_key(dh) == 0 ||
273d059297112922cabb0c674840589be8db821fd9aAdam Langley	    !dh_pub_is_valid(dh, dh->pub_key)) {
274d059297112922cabb0c674840589be8db821fd9aAdam Langley		BN_clear_free(dh->priv_key);
275d059297112922cabb0c674840589be8db821fd9aAdam Langley		return SSH_ERR_LIBCRYPTO_ERROR;
276d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
277d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 0;
278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH *
281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group_asc(const char *gen, const char *modulus)
282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	DH *dh;
284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if ((dh = DH_new()) == NULL)
286d059297112922cabb0c674840589be8db821fd9aAdam Langley		return NULL;
287d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (BN_hex2bn(&dh->p, modulus) == 0 ||
288d059297112922cabb0c674840589be8db821fd9aAdam Langley	    BN_hex2bn(&dh->g, gen) == 0) {
289d059297112922cabb0c674840589be8db821fd9aAdam Langley		DH_free(dh);
290d059297112922cabb0c674840589be8db821fd9aAdam Langley		return NULL;
291d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (dh);
293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * This just returns the group, we still need to generate the exchange
297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * value.
298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH *
301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group(BIGNUM *gen, BIGNUM *modulus)
302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	DH *dh;
304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if ((dh = DH_new()) == NULL)
306d059297112922cabb0c674840589be8db821fd9aAdam Langley		return NULL;
307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dh->p = modulus;
308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	dh->g = gen;
309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (dh);
311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH *
314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group1(void)
315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	static char *gen = "2", *group1 =
317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "FFFFFFFF" "FFFFFFFF";
323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (dh_new_group_asc(gen, group1));
325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanDH *
328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_new_group14(void)
329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	static char *gen = "2", *group14 =
331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	    "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	return (dh_new_group_asc(gen, group14));
344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Estimates the group order for a Diffie-Hellman group that has an
348d059297112922cabb0c674840589be8db821fd9aAdam Langley * attack complexity approximately the same as O(2**bits).
349d059297112922cabb0c674840589be8db821fd9aAdam Langley * Values from NIST Special Publication 800-57: Recommendation for Key
350d059297112922cabb0c674840589be8db821fd9aAdam Langley * Management Part 1 (rev 3) limited by the recommended maximum value
351d059297112922cabb0c674840589be8db821fd9aAdam Langley * from RFC4419 section 3.
352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
354d059297112922cabb0c674840589be8db821fd9aAdam Langleyu_int
355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandh_estimate(int bits)
356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
357d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (bits <= 112)
358d059297112922cabb0c674840589be8db821fd9aAdam Langley		return 2048;
359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (bits <= 128)
360d059297112922cabb0c674840589be8db821fd9aAdam Langley		return 3072;
361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	if (bits <= 192)
362d059297112922cabb0c674840589be8db821fd9aAdam Langley		return 7680;
363d059297112922cabb0c674840589be8db821fd9aAdam Langley	return 8192;
364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
365