Add private key protection information extraction to shh-keygen using -v option on top of -y option which is already parsing the private key. Technically, the passphrase isn't necessary to do this, but it is the most logical thing to do for me. Adding this to -l option is not appropriate because fingerprinting is using the .pub file when available. An other idea is to add a new option, I can do it if you prefer. Also, I'm laking information for information extraction from PEM and PKCS8 file format, I'm OK to have a pointer to implement this correctly. This patch is also adding a regression test for the functionnality. --- authfile.c | 16 ++-- authfile.h | 7 +- regress/Makefile | 3 +- regress/keygen-private-information.sh | 81 +++++++++++++++++++++ ssh-keygen.c | 44 +++++++---- ssh-keysign.c | 2 +- sshconnect2.c | 2 +- sshd.c | 2 +- sshkey.c | 101 +++++++++++++++++++++++--- sshkey.h | 14 +++- 10 files changed, 234 insertions(+), 38 deletions(-) create mode 100644 regress/keygen-private-information.sh diff --git a/authfile.c b/authfile.c index 35ccf576c2b5..6c79369ebfc1 100644 --- a/authfile.c +++ b/authfile.c @@ -116,7 +116,7 @@ sshkey_perm_ok(int fd, const char *filename) int sshkey_load_private_type(int type, const char *filename, const char *passphrase, - struct sshkey **keyp, char **commentp) + struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop) { int fd, r; @@ -124,6 +124,8 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, *keyp = NULL; if (commentp != NULL) *commentp = NULL; + if (vault_infop != NULL) + *vault_infop = NULL; if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; @@ -132,7 +134,7 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, if (r != 0) goto out; - r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); + r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp, vault_infop); if (r == 0 && keyp && *keyp) r = sshkey_set_filename(*keyp, filename); out: @@ -142,15 +144,15 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, int sshkey_load_private(const char *filename, const char *passphrase, - struct sshkey **keyp, char **commentp) + struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop) { return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase, - keyp, commentp); + keyp, commentp, vault_infop); } int sshkey_load_private_type_fd(int fd, int type, const char *passphrase, - struct sshkey **keyp, char **commentp) + struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop) { struct sshbuf *buffer = NULL; int r; @@ -159,7 +161,7 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase, *keyp = NULL; if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || (r = sshkey_parse_private_fileblob_type(buffer, type, - passphrase, keyp, commentp)) != 0) + passphrase, keyp, commentp, vault_infop)) != 0) goto out; /* success */ @@ -334,7 +336,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, } if ((r = sshkey_load_private_type(type, filename, - passphrase, &key, NULL)) != 0 || + passphrase, &key, NULL, NULL)) != 0 || (r = sshkey_load_cert(filename, &cert)) != 0) goto out; diff --git a/authfile.h b/authfile.h index 1db067a813a1..85f78ac78edf 100644 --- a/authfile.h +++ b/authfile.h @@ -29,6 +29,7 @@ struct sshbuf; struct sshkey; +struct sshkey_vault; /* XXX document these */ /* XXX some of these could probably be merged/retired */ @@ -37,13 +38,13 @@ int sshkey_save_private(struct sshkey *, const char *, const char *, const char *, int, const char *, int); int sshkey_load_cert(const char *, struct sshkey **); int sshkey_load_public(const char *, struct sshkey **, char **); -int sshkey_load_private(const char *, const char *, struct sshkey **, char **); +int sshkey_load_private(const char *, const char *, struct sshkey **, char **, struct sshkey_vault **); int sshkey_load_private_cert(int, const char *, const char *, struct sshkey **); int sshkey_load_private_type(int, const char *, const char *, - struct sshkey **, char **); + struct sshkey **, char **, struct sshkey_vault **); int sshkey_load_private_type_fd(int fd, int type, const char *passphrase, - struct sshkey **keyp, char **commentp); + struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop); int sshkey_perm_ok(int, const char *); int sshkey_in_file(struct sshkey *, const char *, int, int); int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file); diff --git a/regress/Makefile b/regress/Makefile index 62794d25fc42..ae6f4dd09edc 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -92,7 +92,8 @@ LTESTS= connect \ allow-deny-users \ authinfo \ sshsig \ - keygen-comment + keygen-comment \ + keygen-private-information INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers diff --git a/regress/keygen-private-information.sh b/regress/keygen-private-information.sh new file mode 100644 index 000000000000..a9959e919fd1 --- /dev/null +++ b/regress/keygen-private-information.sh @@ -0,0 +1,81 @@ +# Placed in the Public Domain. + +tid="Test information extraction from private key" + +check_private_key () { + file="$1" + format="$2" + comment="$3" + secret="$4" + rounds="$5" + + # construct expected output in $exp file + exp=$OBJ/$t-expected + # default format is RFC4716 + test -z "$format" && format="RFC4716" + # Currently PKCS8 is detected as PEM, should be fixed in ssh-keygen + test "$format" = "PKCS8" && format="PEM" + cat > $exp << EOF +$comment +Key protection details: +File format: $format +EOF + if [ -z "$secret" -o "$format" = "PEM" ]; then + # For PEM format, passphrase is not detected yet, should be fixed in ssh-keygen + echo "no passphrase" >> $exp + else + cat >> $exp << EOF +cipher: aes256-ctr +kdf: bcrypt +rounds: $rounds +EOF + fi + + if ! ${SSHKEYGEN} -yv -P "${secret}" -f $file > $OBJ/$t-pub ; then + fail "ssh-keygen -y failed for $t-key" + fi + if ! sed '1 s/[^ ]* [^ ]* \?//' $OBJ/$t-pub > $OBJ/$t-tmp ; then + fail "sed failed for $t-key" + fi + if ! cmp $OBJ/$t-tmp $exp > /dev/null 2>&1; then + fail "ssh-keygen -yv output is not the expected value for $t-key" + diff $exp $OBJ/$t-tmp + fi + rm -f $OBJ/$t-pub $OBJ/$t-tmp $exp +} + +for fmt in '' PKCS8 PEM ; do + for secret in '' 'secret1'; do + rounds_list="0" + test -n "$secret" -a -z "$fmt" && rounds_list="2 16" + for rounds in $rounds_list; do + for t in $SSH_KEYTYPES; do + trace "generating $t key in '$fmt' format with '$secret' passphrase and '$rounds' rounds" + rm -f $OBJ/$t-key* + oldfmt="" + case "$fmt" in + PKCS8|PEM) oldfmt=1 ;; + esac + # Some key types like ssh-ed25519 and *@openssh.com are never + # stored in old formats. + case "$t" in + ssh-ed25519|*openssh.com) test -z "$oldfmt" || continue ;; + esac + comment="foo bar" + fmtarg="" + test -z "$fmt" || fmtarg="-m $fmt" + test "$rounds" = "0" || roundarg="-a $rounds" + ${SSHKEYGEN} $fmtarg $roundarg -N "${secret}" -C "${comment}" \ + -t $t -f $OBJ/$t-key >/dev/null 2>&1 || \ + fatal "keygen of $t in format $fmt failed" + rm -f $OBJ/$t-key.pub # .pub file not used, remove it to be sure it is not used + if [ ! -z "$oldfmt" ] ; then + # Comment cannot be recovered from old format keys. + comment="" + fi + check_private_key $OBJ/$t-key "${fmt}" "${comment}" "${secret}" "${rounds}" + rm -f $OBJ/$t-key* + done + done + done +done diff --git a/ssh-keygen.c b/ssh-keygen.c index d50ca5f28c51..6dd17c48be5e 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -310,7 +310,7 @@ ask_filename(struct passwd *pw, const char *prompt) } static struct sshkey * -load_identity(const char *filename, char **commentp) +load_identity(const char *filename, char **commentp, struct sshkey_vault **vault_infop) { char *pass; struct sshkey *prv; @@ -318,7 +318,9 @@ load_identity(const char *filename, char **commentp) if (commentp != NULL) *commentp = NULL; - if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0) + if (vault_infop != NULL) + *vault_infop = NULL; + if ((r = sshkey_load_private(filename, "", &prv, commentp, vault_infop)) == 0) return prv; if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) fatal("Load key \"%s\": %s", filename, ssh_err(r)); @@ -326,7 +328,7 @@ load_identity(const char *filename, char **commentp) pass = xstrdup(identity_passphrase); else pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); - r = sshkey_load_private(filename, pass, &prv, commentp); + r = sshkey_load_private(filename, pass, &prv, commentp, vault_infop); freezero(pass, strlen(pass)); if (r != 0) fatal("Load key \"%s\": %s", filename, ssh_err(r)); @@ -429,7 +431,7 @@ do_convert_to(struct passwd *pw) if (stat(identity_file, &st) == -1) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0) - k = load_identity(identity_file, NULL); + k = load_identity(identity_file, NULL, NULL); switch (convert_format) { case FMT_RFC4716: do_convert_to_ssh2(pw, k); @@ -806,19 +808,33 @@ do_print_public(struct passwd *pw) struct stat st; int r; char *comment = NULL; + struct sshkey_vault *vault_info = NULL; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); if (stat(identity_file, &st) == -1) fatal("%s: %s", identity_file, strerror(errno)); - prv = load_identity(identity_file, &comment); + prv = load_identity(identity_file, &comment, &vault_info); if ((r = sshkey_write(prv, stdout)) != 0) error("sshkey_write failed: %s", ssh_err(r)); sshkey_free(prv); if (comment != NULL && *comment != '\0') - fprintf(stdout, " %s", comment); - fprintf(stdout, "\n"); + printf(" %s", comment); + printf("\n"); + if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) { + printf("Key protection details:\n"); + printf("File format: %s\n", sshkey_format_name(vault_info->format)); + if ( (vault_info->ciphername == NULL || strcmp(vault_info->ciphername, "none") == 0) + || (vault_info->kdfname == NULL || strcmp(vault_info->kdfname, "none") == 0)) { + printf("no passphrase\n"); + } else { + printf("cipher: %s\n", vault_info->ciphername); + printf("kdf: %s\n", vault_info->kdfname); + printf("rounds: %d\n", vault_info->rounds); + } + } free(comment); + sshkey_vault_free(vault_info); exit(0); } @@ -920,7 +936,7 @@ fingerprint_private(const char *path) if (pubkey == NULL || comment == NULL || *comment == '\0') { free(comment); if ((r = sshkey_load_private(path, NULL, - &privkey, &comment)) != 0) + &privkey, &comment, NULL)) != 0) debug("load private \"%s\": %s", path, ssh_err(r)); } if (pubkey == NULL && privkey == NULL) @@ -1416,7 +1432,7 @@ do_change_passphrase(struct passwd *pw) if (stat(identity_file, &st) == -1) fatal("%s: %s", identity_file, strerror(errno)); /* Try to load the file with empty passphrase. */ - r = sshkey_load_private(identity_file, "", &private, &comment); + r = sshkey_load_private(identity_file, "", &private, &comment, NULL); if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) { if (identity_passphrase) old_passphrase = xstrdup(identity_passphrase); @@ -1425,7 +1441,7 @@ do_change_passphrase(struct passwd *pw) read_passphrase("Enter old passphrase: ", RP_ALLOW_STDIN); r = sshkey_load_private(identity_file, old_passphrase, - &private, &comment); + &private, &comment, NULL); freezero(old_passphrase, strlen(old_passphrase)); if (r != 0) goto badkey; @@ -1525,7 +1541,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) if (stat(identity_file, &st) == -1) fatal("%s: %s", identity_file, strerror(errno)); if ((r = sshkey_load_private(identity_file, "", - &private, &comment)) == 0) + &private, &comment, NULL)) == 0) passphrase = xstrdup(""); else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) fatal("Cannot load private key \"%s\": %s.", @@ -1540,7 +1556,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) RP_ALLOW_STDIN); /* Try to load using the passphrase. */ if ((r = sshkey_load_private(identity_file, passphrase, - &private, &comment)) != 0) { + &private, &comment, NULL)) != 0) { freezero(passphrase, strlen(passphrase)); fatal("Cannot load private key \"%s\": %s.", identity_file, ssh_err(r)); @@ -1785,7 +1801,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, ca->flags |= SSHKEY_FLAG_EXT; } else { /* CA key is assumed to be a private key on the filesystem */ - ca = load_identity(tmp, NULL); + ca = load_identity(tmp, NULL, NULL); } free(tmp); @@ -2494,7 +2510,7 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey) debug("%s: %s looks like a public key, using private key " "path %s instead", __func__, keypath, privpath); } - if ((privkey = load_identity(privpath, NULL)) == NULL) { + if ((privkey = load_identity(privpath, NULL, NULL)) == NULL) { error("Couldn't load identity %s", keypath); goto done; } diff --git a/ssh-keysign.c b/ssh-keysign.c index 3e3ea3e1481d..c9c20483b9a5 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -225,7 +225,7 @@ main(int argc, char **argv) if (key_fd[i] == -1) continue; r = sshkey_load_private_type_fd(key_fd[i], KEY_UNSPEC, - NULL, &key, NULL); + NULL, &key, NULL, NULL); close(key_fd[i]); if (r != 0) debug("parse key %d: %s", i, ssh_err(r)); diff --git a/sshconnect2.c b/sshconnect2.c index 1a6545edf026..7947f2da6584 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1472,7 +1472,7 @@ load_identity_file(Identity *id) } } switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, - passphrase, &private, &comment))) { + passphrase, &private, &comment, NULL))) { case 0: break; case SSH_ERR_KEY_WRONG_PASSPHRASE: diff --git a/sshd.c b/sshd.c index 6f8f11a3bdac..42c19089a225 100644 --- a/sshd.c +++ b/sshd.c @@ -1789,7 +1789,7 @@ main(int ac, char **av) if (options.host_key_files[i] == NULL) continue; if ((r = sshkey_load_private(options.host_key_files[i], "", - &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) + &key, NULL, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) do_log2(ll, "Unable to load host key \"%s\": %s", options.host_key_files[i], ssh_err(r)); if (sshkey_is_sk(key) && diff --git a/sshkey.c b/sshkey.c index 1571e3d93878..4c1948a3752e 100644 --- a/sshkey.c +++ b/sshkey.c @@ -93,6 +93,26 @@ int sshkey_private_serialize_opt(struct sshkey *key, static int sshkey_from_blob_internal(struct sshbuf *buf, struct sshkey **keyp, int allow_cert); +/* Supported format types */ +const char * +sshkey_format_name(enum sshkey_private_format format) { + const char *format_str; + switch (format) { + case SSHKEY_PRIVATE_OPENSSH: + format_str = "RFC4716"; + break; + case SSHKEY_PRIVATE_PKCS8: + format_str = "PKCS8"; + break; + case SSHKEY_PRIVATE_PEM: + format_str = "PEM"; + break; + default: + format_str = "unknown"; + } + return format_str; +} + /* Supported key types */ struct keytype { const char *name; @@ -679,6 +699,29 @@ sshkey_free(struct sshkey *k) freezero(k, sizeof(*k)); } +struct sshkey_vault * +sshkey_vault_new() +{ + struct sshkey_vault *k = calloc(1, sizeof(*k)); + if (k == NULL) + return NULL; + k->format = SSHKEY_PRIVATE_OPENSSH; + k->ciphername = NULL; + k->kdfname = NULL; + k->rounds = -1; + return k; +} + +void +sshkey_vault_free(struct sshkey_vault *k) +{ + if (k == NULL) + return; + free(k->kdfname); + free(k); + return; +} + static int cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) { @@ -4029,7 +4072,7 @@ private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp) static int private2_decrypt(struct sshbuf *decoded, const char *passphrase, - struct sshbuf **decryptedp, struct sshkey **pubkeyp) + struct sshbuf **decryptedp, struct sshkey **pubkeyp, struct sshkey_vault **vault_infop) { char *ciphername = NULL, *kdfname = NULL; const struct sshcipher *cipher = NULL; @@ -4038,12 +4081,21 @@ private2_decrypt(struct sshbuf *decoded, const char *passphrase, struct sshbuf *kdf = NULL, *decrypted = NULL; struct sshcipher_ctx *ciphercontext = NULL; struct sshkey *pubkey = NULL; + struct sshkey_vault *vault_info = NULL; u_char *key = NULL, *salt = NULL, *dp; u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (vault_infop != NULL) { + *vault_infop = NULL; + } + if ((vault_info = sshkey_vault_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + *decryptedp = NULL; *pubkeyp = NULL; @@ -4074,10 +4126,18 @@ private2_decrypt(struct sshbuf *decoded, const char *passphrase, r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } + if ((vault_info->ciphername = strdup(ciphername)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } + if ((vault_info->kdfname = strdup(kdfname)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; @@ -4108,6 +4168,7 @@ private2_decrypt(struct sshbuf *decoded, const char *passphrase, if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 || (r = sshbuf_get_u32(kdf, &rounds)) != 0) goto out; + vault_info->rounds = rounds; if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, key, keylen + ivlen, rounds) < 0) { r = SSH_ERR_INVALID_FORMAT; @@ -4155,6 +4216,10 @@ private2_decrypt(struct sshbuf *decoded, const char *passphrase, decrypted = NULL; *pubkeyp = pubkey; pubkey = NULL; + if (vault_infop != NULL) { + *vault_infop = vault_info; + vault_info = NULL; + } r = 0; out: cipher_free(ciphercontext); @@ -4171,6 +4236,7 @@ private2_decrypt(struct sshbuf *decoded, const char *passphrase, } sshbuf_free(kdf); sshbuf_free(decrypted); + sshkey_vault_free(vault_info); return r; } @@ -4201,7 +4267,7 @@ private2_check_padding(struct sshbuf *decrypted) static int sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, - struct sshkey **keyp, char **commentp) + struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop) { char *comment = NULL; int r = SSH_ERR_INTERNAL_ERROR; @@ -4216,7 +4282,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, /* Undo base64 encoding and decrypt the private section */ if ((r = private2_uudecode(blob, &decoded)) != 0 || (r = private2_decrypt(decoded, passphrase, - &decrypted, &pubkey)) != 0) + &decrypted, &pubkey, vault_infop)) != 0) goto out; if (type != KEY_UNSPEC && @@ -4521,15 +4587,18 @@ pem_passphrase_cb(char *buf, int size, int rwflag, void *u) static int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, - const char *passphrase, struct sshkey **keyp) + const char *passphrase, struct sshkey **keyp, struct sshkey_vault **vault_infop) { EVP_PKEY *pk = NULL; struct sshkey *prv = NULL; + struct sshkey_vault *vault_info = NULL; BIO *bio = NULL; int r; if (keyp != NULL) *keyp = NULL; + if (vault_infop != NULL) + *vault_infop = NULL; if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) return SSH_ERR_ALLOC_FAIL; @@ -4538,6 +4607,13 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, r = SSH_ERR_ALLOC_FAIL; goto out; } + if ((vault_info = sshkey_vault_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + // TODO: identify correctly PEM and PKCS8 format + vault_info->format = SSHKEY_PRIVATE_PEM; + // TODO: put the correct ciphername, kdfname and round if a passphrase is used clear_libcrypto_errors(); if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, @@ -4614,17 +4690,22 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, *keyp = prv; prv = NULL; } + if (vault_infop != NULL) { + *vault_infop = vault_info; + vault_info = NULL; + } out: BIO_free(bio); EVP_PKEY_free(pk); sshkey_free(prv); + sshkey_vault_free(vault_info); return r; } #endif /* WITH_OPENSSL */ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, - const char *passphrase, struct sshkey **keyp, char **commentp) + const char *passphrase, struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop) { int r = SSH_ERR_INTERNAL_ERROR; @@ -4632,22 +4713,24 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, *keyp = NULL; if (commentp != NULL) *commentp = NULL; + if (vault_infop != NULL) + *vault_infop = NULL; switch (type) { case KEY_ED25519: case KEY_XMSS: /* No fallback for new-format-only keys */ return sshkey_parse_private2(blob, type, passphrase, - keyp, commentp); + keyp, commentp, vault_infop); default: r = sshkey_parse_private2(blob, type, passphrase, keyp, - commentp); + commentp, vault_infop); /* Only fallback to PEM parser if a format error occurred. */ if (r != SSH_ERR_INVALID_FORMAT) return r; #ifdef WITH_OPENSSL return sshkey_parse_private_pem_fileblob(blob, type, - passphrase, keyp); + passphrase, keyp, vault_infop); #else return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ @@ -4664,7 +4747,7 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, *commentp = NULL; return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, - passphrase, keyp, commentp); + passphrase, keyp, commentp, NULL); } void diff --git a/sshkey.h b/sshkey.h index 9c1d4f6372f6..7b7de828d9ce 100644 --- a/sshkey.h +++ b/sshkey.h @@ -99,6 +99,8 @@ enum sshkey_private_format { SSHKEY_PRIVATE_PEM = 1, SSHKEY_PRIVATE_PKCS8 = 2, }; +const char * +sshkey_format_name(enum sshkey_private_format); /* key is stored in external hardware */ #define SSHKEY_FLAG_EXT 0x0001 @@ -162,6 +164,16 @@ struct sshkey_sig_details { uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */ }; +/* Key storage parameters in private key file */ +struct sshkey_vault { + enum sshkey_private_format format; + char *ciphername; + char *kdfname; + int rounds; +}; +struct sshkey_vault *sshkey_vault_new(); +void sshkey_vault_free(struct sshkey_vault *); + struct sshkey *sshkey_new(int); void sshkey_free(struct sshkey *); int sshkey_equal_public(const struct sshkey *, @@ -258,7 +270,7 @@ int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, int sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, struct sshkey **keyp, char **commentp); int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, - const char *passphrase, struct sshkey **keyp, char **commentp); + const char *passphrase, struct sshkey **keyp, char **commentp, struct sshkey_vault **vault_infop); int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, struct sshkey **pubkeyp); -- 2.17.1 _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev