[openssh-commits] [openssh] 05/05: upstream: remove single-letter flags for moduli options

git+noreply at mindrot.org git+noreply at mindrot.org
Mon Dec 30 14:34:05 AEDT 2019


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 3e60d18fba1b502c21d64fc7e81d80bcd08a2092
Author: djm at openbsd.org <djm at openbsd.org>
Date:   Mon Dec 30 03:30:09 2019 +0000

    upstream: remove single-letter flags for moduli options
    
    Move all moduli generation options to live under the -O flag.
    
    Frees up seven single-letter flags.
    
    NB. this change break existing ssh-keygen commandline syntax for moduli-
    related operations. Very few people use these fortunately.
    
    feedback and ok markus@
    
    OpenBSD-Commit-ID: d498f3eaf28128484826a4fcb343612764927935
---
 ssh-keygen.1 | 142 +++++++++++++++++++---------------
 ssh-keygen.c | 249 +++++++++++++++++++++++++++++++++++------------------------
 2 files changed, 228 insertions(+), 163 deletions(-)

diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 67a57b9f..9afb9294 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
-.\"	$OpenBSD: ssh-keygen.1,v 1.183 2019/12/30 03:28:41 djm Exp $
+.\"	$OpenBSD: ssh-keygen.1,v 1.184 2019/12/30 03:30:09 djm Exp $
 .\"
 .\" Author: Tatu Ylonen <ylo at cs.hut.fi>
 .\" Copyright (c) 1995 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -99,20 +99,14 @@
 .Op Fl g
 .Op Fl f Ar input_keyfile
 .Nm ssh-keygen
-.Fl G Ar output_file
-.Op Fl v
-.Op Fl b Ar bits
-.Op Fl M Ar memory
-.Op Fl S Ar start_point
+.Fl M Cm generate
+.Op Fl O Ar option
+.Ar
 .Nm ssh-keygen
+.Fl M Cm screen
 .Fl f Ar input_file
-.Fl T Ar output_file
-.Op Fl v
-.Op Fl a Ar rounds
-.Op Fl J Ar num_lines
-.Op Fl j Ar start_line
-.Op Fl K Ar checkpt
-.Op Fl W Ar generator
+.Op Fl O Ar option
+.Ar
 .Nm ssh-keygen
 .Fl I Ar certificate_identity
 .Fl s Ar ca_key
@@ -268,11 +262,6 @@ When saving a private key, this option specifies the number of KDF
 (key derivation function) rounds used.
 Higher numbers result in slower passphrase verification and increased
 resistance to brute-force password cracking (should the keys be stolen).
-.Pp
-When screening DH-GEX candidates (using the
-.Fl T
-command),
-this option specifies the number of primality tests to perform.
 .It Fl B
 Show the bubblebabble digest of specified private or public key file.
 .It Fl b Ar bits
@@ -333,12 +322,6 @@ used in conjunction with the
 option to print found keys in a hashed format.
 .It Fl f Ar filename
 Specifies the filename of the key file.
-.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 g
 Use generic DNS format when printing fingerprint resource records using the
 .Fl r
@@ -379,24 +362,6 @@ This option allows importing keys from other software, including several
 commercial SSH implementations.
 The default import format is
 .Dq RFC4716 .
-.It Fl J Ar num_lines
-Exit after screening the specified number of lines
-while performing DH candidate screening using the
-.Fl T
-option.
-.It Fl j Ar start_line
-Start screening at the specified line number
-while performing DH candidate screening using the
-.Fl T
-option.
-.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.
 .It Fl k
 Generate a KRL file.
 In this mode,
@@ -419,9 +384,26 @@ If combined with
 .Fl v ,
 a visual ASCII art representation of the key is supplied with the
 fingerprint.
