-/* $OpenBSD: authfile.c,v 1.132 2019/06/28 13:35:04 deraadt Exp $ */
+/* $OpenBSD: authfile.c,v 1.133 2019/07/15 13:16:29 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
int
sshkey_save_private(struct sshkey *key, const char *filename,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
struct sshbuf *keyblob = NULL;
int r;
if ((keyblob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
- force_new_format, new_format_cipher, new_format_rounds)) != 0)
+ format, openssh_format_cipher, openssh_format_rounds)) != 0)
goto out;
if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
goto out;
-.\" $OpenBSD: ssh-keygen.1,v 1.160 2019/05/20 06:01:59 jmc Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.161 2019/07/15 13:16:29 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: May 20 2019 $
+.Dd $Mdocdate: July 15 2019 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
.Dq RFC4716
(RFC 4716/SSH2 public or private key),
.Dq PKCS8
-(PEM PKCS8 public key)
+(PKCS8 public or private key)
or
.Dq PEM
(PEM public key).
-The default conversion format is
+By default OpenSSH will write newly-generated private keys in its own
+format, but when converting public keys for export the default format is
.Dq RFC4716 .
Setting a format of
.Dq PEM
-/* $OpenBSD: ssh-keygen.c,v 1.335 2019/07/05 07:32:01 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.336 2019/07/15 13:16:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
/* Load key from this PKCS#11 provider */
static char *pkcs11provider = NULL;
-/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */
-static int use_new_format = 1;
+/* Format for writing private keys */
+static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
/* Cipher for new-format private keys */
-static char *new_format_cipher = NULL;
+static char *openssh_format_cipher = NULL;
/*
* Number of KDF rounds to derive new format keys /
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
if ((r = sshkey_save_private(private, prv_tmp, "",
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher,
+ rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
prv_tmp, ssh_err(r));
goto failnext;
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s.",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
}
if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
- !use_new_format) {
+ private_key_format != SSHKEY_PRIVATE_OPENSSH) {
error("Comments are only supported for keys stored in "
"the new format (-o).");
explicit_bzero(passphrase, strlen(passphrase));
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
- new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ new_comment, private_key_format, openssh_format_cipher,
+ rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase, strlen(passphrase));
}
if (strcasecmp(optarg, "PKCS8") == 0) {
convert_format = FMT_PKCS8;
+ private_key_format = SSHKEY_PRIVATE_PKCS8;
break;
}
if (strcasecmp(optarg, "PEM") == 0) {
convert_format = FMT_PEM;
- use_new_format = 0;
+ private_key_format = SSHKEY_PRIVATE_PEM;
break;
}
fatal("Unsupported conversion format \"%s\"", optarg);
add_cert_option(optarg);
break;
case 'Z':
- new_format_cipher = optarg;
+ openssh_format_cipher = optarg;
break;
case 'C':
identity_comment = optarg;
/* Save the key with the given passphrase and comment. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
- comment, use_new_format, new_format_cipher, rounds)) != 0) {
+ comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
error("Saving key \"%s\" failed: %s",
identity_file, ssh_err(r));
explicit_bzero(passphrase1, strlen(passphrase1));
-/* $OpenBSD: sshkey.c,v 1.79 2019/07/07 01:05:00 dtucker Exp $ */
+/* $OpenBSD: sshkey.c,v 1.80 2019/07/15 13:16:29 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
#ifdef WITH_OPENSSL
-/* convert SSH v2 key in OpenSSL PEM format */
+/* convert SSH v2 key to PEM or PKCS#8 format */
static int
-sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
- const char *_passphrase, const char *comment)
+sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
+ int format, const char *_passphrase, const char *comment)
{
int was_shielded = sshkey_is_shielded(key);
int success, r;
char *bptr;
BIO *bio = NULL;
struct sshbuf *blob;
+ EVP_PKEY *pkey = NULL;
if (len > 0 && len <= 4)
return SSH_ERR_PASSPHRASE_TOO_SHORT;
if ((blob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((bio = BIO_new(BIO_s_mem())) == NULL) {
- sshbuf_free(blob);
- return SSH_ERR_ALLOC_FAIL;
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
}
+ if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
if ((r = sshkey_unshield_private(key)) != 0)
goto out;
switch (key->type) {
case KEY_DSA:
- success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_DSA(pkey, key->dsa);
+ }
break;
#ifdef OPENSSL_HAS_ECC
case KEY_ECDSA:
- success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
+ }
break;
#endif
case KEY_RSA:
- success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
- cipher, passphrase, len, NULL, NULL);
+ if (format == SSHKEY_PRIVATE_PEM) {
+ success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
+ cipher, passphrase, len, NULL, NULL);
+ } else {
+ success = EVP_PKEY_set1_RSA(pkey, key->rsa);
+ }
break;
default:
success = 0;
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if (format == SSHKEY_PRIVATE_PKCS8) {
+ if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
+ passphrase, len, NULL, NULL)) == 0) {
+ r = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ }
if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
r = SSH_ERR_INTERNAL_ERROR;
goto out;
r = sshkey_shield_private(key);
if (r == 0)
r = sshbuf_putb(buf, blob);
- sshbuf_free(blob);
+ EVP_PKEY_free(pkey);
+ sshbuf_free(blob);
BIO_free(bio);
return r;
}
int
sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds)
+ int format, const char *openssh_format_cipher, int openssh_format_rounds)
{
switch (key->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
case KEY_RSA:
- if (force_new_format) {
- return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
- }
- return sshkey_private_pem_to_blob(key, blob,
- passphrase, comment);
+ break; /* see below */
#endif /* WITH_OPENSSL */
case KEY_ED25519:
#ifdef WITH_XMSS
case KEY_XMSS:
#endif /* WITH_XMSS */
return sshkey_private_to_blob2(key, blob, passphrase,
- comment, new_format_cipher, new_format_rounds);
+ comment, openssh_format_cipher, openssh_format_rounds);
default:
return SSH_ERR_KEY_TYPE_UNKNOWN;
}
+
+#ifdef WITH_OPENSSL
+ switch (format) {
+ case SSHKEY_PRIVATE_OPENSSH:
+ return sshkey_private_to_blob2(key, blob, passphrase,
+ comment, openssh_format_cipher, openssh_format_rounds);
+ case SSHKEY_PRIVATE_PEM:
+ case SSHKEY_PRIVATE_PKCS8:
+ return sshkey_private_to_blob_pem_pkcs8(key, blob,
+ format, passphrase, comment);
+ default:
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+#endif /* WITH_OPENSSL */
}
-/* $OpenBSD: sshkey.h,v 1.32 2019/06/21 04:21:05 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.33 2019/07/15 13:16:29 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
SSHKEY_SERIALIZE_INFO = 254,
};
+/* Private key disk formats */
+enum sshkey_private_format {
+ SSHKEY_PRIVATE_OPENSSH = 0,
+ SSHKEY_PRIVATE_PEM = 1,
+ SSHKEY_PRIVATE_PKCS8 = 2,
+};
+
/* key is stored in external hardware */
#define SSHKEY_FLAG_EXT 0x0001
/* private key file format parsing and serialisation */
int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
const char *passphrase, const char *comment,
- int force_new_format, const char *new_format_cipher, int new_format_rounds);
+ int format, const char *openssh_format_cipher, int openssh_format_rounds);
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,