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