From c35a6dc5a1c707c0f6255b1ea628aaac342eb72f Mon Sep 17 00:00:00 2001 From: dtucker Date: Sat, 2 Aug 2003 12:40:07 +0000 Subject: [PATCH] - djm@cvs.openbsd.org 2003/07/28 09:49:56 [ssh-keygen.1 ssh-keygen.c] Support for generating Diffie-Hellman groups (/etc/moduli) from ssh-keygen. Based on code from Phil Karn, William Allen Simpson and Niels Provos. ok markus@, thanks jmc@ --- ChangeLog | 5 +++ ssh-keygen.1 | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++- ssh-keygen.c | 86 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 186 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 754f0ec4..12aa555e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,11 @@ - markus@cvs.openbsd.org 2003/07/23 07:42:43 [sshd_config] remove AFS; itojun@ + - djm@cvs.openbsd.org 2003/07/28 09:49:56 + [ssh-keygen.1 ssh-keygen.c] + Support for generating Diffie-Hellman groups (/etc/moduli) from ssh-keygen. + Based on code from Phil Karn, William Allen Simpson and Niels Provos. + ok markus@, thanks jmc@ 20030730 - (djm) [auth-pam.c] Don't use crappy APIs like sprintf. Thanks bal diff --git a/ssh-keygen.1 b/ssh-keygen.1 index fc6b5a5e..dc4bcacd 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.59 2003/06/10 09:12:11 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.60 2003/07/28 09:49:56 djm Exp $ .\" .\" -*- nroff -*- .\" @@ -87,6 +87,16 @@ .Fl r Ar hostname .Op Fl f Ar input_keyfile .Op Fl g +.Nm ssh-keygen +.Fl G Ar output_file +.Op Fl b Ar bits +.Op Fl M Ar memory +.Op Fl S Ar start_point +.Nm ssh-keygen +.Fl T Ar output_file +.Fl f Ar input_file +.Op Fl a Ar num_trials +.Op Fl W Ar generator .Sh DESCRIPTION .Nm generates, manages and converts authentication keys for @@ -98,6 +108,13 @@ The type of key to be generated is specified with the .Fl t option. .Pp +.Nm +is also used to generate groups for use in Diffie-Hellman group +exchange (DH-GEX). +See the +.Sx MODULI GENERATION +section for details. +.Pp Normally each user wishing to use SSH with RSA or DSA authentication runs this once to create the authentication key in @@ -150,6 +167,11 @@ should be placed to be activated. .Pp The options are as follows: .Bl -tag -width Ds +.It Fl a Ar trials +Specifies the number of primality tests to perform when screening DH-GEX +candidates using the +.Fl T +command. .It Fl b Ar bits Specifies the number of bits in the key to create. Minimum is 512 bits. @@ -217,10 +239,27 @@ Provides the new comment. .It Fl D Ar reader Download the RSA public key stored in the smartcard in .Ar reader . +.It Fl G Ar output_file +Generate candidate primes for DH-GEX. +These primes must be screened for +safety (using the +.Fl T +option) before use. +.It Fl M Ar memory +Specify the amount of memory to use (in megabytes) when generating +candidate moduli for DH-GEX. .It Fl N Ar new_passphrase Provides the new passphrase. .It Fl P Ar passphrase Provides the (old) passphrase. +.It Fl S Ar start +Specify start point (in hex) when generating candidate moduli for DH-GEX. +.It Fl T Ar output_file +Test DH group exchange candidate primes (generated using the +.Fl G +option) for safety. +.It Fl W Ar generator +Specify desired generator when testing candidate moduli for DH-GEX. .It Fl U Ar reader Upload an existing RSA private key into the smartcard in .Ar reader . @@ -228,6 +267,60 @@ Upload an existing RSA private key into the smartcard in Print DNS resource record with the specified .Ar hostname . .El +.Sh MODULI GENERATION +.Nm +may be used to generate groups for the Diffie-Hellman Group Exchange +(DH-GEX) protocol. +Generating these groups is a two-step process: first, candidate +primes are generated using a fast, but memory intensive process. +These candidate primes are then tested for suitability (a CPU-intensive +process). +.Pp +Generation of primes is performed using the +.Fl G +option. +The desired length of the primes may be specified by the +.Fl b +option. +For example: +.Pp +.Dl ssh-keygen -G moduli-2048.candidates -b 2048 +.Pp +By default, the search for primes begins at a random point in the +desired length range. +This may be overridden using the +.Fl S +option, which specifies a different start point (in hex). +.Pp +Once a set of candidates have been generated, they must be tested for +suitability. +This may be performed using the +.Fl T +option. +In this mode +.Nm +will read candidates from standard input (or a file specified using the +.Fl f +option). +For example: +.Pp +.Dl ssh-keygen -T moduli-2048 -f moduli-2048.candidates +.Pp +By default, each candidate will be subjected to 100 primality tests. +This may be overridden using the +.Fl a +option. +The DH generator value will be chosen automatically for the +prime under consideration. +If a specific generator is desired, it may be requested using the +.Fl W +option. +Valid generator values are 2, 3 and 5. +.Pp +Screened DH groups may be installed in +.Pa /etc/moduli . +It is important that this file contains moduli of a range of bit lengths and +that both ends of a connection share common moduli. .Sh FILES .Bl -tag -width Ds .It Pa $HOME/.ssh/identity @@ -284,11 +377,16 @@ The contents of this file should be added to on all machines where the user wishes to log in using public key authentication. There is no need to keep the contents of this file secret. +.It Pa /etc/moduli +Contains Diffie-Hellman groups used for DH-GEX. +The file format is described in +.Xr moduli 5 . .El .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , +.Xr moduli 5 , .Xr sshd 8 .Rs .%A J. Galbraith diff --git a/ssh-keygen.c b/ssh-keygen.c index c93d70ba..a6342b18 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -12,7 +12,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keygen.c,v 1.106 2003/05/15 03:10:52 djm Exp $"); +RCSID("$OpenBSD: ssh-keygen.c,v 1.107 2003/07/28 09:49:56 djm Exp $"); #include #include @@ -27,6 +27,7 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.106 2003/05/15 03:10:52 djm Exp $"); #include "pathnames.h" #include "log.h" #include "readpass.h" +#include "moduli.h" #ifdef SMARTCARD #include "scard.h" @@ -781,6 +782,9 @@ usage(void) fprintf(stderr, " -U reader Upload private key to smartcard.\n"); #endif /* SMARTCARD */ + fprintf(stderr, " -G file Generate candidates for DH-GEX moduli\n"); + fprintf(stderr, " -T file Screen candidates for DH-GEX moduli\n"); + exit(1); } @@ -791,12 +795,15 @@ int main(int ac, char **av) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; - char *reader_id = NULL; + char out_file[PATH_MAX], *reader_id = NULL; char *resource_record_hostname = NULL; Key *private, *public; struct passwd *pw; struct stat st; - int opt, type, fd, download = 0; + int opt, type, fd, download = 0, memory = 0; + int generator_wanted = 0, trials = 100; + int do_gen_candidates = 0, do_screen_candidates = 0; + BIGNUM *start = NULL; FILE *f; extern int optind; @@ -805,6 +812,8 @@ main(int ac, char **av) __progname = get_progname(av[0]); SSLeay_add_all_algorithms(); + log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + init_rng(); seed_rng(); @@ -819,7 +828,8 @@ main(int ac, char **av) exit(1); } - while ((opt = getopt(ac, av, "degiqpclBRxXyb:f:t:U:D:P:N:C:r:")) != -1) { + while ((opt = getopt(ac, av, + "degiqpclBRxXyb:f:t:U:D:P:N:C:r:g:T:G:M:S:a:W:")) != -1) { switch (opt) { case 'b': bits = atoi(optarg); @@ -890,6 +900,39 @@ main(int ac, char **av) case 'r': resource_record_hostname = optarg; break; + case 'W': + generator_wanted = atoi(optarg); + if (generator_wanted < 1) + fatal("Desired generator has bad value."); + break; + case 'a': + trials = atoi(optarg); + if (trials < TRIAL_MINIMUM) { + fatal("Minimum primality trials is %d", + TRIAL_MINIMUM); + } + break; + case 'M': + memory = atoi(optarg); + if (memory != 0 && + (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { + fatal("Invalid memory amount (min %ld, max %ld)", + LARGE_MINIMUM, LARGE_MAXIMUM); + } + break; + case 'G': + do_gen_candidates = 1; + strlcpy(out_file, optarg, sizeof(out_file)); + break; + case 'T': + do_screen_candidates = 1; + strlcpy(out_file, optarg, sizeof(out_file)); + break; + case 'S': + /* XXX - also compare length against bits */ + if (BN_hex2bn(&start, optarg) == 0) + fatal("Invalid start point."); + break; case '?': default: usage(); @@ -933,6 +976,41 @@ main(int ac, char **av) #endif /* SMARTCARD */ } + if (do_gen_candidates) { + FILE *out = fopen(out_file, "w"); + + if (out == NULL) { + error("Couldn't open modulus candidate file \"%s\": %s", + out_file, strerror(errno)); + return (1); + } + if (gen_candidates(out, memory, bits, start) != 0) + fatal("modulus candidate generation failed\n"); + + return (0); + } + + if (do_screen_candidates) { + FILE *in; + FILE *out = fopen(out_file, "w"); + + if (have_identity && strcmp(identity_file, "-") != 0) { + if ((in = fopen(identity_file, "r")) == NULL) { + fatal("Couldn't open modulus candidate " + "file \"%s\": %s", identity_file, + strerror(errno)); + } + } else + in = stdin; + + if (out == NULL) { + fatal("Couldn't open moduli file \"%s\": %s", + out_file, strerror(errno)); + } + if (prime_test(in, out, trials, generator_wanted) != 0) + fatal("modulus screening failed\n"); + } + arc4random_stir(); if (key_type_name == NULL) { -- 2.45.2