[moduli.c ssh-keygen.1 ssh-keygen.c]
     Add optional checkpoints for moduli screening.  feedback & ok deraadt
This commit is contained in:
Damien Miller 2011-10-18 16:05:19 +11:00
parent d3e6990c4c
commit 390d0561fc
4 changed files with 92 additions and 9 deletions

View File

@ -3,6 +3,9 @@
- djm@cvs.openbsd.org 2011/10/04 14:17:32 - djm@cvs.openbsd.org 2011/10/04 14:17:32
[sftp-glob.c] [sftp-glob.c]
silence error spam for "ls */foo" in directory with files; bz#1683 silence error spam for "ls */foo" in directory with files; bz#1683
- dtucker@cvs.openbsd.org 2011/10/16 11:02:46
[moduli.c ssh-keygen.1 ssh-keygen.c]
Add optional checkpoints for moduli screening. feedback & ok deraadt
20111001 20111001
- (dtucker) [openbsd-compat/mktemp.c] Fix compiler warning. ok djm - (dtucker) [openbsd-compat/mktemp.c] Fix compiler warning. ok djm

View File

@ -1,4 +1,4 @@
/* $OpenBSD: moduli.c,v 1.22 2010/11/10 01:33:07 djm Exp $ */ /* $OpenBSD: moduli.c,v 1.23 2011/10/16 11:02:46 dtucker 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>
@ -49,6 +49,7 @@
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include "xmalloc.h" #include "xmalloc.h"
#include "dh.h" #include "dh.h"
@ -137,7 +138,7 @@ static u_int32_t largebits, largememory; /* megabytes */
static BIGNUM *largebase; static BIGNUM *largebase;
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *);
/* /*
* print moduli out in consistent form, * print moduli out in consistent form,
@ -438,6 +439,52 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
return (ret); return (ret);
} }
static void
write_checkpoint(char *cpfile, u_int32_t lineno)
{
FILE *fp;
char tmpfile[MAXPATHLEN];
int r;
r = snprintf(tmpfile, sizeof(tmpfile), "%s.XXXXXXXXXX", cpfile);
if (r == -1 || r >= MAXPATHLEN) {
logit("write_checkpoint: temp pathname too long");
return;
}
if ((r = mkstemp(tmpfile)) == -1) {
logit("mkstemp(%s): %s", tmpfile, strerror(errno));
return;
}
if ((fp = fdopen(r, "w")) == NULL) {
logit("write_checkpoint: fdopen: %s", strerror(errno));
close(r);
return;
}
if (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0 && fclose(fp) == 0
&& rename(tmpfile, cpfile) == 0)
debug3("wrote checkpoint line %lu to '%s'",
(unsigned long)lineno, cpfile);
else
logit("failed to write to checkpoint file '%s': %s", cpfile,
strerror(errno));
}
static unsigned long
read_checkpoint(char *cpfile)
{
FILE *fp;
unsigned long lineno = 0;
if ((fp = fopen(cpfile, "r")) == NULL)
return 0;
if (fscanf(fp, "%lu\n", &lineno) < 1)
logit("Failed to load checkpoint from '%s'", cpfile);
else
logit("Loaded checkpoint from '%s' line %lu", cpfile, lineno);
fclose(fp);
return lineno;
}
/* /*
* perform a Miller-Rabin primality test * perform a Miller-Rabin primality test
* on the list of candidates * on the list of candidates
@ -445,13 +492,15 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start)
* The result is a list of so-call "safe" primes * The result is a list of so-call "safe" primes
*/ */
int int
prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted,
char *checkpoint_file)
{ {
BIGNUM *q, *p, *a; BIGNUM *q, *p, *a;
BN_CTX *ctx; BN_CTX *ctx;
char *cp, *lp; char *cp, *lp;
u_int32_t count_in = 0, count_out = 0, count_possible = 0; u_int32_t count_in = 0, count_out = 0, count_possible = 0;
u_int32_t generator_known, in_tests, in_tries, in_type, in_size; u_int32_t generator_known, in_tests, in_tries, in_type, in_size;
unsigned long last_processed = 0;
time_t time_start, time_stop; time_t time_start, time_stop;
int res; int res;
@ -472,10 +521,21 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
debug2("%.24s Final %u Miller-Rabin trials (%x generator)", debug2("%.24s Final %u Miller-Rabin trials (%x generator)",
ctime(&time_start), trials, generator_wanted); ctime(&time_start), trials, generator_wanted);
if (checkpoint_file != NULL)
last_processed = read_checkpoint(checkpoint_file);
res = 0; res = 0;
lp = xmalloc(QLINESIZE + 1); lp = xmalloc(QLINESIZE + 1);
while (fgets(lp, QLINESIZE + 1, in) != NULL) { while (fgets(lp, QLINESIZE + 1, in) != NULL) {
count_in++; count_in++;
if (checkpoint_file != NULL) {
if (count_in <= last_processed) {
debug3("skipping line %u, before checkpoint",
count_in);
continue;
}
write_checkpoint(checkpoint_file, count_in);
}
if (strlen(lp) < 14 || *lp == '!' || *lp == '#') { if (strlen(lp) < 14 || *lp == '!' || *lp == '#') {
debug2("%10u: comment or short line", count_in); debug2("%10u: comment or short line", count_in);
continue; continue;
@ -644,6 +704,9 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted)
BN_free(q); BN_free(q);
BN_CTX_free(ctx); BN_CTX_free(ctx);
if (checkpoint_file != NULL)
unlink(checkpoint_file);
logit("%.24s Found %u safe primes of %u candidates in %ld seconds", logit("%.24s Found %u safe primes of %u candidates in %ld seconds",
ctime(&time_stop), count_out, count_possible, ctime(&time_stop), count_out, count_possible,
(long) (time_stop - time_start)); (long) (time_stop - time_start));

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.107 2011/09/07 02:18:31 deraadt Exp $ .\" $OpenBSD: ssh-keygen.1,v 1.108 2011/10/16 11:02:46 dtucker Exp $
.\" .\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi> .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: September 7 2011 $ .Dd $Mdocdate: October 16 2011 $
.Dt SSH-KEYGEN 1 .Dt SSH-KEYGEN 1
.Os .Os
.Sh NAME .Sh NAME
@ -104,6 +104,7 @@
.Fl f Ar input_file .Fl f Ar input_file
.Op Fl v .Op Fl v
.Op Fl a Ar num_trials .Op Fl a Ar num_trials
.Op Fl K Ar checkpt
.Op Fl W Ar generator .Op Fl W Ar generator
.Nm ssh-keygen .Nm ssh-keygen
.Fl s Ar ca_key .Fl s Ar ca_key
@ -296,6 +297,14 @@ in the format specified by the
.Fl m .Fl m
option and print an OpenSSH compatible private option and print an OpenSSH compatible private
(or public) key to stdout. (or public) key to stdout.
.It Fl K Ar checkpt
Write the last line processed to the file
.Ar checkpt
while performing DH candidate screening using the
.Fl T
option.
This will be used to skip lines in the input file that have already been
processed if the job is restarted.
This option allows importing keys from other software, including several This option allows importing keys from other software, including several
commercial SSH implementations. commercial SSH implementations.
The default import format is The default import format is

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keygen.c,v 1.210 2011/04/18 00:46:05 djm Exp $ */ /* $OpenBSD: ssh-keygen.c,v 1.211 2011/10/16 11:02:46 dtucker Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -154,7 +154,7 @@ char hostname[MAXHOSTNAMELEN];
/* moduli.c */ /* moduli.c */
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *);
static void static void
type_bits_valid(int type, u_int32_t *bitsp) type_bits_valid(int type, u_int32_t *bitsp)
@ -1881,6 +1881,7 @@ usage(void)
fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n");
fprintf(stderr, " -g Use generic DNS resource record format.\n"); fprintf(stderr, " -g Use generic DNS resource record format.\n");
fprintf(stderr, " -H Hash names in known_hosts file.\n"); fprintf(stderr, " -H Hash names in known_hosts file.\n");
fprintf(stderr, " -K checkpt Write checkpoints to this file.\n");
fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n");
fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); fprintf(stderr, " -I key_id Key identifier to include in certificate.\n");
fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n");
@ -1916,6 +1917,7 @@ int
main(int argc, char **argv) main(int argc, char **argv)
{ {
char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
char *checkpoint = NULL;
char out_file[MAXPATHLEN], *rr_hostname = NULL; char out_file[MAXPATHLEN], *rr_hostname = NULL;
Key *private, *public; Key *private, *public;
struct passwd *pw; struct passwd *pw;
@ -1952,7 +1954,7 @@ main(int argc, char **argv)
exit(1); exit(1);
} }
while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:K:P:m:N:n:"
"O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
switch (opt) { switch (opt) {
case 'A': case 'A':
@ -2103,6 +2105,11 @@ main(int argc, char **argv)
sizeof(out_file)) sizeof(out_file))
fatal("Output filename too long"); fatal("Output filename too long");
break; break;
case 'K':
if (strlen(optarg) >= MAXPATHLEN)
fatal("Checkpoint filename too long");
checkpoint = xstrdup(optarg);
break;
case 'S': case 'S':
/* XXX - also compare length against bits */ /* XXX - also compare length against bits */
if (BN_hex2bn(&start, optarg) == 0) if (BN_hex2bn(&start, optarg) == 0)
@ -2225,7 +2232,8 @@ main(int argc, char **argv)
fatal("Couldn't open moduli file \"%s\": %s", fatal("Couldn't open moduli file \"%s\": %s",
out_file, strerror(errno)); out_file, strerror(errno));
} }
if (prime_test(in, out, trials, generator_wanted) != 0) if (prime_test(in, out, trials, generator_wanted, checkpoint)
!= 0)
fatal("modulus screening failed"); fatal("modulus screening failed");
return (0); return (0);
} }