diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | moduli.c | 69 | ||||
-rw-r--r-- | ssh-keygen.1 | 13 | ||||
-rw-r--r-- | ssh-keygen.c | 16 |
4 files changed, 92 insertions, 9 deletions
@@ -3,6 +3,9 @@ | |||
3 | - djm@cvs.openbsd.org 2011/10/04 14:17:32 | 3 | - djm@cvs.openbsd.org 2011/10/04 14:17:32 |
4 | [sftp-glob.c] | 4 | [sftp-glob.c] |
5 | silence error spam for "ls */foo" in directory with files; bz#1683 | 5 | silence error spam for "ls */foo" in directory with files; bz#1683 |
6 | - dtucker@cvs.openbsd.org 2011/10/16 11:02:46 | ||
7 | [moduli.c ssh-keygen.1 ssh-keygen.c] | ||
8 | Add optional checkpoints for moduli screening. feedback & ok deraadt | ||
6 | 9 | ||
7 | 20111001 | 10 | 20111001 |
8 | - (dtucker) [openbsd-compat/mktemp.c] Fix compiler warning. ok djm | 11 | - (dtucker) [openbsd-compat/mktemp.c] Fix compiler warning. ok djm |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: moduli.c,v 1.22 2010/11/10 01:33:07 djm Exp $ */ | 1 | /* $OpenBSD: moduli.c,v 1.23 2011/10/16 11:02:46 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 1994 Phil Karn <karn@qualcomm.com> | 3 | * Copyright 1994 Phil Karn <karn@qualcomm.com> |
4 | * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com> | 4 | * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com> |
@@ -49,6 +49,7 @@ | |||
49 | #include <string.h> | 49 | #include <string.h> |
50 | #include <stdarg.h> | 50 | #include <stdarg.h> |
51 | #include <time.h> | 51 | #include <time.h> |
52 | #include <unistd.h> | ||
52 | 53 | ||
53 | #include "xmalloc.h" | 54 | #include "xmalloc.h" |
54 | #include "dh.h" | 55 | #include "dh.h" |
@@ -137,7 +138,7 @@ static u_int32_t largebits, largememory; /* megabytes */ | |||
137 | static BIGNUM *largebase; | 138 | static BIGNUM *largebase; |
138 | 139 | ||
139 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); | 140 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); |
140 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); | 141 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *); |
141 | 142 | ||
142 | /* | 143 | /* |
143 | * print moduli out in consistent form, | 144 | * print moduli out in consistent form, |
@@ -438,6 +439,52 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) | |||
438 | return (ret); | 439 | return (ret); |
439 | } | 440 | } |
440 | 441 | ||
442 | static void | ||
443 | write_checkpoint(char *cpfile, u_int32_t lineno) | ||
444 | { | ||
445 | FILE *fp; | ||
446 | char tmpfile[MAXPATHLEN]; | ||
447 | int r; | ||
448 | |||
449 | r = snprintf(tmpfile, sizeof(tmpfile), "%s.XXXXXXXXXX", cpfile); | ||
450 | if (r == -1 || r >= MAXPATHLEN) { | ||
451 | logit("write_checkpoint: temp pathname too long"); | ||
452 | return; | ||
453 | } | ||
454 | if ((r = mkstemp(tmpfile)) == -1) { | ||
455 | logit("mkstemp(%s): %s", tmpfile, strerror(errno)); | ||
456 | return; | ||
457 | } | ||
458 | if ((fp = fdopen(r, "w")) == NULL) { | ||
459 | logit("write_checkpoint: fdopen: %s", strerror(errno)); | ||
460 | close(r); | ||
461 | return; | ||
462 | } | ||
463 | if (fprintf(fp, "%lu\n", (unsigned long)lineno) > 0 && fclose(fp) == 0 | ||
464 | && rename(tmpfile, cpfile) == 0) | ||
465 | debug3("wrote checkpoint line %lu to '%s'", | ||
466 | (unsigned long)lineno, cpfile); | ||
467 | else | ||
468 | logit("failed to write to checkpoint file '%s': %s", cpfile, | ||
469 | strerror(errno)); | ||
470 | } | ||
471 | |||
472 | static unsigned long | ||
473 | read_checkpoint(char *cpfile) | ||
474 | { | ||
475 | FILE *fp; | ||
476 | unsigned long lineno = 0; | ||
477 | |||
478 | if ((fp = fopen(cpfile, "r")) == NULL) | ||
479 | return 0; | ||
480 | if (fscanf(fp, "%lu\n", &lineno) < 1) | ||
481 | logit("Failed to load checkpoint from '%s'", cpfile); | ||
482 | else | ||
483 | logit("Loaded checkpoint from '%s' line %lu", cpfile, lineno); | ||
484 | fclose(fp); | ||
485 | return lineno; | ||
486 | } | ||
487 | |||
441 | /* | 488 | /* |
442 | * perform a Miller-Rabin primality test | 489 | * perform a Miller-Rabin primality test |
443 | * on the list of candidates | 490 | * on the list of candidates |
@@ -445,13 +492,15 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) | |||
445 | * The result is a list of so-call "safe" primes | 492 | * The result is a list of so-call "safe" primes |
446 | */ | 493 | */ |
447 | int | 494 | int |
448 | prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) | 495 | prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, |
496 | char *checkpoint_file) | ||
449 | { | 497 | { |
450 | BIGNUM *q, *p, *a; | 498 | BIGNUM *q, *p, *a; |
451 | BN_CTX *ctx; | 499 | BN_CTX *ctx; |
452 | char *cp, *lp; | 500 | char *cp, *lp; |
453 | u_int32_t count_in = 0, count_out = 0, count_possible = 0; | 501 | u_int32_t count_in = 0, count_out = 0, count_possible = 0; |
454 | u_int32_t generator_known, in_tests, in_tries, in_type, in_size; | 502 | u_int32_t generator_known, in_tests, in_tries, in_type, in_size; |
503 | unsigned long last_processed = 0; | ||
455 | time_t time_start, time_stop; | 504 | time_t time_start, time_stop; |
456 | int res; | 505 | int res; |
457 | 506 | ||
@@ -472,10 +521,21 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) | |||
472 | debug2("%.24s Final %u Miller-Rabin trials (%x generator)", | 521 | debug2("%.24s Final %u Miller-Rabin trials (%x generator)", |
473 | ctime(&time_start), trials, generator_wanted); | 522 | ctime(&time_start), trials, generator_wanted); |
474 | 523 | ||
524 | if (checkpoint_file != NULL) | ||
525 | last_processed = read_checkpoint(checkpoint_file); | ||
526 | |||
475 | res = 0; | 527 | res = 0; |
476 | lp = xmalloc(QLINESIZE + 1); | 528 | lp = xmalloc(QLINESIZE + 1); |
477 | while (fgets(lp, QLINESIZE + 1, in) != NULL) { | 529 | while (fgets(lp, QLINESIZE + 1, in) != NULL) { |
478 | count_in++; | 530 | count_in++; |
531 | if (checkpoint_file != NULL) { | ||
532 | if (count_in <= last_processed) { | ||
533 | debug3("skipping line %u, before checkpoint", | ||
534 | count_in); | ||
535 | continue; | ||
536 | } | ||
537 | write_checkpoint(checkpoint_file, count_in); | ||
538 | } | ||
479 | if (strlen(lp) < 14 || *lp == '!' || *lp == '#') { | 539 | if (strlen(lp) < 14 || *lp == '!' || *lp == '#') { |
480 | debug2("%10u: comment or short line", count_in); | 540 | debug2("%10u: comment or short line", count_in); |
481 | continue; | 541 | continue; |
@@ -644,6 +704,9 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted) | |||
644 | BN_free(q); | 704 | BN_free(q); |
645 | BN_CTX_free(ctx); | 705 | BN_CTX_free(ctx); |
646 | 706 | ||
707 | if (checkpoint_file != NULL) | ||
708 | unlink(checkpoint_file); | ||
709 | |||
647 | logit("%.24s Found %u safe primes of %u candidates in %ld seconds", | 710 | logit("%.24s Found %u safe primes of %u candidates in %ld seconds", |
648 | ctime(&time_stop), count_out, count_possible, | 711 | ctime(&time_stop), count_out, count_possible, |
649 | (long) (time_stop - time_start)); | 712 | (long) (time_stop - time_start)); |
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 528fcd39d..41da2077b 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.107 2011/09/07 02:18:31 deraadt Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.108 2011/10/16 11:02:46 dtucker Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: September 7 2011 $ | 38 | .Dd $Mdocdate: October 16 2011 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -104,6 +104,7 @@ | |||
104 | .Fl f Ar input_file | 104 | .Fl f Ar input_file |
105 | .Op Fl v | 105 | .Op Fl v |
106 | .Op Fl a Ar num_trials | 106 | .Op Fl a Ar num_trials |
107 | .Op Fl K Ar checkpt | ||
107 | .Op Fl W Ar generator | 108 | .Op Fl W Ar generator |
108 | .Nm ssh-keygen | 109 | .Nm ssh-keygen |
109 | .Fl s Ar ca_key | 110 | .Fl s Ar ca_key |
@@ -296,6 +297,14 @@ in the format specified by the | |||
296 | .Fl m | 297 | .Fl m |
297 | option and print an OpenSSH compatible private | 298 | option and print an OpenSSH compatible private |
298 | (or public) key to stdout. | 299 | (or public) key to stdout. |
300 | .It Fl K Ar checkpt | ||
301 | Write the last line processed to the file | ||
302 | .Ar checkpt | ||
303 | while performing DH candidate screening using the | ||
304 | .Fl T | ||
305 | option. | ||
306 | This will be used to skip lines in the input file that have already been | ||
307 | processed if the job is restarted. | ||
299 | This option allows importing keys from other software, including several | 308 | This option allows importing keys from other software, including several |
300 | commercial SSH implementations. | 309 | commercial SSH implementations. |
301 | The default import format is | 310 | The default import format is |
diff --git a/ssh-keygen.c b/ssh-keygen.c index 4b6218b10..bd15cccff 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.210 2011/04/18 00:46:05 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.211 2011/10/16 11:02:46 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -154,7 +154,7 @@ char hostname[MAXHOSTNAMELEN]; | |||
154 | 154 | ||
155 | /* moduli.c */ | 155 | /* moduli.c */ |
156 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); | 156 | int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); |
157 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); | 157 | int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *); |
158 | 158 | ||
159 | static void | 159 | static void |
160 | type_bits_valid(int type, u_int32_t *bitsp) | 160 | type_bits_valid(int type, u_int32_t *bitsp) |
@@ -1881,6 +1881,7 @@ usage(void) | |||
1881 | fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); | 1881 | fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); |
1882 | fprintf(stderr, " -g Use generic DNS resource record format.\n"); | 1882 | fprintf(stderr, " -g Use generic DNS resource record format.\n"); |
1883 | fprintf(stderr, " -H Hash names in known_hosts file.\n"); | 1883 | fprintf(stderr, " -H Hash names in known_hosts file.\n"); |
1884 | fprintf(stderr, " -K checkpt Write checkpoints to this file.\n"); | ||
1884 | fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); | 1885 | fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); |
1885 | fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); | 1886 | fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); |
1886 | fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); | 1887 | fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); |
@@ -1916,6 +1917,7 @@ int | |||
1916 | main(int argc, char **argv) | 1917 | main(int argc, char **argv) |
1917 | { | 1918 | { |
1918 | char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; | 1919 | char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; |
1920 | char *checkpoint = NULL; | ||
1919 | char out_file[MAXPATHLEN], *rr_hostname = NULL; | 1921 | char out_file[MAXPATHLEN], *rr_hostname = NULL; |
1920 | Key *private, *public; | 1922 | Key *private, *public; |
1921 | struct passwd *pw; | 1923 | struct passwd *pw; |
@@ -1952,7 +1954,7 @@ main(int argc, char **argv) | |||
1952 | exit(1); | 1954 | exit(1); |
1953 | } | 1955 | } |
1954 | 1956 | ||
1955 | while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" | 1957 | while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:K:P:m:N:n:" |
1956 | "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { | 1958 | "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { |
1957 | switch (opt) { | 1959 | switch (opt) { |
1958 | case 'A': | 1960 | case 'A': |
@@ -2103,6 +2105,11 @@ main(int argc, char **argv) | |||
2103 | sizeof(out_file)) | 2105 | sizeof(out_file)) |
2104 | fatal("Output filename too long"); | 2106 | fatal("Output filename too long"); |
2105 | break; | 2107 | break; |
2108 | case 'K': | ||
2109 | if (strlen(optarg) >= MAXPATHLEN) | ||
2110 | fatal("Checkpoint filename too long"); | ||
2111 | checkpoint = xstrdup(optarg); | ||
2112 | break; | ||
2106 | case 'S': | 2113 | case 'S': |
2107 | /* XXX - also compare length against bits */ | 2114 | /* XXX - also compare length against bits */ |
2108 | if (BN_hex2bn(&start, optarg) == 0) | 2115 | if (BN_hex2bn(&start, optarg) == 0) |
@@ -2225,7 +2232,8 @@ main(int argc, char **argv) | |||
2225 | fatal("Couldn't open moduli file \"%s\": %s", | 2232 | fatal("Couldn't open moduli file \"%s\": %s", |
2226 | out_file, strerror(errno)); | 2233 | out_file, strerror(errno)); |
2227 | } | 2234 | } |
2228 | if (prime_test(in, out, trials, generator_wanted) != 0) | 2235 | if (prime_test(in, out, trials, generator_wanted, checkpoint) |
2236 | != 0) | ||
2229 | fatal("modulus screening failed"); | 2237 | fatal("modulus screening failed"); |
2230 | return (0); | 2238 | return (0); |
2231 | } | 2239 | } |