-.It Fl M Ar memory
-Specify the amount of memory to use (in megabytes) when generating
-candidate moduli for DH-GEX.
+.It Fl M Cm generate
+Generate candidate Diffie-Hellman Group Exchange (DH-GEX) parameters for
+eventual use by the
+.Sq diffie-hellman-group-exchange-*
+key exchange methods.
+The numbers generated by this operation must be further screened before
+use.
+See the
+.Sx MODULI GENERATION
+section for more information.
+.It Fl M Cm screen
+Screen candidate parameters for Diffie-Hellman Group Exchange.
+This will accept a list of candidate numbers and test that they are
+safe (Sophie Germain) primes with acceptable group generators.
+The results of this operation may be added to the
+.Pa /etc/moduli
+file.
+See the
+.Sx MODULI GENERATION
+section for more information.
 .It Fl m Ar key_format
 Specify a key format for key generation, the
 .Fl i
@@ -457,10 +439,20 @@ Please see the
 .Sx CERTIFICATES
 section for details.
 .It Fl O Ar option
-Specify a certificate option when signing a key.
-See the
+Specify a key/value option.
+These are specific to the operation that
+.Nm
+has been requested to perform.
+.Pp
+When signing certificates, one of the options listed in the
 .Sx CERTIFICATES
-section for a list of available certificate options.
+section may be specified here.
+.Pp
+When performing moduli generation or screening, one of the options
+listed in the
+.Sx MODULI GENERATION
+section may be specified.
+.Pp
 This option may be specified multiple times.
 .It Fl P Ar passphrase
 Provides the (old) passphrase.
@@ -489,8 +481,6 @@ option above).
 Print the SSHFP fingerprint resource record named
 .Ar hostname
 for the specified public key file.
-.It Fl S Ar start
-Specify start point (in hex) when generating candidate moduli for DH-GEX.
 .It Fl s Ar ca_key
 Certify (sign) a public key using the specified CA key.
 Please see the
@@ -504,10 +494,6 @@ by key ID or serial number.
 See the
 .Sx KEY REVOCATION LISTS
 section for details.
-.It Fl T Ar output_file
-Test DH group exchange candidate primes (generated using the
-.Fl G
-option) for safety.
 .It Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
 Specifies the type of key to create.
 The possible values are
@@ -583,8 +569,6 @@ Multiple
 .Fl v
 options increase the verbosity.
 The maximum is 3.
-.It Fl W Ar generator
-Specify desired generator when testing candidate moduli for DH-GEX.
 .It Fl w Ar provider
 Specifies a path to a library that will be used when creating
 FIDO authenticator-hosted keys, overriding the default of using
@@ -701,25 +685,25 @@ These candidate primes are then tested for suitability (a CPU-intensive
 process).
 .Pp
 Generation of primes is performed using the
-.Fl G
+.Fl M Cm generate
 option.
 The desired length of the primes may be specified by the
-.Fl b
+.Fl O Cm bits
 option.
 For example:
 .Pp
-.Dl # ssh-keygen -G moduli-2048.candidates -b 2048
+.Dl # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates
 .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
+.Fl O Cm start
 option, which specifies a different start point (in hex).
 .Pp
 Once a set of candidates have been generated, they must be screened for
 suitability.
 This may be performed using the
-.Fl T
+.Fl M Cm screen
 option.
 In this mode
 .Nm
@@ -728,16 +712,16 @@ will read candidates from standard input (or a file specified using the
 option).
 For example:
 .Pp
-.Dl # ssh-keygen -T moduli-2048 -f moduli-2048.candidates
+.Dl # ssh-keygen -M screen -f moduli-2048.candidates moduli-2048
 .Pp
 By default, each candidate will be subjected to 100 primality tests.
 This may be overridden using the
-.Fl a
+.Fl O Cm prime-tests
 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
+.Fl O Cm generator
 option.
 Valid generator values are 2, 3, and 5.
 .Pp
