1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-07-31 00:03:07 +03:00

pki: Rework handling of EVP_PKEYs in OpenSSL backend

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
This commit is contained in:
Jakub Jelen
2022-08-24 16:24:44 +02:00
parent 0800618f32
commit a81e78aff4
5 changed files with 88 additions and 87 deletions

View File

@ -78,7 +78,9 @@ struct ssh_key_struct {
# else
void *ecdsa;
# endif /* HAVE_OPENSSL_EC_H */
EVP_PKEY *key; /* Saving the OpenSSL context here to save time while converting*/
/* This holds either ENGINE key for PKCS#11 support or just key in
* high-level format required by OpenSSL 3.0 */
EVP_PKEY *key;
#endif /* HAVE_LIBGCRYPT */
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519)
uint8_t *ed25519_pubkey;

View File

@ -1096,12 +1096,11 @@ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key)
return NULL;
}
pub = malloc(sizeof(struct ssh_public_key_struct));
pub = calloc(1, sizeof(struct ssh_public_key_struct));
if (pub == NULL) {
ssh_key_free(tmp);
return NULL;
}
ZERO_STRUCTP(pub);
pub->type = tmp->type;
pub->type_c = tmp->type_c;
@ -1125,7 +1124,7 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key)
{
ssh_private_key privkey;
privkey = malloc(sizeof(struct ssh_private_key_struct));
privkey = calloc(1, sizeof(struct ssh_private_key_struct));
if (privkey == NULL) {
ssh_key_free(key);
return NULL;

View File

@ -450,7 +450,7 @@ err:
ssh_key pki_key_dup(const ssh_key key, int demote)
{
ssh_key new;
ssh_key new = NULL;
int rc;
new = ssh_key_new();
@ -458,12 +458,6 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
return NULL;
}
#ifdef WITH_PKCS11_URI
#if OPENSSL_VERSION_NUMBER < 0x30000000L
new->key = key->key;
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* WITH_PKCS11_URI */
new->type = key->type;
new->type_c = key->type_c;
if (demote) {
@ -547,6 +541,19 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
#if OPENSSL_VERSION_NUMBER < 0x30000000L
const BIGNUM *n = NULL, *e = NULL, *d = NULL;
BIGNUM *nn, *ne, *nd;
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
#ifdef WITH_PKCS11_URI
/* Take the PKCS#11 keys as they are */
if (key->flags & SSH_KEY_FLAG_PKCS11_URI && !demote) {
rc = EVP_PKEY_up_ref(key->key);
if (rc != 1) {
goto fail;
}
new->key = key->key;
return new;
}
#endif /* WITH_PKCS11_URI */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
new->rsa = RSA_new();
if (new->rsa == NULL) {
goto fail;
@ -653,6 +660,22 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
case SSH_KEYTYPE_ECDSA_P521:
#ifdef HAVE_OPENSSL_ECC
new->ecdsa_nid = key->ecdsa_nid;
#ifdef WITH_PKCS11_URI
/* Take the PKCS#11 keys as they are */
if (key->flags & SSH_KEY_FLAG_PKCS11_URI && !demote) {
rc = EVP_PKEY_up_ref(key->key);
if (rc != 1) {
goto fail;
}
new->key = key->key;
rc = EC_KEY_up_ref(key->ecdsa);
if (rc != 1) {
goto fail;
}
new->ecdsa = key->ecdsa;
return new;
}
#endif /* WITH_PKCS11_URI */
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
* https://github.com/openssl/openssl/pull/16624
* #if OPENSSL_VERSION_NUMBER < 0x30000000L
@ -678,7 +701,11 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail;
}
} else {
new->ecdsa = EC_KEY_dup(key->ecdsa);
rc = EC_KEY_up_ref(key->ecdsa);
if (rc != 1) {
goto fail;
}
new->ecdsa = key->ecdsa;
}
#else
rc = evp_dup_ecdsa_pkey(key, new, demote);
@ -1116,10 +1143,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
* Delete this part, because it is done below HAVE_ECC
*/
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
pkey = key->key;
if (pkey == NULL) {
rc = EVP_PKEY_up_ref(key->key);
if (rc != 1) {
goto err;
}
pkey = key->key;
/* Mark the operation as successful as for the other key types */
rc = 1;
@ -1149,10 +1177,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
* #if OPENSSL_VERSION_NUMBER >= 0x30000000L
*/
#if 0
pkey = key->key;
if (pkey == NULL) {
rc = EVP_PKEY_up_ref(key->key);
if (rc != 1) {
goto err;
}
pkey = key->key;
/* Mark the operation as successful as for the other key types */
rc = 1;
@ -1216,9 +1245,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
NULL, /* auth_fn */
(void*) passphrase);
}
if (pkey != key->key) {
EVP_PKEY_free(pkey);
}
pkey = NULL;
if (rc != 1) {
@ -1356,10 +1383,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
* https://github.com/openssl/openssl/pull/16624
* Remove these three lines
*/
/* the EVP_PKEY is not saved to the ssh_key struct */
EVP_PKEY_free(pkey);
pkey = NULL;
break;
#endif /* HAVE_OPENSSL_ECC */
#ifdef HAVE_OPENSSL_ED25519
@ -1397,11 +1420,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
}
type = SSH_KEYTYPE_ED25519;
/* the EVP_PKEY is not saved to the ssh_key struct */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY_free(pkey);
pkey = NULL;
#endif /* OPENSSL_VERSION_NUMBER */
}
break;
#endif /* HAVE_OPENSSL_ED25519 */
@ -1411,10 +1429,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
EVP_PKEY_free(pkey);
return NULL;
}
/* at later version the pkey is saved to ssh_key struct */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_PKEY_free(pkey);
#endif /* OPENSSL_VERSION_NUMBER */
key = ssh_key_new();
if (key == NULL) {
@ -1427,9 +1441,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
#if OPENSSL_VERSION_NUMBER < 0x30000000L
key->dsa = dsa;
key->rsa = rsa;
#else
key->key = pkey;
#endif /* OPENSSL_VERSION_NUMBER */
key->key = pkey;
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
* https://github.com/openssl/openssl/pull/16624
* Move key->ecdsa line into the #if above this
@ -2829,12 +2842,8 @@ static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
static EVP_PKEY *pki_key_to_pkey(ssh_key key)
{
EVP_PKEY *pkey = NULL;
#ifdef WITH_PKCS11_URI
if (key->flags & SSH_KEY_FLAG_PKCS11_URI) {
pkey = key->key;
return pkey;
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
int rc = 0;
#endif
switch (key->type) {
@ -2879,11 +2888,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
SSH_LOG(SSH_LOG_TRACE, "NULL key->key");
goto error;
}
pkey = EVP_PKEY_dup(key->key);
if (pkey == NULL) {
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
rc = EVP_PKEY_up_ref(key->key);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "Failed to reference EVP_PKEY");
return NULL;
}
pkey = key->key;
break;
#endif /* OPENSSL_VERSION_NUMBER */
case SSH_KEYTYPE_ECDSA_P256:
@ -2923,11 +2933,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
SSH_LOG(SSH_LOG_TRACE, "NULL key->key");
goto error;
}
pkey = EVP_PKEY_dup(key->key);
if (pkey == NULL) {
SSH_LOG(SSH_LOG_TRACE, "Out of memory");
rc = EVP_PKEY_uo_ref(key->key);
if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "Failed to reference EVP_PKEY");
return NULL;
}
pkey = key->key;
break;
#endif /* OPENSSL_VERSION_NUMBER */
case SSH_KEYTYPE_ED25519:
@ -3126,9 +3137,7 @@ out:
explicit_bzero(raw_sig_data, raw_sig_len);
}
SAFE_FREE(raw_sig_data);
if (pkey != NULL && !(privkey->flags & SSH_KEY_FLAG_PKCS11_URI)) {
EVP_PKEY_free(pkey);
}
return sig;
}
@ -3254,16 +3263,14 @@ out:
if (ctx != NULL) {
EVP_MD_CTX_free(ctx);
}
if (pkey != NULL && !(pubkey->flags & SSH_KEY_FLAG_PKCS11_URI)) {
EVP_PKEY_free(pkey);
}
return rc;
}
int ssh_key_size(ssh_key key)
{
int bits = 0;
EVP_PKEY *pkey;
EVP_PKEY *pkey = NULL;
switch (key->type) {
case SSH_KEYTYPE_DSS:
@ -3284,17 +3291,7 @@ int ssh_key_size(ssh_key key)
return SSH_ERROR;
}
bits = EVP_PKEY_bits(pkey);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_PKEY_free(pkey);
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
* https://github.com/openssl/openssl/pull/16624
* no need of this free
*/
#else
if (is_ecdsa_key_type(key->type)) {
EVP_PKEY_free(pkey);
}
#endif /* OPENSSL_VERSION_NUMBER */
return bits;
case SSH_KEYTYPE_ED25519:
case SSH_KEYTYPE_ED25519_CERT01:
@ -3549,10 +3546,9 @@ int pki_uri_import(const char *uri_name,
key->key = pkey;
key->type = type;
key->type_c = ssh_key_type_to_char(type);
if (key_type == SSH_KEY_PRIVATE) {
key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PKCS11_URI;
} else {
key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI;
if (key_type == SSH_KEY_PRIVATE) {
key->flags |= SSH_KEY_FLAG_PRIVATE;
}
#if OPENSSL_VERSION_NUMBER < 0x30000000L
key->rsa = rsa;

View File

@ -229,6 +229,21 @@ static void torture_pki_ecdsa_publickey_from_privatekey_uri(void **state, const
SSH_KEY_FREE(pubkey);
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_256(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_256, "ecdsa256");
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_384(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_384, "ecdsa384");
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_521(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_521, "ecdsa521");
}
static void import_pubkey_without_loading_public_uri(void **state, const char *uri, const char *type)
{
int rc;
@ -258,21 +273,6 @@ static void import_pubkey_without_loading_public_uri(void **state, const char *u
SSH_KEY_FREE(pubkey);
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_256(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_256, "ecdsa256");
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_384(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_384, "ecdsa384");
}
static void torture_pki_ecdsa_publickey_from_privatekey_uri_521(void **state)
{
torture_pki_ecdsa_publickey_from_privatekey_uri(state, PRIV_URI_FMT_521, "ecdsa521");
}
static void torture_pki_ecdsa_import_pubkey_without_loading_public_uri_256(void **state)
{
import_pubkey_without_loading_public_uri(state, PRIV_URI_FMT_256_NO_PUB, "ecdsa256_no_pub_uri");
@ -544,11 +544,11 @@ int torture_run_tests(void) {
cmocka_unit_test(torture_pki_ecdsa_import_pubkey_without_loading_public_uri_384),
cmocka_unit_test(torture_pki_ecdsa_import_pubkey_without_loading_public_uri_521),
};
ssh_session session = ssh_new();
int verbosity = SSH_LOG_FUNCTIONS;
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_init();
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, setup_directory_structure, teardown_directory_structure);

View File

@ -542,8 +542,12 @@ static void torture_pki_rsa_generate_key(void **state)
ssh_key key = NULL, pubkey = NULL;
ssh_signature sign = NULL;
ssh_session session = ssh_new();
int verbosity = torture_libssh_verbosity();
(void) state;
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if (!ssh_fips_mode()) {
rc = ssh_pki_generate(SSH_KEYTYPE_RSA, 1024, &key);
assert_true(rc == SSH_OK);