10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright (c) 2000 Niels Provos. All rights reserved. 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 50Sstevel@tonic-gate * modification, are permitted provided that the following conditions 60Sstevel@tonic-gate * are met: 70Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 80Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 90Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 100Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 110Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 140Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 150Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 160Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 170Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 180Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 190Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 200Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 210Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 220Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 230Sstevel@tonic-gate */ 240Sstevel@tonic-gate 250Sstevel@tonic-gate #include "includes.h" 260Sstevel@tonic-gate RCSID("$OpenBSD: dh.c,v 1.22 2002/06/27 08:49:44 markus Exp $"); 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include "xmalloc.h" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <openssl/bn.h> 310Sstevel@tonic-gate #include <openssl/dh.h> 320Sstevel@tonic-gate #include <openssl/evp.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include "buffer.h" 350Sstevel@tonic-gate #include "cipher.h" 360Sstevel@tonic-gate #include "kex.h" 370Sstevel@tonic-gate #include "dh.h" 380Sstevel@tonic-gate #include "pathnames.h" 390Sstevel@tonic-gate #include "log.h" 400Sstevel@tonic-gate #include "misc.h" 410Sstevel@tonic-gate 420Sstevel@tonic-gate static int 430Sstevel@tonic-gate parse_prime(int linenum, char *line, struct dhgroup *dhg) 440Sstevel@tonic-gate { 450Sstevel@tonic-gate char *cp, *arg; 460Sstevel@tonic-gate char *strsize, *gen, *prime; 470Sstevel@tonic-gate 480Sstevel@tonic-gate cp = line; 490Sstevel@tonic-gate arg = strdelim(&cp); 500Sstevel@tonic-gate /* Ignore leading whitespace */ 510Sstevel@tonic-gate if (*arg == '\0') 520Sstevel@tonic-gate arg = strdelim(&cp); 530Sstevel@tonic-gate if (!arg || !*arg || *arg == '#') 540Sstevel@tonic-gate return 0; 550Sstevel@tonic-gate 560Sstevel@tonic-gate /* time */ 570Sstevel@tonic-gate if (cp == NULL || *arg == '\0') 580Sstevel@tonic-gate goto fail; 590Sstevel@tonic-gate arg = strsep(&cp, " "); /* type */ 600Sstevel@tonic-gate if (cp == NULL || *arg == '\0') 610Sstevel@tonic-gate goto fail; 620Sstevel@tonic-gate arg = strsep(&cp, " "); /* tests */ 630Sstevel@tonic-gate if (cp == NULL || *arg == '\0') 640Sstevel@tonic-gate goto fail; 650Sstevel@tonic-gate arg = strsep(&cp, " "); /* tries */ 660Sstevel@tonic-gate if (cp == NULL || *arg == '\0') 670Sstevel@tonic-gate goto fail; 680Sstevel@tonic-gate strsize = strsep(&cp, " "); /* size */ 690Sstevel@tonic-gate if (cp == NULL || *strsize == '\0' || 700Sstevel@tonic-gate (dhg->size = atoi(strsize)) == 0) 710Sstevel@tonic-gate goto fail; 720Sstevel@tonic-gate /* The whole group is one bit larger */ 730Sstevel@tonic-gate dhg->size++; 740Sstevel@tonic-gate gen = strsep(&cp, " "); /* gen */ 750Sstevel@tonic-gate if (cp == NULL || *gen == '\0') 760Sstevel@tonic-gate goto fail; 770Sstevel@tonic-gate prime = strsep(&cp, " "); /* prime */ 780Sstevel@tonic-gate if (cp != NULL || *prime == '\0') 790Sstevel@tonic-gate goto fail; 800Sstevel@tonic-gate 810Sstevel@tonic-gate if ((dhg->g = BN_new()) == NULL) 820Sstevel@tonic-gate fatal("parse_prime: BN_new failed"); 830Sstevel@tonic-gate if ((dhg->p = BN_new()) == NULL) 840Sstevel@tonic-gate fatal("parse_prime: BN_new failed"); 850Sstevel@tonic-gate if (BN_hex2bn(&dhg->g, gen) == 0) 860Sstevel@tonic-gate goto failclean; 870Sstevel@tonic-gate 880Sstevel@tonic-gate if (BN_hex2bn(&dhg->p, prime) == 0) 890Sstevel@tonic-gate goto failclean; 900Sstevel@tonic-gate 910Sstevel@tonic-gate if (BN_num_bits(dhg->p) != dhg->size) 920Sstevel@tonic-gate goto failclean; 930Sstevel@tonic-gate 940Sstevel@tonic-gate return (1); 950Sstevel@tonic-gate 960Sstevel@tonic-gate failclean: 970Sstevel@tonic-gate BN_clear_free(dhg->g); 980Sstevel@tonic-gate BN_clear_free(dhg->p); 990Sstevel@tonic-gate fail: 1000Sstevel@tonic-gate error("Bad prime description in line %d", linenum); 1010Sstevel@tonic-gate return (0); 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate DH * 1050Sstevel@tonic-gate choose_dh(int min, int wantbits, int max) 1060Sstevel@tonic-gate { 1070Sstevel@tonic-gate FILE *f; 1080Sstevel@tonic-gate char line[2048]; 1090Sstevel@tonic-gate int best, bestcount, which; 1100Sstevel@tonic-gate int linenum; 1110Sstevel@tonic-gate struct dhgroup dhg; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL && 1140Sstevel@tonic-gate (f = fopen(_PATH_DH_PRIMES, "r")) == NULL) { 1150Sstevel@tonic-gate log("WARNING: %s does not exist, using old modulus", _PATH_DH_MODULI); 1160Sstevel@tonic-gate return (dh_new_group1()); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate linenum = 0; 1200Sstevel@tonic-gate best = bestcount = 0; 1210Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 1220Sstevel@tonic-gate linenum++; 1230Sstevel@tonic-gate if (!parse_prime(linenum, line, &dhg)) 1240Sstevel@tonic-gate continue; 1250Sstevel@tonic-gate BN_clear_free(dhg.g); 1260Sstevel@tonic-gate BN_clear_free(dhg.p); 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate if (dhg.size > max || dhg.size < min) 1290Sstevel@tonic-gate continue; 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate if ((dhg.size > wantbits && dhg.size < best) || 1320Sstevel@tonic-gate (dhg.size > best && best < wantbits)) { 1330Sstevel@tonic-gate best = dhg.size; 1340Sstevel@tonic-gate bestcount = 0; 1350Sstevel@tonic-gate } 1360Sstevel@tonic-gate if (dhg.size == best) 1370Sstevel@tonic-gate bestcount++; 1380Sstevel@tonic-gate } 1390Sstevel@tonic-gate rewind(f); 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate if (bestcount == 0) { 1420Sstevel@tonic-gate fclose(f); 1430Sstevel@tonic-gate log("WARNING: no suitable primes in %s", _PATH_DH_PRIMES); 1440Sstevel@tonic-gate return (NULL); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate linenum = 0; 1480Sstevel@tonic-gate which = arc4random() % bestcount; 1490Sstevel@tonic-gate while (fgets(line, sizeof(line), f)) { 1500Sstevel@tonic-gate if (!parse_prime(linenum, line, &dhg)) 1510Sstevel@tonic-gate continue; 1520Sstevel@tonic-gate if ((dhg.size > max || dhg.size < min) || 1530Sstevel@tonic-gate dhg.size != best || 1540Sstevel@tonic-gate linenum++ != which) { 1550Sstevel@tonic-gate BN_clear_free(dhg.g); 1560Sstevel@tonic-gate BN_clear_free(dhg.p); 1570Sstevel@tonic-gate continue; 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate break; 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate fclose(f); 1620Sstevel@tonic-gate if (linenum != which+1) 1630Sstevel@tonic-gate fatal("WARNING: line %d disappeared in %s, giving up", 1640Sstevel@tonic-gate which, _PATH_DH_PRIMES); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate return (dh_new_group(dhg.g, dhg.p)); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /* diffie-hellman-group1-sha1 */ 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate int 1720Sstevel@tonic-gate dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) 1730Sstevel@tonic-gate { 1740Sstevel@tonic-gate int i; 1750Sstevel@tonic-gate int n = BN_num_bits(dh_pub); 1760Sstevel@tonic-gate int bits_set = 0; 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate if (dh_pub->neg) { 1790Sstevel@tonic-gate log("invalid public DH value: negativ"); 1800Sstevel@tonic-gate return 0; 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate for (i = 0; i <= n; i++) 1830Sstevel@tonic-gate if (BN_is_bit_set(dh_pub, i)) 1840Sstevel@tonic-gate bits_set++; 1850Sstevel@tonic-gate debug("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ 1880Sstevel@tonic-gate if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1)) 1890Sstevel@tonic-gate return 1; 1900Sstevel@tonic-gate log("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); 1910Sstevel@tonic-gate return 0; 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate void 1950Sstevel@tonic-gate dh_gen_key(DH *dh, int need) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate int i, bits_set = 0, tries = 0; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate if (dh->p == NULL) 2000Sstevel@tonic-gate fatal("dh_gen_key: dh->p == NULL"); 2010Sstevel@tonic-gate if (2*need >= BN_num_bits(dh->p)) 2020Sstevel@tonic-gate fatal("dh_gen_key: group too small: %d (2*need %d)", 2030Sstevel@tonic-gate BN_num_bits(dh->p), 2*need); 2040Sstevel@tonic-gate do { 2050Sstevel@tonic-gate if (dh->priv_key != NULL) 2060Sstevel@tonic-gate BN_clear_free(dh->priv_key); 2070Sstevel@tonic-gate if ((dh->priv_key = BN_new()) == NULL) 2080Sstevel@tonic-gate fatal("dh_gen_key: BN_new failed"); 2090Sstevel@tonic-gate /* generate a 2*need bits random private exponent */ 2100Sstevel@tonic-gate if (!BN_rand(dh->priv_key, 2*need, 0, 0)) 2110Sstevel@tonic-gate fatal("dh_gen_key: BN_rand failed"); 2120Sstevel@tonic-gate if (DH_generate_key(dh) == 0) 213*7574SJan.Pechanec@Sun.COM fatal("dh_gen_key: DH_generate_key() failed"); 2140Sstevel@tonic-gate for (i = 0; i <= BN_num_bits(dh->priv_key); i++) 2150Sstevel@tonic-gate if (BN_is_bit_set(dh->priv_key, i)) 2160Sstevel@tonic-gate bits_set++; 2170Sstevel@tonic-gate debug("dh_gen_key: priv key bits set: %d/%d", 2180Sstevel@tonic-gate bits_set, BN_num_bits(dh->priv_key)); 2190Sstevel@tonic-gate if (tries++ > 10) 2200Sstevel@tonic-gate fatal("dh_gen_key: too many bad keys: giving up"); 2210Sstevel@tonic-gate } while (!dh_pub_is_valid(dh, dh->pub_key)); 2220Sstevel@tonic-gate } 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate DH * 2250Sstevel@tonic-gate dh_new_group_asc(const char *gen, const char *modulus) 2260Sstevel@tonic-gate { 2270Sstevel@tonic-gate DH *dh; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate if ((dh = DH_new()) == NULL) 2300Sstevel@tonic-gate fatal("dh_new_group_asc: DH_new"); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate if (BN_hex2bn(&dh->p, modulus) == 0) 2330Sstevel@tonic-gate fatal("BN_hex2bn p"); 2340Sstevel@tonic-gate if (BN_hex2bn(&dh->g, gen) == 0) 2350Sstevel@tonic-gate fatal("BN_hex2bn g"); 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate return (dh); 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /* 2410Sstevel@tonic-gate * This just returns the group, we still need to generate the exchange 2420Sstevel@tonic-gate * value. 2430Sstevel@tonic-gate */ 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate DH * 2460Sstevel@tonic-gate dh_new_group(BIGNUM *gen, BIGNUM *modulus) 2470Sstevel@tonic-gate { 2480Sstevel@tonic-gate DH *dh; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate if ((dh = DH_new()) == NULL) 2510Sstevel@tonic-gate fatal("dh_new_group: DH_new"); 2520Sstevel@tonic-gate dh->p = modulus; 2530Sstevel@tonic-gate dh->g = gen; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate return (dh); 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate 2580Sstevel@tonic-gate DH * 2590Sstevel@tonic-gate dh_new_group1(void) 2600Sstevel@tonic-gate { 2610Sstevel@tonic-gate static char *gen = "2", *group1 = 2620Sstevel@tonic-gate "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" 2630Sstevel@tonic-gate "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" 2640Sstevel@tonic-gate "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" 2650Sstevel@tonic-gate "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" 2660Sstevel@tonic-gate "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" 2670Sstevel@tonic-gate "FFFFFFFF" "FFFFFFFF"; 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate return (dh_new_group_asc(gen, group1)); 2700Sstevel@tonic-gate } 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate /* 2730Sstevel@tonic-gate * Estimates the group order for a Diffie-Hellman group that has an 2740Sstevel@tonic-gate * attack complexity approximately the same as O(2**bits). Estimate 2750Sstevel@tonic-gate * with: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3))) 2760Sstevel@tonic-gate */ 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate int 2790Sstevel@tonic-gate dh_estimate(int bits) 2800Sstevel@tonic-gate { 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate if (bits < 64) 2830Sstevel@tonic-gate return (512); /* O(2**63) */ 2840Sstevel@tonic-gate if (bits < 128) 2850Sstevel@tonic-gate return (1024); /* O(2**86) */ 2860Sstevel@tonic-gate if (bits < 192) 2870Sstevel@tonic-gate return (2048); /* O(2**116) */ 2880Sstevel@tonic-gate return (4096); /* O(2**156) */ 2890Sstevel@tonic-gate } 290