@@ -745,6 +729,36 @@ 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.
+.Pp
+A number of options are available for moduli generation and screening via the
+.Fl O
+flag:
+.Bl -tag -width Ds -compact
+.Pp
+.It Ic lines Ns = Ns Ar number
+Exit after screening the specified number of lines while performing DH
+candidate screening.
+.Pp
+.It Ic start-line Ns = Ns Ar line-number
+Start screening at the specified line number while performing DH candidate
+screening.
+.Pp
+.It Ic checkpoint Ns = Ns Ar filename
+Write the last line processed to the specified file while performing DH
+candidate screening.
+This will be used to skip lines in the input file that have already been
+processed if the job is restarted.
+.Pp
+.It Ic memory Ns = Ns Ar mbytes
+Specify the amount of memory to use (in megabytes) when generating
+candidate moduli for DH-GEX.
+.Pp
+.It Ic start Ns = Ns Ar hex-value
+Specify start point (in hex) when generating candidate moduli for DH-GEX.
+.Pp
+.It Ic generator Ns = Ns Ar value
+Specify desired generator (in decimal) when testing candidate moduli for DH-GEX.
+.El
 .Sh CERTIFICATES
 .Nm
 supports signing of keys to produce certificates that may be used for
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 43f2e1e8..447810fb 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.375 2019/12/30 03:28:41 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.376 2019/12/30 03:30:09 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo at cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo at cs.hut.fi>, Espoo, Finland
@@ -162,10 +162,7 @@ static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
 /* Cipher for new-format private keys */
 static char *openssh_format_cipher = NULL;
 
-/*
- * Number of KDF rounds to derive new format keys /
- * number of primality trials when screening moduli.
- */
+/* Number of KDF rounds to derive new format keys. */
 static int rounds = 0;
 
 /* argv0 */
@@ -2758,6 +2755,122 @@ done:
 	return ret;
 }
 
