*/
#include "crypto-init.h"
+
#include <mutex>
-#include <openssl/evp.h>
#include <atomic>
+#include <functional>
+#include <thread>
+#include <fstream>
+
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+
+#include <dpl/log/log.h>
namespace CKM {
+namespace {
+
+const char* DEV_HW_RANDOM_FILE = "/dev/hwrng";
+const char* DEV_URANDOM_FILE = "/dev/urandom";
+const size_t RANDOM_BUFFER_LEN = 32;
+
+std::mutex* g_mutexes = NULL;
+
+void lockingCallback(int mode, int type, const char*, int)
+{
+ if(!g_mutexes) {
+ LogError("Openssl mutexes do not exist");
+ return;
+ }
+
+ if (mode & CRYPTO_LOCK)
+ g_mutexes[type].lock();
+ else if (mode & CRYPTO_UNLOCK)
+ g_mutexes[type].unlock();
+}
+
+unsigned long threadIdCallback() {
+ std::hash<std::thread::id> hasher;
+ return hasher(std::this_thread::get_id());
+}
+
+void opensslInstallLocks()
+{
+ g_mutexes = new std::mutex[CRYPTO_num_locks()];
+
+ CRYPTO_set_id_callback(threadIdCallback);
+ CRYPTO_set_locking_callback(lockingCallback);
+}
+
+void opensslUninstallLocks()
+{
+ CRYPTO_set_id_callback(NULL);
+ CRYPTO_set_locking_callback(NULL);
+
+ delete[] g_mutexes;
+ g_mutexes = NULL;
+}
+
+} // namespace anonymous
+
+
+void initOpenSsl() {
+ // Loads all error strings (crypto and ssl)
+ SSL_load_error_strings();
+
+ /*
+ * Initialize libcrypto (add all algorithms, digests & ciphers)
+ * It also does the stuff from SSL_library_init() except for ssl_load_ciphers()
+ */
+ OpenSSL_add_all_algorithms(); // Can be optimized by using EVP_add_cipher instead
+
+ /*
+ * Initialize libssl (OCSP uses it)
+ * SSL_library_init() == OpenSSL_add_ssl_algorithms()
+ * It always returns 1
+ */
+ SSL_library_init();
+
+ // load default configuration (/etc/ssl/openssl.cnf)
+ OPENSSL_config(NULL);
+
+ // enable FIPS mode by default
+ if(0 == FIPS_mode_set(1)) {
+ LogError("Failed to set FIPS mode");
+ }
+
+ /*
+ * Initialize entropy
+ * entropy sources - /dev/random,/dev/urandom(Default)
+ */
+ int ret = 0;
+
+ std::ifstream ifile(DEV_HW_RANDOM_FILE);
+ if(ifile.is_open())
+ ret= RAND_load_file(DEV_HW_RANDOM_FILE, RANDOM_BUFFER_LEN);
+
+ if(ret != RANDOM_BUFFER_LEN ){
+ LogWarning("Error in HW_RAND file load");
+ ret = RAND_load_file(DEV_URANDOM_FILE, RANDOM_BUFFER_LEN);
+
+ if(ret != RANDOM_BUFFER_LEN)
+ LogError("Error in U_RAND_file_load");
+ }
+
+ // Install locks for multithreading support
+ opensslInstallLocks();
+}
+
+void deinitOpenSsl() {
+ opensslUninstallLocks();
+ CONF_modules_unload(1);
+ EVP_cleanup();
+ ERR_free_strings();
+ deinitOpenSslThread();
+}
+
+void deinitOpenSslThread() {
+ CRYPTO_cleanup_all_ex_data();
+ ERR_remove_thread_state(NULL);
+}
namespace {
std::mutex cryptoInitMutex;
-void initOpenSSL();
+void initOpenSslAndDetach();
typedef void(*initFnPtr)();
// has to be atomic as storing function pointer is not an atomic operation on armv7l
-std::atomic<initFnPtr> initFn (&initOpenSSL);
+std::atomic<initFnPtr> initFn (&initOpenSslAndDetach);
void initEmpty() {}
-void initOpenSSL() {
+void initOpenSslAndDetach() {
// DCLP
std::lock_guard<std::mutex> lock(cryptoInitMutex);
/*
*/
if(initFn.load(std::memory_order_relaxed) != &initEmpty)
{
- OpenSSL_add_all_ciphers();
- OpenSSL_add_all_algorithms();
- OpenSSL_add_all_digests();
+ initOpenSsl();
/*
* Synchronizes with load. Everything that happened before this store in this thread is
} // namespace anonymous
-void initCryptoLib() {
+void initOpenSslOnce() {
/*
* Synchronizes with store. Everything that happened before store in another thread will be
* visible in this thread after load.
* @version 1.0
*/
#include <exception>
-#include <fstream>
#include <utility>
#include <algorithm>
#define OPENSSL_SUCCESS 1 // DO NOTCHANGE THIS VALUE
#define OPENSSL_FAIL 0 // DO NOTCHANGE THIS VALUE
-#define DEV_HW_RANDOM_FILE "/dev/hwrng"
-#define DEV_URANDOM_FILE "/dev/urandom"
namespace CKM {
namespace Crypto {
} // anonymous namespace
-int initialize() {
- int hw_rand_ret = 0;
- int u_rand_ret = 0;
-
- // try to initialize using ERR_load_crypto_strings and OpenSSL_add_all_algorithms
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
-
- // initialize entropy
- std::ifstream ifile(DEV_HW_RANDOM_FILE);
- if(ifile.is_open()) {
- u_rand_ret= RAND_load_file(DEV_HW_RANDOM_FILE, 32);
- }
- if(u_rand_ret != 32 ){
- LogError("Error in HW_RAND file load");
- hw_rand_ret = RAND_load_file(DEV_URANDOM_FILE, 32);
-
- if(hw_rand_ret != 32) {
- ThrowErr(Exc::Crypto::InternalError, "Error in U_RAND_file_load");
- }
- }
-
- return CKM_CRYPTO_INIT_SUCCESS;
-}
-
const EVP_MD *getMdAlgo(const HashAlgorithm hashAlgo) {
const EVP_MD *md_algo=NULL;
switch(hashAlgo) {
#include <stdlib.h>
#include <signal.h>
-#include <openssl/ssl.h>
-#include <openssl/conf.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-
#include <dpl/log/log.h>
#include <dpl/singleton.h>
#include <ckm-service.h>
#include <ocsp-service.h>
#include <encryption-service.h>
+#include <crypto-init.h>
#include <key-provider.h>
#include <file-system.h>
}
LogInfo("Init external libraries SKMM and openssl");
- SSL_load_error_strings();
- SSL_library_init();
- OpenSSL_add_all_ciphers();
- OPENSSL_config(NULL);
+ CKM::initOpenSsl();
CKM::KeyProvider::initializeLibrary();
// Manager has been destroyed and we may close external libraries.
LogInfo("Deinit SKMM and openssl");
CKM::KeyProvider::closeLibrary();
- // Deinit OPENSSL ?
- EVP_cleanup();
- ERR_free_strings();
+
+ CKM::deinitOpenSsl();
}
catch (const std::runtime_error& e)
{