[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
[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

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 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com>
@ -49,6 +49,7 @@
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#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));

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>
.\" 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
.\" 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

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>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, 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);
}