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@xxxxxxxxxxxxxxxxxxxxx> --- 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@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev