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

openSUSE Build Service is sponsored by