summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--authfile.c6
-rw-r--r--ssh-keygen.19
-rw-r--r--ssh-keygen.c25
-rw-r--r--sshkey.c78
-rw-r--r--sshkey.h11
5 files changed, 87 insertions, 42 deletions
diff --git a/authfile.c b/authfile.c
index 2166c1689..851c1a8a1 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfile.c,v 1.132 2019/06/28 13:35:04 deraadt Exp $ */ 1/* $OpenBSD: authfile.c,v 1.133 2019/07/15 13:16:29 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
4 * 4 *
@@ -74,7 +74,7 @@ sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
74int 74int
75sshkey_save_private(struct sshkey *key, const char *filename, 75sshkey_save_private(struct sshkey *key, const char *filename,
76 const char *passphrase, const char *comment, 76 const char *passphrase, const char *comment,
77 int force_new_format, const char *new_format_cipher, int new_format_rounds) 77 int format, const char *openssh_format_cipher, int openssh_format_rounds)
78{ 78{
79 struct sshbuf *keyblob = NULL; 79 struct sshbuf *keyblob = NULL;
80 int r; 80 int r;
@@ -82,7 +82,7 @@ sshkey_save_private(struct sshkey *key, const char *filename,
82 if ((keyblob = sshbuf_new()) == NULL) 82 if ((keyblob = sshbuf_new()) == NULL)
83 return SSH_ERR_ALLOC_FAIL; 83 return SSH_ERR_ALLOC_FAIL;
84 if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment, 84 if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
85 force_new_format, new_format_cipher, new_format_rounds)) != 0) 85 format, openssh_format_cipher, openssh_format_rounds)) != 0)
86 goto out; 86 goto out;
87 if ((r = sshkey_save_private_blob(keyblob, filename)) != 0) 87 if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
88 goto out; 88 goto out;
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index f42127c60..8184a1797 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-keygen.1,v 1.160 2019/05/20 06:01:59 jmc Exp $ 1.\" $OpenBSD: ssh-keygen.1,v 1.161 2019/07/15 13:16:29 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.\" 37.\"
38.Dd $Mdocdate: May 20 2019 $ 38.Dd $Mdocdate: July 15 2019 $
39.Dt SSH-KEYGEN 1 39.Dt SSH-KEYGEN 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -419,11 +419,12 @@ The supported key formats are:
419.Dq RFC4716 419.Dq RFC4716
420(RFC 4716/SSH2 public or private key), 420(RFC 4716/SSH2 public or private key),
421.Dq PKCS8 421.Dq PKCS8
422(PEM PKCS8 public key) 422(PKCS8 public or private key)
423or 423or
424.Dq PEM 424.Dq PEM
425(PEM public key). 425(PEM public key).
426The default conversion format is 426By default OpenSSH will write newly-generated private keys in its own
427format, but when converting public keys for export the default format is
427.Dq RFC4716 . 428.Dq RFC4716 .
428Setting a format of 429Setting a format of
429.Dq PEM 430.Dq PEM
diff --git a/ssh-keygen.c b/ssh-keygen.c
index b019a02ff..5dcad1f61 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.335 2019/07/05 07:32:01 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.336 2019/07/15 13:16:29 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -147,11 +147,11 @@ static char *key_type_name = NULL;
147/* Load key from this PKCS#11 provider */ 147/* Load key from this PKCS#11 provider */
148static char *pkcs11provider = NULL; 148static char *pkcs11provider = NULL;
149 149
150/* Use new OpenSSH private key format when writing SSH2 keys instead of PEM */ 150/* Format for writing private keys */
151static int use_new_format = 1; 151static int private_key_format = SSHKEY_PRIVATE_OPENSSH;
152 152
153/* Cipher for new-format private keys */ 153/* Cipher for new-format private keys */
154static char *new_format_cipher = NULL; 154static char *openssh_format_cipher = NULL;
155 155
156/* 156/*
157 * Number of KDF rounds to derive new format keys / 157 * Number of KDF rounds to derive new format keys /
@@ -1048,7 +1048,8 @@ do_gen_all_hostkeys(struct passwd *pw)
1048 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, 1048 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1049 hostname); 1049 hostname);
1050 if ((r = sshkey_save_private(private, prv_tmp, "", 1050 if ((r = sshkey_save_private(private, prv_tmp, "",
1051 comment, use_new_format, new_format_cipher, rounds)) != 0) { 1051 comment, private_key_format, openssh_format_cipher,
1052 rounds)) != 0) {
1052 error("Saving key \"%s\" failed: %s", 1053 error("Saving key \"%s\" failed: %s",
1053 prv_tmp, ssh_err(r)); 1054 prv_tmp, ssh_err(r));
1054 goto failnext; 1055 goto failnext;
@@ -1391,7 +1392,7 @@ do_change_passphrase(struct passwd *pw)
1391 1392
1392 /* Save the file using the new passphrase. */ 1393 /* Save the file using the new passphrase. */
1393 if ((r = sshkey_save_private(private, identity_file, passphrase1, 1394 if ((r = sshkey_save_private(private, identity_file, passphrase1,
1394 comment, use_new_format, new_format_cipher, rounds)) != 0) { 1395 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
1395 error("Saving key \"%s\" failed: %s.", 1396 error("Saving key \"%s\" failed: %s.",
1396 identity_file, ssh_err(r)); 1397 identity_file, ssh_err(r));
1397 explicit_bzero(passphrase1, strlen(passphrase1)); 1398 explicit_bzero(passphrase1, strlen(passphrase1));
@@ -1480,7 +1481,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
1480 } 1481 }
1481 1482
1482 if (private->type != KEY_ED25519 && private->type != KEY_XMSS && 1483 if (private->type != KEY_ED25519 && private->type != KEY_XMSS &&
1483 !use_new_format) { 1484 private_key_format != SSHKEY_PRIVATE_OPENSSH) {
1484 error("Comments are only supported for keys stored in " 1485 error("Comments are only supported for keys stored in "
1485 "the new format (-o)."); 1486 "the new format (-o).");
1486 explicit_bzero(passphrase, strlen(passphrase)); 1487 explicit_bzero(passphrase, strlen(passphrase));
@@ -1514,7 +1515,8 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
1514 1515
1515 /* Save the file using the new passphrase. */ 1516 /* Save the file using the new passphrase. */
1516 if ((r = sshkey_save_private(private, identity_file, passphrase, 1517 if ((r = sshkey_save_private(private, identity_file, passphrase,
1517 new_comment, use_new_format, new_format_cipher, rounds)) != 0) { 1518 new_comment, private_key_format, openssh_format_cipher,
1519 rounds)) != 0) {
1518 error("Saving key \"%s\" failed: %s", 1520 error("Saving key \"%s\" failed: %s",
1519 identity_file, ssh_err(r)); 1521 identity_file, ssh_err(r));
1520 explicit_bzero(passphrase, strlen(passphrase)); 1522 explicit_bzero(passphrase, strlen(passphrase));
@@ -2525,11 +2527,12 @@ main(int argc, char **argv)
2525 } 2527 }
2526 if (strcasecmp(optarg, "PKCS8") == 0) { 2528 if (strcasecmp(optarg, "PKCS8") == 0) {
2527 convert_format = FMT_PKCS8; 2529 convert_format = FMT_PKCS8;
2530 private_key_format = SSHKEY_PRIVATE_PKCS8;
2528 break; 2531 break;
2529 } 2532 }
2530 if (strcasecmp(optarg, "PEM") == 0) { 2533 if (strcasecmp(optarg, "PEM") == 0) {
2531 convert_format = FMT_PEM; 2534 convert_format = FMT_PEM;
2532 use_new_format = 0; 2535 private_key_format = SSHKEY_PRIVATE_PEM;
2533 break; 2536 break;
2534 } 2537 }
2535 fatal("Unsupported conversion format \"%s\"", optarg); 2538 fatal("Unsupported conversion format \"%s\"", optarg);
@@ -2567,7 +2570,7 @@ main(int argc, char **argv)
2567 add_cert_option(optarg); 2570 add_cert_option(optarg);
2568 break; 2571 break;
2569 case 'Z': 2572 case 'Z':
2570 new_format_cipher = optarg; 2573 openssh_format_cipher = optarg;
2571 break; 2574 break;
2572 case 'C': 2575 case 'C':
2573 identity_comment = optarg; 2576 identity_comment = optarg;
@@ -2912,7 +2915,7 @@ passphrase_again:
2912 2915
2913 /* Save the key with the given passphrase and comment. */ 2916 /* Save the key with the given passphrase and comment. */
2914 if ((r = sshkey_save_private(private, identity_file, passphrase1, 2917 if ((r = sshkey_save_private(private, identity_file, passphrase1,
2915 comment, use_new_format, new_format_cipher, rounds)) != 0) { 2918 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
2916 error("Saving key \"%s\" failed: %s", 2919 error("Saving key \"%s\" failed: %s",
2917 identity_file, ssh_err(r)); 2920 identity_file, ssh_err(r));
2918 explicit_bzero(passphrase1, strlen(passphrase1)); 2921 explicit_bzero(passphrase1, strlen(passphrase1));
diff --git a/sshkey.c b/sshkey.c
index 6b5ff0485..a0cea9257 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.79 2019/07/07 01:05:00 dtucker Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.80 2019/07/15 13:16:29 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -3975,10 +3975,10 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3975 3975
3976 3976
3977#ifdef WITH_OPENSSL 3977#ifdef WITH_OPENSSL
3978/* convert SSH v2 key in OpenSSL PEM format */ 3978/* convert SSH v2 key to PEM or PKCS#8 format */
3979static int 3979static int
3980sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf, 3980sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
3981 const char *_passphrase, const char *comment) 3981 int format, const char *_passphrase, const char *comment)
3982{ 3982{
3983 int was_shielded = sshkey_is_shielded(key); 3983 int was_shielded = sshkey_is_shielded(key);
3984 int success, r; 3984 int success, r;
@@ -3988,32 +3988,49 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
3988 char *bptr; 3988 char *bptr;
3989 BIO *bio = NULL; 3989 BIO *bio = NULL;
3990 struct sshbuf *blob; 3990 struct sshbuf *blob;
3991 EVP_PKEY *pkey = NULL;
3991 3992
3992 if (len > 0 && len <= 4) 3993 if (len > 0 && len <= 4)
3993 return SSH_ERR_PASSPHRASE_TOO_SHORT; 3994 return SSH_ERR_PASSPHRASE_TOO_SHORT;
3994 if ((blob = sshbuf_new()) == NULL) 3995 if ((blob = sshbuf_new()) == NULL)
3995 return SSH_ERR_ALLOC_FAIL; 3996 return SSH_ERR_ALLOC_FAIL;
3996 if ((bio = BIO_new(BIO_s_mem())) == NULL) { 3997 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
3997 sshbuf_free(blob); 3998 r = SSH_ERR_ALLOC_FAIL;
3998 return SSH_ERR_ALLOC_FAIL; 3999 goto out;
3999 } 4000 }
4001 if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
4002 r = SSH_ERR_ALLOC_FAIL;
4003 goto out;
4004 }
4000 if ((r = sshkey_unshield_private(key)) != 0) 4005 if ((r = sshkey_unshield_private(key)) != 0)
4001 goto out; 4006 goto out;
4002 4007
4003 switch (key->type) { 4008 switch (key->type) {
4004 case KEY_DSA: 4009 case KEY_DSA:
4005 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, 4010 if (format == SSHKEY_PRIVATE_PEM) {
4006 cipher, passphrase, len, NULL, NULL); 4011 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
4012 cipher, passphrase, len, NULL, NULL);
4013 } else {
4014 success = EVP_PKEY_set1_DSA(pkey, key->dsa);
4015 }
4007 break; 4016 break;
4008#ifdef OPENSSL_HAS_ECC 4017#ifdef OPENSSL_HAS_ECC
4009 case KEY_ECDSA: 4018 case KEY_ECDSA:
4010 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, 4019 if (format == SSHKEY_PRIVATE_PEM) {
4011 cipher, passphrase, len, NULL, NULL); 4020 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
4021 cipher, passphrase, len, NULL, NULL);
4022 } else {
4023 success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa);
4024 }
4012 break; 4025 break;
4013#endif 4026#endif
4014 case KEY_RSA: 4027 case KEY_RSA:
4015 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, 4028 if (format == SSHKEY_PRIVATE_PEM) {
4016 cipher, passphrase, len, NULL, NULL); 4029 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
4030 cipher, passphrase, len, NULL, NULL);
4031 } else {
4032 success = EVP_PKEY_set1_RSA(pkey, key->rsa);
4033 }
4017 break; 4034 break;
4018 default: 4035 default:
4019 success = 0; 4036 success = 0;
@@ -4023,6 +4040,13 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
4023 r = SSH_ERR_LIBCRYPTO_ERROR; 4040 r = SSH_ERR_LIBCRYPTO_ERROR;
4024 goto out; 4041 goto out;
4025 } 4042 }
4043 if (format == SSHKEY_PRIVATE_PKCS8) {
4044 if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher,
4045 passphrase, len, NULL, NULL)) == 0) {
4046 r = SSH_ERR_LIBCRYPTO_ERROR;
4047 goto out;
4048 }
4049 }
4026 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { 4050 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
4027 r = SSH_ERR_INTERNAL_ERROR; 4051 r = SSH_ERR_INTERNAL_ERROR;
4028 goto out; 4052 goto out;
@@ -4035,8 +4059,9 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
4035 r = sshkey_shield_private(key); 4059 r = sshkey_shield_private(key);
4036 if (r == 0) 4060 if (r == 0)
4037 r = sshbuf_putb(buf, blob); 4061 r = sshbuf_putb(buf, blob);
4038 sshbuf_free(blob);
4039 4062
4063 EVP_PKEY_free(pkey);
4064 sshbuf_free(blob);
4040 BIO_free(bio); 4065 BIO_free(bio);
4041 return r; 4066 return r;
4042} 4067}
@@ -4046,29 +4071,38 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *buf,
4046int 4071int
4047sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, 4072sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
4048 const char *passphrase, const char *comment, 4073 const char *passphrase, const char *comment,
4049 int force_new_format, const char *new_format_cipher, int new_format_rounds) 4074 int format, const char *openssh_format_cipher, int openssh_format_rounds)
4050{ 4075{
4051 switch (key->type) { 4076 switch (key->type) {
4052#ifdef WITH_OPENSSL 4077#ifdef WITH_OPENSSL
4053 case KEY_DSA: 4078 case KEY_DSA:
4054 case KEY_ECDSA: 4079 case KEY_ECDSA:
4055 case KEY_RSA: 4080 case KEY_RSA:
4056 if (force_new_format) { 4081 break; /* see below */
4057 return sshkey_private_to_blob2(key, blob, passphrase,
4058 comment, new_format_cipher, new_format_rounds);
4059 }
4060 return sshkey_private_pem_to_blob(key, blob,
4061 passphrase, comment);
4062#endif /* WITH_OPENSSL */ 4082#endif /* WITH_OPENSSL */
4063 case KEY_ED25519: 4083 case KEY_ED25519:
4064#ifdef WITH_XMSS 4084#ifdef WITH_XMSS
4065 case KEY_XMSS: 4085 case KEY_XMSS:
4066#endif /* WITH_XMSS */ 4086#endif /* WITH_XMSS */
4067 return sshkey_private_to_blob2(key, blob, passphrase, 4087 return sshkey_private_to_blob2(key, blob, passphrase,
4068 comment, new_format_cipher, new_format_rounds); 4088 comment, openssh_format_cipher, openssh_format_rounds);
4069 default: 4089 default:
4070 return SSH_ERR_KEY_TYPE_UNKNOWN; 4090 return SSH_ERR_KEY_TYPE_UNKNOWN;
4071 } 4091 }
4092
4093#ifdef WITH_OPENSSL
4094 switch (format) {
4095 case SSHKEY_PRIVATE_OPENSSH:
4096 return sshkey_private_to_blob2(key, blob, passphrase,
4097 comment, openssh_format_cipher, openssh_format_rounds);
4098 case SSHKEY_PRIVATE_PEM:
4099 case SSHKEY_PRIVATE_PKCS8:
4100 return sshkey_private_to_blob_pem_pkcs8(key, blob,
4101 format, passphrase, comment);
4102 default:
4103 return SSH_ERR_INVALID_ARGUMENT;
4104 }
4105#endif /* WITH_OPENSSL */
4072} 4106}
4073 4107
4074 4108
diff --git a/sshkey.h b/sshkey.h
index 41d159a1b..d30a69cc9 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.h,v 1.32 2019/06/21 04:21:05 djm Exp $ */ 1/* $OpenBSD: sshkey.h,v 1.33 2019/07/15 13:16:29 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -88,6 +88,13 @@ enum sshkey_serialize_rep {
88 SSHKEY_SERIALIZE_INFO = 254, 88 SSHKEY_SERIALIZE_INFO = 254,
89}; 89};
90 90
91/* Private key disk formats */
92enum sshkey_private_format {
93 SSHKEY_PRIVATE_OPENSSH = 0,
94 SSHKEY_PRIVATE_PEM = 1,
95 SSHKEY_PRIVATE_PKCS8 = 2,
96};
97
91/* key is stored in external hardware */ 98/* key is stored in external hardware */
92#define SSHKEY_FLAG_EXT 0x0001 99#define SSHKEY_FLAG_EXT 0x0001
93 100
@@ -221,7 +228,7 @@ int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
221/* private key file format parsing and serialisation */ 228/* private key file format parsing and serialisation */
222int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, 229int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
223 const char *passphrase, const char *comment, 230 const char *passphrase, const char *comment,
224 int force_new_format, const char *new_format_cipher, int new_format_rounds); 231 int format, const char *openssh_format_cipher, int openssh_format_rounds);
225int sshkey_parse_private_fileblob(struct sshbuf *buffer, 232int sshkey_parse_private_fileblob(struct sshbuf *buffer,
226 const char *passphrase, struct sshkey **keyp, char **commentp); 233 const char *passphrase, struct sshkey **keyp, char **commentp);
227int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, 234int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,