blob: 4c639acc39477d902e73c28b256f05742393ebb0 [file] [log] [blame]
dtucker@openbsd.org40f64292015-05-27 23:39:18 +00001/* $OpenBSD: dh.c,v 1.57 2015/05/27 23:39:18 dtucker Exp $ */
Damien Miller874d77b2000-10-14 16:23:11 +11002/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
Damien Miller874d77b2000-10-14 16:23:11 +110027
deraadt@openbsd.org087266e2015-01-20 23:14:00 +000028#include <sys/param.h> /* MIN */
Damien Miller8dbffe72006-08-05 11:02:17 +100029
Damien Miller874d77b2000-10-14 16:23:11 +110030#include <openssl/bn.h>
31#include <openssl/dh.h>
Damien Miller874d77b2000-10-14 16:23:11 +110032
Damien Millerded319c2006-09-01 15:38:36 +100033#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100034#include <stdio.h>
Damien Millere7a1e5c2006-08-05 11:34:19 +100035#include <stdlib.h>
Damien Millere3476ed2006-07-24 14:13:33 +100036#include <string.h>
deraadt@openbsd.org087266e2015-01-20 23:14:00 +000037#include <limits.h>
Damien Millere3476ed2006-07-24 14:13:33 +100038
Damien Miller874d77b2000-10-14 16:23:11 +110039#include "dh.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000040#include "pathnames.h"
41#include "log.h"
42#include "misc.h"
markus@openbsd.org57d10cb2015-01-19 20:16:15 +000043#include "ssherr.h"
Damien Miller874d77b2000-10-14 16:23:11 +110044
Ben Lindstrombba81212001-06-25 05:01:22 +000045static int
Damien Miller874d77b2000-10-14 16:23:11 +110046parse_prime(int linenum, char *line, struct dhgroup *dhg)
47{
48 char *cp, *arg;
49 char *strsize, *gen, *prime;
Damien Miller5a73c1a2006-03-31 23:09:41 +110050 const char *errstr = NULL;
Damien Miller2e9cf492008-06-29 22:47:04 +100051 long long n;
Damien Miller874d77b2000-10-14 16:23:11 +110052
Damien Miller0d02c3e2013-07-18 16:12:06 +100053 dhg->p = dhg->g = NULL;
Damien Miller874d77b2000-10-14 16:23:11 +110054 cp = line;
Damien Miller928b2362006-03-26 13:53:32 +110055 if ((arg = strdelim(&cp)) == NULL)
56 return 0;
Damien Miller874d77b2000-10-14 16:23:11 +110057 /* Ignore leading whitespace */
58 if (*arg == '\0')
59 arg = strdelim(&cp);
Ben Lindstrom04f9af72002-07-04 00:03:56 +000060 if (!arg || !*arg || *arg == '#')
Damien Miller874d77b2000-10-14 16:23:11 +110061 return 0;
62
63 /* time */
64 if (cp == NULL || *arg == '\0')
Damien Millerbbeb1da2013-07-18 16:10:49 +100065 goto truncated;
Damien Miller874d77b2000-10-14 16:23:11 +110066 arg = strsep(&cp, " "); /* type */
67 if (cp == NULL || *arg == '\0')
Damien Millerbbeb1da2013-07-18 16:10:49 +100068 goto truncated;
Damien Miller2e9cf492008-06-29 22:47:04 +100069 /* Ensure this is a safe prime */
70 n = strtonum(arg, 0, 5, &errstr);
Damien Millerbbeb1da2013-07-18 16:10:49 +100071 if (errstr != NULL || n != MODULI_TYPE_SAFE) {
72 error("moduli:%d: type is not %d", linenum, MODULI_TYPE_SAFE);
Damien Miller2e9cf492008-06-29 22:47:04 +100073 goto fail;
Damien Millerbbeb1da2013-07-18 16:10:49 +100074 }
Damien Miller874d77b2000-10-14 16:23:11 +110075 arg = strsep(&cp, " "); /* tests */
76 if (cp == NULL || *arg == '\0')
Damien Millerbbeb1da2013-07-18 16:10:49 +100077 goto truncated;
Damien Miller2e9cf492008-06-29 22:47:04 +100078 /* Ensure prime has been tested and is not composite */
79 n = strtonum(arg, 0, 0x1f, &errstr);
80 if (errstr != NULL ||
Damien Millerbbeb1da2013-07-18 16:10:49 +100081 (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) {
82 error("moduli:%d: invalid moduli tests flag", linenum);
Damien Miller2e9cf492008-06-29 22:47:04 +100083 goto fail;
Damien Millerbbeb1da2013-07-18 16:10:49 +100084 }
Damien Miller874d77b2000-10-14 16:23:11 +110085 arg = strsep(&cp, " "); /* tries */
86 if (cp == NULL || *arg == '\0')
Damien Millerbbeb1da2013-07-18 16:10:49 +100087 goto truncated;
Damien Miller2e9cf492008-06-29 22:47:04 +100088 n = strtonum(arg, 0, 1<<30, &errstr);
Damien Millerbbeb1da2013-07-18 16:10:49 +100089 if (errstr != NULL || n == 0) {
90 error("moduli:%d: invalid primality trial count", linenum);
Damien Miller2e9cf492008-06-29 22:47:04 +100091 goto fail;
Damien Millerbbeb1da2013-07-18 16:10:49 +100092 }
Damien Miller874d77b2000-10-14 16:23:11 +110093 strsize = strsep(&cp, " "); /* size */
94 if (cp == NULL || *strsize == '\0' ||
Darren Tucker759cb2a2009-10-07 09:01:50 +110095 (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||
Damien Millerbbeb1da2013-07-18 16:10:49 +100096 errstr) {
97 error("moduli:%d: invalid prime length", linenum);
Damien Miller874d77b2000-10-14 16:23:11 +110098 goto fail;
Damien Millerbbeb1da2013-07-18 16:10:49 +100099 }
Ben Lindstromdf221392001-03-29 00:36:16 +0000100 /* The whole group is one bit larger */
101 dhg->size++;
Damien Miller874d77b2000-10-14 16:23:11 +1100102 gen = strsep(&cp, " "); /* gen */
103 if (cp == NULL || *gen == '\0')
Damien Millerbbeb1da2013-07-18 16:10:49 +1000104 goto truncated;
Damien Miller874d77b2000-10-14 16:23:11 +1100105 prime = strsep(&cp, " "); /* prime */
Damien Millerbbeb1da2013-07-18 16:10:49 +1000106 if (cp != NULL || *prime == '\0') {
107 truncated:
108 error("moduli:%d: truncated", linenum);
Damien Miller874d77b2000-10-14 16:23:11 +1100109 goto fail;
Damien Millerbbeb1da2013-07-18 16:10:49 +1000110 }
Damien Miller874d77b2000-10-14 16:23:11 +1100111
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000112 if ((dhg->g = BN_new()) == NULL ||
113 (dhg->p = BN_new()) == NULL) {
114 error("parse_prime: BN_new failed");
115 goto fail;
116 }
Damien Millerbbeb1da2013-07-18 16:10:49 +1000117 if (BN_hex2bn(&dhg->g, gen) == 0) {
118 error("moduli:%d: could not parse generator value", linenum);
119 goto fail;
120 }
121 if (BN_hex2bn(&dhg->p, prime) == 0) {
122 error("moduli:%d: could not parse prime value", linenum);
123 goto fail;
124 }
125 if (BN_num_bits(dhg->p) != dhg->size) {
126 error("moduli:%d: prime has wrong size: actual %d listed %d",
127 linenum, BN_num_bits(dhg->p), dhg->size - 1);
128 goto fail;
129 }
130 if (BN_cmp(dhg->g, BN_value_one()) <= 0) {
131 error("moduli:%d: generator is invalid", linenum);
132 goto fail;
133 }
Damien Millerbbeb1da2013-07-18 16:10:49 +1000134 return 1;
Damien Miller23e526e2001-03-30 10:47:43 +1000135
Damien Miller874d77b2000-10-14 16:23:11 +1100136 fail:
Damien Millerbbeb1da2013-07-18 16:10:49 +1000137 if (dhg->g != NULL)
138 BN_clear_free(dhg->g);
139 if (dhg->p != NULL)
140 BN_clear_free(dhg->p);
141 dhg->g = dhg->p = NULL;
Damien Millerbbeb1da2013-07-18 16:10:49 +1000142 return 0;
Damien Miller874d77b2000-10-14 16:23:11 +1100143}
144
145DH *
Ben Lindstromdf221392001-03-29 00:36:16 +0000146choose_dh(int min, int wantbits, int max)
Damien Miller874d77b2000-10-14 16:23:11 +1100147{
148 FILE *f;
Darren Tuckerc56c7ef2004-02-29 20:13:34 +1100149 char line[4096];
Damien Miller874d77b2000-10-14 16:23:11 +1100150 int best, bestcount, which;
151 int linenum;
152 struct dhgroup dhg;
153
Ben Lindstrom93a29e02001-06-25 04:13:25 +0000154 if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL &&
155 (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) {
Damien Millerf675fc42004-06-15 10:30:09 +1000156 logit("WARNING: %s does not exist, using fixed modulus",
157 _PATH_DH_MODULI);
dtucker@openbsd.org40f64292015-05-27 23:39:18 +0000158 return (dh_new_group_fallback(max));
Damien Miller874d77b2000-10-14 16:23:11 +1100159 }
160
161 linenum = 0;
162 best = bestcount = 0;
163 while (fgets(line, sizeof(line), f)) {
164 linenum++;
165 if (!parse_prime(linenum, line, &dhg))
166 continue;
Damien Miller9ef95dd2002-01-22 23:10:33 +1100167 BN_clear_free(dhg.g);
168 BN_clear_free(dhg.p);
Damien Miller874d77b2000-10-14 16:23:11 +1100169
Ben Lindstromdf221392001-03-29 00:36:16 +0000170 if (dhg.size > max || dhg.size < min)
171 continue;
172
173 if ((dhg.size > wantbits && dhg.size < best) ||
174 (dhg.size > best && best < wantbits)) {
Damien Miller874d77b2000-10-14 16:23:11 +1100175 best = dhg.size;
176 bestcount = 0;
177 }
178 if (dhg.size == best)
179 bestcount++;
180 }
Ben Lindstromaf738802001-06-25 04:18:59 +0000181 rewind(f);
Damien Miller874d77b2000-10-14 16:23:11 +1100182
183 if (bestcount == 0) {
Ben Lindstromaf738802001-06-25 04:18:59 +0000184 fclose(f);
Damien Miller996acd22003-04-09 20:59:48 +1000185 logit("WARNING: no suitable primes in %s", _PATH_DH_PRIMES);
dtucker@openbsd.org40f64292015-05-27 23:39:18 +0000186 return (dh_new_group_fallback(max));
Damien Miller874d77b2000-10-14 16:23:11 +1100187 }
188
Damien Miller874d77b2000-10-14 16:23:11 +1100189 linenum = 0;
Damien Miller354c48c2008-05-19 14:50:00 +1000190 which = arc4random_uniform(bestcount);
Damien Miller874d77b2000-10-14 16:23:11 +1100191 while (fgets(line, sizeof(line), f)) {
192 if (!parse_prime(linenum, line, &dhg))
193 continue;
Ben Lindstrom5ba23b32001-04-05 02:05:21 +0000194 if ((dhg.size > max || dhg.size < min) ||
195 dhg.size != best ||
196 linenum++ != which) {
Damien Miller9ef95dd2002-01-22 23:10:33 +1100197 BN_clear_free(dhg.g);
198 BN_clear_free(dhg.p);
Damien Miller874d77b2000-10-14 16:23:11 +1100199 continue;
200 }
201 break;
202 }
203 fclose(f);
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000204 if (linenum != which+1) {
205 logit("WARNING: line %d disappeared in %s, giving up",
Ben Lindstrom5ba23b32001-04-05 02:05:21 +0000206 which, _PATH_DH_PRIMES);
dtucker@openbsd.org40f64292015-05-27 23:39:18 +0000207 return (dh_new_group_fallback(max));
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000208 }
Damien Miller874d77b2000-10-14 16:23:11 +1100209
210 return (dh_new_group(dhg.g, dhg.p));
211}
Damien Miller9709f902001-03-30 10:50:10 +1000212
Damien Millerf675fc42004-06-15 10:30:09 +1000213/* diffie-hellman-groupN-sha1 */
Damien Miller9709f902001-03-30 10:50:10 +1000214
215int
216dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
217{
218 int i;
219 int n = BN_num_bits(dh_pub);
220 int bits_set = 0;
Darren Tucker31cde682006-05-06 17:43:33 +1000221 BIGNUM *tmp;
Damien Miller9709f902001-03-30 10:50:10 +1000222
223 if (dh_pub->neg) {
Damien Miller603077a2007-10-26 14:25:55 +1000224 logit("invalid public DH value: negative");
Damien Miller9709f902001-03-30 10:50:10 +1000225 return 0;
226 }
Darren Tucker31cde682006-05-06 17:43:33 +1000227 if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */
228 logit("invalid public DH value: <= 1");
229 return 0;
230 }
231
Damien Miller603077a2007-10-26 14:25:55 +1000232 if ((tmp = BN_new()) == NULL) {
233 error("%s: BN_new failed", __func__);
234 return 0;
235 }
Darren Tucker31cde682006-05-06 17:43:33 +1000236 if (!BN_sub(tmp, dh->p, BN_value_one()) ||
237 BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */
238 BN_clear_free(tmp);
239 logit("invalid public DH value: >= p-1");
240 return 0;
241 }
242 BN_clear_free(tmp);
243
Damien Miller9709f902001-03-30 10:50:10 +1000244 for (i = 0; i <= n; i++)
245 if (BN_is_bit_set(dh_pub, i))
246 bits_set++;
Ben Lindstrom1f530832002-12-23 02:03:02 +0000247 debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
Damien Miller9709f902001-03-30 10:50:10 +1000248
249 /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */
Darren Tucker31cde682006-05-06 17:43:33 +1000250 if (bits_set > 1)
Damien Miller9709f902001-03-30 10:50:10 +1000251 return 1;
Darren Tucker31cde682006-05-06 17:43:33 +1000252
Damien Miller996acd22003-04-09 20:59:48 +1000253 logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p));
Damien Miller9709f902001-03-30 10:50:10 +1000254 return 0;
255}
256
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000257int
Damien Miller9709f902001-03-30 10:50:10 +1000258dh_gen_key(DH *dh, int need)
259{
Damien Miller0fde8ac2013-11-21 14:12:23 +1100260 int pbits;
Damien Miller9709f902001-03-30 10:50:10 +1000261
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000262 if (need < 0 || dh->p == NULL ||
263 (pbits = BN_num_bits(dh->p)) <= 0 ||
djm@openbsd.orgb8afbe22015-03-26 06:59:28 +0000264 need > INT_MAX / 2 || 2 * need > pbits)
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000265 return SSH_ERR_INVALID_ARGUMENT;
Damien Miller0fde8ac2013-11-21 14:12:23 +1100266 dh->length = MIN(need * 2, pbits - 1);
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000267 if (DH_generate_key(dh) == 0 ||
268 !dh_pub_is_valid(dh, dh->pub_key)) {
269 BN_clear_free(dh->priv_key);
270 return SSH_ERR_LIBCRYPTO_ERROR;
271 }
272 return 0;
Damien Miller9709f902001-03-30 10:50:10 +1000273}
274
275DH *
276dh_new_group_asc(const char *gen, const char *modulus)
277{
278 DH *dh;
Damien Miller9709f902001-03-30 10:50:10 +1000279
Damien Millerda755162002-01-22 23:09:22 +1100280 if ((dh = DH_new()) == NULL)
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000281 return NULL;
282 if (BN_hex2bn(&dh->p, modulus) == 0 ||
283 BN_hex2bn(&dh->g, gen) == 0) {
284 DH_free(dh);
285 return NULL;
286 }
Damien Miller9709f902001-03-30 10:50:10 +1000287 return (dh);
288}
289
290/*
291 * This just returns the group, we still need to generate the exchange
292 * value.
293 */
294
295DH *
296dh_new_group(BIGNUM *gen, BIGNUM *modulus)
297{
298 DH *dh;
299
Damien Millerda755162002-01-22 23:09:22 +1100300 if ((dh = DH_new()) == NULL)
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000301 return NULL;
Damien Miller9709f902001-03-30 10:50:10 +1000302 dh->p = modulus;
303 dh->g = gen;
304
305 return (dh);
306}
307
308DH *
309dh_new_group1(void)
310{
311 static char *gen = "2", *group1 =
312 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
313 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
314 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
315 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
316 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
317 "FFFFFFFF" "FFFFFFFF";
318
319 return (dh_new_group_asc(gen, group1));
320}
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000321
Damien Millerf675fc42004-06-15 10:30:09 +1000322DH *
323dh_new_group14(void)
324{
325 static char *gen = "2", *group14 =
326 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
327 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
328 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
329 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
330 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
331 "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
332 "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
333 "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
334 "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
335 "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
336 "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF";
337
338 return (dh_new_group_asc(gen, group14));
339}
340
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000341/*
dtucker@openbsd.org40f64292015-05-27 23:39:18 +0000342 * 4k bit fallback group used by DH-GEX if moduli file cannot be read.
343 * Source: MODP group 16 from RFC3526.
344 */
345DH *
346dh_new_group_fallback(int max)
347{
348 static char *gen = "2", *group16 =
349 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
350 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
351 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
352 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
353 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
354 "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
355 "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
356 "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
357 "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
358 "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
359 "15728E5A" "8AAAC42D" "AD33170D" "04507A33" "A85521AB" "DF1CBA64"
360 "ECFB8504" "58DBEF0A" "8AEA7157" "5D060C7D" "B3970F85" "A6E1E4C7"
361 "ABF5AE8C" "DB0933D7" "1E8C94E0" "4A25619D" "CEE3D226" "1AD2EE6B"
362 "F12FFA06" "D98A0864" "D8760273" "3EC86A64" "521F2B18" "177B200C"
363 "BBE11757" "7A615D6C" "770988C0" "BAD946E2" "08E24FA0" "74E5AB31"
364 "43DB5BFC" "E0FD108E" "4B82D120" "A9210801" "1A723C12" "A787E6D7"
365 "88719A10" "BDBA5B26" "99C32718" "6AF4E23C" "1A946834" "B6150BDA"
366 "2583E9CA" "2AD44CE8" "DBBBC2DB" "04DE8EF9" "2E8EFC14" "1FBECAA6"
367 "287C5947" "4E6BC05D" "99B2964F" "A090C3A2" "233BA186" "515BE7ED"
368 "1F612970" "CEE2D7AF" "B81BDD76" "2170481C" "D0069127" "D5B05AA9"
369 "93B4EA98" "8D8FDDC1" "86FFB7DC" "90A6C08F" "4DF435C9" "34063199"
370 "FFFFFFFF" "FFFFFFFF";
371
372 if (max < 4096) {
373 debug3("requested max size %d, using 2k bit group 14", max);
374 return dh_new_group14();
375 }
376 debug3("using 4k bit group 16");
377 return (dh_new_group_asc(gen, group16));
378}
379
380/*
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000381 * Estimates the group order for a Diffie-Hellman group that has an
Darren Tuckerdf62d712013-10-10 10:32:39 +1100382 * attack complexity approximately the same as O(2**bits).
383 * Values from NIST Special Publication 800-57: Recommendation for Key
384 * Management Part 1 (rev 3) limited by the recommended maximum value
385 * from RFC4419 section 3.
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000386 */
387
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000388u_int
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000389dh_estimate(int bits)
390{
Darren Tuckerdf62d712013-10-10 10:32:39 +1100391 if (bits <= 112)
392 return 2048;
Damien Miller8975ddf2003-12-17 16:33:53 +1100393 if (bits <= 128)
Darren Tuckerdf62d712013-10-10 10:32:39 +1100394 return 3072;
Damien Miller8975ddf2003-12-17 16:33:53 +1100395 if (bits <= 192)
Darren Tuckerdf62d712013-10-10 10:32:39 +1100396 return 7680;
397 return 8192;
Ben Lindstrom20d7c7b2001-04-04 01:56:17 +0000398}