libssh/libssh-0.10.6-pkcs11-provider.patch
Sahana Prasad 73ed6c83ad Build libssh with pkcs11-provider instead of pkcs11 engine
Resolves: RHEL-30437

Signed-off-by: Sahana Prasad <sahana@redhat.com>
2024-05-22 12:43:58 +02:00

4070 lines
128 KiB
Diff

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 <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
@@ -32,6 +33,7 @@
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
+#include <openssl/ec.h>
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 <openssl/ecdh.h>
-/* 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, &params);
- 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 <string.h>
-#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 <openssl/rsa.h>
-#include <openssl/dsa.h>
-#include <openssl/ecdsa.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/bn.h>
-
-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, &params);
+ /* 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, &params);
- if (rc != 1) {
- EVP_PKEY_CTX_free(ctx);
- return -1;
- }
+ rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, &params);
+ 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 <openssl/params.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
+#if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER)
+#include <openssl/store.h>
+#include <openssl/provider.h>
+#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, &params);
@@ -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, &params);
@@ -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, &params);
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" <<EOF
+ # Create SoftHSM configuration file
+ cat >"$TESTDIR/softhsm.conf" <<EOF
directories.tokendir = $TESTDIR/db
objectstore.backend = file
log.level = DEBUG
EOF
-export SOFTHSM2_CONF=$TESTDIR/softhsm.conf
+ cat "$TESTDIR/softhsm.conf"
+fi
-cat "$TESTDIR/softhsm.conf"
+export SOFTHSM2_CONF=$TESTDIR/softhsm.conf
-#init
-cmd="softhsm2-util --init-token --label $OBJNAME --free --pin 1234 --so-pin 1234"
+#init -- each object will have its own token
+cmd="softhsm2-util --init-token --label $TOKENLABEL --free --pin 1234 --so-pin 1234"
eval echo "$cmd"
out=$(eval "$cmd")
ret=$?
@@ -43,7 +48,7 @@ if [ $ret -ne 0 ]; then
fi
#load private key
-cmd="p11tool --provider $LIBSOFTHSM_PATH --write --load-privkey $PRIVKEY --label $OBJNAME --login --set-pin=1234 \"pkcs11:token=$OBJNAME\""
+cmd="p11tool --provider $LIBSOFTHSM_PATH --write --load-privkey $PRIVKEY --label $OBJNAME --login --set-pin=1234 \"pkcs11:token=$TOKENLABEL\""
eval echo "$cmd"
out=$(eval "$cmd")
ret=$?
@@ -59,7 +64,7 @@ ls -l "$TESTDIR"
if [ "$LOADPUBLIC" -ne 0 ]; then
#load public key
- cmd="p11tool --provider $LIBSOFTHSM_PATH --write --load-pubkey $PUBKEY --label $OBJNAME --login --set-pin=1234 \"pkcs11:token=$OBJNAME\""
+ cmd="p11tool --provider $LIBSOFTHSM_PATH --write --load-pubkey $PUBKEY --label $OBJNAME --login --set-pin=1234 \"pkcs11:token=$TOKENLABEL\""
eval echo "$cmd"
out=$(eval "$cmd")
ret=$?
@@ -70,7 +75,7 @@ if [ "$LOADPUBLIC" -ne 0 ]; then
fi
fi
-cmd="p11tool --list-all --login \"pkcs11:token=$OBJNAME\" --set-pin=1234"
+cmd="p11tool --list-all --login \"pkcs11:token=$TOKENLABEL\" --set-pin=1234"
eval echo "$cmd"
out=$(eval "$cmd")
ret=$?
@@ -81,4 +86,55 @@ if [ $ret -ne 0 ]; then
fi
echo "$out"
+# Skip the p11-kit if not needed
+if [ -z "$P11_KIT_CLIENT" ]; then
+ exit 0
+fi
+
+# when creating more keys, we need to restart the p11-kit
+# so it can pick up the new keys
+if [ -h "$TESTDIR/p11-kit-server.socket" ]; then
+ kill -9 $(cat $TESTDIR/p11-kit-server.pid)
+ rm $TESTDIR/p11-kit-server.socket
+fi
+
+# p11-kit complains if there is no runtime directory
+if [ -z "$XDG_RUNTIME_DIR" ]; then
+ export XDG_RUNTIME_DIR=$PWD
+fi
+
+# Start the p11-kit server
+cmd="p11-kit server --provider $LIBSOFTHSM_PATH pkcs11:"
+echo "$cmd"
+out=$(eval "$cmd")
+ret=$?
+if [ $ret -ne 0 ]; then
+ echo "Starting p11-kit server failed"
+ echo "$out"
+ exit 1
+fi
+eval $out
+
+# Symlink the p11-kit-server socket to "known place"
+P11_KIT_SERVER_ADDRESS_PATH=${P11_KIT_SERVER_ADDRESS:10}
+cmd="ln -s $P11_KIT_SERVER_ADDRESS_PATH $TESTDIR/p11-kit-server.socket"
+echo "$cmd"
+out=$(eval "$cmd")
+
+# Save the PID for the C code to clean up
+cmd="echo $P11_KIT_SERVER_PID > $TESTDIR/p11-kit-server.pid"
+echo "$cmd"
+out=$(eval "$cmd")
+
+cmd="pkcs11-tool -O --login --pin=1234 --module=$P11_KIT_CLIENT --token-label=$TOKENLABEL"
+echo "$cmd"
+out=$(eval "$cmd")
+ret=$?
+echo "$out"
+if [ $ret -ne 0 ]; then
+ echo "Failed to list keys through p11-kit remoting"
+ echo "$out"
+ exit 1
+fi
+
exit 0
diff --git a/tests/tests_config.h.cmake b/tests/tests_config.h.cmake
index a8147c44..92a08781 100644
--- a/tests/tests_config.h.cmake
+++ b/tests/tests_config.h.cmake
@@ -70,3 +70,4 @@
#cmakedefine WITH_TIMEOUT ${WITH_TIMEOUT}
#cmakedefine TIMEOUT_EXECUTABLE "${TIMEOUT_EXECUTABLE}"
#cmakedefine SOFTHSM2_LIBRARY "${SOFTHSM2_LIBRARY}"
+#cmakedefine P11_KIT_CLIENT "${P11_KIT_CLIENT}"
diff --git a/tests/torture.c b/tests/torture.c
index 6b2d5b7b..35f7d80b 100644
--- a/tests/torture.c
+++ b/tests/torture.c
@@ -1238,19 +1238,60 @@ void torture_setup_tokens(const char *temp_dir,
const char *load_public)
{
char token_setup_start_cmd[1024] = {0};
+ char socket_path[1204] = {0};
+ char conf_path[1024] = {0};
int rc;
- snprintf(token_setup_start_cmd, sizeof(token_setup_start_cmd),
- "%s/tests/pkcs11/setup-softhsm-tokens.sh %s %s %s %s %s",
- BINARYDIR,
- temp_dir,
- filename,
- object_name,
- load_public,
- SOFTHSM2_LIBRARY);
+ rc = snprintf(token_setup_start_cmd,
+ sizeof(token_setup_start_cmd),
+ "%s/tests/pkcs11/setup-softhsm-tokens.sh %s %s %s %s %s %s",
+ BINARYDIR,
+ temp_dir,
+ filename,
+ object_name,
+ load_public,
+ SOFTHSM2_LIBRARY,
+#ifdef WITH_PKCS11_PROVIDER
+ P11_KIT_CLIENT
+#else
+ ""
+#endif
+ );
+ assert_int_not_equal(rc, sizeof(token_setup_start_cmd));
rc = system(token_setup_start_cmd);
assert_return_code(rc, errno);
+
+#ifdef WITH_PKCS11_PROVIDER
+ rc = snprintf(socket_path,
+ sizeof(socket_path),
+ "unix:path=%s/p11-kit-server.socket",
+ temp_dir);
+ assert_int_not_equal(rc, sizeof(socket_path));
+ setenv("P11_KIT_SERVER_ADDRESS", socket_path, 1);
+
+ setenv("PKCS11_PROVIDER_MODULE", P11_KIT_CLIENT, 1);
+ /* This is useful for debugging PKCS#11 calls */
+ // setenv("PKCS11SPY", P11_KIT_CLIENT, 1);
+ // setenv("PKCS11_PROVIDER_MODULE", "/usr/lib64/pkcs11-spy.so", 1);
+#else
+ snprintf(conf_path, sizeof(conf_path), "%s/softhsm.conf", temp_dir);
+ setenv("SOFTHSM2_CONF", conf_path, 1);
+#endif /* WITH_PKCS11_PROVIDER */
+}
+
+void torture_cleanup_tokens(const char *temp_dir)
+{
+ char pidfile[1024] = {0};
+ int rc;
+ pid_t pid;
+
+#ifdef WITH_PKCS11_PROVIDER
+ snprintf(pidfile, sizeof(pidfile), "%s/p11-kit-server.pid", temp_dir);
+ torture_terminate_process(pidfile);
+#else
+ unsetenv("SOFTHSM2_CONF");
+#endif /* WITH_PKCS11_PROVIDER */
}
#endif /* WITH_PKCS11_URI */
diff --git a/tests/torture.h b/tests/torture.h
index 498acf60..36f28f38 100644
--- a/tests/torture.h
+++ b/tests/torture.h
@@ -135,6 +135,7 @@ void torture_setup_tokens(const char *temp_dir,
const char *filename,
const char object_name[],
const char *load_public);
+void torture_cleanup_tokens(const char *temp_dir);
#endif /* WITH_PKCS11_URI */
void torture_reset_config(ssh_session session);
diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt
index f85da72b..58c5b6d7 100644
--- a/tests/unittests/CMakeLists.txt
+++ b/tests/unittests/CMakeLists.txt
@@ -76,6 +76,7 @@ if (UNIX AND NOT WIN32)
torture_pki_rsa_uri
torture_pki_ecdsa_uri
)
+ list(APPEND TORTURE_UNIT_ENVIRONMENT PKCS11_PROVIDER_DEBUG=file:/tmp/p11prov-debug.log)
endif()
if (HAVE_ECC)
diff --git a/tests/unittests/torture_pki_ecdsa_uri.c b/tests/unittests/torture_pki_ecdsa_uri.c
index 038780db..a2bdae8f 100644
--- a/tests/unittests/torture_pki_ecdsa_uri.c
+++ b/tests/unittests/torture_pki_ecdsa_uri.c
@@ -31,7 +31,7 @@
#define PUB_URI_FMT_384_INVALID_TOKEN "pkcs11:token=ecdsa521;object=ecdsa384;type=public"
#define PUB_URI_FMT_521_INVALID_OBJECT "pkcs11:token=ecdsa521;object=ecdsa384;type=public"
-const char template[] = "temp_dir_XXXXXX";
+const char template[] = "/tmp/temp_dir_XXXXXX";
const unsigned char INPUT[] = "1234567890123456789012345678901234567890"
"123456789012345678901234";
struct pki_st {
@@ -80,7 +80,6 @@ static int setup_directory_structure(void **state)
struct pki_st *test_state = NULL;
char *temp_dir;
int rc;
- char conf_path[1024] = {0};
test_state = (struct pki_st *)malloc(sizeof(struct pki_st));
assert_non_null(test_state);
@@ -100,9 +99,6 @@ static int setup_directory_structure(void **state)
*state = test_state;
- snprintf(conf_path, sizeof(conf_path), "%s/softhsm.conf", test_state->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;
}