diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h index cc1ae56d..f40d76b9 100644 --- a/include/libssh/crypto.h +++ b/include/libssh/crypto.h @@ -223,5 +223,8 @@ 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 +ENGINE *pki_get_engine(void); +#endif /* HAVE_LIBCRYPTO */ #endif /* _CRYPTO_H_ */ diff --git a/src/libcrypto.c b/src/libcrypto.c index 77877eb4..e974248d 100644 --- a/src/libcrypto.c +++ b/src/libcrypto.c @@ -85,6 +85,8 @@ static int libcrypto_initialized = 0; +static ENGINE *engine = NULL; + void ssh_reseed(void){ #ifndef _WIN32 struct timeval tv; @@ -93,6 +95,36 @@ void ssh_reseed(void){ #endif } +ENGINE *pki_get_engine(void) +{ + int ok; + + if (engine == NULL) { + ENGINE_load_builtin_engines(); + + engine = ENGINE_by_id("pkcs11"); + if (engine == NULL) { + SSH_LOG(SSH_LOG_WARN, + "Could not load the engine: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NULL; + } + SSH_LOG(SSH_LOG_INFO, "Engine loaded successfully"); + + ok = ENGINE_init(engine); + if (!ok) { + SSH_LOG(SSH_LOG_WARN, + "Could not initialize the engine: %s", + ERR_error_string(ERR_get_error(), NULL)); + ENGINE_free(engine); + return NULL; + } + + SSH_LOG(SSH_LOG_INFO, "Engine init success"); + } + return engine; +} + #ifdef HAVE_OPENSSL_ECC static const EVP_MD *nid_to_evpmd(int nid) { @@ -1393,6 +1425,17 @@ void ssh_crypto_finalize(void) return; } +/* TODO this should finalize engine if it was started, but during atexit calls, + * we are crashing. AFAIK this is related to the dlopened pkcs11 modules calling + * the crypto cleanups earlier. */ +#if 0 + if (engine != NULL) { + ENGINE_finish(engine); + ENGINE_free(engine); + engine = NULL; + } +#endif + #if OPENSSL_VERSION_NUMBER < 0x10100000L ENGINE_cleanup(); EVP_cleanup(); diff --git a/src/pki_crypto.c b/src/pki_crypto.c index a5a6a186..1a35df3e 100644 --- a/src/pki_crypto.c +++ b/src/pki_crypto.c @@ -3461,29 +3461,13 @@ int pki_uri_import(const char *uri_name, #endif ssh_key key = NULL; enum ssh_keytypes_e type = SSH_KEYTYPE_UNKNOWN; - int ok; - ENGINE_load_builtin_engines(); - - engine = ENGINE_by_id("pkcs11"); + /* Do the init only once */ + engine = pki_get_engine(); if (engine == NULL) { - SSH_LOG(SSH_LOG_WARN, - "Could not load the engine: %s", - ERR_error_string(ERR_get_error(),NULL)); - return SSH_ERROR; + SSH_LOG(SSH_LOG_WARN, "Failed to initialize engine"); + goto fail; } - SSH_LOG(SSH_LOG_INFO, "Engine loaded successfully"); - - ok = ENGINE_init(engine); - if (!ok) { - SSH_LOG(SSH_LOG_WARN, - "Could not initialize the engine: %s", - ERR_error_string(ERR_get_error(),NULL)); - ENGINE_free(engine); - return SSH_ERROR; - } - - SSH_LOG(SSH_LOG_INFO, "Engine init success"); switch (key_type) { case SSH_KEY_PRIVATE: @@ -3593,14 +3577,10 @@ int pki_uri_import(const char *uri_name, #endif *nkey = key; - ENGINE_finish(engine); - ENGINE_free(engine); return SSH_OK; fail: - ENGINE_finish(engine); - ENGINE_free(engine); EVP_PKEY_free(pkey); ssh_key_free(key); #if OPENSSL_VERSION_NUMBER < 0x30000000L