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:
@ -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;
|
||||
|
@ -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;
|
||||
|
114
src/pki_crypto.c
114
src/pki_crypto.c
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user