+static void
+do_moduli_gen(const char *out_file, char **opts, size_t nopts)
+{
+#ifdef WITH_OPENSSL
+	/* Moduli generation/screening */
+	u_int32_t memory = 0;
+	BIGNUM *start = NULL;
+	int moduli_bits = 0;
+	FILE *out;
+	size_t i;
+	const char *errstr;
+
+	/* Parse options */
+	for (i = 0; i < nopts; i++) {
+		if (strncmp(opts[i], "memory=", 7) == 0) {
+			memory = (u_int32_t)strtonum(opts[i]+7, 1,
+			    UINT_MAX, &errstr);
+			if (errstr) {
+				fatal("Memory limit is %s: %s",
+				    errstr, opts[i]+7);
+			}
+		} else if (strncmp(opts[i], "start=", 6) == 0) {
+			/* XXX - also compare length against bits */
+			if (BN_hex2bn(&start, opts[i]+6) == 0)
+				fatal("Invalid start point.");
+		} else if (strncmp(opts[i], "bits=", 5) == 0) {
+			moduli_bits = (int)strtonum(opts[i]+5, 1,
+			    INT_MAX, &errstr);
+			if (errstr) {
+				fatal("Invalid number: %s (%s)",
+					opts[i]+12, errstr);
+			}
+		} else {
+			fatal("Option \"%s\" is unsupported for moduli "
+			    "generation", opts[i]);
+		}
+	}
+
+	if ((out = fopen(out_file, "w")) == NULL) {
+		fatal("Couldn't open modulus candidate file \"%s\": %s",
+		    out_file, strerror(errno));
+	}
+	setvbuf(out, NULL, _IOLBF, 0);
+
+	if (moduli_bits == 0)
+		moduli_bits = DEFAULT_BITS;
+	if (gen_candidates(out, memory, moduli_bits, start) != 0)
+		fatal("modulus candidate generation failed");
+#else /* WITH_OPENSSL */
+	fatal("Moduli generation is not supported");
+#endif /* WITH_OPENSSL */
+}
+
+static void
+do_moduli_screen(const char *out_file, char **opts, size_t nopts)
+{
+#ifdef WITH_OPENSSL
+	/* Moduli generation/screening */
+	char *checkpoint = NULL;
+	u_int32_t generator_wanted = 0;
+	unsigned long start_lineno = 0, lines_to_process = 0;
+	int prime_tests = 0;
+	FILE *out, *in = stdin;
+	size_t i;
+	const char *errstr;
+
+	/* Parse options */
+	for (i = 0; i < nopts; i++) {
+		if (strncmp(opts[i], "lines=", 6) == 0) {
+			lines_to_process = strtoul(opts[i]+6, NULL, 10);
+		} else if (strncmp(opts[i], "start-line=", 11) == 0) {
+			start_lineno = strtoul(opts[i]+11, NULL, 10);
+		} else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
+			checkpoint = xstrdup(opts[i]+11);
+		} else if (strncmp(opts[i], "generator=", 10) == 0) {
+			generator_wanted = (u_int32_t)strtonum(
+			    opts[i]+10, 1, UINT_MAX, &errstr);
+			if (errstr != NULL) {
+				fatal("Generator invalid: %s (%s)",
+				    opts[i]+10, errstr);
+			}
+		} else if (strncmp(opts[i], "prime-tests=", 12) == 0) {
+			prime_tests = (int)strtonum(opts[i]+12, 1,
+			    INT_MAX, &errstr);
+			if (errstr) {
+				fatal("Invalid number: %s (%s)",
+					opts[i]+12, errstr);
+			}
+		} else {
+			fatal("Option \"%s\" is unsupported for moduli "
+			    "screening", opts[i]);
+		}
+	}
+
+	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));
+		}
+	}
+
+	if ((out = fopen(out_file, "a")) == NULL) {
+		fatal("Couldn't open moduli file \"%s\": %s",
+		    out_file, strerror(errno));
+	}
+	setvbuf(out, NULL, _IOLBF, 0);
+	if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests,
+	    generator_wanted, checkpoint,
+	    start_lineno, lines_to_process) != 0)
+		fatal("modulus screening failed");
+#else /* WITH_OPENSSL */
+	fatal("Moduli screening is not supported");
+#endif /* WITH_OPENSSL */
+}
+
 static void
 usage(void)
 {
@@ -2783,9 +2896,8 @@ usage(void)
 	    "       ssh-keygen -R hostname [-f known_hosts_file]\n"
 	    "       ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
 #ifdef WITH_OPENSSL
-	    "       ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n"
-	    "       ssh-keygen -f input_file -T output_file [-v] [-a rounds] [-J num_lines]\n"
-	    "                  [-j start_line] [-K checkpt] [-W generator]\n"
+	    "       ssh-keygen -M generate [-O option] output\n"
+	    "       ssh-keygen -M screen [-f input_file] [-O option] [-a rounds] output_file\n"
 #endif
 	    "       ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
 	    "                  [-n principals] [-O option] [-V validity_interval]\n"
@@ -2819,6 +2931,7 @@ main(int argc, char **argv)
 	int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
 	int prefer_agent = 0, convert_to = 0, convert_from = 0;
 	int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
+	int do_gen_candidates = 0, do_screen_candidates = 0;
 	unsigned long long ull, cert_serial = 0;
 	char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
 	size_t i, nopts = 0;
@@ -2828,14 +2941,6 @@ main(int argc, char **argv)
 	const char *errstr;
 	int log_level = SYSLOG_LEVEL_INFO;
 	char *sign_op = NULL;
-#ifdef WITH_OPENSSL
-	/* Moduli generation/screening */
-	char out_file[PATH_MAX], *checkpoint = NULL;
-	u_int32_t memory = 0, generator_wanted = 0;
-	int do_gen_candidates = 0, do_screen_candidates = 0;
-	unsigned long start_lineno = 0, lines_to_process = 0;
-	BIGNUM *start = NULL;
-#endif
 
 	extern int optind;
 	extern char *optarg;
@@ -2860,10 +2965,10 @@ main(int argc, char **argv)
 
 	sk_provider = getenv("SSH_SK_PROVIDER");
 
-	/* Remaining character: d */
+	/* Remaining characters: dGjJKSTW */
 	while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvy"
-	    "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Y:Z:"
-	    "a:b:f:g:j:m:n:r:s:t:w:x:z:")) != -1) {
+	    "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
+	    "a:b:f:g:m:n:r:s:t:w:x:z:")) != -1) {
 		switch (opt) {
 		case 'A':
 			gen_all_hostkeys = 1;
@@ -3053,50 +3158,14 @@ main(int argc, char **argv)
 			    (errno == ERANGE && cert_serial == ULLONG_MAX))
 				fatal("Invalid serial number \"%s\"", optarg);
 			break;
-#ifdef WITH_OPENSSL
-		/* Moduli generation/screening */
-		case 'G':
-			do_gen_candidates = 1;
-			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
-			    sizeof(out_file))
-				fatal("Output filename too long");
-			break;
-		case 'J':
-			lines_to_process = strtoul(optarg, NULL, 10);
-			break;
-		case 'j':
-			start_lineno = strtoul(optarg, NULL, 10);
-			break;
-		case 'K':
-			if (strlen(optarg) >= PATH_MAX)
-				fatal("Checkpoint filename too long");
-			checkpoint = xstrdup(optarg);
-			break;
 		case 'M':
