X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/fd06fbe0c37836f19058c3128e9f97679d34dbd4..HEAD:/dh.c diff --git a/dh.c b/dh.c index b32a7efb..b9029d86 100644 --- a/dh.c +++ b/dh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.c,v 1.35 2006/03/27 13:03:54 deraadt Exp $ */ +/* $OpenBSD: dh.c,v 1.48 2009/10/01 11:37:33 grunk Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * @@ -25,15 +25,16 @@ #include "includes.h" -#include "xmalloc.h" +#include #include #include -#include -#include "buffer.h" -#include "cipher.h" -#include "kex.h" +#include +#include +#include +#include + #include "dh.h" #include "pathnames.h" #include "log.h" @@ -45,6 +46,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) char *cp, *arg; char *strsize, *gen, *prime; const char *errstr = NULL; + long long n; cp = line; if ((arg = strdelim(&cp)) == NULL) @@ -61,15 +63,27 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg) arg = strsep(&cp, " "); /* type */ if (cp == NULL || *arg == '\0') goto fail; + /* Ensure this is a safe prime */ + n = strtonum(arg, 0, 5, &errstr); + if (errstr != NULL || n != MODULI_TYPE_SAFE) + goto fail; arg = strsep(&cp, " "); /* tests */ if (cp == NULL || *arg == '\0') goto fail; + /* Ensure prime has been tested and is not composite */ + n = strtonum(arg, 0, 0x1f, &errstr); + if (errstr != NULL || + (n & MODULI_TESTS_COMPOSITE) || !(n & ~MODULI_TESTS_COMPOSITE)) + goto fail; arg = strsep(&cp, " "); /* tries */ if (cp == NULL || *arg == '\0') goto fail; + n = strtonum(arg, 0, 1<<30, &errstr); + if (errstr != NULL || n == 0) + goto fail; strsize = strsep(&cp, " "); /* size */ if (cp == NULL || *strsize == '\0' || - (dhg->size = (u_int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || + (dhg->size = (int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || errstr) goto fail; /* The whole group is one bit larger */ @@ -152,7 +166,7 @@ choose_dh(int min, int wantbits, int max) } linenum = 0; - which = arc4random() % bestcount; + which = arc4random_uniform(bestcount); while (fgets(line, sizeof(line), f)) { if (!parse_prime(linenum, line, &dhg)) continue; @@ -181,19 +195,38 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) int i; int n = BN_num_bits(dh_pub); int bits_set = 0; + BIGNUM *tmp; if (dh_pub->neg) { - logit("invalid public DH value: negativ"); + logit("invalid public DH value: negative"); return 0; } + if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ + logit("invalid public DH value: <= 1"); + return 0; + } + + if ((tmp = BN_new()) == NULL) { + error("%s: BN_new failed", __func__); + return 0; + } + if (!BN_sub(tmp, dh->p, BN_value_one()) || + BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ + BN_clear_free(tmp); + logit("invalid public DH value: >= p-1"); + return 0; + } + BN_clear_free(tmp); + for (i = 0; i <= n; i++) if (BN_is_bit_set(dh_pub, i)) bits_set++; debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); /* if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ - if (bits_set > 1 && (BN_cmp(dh_pub, dh->p) == -1)) + if (bits_set > 1) return 1; + logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(dh->p)); return 0; }