1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-30 13:01:23 +03:00

pki_crypto: Use the new OpenSSL API to read PEM files

This allows the use of the new PKCS#8 PEM files and does not
limit libssh to using only the "traditional" PEM files, that
are not default in OpenSSL since 1.0.0 and which do not work
at all in FIPS mode.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
Jakub Jelen
2019-05-23 11:34:41 +02:00
committed by Andreas Schneider
parent 0ce1e84d90
commit 167aa8bc6c

View File

@@ -816,96 +816,68 @@ err:
ssh_key pki_private_key_from_base64(const char *b64_key, ssh_key pki_private_key_from_base64(const char *b64_key,
const char *passphrase, const char *passphrase,
ssh_auth_callback auth_fn, ssh_auth_callback auth_fn,
void *auth_data) { void *auth_data)
{
BIO *mem = NULL; BIO *mem = NULL;
DSA *dsa = NULL; DSA *dsa = NULL;
RSA *rsa = NULL; RSA *rsa = NULL;
ed25519_privkey *ed25519 = NULL; ed25519_privkey *ed25519 = NULL;
ssh_key key = NULL; ssh_key key = NULL;
enum ssh_keytypes_e type; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN;
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
EC_KEY *ecdsa = NULL; EC_KEY *ecdsa = NULL;
#else #else
void *ecdsa = NULL; void *ecdsa = NULL;
#endif #endif
EVP_PKEY *pkey = NULL;
type = pki_privatekey_type_from_string(b64_key);
if (type == SSH_KEYTYPE_UNKNOWN) {
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key.");
return NULL;
}
mem = BIO_new_mem_buf((void*)b64_key, -1); mem = BIO_new_mem_buf((void*)b64_key, -1);
switch (type) {
case SSH_KEYTYPE_DSS:
if (passphrase == NULL) { if (passphrase == NULL) {
if (auth_fn) { if (auth_fn) {
struct pem_get_password_struct pgp = { auth_fn, auth_data }; struct pem_get_password_struct pgp = { auth_fn, auth_data };
dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, &pgp); pkey = PEM_read_bio_PrivateKey(mem, NULL, pem_get_password, &pgp);
} else { } else {
/* openssl uses its own callback to get the passphrase here */ /* openssl uses its own callback to get the passphrase here */
dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, NULL); pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, NULL);
} }
} else { } else {
dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, (void *) passphrase); pkey = PEM_read_bio_PrivateKey(mem, NULL, NULL, (void *) passphrase);
} }
BIO_free(mem); BIO_free(mem);
if (dsa == NULL) { if (pkey == NULL) {
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"Parsing private key: %s", "Parsing private key: %s",
ERR_error_string(ERR_get_error(), NULL)); ERR_error_string(ERR_get_error(), NULL));
return NULL; return NULL;
} }
switch (EVP_PKEY_base_id(pkey)) {
case EVP_PKEY_DSA:
dsa = EVP_PKEY_get1_DSA(pkey);
if (dsa == NULL) {
SSH_LOG(SSH_LOG_WARN,
"Parsing private key: %s",
ERR_error_string(ERR_get_error(),NULL));
return NULL;
}
type = SSH_KEYTYPE_DSS;
break; break;
case SSH_KEYTYPE_RSA: case EVP_PKEY_RSA:
case SSH_KEYTYPE_RSA1: rsa = EVP_PKEY_get1_RSA(pkey);
if (passphrase == NULL) {
if (auth_fn) {
struct pem_get_password_struct pgp = { auth_fn, auth_data };
rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, &pgp);
} else {
/* openssl uses its own callback to get the passphrase here */
rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL);
}
} else {
rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, (void *) passphrase);
}
BIO_free(mem);
if (rsa == NULL) { if (rsa == NULL) {
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"Parsing private key: %s", "Parsing private key: %s",
ERR_error_string(ERR_get_error(),NULL)); ERR_error_string(ERR_get_error(),NULL));
return NULL; return NULL;
} }
type = SSH_KEYTYPE_RSA;
break; break;
case SSH_KEYTYPE_ECDSA_P256: case EVP_PKEY_EC:
case SSH_KEYTYPE_ECDSA_P384:
case SSH_KEYTYPE_ECDSA_P521:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
if (passphrase == NULL) { ecdsa = EVP_PKEY_get1_EC_KEY(pkey);
if (auth_fn) {
struct pem_get_password_struct pgp = { auth_fn, auth_data };
ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, pem_get_password, &pgp);
} else {
/* openssl uses its own callback to get the passphrase here */
ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, NULL, NULL);
}
} else {
ecdsa = PEM_read_bio_ECPrivateKey(mem, NULL, NULL, (void *) passphrase);
}
BIO_free(mem);
if (ecdsa == NULL) { if (ecdsa == NULL) {
SSH_LOG(SSH_LOG_WARN, SSH_LOG(SSH_LOG_WARN,
"Parsing private key: %s", "Parsing private key: %s",
@@ -923,20 +895,13 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
break; break;
#endif #endif
case SSH_KEYTYPE_ED25519: default:
/* Cannot open ed25519 keys with libcrypto */ EVP_PKEY_free(pkey);
case SSH_KEYTYPE_DSS_CERT01: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d",
case SSH_KEYTYPE_RSA_CERT01: EVP_PKEY_base_id(pkey));
case SSH_KEYTYPE_ECDSA:
case SSH_KEYTYPE_ECDSA_P256_CERT01:
case SSH_KEYTYPE_ECDSA_P384_CERT01:
case SSH_KEYTYPE_ECDSA_P521_CERT01:
case SSH_KEYTYPE_ED25519_CERT01:
case SSH_KEYTYPE_UNKNOWN:
BIO_free(mem);
SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type);
return NULL; return NULL;
} }
EVP_PKEY_free(pkey);
key = ssh_key_new(); key = ssh_key_new();
if (key == NULL) { if (key == NULL) {