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 # else
void *ecdsa; void *ecdsa;
# endif /* HAVE_OPENSSL_EC_H */ # 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 */ #endif /* HAVE_LIBGCRYPT */
#if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519) #if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519)
uint8_t *ed25519_pubkey; uint8_t *ed25519_pubkey;

View File

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

View File

@ -450,7 +450,7 @@ err:
ssh_key pki_key_dup(const ssh_key key, int demote) ssh_key pki_key_dup(const ssh_key key, int demote)
{ {
ssh_key new; ssh_key new = NULL;
int rc; int rc;
new = ssh_key_new(); new = ssh_key_new();
@ -458,12 +458,6 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
return NULL; 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 = key->type;
new->type_c = key->type_c; new->type_c = key->type_c;
if (demote) { if (demote) {
@ -547,6 +541,19 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
const BIGNUM *n = NULL, *e = NULL, *d = NULL; const BIGNUM *n = NULL, *e = NULL, *d = NULL;
BIGNUM *nn, *ne, *nd; 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(); new->rsa = RSA_new();
if (new->rsa == NULL) { if (new->rsa == NULL) {
goto fail; goto fail;
@ -631,7 +638,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
/* Memory management of ndmp1, ndmq1 and niqmp is transferred /* Memory management of ndmp1, ndmq1 and niqmp is transferred
* to RSA object */ * to RSA object */
rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp); rc = RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp);
if (rc == 0) { if (rc == 0) {
BN_free(ndmp1); BN_free(ndmp1);
BN_free(ndmq1); BN_free(ndmq1);
@ -653,6 +660,22 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
case SSH_KEYTYPE_ECDSA_P521: case SSH_KEYTYPE_ECDSA_P521:
#ifdef HAVE_OPENSSL_ECC #ifdef HAVE_OPENSSL_ECC
new->ecdsa_nid = key->ecdsa_nid; 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 /* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
* https://github.com/openssl/openssl/pull/16624 * https://github.com/openssl/openssl/pull/16624
* #if OPENSSL_VERSION_NUMBER < 0x30000000L * #if OPENSSL_VERSION_NUMBER < 0x30000000L
@ -678,7 +701,11 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
goto fail; goto fail;
} }
} else { } 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 #else
rc = evp_dup_ecdsa_pkey(key, new, demote); 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 * Delete this part, because it is done below HAVE_ECC
*/ */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L #if OPENSSL_VERSION_NUMBER >= 0x30000000L
pkey = key->key; rc = EVP_PKEY_up_ref(key->key);
if (pkey == NULL) { if (rc != 1) {
goto err; goto err;
} }
pkey = key->key;
/* Mark the operation as successful as for the other key types */ /* Mark the operation as successful as for the other key types */
rc = 1; rc = 1;
@ -1149,10 +1177,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
* #if OPENSSL_VERSION_NUMBER >= 0x30000000L * #if OPENSSL_VERSION_NUMBER >= 0x30000000L
*/ */
#if 0 #if 0
pkey = key->key; rc = EVP_PKEY_up_ref(key->key);
if (pkey == NULL) { if (rc != 1) {
goto err; goto err;
} }
pkey = key->key;
/* Mark the operation as successful as for the other key types */ /* Mark the operation as successful as for the other key types */
rc = 1; rc = 1;
@ -1216,9 +1245,7 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
NULL, /* auth_fn */ NULL, /* auth_fn */
(void*) passphrase); (void*) passphrase);
} }
if (pkey != key->key) { EVP_PKEY_free(pkey);
EVP_PKEY_free(pkey);
}
pkey = NULL; pkey = NULL;
if (rc != 1) { 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 * https://github.com/openssl/openssl/pull/16624
* Remove these three lines * Remove these three lines
*/ */
/* the EVP_PKEY is not saved to the ssh_key struct */
EVP_PKEY_free(pkey);
pkey = NULL;
break; break;
#endif /* HAVE_OPENSSL_ECC */ #endif /* HAVE_OPENSSL_ECC */
#ifdef HAVE_OPENSSL_ED25519 #ifdef HAVE_OPENSSL_ED25519
@ -1397,11 +1420,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
} }
type = SSH_KEYTYPE_ED25519; 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; break;
#endif /* HAVE_OPENSSL_ED25519 */ #endif /* HAVE_OPENSSL_ED25519 */
@ -1411,10 +1429,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
return NULL; 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(); key = ssh_key_new();
if (key == NULL) { if (key == NULL) {
@ -1427,9 +1441,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key,
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
key->dsa = dsa; key->dsa = dsa;
key->rsa = rsa; key->rsa = rsa;
#else
key->key = pkey;
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
key->key = pkey;
/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys /* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys
* https://github.com/openssl/openssl/pull/16624 * https://github.com/openssl/openssl/pull/16624
* Move key->ecdsa line into the #if above this * Move key->ecdsa line into the #if above this
@ -2829,15 +2842,11 @@ static const EVP_MD *pki_digest_to_md(enum ssh_digest_e hash_type)
static EVP_PKEY *pki_key_to_pkey(ssh_key key) static EVP_PKEY *pki_key_to_pkey(ssh_key key)
{ {
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#ifdef WITH_PKCS11_URI int rc = 0;
if (key->flags & SSH_KEY_FLAG_PKCS11_URI) {
pkey = key->key;
return pkey;
}
#endif #endif
switch(key->type) { switch (key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_DSS_CERT01:
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
@ -2879,11 +2888,12 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key)
SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); SSH_LOG(SSH_LOG_TRACE, "NULL key->key");
goto error; goto error;
} }
pkey = EVP_PKEY_dup(key->key); rc = EVP_PKEY_up_ref(key->key);
if (pkey == NULL) { if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "Out of memory"); SSH_LOG(SSH_LOG_TRACE, "Failed to reference EVP_PKEY");
return NULL; return NULL;
} }
pkey = key->key;
break; break;
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
case SSH_KEYTYPE_ECDSA_P256: 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"); SSH_LOG(SSH_LOG_TRACE, "NULL key->key");
goto error; goto error;
} }
pkey = EVP_PKEY_dup(key->key); rc = EVP_PKEY_uo_ref(key->key);
if (pkey == NULL) { if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "Out of memory"); SSH_LOG(SSH_LOG_TRACE, "Failed to reference EVP_PKEY");
return NULL; return NULL;
} }
pkey = key->key;
break; break;
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519:
@ -3126,9 +3137,7 @@ out:
explicit_bzero(raw_sig_data, raw_sig_len); explicit_bzero(raw_sig_data, raw_sig_len);
} }
SAFE_FREE(raw_sig_data); SAFE_FREE(raw_sig_data);
if (pkey != NULL && !(privkey->flags & SSH_KEY_FLAG_PKCS11_URI)) { EVP_PKEY_free(pkey);
EVP_PKEY_free(pkey);
}
return sig; return sig;
} }
@ -3254,16 +3263,14 @@ out:
if (ctx != NULL) { if (ctx != NULL) {
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
} }
if (pkey != NULL && !(pubkey->flags & SSH_KEY_FLAG_PKCS11_URI)) { EVP_PKEY_free(pkey);
EVP_PKEY_free(pkey);
}
return rc; return rc;
} }
int ssh_key_size(ssh_key key) int ssh_key_size(ssh_key key)
{ {
int bits = 0; int bits = 0;
EVP_PKEY *pkey; EVP_PKEY *pkey = NULL;
switch (key->type) { switch (key->type) {
case SSH_KEYTYPE_DSS: case SSH_KEYTYPE_DSS:
@ -3284,17 +3291,7 @@ int ssh_key_size(ssh_key key)
return SSH_ERROR; return SSH_ERROR;
} }
bits = EVP_PKEY_bits(pkey); bits = EVP_PKEY_bits(pkey);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_PKEY_free(pkey); 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; return bits;
case SSH_KEYTYPE_ED25519: case SSH_KEYTYPE_ED25519:
case SSH_KEYTYPE_ED25519_CERT01: case SSH_KEYTYPE_ED25519_CERT01:
@ -3549,10 +3546,9 @@ int pki_uri_import(const char *uri_name,
key->key = pkey; key->key = pkey;
key->type = type; key->type = type;
key->type_c = ssh_key_type_to_char(type); key->type_c = ssh_key_type_to_char(type);
key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI;
if (key_type == SSH_KEY_PRIVATE) { if (key_type == SSH_KEY_PRIVATE) {
key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PKCS11_URI; key->flags |= SSH_KEY_FLAG_PRIVATE;
} else {
key->flags = SSH_KEY_FLAG_PUBLIC | SSH_KEY_FLAG_PKCS11_URI;
} }
#if OPENSSL_VERSION_NUMBER < 0x30000000L #if OPENSSL_VERSION_NUMBER < 0x30000000L
key->rsa = rsa; 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); 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) static void import_pubkey_without_loading_public_uri(void **state, const char *uri, const char *type)
{ {
int rc; int rc;
@ -258,21 +273,6 @@ static void import_pubkey_without_loading_public_uri(void **state, const char *u
SSH_KEY_FREE(pubkey); 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) 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"); 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_384),
cmocka_unit_test(torture_pki_ecdsa_import_pubkey_without_loading_public_uri_521), cmocka_unit_test(torture_pki_ecdsa_import_pubkey_without_loading_public_uri_521),
}; };
ssh_session session = ssh_new(); ssh_session session = ssh_new();
int verbosity = SSH_LOG_FUNCTIONS; int verbosity = SSH_LOG_FUNCTIONS;
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_init(); ssh_init();
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
torture_filter_tests(tests); torture_filter_tests(tests);
rc = cmocka_run_group_tests(tests, setup_directory_structure, teardown_directory_structure); rc = cmocka_run_group_tests(tests, setup_directory_structure, teardown_directory_structure);

View File

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