dh.c revision 69587
169587Sgreen/* 269587Sgreen * Copyright (c) 2000 Niels Provos. All rights reserved. 369587Sgreen * 469587Sgreen * Redistribution and use in source and binary forms, with or without 569587Sgreen * modification, are permitted provided that the following conditions 669587Sgreen * are met: 769587Sgreen * 1. Redistributions of source code must retain the above copyright 869587Sgreen * notice, this list of conditions and the following disclaimer. 969587Sgreen * 2. Redistributions in binary form must reproduce the above copyright 1069587Sgreen * notice, this list of conditions and the following disclaimer in the 1169587Sgreen * documentation and/or other materials provided with the distribution. 1269587Sgreen * 1369587Sgreen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1469587Sgreen * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1569587Sgreen * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1669587Sgreen * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1769587Sgreen * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1869587Sgreen * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1969587Sgreen * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2069587Sgreen * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2169587Sgreen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2269587Sgreen * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2369587Sgreen */ 2469587Sgreen 2569587Sgreen#include "includes.h" 2669587SgreenRCSID("$OpenBSD: dh.c,v 1.2 2000/10/11 20:11:35 markus Exp $"); 2769587Sgreen 2869587Sgreen#include "xmalloc.h" 2969587Sgreen 3069587Sgreen#include <openssl/bn.h> 3169587Sgreen#include <openssl/dh.h> 3269587Sgreen#include <openssl/evp.h> 3369587Sgreen 3469587Sgreen#include "ssh.h" 3569587Sgreen#include "buffer.h" 3669587Sgreen#include "kex.h" 3769587Sgreen#include "dh.h" 3869587Sgreen 3969587Sgreenint 4069587Sgreenparse_prime(int linenum, char *line, struct dhgroup *dhg) 4169587Sgreen{ 4269587Sgreen char *cp, *arg; 4369587Sgreen char *strsize, *gen, *prime; 4469587Sgreen 4569587Sgreen cp = line; 4669587Sgreen arg = strdelim(&cp); 4769587Sgreen /* Ignore leading whitespace */ 4869587Sgreen if (*arg == '\0') 4969587Sgreen arg = strdelim(&cp); 5069587Sgreen if (!*arg || *arg == '#') 5169587Sgreen return 0; 5269587Sgreen 5369587Sgreen /* time */ 5469587Sgreen if (cp == NULL || *arg == '\0') 5569587Sgreen goto fail; 5669587Sgreen arg = strsep(&cp, " "); /* type */ 5769587Sgreen if (cp == NULL || *arg == '\0') 5869587Sgreen goto fail; 5969587Sgreen arg = strsep(&cp, " "); /* tests */ 6069587Sgreen if (cp == NULL || *arg == '\0') 6169587Sgreen goto fail; 6269587Sgreen arg = strsep(&cp, " "); /* tries */ 6369587Sgreen if (cp == NULL || *arg == '\0') 6469587Sgreen goto fail; 6569587Sgreen strsize = strsep(&cp, " "); /* size */ 6669587Sgreen if (cp == NULL || *strsize == '\0' || 6769587Sgreen (dhg->size = atoi(strsize)) == 0) 6869587Sgreen goto fail; 6969587Sgreen gen = strsep(&cp, " "); /* gen */ 7069587Sgreen if (cp == NULL || *gen == '\0') 7169587Sgreen goto fail; 7269587Sgreen prime = strsep(&cp, " "); /* prime */ 7369587Sgreen if (cp != NULL || *prime == '\0') 7469587Sgreen goto fail; 7569587Sgreen 7669587Sgreen dhg->g = BN_new(); 7769587Sgreen if (BN_hex2bn(&dhg->g, gen) < 0) { 7869587Sgreen BN_free(dhg->g); 7969587Sgreen goto fail; 8069587Sgreen } 8169587Sgreen dhg->p = BN_new(); 8269587Sgreen if (BN_hex2bn(&dhg->p, prime) < 0) { 8369587Sgreen BN_free(dhg->g); 8469587Sgreen BN_free(dhg->p); 8569587Sgreen goto fail; 8669587Sgreen } 8769587Sgreen 8869587Sgreen return (1); 8969587Sgreen fail: 9069587Sgreen fprintf(stderr, "Bad prime description in line %d\n", linenum); 9169587Sgreen return (0); 9269587Sgreen} 9369587Sgreen 9469587SgreenDH * 9569587Sgreenchoose_dh(int minbits) 9669587Sgreen{ 9769587Sgreen FILE *f; 9869587Sgreen char line[1024]; 9969587Sgreen int best, bestcount, which; 10069587Sgreen int linenum; 10169587Sgreen struct dhgroup dhg; 10269587Sgreen 10369587Sgreen f = fopen(DH_PRIMES, "r"); 10469587Sgreen if (!f) { 10569587Sgreen perror(DH_PRIMES); 10669587Sgreen log("WARNING: %s does not exist, using old prime", DH_PRIMES); 10769587Sgreen return (dh_new_group1()); 10869587Sgreen } 10969587Sgreen 11069587Sgreen linenum = 0; 11169587Sgreen best = bestcount = 0; 11269587Sgreen while (fgets(line, sizeof(line), f)) { 11369587Sgreen linenum++; 11469587Sgreen if (!parse_prime(linenum, line, &dhg)) 11569587Sgreen continue; 11669587Sgreen BN_free(dhg.g); 11769587Sgreen BN_free(dhg.p); 11869587Sgreen 11969587Sgreen if ((dhg.size > minbits && dhg.size < best) || 12069587Sgreen (dhg.size > best && best < minbits)) { 12169587Sgreen best = dhg.size; 12269587Sgreen bestcount = 0; 12369587Sgreen } 12469587Sgreen if (dhg.size == best) 12569587Sgreen bestcount++; 12669587Sgreen } 12769587Sgreen fclose (f); 12869587Sgreen 12969587Sgreen if (bestcount == 0) { 13069587Sgreen log("WARNING: no primes in %s, using old prime", DH_PRIMES); 13169587Sgreen return (dh_new_group1()); 13269587Sgreen } 13369587Sgreen 13469587Sgreen f = fopen(DH_PRIMES, "r"); 13569587Sgreen if (!f) { 13669587Sgreen perror(DH_PRIMES); 13769587Sgreen exit(1); 13869587Sgreen } 13969587Sgreen 14069587Sgreen linenum = 0; 14169587Sgreen which = arc4random() % bestcount; 14269587Sgreen while (fgets(line, sizeof(line), f)) { 14369587Sgreen if (!parse_prime(linenum, line, &dhg)) 14469587Sgreen continue; 14569587Sgreen if (dhg.size != best) 14669587Sgreen continue; 14769587Sgreen if (linenum++ != which) { 14869587Sgreen BN_free(dhg.g); 14969587Sgreen BN_free(dhg.p); 15069587Sgreen continue; 15169587Sgreen } 15269587Sgreen break; 15369587Sgreen } 15469587Sgreen fclose(f); 15569587Sgreen 15669587Sgreen return (dh_new_group(dhg.g, dhg.p)); 15769587Sgreen} 158