=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.201 retrieving revision 1.217 diff -u -r1.201 -r1.217 --- src/usr.bin/ssh/ssh-keygen.c 2010/08/31 12:33:38 1.201 +++ src/usr.bin/ssh/ssh-keygen.c 2012/08/17 01:25:58 1.217 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.201 2010/08/31 12:33:38 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.217 2012/08/17 01:25:58 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -49,7 +49,7 @@ /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ #define DEFAULT_BITS 2048 #define DEFAULT_BITS_DSA 1024 -#define DEFAULT_BITS_ECDSA 521 +#define DEFAULT_BITS_ECDSA 256 u_int32_t bits = 0; /* @@ -149,9 +149,42 @@ /* moduli.c */ int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); -int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); +int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long, + unsigned long); static void +type_bits_valid(int type, u_int32_t *bitsp) +{ + u_int maxbits; + + if (type == KEY_UNSPEC) { + fprintf(stderr, "unknown key type %s\n", key_type_name); + exit(1); + } + if (*bitsp == 0) { + if (type == KEY_DSA) + *bitsp = DEFAULT_BITS_DSA; + else if (type == KEY_ECDSA) + *bitsp = DEFAULT_BITS_ECDSA; + else + *bitsp = DEFAULT_BITS; + } + maxbits = (type == KEY_DSA) ? + OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; + if (*bitsp > maxbits) { + fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); + exit(1); + } + if (type == KEY_DSA && *bitsp != 1024) + fatal("DSA keys must be 1024 bits"); + else if (type != KEY_ECDSA && *bitsp < 768) + fatal("Key must at least be 768 bits"); + else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1) + fatal("Invalid ECDSA key length - valid lengths are " + "256, 384 or 521 bits"); +} + +static void ask_filename(struct passwd *pw, const char *prompt) { char buf[1024]; @@ -226,6 +259,10 @@ u_char *blob; char comment[61]; + if (k->type == KEY_RSA1) { + fprintf(stderr, "version 1 keys are not supported\n"); + exit(1); + } if (key_to_blob(k, &blob, &len) <= 0) { fprintf(stderr, "key_to_blob failed\n"); exit(1); @@ -249,6 +286,7 @@ do_convert_to_pkcs8(Key *k) { switch (key_type_plain(k->type)) { + case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSA_PUBKEY(stdout, k->rsa)) fatal("PEM_write_RSA_PUBKEY failed"); @@ -271,6 +309,7 @@ do_convert_to_pem(Key *k) { switch (key_type_plain(k->type)) { + case KEY_RSA1: case KEY_RSA: if (!PEM_write_RSAPublicKey(stdout, k->rsa)) fatal("PEM_write_RSAPublicKey failed"); @@ -304,10 +343,6 @@ exit(1); } } - if (k->type == KEY_RSA1) { - fprintf(stderr, "version 1 keys are not supported\n"); - exit(1); - } switch (convert_format) { case FMT_RFC4716: @@ -545,8 +580,7 @@ *k = key_new(KEY_UNSPEC); (*k)->type = KEY_ECDSA; (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey); - (*k)->ecdsa_nid = key_ecdsa_group_to_nid( - EC_KEY_get0_group((*k)->ecdsa)); + (*k)->ecdsa_nid = key_ecdsa_key_to_nid((*k)->ecdsa); break; default: fatal("%s: unsupported pubkey type %d", __func__, @@ -803,6 +837,98 @@ } static void +do_gen_all_hostkeys(struct passwd *pw) +{ + struct { + char *key_type; + char *key_type_display; + char *path; + } key_types[] = { + { "rsa1", "RSA1", _PATH_HOST_KEY_FILE }, + { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE }, + { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE }, + { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE }, + { NULL, NULL, NULL } + }; + + int first = 0; + struct stat st; + Key *private, *public; + char comment[1024]; + int i, type, fd; + FILE *f; + + for (i = 0; key_types[i].key_type; i++) { + if (stat(key_types[i].path, &st) == 0) + continue; + if (errno != ENOENT) { + printf("Could not stat %s: %s", key_types[i].path, + strerror(errno)); + first = 0; + continue; + } + + if (first == 0) { + first = 1; + printf("%s: generating new host keys: ", __progname); + } + printf("%s ", key_types[i].key_type_display); + fflush(stdout); + arc4random_stir(); + type = key_type_from_name(key_types[i].key_type); + strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); + bits = 0; + type_bits_valid(type, &bits); + private = key_generate(type, bits); + if (private == NULL) { + fprintf(stderr, "key_generate failed\n"); + first = 0; + continue; + } + public = key_from_private(private); + snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, + hostname); + if (!key_save_private(private, identity_file, "", comment)) { + printf("Saving the key failed: %s.\n", identity_file); + key_free(private); + key_free(public); + first = 0; + continue; + } + key_free(private); + arc4random_stir(); + strlcat(identity_file, ".pub", sizeof(identity_file)); + fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + printf("Could not save your public key in %s\n", + identity_file); + key_free(public); + first = 0; + continue; + } + f = fdopen(fd, "w"); + if (f == NULL) { + printf("fdopen %s failed\n", identity_file); + key_free(public); + first = 0; + continue; + } + if (!key_write(public, f)) { + fprintf(stderr, "write key failed\n"); + key_free(public); + first = 0; + continue; + } + fprintf(f, " %s\n", comment); + fclose(f); + key_free(public); + + } + if (first != 0) + printf("\n"); +} + +static void printhost(FILE *f, const char *name, Key *public, int ca, int hash) { if (print_fingerprint) { @@ -947,8 +1073,14 @@ ca ? " (CA key)" : ""); printhost(out, cp, pub, ca, 0); } - if (delete_host && !c && !ca) - printhost(out, cp, pub, ca, 0); + if (delete_host) { + if (!c && !ca) + printhost(out, cp, pub, ca, 0); + else + printf("# Host %s found: " + "line %d type %s\n", name, + num, key_type(pub)); + } } else if (hash_hosts) printhost(out, cp, pub, ca, 0); } else { @@ -963,8 +1095,14 @@ printhost(out, name, pub, ca, hash_hosts && !ca); } - if (delete_host && !c && !ca) - printhost(out, cp, pub, ca, 0); + if (delete_host) { + if (!c && !ca) + printhost(out, cp, pub, ca, 0); + else + printf("# Host %s found: " + "line %d type %s\n", name, + num, key_type(pub)); + } } else if (hash_hosts) { for (cp2 = strsep(&cp, ","); cp2 != NULL && *cp2 != '\0'; @@ -1315,6 +1453,9 @@ certflags_command != NULL) add_string_option(c, "force-command", certflags_command); if ((which & OPTIONS_EXTENSIONS) != 0 && + (certflags_flags & CERTOPT_X_FWD) != 0) + add_flag_option(c, "permit-X11-forwarding"); + if ((which & OPTIONS_EXTENSIONS) != 0 && (certflags_flags & CERTOPT_AGENT_FWD) != 0) add_flag_option(c, "permit-agent-forwarding"); if ((which & OPTIONS_EXTENSIONS) != 0 && @@ -1326,9 +1467,6 @@ if ((which & OPTIONS_EXTENSIONS) != 0 && (certflags_flags & CERTOPT_USER_RC) != 0) add_flag_option(c, "permit-user-rc"); - if ((which & OPTIONS_EXTENSIONS) != 0 && - (certflags_flags & CERTOPT_X_FWD) != 0) - add_flag_option(c, "permit-X11-forwarding"); if ((which & OPTIONS_CRITICAL) != 0 && certflags_src_addr != NULL) add_string_option(c, "source-address", certflags_src_addr); @@ -1465,7 +1603,8 @@ if (!quiet) { logit("Signed %s key %s: id \"%s\" serial %llu%s%s " "valid %s", key_cert_type(public), - out, public->cert->key_id, public->cert->serial, + out, public->cert->key_id, + (unsigned long long)public->cert->serial, cert_principals != NULL ? " for " : "", cert_principals != NULL ? cert_principals : "", fmt_validity(cert_valid_from, cert_valid_to)); @@ -1577,7 +1716,7 @@ { char *val; - if (strcmp(opt, "clear") == 0) + if (strcasecmp(opt, "clear") == 0) certflags_flags = 0; else if (strcasecmp(opt, "no-x11-forwarding") == 0) certflags_flags &= ~CERTOPT_X_FWD; @@ -1690,8 +1829,10 @@ printf(" Signing CA: %s %s\n", key_type(key->cert->signature_key), ca_fp); printf(" Key ID: \"%s\"\n", key->cert->key_id); - if (!v00) - printf(" Serial: %llu\n", key->cert->serial); + if (!v00) { + printf(" Serial: %llu\n", + (unsigned long long)key->cert->serial); + } printf(" Valid: %s\n", fmt_validity(key->cert->valid_after, key->cert->valid_before)); printf(" Principals: "); @@ -1727,6 +1868,7 @@ { fprintf(stderr, "usage: %s [options]\n", __progname); fprintf(stderr, "Options:\n"); + fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); fprintf(stderr, " -b bits Number of bits in the key to create.\n"); @@ -1744,6 +1886,9 @@ fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); + fprintf(stderr, " -J number Screen this number of moduli lines.\n"); + fprintf(stderr, " -j number Start screening moduli at specified line.\n"); + fprintf(stderr, " -K checkpt Write checkpoints to this file.\n"); fprintf(stderr, " -L Print the contents of a certificate.\n"); fprintf(stderr, " -l Show fingerprint of key file.\n"); fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); @@ -1776,14 +1921,16 @@ main(int argc, char **argv) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; + char *checkpoint = NULL; char out_file[MAXPATHLEN], *rr_hostname = NULL; Key *private, *public; struct passwd *pw; struct stat st; int opt, type, fd; - u_int maxbits; u_int32_t memory = 0, generator_wanted = 0, trials = 100; int do_gen_candidates = 0, do_screen_candidates = 0; + int gen_all_hostkeys = 0; + unsigned long start_lineno = 0, lines_to_process = 0; BIGNUM *start = NULL; FILE *f; const char *errstr; @@ -1808,11 +1955,14 @@ exit(1); } - while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" - "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { + while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:J:j:K:P:" + "m:N:n:O:C:r:g:R:T:G:M:S:s:a:V:W:z")) != -1) { switch (opt) { + case 'A': + gen_all_hostkeys = 1; + break; case 'b': - bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); + bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr); if (errstr) fatal("Bits has bad value %s (%s)", optarg, errstr); @@ -1827,6 +1977,12 @@ case 'I': cert_key_id = optarg; break; + case 'J': + lines_to_process = strtoul(optarg, NULL, 10); + break; + case 'j': + start_lineno = strtoul(optarg, NULL, 10); + break; case 'R': delete_host = 1; rr_hostname = optarg; @@ -1905,9 +2061,6 @@ case 'y': print_public = 1; break; - case 'd': - key_type_name = "dsa"; - break; case 's': ca_key_path = optarg; break; @@ -1959,6 +2112,11 @@ sizeof(out_file)) fatal("Output filename too long"); break; + case 'K': + if (strlen(optarg) >= MAXPATHLEN) + fatal("Checkpoint filename too long"); + checkpoint = xstrdup(optarg); + break; case 'S': /* XXX - also compare length against bits */ if (BN_hex2bn(&start, optarg) == 0) @@ -2039,6 +2197,8 @@ _PATH_HOST_RSA_KEY_FILE, rr_hostname); n += do_print_resource_record(pw, _PATH_HOST_DSA_KEY_FILE, rr_hostname); + n += do_print_resource_record(pw, + _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); if (n == 0) fatal("no keys found."); @@ -2081,40 +2241,25 @@ fatal("Couldn't open moduli file \"%s\": %s", out_file, strerror(errno)); } - if (prime_test(in, out, trials, generator_wanted) != 0) + if (prime_test(in, out, trials, generator_wanted, checkpoint, + start_lineno, lines_to_process) != 0) fatal("modulus screening failed"); return (0); } + if (gen_all_hostkeys) { + do_gen_all_hostkeys(pw); + return (0); + } + arc4random_stir(); if (key_type_name == NULL) key_type_name = "rsa"; type = key_type_from_name(key_type_name); - if (type == KEY_UNSPEC) { - fprintf(stderr, "unknown key type %s\n", key_type_name); - exit(1); - } - if (bits == 0) { - if (type == KEY_DSA) - bits = DEFAULT_BITS_DSA; - else if (type == KEY_ECDSA) - bits = DEFAULT_BITS_ECDSA; - else - bits = DEFAULT_BITS; - } - maxbits = (type == KEY_DSA) ? - OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; - if (bits > maxbits) { - fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); - exit(1); - } - if (type == KEY_DSA && bits != 1024) - fatal("DSA keys must be 1024 bits"); - else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(bits) == -1) - fatal("Invalid ECDSA key length - valid lengths are " - "256, 384 or 521 bits"); + type_bits_valid(type, &bits); + if (!quiet) printf("Generating public/private %s key pair.\n", key_type_name); private = key_generate(type, bits);