From ea700d80f5d65f7d6c4cab4ccd09192467b15204 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Mon, 13 May 2013 16:05:56 +0200 Subject: [PATCH] Cross-platform and (truly) thread-safe OpenSSL initialization. --- src/net/tls/openssl/OpenSSLInitializer.cpp | 76 ++++++++----------- src/net/tls/openssl/TLSSession_OpenSSL.cpp | 6 +- src/net/tls/openssl/TLSSocket_OpenSSL.cpp | 4 + .../cert/openssl/X509Certificate_OpenSSL.cpp | 6 +- vmime/net/tls/openssl/OpenSSLInitializer.hpp | 21 +++-- 5 files changed, 58 insertions(+), 55 deletions(-) diff --git a/src/net/tls/openssl/OpenSSLInitializer.cpp b/src/net/tls/openssl/OpenSSLInitializer.cpp index dce86179..8238b864 100644 --- a/src/net/tls/openssl/OpenSSLInitializer.cpp +++ b/src/net/tls/openssl/OpenSSLInitializer.cpp @@ -50,79 +50,69 @@ namespace tls { ref * OpenSSLInitializer::sm_mutexes; -int OpenSSLInitializer::sm_initCount(0); -OpenSSLInitializer::OpenSSLInitializer() +OpenSSLInitializer::autoInitializer::autoInitializer() +{ + // The construction of this unique 'oneTimeInitializer' object will be triggered + // by the 'autoInitializer' objects from the other translation units + static OpenSSLInitializer::oneTimeInitializer oneTimeInitializer; +} + + +OpenSSLInitializer::autoInitializer::~autoInitializer() +{ +} + + +OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() { initialize(); } -OpenSSLInitializer::~OpenSSLInitializer() +OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() { uninitialize(); } -// static -ref OpenSSLInitializer::getMutex() -{ - static ref criticalSection - = vmime::platform::getHandler()->createCriticalSection(); - - return criticalSection; -} - - // static void OpenSSLInitializer::initialize() { - ref mutex = getMutex(); - vmime::utility::sync::autoLock lock(mutex); - - if (++sm_initCount == 1) - { #if OPENSSL_VERSION_NUMBER >= 0x0907000L - OPENSSL_config(NULL); + OPENSSL_config(NULL); #endif - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + SSL_library_init(); + OpenSSL_add_all_algorithms(); - unsigned char seed[SEEDSIZE]; - vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE); - RAND_seed(seed, SEEDSIZE); + unsigned char seed[SEEDSIZE]; + vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE); + RAND_seed(seed, SEEDSIZE); - int numMutexes = CRYPTO_num_locks(); - sm_mutexes = new ref [numMutexes]; + int numMutexes = CRYPTO_num_locks(); + sm_mutexes = new ref [numMutexes]; - for (int i = 0 ; i < numMutexes ; ++i) - sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); + for (int i = 0 ; i < numMutexes ; ++i) + sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); - CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); - CRYPTO_set_id_callback(&OpenSSLInitializer::id); - } + CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); + CRYPTO_set_id_callback(&OpenSSLInitializer::id); } // static void OpenSSLInitializer::uninitialize() { - ref mutex = getMutex(); - vmime::utility::sync::autoLock lock(mutex); + EVP_cleanup(); + ERR_free_strings(); - if (--sm_initCount == 0) - { - EVP_cleanup(); - ERR_free_strings(); + CRYPTO_set_locking_callback(NULL); + CRYPTO_set_id_callback(NULL); - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - delete [] sm_mutexes; - } + delete [] sm_mutexes; } diff --git a/src/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/net/tls/openssl/TLSSession_OpenSSL.cpp index a18e2958..fcf82c7b 100644 --- a/src/net/tls/openssl/TLSSession_OpenSSL.cpp +++ b/src/net/tls/openssl/TLSSession_OpenSSL.cpp @@ -41,6 +41,9 @@ namespace net { namespace tls { +static OpenSSLInitializer::autoInitializer openSSLInitializer; + + // static ref TLSSession::create(ref cv) { @@ -51,9 +54,6 @@ ref TLSSession::create(ref cv TLSSession_OpenSSL::TLSSession_OpenSSL(ref cv) : m_sslctx(0), m_certVerifier(cv) { - // Thread-safe OpenSSL initialization - static OpenSSLInitializer openSSLInitialization; - m_sslctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY); diff --git a/src/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/net/tls/openssl/TLSSocket_OpenSSL.cpp index b8ac18e9..7fda1f15 100644 --- a/src/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ b/src/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -32,6 +32,7 @@ #include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp" #include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp" +#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" #include "vmime/platform.hpp" @@ -45,6 +46,9 @@ namespace net { namespace tls { +static OpenSSLInitializer::autoInitializer openSSLInitializer; + + // static BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = { diff --git a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp index 056631ec..20df3739 100644 --- a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -59,6 +59,9 @@ namespace security { namespace cert { +static net::tls::OpenSSLInitializer::autoInitializer openSSLInitializer; + + #ifndef VMIME_BUILDING_DOC class monthMap @@ -107,9 +110,6 @@ struct OpenSSLX509CertificateInternalData { OpenSSLX509CertificateInternalData() { - // Thread-safe OpenSSL initialization - static net::tls::OpenSSLInitializer openSSLInitialization; - cert = 0; } diff --git a/vmime/net/tls/openssl/OpenSSLInitializer.hpp b/vmime/net/tls/openssl/OpenSSLInitializer.hpp index 9c85ef25..5277d4ff 100644 --- a/vmime/net/tls/openssl/OpenSSLInitializer.hpp +++ b/vmime/net/tls/openssl/OpenSSLInitializer.hpp @@ -48,19 +48,29 @@ namespace tls { */ class OpenSSLInitializer { - public: /** Automatically initialize OpenSSL */ - OpenSSLInitializer(); + class autoInitializer + { + public: - /** Automatically uninitialize OpenSSL - */ - ~OpenSSLInitializer(); + autoInitializer(); + ~autoInitializer(); + }; protected: + class oneTimeInitializer + { + public: + + oneTimeInitializer(); + ~oneTimeInitializer(); + }; + + /** Initializes the OpenSSL lib */ static void initialize(); @@ -85,7 +95,6 @@ protected: private: static ref * sm_mutexes; - static int sm_initCount; };