version 1.375, 2019/12/30 03:28:41 |
version 1.376, 2019/12/30 03:30:09 |
|
|
/* Cipher for new-format private keys */ |
/* Cipher for new-format private keys */ |
static char *openssh_format_cipher = NULL; |
static char *openssh_format_cipher = NULL; |
|
|
/* |
/* Number of KDF rounds to derive new format keys. */ |
* Number of KDF rounds to derive new format keys / |
|
* number of primality trials when screening moduli. |
|
*/ |
|
static int rounds = 0; |
static int rounds = 0; |
|
|
/* argv0 */ |
/* argv0 */ |
|
|
} |
} |
|
|
static void |
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) |
usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
|
|
" ssh-keygen -R hostname [-f known_hosts_file]\n" |
" ssh-keygen -R hostname [-f known_hosts_file]\n" |
" ssh-keygen -r hostname [-g] [-f input_keyfile]\n" |
" ssh-keygen -r hostname [-g] [-f input_keyfile]\n" |
#ifdef WITH_OPENSSL |
#ifdef WITH_OPENSSL |
" ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n" |
" ssh-keygen -M generate [-O option] output\n" |
" ssh-keygen -f input_file -T output_file [-v] [-a rounds] [-J num_lines]\n" |
" ssh-keygen -M screen [-f input_file] [-O option] [-a rounds] output_file\n" |
" [-j start_line] [-K checkpt] [-W generator]\n" |
|
#endif |
#endif |
" ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n" |
" ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n" |
" [-n principals] [-O option] [-V validity_interval]\n" |
" [-n principals] [-O option] [-V validity_interval]\n" |
|
|
int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; |
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 prefer_agent = 0, convert_to = 0, convert_from = 0; |
int print_public = 0, print_generic = 0, cert_serial_autoinc = 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; |
unsigned long long ull, cert_serial = 0; |
char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; |
char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; |
size_t i, nopts = 0; |
size_t i, nopts = 0; |
|
|
const char *errstr; |
const char *errstr; |
int log_level = SYSLOG_LEVEL_INFO; |
int log_level = SYSLOG_LEVEL_INFO; |
char *sign_op = NULL; |
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 int optind; |
extern char *optarg; |
extern char *optarg; |
|
|
|
|
sk_provider = getenv("SSH_SK_PROVIDER"); |
sk_provider = getenv("SSH_SK_PROVIDER"); |
|
|
/* Remaining character: d */ |
/* Remaining characters: dGjJKSTW */ |
while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvy" |
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:" |
"C:D:E:F:I:M:N:O:P:R:V:Y:Z:" |
"a:b:f:g:j:m:n:r:s:t:w:x:z:")) != -1) { |
"a:b:f:g:m:n:r:s:t:w:x:z:")) != -1) { |
switch (opt) { |
switch (opt) { |
case 'A': |
case 'A': |
gen_all_hostkeys = 1; |
gen_all_hostkeys = 1; |
|
|
(errno == ERANGE && cert_serial == ULLONG_MAX)) |
(errno == ERANGE && cert_serial == ULLONG_MAX)) |
fatal("Invalid serial number \"%s\"", optarg); |
fatal("Invalid serial number \"%s\"", optarg); |
break; |
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': |
case 'M': |
memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, |
if (strcmp(optarg, "generate") == 0) |
&errstr); |
do_gen_candidates = 1; |
if (errstr) |
else if (strcmp(optarg, "screen") == 0) |
fatal("Memory limit is %s: %s", errstr, optarg); |
do_screen_candidates = 1; |
|
else |
|
fatal("Unsupported moduli option %s", optarg); |
break; |
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 '?': |
case '?': |
default: |
default: |
usage(); |
usage(); |
|
|
error("Too few arguments."); |
error("Too few arguments."); |
usage(); |
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."); |
error("Too many arguments."); |
usage(); |
usage(); |
} |
} |
|
|
error("Cannot use -l with -H or -R."); |
error("Cannot use -l with -H or -R."); |
usage(); |
usage(); |
} |
} |
#ifdef WITH_OPENSSL |
|
if (gen_krl) { |
if (gen_krl) { |
|
#ifdef WITH_OPENSSL |
do_gen_krl(pw, update_krl, ca_key_path, |
do_gen_krl(pw, update_krl, ca_key_path, |
cert_serial, identity_comment, argc, argv); |
cert_serial, identity_comment, argc, argv); |
return (0); |
return (0); |
|
#else |
|
fatal("KRL generation not supported"); |
|
#endif |
} |
} |
if (check_krl) { |
if (check_krl) { |
|
#ifdef WITH_OPENSSL |
do_check_krl(pw, argc, argv); |
do_check_krl(pw, argc, argv); |
return (0); |
return (0); |
} |
#else |
|
fatal("KRL checking not supported"); |
#endif |
#endif |
|
} |
if (ca_key_path != NULL) { |
if (ca_key_path != NULL) { |
if (cert_key_id == NULL) |
if (cert_key_id == NULL) |
fatal("Must specify key id (-I) when certifying"); |
fatal("Must specify key id (-I) when certifying"); |
|
|
} |
} |
} |
} |
|
|
#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) { |
if (do_gen_candidates) { |
FILE *out = fopen(out_file, "w"); |
do_moduli_gen(argv[0], opts, nopts); |
|
return 0; |
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); |
|
} |
} |
|
|
if (do_screen_candidates) { |
if (do_screen_candidates) { |
FILE *in; |
do_moduli_screen(argv[0], opts, nopts); |
FILE *out = fopen(out_file, "a"); |
return 0; |
|
|
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); |
|
} |
} |
#endif |
|
|
|
if (gen_all_hostkeys) { |
if (gen_all_hostkeys) { |
do_gen_all_hostkeys(pw); |
do_gen_all_hostkeys(pw); |