- 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@
This commit is contained in:
Darren Tucker 2003-08-02 22:40:07 +10:00
parent c20c60bc99
commit 019cefeaad
3 changed files with 187 additions and 6 deletions

View File

@ -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
@ -751,4 +756,4 @@
- Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
Report from murple@murple.net, diagnosis from dtucker@zip.com.au
$Id: ChangeLog,v 1.2870 2003/08/02 12:31:45 dtucker Exp $
$Id: ChangeLog,v 1.2871 2003/08/02 12:40:07 dtucker Exp $

View File

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

View File

@ -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 <openssl/evp.h>
#include <openssl/pem.h>
@ -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) {