-			memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX,
-			    &errstr);
-			if (errstr)
-				fatal("Memory limit is %s: %s", errstr, optarg);
+			if (strcmp(optarg, "generate") == 0)
+				do_gen_candidates = 1;
+			else if (strcmp(optarg, "screen") == 0)
+				do_screen_candidates = 1;
+			else
+				fatal("Unsupported moduli option %s", optarg);
 			break;
-		case 'S':
-			/* XXX - also compare length against bits */
-			if (BN_hex2bn(&start, optarg) == 0)
-				fatal("Invalid start point.");
-			break;
-		case 'T':
-			do_screen_candidates = 1;
-			if (strlcpy(out_file, optarg, sizeof(out_file)) >=
-			    sizeof(out_file))
-				fatal("Output filename too long");
-			break;
-		case 'W':
-			generator_wanted = (u_int32_t)strtonum(optarg, 1,
-			    UINT_MAX, &errstr);
-			if (errstr != NULL)
-				fatal("Desired generator invalid: %s (%s)",
-				    optarg, errstr);
-			break;
-#endif /* WITH_OPENSSL */
 		case '?':
 		default:
 			usage();
@@ -3163,7 +3232,8 @@ main(int argc, char **argv)
 			error("Too few arguments.");
 			usage();
 		}
-	} else if (argc > 0 && !gen_krl && !check_krl) {
+	} else if (argc > 0 && !gen_krl && !check_krl &&
+	    !do_gen_candidates && !do_screen_candidates) {
 		error("Too many arguments.");
 		usage();
 	}
@@ -3176,13 +3246,21 @@ main(int argc, char **argv)
 		usage();
 	}
 	if (gen_krl) {
+#ifdef WITH_OPENSSL
 		do_gen_krl(pw, update_krl, ca_key_path,
 		    cert_serial, identity_comment, argc, argv);
 		return (0);
+#else
+		fatal("KRL generation not supported");
+#endif
 	}
 	if (check_krl) {
+#ifdef WITH_OPENSSL
 		do_check_krl(pw, argc, argv);
 		return (0);
+#else
+		fatal("KRL checking not supported");
+#endif
 	}
 	if (ca_key_path != NULL) {
 		if (cert_key_id == NULL)
@@ -3249,47 +3327,20 @@ main(int argc, char **argv)
 		}
 	}
 
-#ifdef WITH_OPENSSL
+	if (do_gen_candidates || do_screen_candidates) {
+		if (argc <= 0)
+			fatal("No output file specified");
+		else if (argc > 1)
+			fatal("Too many output files specified");
+	}
 	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 (bits == 0)
-			bits = DEFAULT_BITS;
-		if (gen_candidates(out, memory, bits, start) != 0)
-			fatal("modulus candidate generation failed");
-
-		return (0);
+		do_moduli_gen(argv[0], opts, nopts);
+		return 0;
 	}
-
 	if (do_screen_candidates) {
-		FILE *in;
-		FILE *out = fopen(out_file, "a");
-
-		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, rounds == 0 ? 100 : rounds,
-		    generator_wanted, checkpoint,
-		    start_lineno, lines_to_process) != 0)
-			fatal("modulus screening failed");
-		return (0);
+		do_moduli_screen(argv[0], opts, nopts);
+		return 0;
 	}
-#endif
 
 	if (gen_all_hostkeys) {
 		do_gen_all_hostkeys(pw);

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list