diff --git a/libssh-0.10.6-pkcs11-provider.patch b/libssh-0.10.6-pkcs11-provider.patch new file mode 100644 index 0000000..d1134a2 --- /dev/null +++ b/libssh-0.10.6-pkcs11-provider.patch @@ -0,0 +1,4069 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a64b7708..535c74a9 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -89,13 +89,6 @@ if (WITH_GSSAPI) + find_package(GSSAPI) + endif (WITH_GSSAPI) + +-if (WITH_PKCS11_URI) +- find_package(softhsm) +- if (NOT SOFTHSM_FOUND) +- message(SEND_ERROR "Could not find softhsm module!") +- endif (NOT SOFTHSM_FOUND) +-endif (WITH_PKCS11_URI) +- + if (WITH_NACL) + find_package(NaCl) + if (NOT NACL_FOUND) +@@ -239,6 +232,7 @@ message(STATUS "Unit testing: ${UNIT_TESTING}") + message(STATUS "Client code testing: ${CLIENT_TESTING}") + message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}") + message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}") ++message(STATUS "With PKCS #11 provider support: ${WITH_PKCS11_PROVIDER}") + message(STATUS "DSA support: ${WITH_DSA}") + set(_SERVER_TESTING OFF) + if (WITH_SERVER) +diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake +index 9de10225..06ed23c8 100644 +--- a/ConfigureChecks.cmake ++++ b/ConfigureChecks.cmake +@@ -489,12 +489,21 @@ if (WITH_PKCS11_URI) + if (WITH_GCRYPT) + message(FATAL_ERROR "PKCS #11 is not supported for gcrypt.") + set(WITH_PKCS11_URI 0) +- endif() +- if (WITH_MBEDTLS) ++ elseif (WITH_MBEDTLS) + message(FATAL_ERROR "PKCS #11 is not supported for mbedcrypto") + set(WITH_PKCS11_URI 0) +- endif() +- if (HAVE_OPENSSL AND NOT OPENSSL_VERSION VERSION_GREATER_EQUAL "1.1.1") ++ elseif (OPENSSL_FOUND AND OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0") ++ find_library(PKCS11_PROVIDER ++ NAMES ++ pkcs11.so ++ PATH_SUFFIXES ++ ossl-modules ++ ) ++ if (NOT PKCS11_PROVIDER) ++ set(WITH_PKCS11_PROVIDER 0) ++ message(WARNING "Could not find pkcs11 provider! Falling back to engines") ++ endif (NOT PKCS11_PROVIDER) ++ elseif (HAVE_OPENSSL AND NOT OPENSSL_VERSION VERSION_GREATER_EQUAL "1.1.1") + message(FATAL_ERROR "PKCS #11 requires at least OpenSSL 1.1.1") + set(WITH_PKCS11_URI 0) + endif() +diff --git a/DefineOptions.cmake b/DefineOptions.cmake +index 6881b9a2..bc32abe5 100644 +--- a/DefineOptions.cmake ++++ b/DefineOptions.cmake +@@ -13,6 +13,7 @@ option(WITH_PCAP "Compile with Pcap generation support" ON) + option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF) + option(BUILD_SHARED_LIBS "Build shared libraries" ON) + option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF) ++option(WITH_PKCS11_PROVIDER "Use the PKCS#11 provider for accessing pkcs11 objects" OFF) + option(UNIT_TESTING "Build with unit tests" OFF) + option(CLIENT_TESTING "Build with client tests; requires openssh" OFF) + option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF) +diff --git a/config.h.cmake b/config.h.cmake +index cc83734d..409f5d0d 100644 +--- a/config.h.cmake ++++ b/config.h.cmake +@@ -276,6 +276,9 @@ + /* Define to 1 if you want to enable PKCS #11 URI support */ + #cmakedefine WITH_PKCS11_URI 1 + ++/* Define to 1 if we want to build a support for PKCS #11 provider. */ ++#cmakedefine WITH_PKCS11_PROVIDER 1 ++ + /*************************** ENDIAN *****************************/ + + /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +diff --git a/doc/pkcs11.dox b/doc/pkcs11.dox +index 0bdfc6dc..c2732a81 100644 +--- a/doc/pkcs11.dox ++++ b/doc/pkcs11.dox +@@ -9,11 +9,11 @@ objects stored on the tokens can be uniquely identified is called PKCS #11 URI + (Uniform Resource Identifier) and is defined in RFC 7512 + (https://tools.ietf.org/html/rfc7512). + +-Pre-requisites: ++# Pre-requisites (OpenSSL < 3.0): + +-OpenSSL defines an abstract layer called the "engine" to achieve cryptographic +-acceleration. The engine_pkcs11 module acts like an interface between the PKCS #11 +-modules and the OpenSSL engine. ++OpenSSL 1.x defines an abstract layer called the "engine" to achieve ++cryptographic acceleration. The engine_pkcs11 module acts like an interface ++between the PKCS #11 modules and the OpenSSL application. + + To build and use libssh with PKCS #11 support: + 1. Enable the cmake option: $ cmake -DWITH_PKCS11_URI=ON +@@ -21,6 +21,20 @@ To build and use libssh with PKCS #11 support: + 3. Install and configure engine_pkcs11 (https://github.com/OpenSC/libp11). + 4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm). + ++# Pre-requisites (OpenSSL 3.0.8+) ++ ++The OpenSSL 3.0 is deprecating usage of low-level engines in favor of high-level ++"providers" to provide alternative implementation of cryptographic operations ++or acceleration. ++ ++To build and use libssh with PKCS #11 support using OpenSSL providers: ++1. Install and configure pkcs11 provider (https://github.com/latchset/pkcs11-provider). ++2. Enable the cmake options: $ cmake -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON ++3. Build with OpenSSL. ++4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm). ++ ++# New API functions ++ + The functions ssh_pki_import_pubkey_file() and ssh_pki_import_privkey_file() that + import the public and private keys from files respectively are now modified to support + PKCS #11 URIs. These functions automatically detect if the provided filename is a file path +@@ -31,7 +45,7 @@ corresponding to the PKCS #11 URI are loaded from the PKCS #11 device. + If you wish to authenticate using public keys on your own, follow the steps mentioned under + "Authentication with public keys" in Chapter 2 - A deeper insight into authentication. + +-The function pki_uri_import() is used to populate the public/private ssh_key from the ++The function pki_uri_import() is used to populate the public/private ssh_key from the + engine with PKCS #11 URIs as the look up. + + Here is a minimalistic example of public key authentication using PKCS #11 URIs: +@@ -64,4 +78,10 @@ We recommend the users to provide a specific PKCS #11 URI so that it matches onl + If the engine discovers multiple slots that could potentially contain the private keys referenced + by the provided PKCS #11 URI, the engine will not try to authenticate. + ++For testing, the SoftHSM PKCS#11 library is used. But it has some issues with ++OpenSSL initialization/cleanup when used with OpenSSL 3.0 so we are using it ++indirectly through a p11-kit remoting as described in the following article: ++ ++https://p11-glue.github.io/p11-glue/p11-kit/manual/remoting.html ++ + */ +diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h +index 3dba18d0..32016827 100644 +--- a/include/libssh/crypto.h ++++ b/include/libssh/crypto.h +@@ -111,11 +111,7 @@ struct ssh_crypto_struct { + #endif /* WITH_GEX */ + #ifdef HAVE_ECDH + #ifdef HAVE_OPENSSL_ECC +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY *ecdh_privkey; + #else + EVP_PKEY *ecdh_privkey; +@@ -227,7 +223,7 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto, + size_t requested_len); + + int secure_memcmp(const void *s1, const void *s2, size_t n); +-#ifdef HAVE_LIBCRYPTO ++#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER) + ENGINE *pki_get_engine(void); + #endif /* HAVE_LIBCRYPTO */ + +diff --git a/include/libssh/keys.h b/include/libssh/keys.h +index 615f1eae..79bba747 100644 +--- a/include/libssh/keys.h ++++ b/include/libssh/keys.h +@@ -32,12 +32,7 @@ struct ssh_public_key_struct { + gcry_sexp_t dsa_pub; + gcry_sexp_t rsa_pub; + #elif defined(HAVE_LIBCRYPTO) +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA *dsa_pub; +- RSA *rsa_pub; +-#else /* OPENSSL_VERSION_NUMBER */ + EVP_PKEY *key_pub; +-#endif + #elif defined(HAVE_LIBMBEDCRYPTO) + mbedtls_pk_context *rsa_pub; + void *dsa_pub; +@@ -50,12 +45,7 @@ struct ssh_private_key_struct { + gcry_sexp_t dsa_priv; + gcry_sexp_t rsa_priv; + #elif defined(HAVE_LIBCRYPTO) +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA *dsa_priv; +- RSA *rsa_priv; +-#else + EVP_PKEY *key_priv; +-#endif /* OPENSSL_VERSION_NUMBER */ + #elif defined(HAVE_LIBMBEDCRYPTO) + mbedtls_pk_context *rsa_priv; + void *dsa_priv; +diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h +index 87f30a4d..3abfa814 100644 +--- a/include/libssh/libcrypto.h ++++ b/include/libssh/libcrypto.h +@@ -25,6 +25,7 @@ + + #ifdef HAVE_LIBCRYPTO + ++#include "libssh/libssh.h" + #include + #include + #include +@@ -32,6 +33,7 @@ + #include + #include + #include ++#include + + typedef EVP_MD_CTX* SHACTX; + typedef EVP_MD_CTX* SHA256CTX; +@@ -111,6 +113,8 @@ typedef BN_CTX* bignum_CTX; + #define ssh_fips_mode() false + #endif + ++ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p); ++int pki_key_ecgroup_name_to_nid(const char *group); + #endif /* HAVE_LIBCRYPTO */ + + #endif /* LIBCRYPTO_H_ */ +diff --git a/include/libssh/pki.h b/include/libssh/pki.h +index 879a1d5c..10814f5b 100644 +--- a/include/libssh/pki.h ++++ b/include/libssh/pki.h +@@ -65,21 +65,8 @@ struct ssh_key_struct { + mbedtls_ecdsa_context *ecdsa; + void *dsa; + #elif defined(HAVE_LIBCRYPTO) +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA *dsa; +- RSA *rsa; +-#endif /* OPENSSL_VERSION_NUMBER */ +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move into the #if above +- */ +-# if defined(HAVE_OPENSSL_ECC) +- EC_KEY *ecdsa; +-# else +- void *ecdsa; +-# endif /* HAVE_OPENSSL_EC_H */ + /* This holds either ENGINE key for PKCS#11 support or just key in +- * high-level format required by OpenSSL 3.0 */ ++ * high-level format */ + EVP_PKEY *key; + #endif /* HAVE_LIBGCRYPT */ + #if defined(HAVE_LIBCRYPTO) && defined(HAVE_OPENSSL_ED25519) +@@ -108,7 +95,7 @@ struct ssh_signature_struct { + #endif /* HAVE_LIBGCRYPT */ + #if !defined(HAVE_LIBCRYPTO) || !defined(HAVE_OPENSSL_ED25519) + ed25519_signature *ed25519_sig; +-#endif ++#endif /* HAVE_LIBGCRYPT */ + ssh_string raw_sig; + + /* Security Key specific additions */ +diff --git a/src/auth.c b/src/auth.c +index 4feb6558..c48eea5e 100644 +--- a/src/auth.c ++++ b/src/auth.c +@@ -1409,21 +1409,21 @@ int ssh_userauth_agent_pubkey(ssh_session session, + key->type = publickey->type; + key->type_c = ssh_key_type_to_char(key->type); + key->flags = SSH_KEY_FLAG_PUBLIC; +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = publickey->dsa_pub; + key->rsa = publickey->rsa_pub; + #else + key->key = publickey->key_pub; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + rc = ssh_userauth_agent_publickey(session, username, key); + +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = NULL; + key->rsa = NULL; + #else + key->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + ssh_key_free(key); + + return rc; +diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c +index 069b1372..a8bce894 100644 +--- a/src/ecdh_crypto.c ++++ b/src/ecdh_crypto.c +@@ -30,11 +30,7 @@ + + #ifdef HAVE_ECDH + #include +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + #define NISTP256 NID_X9_62_prime256v1 + #define NISTP384 NID_secp384r1 + #define NISTP521 NID_secp521r1 +@@ -48,11 +44,7 @@ + /** @internal + * @brief Map the given key exchange enum value to its curve name. + */ +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + static int ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { + #else + static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { +@@ -64,183 +56,156 @@ static const char *ecdh_kex_type_to_curve(enum ssh_key_exchange_e kex_type) { + } else if (kex_type == SSH_KEX_ECDH_SHA2_NISTP521) { + return NISTP521; + } +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + return SSH_ERROR; + #else + return NULL; + #endif + } + +-/** @internal +- * @brief Starts ecdh-sha2-nistp256 key exchange +- */ +-int ssh_client_ecdh_init(ssh_session session){ +- int rc; +- ssh_string client_pubkey; +-/* 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 ++/* @internal ++ * @brief Generate ECDH key pair for ecdh key exchange and store it in the ++ * session->next_crypto structure + */ +-#if 1 +- EC_KEY *key; +- const EC_GROUP *group; +- const EC_POINT *pubkey; +- int curve; +- int len; +- bignum_CTX ctx = BN_CTX_new(); +- if (ctx == NULL) { +- return SSH_ERROR; +- } ++static ssh_string ssh_ecdh_generate(ssh_session session) ++{ ++ ssh_string pubkey_string = NULL; ++ const EC_GROUP *group = NULL; ++ const EC_POINT *point = NULL; ++ int rc; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *key = NULL; ++ int curve; + #else +- const char *curve = NULL; +- EVP_PKEY *key = NULL; +- OSSL_PARAM *out_params = NULL; +- const OSSL_PARAM *pubkey_param = NULL; +- const uint8_t *pubkey = NULL; +- size_t pubkey_len; +-#endif /* OPENSSL_VERSION_NUMBER */ +- +- rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); +- if (rc < 0) { +-/* 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 +- */ +-#if 1 +- BN_CTX_free(ctx); ++ const char *curve = NULL; ++ EVP_PKEY *key = NULL; ++ OSSL_PARAM *out_params = NULL; ++ const OSSL_PARAM *pubkey_param = NULL; ++ const void *pubkey = NULL; ++ size_t pubkey_len; ++ int nid; + #endif /* OPENSSL_VERSION_NUMBER */ +- return SSH_ERROR; +- } + +- curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); +-/* 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 +- */ +-#if 1 +- if (curve == SSH_ERROR) { +- BN_CTX_free(ctx); +- return SSH_ERROR; +- } ++ curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ if (curve == SSH_ERROR) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to get curve name"); ++ return NULL; ++ } + +- key = EC_KEY_new_by_curve_name(curve); ++ key = EC_KEY_new_by_curve_name(curve); + #else +- if (curve == NULL) { +- return SSH_ERROR; +- } +- +- key = EVP_EC_gen(curve); +-#endif /* OPENSSL_VERSION_NUMBER */ ++ if (curve == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to get curve name"); ++ return NULL; ++ } + +- if (key == NULL) { +-/* 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 +- */ +-#if 1 +- BN_CTX_free(ctx); ++ key = EVP_EC_gen(curve); + #endif /* OPENSSL_VERSION_NUMBER */ +- return SSH_ERROR; +- } +- +-/* 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 +- */ +-#if 1 +- group = EC_KEY_get0_group(key); +- +- EC_KEY_generate_key(key); ++ if (key == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to generate key"); ++ return NULL; ++ } + +- pubkey=EC_KEY_get0_public_key(key); +- len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, +- NULL,0,ctx); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ group = EC_KEY_get0_group(key); + +- client_pubkey = ssh_string_new(len); +- if (client_pubkey == NULL) { +- BN_CTX_free(ctx); +- EC_KEY_free(key); +- return SSH_ERROR; +- } ++ EC_KEY_generate_key(key); + +- EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED, +- ssh_string_data(client_pubkey),len,ctx); +- BN_CTX_free(ctx); ++ point = EC_KEY_get0_public_key(key); + #else +- rc = EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &out_params); +- if (rc != 1) { +- EVP_PKEY_free(key); +- return SSH_ERROR; +- } ++ rc = EVP_PKEY_todata(key, EVP_PKEY_PUBLIC_KEY, &out_params); ++ if (rc != 1) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to export public key"); ++ EVP_PKEY_free(key); ++ return NULL; ++ } + +- pubkey_param = OSSL_PARAM_locate_const(out_params, OSSL_PKEY_PARAM_PUB_KEY); +- if (pubkey_param == NULL) { +- EVP_PKEY_free(key); +- OSSL_PARAM_free(out_params); +- return SSH_ERROR; +- } ++ pubkey_param = OSSL_PARAM_locate_const(out_params, OSSL_PKEY_PARAM_PUB_KEY); ++ if (pubkey_param == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to find public key"); ++ EVP_PKEY_free(key); ++ OSSL_PARAM_free(out_params); ++ return NULL; ++ } + +- rc = OSSL_PARAM_get_octet_string_ptr(pubkey_param, +- (const void**)&pubkey, +- &pubkey_len); +- if (rc != 1) { +- OSSL_PARAM_free(out_params); +- EVP_PKEY_free(key); +- return SSH_ERROR; +- } ++ rc = OSSL_PARAM_get_octet_string_ptr(pubkey_param, ++ (const void**)&pubkey, ++ &pubkey_len); ++ OSSL_PARAM_free(out_params); ++ if (rc != 1) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to read public key"); ++ EVP_PKEY_free(key); ++ return NULL; ++ } + +- client_pubkey = ssh_string_new(pubkey_len); +- if (client_pubkey == NULL) { +- OSSL_PARAM_free(out_params); +- EVP_PKEY_free(key); +- return SSH_ERROR; +- } ++ /* Convert the data to low-level representation */ ++ nid = pki_key_ecgroup_name_to_nid(curve); ++ group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, nid); ++ point = EC_POINT_new(group); ++ rc = EC_POINT_oct2point(group, (EC_POINT *)point, pubkey, pubkey_len, NULL); ++ if (group == NULL || point == NULL || rc != 1) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to export public key"); ++ EVP_PKEY_free(key); ++ return NULL; ++ } + +- memcpy(ssh_string_data(client_pubkey), pubkey, pubkey_len); +- OSSL_PARAM_free(out_params); + #endif /* OPENSSL_VERSION_NUMBER */ +- +- rc = ssh_buffer_add_ssh_string(session->out_buffer,client_pubkey); +- if (rc < 0) { +-/* 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 +- */ +-#if 1 +- EC_KEY_free(key); ++ pubkey_string = pki_key_make_ecpoint_string(group, point); ++ if (pubkey_string == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, "Failed to convert public key"); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY_free(key); + #else +- EVP_PKEY_free(key); ++ EVP_PKEY_free(key); + #endif /* OPENSSL_VERSION_NUMBER */ +- SSH_STRING_FREE(client_pubkey); +- return SSH_ERROR; +- } ++ return NULL; ++ } ++ session->next_crypto->ecdh_privkey = key; ++ return pubkey_string; ++} + +- session->next_crypto->ecdh_privkey = key; +- session->next_crypto->ecdh_client_pubkey = client_pubkey; ++/** @internal ++ * @brief Starts ecdh-sha2-nistp256 key exchange ++ */ ++int ssh_client_ecdh_init(ssh_session session) ++{ ++ ssh_string client_pubkey = NULL; ++ int rc; + +- /* register the packet callbacks */ +- ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); +- session->dh_handshake_state = DH_STATE_INIT_SENT; ++ rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT); ++ if (rc < 0) { ++ return SSH_ERROR; ++ } + +- rc = ssh_packet_send(session); ++ client_pubkey = ssh_ecdh_generate(session); ++ if (client_pubkey == NULL) { ++ return SSH_ERROR; ++ } + +- return rc; ++ rc = ssh_buffer_add_ssh_string(session->out_buffer, client_pubkey); ++ if (rc < 0) { ++ return SSH_ERROR; ++ } ++ ++ session->next_crypto->ecdh_client_pubkey = client_pubkey; ++ ++ /* register the packet callbacks */ ++ ssh_packet_set_callbacks(session, &ssh_ecdh_client_callbacks); ++ session->dh_handshake_state = DH_STATE_INIT_SENT; ++ ++ rc = ssh_packet_send(session); ++ ++ return rc; + } + +-int ecdh_build_k(ssh_session session) { ++int ecdh_build_k(ssh_session session) ++{ + struct ssh_crypto_struct *next_crypto = session->next_crypto; +-/* 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 +- */ +- #if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + const EC_GROUP *group = EC_KEY_get0_group(next_crypto->ecdh_privkey); +- EC_POINT *pubkey; +- void *buffer; ++ EC_POINT *pubkey = NULL; ++ void *buffer = NULL; + int rc; + int len = (EC_GROUP_get_degree(group) + 7) / 8; + bignum_CTX ctx = bignum_ctx_new(); +@@ -292,11 +257,13 @@ int ecdh_build_k(ssh_session session) { + bignum_bin2bn(buffer, len, &next_crypto->shared_secret); + free(buffer); + #else ++ const char *curve = NULL; + EVP_PKEY *pubkey = NULL; + void *secret = NULL; + size_t secret_len; + int rc; +- OSSL_PARAM params[2]; ++ OSSL_PARAM params[3]; ++ ssh_string peer_pubkey = NULL; + EVP_PKEY_CTX *dh_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, + next_crypto->ecdh_privkey, + NULL); +@@ -324,15 +291,18 @@ int ecdh_build_k(ssh_session session) { + } + + if (session->server) { +- params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, +- ssh_string_data(next_crypto->ecdh_client_pubkey), +- ssh_string_len(next_crypto->ecdh_client_pubkey)); ++ peer_pubkey = next_crypto->ecdh_client_pubkey; + } else { +- params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, +- ssh_string_data(next_crypto->ecdh_server_pubkey), +- ssh_string_len(next_crypto->ecdh_server_pubkey)); ++ peer_pubkey = next_crypto->ecdh_server_pubkey; + } +- params[1] = OSSL_PARAM_construct_end(); ++ params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, ++ ssh_string_data(peer_pubkey), ++ ssh_string_len(peer_pubkey)); ++ curve = ecdh_kex_type_to_curve(next_crypto->kex_type); ++ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, ++ (char *)curve, ++ strlen(curve)); ++ params[2] = OSSL_PARAM_construct_end(); + + rc = EVP_PKEY_fromdata(pubkey_ctx, &pubkey, EVP_PKEY_PUBLIC_KEY, params); + if (rc != 1) { +@@ -374,11 +344,7 @@ int ecdh_build_k(ssh_session session) { + free(secret); + #endif /* OPENSSL_VERSION_NUMBER */ + if (next_crypto->shared_secret == NULL) { +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY_free(next_crypto->ecdh_privkey); + #else + EVP_PKEY_free(next_crypto->ecdh_privkey); +@@ -386,11 +352,7 @@ int ecdh_build_k(ssh_session session) { + next_crypto->ecdh_privkey = NULL; + return -1; + } +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY_free(next_crypto->ecdh_privkey); + #else + EVP_PKEY_free(next_crypto->ecdh_privkey); +@@ -413,29 +375,11 @@ int ecdh_build_k(ssh_session session) { + /** @brief Handle a SSH_MSG_KEXDH_INIT packet (server) and send a + * SSH_MSG_KEXDH_REPLY + */ +-SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ ++SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init) ++{ + /* ECDH keys */ +- ssh_string q_c_string; +- ssh_string q_s_string; +-/* 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 +- */ +-#if 1 +- EC_KEY *ecdh_key; +- const EC_GROUP *group; +- const EC_POINT *ecdh_pubkey; +- bignum_CTX ctx; +- int curve; +- int len; +-#else +- EVP_PKEY *ecdh_key = NULL; +- const void *pubkey_ptr = NULL; +- size_t len; +- OSSL_PARAM *params = NULL; +- const OSSL_PARAM *pubkey = NULL; +- const char *curve = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++ ssh_string q_c_string = NULL; ++ ssh_string q_s_string = NULL; + /* SSH host keys (rsa,dsa,ecdsa) */ + ssh_key privkey; + enum ssh_digest_e digest = SSH_DIGEST_AUTO; +@@ -445,125 +389,22 @@ SSH_PACKET_CALLBACK(ssh_packet_server_ecdh_init){ + (void)type; + (void)user; + ++ SSH_LOG(SSH_LOG_TRACE, "Processing SSH_MSG_KEXDH_INIT"); ++ + ssh_packet_remove_callbacks(session, &ssh_ecdh_server_callbacks); + /* Extract the client pubkey from the init packet */ + q_c_string = ssh_buffer_get_ssh_string(packet); + if (q_c_string == NULL) { +- ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); ++ ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet"); + goto error; + } + session->next_crypto->ecdh_client_pubkey = q_c_string; + +- curve = ecdh_kex_type_to_curve(session->next_crypto->kex_type); +-/* 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 +- */ +-#if 1 +- if (curve == SSH_ERROR) { +- return SSH_ERROR; +- } +-#else +- if (curve == NULL) { +- return SSH_ERROR; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ +- +-/* 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 +- */ +-#if 1 +- ecdh_key = EC_KEY_new_by_curve_name(curve); +-#else +- ecdh_key = EVP_EC_gen(curve); +-#endif /* OPENSSL_VERSION_NUMBER */ +- if (ecdh_key == NULL) { +- ssh_set_error_oom(session); +- goto error; +- } +- +-/* 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 +- */ +-#if 1 +- /* Build server's keypair */ +- ctx = BN_CTX_new(); +- if (ctx == NULL) { +- EC_KEY_free(ecdh_key); +- return SSH_ERROR; +- } +- +- group = EC_KEY_get0_group(ecdh_key); +- EC_KEY_generate_key(ecdh_key); +- +- ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key); +- len = EC_POINT_point2oct(group, +- ecdh_pubkey, +- POINT_CONVERSION_UNCOMPRESSED, +- NULL, +- 0, +- ctx); +-#else +- rc = EVP_PKEY_todata(ecdh_key, EVP_PKEY_PUBLIC_KEY, ¶ms); +- if (rc != 1) { +- EVP_PKEY_free(ecdh_key); +- return SSH_ERROR; +- } +- +- pubkey = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); +- if (pubkey == NULL) { +- OSSL_PARAM_free(params); +- EVP_PKEY_free(ecdh_key); +- return SSH_ERROR; +- } +- +- rc = OSSL_PARAM_get_octet_string_ptr(pubkey, &pubkey_ptr, &len); +- if (rc != 1) { +- OSSL_PARAM_free(params); +- EVP_PKEY_free(ecdh_key); +- return SSH_ERROR; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ +- q_s_string = ssh_string_new(len); ++ q_s_string = ssh_ecdh_generate(session); + if (q_s_string == NULL) { +-/* 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 +- */ +-#if 1 +- EC_KEY_free(ecdh_key); +- BN_CTX_free(ctx); +-#else +- EVP_PKEY_free(ecdh_key); +-#endif /* OPENSSL_VERSION_NUMBER */ + goto error; + } + +-/* 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 +- */ +-#if 1 +- EC_POINT_point2oct(group, +- ecdh_pubkey, +- POINT_CONVERSION_UNCOMPRESSED, +- ssh_string_data(q_s_string), +- len, +- ctx); +- BN_CTX_free(ctx); +-#else +- if (memcpy(ssh_string_data(q_s_string), pubkey_ptr, len)) { +- OSSL_PARAM_free(params); +- EVP_PKEY_free(ecdh_key); +- return SSH_ERROR; +- } +- +- OSSL_PARAM_free(params); +-#endif /* OPENSSL_VERSION_NUMBER */ +- +- session->next_crypto->ecdh_privkey = ecdh_key; + session->next_crypto->ecdh_server_pubkey = q_s_string; + + /* build k and session_id */ +diff --git a/src/legacy.c b/src/legacy.c +index 7b165dbe..4c2c0052 100644 +--- a/src/legacy.c ++++ b/src/legacy.c +@@ -83,20 +83,20 @@ int ssh_userauth_pubkey(ssh_session session, + key->type = privatekey->type; + key->type_c = ssh_key_type_to_char(key->type); + key->flags = SSH_KEY_FLAG_PRIVATE|SSH_KEY_FLAG_PUBLIC; +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = privatekey->dsa_priv; + key->rsa = privatekey->rsa_priv; + #else + key->key = privatekey->key_priv; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + rc = ssh_userauth_publickey(session, username, key); +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = NULL; + key->rsa = NULL; + #else + key->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + ssh_key_free(key); + + return rc; +@@ -362,22 +362,14 @@ void publickey_free(ssh_public_key key) { + #ifdef HAVE_LIBGCRYPT + gcry_sexp_release(key->dsa_pub); + #elif defined HAVE_LIBCRYPTO +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA_free(key->dsa_pub); +-#else + EVP_PKEY_free(key->key_pub); +-#endif /* OPENSSL_VERSION_NUMBER */ + #endif /* HAVE_LIBGCRYPT */ + break; + case SSH_KEYTYPE_RSA: + #ifdef HAVE_LIBGCRYPT + gcry_sexp_release(key->rsa_pub); + #elif defined HAVE_LIBCRYPTO +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- RSA_free(key->rsa_pub); +-#else + EVP_PKEY_free(key->key_pub); +-#endif /* OPENSSL_VERSION_NUMBER */ + #elif defined HAVE_LIBMBEDCRYPTO + mbedtls_pk_free(key->rsa_pub); + SAFE_FREE(key->rsa_pub); +@@ -403,20 +395,20 @@ ssh_public_key publickey_from_privatekey(ssh_private_key prv) { + privkey->type = prv->type; + privkey->type_c = ssh_key_type_to_char(privkey->type); + privkey->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + privkey->dsa = prv->dsa_priv; + privkey->rsa = prv->rsa_priv; + #else + privkey->key = prv->key_priv; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + rc = ssh_pki_export_privkey_to_pubkey(privkey, &pubkey); +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + privkey->dsa = NULL; + privkey->rsa = NULL; + #else + privkey->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + ssh_key_free(privkey); + if (rc < 0) { + return NULL; +@@ -462,7 +454,7 @@ ssh_private_key privatekey_from_file(ssh_session session, + } + + privkey->type = key->type; +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + privkey->dsa_priv = key->dsa; + privkey->rsa_priv = key->rsa; + +@@ -472,7 +464,7 @@ ssh_private_key privatekey_from_file(ssh_session session, + privkey->key_priv = key->key; + + key->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + ssh_key_free(key); + +@@ -494,12 +486,7 @@ void privatekey_free(ssh_private_key prv) { + gcry_sexp_release(prv->dsa_priv); + gcry_sexp_release(prv->rsa_priv); + #elif defined HAVE_LIBCRYPTO +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA_free(prv->dsa_priv); +- RSA_free(prv->rsa_priv); +-#else + EVP_PKEY_free(prv->key_priv); +-#endif /* OPENSSL_VERSION_NUMBER */ + #elif defined HAVE_LIBMBEDCRYPTO + mbedtls_pk_free(prv->rsa_priv); + SAFE_FREE(prv->rsa_priv); +@@ -564,7 +551,7 @@ ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) { + pubkey->type = key->type; + pubkey->type_c = key->type_c; + +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + pubkey->dsa_pub = key->dsa; + key->dsa = NULL; + pubkey->rsa_pub = key->rsa; +@@ -572,7 +559,7 @@ ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s) { + #else + pubkey->key_pub = key->key; + key->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + ssh_key_free(key); + +@@ -596,24 +583,24 @@ ssh_string publickey_to_string(ssh_public_key pubkey) { + key->type = pubkey->type; + key->type_c = pubkey->type_c; + +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = pubkey->dsa_pub; + key->rsa = pubkey->rsa_pub; + #else + key->key = pubkey->key_pub; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + rc = ssh_pki_export_pubkey_blob(key, &key_blob); + if (rc < 0) { + key_blob = NULL; + } + +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + key->dsa = NULL; + key->rsa = NULL; + #else + key->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + ssh_key_free(key); + + return key_blob; +diff --git a/src/libcrypto-compat.c b/src/libcrypto-compat.c +deleted file mode 100644 +index 33b8dffd..00000000 +--- a/src/libcrypto-compat.c ++++ /dev/null +@@ -1,305 +0,0 @@ +-/* +- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. +- * +- * Licensed under the OpenSSL license (the "License"). You may not use +- * this file except in compliance with the License. You can obtain a copy +- * in the file LICENSE in the source distribution or at +- * https://www.openssl.org/source/license.html +- */ +- +-#include "config.h" +- +-#include +-#include "libcrypto-compat.h" +- +-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +-{ +- /* If the fields n and e in r are NULL, the corresponding input +- * parameters MUST be non-NULL for n and e. d may be +- * left NULL (in case only the public key is used). +- */ +- if ((r->n == NULL && n == NULL) +- || (r->e == NULL && e == NULL)) +- return 0; +- +- if (n != NULL) { +- BN_free(r->n); +- r->n = n; +- } +- if (e != NULL) { +- BN_free(r->e); +- r->e = e; +- } +- if (d != NULL) { +- BN_free(r->d); +- r->d = d; +- } +- +- return 1; +-} +- +-int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +-{ +- /* If the fields p and q in r are NULL, the corresponding input +- * parameters MUST be non-NULL. +- */ +- if ((r->p == NULL && p == NULL) +- || (r->q == NULL && q == NULL)) +- return 0; +- +- if (p != NULL) { +- BN_free(r->p); +- r->p = p; +- } +- if (q != NULL) { +- BN_free(r->q); +- r->q = q; +- } +- +- return 1; +-} +- +-int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +-{ +- /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input +- * parameters MUST be non-NULL. +- */ +- if ((r->dmp1 == NULL && dmp1 == NULL) +- || (r->dmq1 == NULL && dmq1 == NULL) +- || (r->iqmp == NULL && iqmp == NULL)) +- return 0; +- +- if (dmp1 != NULL) { +- BN_free(r->dmp1); +- r->dmp1 = dmp1; +- } +- if (dmq1 != NULL) { +- BN_free(r->dmq1); +- r->dmq1 = dmq1; +- } +- if (iqmp != NULL) { +- BN_free(r->iqmp); +- r->iqmp = iqmp; +- } +- +- return 1; +-} +- +-void RSA_get0_key(const RSA *r, +- const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +-{ +- if (n != NULL) +- *n = r->n; +- if (e != NULL) +- *e = r->e; +- if (d != NULL) +- *d = r->d; +-} +- +-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +-{ +- if (p != NULL) +- *p = r->p; +- if (q != NULL) +- *q = r->q; +-} +- +-void RSA_get0_crt_params(const RSA *r, +- const BIGNUM **dmp1, const BIGNUM **dmq1, +- const BIGNUM **iqmp) +-{ +- if (dmp1 != NULL) +- *dmp1 = r->dmp1; +- if (dmq1 != NULL) +- *dmq1 = r->dmq1; +- if (iqmp != NULL) +- *iqmp = r->iqmp; +-} +- +-void DSA_get0_pqg(const DSA *d, +- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +-{ +- if (p != NULL) +- *p = d->p; +- if (q != NULL) +- *q = d->q; +- if (g != NULL) +- *g = d->g; +-} +- +-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +-{ +- /* If the fields p, q and g in d are NULL, the corresponding input +- * parameters MUST be non-NULL. +- */ +- if ((d->p == NULL && p == NULL) +- || (d->q == NULL && q == NULL) +- || (d->g == NULL && g == NULL)) +- return 0; +- +- if (p != NULL) { +- BN_free(d->p); +- d->p = p; +- } +- if (q != NULL) { +- BN_free(d->q); +- d->q = q; +- } +- if (g != NULL) { +- BN_free(d->g); +- d->g = g; +- } +- +- return 1; +-} +- +-void DSA_get0_key(const DSA *d, +- const BIGNUM **pub_key, const BIGNUM **priv_key) +-{ +- if (pub_key != NULL) +- *pub_key = d->pub_key; +- if (priv_key != NULL) +- *priv_key = d->priv_key; +-} +- +-int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +-{ +- /* If the field pub_key in d is NULL, the corresponding input +- * parameters MUST be non-NULL. The priv_key field may +- * be left NULL. +- */ +- if (d->pub_key == NULL && pub_key == NULL) +- return 0; +- +- if (pub_key != NULL) { +- BN_free(d->pub_key); +- d->pub_key = pub_key; +- } +- if (priv_key != NULL) { +- BN_free(d->priv_key); +- d->priv_key = priv_key; +- } +- +- return 1; +-} +- +-void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +-{ +- if (pr != NULL) +- *pr = sig->r; +- if (ps != NULL) +- *ps = sig->s; +-} +- +-int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +-{ +- if (r == NULL || s == NULL) +- return 0; +- BN_clear_free(sig->r); +- BN_clear_free(sig->s); +- sig->r = r; +- sig->s = s; +- return 1; +-} +- +-void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +-{ +- if (pr != NULL) +- *pr = sig->r; +- if (ps != NULL) +- *ps = sig->s; +-} +- +-int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +-{ +- if (r == NULL || s == NULL) +- return 0; +- BN_clear_free(sig->r); +- BN_clear_free(sig->s); +- sig->r = r; +- sig->s = s; +- return 1; +-} +- +-EVP_MD_CTX *EVP_MD_CTX_new(void) +-{ +- EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX)); +- if (ctx != NULL) { +- EVP_MD_CTX_init(ctx); +- } +- return ctx; +-} +- +-void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +-{ +- EVP_MD_CTX_cleanup(ctx); +- OPENSSL_free(ctx); +-} +- +-void DH_get0_pqg(const DH *dh, +- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +-{ +- if (p) { +- *p = dh->p; +- } +- if (q) { +- *q = NULL; +- } +- if (g) { +- *g = dh->g; +- } +-} +- +-int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +-{ +- if (p) { +- if (dh->p) { +- BN_free(dh->p); +- } +- dh->p = p; +- } +- if (g) { +- if (dh->g) { +- BN_free(dh->g); +- } +- dh->g = g; +- } +- return 1; +-} +- +-void DH_get0_key(const DH *dh, +- const BIGNUM **pub_key, const BIGNUM **priv_key) +-{ +- if (pub_key) { +- *pub_key = dh->pub_key; +- } +- if (priv_key) { +- *priv_key = dh->priv_key; +- } +-} +- +-int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +-{ +- if (pub_key) { +- if (dh->pub_key) { +- BN_free(dh->pub_key); +- } +- dh->pub_key = pub_key; +- } +- if (priv_key) { +- if (dh->priv_key) { +- BN_free(dh->priv_key); +- } +- dh->priv_key = priv_key; +- } +- return 1; +-} +- +-const char *OpenSSL_version(int type) +-{ +- return SSLeay_version(type); +-} +-unsigned long OpenSSL_version_num(void) +-{ +- return SSLeay(); +-} +diff --git a/src/libcrypto-compat.h b/src/libcrypto-compat.h +index 48e30bd1..0f2dc184 100644 +--- a/src/libcrypto-compat.h ++++ b/src/libcrypto-compat.h +@@ -7,47 +7,8 @@ + #define NISTP384 "P-384" + #define NISTP521 "P-521" + +-#if OPENSSL_VERSION_NUMBER < 0x10100000L +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +-int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +-int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +-void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +-void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +-void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp); +- +-void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +-int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +-void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); +-int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); +- +-void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +-int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); +- +-void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +-int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); +- +-EVP_MD_CTX *EVP_MD_CTX_new(void); +-void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +- +-void DH_get0_pqg(const DH *dh, +- const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +-int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +-void DH_get0_key(const DH *dh, +- const BIGNUM **pub_key, const BIGNUM **priv_key); +-int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +- +-const char *OpenSSL_version(int type); +-unsigned long OpenSSL_version_num(void); +- ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++#define EVP_PKEY_eq EVP_PKEY_cmp + #endif /* OPENSSL_VERSION_NUMBER */ + + #endif /* LIBCRYPTO_COMPAT_H */ +diff --git a/src/libcrypto.c b/src/libcrypto.c +index 4f945d90..7b9ffc00 100644 +--- a/src/libcrypto.c ++++ b/src/libcrypto.c +@@ -85,7 +85,6 @@ + + static int libcrypto_initialized = 0; + +-static ENGINE *engine = NULL; + + void ssh_reseed(void){ + #ifndef _WIN32 +@@ -95,6 +94,9 @@ void ssh_reseed(void){ + #endif + } + ++#ifndef WITH_PKCS11_PROVIDER ++static ENGINE *engine = NULL; ++ + ENGINE *pki_get_engine(void) + { + int ok; +@@ -124,6 +126,7 @@ ENGINE *pki_get_engine(void) + } + return engine; + } ++#endif /* WITH_PKCS11_PROVIDER */ + + #ifdef HAVE_OPENSSL_EVP_KDF_CTX + #if OPENSSL_VERSION_NUMBER < 0x30000000L +@@ -1460,57 +1463,59 @@ int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, + * + * @return 0 on success, -1 on error + */ +-static int evp_dup_pkey(const char* name, const ssh_key key, int demote, +- ssh_key new_key) ++static int ++evp_dup_pkey(const char *name, const ssh_key key, int demote, ssh_key new_key) + { + int rc; +- EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); ++ EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM *params = NULL; + +- if (ctx == NULL) { +- return -1; +- } +- +- if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { +- rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms); ++ /* The simple case -- just reference the existing key */ ++ if (!demote || (key->flags & SSH_KEY_FLAG_PRIVATE) == 0) { ++ rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { +- EVP_PKEY_CTX_free(ctx); + return -1; + } ++ new_key->key = key->key; ++ return SSH_OK; ++ } + +- rc = EVP_PKEY_fromdata_init(ctx); +- if (rc != 1) { +- EVP_PKEY_CTX_free(ctx); +- OSSL_PARAM_free(params); +- return -1; +- } ++ /* demote == 1 */ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL); ++ if (ctx == NULL) { ++ return -1; ++ } + +- rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_KEYPAIR, params); +- if (rc != 1) { +- EVP_PKEY_CTX_free(ctx); +- OSSL_PARAM_free(params); +- return -1; +- } +- } else { +- rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); +- if (rc != 1) { +- EVP_PKEY_CTX_free(ctx); +- return -1; +- } ++ rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); ++ if (rc != 1) { ++ EVP_PKEY_CTX_free(ctx); ++ return -1; ++ } + +- rc = EVP_PKEY_fromdata_init(ctx); +- if (rc != 1) { ++ if (strcmp(name, "EC") == 0) { ++ OSSL_PARAM *locate_param = NULL; ++ /* For ECC keys provided by engine or provider, we need to have the ++ * explicit public part available, otherwise the key will not be ++ * usable */ ++ locate_param = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY); ++ if (locate_param == NULL) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + return -1; + } ++ } ++ rc = EVP_PKEY_fromdata_init(ctx); ++ if (rc != 1) { ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_free(params); ++ return -1; ++ } + +- rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_PUBLIC_KEY, params); +- if (rc != 1) { +- EVP_PKEY_CTX_free(ctx); +- OSSL_PARAM_free(params); +- return -1; +- } ++ rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_PUBLIC_KEY, params); ++ if (rc != 1) { ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_free(params); ++ return -1; + } + + OSSL_PARAM_free(params); +@@ -1535,4 +1540,54 @@ int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote) + } + #endif /* OPENSSL_VERSION_NUMBER */ + ++ssh_string ++pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p) ++{ ++ ssh_string s = NULL; ++ size_t len; ++ ++ len = EC_POINT_point2oct(g, ++ p, ++ POINT_CONVERSION_UNCOMPRESSED, ++ NULL, ++ 0, ++ NULL); ++ if (len == 0) { ++ return NULL; ++ } ++ ++ s = ssh_string_new(len); ++ if (s == NULL) { ++ return NULL; ++ } ++ ++ len = EC_POINT_point2oct(g, ++ p, ++ POINT_CONVERSION_UNCOMPRESSED, ++ ssh_string_data(s), ++ ssh_string_len(s), ++ NULL); ++ if (len != ssh_string_len(s)) { ++ SSH_STRING_FREE(s); ++ return NULL; ++ } ++ ++ return s; ++} ++ ++int pki_key_ecgroup_name_to_nid(const char *group) ++{ ++ if (strcmp(group, NISTP256) == 0 || ++ strcmp(group, "secp256r1") == 0 || ++ strcmp(group, "prime256v1") == 0) { ++ return NID_X9_62_prime256v1; ++ } else if (strcmp(group, NISTP384) == 0 || ++ strcmp(group, "secp384r1") == 0) { ++ return NID_secp384r1; ++ } else if (strcmp(group, NISTP521) == 0 || ++ strcmp(group, "secp521r1") == 0) { ++ return NID_secp521r1; ++ } ++ return -1; ++} + #endif /* LIBCRYPTO */ +diff --git a/src/pki.c b/src/pki.c +index a7c84c5e..b606ae99 100644 +--- a/src/pki.c ++++ b/src/pki.c +@@ -1114,7 +1114,7 @@ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) + pub->type = tmp->type; + pub->type_c = tmp->type_c; + +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + pub->dsa_pub = tmp->dsa; + tmp->dsa = NULL; + pub->rsa_pub = tmp->rsa; +@@ -1122,7 +1122,7 @@ ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key) + #else + pub->key_pub = tmp->key; + tmp->key = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + ssh_key_free(tmp); + +@@ -1140,12 +1140,12 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) + } + + privkey->type = key->type; +-#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L ++#ifndef HAVE_LIBCRYPTO + privkey->dsa_priv = key->dsa; + privkey->rsa_priv = key->rsa; + #else + privkey->key_priv = key->key; +-#endif /* OPENSSL_VERSION_NUMBER */ ++#endif /* HAVE_LIBCRYPTO */ + + return privkey; + } +diff --git a/src/pki_crypto.c b/src/pki_crypto.c +index 5b0d7ded..d3e98ba6 100644 +--- a/src/pki_crypto.c ++++ b/src/pki_crypto.c +@@ -42,6 +42,10 @@ + #include + #include + #include ++#if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER) ++#include ++#include ++#endif + #endif /* OPENSSL_VERSION_NUMBER */ + + #ifdef HAVE_OPENSSL_EC_H +@@ -91,37 +95,20 @@ void pki_key_clean(ssh_key key) + { + if (key == NULL) + return; +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA_free(key->dsa); +- key->dsa = NULL; +- RSA_free(key->rsa); +- key->rsa = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ +-#ifdef HAVE_OPENSSL_ECC +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move whole HAVE_OPENSSL_ECC into #if < 0x3 above +- */ +-#if 1 +- EC_KEY_free(key->ecdsa); +- key->ecdsa = NULL; +-#endif +-#endif /* HAVE_OPENSSL_ECC */ + EVP_PKEY_free(key->key); + key->key = NULL; + } + + #ifdef HAVE_OPENSSL_ECC +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + static int pki_key_ecdsa_to_nid(EC_KEY *k) + { + const EC_GROUP *g = EC_KEY_get0_group(k); + int nid; + ++ if (g == NULL) { ++ return -1; ++ } + nid = EC_GROUP_get_curve_name(g); + if (nid) { + return nid; +@@ -133,34 +120,22 @@ static int pki_key_ecdsa_to_nid(EC_KEY *k) + static int pki_key_ecdsa_to_nid(EVP_PKEY *k) + { + char gname[25] = { 0 }; +- int nid, rc; +- +- rc = EVP_PKEY_get_utf8_string_param(k, "group", gname, 25, NULL); +- if (rc != 1) +- return -1; ++ int rc; + +- if (strcmp(gname, NISTP256) == 0 +- || strcmp(gname, "secp256r1") == 0 +- || strcmp(gname, "prime256v1") == 0) { +- nid = NID_X9_62_prime256v1; +- } else if (strcmp(gname, NISTP384) == 0 +- || strcmp(gname, "secp384r1") == 0) { +- nid = NID_secp384r1; +- } else if (strcmp(gname, NISTP521) == 0 +- || strcmp(gname, "secp521r1") == 0) { +- nid = NID_secp521r1; +- } else ++ rc = EVP_PKEY_get_utf8_string_param(k, ++ OSSL_PKEY_PARAM_GROUP_NAME, ++ gname, ++ 25, ++ NULL); ++ if (rc != 1) { + return -1; ++ } + +- return nid; ++ return pki_key_ecgroup_name_to_nid(gname); + } + #endif /* OPENSSL_VERSION_NUMBER */ + +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EC_KEY *k) + #else + static enum ssh_keytypes_e pki_key_ecdsa_to_key_type(EVP_PKEY *k) +@@ -227,160 +202,139 @@ int pki_key_ecdsa_nid_from_name(const char *name) + return -1; + } + +-/* 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 +- */ +-#if 1 +-static ssh_string make_ecpoint_string(const EC_GROUP *g, +- const EC_POINT *p) +-{ +- ssh_string s; +- size_t len; +- +- len = EC_POINT_point2oct(g, +- p, +- POINT_CONVERSION_UNCOMPRESSED, +- NULL, +- 0, +- NULL); +- if (len == 0) { +- return NULL; +- } +- +- s = ssh_string_new(len); +- if (s == NULL) { +- return NULL; +- } +- +- len = EC_POINT_point2oct(g, +- p, +- POINT_CONVERSION_UNCOMPRESSED, +- ssh_string_data(s), +- ssh_string_len(s), +- NULL); +- if (len != ssh_string_len(s)) { +- SSH_STRING_FREE(s); +- return NULL; +- } +- +- return s; +-} +-#endif /* OPENSSL_VERSION_NUMBER */ +- + int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp) + { +-/* 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 +- */ +-#if 1 ++ int rc = 0; ++ BIGNUM *bexp = NULL; ++ ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_POINT *p = NULL; + const EC_GROUP *g = NULL; +- int ok; +- BIGNUM *bexp = NULL; ++ EC_KEY *ecdsa = NULL; + #else +- int rc; +- const BIGNUM *expb; + const char *group_name = OSSL_EC_curve_nid2name(nid); + OSSL_PARAM_BLD *param_bld = NULL; + + if (group_name == NULL) { + return -1; + } +- expb = ssh_make_string_bn(exp); + #endif /* OPENSSL_VERSION_NUMBER */ + ++ bexp = ssh_make_string_bn(exp); ++ if (bexp == NULL) { ++ return -1; ++ } ++ + key->ecdsa_nid = nid; + key->type_c = pki_key_ecdsa_nid_to_name(nid); + +-/* 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 +- */ +-#if 1 +- key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); +- if (key->ecdsa == NULL) { +- return -1; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); ++ if (ecdsa == NULL) { ++ rc = -1; ++ goto cleanup; + } + +- g = EC_KEY_get0_group(key->ecdsa); ++ g = EC_KEY_get0_group(ecdsa); + + p = EC_POINT_new(g); + if (p == NULL) { +- return -1; ++ rc = -1; ++ goto cleanup; + } + +- ok = EC_POINT_oct2point(g, ++ rc = EC_POINT_oct2point(g, + p, + ssh_string_data(e), + ssh_string_len(e), + NULL); +- if (!ok) { +- EC_POINT_free(p); +- return -1; ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; + } + + /* EC_KEY_set_public_key duplicates p */ +- ok = EC_KEY_set_public_key(key->ecdsa, p); +- EC_POINT_free(p); +- if (!ok) { +- return -1; ++ rc = EC_KEY_set_public_key(ecdsa, p); ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; + } + +- bexp = ssh_make_string_bn(exp); +- if (bexp == NULL) { +- EC_KEY_free(key->ecdsa); +- return -1; +- } + /* EC_KEY_set_private_key duplicates exp */ +- ok = EC_KEY_set_private_key(key->ecdsa, bexp); +- BN_free(bexp); +- if (!ok) { +- EC_KEY_free(key->ecdsa); +- return -1; ++ rc = EC_KEY_set_private_key(ecdsa, bexp); ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; + } + +- return 0; ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ rc = -1; ++ goto cleanup; ++ } ++ ++ /* ecdsa will be freed when the EVP_PKEY key->key is freed */ ++ rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; ++ } ++ /* ssh_key is now the owner of this memory */ ++ ecdsa = NULL; ++ ++ /* set rc to 0 if everything went well */ ++ rc = 0; ++ ++cleanup: ++ EC_KEY_free(ecdsa); ++ EC_POINT_free(p); ++ BN_free(bexp); ++ return rc; + #else + param_bld = OSSL_PARAM_BLD_new(); +- if (param_bld == NULL) +- goto err; ++ if (param_bld == NULL){ ++ rc = -1; ++ goto cleanup; ++ } + + rc = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_PKEY_PARAM_GROUP_NAME, + group_name, strlen(group_name)); +- if (rc != 1) +- goto err; ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; ++ } ++ + rc = OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_PKEY_PARAM_PUB_KEY, + ssh_string_data(e), ssh_string_len(e)); +- if (rc != 1) +- goto err; +- rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, expb); +- if (rc != 1) +- goto err; ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; ++ } ++ ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, bexp); ++ if (rc != 1) { ++ rc = -1; ++ goto cleanup; ++ } + + rc = evp_build_pkey("EC", param_bld, &(key->key), EVP_PKEY_KEYPAIR); +- OSSL_PARAM_BLD_free(param_bld); + +- return rc; +-err: ++cleanup: + OSSL_PARAM_BLD_free(param_bld); +- return -1; ++ BN_free(bexp); ++ return rc; + #endif /* OPENSSL_VERSION_NUMBER */ + } + + int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) + { +-/* 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 +- */ +-#if 1 ++ int rc; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_POINT *p = NULL; + const EC_GROUP *g = NULL; ++ EC_KEY *ecdsa = NULL; + int ok; + #else +- int rc; + const char *group_name = OSSL_EC_curve_nid2name(nid); + OSSL_PARAM_BLD *param_bld; + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -388,20 +342,17 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) + key->ecdsa_nid = nid; + key->type_c = pki_key_ecdsa_nid_to_name(nid); + +-/* 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 +- */ +- #if 1 +- key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); +- if (key->ecdsa == NULL) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); ++ if (ecdsa == NULL) { + return -1; + } + +- g = EC_KEY_get0_group(key->ecdsa); ++ g = EC_KEY_get0_group(ecdsa); + + p = EC_POINT_new(g); + if (p == NULL) { ++ EC_KEY_free(ecdsa); + return -1; + } + +@@ -411,14 +362,28 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e) + ssh_string_len(e), + NULL); + if (!ok) { ++ EC_KEY_free(ecdsa); + EC_POINT_free(p); + return -1; + } + + /* EC_KEY_set_public_key duplicates p */ +- ok = EC_KEY_set_public_key(key->ecdsa, p); ++ ok = EC_KEY_set_public_key(ecdsa, p); + EC_POINT_free(p); + if (!ok) { ++ EC_KEY_free(ecdsa); ++ return -1; ++ } ++ ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ EC_KEY_free(ecdsa); ++ return -1; ++ } ++ ++ rc = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); ++ if (rc != 1) { ++ EC_KEY_free(ecdsa); + return -1; + } + +@@ -472,8 +437,9 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + const BIGNUM *p = NULL, *q = NULL, *g = NULL, + *pub_key = NULL, *priv_key = NULL; + BIGNUM *np, *nq, *ng, *npub_key, *npriv_key; +- new->dsa = DSA_new(); +- if (new->dsa == NULL) { ++ DSA *new_dsa = DSA_new(); ++ const DSA *key_dsa = EVP_PKEY_get0_DSA(key->key); ++ if (new_dsa == NULL) { + goto fail; + } + +@@ -484,11 +450,12 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + * pub_key = public key y = g^x + * priv_key = private key x + */ +- DSA_get0_pqg(key->dsa, &p, &q, &g); ++ DSA_get0_pqg(key_dsa, &p, &q, &g); + np = BN_dup(p); + nq = BN_dup(q); + ng = BN_dup(g); + if (np == NULL || nq == NULL || ng == NULL) { ++ DSA_free(new_dsa); + BN_free(np); + BN_free(nq); + BN_free(ng); +@@ -496,38 +463,58 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + } + + /* Memory management of np, nq and ng is transferred to DSA object */ +- rc = DSA_set0_pqg(new->dsa, np, nq, ng); ++ rc = DSA_set0_pqg(new_dsa, np, nq, ng); + if (rc == 0) { ++ DSA_free(new_dsa); + BN_free(np); + BN_free(nq); + BN_free(ng); + goto fail; + } + +- DSA_get0_key(key->dsa, &pub_key, &priv_key); ++ DSA_get0_key(key_dsa, &pub_key, &priv_key); + npub_key = BN_dup(pub_key); + if (npub_key == NULL) { ++ DSA_free(new_dsa); + goto fail; + } + + /* Memory management of npubkey is transferred to DSA object */ +- rc = DSA_set0_key(new->dsa, npub_key, NULL); ++ rc = DSA_set0_key(new_dsa, npub_key, NULL); + if (rc == 0) { ++ DSA_free(new_dsa); + goto fail; + } + + if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) { + npriv_key = BN_dup(priv_key); + if (npriv_key == NULL) { ++ DSA_free(new_dsa); + goto fail; + } + + /* Memory management of npriv_key is transferred to DSA object */ +- rc = DSA_set0_key(new->dsa, NULL, npriv_key); ++ rc = DSA_set0_key(new_dsa, NULL, npriv_key); + if (rc == 0) { ++ DSA_free(new_dsa); + goto fail; + } + } ++ ++ new->key = EVP_PKEY_new(); ++ if (new->key == NULL) { ++ DSA_free(new_dsa); ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_DSA(new->key, new_dsa); ++ if (rc != 1) { ++ EVP_PKEY_free(new->key); ++ DSA_free(new_dsa); ++ goto fail; ++ } ++ ++ new_dsa = NULL; + #else + rc = evp_dup_dsa_pkey(key, new, demote); + if (rc != SSH_OK) { +@@ -541,6 +528,8 @@ 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; ++ RSA *new_rsa = NULL; ++ const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key); + #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + #ifdef WITH_PKCS11_URI + /* Take the PKCS#11 keys as they are */ +@@ -554,8 +543,8 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + } + #endif /* WITH_PKCS11_URI */ + #if OPENSSL_VERSION_NUMBER < 0x30000000L +- new->rsa = RSA_new(); +- if (new->rsa == NULL) { ++ new_rsa = RSA_new(); ++ if (new_rsa == NULL) { + goto fail; + } + +@@ -569,18 +558,20 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + * dmq1 = d mod (q-1) + * iqmp = q^-1 mod p + */ +- RSA_get0_key(key->rsa, &n, &e, &d); ++ RSA_get0_key(key_rsa, &n, &e, &d); + nn = BN_dup(n); + ne = BN_dup(e); + if (nn == NULL || ne == NULL) { ++ RSA_free(new_rsa); + BN_free(nn); + BN_free(ne); + goto fail; + } + + /* Memory management of nn and ne is transferred to RSA object */ +- rc = RSA_set0_key(new->rsa, nn, ne, NULL); ++ rc = RSA_set0_key(new_rsa, nn, ne, NULL); + if (rc == 0) { ++ RSA_free(new_rsa); + BN_free(nn); + BN_free(ne); + goto fail; +@@ -593,43 +584,48 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + + nd = BN_dup(d); + if (nd == NULL) { ++ RSA_free(new_rsa); + goto fail; + } + + /* Memory management of nd is transferred to RSA object */ +- rc = RSA_set0_key(new->rsa, NULL, NULL, nd); ++ rc = RSA_set0_key(new_rsa, NULL, NULL, nd); + if (rc == 0) { ++ RSA_free(new_rsa); + goto fail; + } + + /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the + * RSA operations are much faster when these values are available. + */ +- RSA_get0_factors(key->rsa, &p, &q); ++ RSA_get0_factors(key_rsa, &p, &q); + if (p != NULL && q != NULL) { /* need to set both of them */ + np = BN_dup(p); + nq = BN_dup(q); + if (np == NULL || nq == NULL) { ++ RSA_free(new_rsa); + BN_free(np); + BN_free(nq); + goto fail; + } + + /* Memory management of np and nq is transferred to RSA object */ +- rc = RSA_set0_factors(new->rsa, np, nq); ++ rc = RSA_set0_factors(new_rsa, np, nq); + if (rc == 0) { ++ RSA_free(new_rsa); + BN_free(np); + BN_free(nq); + goto fail; + } + } + +- RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp); ++ RSA_get0_crt_params(key_rsa, &dmp1, &dmq1, &iqmp); + if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) { + ndmp1 = BN_dup(dmp1); + ndmq1 = BN_dup(dmq1); + niqmp = BN_dup(iqmp); + if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL) { ++ RSA_free(new_rsa); + BN_free(ndmp1); + BN_free(ndmq1); + BN_free(niqmp); +@@ -638,8 +634,9 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + + /* Memory management of ndmp1, ndmq1 and niqmp is transferred + * 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) { ++ RSA_free(new_rsa); + BN_free(ndmp1); + BN_free(ndmq1); + BN_free(niqmp); +@@ -647,6 +644,21 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + } + } + } ++ ++ new->key = EVP_PKEY_new(); ++ if (new->key == NULL) { ++ RSA_free(new_rsa); ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_RSA(new->key, new_rsa); ++ if (rc != 1) { ++ EVP_PKEY_free(new->key); ++ RSA_free(new_rsa); ++ goto fail; ++ } ++ ++ new_rsa = NULL; + #else + rc = evp_dup_rsa_pkey(key, new, demote); + if (rc != SSH_OK) { +@@ -668,44 +680,56 @@ ssh_key pki_key_dup(const ssh_key key, int demote) + 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + /* privkey -> pubkey */ + if (demote && ssh_key_is_private(key)) { +- const EC_POINT *p; ++ const EC_POINT *p = NULL; ++ EC_KEY *new_ecdsa = NULL, *old_ecdsa = NULL; + int ok; + +- new->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); +- if (new->ecdsa == NULL) { ++ new_ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); ++ if (new_ecdsa == NULL) { + goto fail; + } + +- p = EC_KEY_get0_public_key(key->ecdsa); ++ old_ecdsa = EVP_PKEY_get0_EC_KEY(key->key); ++ if (old_ecdsa == NULL) { ++ EC_KEY_free(new_ecdsa); ++ goto fail; ++ } ++ ++ p = EC_KEY_get0_public_key(old_ecdsa); + if (p == NULL) { ++ EC_KEY_free(new_ecdsa); ++ goto fail; ++ } ++ ++ ok = EC_KEY_set_public_key(new_ecdsa, p); ++ if (ok != 1) { ++ EC_KEY_free(new_ecdsa); + goto fail; + } + +- ok = EC_KEY_set_public_key(new->ecdsa, p); +- if (!ok) { ++ new->key = EVP_PKEY_new(); ++ if (new->key == NULL) { ++ EC_KEY_free(new_ecdsa); ++ goto fail; ++ } ++ ++ ok = EVP_PKEY_assign_EC_KEY(new->key, new_ecdsa); ++ if (ok != 1) { ++ EC_KEY_free(new_ecdsa); + goto fail; + } + } else { +- rc = EC_KEY_up_ref(key->ecdsa); ++ rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + goto fail; + } +- new->ecdsa = key->ecdsa; ++ new->key = key->key; + } + #else + rc = evp_dup_ecdsa_pkey(key, new, demote); +@@ -736,7 +760,8 @@ fail: + int pki_key_generate_rsa(ssh_key key, int parameter){ + int rc; + #if OPENSSL_VERSION_NUMBER < 0x30000000L +- BIGNUM *e; ++ BIGNUM *e = NULL; ++ RSA *key_rsa = NULL; + #else + OSSL_PARAM params[3]; + EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); +@@ -745,15 +770,34 @@ int pki_key_generate_rsa(ssh_key key, int parameter){ + + #if OPENSSL_VERSION_NUMBER < 0x30000000L + e = BN_new(); +- key->rsa = RSA_new(); ++ key_rsa = RSA_new(); ++ if (key_rsa == NULL) { ++ return SSH_ERROR; ++ } + + BN_set_word(e, 65537); +- rc = RSA_generate_key_ex(key->rsa, parameter, e, NULL); ++ rc = RSA_generate_key_ex(key_rsa, parameter, e, NULL); + + BN_free(e); + +- if (rc <= 0 || key->rsa == NULL) ++ if (rc <= 0 || key_rsa == NULL) { ++ return SSH_ERROR; ++ } ++ ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ RSA_free(key_rsa); ++ return SSH_ERROR; ++ } ++ ++ rc = EVP_PKEY_assign_RSA(key->key, key_rsa); ++ if (rc != 1) { ++ RSA_free(key_rsa); ++ EVP_PKEY_free(key->key); + return SSH_ERROR; ++ } ++ ++ key_rsa = NULL; + #else + key->key = NULL; + +@@ -785,11 +829,11 @@ int pki_key_generate_rsa(ssh_key key, int parameter){ + int pki_key_generate_dss(ssh_key key, int parameter){ + int rc; + #if OPENSSL_VERSION_NUMBER < 0x30000000L +- key->dsa = DSA_new(); +- if (key->dsa == NULL) { ++ DSA *key_dsa = DSA_new(); ++ if (key_dsa == NULL) { + return SSH_ERROR; + } +- rc = DSA_generate_parameters_ex(key->dsa, ++ rc = DSA_generate_parameters_ex(key_dsa, + parameter, + NULL, /* seed */ + 0, /* seed_len */ +@@ -797,16 +841,29 @@ int pki_key_generate_dss(ssh_key key, int parameter){ + NULL, /* h_ret */ + NULL); /* cb */ + if (rc != 1) { +- DSA_free(key->dsa); +- key->dsa = NULL; ++ DSA_free(key_dsa); + return SSH_ERROR; + } +- rc = DSA_generate_key(key->dsa); ++ rc = DSA_generate_key(key_dsa); + if (rc != 1) { +- DSA_free(key->dsa); +- key->dsa=NULL; ++ DSA_free(key_dsa); ++ return SSH_ERROR; ++ } ++ ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ DSA_free(key_dsa); + return SSH_ERROR; + } ++ ++ rc = EVP_PKEY_assign_DSA(key->key, key_dsa); ++ if (rc != 1) { ++ DSA_free(key_dsa); ++ EVP_PKEY_free(key->key); ++ return SSH_ERROR; ++ } ++ ++ key_dsa = NULL; + #else + OSSL_PARAM params[3]; + EVP_PKEY *param_key = NULL; +@@ -871,12 +928,10 @@ int pki_key_generate_dss(ssh_key key, int parameter){ + } + + #ifdef HAVE_OPENSSL_ECC +-int pki_key_generate_ecdsa(ssh_key key, int parameter) { +-/* 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 +- */ +-#if 1 ++int pki_key_generate_ecdsa(ssh_key key, int parameter) ++{ ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ EC_KEY *ecdsa = NULL; + int ok; + #else + const char *group_name = NULL; +@@ -885,33 +940,21 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) { + case 256: + key->ecdsa_nid = NID_X9_62_prime256v1; + key->type = SSH_KEYTYPE_ECDSA_P256; +-/* 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 +- */ +-#if 0 ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L + group_name = NISTP256; + #endif /* OPENSSL_VERSION_NUMBER */ + break; + case 384: + key->ecdsa_nid = NID_secp384r1; + key->type = SSH_KEYTYPE_ECDSA_P384; +-/* 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 +- */ +-#if 0 ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L + group_name = NISTP384; + #endif /* OPENSSL_VERSION_NUMBER */ + break; + case 521: + key->ecdsa_nid = NID_secp521r1; + key->type = SSH_KEYTYPE_ECDSA_P521; +-/* 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 +- */ +-#if 0 ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L + group_name = NISTP521; + #endif /* OPENSSL_VERSION_NUMBER */ + break; +@@ -920,35 +963,37 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) { + "generation", parameter); + return SSH_ERROR; + } +-/* 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 +- */ +-#if 1 +- key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); +- if (key->ecdsa == NULL) { ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid); ++ if (ecdsa == NULL) { + return SSH_ERROR; + } +-#else +- key->key = EVP_EC_gen(group_name); ++ ok = EC_KEY_generate_key(ecdsa); ++ if (!ok) { ++ EC_KEY_free(ecdsa); ++ return SSH_ERROR; ++ } ++ ++ EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE); ++ ++ key->key = EVP_PKEY_new(); + if (key->key == NULL) { ++ EC_KEY_free(ecdsa); + return SSH_ERROR; + } +-#endif /* OPENSSL_VERSION_NUMBER */ + +-/* 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 +- */ +-#if 1 +- ok = EC_KEY_generate_key(key->ecdsa); +- if (!ok) { +- EC_KEY_free(key->ecdsa); ++ ok = EVP_PKEY_assign_EC_KEY(key->key, ecdsa); ++ if (ok != 1) { + return SSH_ERROR; + } + +- EC_KEY_set_asn1_flag(key->ecdsa, OPENSSL_EC_NAMED_CURVE); ++#else ++ key->key = EVP_EC_gen(group_name); ++ if (key->key == NULL) { ++ return SSH_ERROR; ++ } + #endif /* OPENSSL_VERSION_NUMBER */ ++ + return SSH_OK; + } + #endif /* HAVE_OPENSSL_ECC */ +@@ -960,104 +1005,34 @@ int pki_key_compare(const ssh_key k1, + const ssh_key k2, + enum ssh_keycmp_e what) + { +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int rc; + (void) what; +-#endif /* OPENSSL_VERSION_NUMBER */ + + switch (k1->type) { +- case SSH_KEYTYPE_DSS: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- { +- const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2, +- *pub_key1, *pub_key2, *priv_key1, *priv_key2; +- if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) { +- return 1; +- } +- DSA_get0_pqg(k1->dsa, &p1, &q1, &g1); +- DSA_get0_pqg(k2->dsa, &p2, &q2, &g2); +- if (bignum_cmp(p1, p2) != 0) { +- return 1; +- } +- if (bignum_cmp(q1, q2) != 0) { +- return 1; +- } +- if (bignum_cmp(g1, g2) != 0) { +- return 1; +- } +- DSA_get0_key(k1->dsa, &pub_key1, &priv_key1); +- DSA_get0_key(k2->dsa, &pub_key2, &priv_key2); +- if (bignum_cmp(pub_key1, pub_key2) != 0) { +- return 1; +- } +- +- if (what == SSH_KEY_CMP_PRIVATE) { +- if (bignum_cmp(priv_key1, priv_key2) != 0) { +- return 1; +- } +- } +- break; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ +- case SSH_KEYTYPE_RSA: +- case SSH_KEYTYPE_RSA1: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- { +- const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2; +- if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) { +- return 1; +- } +- RSA_get0_key(k1->rsa, &n1, &e1, NULL); +- RSA_get0_key(k2->rsa, &n2, &e2, NULL); +- if (bignum_cmp(e1, e2) != 0) { +- return 1; +- } +- if (bignum_cmp(n1, n2) != 0) { +- return 1; +- } +- +- if (what == SSH_KEY_CMP_PRIVATE) { +- RSA_get0_factors(k1->rsa, &p1, &q1); +- RSA_get0_factors(k2->rsa, &p2, &q2); +- if (bignum_cmp(p1, p2) != 0) { +- return 1; +- } +- +- if (bignum_cmp(q1, q2) != 0) { +- return 1; +- } +- } +- break; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * delete this part of #if because it gets done below EC +- */ +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L +- rc = EVP_PKEY_eq(k1->key, k2->key); +- if (rc != 1) { +- return 1; +- } +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_ECDSA_P256: + case SSH_KEYTYPE_ECDSA_P384: + case SSH_KEYTYPE_ECDSA_P521: + case SSH_KEYTYPE_SK_ECDSA: +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + #ifdef HAVE_OPENSSL_ECC + { +- const EC_POINT *p1 = EC_KEY_get0_public_key(k1->ecdsa); +- const EC_POINT *p2 = EC_KEY_get0_public_key(k2->ecdsa); +- const EC_GROUP *g1 = EC_KEY_get0_group(k1->ecdsa); +- const EC_GROUP *g2 = EC_KEY_get0_group(k2->ecdsa); ++ const EC_KEY *ec1 = EVP_PKEY_get0_EC_KEY(k1->key); ++ const EC_KEY *ec2 = EVP_PKEY_get0_EC_KEY(k2->key); ++ const EC_POINT *p1 = NULL; ++ const EC_POINT *p2 = NULL; ++ const EC_GROUP *g1 = NULL; ++ const EC_GROUP *g2 = NULL; ++ ++ if (ec1 == NULL || ec2 == NULL) { ++ return 1; ++ } ++ ++ p1 = EC_KEY_get0_public_key(ec1); ++ p2 = EC_KEY_get0_public_key(ec2); ++ g1 = EC_KEY_get0_group(ec1); ++ g2 = EC_KEY_get0_group(ec2); + +- if (p1 == NULL || p2 == NULL) { ++ if (p1 == NULL || p2 == NULL || g1 == NULL || g2 == NULL) { + return 1; + } + +@@ -1070,8 +1045,8 @@ int pki_key_compare(const ssh_key k1, + } + + if (what == SSH_KEY_CMP_PRIVATE) { +- if (bignum_cmp(EC_KEY_get0_private_key(k1->ecdsa), +- EC_KEY_get0_private_key(k2->ecdsa))) { ++ if (bignum_cmp(EC_KEY_get0_private_key(ec1), ++ EC_KEY_get0_private_key(ec2))) { + return 1; + } + } +@@ -1079,17 +1054,14 @@ int pki_key_compare(const ssh_key k1, + } + #endif /* HAVE_OPENSSL_ECC */ + #endif /* OPENSSL_VERSION_NUMBER */ +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * else +- */ +-#if 0 ++ case SSH_KEYTYPE_DSS: ++ case SSH_KEYTYPE_RSA: ++ case SSH_KEYTYPE_RSA1: + rc = EVP_PKEY_eq(k1->key, k2->key); + if (rc != 1) { + return 1; + } + break; +-#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_ED25519: + case SSH_KEYTYPE_SK_ED25519: + /* ed25519 keys handled globally */ +@@ -1118,65 +1090,11 @@ ssh_string pki_private_key_to_pem(const ssh_key key, + + switch (key->type) { + case SSH_KEYTYPE_DSS: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- goto err; +- } +- +- rc = EVP_PKEY_set1_DSA(pkey, key->dsa); +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- goto err; +- } +- +- rc = EVP_PKEY_set1_RSA(pkey, key->rsa); +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Delete this part, because it is done below HAVE_ECC +- */ +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L +- 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; +- +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ +- case SSH_KEYTYPE_ECDSA_P256: +- case SSH_KEYTYPE_ECDSA_P384: +- case SSH_KEYTYPE_ECDSA_P521: +-#ifdef HAVE_ECC +-/* 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 +- */ +-#if 1 +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- goto err; +- } +- +- rc = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ +-#endif /* HAVE_ECC */ +-/* 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 +- */ +-#if 0 ++ case SSH_KEYTYPE_ECDSA_P256: ++ case SSH_KEYTYPE_ECDSA_P384: ++ case SSH_KEYTYPE_ECDSA_P521: + rc = EVP_PKEY_up_ref(key->key); + if (rc != 1) { + goto err; +@@ -1187,7 +1105,6 @@ ssh_string pki_private_key_to_pem(const ssh_key key, + rc = 1; + + break; +-#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_ED25519: + #ifdef HAVE_OPENSSL_ED25519 + /* In OpenSSL, the input is the private key seed only, which means +@@ -1282,14 +1199,8 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + { + BIO *mem = NULL; + #if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA *dsa = NULL; +- RSA *rsa = NULL; +-#endif /* OPENSSL_VERSION_NUMBER */ +-#ifdef HAVE_OPENSSL_ECC + EC_KEY *ecdsa = NULL; +-#else +- void *ecdsa = NULL; +-#endif /* HAVE_OPENSSL_ECC */ ++#endif /* OPENSSL_VERSION_NUMBER */ + #ifdef HAVE_OPENSSL_ED25519 + uint8_t *ed25519 = NULL; + #else +@@ -1324,37 +1235,15 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + } + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_DSA: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- 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)); +- goto fail; +- } +-#endif + type = SSH_KEYTYPE_DSS; + break; + case EVP_PKEY_RSA: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- rsa = EVP_PKEY_get1_RSA(pkey); +- if (rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing private key: %s", +- ERR_error_string(ERR_get_error(),NULL)); +- goto fail; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ + type = SSH_KEYTYPE_RSA; + break; + case EVP_PKEY_EC: + #ifdef HAVE_OPENSSL_ECC +-/* 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 +- */ +-#if 1 +- ecdsa = EVP_PKEY_get1_EC_KEY(pkey); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ecdsa = EVP_PKEY_get0_EC_KEY(pkey); + if (ecdsa == NULL) { + SSH_LOG(SSH_LOG_WARN, + "Parsing private key: %s", +@@ -1365,11 +1254,7 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + + /* pki_privatekey_type_from_string always returns P256 for ECDSA + * keys, so we need to figure out the correct type here */ +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + type = pki_key_ecdsa_to_key_type(ecdsa); + #else + type = pki_key_ecdsa_to_key_type(pkey); +@@ -1379,10 +1264,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + goto fail; + } + +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Remove these three lines +- */ + break; + #endif /* HAVE_OPENSSL_ECC */ + #ifdef HAVE_OPENSSL_ED25519 +@@ -1438,25 +1319,12 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + key->type = type; + key->type_c = ssh_key_type_to_char(type); + key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- key->dsa = dsa; +- key->rsa = rsa; +-#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 +- */ +- key->ecdsa = ecdsa; + key->ed25519_privkey = ed25519; + #ifdef HAVE_OPENSSL_ECC + if (is_ecdsa_key_type(key->type)) { +-/* 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 +- */ +-#if 1 +- key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ key->ecdsa_nid = pki_key_ecdsa_to_nid(ecdsa); + #else + key->ecdsa_nid = pki_key_ecdsa_to_nid(key->key); + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -1467,17 +1335,6 @@ ssh_key pki_private_key_from_base64(const char *b64_key, + fail: + EVP_PKEY_free(pkey); + ssh_key_free(key); +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- DSA_free(dsa); +- RSA_free(rsa); +-#endif /* OPENSSL_VERSION_NUMBER */ +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move HAVE_OPENSSL_ECC #ifdef inside the #if above +- */ +-#ifdef HAVE_OPENSSL_ECC +- EC_KEY_free(ecdsa); +-#endif + #ifdef HAVE_OPENSSL_ED25519 + SAFE_FREE(ed25519); + #endif +@@ -1499,8 +1356,8 @@ int pki_privkey_build_dss(ssh_key key, + return SSH_ERROR; + } + #else +- key->dsa = DSA_new(); +- if (key->dsa == NULL) { ++ DSA *key_dsa = DSA_new(); ++ if (key_dsa == NULL) { + return SSH_ERROR; + } + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -1518,20 +1375,31 @@ int pki_privkey_build_dss(ssh_key key, + + #if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Memory management of bp, qq and bg is transferred to DSA object */ +- rc = DSA_set0_pqg(key->dsa, bp, bq, bg); ++ rc = DSA_set0_pqg(key_dsa, bp, bq, bg); + if (rc == 0) { + goto fail; + } + + /* Memory management of bpub_key and bpriv_key is transferred to DSA object */ +- rc = DSA_set0_key(key->dsa, bpub_key, bpriv_key); ++ rc = DSA_set0_key(key_dsa, bpub_key, bpriv_key); + if (rc == 0) { + goto fail; + } + ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_DSA(key->key, key_dsa); ++ if (rc != 1) { ++ goto fail; ++ } ++ + return SSH_OK; + fail: +- DSA_free(key->dsa); ++ EVP_PKEY_free(key->key); ++ DSA_free(key_dsa); + return SSH_ERROR; + #else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, bp); +@@ -1587,8 +1455,8 @@ int pki_pubkey_build_dss(ssh_key key, + return SSH_ERROR; + } + #else +- key->dsa = DSA_new(); +- if (key->dsa == NULL) { ++ DSA *key_dsa = DSA_new(); ++ if (key_dsa == NULL) { + return SSH_ERROR; + } + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -1605,20 +1473,31 @@ int pki_pubkey_build_dss(ssh_key key, + + #if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Memory management of bp, bq and bg is transferred to DSA object */ +- rc = DSA_set0_pqg(key->dsa, bp, bq, bg); ++ rc = DSA_set0_pqg(key_dsa, bp, bq, bg); + if (rc == 0) { + goto fail; + } + + /* Memory management of npub_key is transferred to DSA object */ +- rc = DSA_set0_key(key->dsa, bpub_key, NULL); ++ rc = DSA_set0_key(key_dsa, bpub_key, NULL); + if (rc == 0) { + goto fail; + } + ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_DSA(key->key, key_dsa); ++ if (rc != 1) { ++ goto fail; ++ } ++ + return SSH_OK; + fail: +- DSA_free(key->dsa); ++ EVP_PKEY_free(key->key); ++ DSA_free(key_dsa); + return SSH_ERROR; + #else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, bp); +@@ -1659,20 +1538,25 @@ int pki_privkey_build_rsa(ssh_key key, + ssh_string n, + ssh_string e, + ssh_string d, +- UNUSED_PARAM(ssh_string iqmp), ++ ssh_string iqmp, + ssh_string p, + ssh_string q) + { + int rc; +- BIGNUM *be, *bn, *bd/*, *biqmp*/, *bp, *bq; ++ BIGNUM *be = NULL, *bn = NULL, *bd = NULL; ++ BIGNUM *biqmp = NULL, *bp = NULL, *bq = NULL; ++ BIGNUM *aux = NULL, *d_consttime = NULL; ++ BIGNUM *bdmq1 = NULL, *bdmp1 = NULL; ++ BN_CTX *ctx = NULL; ++ + #if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + if (param_bld == NULL) { + return SSH_ERROR; + } + #else +- key->rsa = RSA_new(); +- if (key->rsa == NULL) { ++ RSA *key_rsa = RSA_new(); ++ if (key_rsa == NULL) { + return SSH_ERROR; + } + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -1680,7 +1564,7 @@ int pki_privkey_build_rsa(ssh_key key, + bn = ssh_make_string_bn(n); + be = ssh_make_string_bn(e); + bd = ssh_make_string_bn(d); +- /*biqmp = ssh_make_string_bn(iqmp);*/ ++ biqmp = ssh_make_string_bn(iqmp); + bp = ssh_make_string_bn(p); + bq = ssh_make_string_bn(q); + if (be == NULL || bn == NULL || bd == NULL || +@@ -1689,15 +1573,42 @@ int pki_privkey_build_rsa(ssh_key key, + goto fail; + } + ++ /* Calculate remaining CRT parameters for OpenSSL to be happy ++ * taken from OpenSSH */ ++ if ((ctx = BN_CTX_new()) == NULL) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ if ((aux = BN_new()) == NULL || ++ (bdmq1 = BN_new()) == NULL || ++ (bdmp1 = BN_new()) == NULL) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ if ((d_consttime = BN_dup(bd)) == NULL) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ BN_set_flags(aux, BN_FLG_CONSTTIME); ++ BN_set_flags(d_consttime, BN_FLG_CONSTTIME); ++ ++ if ((BN_sub(aux, bq, BN_value_one()) == 0) || ++ (BN_mod(bdmq1, d_consttime, aux, ctx) == 0) || ++ (BN_sub(aux, bp, BN_value_one()) == 0) || ++ (BN_mod(bdmp1, d_consttime, aux, ctx) == 0)) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ + #if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Memory management of be, bn and bd is transferred to RSA object */ +- rc = RSA_set0_key(key->rsa, bn, be, bd); ++ rc = RSA_set0_key(key_rsa, bn, be, bd); + if (rc == 0) { + goto fail; + } + + /* Memory management of bp and bq is transferred to RSA object */ +- rc = RSA_set0_factors(key->rsa, bp, bq); ++ rc = RSA_set0_factors(key_rsa, bp, bq); + if (rc == 0) { + goto fail; + } +@@ -1705,13 +1616,30 @@ int pki_privkey_build_rsa(ssh_key key, + /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the RSA + * operations are much faster when these values are available. + * https://www.openssl.org/docs/man1.0.2/crypto/rsa.html ++ * And OpenSSL fails to export these keys to PEM if these are missing: ++ * https://github.com/openssl/openssl/issues/21826 + */ +- /* RSA_set0_crt_params(key->rsa, biqmp, NULL, NULL); +- TODO calculate missing crt_params */ ++ rc = RSA_set0_crt_params(key_rsa, bdmp1, bdmq1, biqmp); ++ if (rc == 0) { ++ goto fail; ++ } ++ bignum_safe_free(aux); ++ bignum_safe_free(d_consttime); ++ ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_RSA(key->key, key_rsa); ++ if (rc != 1) { ++ goto fail; ++ } + + return SSH_OK; + fail: +- RSA_free(key->rsa); ++ RSA_free(key_rsa); ++ EVP_PKEY_free(key->key); + return SSH_ERROR; + #else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); +@@ -1730,6 +1658,36 @@ fail: + goto fail; + } + ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR1, bp); ++ if (rc != 1) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR2, bq); ++ if (rc != 1) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT1, bdmp1); ++ if (rc != 1) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT2, bdmq1); ++ if (rc != 1) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ ++ rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, biqmp); ++ if (rc != 1) { ++ rc = SSH_ERROR; ++ goto fail; ++ } ++ + rc = evp_build_pkey("RSA", param_bld, &(key->key), EVP_PKEY_KEYPAIR); + if (rc != SSH_OK) { + rc = SSH_ERROR; +@@ -1755,7 +1713,13 @@ fail: + bignum_safe_free(bd); + bignum_safe_free(bp); + bignum_safe_free(bq); ++ bignum_safe_free(biqmp); + ++ bignum_safe_free(aux); ++ bignum_safe_free(d_consttime); ++ bignum_safe_free(bdmp1); ++ bignum_safe_free(bdmq1); ++ BN_CTX_free(ctx); + return rc; + #endif /* OPENSSL_VERSION_NUMBER */ + } +@@ -1771,8 +1735,8 @@ int pki_pubkey_build_rsa(ssh_key key, + return SSH_ERROR; + } + #else +- key->rsa = RSA_new(); +- if (key->rsa == NULL) { ++ RSA *key_rsa = RSA_new(); ++ if (key_rsa == NULL) { + return SSH_ERROR; + } + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -1786,14 +1750,25 @@ int pki_pubkey_build_rsa(ssh_key key, + + #if OPENSSL_VERSION_NUMBER < 0x30000000L + /* Memory management of bn and be is transferred to RSA object */ +- rc = RSA_set0_key(key->rsa, bn, be, NULL); ++ rc = RSA_set0_key(key_rsa, bn, be, NULL); + if (rc == 0) { + goto fail; + } + ++ key->key = EVP_PKEY_new(); ++ if (key->key == NULL) { ++ goto fail; ++ } ++ ++ rc = EVP_PKEY_assign_RSA(key->key, key_rsa); ++ if (rc != 1) { ++ goto fail; ++ } ++ + return SSH_OK; + fail: +- RSA_free(key->rsa); ++ EVP_PKEY_free(key->key); ++ RSA_free(key_rsa); + return SSH_ERROR; + #else + rc = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, bn); +@@ -1866,8 +1841,9 @@ ssh_string pki_publickey_to_blob(const ssh_key key) + case SSH_KEYTYPE_DSS: { + #if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *bp, *bq, *bg, *bpub_key; +- DSA_get0_pqg(key->dsa, &bp, &bq, &bg); +- DSA_get0_key(key->dsa, &bpub_key, NULL); ++ const DSA *key_dsa = EVP_PKEY_get0_DSA(key->key); ++ DSA_get0_pqg(key_dsa, &bp, &bq, &bg); ++ DSA_get0_key(key_dsa, &bpub_key, NULL); + #else + const OSSL_PARAM *out_param = NULL; + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); +@@ -1970,7 +1946,8 @@ ssh_string pki_publickey_to_blob(const ssh_key key) + case SSH_KEYTYPE_RSA1: { + #if OPENSSL_VERSION_NUMBER < 0x30000000L + const BIGNUM *be, *bn; +- RSA_get0_key(key->rsa, &bn, &be, NULL); ++ const RSA *key_rsa = EVP_PKEY_get0_RSA(key->key); ++ RSA_get0_key(key_rsa, &bn, &be, NULL); + #else + const OSSL_PARAM *out_param = NULL; + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); +@@ -2043,14 +2020,16 @@ ssh_string pki_publickey_to_blob(const ssh_key key) + case SSH_KEYTYPE_SK_ECDSA: + #ifdef HAVE_OPENSSL_ECC + { +-/* 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 +- */ +-#if 0 ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L ++ EC_GROUP *group = NULL; ++ EC_POINT *point = NULL; + const void *pubkey; + size_t pubkey_len; +- OSSL_PARAM *params = NULL, *locate_param = NULL; ++ OSSL_PARAM *locate_param = NULL; ++#else ++ const EC_GROUP *group = NULL; ++ const EC_POINT *point = NULL; ++ EC_KEY *ec = NULL; + #endif /* OPENSSL_VERSION_NUMBER */ + + type_s = ssh_string_from_char(pki_key_ecdsa_nid_to_char(key->ecdsa_nid)); +@@ -2066,25 +2045,29 @@ ssh_string pki_publickey_to_blob(const ssh_key key) + return NULL; + } + +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ec = EVP_PKEY_get0_EC_KEY(key->key); ++ if (ec == NULL) { ++ goto fail; ++ } + #ifdef WITH_PKCS11_URI +- if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(key->ecdsa)) { +- SSH_LOG(SSH_LOG_INFO, "It is mandatory to have separate public" +- " ECDSA key objects in the PKCS #11 device. Unlike RSA," +- " ECDSA public keys cannot be derived from their private keys."); +- goto fail; +- } ++ if (ssh_key_is_private(key) && !EC_KEY_get0_public_key(ec)) { ++ SSH_LOG(SSH_LOG_TRACE, "It is mandatory to have separate" ++ " public ECDSA key objects in the PKCS #11 device." ++ " Unlike RSA, ECDSA public keys cannot be derived" ++ " from their private keys."); ++ goto fail; ++ } + #endif /* WITH_PKCS11_URI */ +- e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa), +- EC_KEY_get0_public_key(key->ecdsa)); ++ group = EC_KEY_get0_group(ec); ++ point = EC_KEY_get0_public_key(ec); ++ if (group == NULL || point == NULL) { ++ goto fail; ++ } ++ e = pki_key_make_ecpoint_string(group, point); + #else + rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms); + if (rc < 0) { +- OSSL_PARAM_free(params); + goto fail; + } + +@@ -2101,47 +2084,36 @@ ssh_string pki_publickey_to_blob(const ssh_key key) + + rc = OSSL_PARAM_get_octet_string_ptr(locate_param, &pubkey, &pubkey_len); + if (rc != 1) { +- OSSL_PARAM_free(params); ++ goto fail; ++ } ++ /* Convert the data to low-level representation */ ++ group = EC_GROUP_new_by_curve_name_ex(NULL, NULL, key->ecdsa_nid); ++ point = EC_POINT_new(group); ++ rc = EC_POINT_oct2point(group, point, pubkey, pubkey_len, NULL); ++ if (group == NULL || point == NULL || rc != 1) { ++ EC_GROUP_free(group); ++ EC_POINT_free(point); + goto fail; + } + +- e = ssh_string_new(pubkey_len); ++ e = pki_key_make_ecpoint_string(group, point); ++ EC_GROUP_free(group); ++ EC_POINT_free(point); + #endif /* OPENSSL_VERSION_NUMBER */ + if (e == NULL) { + SSH_BUFFER_FREE(buffer); + return NULL; + } + +-/* 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 +- */ +-#if 0 +- if (memcpy(ssh_string_data(e), pubkey, pubkey_len) == NULL) { +- OSSL_PARAM_free(params); +- goto fail; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ + rc = ssh_buffer_add_ssh_string(buffer, e); + if (rc < 0) { +-/* 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 +- */ +-#if 0 +- OSSL_PARAM_free(params); +-#endif /* OPENSSL_VERSION_NUMBER */ + goto fail; + } + + ssh_string_burn(e); + SSH_STRING_FREE(e); + e = NULL; +-/* 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 +- */ +-#if 0 ++#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_free(params); + #endif /* OPENSSL_VERSION_NUMBER */ + +@@ -2415,12 +2387,14 @@ static int pki_signature_from_rsa_blob(const ssh_key pubkey, + size_t len = ssh_string_len(sig_blob); + + #if OPENSSL_VERSION_NUMBER < 0x30000000L +- if (pubkey->rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, "Pubkey RSA field NULL"); ++ const RSA *rsa = EVP_PKEY_get0_RSA(pubkey->key); ++ ++ if (rsa == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, "RSA field NULL"); + goto errout; + } + +- rsalen = RSA_size(pubkey->rsa); ++ rsalen = RSA_size(rsa); + #else + if (EVP_PKEY_get_base_id(pubkey->key) != EVP_PKEY_RSA) { + SSH_LOG(SSH_LOG_WARN, "Key has no RSA pubkey"); +@@ -2851,60 +2825,14 @@ 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; +-#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int rc = 0; +-#endif + + switch (key->type) { + case SSH_KEYTYPE_DSS: + case SSH_KEYTYPE_DSS_CERT01: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- if (key->dsa == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "NULL key->dsa"); +- goto error; +- } +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "Out of memory"); +- return NULL; +- } +- +- EVP_PKEY_set1_DSA(pkey, key->dsa); +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ + case SSH_KEYTYPE_RSA: + case SSH_KEYTYPE_RSA1: + case SSH_KEYTYPE_RSA_CERT01: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- if (key->rsa == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "NULL key->rsa"); +- goto error; +- } +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "Out of memory"); +- return NULL; +- } +- +- EVP_PKEY_set1_RSA(pkey, key->rsa); +- break; +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Remove this #else part from here +- */ +-#else +- if (key->key == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); +- goto error; +- } +- 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: + case SSH_KEYTYPE_ECDSA_P384: + case SSH_KEYTYPE_ECDSA_P521: +@@ -2913,43 +2841,17 @@ static EVP_PKEY *pki_key_to_pkey(ssh_key key) + case SSH_KEYTYPE_ECDSA_P521_CERT01: + case SSH_KEYTYPE_SK_ECDSA: + case SSH_KEYTYPE_SK_ECDSA_CERT01: +-# if defined(HAVE_OPENSSL_ECC) +-/* 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 +- */ +-#if 1 +- if (key->ecdsa == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "NULL key->ecdsa"); +- goto error; +- } +- pkey = EVP_PKEY_new(); +- if (pkey == NULL) { +- SSH_LOG(SSH_LOG_TRACE, "Out of memory"); +- return NULL; +- } +- +- EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); +- break; +-#endif /* OPENSSL_VERSION_NUMBER */ +-# endif +-/* 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 +- */ +-#if 0 + if (key->key == NULL) { + SSH_LOG(SSH_LOG_TRACE, "NULL key->key"); + goto error; + } +- rc = EVP_PKEY_uo_ref(key->key); ++ 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_ED25519: + case SSH_KEYTYPE_ED25519_CERT01: + case SSH_KEYTYPE_SK_ED25519: +@@ -3437,15 +3339,19 @@ ssh_signature pki_do_sign_hash(const ssh_key privkey, + #endif /* HAVE_OPENSSL_ED25519 */ + + #ifdef WITH_PKCS11_URI ++#ifdef WITH_PKCS11_PROVIDER ++static bool pkcs11_provider_failed = false; ++#endif ++ + /** + * @internal + * +- * @brief Populate the public/private ssh_key from the engine with ++ * @brief Populate the public/private ssh_key from the engine/provider with + * PKCS#11 URIs as the look up. + * + * @param[in] uri_name The PKCS#11 URI + * @param[in] nkey The ssh-key context for +- * the key loaded from the engine. ++ * the key loaded from the engine/provider. + * @param[in] key_type The type of the key used. Public/Private. + * + * @return SSH_OK if ssh-key is valid; SSH_ERROR otherwise. +@@ -3454,22 +3360,14 @@ int pki_uri_import(const char *uri_name, + ssh_key *nkey, + enum ssh_key_e key_type) + { +- ENGINE *engine = NULL; + EVP_PKEY *pkey = NULL; +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- RSA *rsa = NULL; +-#endif +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move HAVE_OPENSSL_ECC #ifdef into #if above +- */ +-#ifdef HAVE_OPENSSL_ECC +- EC_KEY *ecdsa = NULL; +-#else +- void *ecdsa = NULL; +-#endif + ssh_key key = NULL; + enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; ++#if OPENSSL_VERSION_NUMBER < 0x30000000L && HAVE_OPENSSL_ECC ++ EC_KEY *ecdsa = NULL; ++#endif ++#ifndef WITH_PKCS11_PROVIDER ++ ENGINE *engine = NULL; + + /* Do the init only once */ + engine = pki_get_engine(); +@@ -3484,7 +3382,7 @@ int pki_uri_import(const char *uri_name, + if (pkey == NULL) { + SSH_LOG(SSH_LOG_WARN, + "Could not load key: %s", +- ERR_error_string(ERR_get_error(),NULL)); ++ ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + break; +@@ -3493,7 +3391,7 @@ int pki_uri_import(const char *uri_name, + if (pkey == NULL) { + SSH_LOG(SSH_LOG_WARN, + "Could not load key: %s", +- ERR_error_string(ERR_get_error(),NULL)); ++ ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + break; +@@ -3502,6 +3400,72 @@ int pki_uri_import(const char *uri_name, + "Invalid key type: %d", key_type); + goto fail; + } ++#else /* WITH_PKCS11_PROVIDER */ ++ OSSL_STORE_CTX *store = NULL; ++ OSSL_STORE_INFO *info = NULL; ++ int rv, expect_type = OSSL_STORE_INFO_PKEY; ++ ++ /* The provider can be either configured in openssl.cnf or dynamically ++ * loaded, assuming it does not need any special configuration */ ++ if (OSSL_PROVIDER_available(NULL, "pkcs11") == 0 && ++ !pkcs11_provider_failed) { ++ OSSL_PROVIDER *pkcs11_provider = NULL; ++ ++ pkcs11_provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1); ++ if (pkcs11_provider == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, ++ "Failed to initialize provider: %s", ++ ERR_error_string(ERR_get_error(), NULL)); ++ /* Do not attempt to load it again */ ++ pkcs11_provider_failed = true; ++ goto fail; ++ } ++ } ++ ++ store = OSSL_STORE_open(uri_name, NULL, NULL, NULL, NULL); ++ if (store == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, ++ "Failed to open OpenSSL store: %s", ++ ERR_error_string(ERR_get_error(), NULL)); ++ goto fail; ++ } ++ if (key_type == SSH_KEY_PUBLIC) { ++ expect_type = OSSL_STORE_INFO_PUBKEY; ++ } ++ rv = OSSL_STORE_expect(store, expect_type); ++ if (rv != 1) { ++ SSH_LOG(SSH_LOG_TRACE, ++ "Failed to set the store preference. Ignoring the error: %s", ++ ERR_error_string(ERR_get_error(), NULL)); ++ } ++ ++ for (info = OSSL_STORE_load(store); ++ info != NULL; ++ info = OSSL_STORE_load(store)) { ++ int ossl_type = OSSL_STORE_INFO_get_type(info); ++ ++ if (ossl_type == OSSL_STORE_INFO_PUBKEY && key_type == SSH_KEY_PUBLIC) { ++ pkey = OSSL_STORE_INFO_get1_PUBKEY(info); ++ break; ++ } else if (ossl_type == OSSL_STORE_INFO_PKEY && ++ key_type == SSH_KEY_PRIVATE) { ++ pkey = OSSL_STORE_INFO_get1_PKEY(info); ++ break; ++ } else { ++ SSH_LOG(SSH_LOG_TRACE, ++ "Ignoring object not matching our type: %d", ++ ossl_type); ++ } ++ } ++ OSSL_STORE_close(store); ++ if (pkey == NULL) { ++ SSH_LOG(SSH_LOG_TRACE, ++ "No key found in the pkcs11 store: %s", ++ ERR_error_string(ERR_get_error(), NULL)); ++ goto fail; ++ } ++ ++#endif /* WITH_PKCS11_PROVIDER */ + + key = ssh_key_new(); + if (key == NULL) { +@@ -3510,25 +3474,12 @@ int pki_uri_import(const char *uri_name, + + switch (EVP_PKEY_base_id(pkey)) { + case EVP_PKEY_RSA: +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- rsa = EVP_PKEY_get1_RSA(pkey); +- if (rsa == NULL) { +- SSH_LOG(SSH_LOG_WARN, +- "Parsing pub key: %s", +- ERR_error_string(ERR_get_error(),NULL)); +- goto fail; +- } +-#endif /* OPENSSL_VERSION_NUMBER */ + type = SSH_KEYTYPE_RSA; + break; + case EVP_PKEY_EC: + #ifdef HAVE_OPENSSL_ECC +-/* 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 +- */ +-#if 1 +- ecdsa = EVP_PKEY_get1_EC_KEY(pkey); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ ecdsa = EVP_PKEY_get0_EC_KEY(pkey); + if (ecdsa == NULL) { + SSH_LOG(SSH_LOG_WARN, + "Parsing pub key: %s", +@@ -3562,22 +3513,10 @@ int pki_uri_import(const char *uri_name, + if (key_type == SSH_KEY_PRIVATE) { + key->flags |= SSH_KEY_FLAG_PRIVATE; + } +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- key->rsa = rsa; +-#endif +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move line key->ecdsa into #if above +- */ +- key->ecdsa = ecdsa; + #ifdef HAVE_OPENSSL_ECC + if (is_ecdsa_key_type(key->type)) { +-/* 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 +- */ +-#if 1 +- key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); ++#if OPENSSL_VERSION_NUMBER < 0x30000000L ++ key->ecdsa_nid = pki_key_ecdsa_to_nid(ecdsa); + #else + key->ecdsa_nid = pki_key_ecdsa_to_nid(key->key); + #endif /* OPENSSL_VERSION_NUMBER */ +@@ -3591,16 +3530,6 @@ int pki_uri_import(const char *uri_name, + fail: + EVP_PKEY_free(pkey); + ssh_key_free(key); +-#if OPENSSL_VERSION_NUMBER < 0x30000000L +- RSA_free(rsa); +-#endif +-/* TODO Change to new API when the OpenSSL will support export of uncompressed EC keys +- * https://github.com/openssl/openssl/pull/16624 +- * Move HAVE_OPENSSL_ECC #ifdef into #if above +- */ +-#ifdef HAVE_OPENSSL_ECC +- EC_KEY_free(ecdsa); +-#endif + + return SSH_ERROR; + } +diff --git a/src/wrapper.c b/src/wrapper.c +index d317dc4c..bf949ea9 100644 +--- a/src/wrapper.c ++++ b/src/wrapper.c +@@ -177,13 +177,9 @@ void crypto_free(struct ssh_crypto_struct *crypto) + #ifdef HAVE_ECDH + SAFE_FREE(crypto->ecdh_client_pubkey); + SAFE_FREE(crypto->ecdh_server_pubkey); +- if(crypto->ecdh_privkey != NULL){ ++ if (crypto->ecdh_privkey != NULL) { + #ifdef HAVE_OPENSSL_ECC +-/* 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 +- */ +-#if 1 ++#if OPENSSL_VERSION_NUMBER < 0x30000000L + EC_KEY_free(crypto->ecdh_privkey); + #else + EVP_PKEY_free(crypto->ecdh_privkey); +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index f5c30061..93d1250f 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -183,6 +183,16 @@ if (CLIENT_TESTING OR SERVER_TESTING) + if (NOT SOFTHSM_FOUND) + message(SEND_ERROR "Could not find softhsm module!") + endif (NOT SOFTHSM_FOUND) ++ if (WITH_PKCS11_PROVIDER) ++ find_package(PkgConfig) ++ if (PKG_CONFIG_FOUND) ++ pkg_check_modules(P11_KIT p11-kit-1) ++ if (P11_KIT_FOUND) ++ pkg_get_variable(P11_MODULE_PATH p11-kit-1 p11_module_path) ++ set(P11_KIT_CLIENT ${P11_MODULE_PATH}/p11-kit-client.so) ++ endif (P11_KIT_FOUND) ++ endif (PKG_CONFIG_FOUND) ++ endif (WITH_PKCS11_PROVIDER) + endif (WITH_PKCS11_URI) + + find_program(SSH_EXECUTABLE NAMES ssh) +@@ -296,12 +306,14 @@ if (CLIENT_TESTING OR SERVER_TESTING) + file(COPY keys/certauth/id_rsa DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) + file(COPY keys/certauth/id_rsa.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) + file(COPY keys/certauth/id_rsa-cert.pub DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/home/bob/.ssh_cert/ FILE_PERMISSIONS OWNER_READ OWNER_WRITE) ++endif () + ++if (WITH_PKCS11_URI) + #Copy the script to setup PKCS11 tokens + file(COPY pkcs11/setup-softhsm-tokens.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/pkcs11 FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) ++endif (WITH_PKCS11_URI) + +- message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}") +-endif () ++message(STATUS "TORTURE_ENVIRONMENT=${TORTURE_ENVIRONMENT}") + + configure_file(tests_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/tests_config.h) + +diff --git a/tests/client/torture_auth_pkcs11.c b/tests/client/torture_auth_pkcs11.c +index e75fea0e..2537d2d8 100644 +--- a/tests/client/torture_auth_pkcs11.c ++++ b/tests/client/torture_auth_pkcs11.c +@@ -39,9 +39,8 @@ + #define LIBSSH_ECDSA_256_TESTKEY "id_pkcs11_ecdsa_256" + #define LIBSSH_ECDSA_384_TESTKEY "id_pkcs11_ecdsa_384" + #define LIBSSH_ECDSA_521_TESTKEY "id_pkcs11_ecdsa_521" +-#define SOFTHSM_CONF "softhsm.conf" + +-const char template[] = "temp_dir_XXXXXX"; ++const char template[] = "/tmp/temp_dir_XXXXXX"; + + struct pki_st { + char *temp_dir; +@@ -109,7 +108,6 @@ static int setup_session(void **state) + struct torture_state *s = *state; + struct pki_st *test_state = NULL; + int rc; +- char conf_path[1024] = {0}; + char keys_dir[1024] = {0}; + char *temp_dir; + +@@ -134,9 +132,6 @@ static int setup_session(void **state) + + test_state->keys_dir = strdup(keys_dir); + +- snprintf(conf_path, sizeof(conf_path), "%s/softhsm.conf", test_state->temp_dir); +- setenv("SOFTHSM2_CONF", conf_path, 1); +- + setup_tokens(state, LIBSSH_RSA_TESTKEY, "rsa"); + setup_tokens(state, LIBSSH_ECDSA_256_TESTKEY, "ecdsa256"); + setup_tokens(state, LIBSSH_ECDSA_384_TESTKEY, "ecdsa384"); +@@ -160,7 +155,7 @@ static int sshd_teardown(void **state) { + struct pki_st *test_state = s->private_data; + int rc; + +- unsetenv("SOFTHSM2_CONF"); ++ torture_cleanup_tokens(test_state->temp_dir); + + rc = torture_change_dir(test_state->orig_dir); + assert_int_equal(rc, 0); +diff --git a/tests/pkcs11/setup-softhsm-tokens.sh b/tests/pkcs11/setup-softhsm-tokens.sh +index ae316c7a..bd8e0944 100755 +--- a/tests/pkcs11/setup-softhsm-tokens.sh ++++ b/tests/pkcs11/setup-softhsm-tokens.sh +@@ -5,8 +5,10 @@ + TESTDIR=$1 + PRIVKEY=$2 + OBJNAME=$3 ++TOKENLABEL=$3 # yeah. The same as object label + LOADPUBLIC=$4 + LIBSOFTHSM_PATH=$5 ++P11_KIT_CLIENT=$6 + shift 5 + + PUBKEY="$PRIVKEY.pub" +@@ -15,24 +17,27 @@ echo "TESTDIR: $TESTDIR" + echo "PRIVKEY: $PRIVKEY" + echo "PUBKEY: $PUBKEY" + echo "OBJNAME: $OBJNAME" ++echo "TOKENLABEL: $TOKENLABEL" + echo "LOADPUBLIC: $LOADPUBLIC" + +-# Create temporary directory for tokens +-install -d -m 0755 "$TESTDIR/db" ++if [ ! -d "$TESTDIR/db" ]; then ++ # Create temporary directory for tokens ++ install -d -m 0755 "$TESTDIR/db" + +-# Create SoftHSM configuration file +-cat >"$TESTDIR/softhsm.conf" <"$TESTDIR/softhsm.conf" <temp_dir); +- setenv("SOFTHSM2_CONF", conf_path, 1); +- + setup_tokens_ecdsa(state, 256, "ecdsa256", "1"); + setup_tokens_ecdsa(state, 384, "ecdsa384", "1"); + setup_tokens_ecdsa(state, 521, "ecdsa521", "1"); +@@ -118,7 +114,7 @@ static int teardown_directory_structure(void **state) + struct pki_st *test_state = *state; + int rc; + +- unsetenv("SOFTHSM2_CONF"); ++ torture_cleanup_tokens(test_state->temp_dir); + + rc = torture_change_dir(test_state->orig_dir); + assert_int_equal(rc, 0); +diff --git a/tests/unittests/torture_pki_rsa_uri.c b/tests/unittests/torture_pki_rsa_uri.c +index 1d15db6d..d0325def 100644 +--- a/tests/unittests/torture_pki_rsa_uri.c ++++ b/tests/unittests/torture_pki_rsa_uri.c +@@ -13,11 +13,10 @@ + + #define LIBSSH_RSA_TESTKEY "libssh_testkey.id_rsa" + #define LIBSSH_RSA_TESTKEY_PASSPHRASE "libssh_testkey_passphrase.id_rsa" +-#define SOFTHSM_CONF "softhsm.conf" + #define PUB_URI_FMT "pkcs11:token=%s;object=%s;type=public" + #define PRIV_URI_FMT "pkcs11:token=%s;object=%s;type=private?pin-value=%s" + +-const char template[] = "temp_dir_XXXXXX"; ++const char template[] = "/tmp/temp_dir_XXXXXX"; + const unsigned char INPUT[] = "1234567890123456789012345678901234567890" + "123456789012345678901234"; + struct pki_st { +@@ -33,7 +32,6 @@ struct pki_st { + + static int setup_tokens(void **state) + { +- char conf_path[1024] = {0}; + char keys_path[1024] = {0}; + char keys_path_pub[1024] = {0}; + char *cwd = NULL; +@@ -85,10 +83,6 @@ static int setup_tokens(void **state) + + torture_setup_tokens(cwd, keys_path, obj_tempname, "1"); + +- snprintf(conf_path, sizeof(conf_path), "%s/softhsm.conf", cwd); +- +- setenv("SOFTHSM2_CONF", conf_path, 1); +- + return 0; + } + +@@ -126,6 +120,8 @@ static int teardown_directory_structure(void **state) + struct pki_st *test_state = *state; + int rc; + ++ torture_cleanup_tokens(test_state->temp_dir); ++ + rc = torture_change_dir(test_state->orig_dir); + assert_int_equal(rc, 0); + +@@ -142,8 +138,6 @@ static int teardown_directory_structure(void **state) + SAFE_FREE(test_state->pub_uri_invalid_token); + SAFE_FREE(test_state); + +- unsetenv("SOFTHSM2_CONF"); +- + return 0; + } + diff --git a/libssh.spec b/libssh.spec index 032a549..ba3da1a 100644 --- a/libssh.spec +++ b/libssh.spec @@ -1,6 +1,6 @@ Name: libssh Version: 0.10.6 -Release: 4%{?dist} +Release: 5%{?dist} Summary: A library implementing the SSH protocol License: LGPL-2.1-or-later URL: http://www.libssh.org @@ -13,6 +13,19 @@ Source4: libssh_server.config Patch1: libssh-0.10.6-rekey-timeout.patch # https://gitlab.com/libssh/libssh-mirror/-/merge_requests/431 Patch2: libssh-0.10.6-ipv6-hostname.patch +# Backport of the following commits from master before we will have the next 0.11.0 release: +# 9717b99136cbff850000378f70d1391f348713f9 libcrypto-compat.c/h: Remove no longer supported openssl versions +# 54c1703cb22b917222a6eb2a5d2fde22319d9b7a Move old DSA and RSA structs into EVP_PKEY +# 1eb3df5254a4348eae6edbc8a2bf08fef4015897 Get rid of the deprecated OpenSSL API +# 4fb5af1da5cb02933cb4cfa10f72484cca9ca961 src/pki_crypto.c: Fix errors introduced by EC rework +# 2539d72b7c8d03d54538533db5b346dad52d6db3 Add support for PKCS#11 provider in OpenSSL 3.0 +# f8d7fee58842a11ad7a0386b4e829e36cd6e9432 pki: Use preference hints when loading keys from store +# e0011a197009897fcba09229e76940d9f5b12404 pki: Avoid freeing static groups/points on OpenSSL<3 +# 9b263cf5e1da6e06f6ab90e3169409a7bed60835 pki_crypto: Fix ecdsa memory leak +# baa773d1cd6838af33fedcd65ddbb4e46e2b06c0 pki: Calculate missing CRT parameters when building RSA Key +# 2c876464ab0a27387a122c6a4b39ec187a6fc596 ecdh: Fix missing-prototype warning +# 2c918aad6763754bdffb84796b410e21f24bb7ec tests: Use /tmp for tmpdirs that contain sockets +Patch3: libssh-0.10.6-pkcs11-provider.patch BuildRequires: cmake BuildRequires: gcc-c++ @@ -30,7 +43,10 @@ BuildRequires: priv_wrapper BuildRequires: openssh-clients BuildRequires: openssh-server BuildRequires: nmap-ncat -BuildRequires: openssl-pkcs11 +BuildRequires: pkcs11-provider +BuildRequires: p11-kit-devel +BuildRequires: p11-kit-server +BuildRequires: opensc BuildRequires: softhsm BuildRequires: gnutls-utils @@ -79,6 +95,7 @@ gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} -DCLIENT_TESTING=ON \ -DSERVER_TESTING=ON \ -DWITH_PKCS11_URI=ON \ + -DWITH_PKCS11_PROVIDER=ON \ -DGLOBAL_CLIENT_CONFIG="%{_sysconfdir}/libssh/libssh_client.config" \ -DGLOBAL_BIND_CONFIG="%{_sysconfdir}/libssh/libssh_server.config" @@ -138,6 +155,10 @@ popd %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_server.config %changelog +* Wed May 22 2024 Sahana Prasad - 0.10.6-5 +- Build libssh with pkcs11-provider instead of pkcs11 engine +- Resolves: RHEL-30437 + * Thu Jan 25 2024 Fedora Release Engineering - 0.10.6-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild