1 /* 2 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "includes.h" 26 RCSID("$OpenBSD: dh.c,v 1.2 2000/10/11 20:11:35 markus Exp $"); 27 28 #include "xmalloc.h" 29 30 #include <openssl/bn.h> 31 #include <openssl/dh.h> 32 #include <openssl/evp.h> 33 34 #include "ssh.h" 35 #include "buffer.h" 36 #include "kex.h" 37 #include "dh.h" 38 39 int 40 parse_prime(int linenum, char *line, struct dhgroup *dhg) 41 { 42 char *cp, *arg; 43 char *strsize, *gen, *prime; 44 45 cp = line; 46 arg = strdelim(&cp); 47 /* Ignore leading whitespace */ 48 if (*arg == '\0') 49 arg = strdelim(&cp); 50 if (!*arg || *arg == '#') 51 return 0; 52 53 /* time */ 54 if (cp == NULL || *arg == '\0') 55 goto fail; 56 arg = strsep(&cp, " "); /* type */ 57 if (cp == NULL || *arg == '\0') 58 goto fail; 59 arg = strsep(&cp, " "); /* tests */ 60 if (cp == NULL || *arg == '\0') 61 goto fail; 62 arg = strsep(&cp, " "); /* tries */ 63 if (cp == NULL || *arg == '\0') 64 goto fail; 65 strsize = strsep(&cp, " "); /* size */ 66 if (cp == NULL || *strsize == '\0' || 67 (dhg->size = atoi(strsize)) == 0) 68 goto fail; 69 gen = strsep(&cp, " "); /* gen */ 70 if (cp == NULL || *gen == '\0') 71 goto fail; 72 prime = strsep(&cp, " "); /* prime */ 73 if (cp != NULL || *prime == '\0') 74 goto fail; 75 76 dhg->g = BN_new(); 77 if (BN_hex2bn(&dhg->g, gen) < 0) { 78 BN_free(dhg->g); 79 goto fail; 80 } 81 dhg->p = BN_new(); 82 if (BN_hex2bn(&dhg->p, prime) < 0) { 83 BN_free(dhg->g); 84 BN_free(dhg->p); 85 goto fail; 86 } 87 88 return (1); 89 fail: 90 fprintf(stderr, "Bad prime description in line %d\n", linenum); 91 return (0); 92 } 93 94 DH * 95 choose_dh(int minbits) 96 { 97 FILE *f; 98 char line[1024]; 99 int best, bestcount, which; 100 int linenum; 101 struct dhgroup dhg; 102 103 f = fopen(DH_PRIMES, "r"); 104 if (!f) { 105 perror(DH_PRIMES); 106 log("WARNING: %s does not exist, using old prime", DH_PRIMES); 107 return (dh_new_group1()); 108 } 109 110 linenum = 0; 111 best = bestcount = 0; 112 while (fgets(line, sizeof(line), f)) { 113 linenum++; 114 if (!parse_prime(linenum, line, &dhg)) 115 continue; 116 BN_free(dhg.g); 117 BN_free(dhg.p); 118 119 if ((dhg.size > minbits && dhg.size < best) || 120 (dhg.size > best && best < minbits)) { 121 best = dhg.size; 122 bestcount = 0; 123 } 124 if (dhg.size == best) 125 bestcount++; 126 } 127 fclose (f); 128 129 if (bestcount == 0) { 130 log("WARNING: no primes in %s, using old prime", DH_PRIMES); 131 return (dh_new_group1()); 132 } 133 134 f = fopen(DH_PRIMES, "r"); 135 if (!f) { 136 perror(DH_PRIMES); 137 exit(1); 138 } 139 140 linenum = 0; 141 which = arc4random() % bestcount; 142 while (fgets(line, sizeof(line), f)) { 143 if (!parse_prime(linenum, line, &dhg)) 144 continue; 145 if (dhg.size != best) 146 continue; 147 if (linenum++ != which) { 148 BN_free(dhg.g); 149 BN_free(dhg.p); 150 continue; 151 } 152 break; 153 } 154 fclose(f); 155 156 return (dh_new_group(dhg.g, dhg.p)); 157 } 158