File 0001-sshkey-expose-openssl-EVP_PKEY-to-sshkey-conversion-.patch of Package openssh
From 56a37c17c4993f03ef6f2840113eee1d4b01f30f Mon Sep 17 00:00:00 2001
From: James Bottomley <James.Bottomley@HansenPartnership.com>
Date: Mon, 25 May 2020 10:46:02 -0700
Subject: [PATCH 1/3] sshkey: expose openssl EVP_PKEY to sshkey conversion
routine.
Break a new function, sshkey_openssl_private_key(), out of
sshkey_parse_private_pem_fileblob() which will be used with engine
keys that have no internal private key. Add an external flag, which
disables any private key component checking and sets SSHKEY_FLAG_EXT
on the sshkey.
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
sshkey.c | 111 ++++++++++++++++++++++++++++++-------------------------
sshkey.h | 5 +++
2 files changed, 65 insertions(+), 51 deletions(-)
diff --git a/sshkey.c b/sshkey.c
index 1db83788d..87beac5c9 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -3534,53 +3534,22 @@ pem_passphrase_cb(char *buf, int size, int rwflag, void *u)
return (int)len;
}
-static int
-sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
- const char *passphrase, struct sshkey **keyp)
+int
+sshkey_openssl_private_key(int type, EVP_PKEY *pk, struct sshkey **keyp,
+ int external)
{
- EVP_PKEY *pk = NULL;
struct sshkey *prv = NULL;
- BIO *bio = NULL;
int r;
RSA *rsa = NULL;
EC_KEY *ecdsa = NULL;
- if (keyp != NULL)
- *keyp = NULL;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
- return SSH_ERR_ALLOC_FAIL;
- if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
- (int)sshbuf_len(blob)) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- clear_libcrypto_errors();
- if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
- (char *)passphrase)) == NULL) {
- /*
- * libcrypto may return various ASN.1 errors when attempting
- * to parse a key with an incorrect passphrase.
- * Treat all format errors as "incorrect passphrase" if a
- * passphrase was supplied.
- */
- if (passphrase != NULL && *passphrase != '\0')
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- else
- r = convert_libcrypto_error();
- goto out;
- }
if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA &&
(type == KEY_UNSPEC || type == KEY_RSA)) {
- if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((rsa = EVP_PKEY_get1_RSA(pk)) == NULL) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
+ if ((prv = sshkey_new(KEY_UNSPEC)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
+ if ((rsa = EVP_PKEY_get1_RSA(pk)) == NULL)
+ return SSH_ERR_LIBCRYPTO_ERROR;
prv->type = KEY_RSA;
#ifdef DEBUG_PK
RSA_print_fp(stderr, rsa, 8);
@@ -3597,10 +3566,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
#ifdef WITH_DSA
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) {
- if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ if ((prv = sshkey_new(KEY_UNSPEC)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
prv->dsa = EVP_PKEY_get1_DSA(pk);
prv->type = KEY_DSA;
#ifdef DEBUG_PK
@@ -3610,10 +3578,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
#ifdef OPENSSL_HAS_ECC
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC &&
(type == KEY_UNSPEC || type == KEY_ECDSA)) {
- if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
+ if ((prv = sshkey_new(KEY_UNSPEC)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
if ((prv->ecdsa_nid = sshkey_ecdsa_fixup_group(pk)) == -1 ||
(ecdsa = EVP_PKEY_get1_EC_KEY(pk)) == NULL) {
r = SSH_ERR_LIBCRYPTO_ERROR;
@@ -3623,7 +3590,8 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
if (sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
sshkey_ec_validate_public(EC_KEY_get0_group(ecdsa),
EC_KEY_get0_public_key(ecdsa)) != 0 ||
- sshkey_ec_validate_private(ecdsa) != 0) {
+ (!external &&
+ sshkey_ec_validate_private(ecdsa) != 0)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -3675,19 +3643,60 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ if (external)
+ prv->flags |= SSHKEY_FLAG_EXT;
r = 0;
if (keyp != NULL) {
*keyp = prv;
prv = NULL;
}
out:
- BIO_free(bio);
- EVP_PKEY_free(pk);
+ sshkey_free(prv);
RSA_free(rsa);
#ifdef OPENSSL_HAS_ECC
EC_KEY_free(ecdsa);
#endif
- sshkey_free(prv);
+ return r;
+}
+
+static int
+sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
+ const char *passphrase, struct sshkey **keyp)
+{
+ EVP_PKEY *pk = NULL;
+ BIO *bio = NULL;
+ int r;
+
+ if (keyp != NULL)
+ *keyp = NULL;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
+ return SSH_ERR_ALLOC_FAIL;
+ if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
+ (int)sshbuf_len(blob)) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+
+ clear_libcrypto_errors();
+ if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
+ (char *)passphrase)) == NULL) {
+ /*
+ * libcrypto may return various ASN.1 errors when attempting
+ * to parse a key with an incorrect passphrase.
+ * Treat all format errors as "incorrect passphrase" if a
+ * passphrase was supplied.
+ */
+ if (passphrase != NULL && *passphrase != '\0')
+ r = SSH_ERR_KEY_WRONG_PASSPHRASE;
+ else
+ r = convert_libcrypto_error();
+ goto out;
+ }
+ r = sshkey_openssl_private_key(type, pk, keyp, 0);
+ out:
+ BIO_free(bio);
+ EVP_PKEY_free(pk);
return r;
}
#endif /* WITH_OPENSSL */
diff --git a/sshkey.h b/sshkey.h
index d0cdea0ce..bfd67b9d9 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -349,6 +349,11 @@ int check_rsa_length(const RSA *rsa); /* XXX remove */
#endif
#endif
+#ifdef WITH_OPENSSL
+int sshkey_openssl_private_key(int type, EVP_PKEY *pk, struct sshkey **keyp,
+ int external);
+#endif
+
#if !defined(WITH_OPENSSL)
# undef RSA
# undef DSA
--
2.35.3