- djm@cvs.openbsd.org 2008/06/26 09:19:40

[dh.c dh.h moduli.c]
     when loading moduli from /etc/moduli in sshd(8), check that they
     are of the expected "safe prime" structure and have had
     appropriate primality tests performed;
     feedback and ok dtucker@
This commit is contained in:
Damien Miller 2008-06-29 22:47:04 +10:00
parent 9e720284fe
commit 2e9cf49069
4 changed files with 62 additions and 36 deletions

View File

@ -14,6 +14,12 @@
bits. Note that this only affects explicit setting of modes (e.g. via bits. Note that this only affects explicit setting of modes (e.g. via
sftp(1)'s chmod command) and not file transfers. (bz#1310) sftp(1)'s chmod command) and not file transfers. (bz#1310)
ok deraadt@ at c2k8 ok deraadt@ at c2k8
- djm@cvs.openbsd.org 2008/06/26 09:19:40
[dh.c dh.h moduli.c]
when loading moduli from /etc/moduli in sshd(8), check that they
are of the expected "safe prime" structure and have had
appropriate primality tests performed;
feedback and ok dtucker@
20080628 20080628
- (djm) [RFC.nroff contrib/cygwin/Makefile contrib/suse/openssh.spec] - (djm) [RFC.nroff contrib/cygwin/Makefile contrib/suse/openssh.spec]
@ -4434,4 +4440,4 @@
OpenServer 6 and add osr5bigcrypt support so when someone migrates OpenServer 6 and add osr5bigcrypt support so when someone migrates
passwords between UnixWare and OpenServer they will still work. OK dtucker@ passwords between UnixWare and OpenServer they will still work. OK dtucker@
$Id: ChangeLog,v 1.5027 2008/06/29 12:46:35 djm Exp $ $Id: ChangeLog,v 1.5028 2008/06/29 12:47:04 djm Exp $

15
dh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dh.c,v 1.46 2008/04/13 00:22:17 djm Exp $ */ /* $OpenBSD: dh.c,v 1.47 2008/06/26 09:19:39 djm Exp $ */
/* /*
* Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2000 Niels Provos. All rights reserved.
* *
@ -46,6 +46,7 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
char *cp, *arg; char *cp, *arg;
char *strsize, *gen, *prime; char *strsize, *gen, *prime;
const char *errstr = NULL; const char *errstr = NULL;
long long n;
cp = line; cp = line;
if ((arg = strdelim(&cp)) == NULL) if ((arg = strdelim(&cp)) == NULL)
@ -62,12 +63,24 @@ parse_prime(int linenum, char *line, struct dhgroup *dhg)
arg = strsep(&cp, " "); /* type */ arg = strsep(&cp, " "); /* type */
if (cp == NULL || *arg == '\0') if (cp == NULL || *arg == '\0')
goto fail; 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 */ arg = strsep(&cp, " "); /* tests */
if (cp == NULL || *arg == '\0') if (cp == NULL || *arg == '\0')
goto fail; 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 */ arg = strsep(&cp, " "); /* tries */
if (cp == NULL || *arg == '\0') if (cp == NULL || *arg == '\0')
goto fail; goto fail;
n = strtonum(arg, 0, 1<<30, &errstr);
if (errstr != NULL || n == 0)
goto fail;
strsize = strsep(&cp, " "); /* size */ strsize = strsep(&cp, " "); /* size */
if (cp == NULL || *strsize == '\0' || if (cp == NULL || *strsize == '\0' ||
(dhg->size = (u_int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 || (dhg->size = (u_int)strtonum(strsize, 0, 64*1024, &errstr)) == 0 ||

26
dh.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dh.h,v 1.9 2006/03/25 22:22:43 djm Exp $ */ /* $OpenBSD: dh.h,v 1.10 2008/06/26 09:19:40 djm Exp $ */
/* /*
* Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2000 Niels Provos. All rights reserved.
@ -46,4 +46,28 @@ int dh_estimate(int);
#define DH_GRP_MIN 1024 #define DH_GRP_MIN 1024
#define DH_GRP_MAX 8192 #define DH_GRP_MAX 8192
/*
* Values for "type" field of moduli(5)
* Specifies the internal structure of the prime modulus.
*/
#define MODULI_TYPE_UNKNOWN (0)
#define MODULI_TYPE_UNSTRUCTURED (1)
#define MODULI_TYPE_SAFE (2)
#define MODULI_TYPE_SCHNORR (3)
#define MODULI_TYPE_SOPHIE_GERMAIN (4)
#define MODULI_TYPE_STRONG (5)
/*
* Values for "tests" field of moduli(5)
* Specifies the methods used in checking for primality.
* Usually, more than one test is used.
*/
#define MODULI_TESTS_UNTESTED (0x00)
#define MODULI_TESTS_COMPOSITE (0x01)
#define MODULI_TESTS_SIEVE (0x02)
#define MODULI_TESTS_MILLER_RABIN (0x04)
#define MODULI_TESTS_JACOBI (0x08)
#define MODULI_TESTS_ELLIPTIC (0x10)
#endif #endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: moduli.c,v 1.20 2007/02/24 03:30:11 ray Exp $ */ /* $OpenBSD: moduli.c,v 1.21 2008/06/26 09:19:40 djm Exp $ */
/* /*
* Copyright 1994 Phil Karn <karn@qualcomm.com> * Copyright 1994 Phil Karn <karn@qualcomm.com>
* Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com> * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
@ -42,6 +42,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/dh.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -50,6 +51,7 @@
#include <time.h> #include <time.h>
#include "xmalloc.h" #include "xmalloc.h"
#include "dh.h"
#include "log.h" #include "log.h"
/* /*
@ -59,27 +61,6 @@
/* need line long enough for largest moduli plus headers */ /* need line long enough for largest moduli plus headers */
#define QLINESIZE (100+8192) #define QLINESIZE (100+8192)
/* Type: decimal.
* Specifies the internal structure of the prime modulus.
*/
#define QTYPE_UNKNOWN (0)
#define QTYPE_UNSTRUCTURED (1)
#define QTYPE_SAFE (2)
#define QTYPE_SCHNORR (3)
#define QTYPE_SOPHIE_GERMAIN (4)
#define QTYPE_STRONG (5)
/* Tests: decimal (bit field).
* Specifies the methods used in checking for primality.
* Usually, more than one test is used.
*/
#define QTEST_UNTESTED (0x00)
#define QTEST_COMPOSITE (0x01)
#define QTEST_SIEVE (0x02)
#define QTEST_MILLER_RABIN (0x04)
#define QTEST_JACOBI (0x08)
#define QTEST_ELLIPTIC (0x10)
/* /*
* Size: decimal. * Size: decimal.
* Specifies the number of the most significant bit (0 to M). * Specifies the number of the most significant bit (0 to M).
@ -434,8 +415,9 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
fatal("BN_set_word failed"); fatal("BN_set_word failed");
if (BN_add(q, q, largebase) == 0) if (BN_add(q, q, largebase) == 0)
fatal("BN_add failed"); fatal("BN_add failed");
if (qfileout(out, QTYPE_SOPHIE_GERMAIN, QTEST_SIEVE, if (qfileout(out, MODULI_TYPE_SOPHIE_GERMAIN,
largetries, (power - 1) /* MSB */, (0), q) == -1) { MODULI_TESTS_SIEVE, largetries,
(power - 1) /* MSB */, (0), q) == -1) {
ret = -1; ret = -1;
break; break;
} }
@ -507,7 +489,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
/* tests */ /* tests */
in_tests = strtoul(cp, &cp, 10); in_tests = strtoul(cp, &cp, 10);
if (in_tests & QTEST_COMPOSITE) { if (in_tests & MODULI_TESTS_COMPOSITE) {
debug2("%10u: known composite", count_in); debug2("%10u: known composite", count_in);
continue; continue;
} }
@ -526,7 +508,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
/* modulus (hex) */ /* modulus (hex) */
switch (in_type) { switch (in_type) {
case QTYPE_SOPHIE_GERMAIN: case MODULI_TYPE_SOPHIE_GERMAIN:
debug2("%10u: (%u) Sophie-Germain", count_in, in_type); debug2("%10u: (%u) Sophie-Germain", count_in, in_type);
a = q; a = q;
if (BN_hex2bn(&a, cp) == 0) if (BN_hex2bn(&a, cp) == 0)
@ -539,11 +521,11 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
in_size += 1; in_size += 1;
generator_known = 0; generator_known = 0;
break; break;
case QTYPE_UNSTRUCTURED: case MODULI_TYPE_UNSTRUCTURED:
case QTYPE_SAFE: case MODULI_TYPE_SAFE:
case QTYPE_SCHNORR: case MODULI_TYPE_SCHNORR:
case QTYPE_STRONG: case MODULI_TYPE_STRONG:
case QTYPE_UNKNOWN: case MODULI_TYPE_UNKNOWN:
debug2("%10u: (%u)", count_in, in_type); debug2("%10u: (%u)", count_in, in_type);
a = p; a = p;
if (BN_hex2bn(&a, cp) == 0) if (BN_hex2bn(&a, cp) == 0)
@ -570,7 +552,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
continue; continue;
} }
if (in_tests & QTEST_MILLER_RABIN) if (in_tests & MODULI_TESTS_MILLER_RABIN)
in_tries += trials; in_tries += trials;
else else
in_tries = trials; in_tries = trials;
@ -644,7 +626,8 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
} }
debug("%10u: q is almost certainly prime", count_in); debug("%10u: q is almost certainly prime", count_in);
if (qfileout(out, QTYPE_SAFE, (in_tests | QTEST_MILLER_RABIN), if (qfileout(out, MODULI_TYPE_SAFE,
in_tests | MODULI_TESTS_MILLER_RABIN,
in_tries, in_size, generator_known, p)) { in_tries, in_size, generator_known, p)) {
res = -1; res = -1;
break; break;