From 390d0561fccfba5e2e97105f75b70b32aab59578 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 18 Oct 2011 16:05:19 +1100 Subject: - 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 --- ChangeLog | 3 +++ moduli.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- ssh-keygen.1 | 13 ++++++++++-- ssh-keygen.c | 16 ++++++++++---- 4 files changed, 92 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1d00c68c..9f33f53b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ - djm@cvs.openbsd.org 2011/10/04 14:17:32 [sftp-glob.c] 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 - (dtucker) [openbsd-compat/mktemp.c] Fix compiler warning. ok djm diff --git a/moduli.c b/moduli.c index 2964a8b3..f734d1c2 100644 --- a/moduli.c +++ b/moduli.c @@ -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 * Copyright 1996-1998, 2003 William Allen Simpson @@ -49,6 +49,7 @@ #include #include #include +#include #include "xmalloc.h" #include "dh.h" @@ -137,7 +138,7 @@ static u_int32_t largebits, largememory; /* megabytes */ static BIGNUM *largebase; 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, @@ -438,6 +439,52 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) 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 * 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 */ 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; BN_CTX *ctx; char *cp, *lp; 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; + unsigned long last_processed = 0; time_t time_start, time_stop; 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)", ctime(&time_start), trials, generator_wanted); + if (checkpoint_file != NULL) + last_processed = read_checkpoint(checkpoint_file); + res = 0; lp = xmalloc(QLINESIZE + 1); while (fgets(lp, QLINESIZE + 1, in) != NULL) { 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 == '#') { debug2("%10u: comment or short line", count_in); continue; @@ -644,6 +704,9 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) BN_free(q); BN_CTX_free(ctx); + if (checkpoint_file != NULL) + unlink(checkpoint_file); + logit("%.24s Found %u safe primes of %u candidates in %ld seconds", ctime(&time_stop), count_out, count_possible, (long) (time_stop - time_start)); diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 528fcd39..41da2077 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -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 .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" 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 .Os .Sh NAME @@ -104,6 +104,7 @@ .Fl f Ar input_file .Op Fl v .Op Fl a Ar num_trials +.Op Fl K Ar checkpt .Op Fl W Ar generator .Nm ssh-keygen .Fl s Ar ca_key @@ -296,6 +297,14 @@ in the format specified by the .Fl m option and print an OpenSSH compatible private (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 commercial SSH implementations. The default import format is diff --git a/ssh-keygen.c b/ssh-keygen.c index 4b6218b1..bd15cccf 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -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 * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -154,7 +154,7 @@ char hostname[MAXHOSTNAMELEN]; /* moduli.c */ 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 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 Use generic DNS resource record format.\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, " -I key_id Key identifier to include in certificate.\n"); fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); @@ -1916,6 +1917,7 @@ int main(int argc, char **argv) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; + char *checkpoint = NULL; char out_file[MAXPATHLEN], *rr_hostname = NULL; Key *private, *public; struct passwd *pw; @@ -1952,7 +1954,7 @@ main(int argc, char **argv) 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) { switch (opt) { case 'A': @@ -2103,6 +2105,11 @@ main(int argc, char **argv) sizeof(out_file)) fatal("Output filename too long"); break; + case 'K': + if (strlen(optarg) >= MAXPATHLEN) + fatal("Checkpoint filename too long"); + checkpoint = xstrdup(optarg); + break; case 'S': /* XXX - also compare length against bits */ if (BN_hex2bn(&start, optarg) == 0) @@ -2225,7 +2232,8 @@ main(int argc, char **argv) fatal("Couldn't open moduli file \"%s\": %s", 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"); return (0); } -- cgit v1.2.3