Mailing List Archive

[PATCH v2 1/2] 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 | 87 ++++++++++++++++++++++++++++++++------------------------
sshkey.h | 5 ++++
2 files changed, 55 insertions(+), 37 deletions(-)

diff --git a/sshkey.c b/sshkey.c
index 1571e3d93..32beb73f5 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -4519,47 +4519,18 @@ 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;

- 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 ((prv = sshkey_new(KEY_UNSPEC)) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+
prv->rsa = EVP_PKEY_get1_RSA(pk);
prv->type = KEY_RSA;
#ifdef DEBUG_PK
@@ -4596,7 +4567,8 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
- sshkey_ec_validate_private(prv->ecdsa) != 0) {
+ (!external &&
+ sshkey_ec_validate_private(prv->ecdsa) != 0)) {
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -4609,15 +4581,56 @@ 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:
+ 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);
- sshkey_free(prv);
return r;
}
#endif /* WITH_OPENSSL */
diff --git a/sshkey.h b/sshkey.h
index 9c1d4f637..326996913 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -317,6 +317,11 @@ int ssh_xmss_verify(const struct sshkey *key,
const u_char *data, size_t datalen, u_int compat);
#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.26.2

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev