From 962012bbf66895bc50b35eaf2ef47a8a7a2dbccd Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Mon, 2 Jun 2025 17:44:43 +0200 Subject: [PATCH] Cleanup the loaded pkcs11 provider Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider (cherry picked from commit 62762bbbc93f66e4a7aef998be18a4fcd99e22c5) --- include/libssh/crypto.h | 3 --- include/libssh/libcrypto.h | 9 ++++++++ src/libcrypto.c | 46 +++++++++++++++++++++++++++++++++++--- src/pki_crypto.c | 21 ++++------------- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index 04b5c80e..92a6357c 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -223,9 +223,6 @@ 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); -#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER) -ENGINE *pki_get_engine(void); -#endif /* HAVE_LIBCRYPTO */ void compress_cleanup(struct ssh_crypto_struct *crypto); diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h index 2f6bdc0a..f9aea0d7 100644 --- a/include/libssh/libcrypto.h +++ b/include/libssh/libcrypto.h @@ -121,6 +121,15 @@ typedef BN_CTX* bignum_CTX; 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); + +#if defined(WITH_PKCS11_URI) +#if defined(WITH_PKCS11_PROVIDER) +int pki_load_pkcs11_provider(void); +#else +ENGINE *pki_get_engine(void); +#endif +#endif /* WITH_PKCS11_PROVIDER */ + #endif /* HAVE_LIBCRYPTO */ #endif /* LIBCRYPTO_H_ */ diff --git a/src/libcrypto.c b/src/libcrypto.c index 8af28f32..e21a82bc 100644 --- a/src/libcrypto.c +++ b/src/libcrypto.c @@ -49,8 +49,9 @@ #include #include #else -#include #include +#include +#include #endif /* OPENSSL_VERSION_NUMBER */ #include #if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) @@ -96,7 +97,37 @@ void ssh_reseed(void){ #endif } -#if defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) +#if defined(WITH_PKCS11_URI) +#if defined(WITH_PKCS11_PROVIDER) +static OSSL_PROVIDER *provider = NULL; +static bool pkcs11_provider_failed = false; + +int pki_load_pkcs11_provider(void) +{ + if (OSSL_PROVIDER_available(NULL, "pkcs11") == 1) { + /* the provider is already available. + * Loaded through a configuration file? */ + return SSH_OK; + } + + if (pkcs11_provider_failed) { + /* the loading failed previously -- do not retry */ + return SSH_ERROR; + } + + provider = OSSL_PROVIDER_try_load(NULL, "pkcs11", 1); + if (provider != NULL) { + return SSH_OK; + } + + SSH_LOG(SSH_LOG_TRACE, + "Failed to load the pkcs11 provider: %s", + ERR_error_string(ERR_get_error(), NULL)); + /* Do not attempt to load it again */ + pkcs11_provider_failed = true; + return SSH_ERROR; +} +#else static ENGINE *engine = NULL; ENGINE *pki_get_engine(void) @@ -128,7 +159,8 @@ ENGINE *pki_get_engine(void) } return engine; } -#endif /* defined(WITH_PKCS11_URI) && !defined(WITH_PKCS11_PROVIDER) */ +#endif /* defined(WITH_PKCS11_PROVIDER) */ +#endif /* defined(WITH_PKCS11_URI) */ #ifdef HAVE_OPENSSL_EVP_KDF_CTX #if OPENSSL_VERSION_NUMBER < 0x30000000L @@ -1402,6 +1434,14 @@ void ssh_crypto_finalize(void) engine = NULL; } #endif +#if defined(WITH_PKCS11_URI) +#if defined(WITH_PKCS11_PROVIDER) + if (provider != NULL) { + OSSL_PROVIDER_unload(provider); + provider = NULL; + } +#endif /* WITH_PKCS11_PROVIDER */ +#endif /* WITH_PKCS11_URI */ libcrypto_initialized = 0; } diff --git a/src/pki_crypto.c b/src/pki_crypto.c index 42ff2271..cbe8e290 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -46,7 +46,6 @@ #include #if defined(WITH_PKCS11_URI) && defined(WITH_PKCS11_PROVIDER) #include -#include #endif #endif /* OPENSSL_VERSION_NUMBER */ @@ -2719,9 +2718,6 @@ error: } #ifdef WITH_PKCS11_URI -#ifdef WITH_PKCS11_PROVIDER -static bool pkcs11_provider_failed = false; -#endif /** * @internal @@ -2787,19 +2783,10 @@ int pki_uri_import(const char *uri_name, /* 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; - } + rv = pki_load_pkcs11_provider(); + if (rv != SSH_OK) { + SSH_LOG(SSH_LOG_TRACE, "Failed to load or initialize pkcs11 provider"); + goto fail; } store = OSSL_STORE_open(uri_name, NULL, NULL, NULL, NULL);