version 1.316, 2018/06/01 04:21:29 |
version 1.324, 2019/01/22 20:48:01 |
|
|
char *pkcs11provider = NULL; |
char *pkcs11provider = NULL; |
|
|
/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ |
/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ |
int use_new_format = 0; |
int use_new_format = 1; |
|
|
/* Cipher for new-format private keys */ |
/* Cipher for new-format private keys */ |
char *new_format_cipher = NULL; |
char *new_format_cipher = NULL; |
|
|
u_int magic, i1, i2, i3, i4; |
u_int magic, i1, i2, i3, i4; |
size_t slen; |
size_t slen; |
u_long e; |
u_long e; |
|
BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; |
|
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; |
|
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; |
|
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; |
if ((b = sshbuf_from(blob, blen)) == NULL) |
if ((b = sshbuf_from(blob, blen)) == NULL) |
fatal("%s: sshbuf_from failed", __func__); |
fatal("%s: sshbuf_from failed", __func__); |
if ((r = sshbuf_get_u32(b, &magic)) != 0) |
if ((r = sshbuf_get_u32(b, &magic)) != 0) |
|
|
free(type); |
free(type); |
return NULL; |
return NULL; |
} |
} |
if ((key = sshkey_new_private(ktype)) == NULL) |
if ((key = sshkey_new(ktype)) == NULL) |
fatal("sshkey_new_private failed"); |
fatal("sshkey_new failed"); |
free(type); |
free(type); |
|
|
switch (key->type) { |
switch (key->type) { |
case KEY_DSA: |
case KEY_DSA: |
buffer_get_bignum_bits(b, key->dsa->p); |
if ((dsa_p = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->dsa->g); |
(dsa_q = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->dsa->q); |
(dsa_g = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->dsa->pub_key); |
(dsa_pub_key = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->dsa->priv_key); |
(dsa_priv_key = BN_new()) == NULL) |
|
fatal("%s: BN_new", __func__); |
|
buffer_get_bignum_bits(b, dsa_p); |
|
buffer_get_bignum_bits(b, dsa_g); |
|
buffer_get_bignum_bits(b, dsa_q); |
|
buffer_get_bignum_bits(b, dsa_pub_key); |
|
buffer_get_bignum_bits(b, dsa_priv_key); |
|
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) |
|
fatal("%s: DSA_set0_pqg failed", __func__); |
|
dsa_p = dsa_q = dsa_g = NULL; /* transferred */ |
|
if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) |
|
fatal("%s: DSA_set0_key failed", __func__); |
|
dsa_pub_key = dsa_priv_key = NULL; /* transferred */ |
break; |
break; |
case KEY_RSA: |
case KEY_RSA: |
if ((r = sshbuf_get_u8(b, &e1)) != 0 || |
if ((r = sshbuf_get_u8(b, &e1)) != 0 || |
|
|
e += e3; |
e += e3; |
debug("e %lx", e); |
debug("e %lx", e); |
} |
} |
if (!BN_set_word(key->rsa->e, e)) { |
if ((rsa_e = BN_new()) == NULL) |
|
fatal("%s: BN_new", __func__); |
|
if (!BN_set_word(rsa_e, e)) { |
|
BN_clear_free(rsa_e); |
sshbuf_free(b); |
sshbuf_free(b); |
sshkey_free(key); |
sshkey_free(key); |
return NULL; |
return NULL; |
} |
} |
buffer_get_bignum_bits(b, key->rsa->d); |
if ((rsa_n = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->rsa->n); |
(rsa_d = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->rsa->iqmp); |
(rsa_p = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->rsa->q); |
(rsa_q = BN_new()) == NULL || |
buffer_get_bignum_bits(b, key->rsa->p); |
(rsa_iqmp = BN_new()) == NULL) |
if ((r = ssh_rsa_generate_additional_parameters(key)) != 0) |
fatal("%s: BN_new", __func__); |
|
buffer_get_bignum_bits(b, rsa_d); |
|
buffer_get_bignum_bits(b, rsa_n); |
|
buffer_get_bignum_bits(b, rsa_iqmp); |
|
buffer_get_bignum_bits(b, rsa_q); |
|
buffer_get_bignum_bits(b, rsa_p); |
|
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d)) |
|
fatal("%s: RSA_set0_key failed", __func__); |
|
rsa_n = rsa_e = rsa_d = NULL; /* transferred */ |
|
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q)) |
|
fatal("%s: RSA_set0_factors failed", __func__); |
|
rsa_p = rsa_q = NULL; /* transferred */ |
|
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0) |
fatal("generate RSA parameters failed: %s", ssh_err(r)); |
fatal("generate RSA parameters failed: %s", ssh_err(r)); |
|
BN_clear_free(rsa_iqmp); |
break; |
break; |
} |
} |
rlen = sshbuf_len(b); |
rlen = sshbuf_len(b); |
|
|
identity_file); |
identity_file); |
} |
} |
fclose(fp); |
fclose(fp); |
switch (EVP_PKEY_type(pubkey->type)) { |
switch (EVP_PKEY_base_id(pubkey)) { |
case EVP_PKEY_RSA: |
case EVP_PKEY_RSA: |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) |
fatal("sshkey_new failed"); |
fatal("sshkey_new failed"); |
|
|
break; |
break; |
default: |
default: |
fatal("%s: unsupported pubkey type %d", __func__, |
fatal("%s: unsupported pubkey type %d", __func__, |
EVP_PKEY_type(pubkey->type)); |
EVP_PKEY_base_id(pubkey)); |
} |
} |
EVP_PKEY_free(pubkey); |
EVP_PKEY_free(pubkey); |
return; |
return; |
|
|
{ |
{ |
FILE *f; |
FILE *f; |
struct sshkey *public = NULL; |
struct sshkey *public = NULL; |
char *comment = NULL, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES]; |
char *comment = NULL, *cp, *ep, *line = NULL; |
|
size_t linesize = 0; |
int i, invalid = 1; |
int i, invalid = 1; |
const char *path; |
const char *path; |
u_long lnum = 0; |
u_long lnum = 0; |
|
|
} else if ((f = fopen(path, "r")) == NULL) |
} else if ((f = fopen(path, "r")) == NULL) |
fatal("%s: %s: %s", __progname, path, strerror(errno)); |
fatal("%s: %s: %s", __progname, path, strerror(errno)); |
|
|
while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) { |
while (getline(&line, &linesize, f) != -1) { |
|
lnum++; |
cp = line; |
cp = line; |
cp[strcspn(cp, "\n")] = '\0'; |
cp[strcspn(cp, "\n")] = '\0'; |
/* Trim leading space and comments */ |
/* Trim leading space and comments */ |
|
|
*/ |
*/ |
if (lnum == 1 && strcmp(identity_file, "-") != 0 && |
if (lnum == 1 && strcmp(identity_file, "-") != 0 && |
strstr(cp, "PRIVATE KEY") != NULL) { |
strstr(cp, "PRIVATE KEY") != NULL) { |
|
free(line); |
fclose(f); |
fclose(f); |
fingerprint_private(path); |
fingerprint_private(path); |
exit(0); |
exit(0); |
|
|
invalid = 0; /* One good key in the file is sufficient */ |
invalid = 0; /* One good key in the file is sufficient */ |
} |
} |
fclose(f); |
fclose(f); |
|
free(line); |
|
|
if (invalid) |
if (invalid) |
fatal("%s is not a public key file.", path); |
fatal("%s is not a public key file.", path); |
|
|
printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), |
printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), |
sshkey_cert_type(key)); |
sshkey_cert_type(key)); |
printf(" Public key: %s %s\n", sshkey_type(key), key_fp); |
printf(" Public key: %s %s\n", sshkey_type(key), key_fp); |
printf(" Signing CA: %s %s\n", |
printf(" Signing CA: %s %s (using %s)\n", |
sshkey_type(key->cert->signature_key), ca_fp); |
sshkey_type(key->cert->signature_key), ca_fp, |
|
key->cert->signature_type); |
printf(" Key ID: \"%s\"\n", key->cert->key_id); |
printf(" Key ID: \"%s\"\n", key->cert->key_id); |
printf(" Serial: %llu\n", (unsigned long long)key->cert->serial); |
printf(" Serial: %llu\n", (unsigned long long)key->cert->serial); |
printf(" Valid: %s\n", valid); |
printf(" Valid: %s\n", valid); |
|
|
struct stat st; |
struct stat st; |
int r, is_stdin = 0, ok = 0; |
int r, is_stdin = 0, ok = 0; |
FILE *f; |
FILE *f; |
char *cp, line[SSH_MAX_PUBKEY_BYTES]; |
char *cp, *line = NULL; |
const char *path; |
const char *path; |
|
size_t linesize = 0; |
u_long lnum = 0; |
u_long lnum = 0; |
|
|
if (!have_identity) |
if (!have_identity) |
|
|
} else if ((f = fopen(identity_file, "r")) == NULL) |
} else if ((f = fopen(identity_file, "r")) == NULL) |
fatal("fopen %s: %s", identity_file, strerror(errno)); |
fatal("fopen %s: %s", identity_file, strerror(errno)); |
|
|
while (read_keyfile_line(f, path, line, sizeof(line), &lnum) == 0) { |
while (getline(&line, &linesize, f) != -1) { |
|
lnum++; |
sshkey_free(key); |
sshkey_free(key); |
key = NULL; |
key = NULL; |
/* Trim leading space and comments */ |
/* Trim leading space and comments */ |
|
|
printf("%s:%lu:\n", path, lnum); |
printf("%s:%lu:\n", path, lnum); |
print_cert(key); |
print_cert(key); |
} |
} |
|
free(line); |
sshkey_free(key); |
sshkey_free(key); |
fclose(f); |
fclose(f); |
exit(ok ? 0 : 1); |
exit(ok ? 0 : 1); |
|
|
} |
} |
|
|
static void |
static void |
|
hash_to_blob(const char *cp, u_char **blobp, size_t *lenp, |
|
const char *file, u_long lnum) |
|
{ |
|
char *tmp; |
|
size_t tlen; |
|
struct sshbuf *b; |
|
int r; |
|
|
|
if (strncmp(cp, "SHA256:", 7) != 0) |
|
fatal("%s:%lu: unsupported hash algorithm", file, lnum); |
|
cp += 7; |
|
|
|
/* |
|
* OpenSSH base64 hashes omit trailing '=' |
|
* characters; put them back for decode. |
|
*/ |
|
tlen = strlen(cp); |
|
tmp = xmalloc(tlen + 4 + 1); |
|
strlcpy(tmp, cp, tlen + 1); |
|
while ((tlen % 4) != 0) { |
|
tmp[tlen++] = '='; |
|
tmp[tlen] = '\0'; |
|
} |
|
if ((b = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new failed", __func__); |
|
if ((r = sshbuf_b64tod(b, tmp)) != 0) |
|
fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r)); |
|
free(tmp); |
|
*lenp = sshbuf_len(b); |
|
*blobp = xmalloc(*lenp); |
|
memcpy(*blobp, sshbuf_ptr(b), *lenp); |
|
sshbuf_free(b); |
|
} |
|
|
|
static void |
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, |
update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, |
const struct sshkey *ca, struct ssh_krl *krl) |
const struct sshkey *ca, struct ssh_krl *krl) |
{ |
{ |
struct sshkey *key = NULL; |
struct sshkey *key = NULL; |
u_long lnum = 0; |
u_long lnum = 0; |
char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES]; |
char *path, *cp, *ep, *line = NULL; |
|
u_char *blob = NULL; |
|
size_t blen = 0, linesize = 0; |
unsigned long long serial, serial2; |
unsigned long long serial, serial2; |
int i, was_explicit_key, was_sha1, r; |
int i, was_explicit_key, was_sha1, was_sha256, was_hash, r; |
FILE *krl_spec; |
FILE *krl_spec; |
|
|
path = tilde_expand_filename(file, pw->pw_uid); |
path = tilde_expand_filename(file, pw->pw_uid); |
|
|
|
|
if (!quiet) |
if (!quiet) |
printf("Revoking from %s\n", path); |
printf("Revoking from %s\n", path); |
while (read_keyfile_line(krl_spec, path, line, sizeof(line), |
while (getline(&line, &linesize, krl_spec) != -1) { |
&lnum) == 0) { |
lnum++; |
was_explicit_key = was_sha1 = 0; |
was_explicit_key = was_sha1 = was_sha256 = was_hash = 0; |
cp = line + strspn(line, " \t"); |
cp = line + strspn(line, " \t"); |
/* Trim trailing space, comments and strip \n */ |
/* Trim trailing space, comments and strip \n */ |
for (i = 0, r = -1; cp[i] != '\0'; i++) { |
for (i = 0, r = -1; cp[i] != '\0'; i++) { |
|
|
cp = cp + strspn(cp, " \t"); |
cp = cp + strspn(cp, " \t"); |
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) |
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0) |
fatal("%s: revoke key ID failed", __func__); |
fatal("%s: revoke key ID failed", __func__); |
|
} else if (strncasecmp(cp, "hash:", 5) == 0) { |
|
cp += 5; |
|
cp = cp + strspn(cp, " \t"); |
|
hash_to_blob(cp, &blob, &blen, file, lnum); |
|
r = ssh_krl_revoke_key_sha256(krl, blob, blen); |
} else { |
} else { |
if (strncasecmp(cp, "key:", 4) == 0) { |
if (strncasecmp(cp, "key:", 4) == 0) { |
cp += 4; |
cp += 4; |
|
|
cp += 5; |
cp += 5; |
cp = cp + strspn(cp, " \t"); |
cp = cp + strspn(cp, " \t"); |
was_sha1 = 1; |
was_sha1 = 1; |
} else { |
} else if (strncasecmp(cp, "sha256:", 7) == 0) { |
|
cp += 7; |
|
cp = cp + strspn(cp, " \t"); |
|
was_sha256 = 1; |
/* |
/* |
* Just try to process the line as a key. |
* Just try to process the line as a key. |
* Parsing will fail if it isn't. |
* Parsing will fail if it isn't. |
|
|
path, lnum, ssh_err(r)); |
path, lnum, ssh_err(r)); |
if (was_explicit_key) |
if (was_explicit_key) |
r = ssh_krl_revoke_key_explicit(krl, key); |
r = ssh_krl_revoke_key_explicit(krl, key); |
else if (was_sha1) |
else if (was_sha1) { |
r = ssh_krl_revoke_key_sha1(krl, key); |
if (sshkey_fingerprint_raw(key, |
else |
SSH_DIGEST_SHA1, &blob, &blen) != 0) { |
|
fatal("%s:%lu: fingerprint failed", |
|
file, lnum); |
|
} |
|
r = ssh_krl_revoke_key_sha1(krl, blob, blen); |
|
} else if (was_sha256) { |
|
if (sshkey_fingerprint_raw(key, |
|
SSH_DIGEST_SHA256, &blob, &blen) != 0) { |
|
fatal("%s:%lu: fingerprint failed", |
|
file, lnum); |
|
} |
|
r = ssh_krl_revoke_key_sha256(krl, blob, blen); |
|
} else |
r = ssh_krl_revoke_key(krl, key); |
r = ssh_krl_revoke_key(krl, key); |
if (r != 0) |
if (r != 0) |
fatal("%s: revoke key failed: %s", |
fatal("%s: revoke key failed: %s", |
__func__, ssh_err(r)); |
__func__, ssh_err(r)); |
|
freezero(blob, blen); |
|
blob = NULL; |
|
blen = 0; |
sshkey_free(key); |
sshkey_free(key); |
} |
} |
} |
} |
if (strcmp(path, "-") != 0) |
if (strcmp(path, "-") != 0) |
fclose(krl_spec); |
fclose(krl_spec); |
|
free(line); |
free(path); |
free(path); |
} |
} |
|
|
|
|
fatal("Couldn't generate KRL"); |
fatal("Couldn't generate KRL"); |
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) |
if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) |
fatal("open %s: %s", identity_file, strerror(errno)); |
fatal("open %s: %s", identity_file, strerror(errno)); |
if (atomicio(vwrite, fd, (void *)sshbuf_ptr(kbuf), sshbuf_len(kbuf)) != |
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(kbuf), sshbuf_len(kbuf)) != |
sshbuf_len(kbuf)) |
sshbuf_len(kbuf)) |
fatal("write %s: %s", identity_file, strerror(errno)); |
fatal("write %s: %s", identity_file, strerror(errno)); |
close(fd); |
close(fd); |
|
|
usage(void) |
usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
"usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa]\n" |
"usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa] [-m format]\n" |
" [-N new_passphrase] [-C comment] [-f output_keyfile]\n" |
" [-N new_passphrase] [-C comment] [-f output_keyfile]\n" |
" ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n" |
" ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-m format]\n" |
|
" [-f keyfile]\n" |
" ssh-keygen -i [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -i [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -e [-m key_format] [-f input_keyfile]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
" ssh-keygen -y [-f input_keyfile]\n" |
|
|
} |
} |
if (strcasecmp(optarg, "PEM") == 0) { |
if (strcasecmp(optarg, "PEM") == 0) { |
convert_format = FMT_PEM; |
convert_format = FMT_PEM; |
|
use_new_format = 0; |
break; |
break; |
} |
} |
fatal("Unsupported conversion format \"%s\"", optarg); |
fatal("Unsupported conversion format \"%s\"", optarg); |
|
|
cert_principals = optarg; |
cert_principals = optarg; |
break; |
break; |
case 'o': |
case 'o': |
use_new_format = 1; |
/* no-op; new format is already the default */ |
break; |
break; |
case 'p': |
case 'p': |
change_passphrase = 1; |
change_passphrase = 1; |