From 603ee8d8fd60db28a425c2e95f83987ec4b54fc8 Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Fri, 25 Oct 2024 16:38:03 +0300 Subject: [PATCH] import libssh-0.10.6-8.el10 --- .gitignore | 2 + .libssh.metadata | 2 + SOURCES/libssh-0.10.6-compress.patch | 41 + SOURCES/libssh-0.10.6-ipv6-hostname.patch | 263 ++ SOURCES/libssh-0.10.6-no-engine.patch | 48 + SOURCES/libssh-0.10.6-pkcs11-provider.patch | 4069 +++++++++++++++++++ SOURCES/libssh-0.10.6-rate-limit.patch | 47 + SOURCES/libssh-0.10.6-rekey-timeout.patch | 37 + SOURCES/libssh-0.10.6.tar.xz.asc | 16 + SOURCES/libssh_client.config | 4 + SOURCES/libssh_server.config | 2 + SPECS/libssh.spec | 566 +++ 12 files changed, 5097 insertions(+) create mode 100644 .gitignore create mode 100644 .libssh.metadata create mode 100644 SOURCES/libssh-0.10.6-compress.patch create mode 100644 SOURCES/libssh-0.10.6-ipv6-hostname.patch create mode 100644 SOURCES/libssh-0.10.6-no-engine.patch create mode 100644 SOURCES/libssh-0.10.6-pkcs11-provider.patch create mode 100644 SOURCES/libssh-0.10.6-rate-limit.patch create mode 100644 SOURCES/libssh-0.10.6-rekey-timeout.patch create mode 100644 SOURCES/libssh-0.10.6.tar.xz.asc create mode 100644 SOURCES/libssh_client.config create mode 100644 SOURCES/libssh_server.config create mode 100644 SPECS/libssh.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f00c11c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/libssh-0.10.6.tar.xz +SOURCES/libssh.keyring diff --git a/.libssh.metadata b/.libssh.metadata new file mode 100644 index 0000000..f88df44 --- /dev/null +++ b/.libssh.metadata @@ -0,0 +1,2 @@ +e8fb3b4750db11d2483cac4b5f046e301c09b72f SOURCES/libssh-0.10.6.tar.xz +3f2ab0bca02893402ba0ad172a6bd44456a65f86 SOURCES/libssh.keyring diff --git a/SOURCES/libssh-0.10.6-compress.patch b/SOURCES/libssh-0.10.6-compress.patch new file mode 100644 index 0000000..be72f9d --- /dev/null +++ b/SOURCES/libssh-0.10.6-compress.patch @@ -0,0 +1,41 @@ +From c9cfeb9b838b801c3e2bb070c3db914e81ca4e68 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 12 Aug 2024 17:49:46 +0200 +Subject: [PATCH] wrapper: Avoid asymmetric termination of gzip context + +For some reason, both compress and decompress contexts were terminated +with both compress and decompress end functions (if the deflateEnd worked), +which was causing for some another unexplained reasons issues on i686 +architecture when running the torture_packet unit test. + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + src/wrapper.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/wrapper.c b/src/wrapper.c +index bf949ea9..d9cf6db5 100644 +--- a/src/wrapper.c ++++ b/src/wrapper.c +@@ -200,14 +200,12 @@ void crypto_free(struct ssh_crypto_struct *crypto) + SAFE_FREE(crypto->secret_hash); + } + #ifdef WITH_ZLIB +- if (crypto->compress_out_ctx && +- (deflateEnd(crypto->compress_out_ctx) != 0)) { +- inflateEnd(crypto->compress_out_ctx); ++ if (crypto->compress_out_ctx) { ++ deflateEnd(crypto->compress_out_ctx); + } + SAFE_FREE(crypto->compress_out_ctx); + +- if (crypto->compress_in_ctx && +- (deflateEnd(crypto->compress_in_ctx) != 0)) { ++ if (crypto->compress_in_ctx) { + inflateEnd(crypto->compress_in_ctx); + } + SAFE_FREE(crypto->compress_in_ctx); +-- +2.46.0 + diff --git a/SOURCES/libssh-0.10.6-ipv6-hostname.patch b/SOURCES/libssh-0.10.6-ipv6-hostname.patch new file mode 100644 index 0000000..a0c5ad7 --- /dev/null +++ b/SOURCES/libssh-0.10.6-ipv6-hostname.patch @@ -0,0 +1,263 @@ +From 4f997aee7c7d7ea346b3e8ba505da0b7601ff318 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 22 Dec 2023 10:32:40 +0100 +Subject: [PATCH 1/2] Fix regression in IPv6 addresses in hostname parsing + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + include/libssh/config_parser.h | 11 ++++++++--- + src/config.c | 4 ++-- + src/config_parser.c | 16 +++++++++++----- + src/options.c | 10 ++-------- + 4 files changed, 23 insertions(+), 18 deletions(-) + +diff --git a/include/libssh/config_parser.h b/include/libssh/config_parser.h +index a7dd42a2..ca353432 100644 +--- a/include/libssh/config_parser.h ++++ b/include/libssh/config_parser.h +@@ -30,6 +30,8 @@ + extern "C" { + #endif + ++#include ++ + char *ssh_config_get_cmd(char **str); + + char *ssh_config_get_token(char **str); +@@ -49,14 +51,17 @@ int ssh_config_get_yesno(char **str, int notfound); + * be stored or NULL if we do not care about the result. + * @param[out] port Pointer to the location, where the new port will + * be stored or NULL if we do not care about the result. ++ * @param[in] ignore_port Set to true if the we should not attempt to parse ++ * port number. + * + * @returns SSH_OK if the provided string is in format of SSH URI, + * SSH_ERROR on failure + */ + int ssh_config_parse_uri(const char *tok, +- char **username, +- char **hostname, +- char **port); ++ char **username, ++ char **hostname, ++ char **port, ++ bool ignore_port); + + #ifdef __cplusplus + } +diff --git a/src/config.c b/src/config.c +index 5eedbce9..7135c3b1 100644 +--- a/src/config.c ++++ b/src/config.c +@@ -464,7 +464,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) + } + if (parse_entry) { + /* We actually care only about the first item */ +- rv = ssh_config_parse_uri(cp, &username, &hostname, &port); ++ rv = ssh_config_parse_uri(cp, &username, &hostname, &port, false); + /* The rest of the list needs to be passed on */ + if (endp != NULL) { + next = strdup(endp + 1); +@@ -475,7 +475,7 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing) + } + } else { + /* The rest is just sanity-checked to avoid failures later */ +- rv = ssh_config_parse_uri(cp, NULL, NULL, NULL); ++ rv = ssh_config_parse_uri(cp, NULL, NULL, NULL, false); + } + if (rv != SSH_OK) { + goto out; +diff --git a/src/config_parser.c b/src/config_parser.c +index 9ffc8b8b..5f30cd3e 100644 +--- a/src/config_parser.c ++++ b/src/config_parser.c +@@ -162,9 +162,10 @@ int ssh_config_get_yesno(char **str, int notfound) + } + + int ssh_config_parse_uri(const char *tok, +- char **username, +- char **hostname, +- char **port) ++ char **username, ++ char **hostname, ++ char **port, ++ bool ignore_port) + { + char *endp = NULL; + long port_n; +@@ -210,12 +211,17 @@ int ssh_config_parse_uri(const char *tok, + if (endp == NULL) { + goto error; + } +- } else { +- /* Hostnames or aliases expand to the last colon or to the end */ ++ } else if (!ignore_port) { ++ /* Hostnames or aliases expand to the last colon (if port is requested) ++ * or to the end */ + endp = strrchr(tok, ':'); + if (endp == NULL) { + endp = strchr(tok, '\0'); + } ++ } else { ++ /* If no port is requested, expand to the end of line ++ * (to accommodate the IPv6 addresses) */ ++ endp = strchr(tok, '\0'); + } + if (tok == endp) { + /* Zero-length hostnames are not valid */ +diff --git a/src/options.c b/src/options.c +index 2e73be46..676c49e7 100644 +--- a/src/options.c ++++ b/src/options.c +@@ -634,17 +634,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, + ssh_set_error_invalid(session); + return -1; + } else { +- char *username = NULL, *hostname = NULL, *port = NULL; +- rc = ssh_config_parse_uri(value, &username, &hostname, &port); ++ char *username = NULL, *hostname = NULL; ++ rc = ssh_config_parse_uri(value, &username, &hostname, NULL, true); + if (rc != SSH_OK) { + return -1; + } +- if (port != NULL) { +- SAFE_FREE(username); +- SAFE_FREE(hostname); +- SAFE_FREE(port); +- return -1; +- } + if (username != NULL) { + SAFE_FREE(session->opts.username); + session->opts.username = username; +-- +2.43.0 + + +From 6f6e453d7b0ad4ee6a6f6a1c96a9a6b27821410d Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 22 Dec 2023 09:52:18 +0100 +Subject: [PATCH 2/2] tests: Increase test coverage for IPv6 address parsing as + hostnames + +This was an issue in cockpit: + +https://github.com/cockpit-project/cockpit/issues/19772 + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + tests/unittests/torture_config.c | 49 +++++++++++++++++++++++++++++++ + tests/unittests/torture_options.c | 16 ++++++++++ + 2 files changed, 65 insertions(+) + +diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c +index bc6b08f9..751aa126 100644 +--- a/tests/unittests/torture_config.c ++++ b/tests/unittests/torture_config.c +@@ -2332,6 +2332,53 @@ static void torture_config_make_absolute_no_sshdir(void **state) + torture_config_make_absolute_int(state, 1); + } + ++static void torture_config_parse_uri(void **state) ++{ ++ char *username = NULL; ++ char *hostname = NULL; ++ char *port = NULL; ++ int rc; ++ ++ (void)state; /* unused */ ++ ++ rc = ssh_config_parse_uri("localhost", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "localhost"); ++ SAFE_FREE(hostname); ++ assert_null(port); ++ ++ rc = ssh_config_parse_uri("1.2.3.4", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1.2.3.4"); ++ SAFE_FREE(hostname); ++ assert_null(port); ++ ++ rc = ssh_config_parse_uri("1.2.3.4:2222", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1.2.3.4"); ++ SAFE_FREE(hostname); ++ assert_string_equal(port, "2222"); ++ SAFE_FREE(port); ++ ++ rc = ssh_config_parse_uri("[1:2:3::4]:2222", &username, &hostname, &port, false); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1:2:3::4"); ++ SAFE_FREE(hostname); ++ assert_string_equal(port, "2222"); ++ SAFE_FREE(port); ++ ++ /* do not want port */ ++ rc = ssh_config_parse_uri("1:2:3::4", &username, &hostname, NULL, true); ++ assert_return_code(rc, errno); ++ assert_null(username); ++ assert_string_equal(hostname, "1:2:3::4"); ++ SAFE_FREE(hostname); ++} ++ + int torture_run_tests(void) + { + int rc; +@@ -2424,6 +2471,8 @@ int torture_run_tests(void) + setup, teardown), + cmocka_unit_test_setup_teardown(torture_config_make_absolute_no_sshdir, + setup_no_sshdir, teardown), ++ cmocka_unit_test_setup_teardown(torture_config_parse_uri, ++ setup, teardown), + }; + + +diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c +index 5ba3bdc6..b07712d8 100644 +--- a/tests/unittests/torture_options.c ++++ b/tests/unittests/torture_options.c +@@ -57,6 +57,20 @@ static void torture_options_set_host(void **state) { + assert_non_null(session->opts.host); + assert_string_equal(session->opts.host, "localhost"); + ++ /* IPv4 address */ ++ rc = ssh_options_set(session, SSH_OPTIONS_HOST, "127.1.1.1"); ++ assert_true(rc == 0); ++ assert_non_null(session->opts.host); ++ assert_string_equal(session->opts.host, "127.1.1.1"); ++ assert_null(session->opts.username); ++ ++ /* IPv6 address */ ++ rc = ssh_options_set(session, SSH_OPTIONS_HOST, "::1"); ++ assert_true(rc == 0); ++ assert_non_null(session->opts.host); ++ assert_string_equal(session->opts.host, "::1"); ++ assert_null(session->opts.username); ++ + rc = ssh_options_set(session, SSH_OPTIONS_HOST, "guru@meditation"); + assert_true(rc == 0); + assert_non_null(session->opts.host); +@@ -64,12 +78,14 @@ static void torture_options_set_host(void **state) { + assert_non_null(session->opts.username); + assert_string_equal(session->opts.username, "guru"); + ++ /* more @ in uri is OK -- it should go to the username */ + rc = ssh_options_set(session, SSH_OPTIONS_HOST, "at@login@hostname"); + assert_true(rc == 0); + assert_non_null(session->opts.host); + assert_string_equal(session->opts.host, "hostname"); + assert_non_null(session->opts.username); + assert_string_equal(session->opts.username, "at@login"); ++ + } + + static void torture_options_set_ciphers(void **state) { +-- +2.43.0 + diff --git a/SOURCES/libssh-0.10.6-no-engine.patch b/SOURCES/libssh-0.10.6-no-engine.patch new file mode 100644 index 0000000..d38a36a --- /dev/null +++ b/SOURCES/libssh-0.10.6-no-engine.patch @@ -0,0 +1,48 @@ +diff -up libssh-0.10.6/src/libcrypto.c.no-engine libssh-0.10.6/src/libcrypto.c +--- libssh-0.10.6/src/libcrypto.c.no-engine 2024-07-31 09:25:56.460404672 +0200 ++++ libssh-0.10.6/src/libcrypto.c 2024-07-31 09:28:46.900273530 +0200 +@@ -94,7 +94,7 @@ void ssh_reseed(void){ + #endif + } + +-#ifndef WITH_PKCS11_PROVIDER ++#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) + static ENGINE *engine = NULL; + + ENGINE *pki_get_engine(void) +@@ -126,7 +126,7 @@ ENGINE *pki_get_engine(void) + } + return engine; + } +-#endif /* WITH_PKCS11_PROVIDER */ ++#endif /* defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) */ + + #ifdef HAVE_OPENSSL_EVP_KDF_CTX + #if OPENSSL_VERSION_NUMBER < 0x30000000L +diff -up libssh-0.10.6/src/pki_crypto.c.no-engine libssh-0.10.6/src/pki_crypto.c +--- libssh-0.10.6/src/pki_crypto.c.no-engine 2024-07-31 09:26:34.296823306 +0200 ++++ libssh-0.10.6/src/pki_crypto.c 2024-07-31 09:29:36.414810967 +0200 +@@ -33,7 +33,9 @@ + + #include + #include ++#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) + #include ++#endif + #include + #if OPENSSL_VERSION_NUMBER < 0x30000000L + #include +diff -up libssh-0.10.6/src/libcrypto.c.no-engine libssh-0.10.6/src/libcrypto.c +--- libssh-0.10.6/src/libcrypto.c.no-engine 2024-07-31 11:03:45.262319724 +0200 ++++ libssh-0.10.6/src/libcrypto.c 2024-07-31 11:04:59.842161279 +0200 +@@ -53,7 +53,9 @@ + #include + #endif /* OPENSSL_VERSION_NUMBER */ + #include ++#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) + #include ++#endif + + #include "libcrypto-compat.h" + + diff --git a/SOURCES/libssh-0.10.6-pkcs11-provider.patch b/SOURCES/libssh-0.10.6-pkcs11-provider.patch new file mode 100644 index 0000000..d1134a2 --- /dev/null +++ b/SOURCES/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/SOURCES/libssh-0.10.6-rate-limit.patch b/SOURCES/libssh-0.10.6-rate-limit.patch new file mode 100644 index 0000000..e3fc1bd --- /dev/null +++ b/SOURCES/libssh-0.10.6-rate-limit.patch @@ -0,0 +1,47 @@ +From 7b89ff760a2c7119916eaa8fd6a62afbd15fc3ad Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 9 Aug 2024 11:30:15 +0200 +Subject: [PATCH] test: Workaround the new OpenSSH failure rate limiting + +The new OpenSSH rate limits the failed authentication attempts per source +address and drops connection when the amount is reached, which is happening +in our testsuite. + +By whitelisting the IP address of the client on the socket wrapper, +this allows the tests to pass. + +https://man.openbsd.org/sshd_config.5#PerSourcePenaltyExemptList + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +--- + tests/torture.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tests/torture.c b/tests/torture.c +index c832dfa6..ad0a7836 100644 +--- a/tests/torture.c ++++ b/tests/torture.c +@@ -755,6 +755,9 @@ static void torture_setup_create_sshd_config(void **state, bool pam) + "HostKeyAlgorithms " OPENSSH_KEYS "\n" + #if OPENSSH_VERSION_MAJOR == 8 && OPENSSH_VERSION_MINOR >= 2 + "CASignatureAlgorithms " OPENSSH_KEYS "\n" ++#endif ++#if (OPENSSH_VERSION_MAJOR == 9 && OPENSSH_VERSION_MINOR >= 8) || OPENSSH_VERSION_MAJOR > 9 ++ "PerSourcePenaltyExemptList 127.0.0.21\n" + #endif + "Ciphers " OPENSSH_CIPHERS "\n" + "KexAlgorithms " OPENSSH_KEX "\n" +@@ -786,6 +789,9 @@ static void torture_setup_create_sshd_config(void **state, bool pam) + "%s\n" /* Here comes UsePam */ + "%s" /* The space for test-specific options */ + "\n" ++#if (OPENSSH_VERSION_MAJOR == 9 && OPENSSH_VERSION_MINOR >= 8) || OPENSSH_VERSION_MAJOR > 9 ++ "PerSourcePenaltyExemptList 127.0.0.21\n" ++#endif + "Ciphers " + "aes256-gcm@openssh.com,aes256-ctr,aes256-cbc," + "aes128-gcm@openssh.com,aes128-ctr,aes128-cbc" +-- +2.46.0 + diff --git a/SOURCES/libssh-0.10.6-rekey-timeout.patch b/SOURCES/libssh-0.10.6-rekey-timeout.patch new file mode 100644 index 0000000..b2fd232 --- /dev/null +++ b/SOURCES/libssh-0.10.6-rekey-timeout.patch @@ -0,0 +1,37 @@ +From 96d76161666b117099696afebcef2fe42ae80715 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 16 May 2023 22:55:11 +0200 +Subject: [PATCH] tests: Give the server more time handle rekey + +Signed-off-by: Jakub Jelen +Reviewed-by: Norbert Pocs +--- + tests/client/torture_rekey.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/client/torture_rekey.c b/tests/client/torture_rekey.c +index ccd5ae2cf..0fc13b8b3 100644 +--- a/tests/client/torture_rekey.c ++++ b/tests/client/torture_rekey.c +@@ -505,7 +505,7 @@ static void torture_rekey_different_kex(void **state) + memset(data, 'A', 128); + for (i = 0; i < KEX_RETRY; i++) { + ssh_send_ignore(s->ssh.session, data); +- ssh_handle_packets(s->ssh.session, 100); ++ ssh_handle_packets(s->ssh.session, 1000); + + c = s->ssh.session->current_crypto; + /* SHA256 len */ +@@ -583,7 +583,7 @@ static void torture_rekey_server_different_kex(void **state) + memset(data, 'A', 128); + for (i = 0; i < KEX_RETRY; i++) { + ssh_send_ignore(s->ssh.session, data); +- ssh_handle_packets(s->ssh.session, 100); ++ ssh_handle_packets(s->ssh.session, 1000); + + c = s->ssh.session->current_crypto; + /* SHA256 len */ +-- +GitLab + + diff --git a/SOURCES/libssh-0.10.6.tar.xz.asc b/SOURCES/libssh-0.10.6.tar.xz.asc new file mode 100644 index 0000000..bf9c364 --- /dev/null +++ b/SOURCES/libssh-0.10.6.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEjf9T4Y8qvI2PPJIjfuD8TcwBTj0FAmWAeGkACgkQfuD8TcwB +Tj2yAw//QOMEcCiijJvOgXCKsVoV9oSuK3aYxqpOS9cV2P40eev0KQrAZC2EXNt3 +XAdfNhA21b2C6qSxckmkCWg3vwPmM6LousHG+zpyZkiSziolMoeBkvbEdU42fufE +SD39cA1bBEbZahyrILWT2I3Bi0d0G7FC13tIBXShS2zIITSXs/2SSRIhg3OXB979 +FTwvEE4zHeSXO4itTMNA/sMJ/0qPccQIzisH0g/TF4318b0qjlQjkHJS1y0f3/PL +Ge3RORQVcZqGTnhJNlF/tKD8wZ9mfqqurQ9yNshiAu8hH8sDH5ZhI3o5pjQe0mGO +JNEwTw0X/vZ4iglWFmm2CusiHrh0KUFsrp8f3oaL3HU4i7yYgo0FhzFtgFVt0gXO +JQOhlSUq50yqbBj6S9C5ecuSR0uPgYA4d8qCFrt9oD77m7Qi3mMi+f/kP+HctIaV +4ro7lZf6IS54J4/m5hRY3F0nweFnZZL8gn8Da8mBZSvhXCqQL6qbD9buwrTzxGft +Fct7+PrRwz9igO7j2nNMyWxtX55/GpX06n7vuonRgQQQiT8eQ5R71STMHJaACFPS +CJHCpuVL28HGdyAxN5d65TCvkNo9/gFGM6ocIH3OlreTFUvy22qNrqwHpCkLgYWU +ylntVoE/VYtHtwFOe0uuCX+2TiM03P5UT2NqAAa/8D4Z5ur3qUY= +=nXW5 +-----END PGP SIGNATURE----- diff --git a/SOURCES/libssh_client.config b/SOURCES/libssh_client.config new file mode 100644 index 0000000..1d293bd --- /dev/null +++ b/SOURCES/libssh_client.config @@ -0,0 +1,4 @@ +# Parse system-wide crypto configuration file +Include /etc/crypto-policies/back-ends/libssh.config +# Parse OpenSSH configuration file for consistency +Include /etc/ssh/ssh_config diff --git a/SOURCES/libssh_server.config b/SOURCES/libssh_server.config new file mode 100644 index 0000000..d3ef5c2 --- /dev/null +++ b/SOURCES/libssh_server.config @@ -0,0 +1,2 @@ +# Parse system-wide crypto configuration file +Include /etc/crypto-policies/back-ends/libssh.config diff --git a/SPECS/libssh.spec b/SPECS/libssh.spec new file mode 100644 index 0000000..12771ee --- /dev/null +++ b/SPECS/libssh.spec @@ -0,0 +1,566 @@ +Name: libssh +Version: 0.10.6 +Release: 8%{?dist} +Summary: A library implementing the SSH protocol +License: LGPL-2.1-or-later +URL: http://www.libssh.org + +Source0: https://www.libssh.org/files/0.10/%{name}-%{version}.tar.xz +Source1: https://www.libssh.org/files/0.10/%{name}-%{version}.tar.xz.asc +Source2: https://cryptomilk.org/gpgkey-8DFF53E18F2ABC8D8F3C92237EE0FC4DCC014E3D.gpg#/%{name}.keyring +Source3: libssh_client.config +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 +Patch4: libssh-0.10.6-no-engine.patch +# 7b89ff760a2c7119916eaa8fd6a62afbd15fc3ad +Patch5: libssh-0.10.6-rate-limit.patch +# c9cfeb9b838b801c3e2bb070c3db914e81ca4e68 +Patch6: libssh-0.10.6-compress.patch + + +BuildRequires: cmake +BuildRequires: gcc-c++ +BuildRequires: gnupg2 +BuildRequires: openssl-devel +BuildRequires: pkgconfig +BuildRequires: zlib-devel +BuildRequires: krb5-devel +BuildRequires: libcmocka-devel +BuildRequires: pam_wrapper +BuildRequires: socket_wrapper +BuildRequires: nss_wrapper +BuildRequires: uid_wrapper +BuildRequires: priv_wrapper +BuildRequires: openssh-clients +BuildRequires: openssh-server +BuildRequires: nmap-ncat +BuildRequires: pkcs11-provider +BuildRequires: p11-kit-devel +BuildRequires: p11-kit-server +BuildRequires: opensc +BuildRequires: softhsm +BuildRequires: gnutls-utils + +Requires: %{name}-config = %{version}-%{release} + +Recommends: crypto-policies + +%ifarch aarch64 ppc64 ppc64le s390x x86_64 riscv64 +Provides: libssh_threads.so.4()(64bit) +%else +Provides: libssh_threads.so.4 +%endif + +%description +The ssh library was designed to be used by programmers needing a working SSH +implementation by the mean of a library. The complete control of the client is +made by the programmer. With libssh, you can remotely execute programs, transfer +files, use a secure and transparent tunnel for your remote programs. With its +Secure FTP implementation, you can play with remote files easily, without +third-party programs others than libcrypto (from openssl). + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: cmake-filesystem + +%description devel +The %{name}-devel package contains libraries and header files for developing +applications that use %{name}. + +%package config +Summary: Configuration files for %{name} +BuildArch: noarch +Obsoletes: %{name} < 0.9.0-3 + +%description config +The %{name}-config package provides the default configuration files for %{name}. + +%prep +gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} +%autosetup -p1 + +%build +%cmake \ + -DUNIT_TESTING=ON \ + -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" + +%cmake_build + +%install +%cmake_install +install -d -m755 %{buildroot}%{_sysconfdir}/libssh +install -m644 %{SOURCE3} %{buildroot}%{_sysconfdir}/libssh/libssh_client.config +install -m644 %{SOURCE4} %{buildroot}%{_sysconfdir}/libssh/libssh_server.config + +# +# Workaround for the removal of libssh_threads.so +# +# This will allow libraries which link against libssh_threads.so or packages +# requiring it to continue working. +# +pushd %{buildroot}%{_libdir} +for i in libssh.so*; +do + _target="${i}" + _link_name="${i%libssh*}libssh_threads${i##*libssh}" + if [ -L "${i}" ]; then + _target="$(readlink ${i})" + fi + ln -s "${_target}" "${_link_name}" +done; +popd + +%ldconfig_scriptlets + +%check +# Tests are randomly failing when run in parallel +%global _smp_build_ncpus 1 +%ctest + +%files +%doc AUTHORS BSD CHANGELOG README +%license COPYING +%{_libdir}/libssh.so.4* +%{_libdir}/libssh_threads.so.4* + +%files devel +%{_includedir}/libssh/ +%{_libdir}/cmake/libssh/ +%{_libdir}/pkgconfig/libssh.pc +%{_libdir}/libssh.so +%{_libdir}/libssh_threads.so + +%files config +%attr(0755,root,root) %dir %{_sysconfdir}/libssh +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_client.config +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_server.config + +%changelog +* Fri Oct 25 2024 MSVSphere Packaging Team - 0.10.6-8 +- Rebuilt for MSVSphere 10 + +* Tue Aug 20 2024 Jakub Jelen - 0.10.6-8 +- Remove the dependency on engine.h + +* Mon Jun 24 2024 Troy Dawson - 0.10.6-7 +- Bump release for June 2024 mass rebuild + +* Fri Jun 07 2024 David Abdurachmanov - 0.10.6-6 +- Add riscv64 + +* 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 + +* Sun Jan 21 2024 Fedora Release Engineering - 0.10.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Dec 22 2023 Jakub Jelen - 0.10.6-2 +- Fix regression in IPv6 hosntames parsing + +* Mon Dec 18 2023 Jakub Jelen - 0.10.6-1 +- New upstream release fixing (CVE-2023-48795, CVE-2023-6004, CVE-2023-6918) + +* Thu Jul 20 2023 Fedora Release Engineering - 0.10.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Fri May 05 2023 Orion Poplawski - 0.10.5-1 +- Update to 0.10.5 (CVE-2023-1667 CVE-2023-2283) +- Have libssh-devel require cmake-filesystem + +* Sun Mar 05 2023 Andreas Schneider - 0.10.4-4 +- Update License to SPDX expression + +* Thu Jan 19 2023 Fedora Release Engineering - 0.10.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Thu Oct 06 2022 Norbert Pocs - 0.10.4-2 +- Enable pkcs11 support + +* Wed Sep 07 2022 Andreas Schneider - 0.10.4-1 +- Update to version 0.10.4 + https://git.libssh.org/projects/libssh.git/tag/?h=libssh-0.10.4 + +* Fri Sep 02 2022 Andreas Schneider - 0.10.3-1 +- Update to version 0.10.3 + https://git.libssh.org/projects/libssh.git/tag/?h=libssh-0.10.3 + https://git.libssh.org/projects/libssh.git/tag/?h=libssh-0.10.2 + https://git.libssh.org/projects/libssh.git/tag/?h=libssh-0.10.1 + https://git.libssh.org/projects/libssh.git/tag/?h=libssh-0.10.0 +- Removed libssh-0.9.6-openssh-8.8p1-compat.patch +- resolves: rhbz#2121741 + +* Thu Jul 21 2022 Fedora Release Engineering - 0.9.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Fri Jan 28 2022 Jakub Jelen - 0.9.6-4 +- Fix build-time tests to work with OpenSSH 8.8p1 + +* Thu Jan 20 2022 Fedora Release Engineering - 0.9.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Mon Jan 10 2022 Stephen Gallagher - 0.9.6-2 +- Skip broken torture_auth tests + +* Wed Sep 15 2021 Norbert Pocs - 0.9.6-1 +- Fix CVE-CVE-2021-3634 libssh: possible heap-based buffer + overflow when rekeying +- Resolves: rhbz#1994600 + +* Tue Sep 14 2021 Sahana Prasad - 0.9.5-4 +- Rebuilt with OpenSSL 3.0.0 + +* Thu Jul 22 2021 Fedora Release Engineering - 0.9.5-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Tue Jan 26 2021 Fedora Release Engineering - 0.9.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Thu Sep 10 2020 Anderson Sasaki - 0.9.5-1 +- Update to version 0.9.5 + https://www.libssh.org/2020/09/10/libssh-0-9-5/ +- Removed patch to re-enable algorithms using sha1 in sshd for testing +- The algorithms supported by sshd are now automatically detected for testing +- Resolves: #1862457 - CVE-2020-16135 + +* Sat Aug 01 2020 Fedora Release Engineering - 0.9.4-5 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 28 2020 Fedora Release Engineering - 0.9.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jun 22 2020 Anderson Sasaki - 0.9.4-3 +- Do not return error when server properly closed the channel (#1849069) +- Add a test for CVE-2019-14889 +- Do not parse configuration file in torture_knownhosts test + +* Wed Apr 15 2020 Anderson Sasaki - 0.9.4-2 +- Added patch to fix returned version + +* Thu Apr 09 2020 Anderson Sasaki - 0.9.4-1 +- Update to version 0.9.4 + https://www.libssh.org/2020/04/09/libssh-0-9-4-and-libssh-0-8-9-security-release/ +- Removed inclusion of OpenSSH server configuration file from + libssh_server.config +- Added patch to re-enable algorithms using sha1 in sshd for testing +- resolves: #1822529 - CVE-2020-1730 + +* Wed Jan 29 2020 Fedora Release Engineering - 0.9.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Tue Dec 10 2019 Andreas Schneider - 0.9.3-1 +- Update to version 0.9.3 +- resolves: #1781780 - Fixes CVE-2019-14889 + +* Thu Nov 07 2019 Andreas Schneider - 0.9.2-1 +- Upate to version 0.9.2 +- resolves #1769370 - Remove the docs, they can be found on https://api.libssh.org/ + +* Thu Jul 25 2019 Fedora Release Engineering - 0.9.0-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Thu Jul 11 2019 Anderson Sasaki - 0.9.0-5 +- Add Obsoletes in libssh-config to avoid conflict with old libssh which + installed the configuration files. + +* Wed Jul 10 2019 Anderson Sasaki - 0.9.0-4 +- Eliminate circular dependency with libssh-config subpackage + +* Wed Jul 10 2019 Anderson Sasaki - 0.9.0-3 +- Provide the configuration files in a separate libssh-config subpackage + +* Thu Jul 04 2019 Anderson Sasaki - 0.9.0-2 +- Do not ignore keys from known_hosts when SSH_OPTIONS_HOSTKEYS is set + +* Fri Jun 28 2019 Anderson Sasaki - 0.9.0-1 +- Fixed Release number to released format + +* Fri Jun 28 2019 Anderson Sasaki - 0.9.0-0.1 +- Update to version 0.9.0 + https://www.libssh.org/2019/06/28/libssh-0-9-0/ + +* Wed Jun 19 2019 Anderson Sasaki - 0.8.91-0.1 +- Update to 0.9.0 pre release version (0.8.91) +- Added default configuration files for client and server +- Follow system-wide crypto configuration (crypto-policies) +- Added Recommends for crypto-policies +- Use OpenSSL implementation for KDF, DH, and signatures. +- Detect FIPS mode and use only allowed algorithms +- Run client and server tests during build + +* Mon Feb 25 2019 Anderson Sasaki - 0.8.7-1 +- Update to version 0.8.7 + https://www.libssh.org/2019/02/25/libssh-0-8-7/ + +* Fri Feb 01 2019 Fedora Release Engineering - 0.8.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Tue Jan 15 2019 Anderson Sasaki - 0.8.6-2 +- Fix rsa-sha2 extension handling (#1666342) + +* Thu Jan 03 2019 Anderson Sasaki - 0.8.6-1 +- Update to version 0.8.6 + https://www.libssh.org/2018/12/24/libssh-0-8-6-xmas-edition/ + +* Mon Oct 29 2018 Andreas Schneider - 0.8.5-1 +- Update to version 0.8.5 + https://www.libssh.org/2018/10/29/libssh-0-8-5-and-libssh-0-7-7/ + +* Tue Oct 16 2018 Andreas Schneider - 0.8.4-1 +- Update to version 0.8.4 + https://www.libssh.org/2018/10/16/libssh-0-8-4-and-0-7-6-security-and-bugfix-release +- Fixes CVE-2018-10933 + +* Mon Oct 01 2018 Anderson Sasaki - 0.8.3-3 +- Fixed errors found by static code analysis + +* Tue Sep 25 2018 Anderson Sasaki - 0.8.3-2 +- Add missing libssh_threads.so link to libssh-devel package + +* Fri Sep 21 2018 Andreas Schneider - 0.8.3-1 +- Update to version 0.8.3 + https://www.libssh.org/2018/09/21/libssh-0-8-3/ + +* Thu Aug 30 2018 Andreas Schneider - 0.8.2-1 +- Update to version 0.8.2 + https://www.libssh.org/2018/08/30/libssh-0-8-2 + +* Thu Aug 16 2018 Andreas Schneider - 0.8.1-4 +- Fix link creation or RPM doesn't install it + +* Wed Aug 15 2018 Andreas Schneider - 0.8.1-3 +- Add missing so version for libssh_threads.so.4 + +* Tue Aug 14 2018 Andreas Schneider - 0.8.1-2 +- Add Provides for libssh_threads.so to unbreak applications + +* Mon Aug 13 2018 Andreas Schneider - 0.8.1-1 +- Update to version 0.8.1 + https://www.libssh.org/2018/08/13/libssh-0-8-1 +- resolves: #1615248 - pkg-config --modversion +- resolves: #1615132 - library initialization + +* Fri Aug 10 2018 Andreas Schneider - 0.8.0-1 +- Update to version 0.8.0 + https://www.libssh.org/2018/08/10/libssh-0-8-0/ + +* Fri Jul 13 2018 Fedora Release Engineering - 0.7.5-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed Mar 07 2018 Rex Dieter - 0.7.5-8 +- BR: gcc-c++, use %%make_build + +* Wed Feb 07 2018 Fedora Release Engineering - 0.7.5-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Feb 01 2018 Andreas Schneider - 0.7.5-6 +- resolves: #1540021 - Build against OpenSSL 1.1 + +* Wed Jan 31 2018 Igor Gnatenko - 0.7.5-5 +- Switch to %%ldconfig_scriptlets + +* Fri Dec 29 2017 Andreas Schneider - 0.7.5-4 +- Fix parsing ssh_config + +* Thu Aug 03 2017 Fedora Release Engineering - 0.7.5-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 0.7.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Apr 26 2017 Peter Robinson 0.7.5-1 +- Update to version 0.7.5 + +* Sat Mar 11 2017 Rex Dieter - 0.7.4-2 +- BR: compat-openssl10-devel (f26+, #1423088) +- use %%license +- -devel: drop hardcoded pkgconfig dep (let autodeps handle it) +- %%files: track library sonames, simplify -devel +- %%install: use 'install/fast' target +- .spec cosmetics, drop deprecated %%clean section + +* Wed Feb 08 2017 Andreas Schneider - 0.7.4-1 +- Update to version 0.7.4 + * Added id_ed25519 to the default identity list + * Fixed sftp EOF packet handling + * Fixed ssh_send_banner() to confirm with RFC 4253 + * Fixed some memory leaks +- resolves: #1419007 + +* Wed Feb 24 2016 Andreas Schneider - 0.7.3-1 +- resolves: #1311259 - Fix CVE-2016-0739 +- resolves: #1311332 - Update to version 0.7.3 + * Fixed CVE-2016-0739 + * Fixed ssh-agent on big endian + * Fixed some documentation issues +- Enabled GSSAPI support + +* Thu Feb 04 2016 Fedora Release Engineering - 0.7.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Oct 22 2015 Andreas Schneider - 0.7.2-2 +- resolves: #1271230 - Fix ssh-agent support on big endian + +* Wed Sep 30 2015 Andreas Schneider - 0.7.2-1 +- Update to version 0.7.2 + * Fixed OpenSSL detection on Windows + * Fixed return status for ssh_userauth_agent() + * Fixed KEX to prefer hmac-sha2-256 + * Fixed sftp packet handling + * Fixed return values of ssh_key_is_(public|private) + * Fixed bug in global success reply +- resolves: #1267346 + +* Tue Jun 30 2015 Andreas Schneider - 0.7.1-1 +- Update to version 0.7.1 + * Fixed SSH_AUTH_PARTIAL auth with auto public key + * Fixed memory leak in session options + * Fixed allocation of ed25519 public keys + * Fixed channel exit-status and exit-signal + * Reintroduce ssh_forward_listen() + +* Wed Jun 17 2015 Fedora Release Engineering - 0.7.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu May 21 2015 Orion Poplawski - 0.7.0-2 +- Add patch to fix undefined symbol: ssh_forward_listen (bug #1221310) + +* Mon May 11 2015 Andreas Schneider - 0.7.0-1 +- Update to version 0.7.0 + * Added support for ed25519 keys + * Added SHA2 algorithms for HMAC + * Added improved and more secure buffer handling code + * Added callback for auth_none_function + * Added support for ECDSA private key signing + * Added more tests + * Fixed a lot of bugs + * Improved API documentation + +* Thu Apr 30 2015 Andreas Schneider - 0.6.5-1 +- resolves: #1213775 - Security fix for CVE-2015-3146 +- resolves: #1218076 - Security fix for CVE-2015-3146 + +* Fri Dec 19 2014 - Andreas Schneider - 0.6.4-1 +- Security fix for CVE-2014-8132. + +* Sun Aug 17 2014 Fedora Release Engineering - 0.6.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jun 07 2014 Fedora Release Engineering - 0.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Mar 04 2014 - Andreas Schneider - 0.6.3-1 +- Fix CVE-2014-0017. + +* Mon Feb 10 2014 - Andreas Schneider - 0.6.1-1 +- Update to version 0.6.1. +- resolves: #1056757 - Fix scp mode. +- resolves: #1053305 - Fix known_hosts heuristic. + +* Wed Jan 08 2014 - Andreas Schneider - 0.6.0-1 +- Update to 0.6.0 + +* Fri Jul 26 2013 - Andreas Schneider - 0.5.5-1 +- Update to 0.5.5. +- Clenup the spec file. + +* Thu Jul 18 2013 Simone Caronni - 0.5.4-5 +- Add EPEL 5 support. +- Add Debian patches to enable Doxygen documentation. + +* Tue Jul 16 2013 Simone Caronni - 0.5.4-4 +- Add patch for #982685. + +* Mon Jun 10 2013 Simone Caronni - 0.5.4-3 +- Clean up SPEC file and fix rpmlint complaints. + +* Thu Feb 14 2013 Fedora Release Engineering - 0.5.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 23 2013 Petr Lautrbach 0.5.4-1 +- update to security 0.5.4 release +- CVE-2013-0176 (#894407) + +* Tue Nov 20 2012 Petr Lautrbach 0.5.3-1 +- update to security 0.5.3 release (#878465) + +* Thu Jul 19 2012 Fedora Release Engineering - 0.5.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Feb 02 2012 Petr Lautrbach 0.5.2-1 +- update to 0.5.2 version (#730270) + +* Fri Jan 13 2012 Fedora Release Engineering - 0.5.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Jun 1 2011 Jan F. Chadima - 0.5.0-1 +- bounce versionn to 0.5.0 (#709785) +- the support for protocol v1 is disabled + +* Tue Feb 08 2011 Fedora Release Engineering - 0.4.8-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Jan 19 2011 Jan F. Chadima - 0.4.8-1 +- bounce versionn to 0.4.8 (#670456) + +* Mon Sep 6 2010 Jan F. Chadima - 0.4.6-1 +- bounce versionn to 0.4.6 (#630602) + +* Thu Jun 3 2010 Jan F. Chadima - 0.4.4-1 +- bounce versionn to 0.4.4 (#598592) + +* Wed May 19 2010 Jan F. Chadima - 0.4.3-1 +- bounce versionn to 0.4.3 (#593288) + +* Tue Mar 16 2010 Jan F. Chadima - 0.4.2-1 +- bounce versionn to 0.4.2 (#573972) + +* Tue Feb 16 2010 Jan F. Chadima - 0.4.1-1 +- bounce versionn to 0.4.1 (#565870) + +* Fri Dec 11 2009 Jan F. Chadima - 0.4.0-1 +- bounce versionn to 0.4.0 (#541010) + +* Thu Nov 26 2009 Jan F. Chadima - 0.3.92-2 +- typo in spec file + +* Thu Nov 26 2009 Jan F. Chadima - 0.3.92-1 +- bounce versionn to 0.3.92 (0.4 beta2) (#541010) + +* Fri Aug 21 2009 Tomas Mraz - 0.2-4 +- rebuilt with new openssl + +* Sat Jul 25 2009 Fedora Release Engineering - 0.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 02 2009 Jan F. Chadima - 0.2-2 +- Small changes during review + +* Mon Jun 01 2009 Jan F. Chadima - 0.2-1 +- Initial build +