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