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