From 0ce1e84d9046d680ae65cd650a9d4557f203baef Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Thu, 23 May 2019 11:30:06 +0200 Subject: [PATCH] pki_crypto: Use the new OpenSSL API to write new PKCS#8 PEM files Since OpenSSL 1.0.0, the "traditional" PEM format was deprecated in favor of the PKCS#8 PEM files which is more standardized, more secure and does not depend on the MD5 hash, which is not available for example in FIPS mode. This requires using the new EVP_PKEY API for reading private key blobs. Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider --- src/pki_crypto.c | 119 ++++++++++++++++++----------------------------- 1 file changed, 46 insertions(+), 73 deletions(-) diff --git a/src/pki_crypto.c b/src/pki_crypto.c index ef0f7c16..f1e5fce0 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -719,9 +719,10 @@ ssh_string pki_private_key_to_pem(const ssh_key key, ssh_auth_callback auth_fn, void *auth_data) { - ssh_string blob; - BUF_MEM *buf; - BIO *mem; + ssh_string blob = NULL; + BUF_MEM *buf = NULL; + BIO *mem = NULL; + EVP_PKEY *pkey = NULL; int rc; mem = BIO_new(BIO_s_mem()); @@ -729,88 +730,29 @@ ssh_string pki_private_key_to_pem(const ssh_key key, return NULL; } + pkey = EVP_PKEY_new(); + if (pkey == NULL) { + goto err; + } + switch (key->type) { case SSH_KEYTYPE_DSS: - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_DSAPrivateKey(mem, - key->dsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_DSAPrivateKey(mem, - key->dsa, - EVP_aes_128_cbc(), - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } + rc = EVP_PKEY_set1_DSA(pkey, key->dsa); break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_RSAPrivateKey(mem, - key->rsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_RSAPrivateKey(mem, - key->rsa, - EVP_aes_128_cbc(), - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } + rc = EVP_PKEY_set1_RSA(pkey, key->rsa); break; #ifdef HAVE_ECC case SSH_KEYTYPE_ECDSA_P256: case SSH_KEYTYPE_ECDSA_P384: case SSH_KEYTYPE_ECDSA_P521: - if (passphrase == NULL) { - struct pem_get_password_struct pgp = { auth_fn, auth_data }; - - rc = PEM_write_bio_ECPrivateKey(mem, - key->ecdsa, - NULL, /* cipher */ - NULL, /* kstr */ - 0, /* klen */ - pem_get_password, - &pgp); - } else { - rc = PEM_write_bio_ECPrivateKey(mem, - key->ecdsa, - EVP_aes_128_cbc(), - NULL, /* kstr */ - 0, /* klen */ - NULL, /* auth_fn */ - (void*) passphrase); - } - if (rc != 1) { - goto err; - } + rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); break; #endif case SSH_KEYTYPE_ED25519: - BIO_free(mem); SSH_LOG(SSH_LOG_WARN, "PEM output not supported for key type ssh-ed25519"); - return NULL; + goto err; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_ECDSA_P256_CERT01: @@ -819,9 +761,38 @@ ssh_string pki_private_key_to_pem(const ssh_key key, case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_UNKNOWN: default: - BIO_free(mem); SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", key->type); - return NULL; + goto err; + } + if (rc != 1) { + SSH_LOG(SSH_LOG_WARN, "Failed to initialize EVP_PKEY structure"); + goto err; + } + + if (passphrase == NULL) { + struct pem_get_password_struct pgp = { auth_fn, auth_data }; + + rc = PEM_write_bio_PrivateKey(mem, + pkey, + NULL, /* cipher */ + NULL, /* kstr */ + 0, /* klen */ + pem_get_password, + &pgp); + } else { + rc = PEM_write_bio_PrivateKey(mem, + pkey, + EVP_aes_128_cbc(), + NULL, /* kstr */ + 0, /* klen */ + NULL, /* auth_fn */ + (void*) passphrase); + } + EVP_PKEY_free(pkey); + pkey = NULL; + + if (rc != 1) { + goto err; } BIO_get_mem_ptr(mem, &buf); @@ -835,7 +806,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key, BIO_free(mem); return blob; + err: + EVP_PKEY_free(pkey); BIO_free(mem); return NULL; }