2 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 * @file crypto-init.cpp
18 * @author Maciej Karpiuk (m.karpiuk2@samsung.com)
22 #include "crypto-init.h"
30 #include <openssl/evp.h>
31 #include <openssl/crypto.h>
32 #include <openssl/ssl.h>
33 #include <openssl/conf.h>
34 #include <openssl/err.h>
35 #include <openssl/rand.h>
37 #include <dpl/log/log.h>
42 const char* DEV_HW_RANDOM_FILE = "/dev/hwrng";
43 const char* DEV_URANDOM_FILE = "/dev/urandom";
44 const size_t RANDOM_BUFFER_LEN = 32;
46 std::mutex* g_mutexes = NULL;
48 void lockingCallback(int mode, int type, const char*, int)
51 LogError("Openssl mutexes do not exist");
55 if (mode & CRYPTO_LOCK)
56 g_mutexes[type].lock();
57 else if (mode & CRYPTO_UNLOCK)
58 g_mutexes[type].unlock();
61 unsigned long threadIdCallback() {
62 std::hash<std::thread::id> hasher;
63 return hasher(std::this_thread::get_id());
66 void opensslInstallLocks()
68 g_mutexes = new std::mutex[CRYPTO_num_locks()];
70 CRYPTO_set_id_callback(threadIdCallback);
71 CRYPTO_set_locking_callback(lockingCallback);
74 void opensslUninstallLocks()
76 CRYPTO_set_id_callback(NULL);
77 CRYPTO_set_locking_callback(NULL);
83 } // namespace anonymous
87 // Loads all error strings (crypto and ssl)
88 SSL_load_error_strings();
91 * Initialize libcrypto (add all algorithms, digests & ciphers)
92 * It also does the stuff from SSL_library_init() except for ssl_load_ciphers()
94 OpenSSL_add_all_algorithms(); // Can be optimized by using EVP_add_cipher instead
97 * Initialize libssl (OCSP uses it)
98 * SSL_library_init() == OpenSSL_add_ssl_algorithms()
103 // load default configuration (/etc/ssl/openssl.cnf)
104 OPENSSL_config(NULL);
106 // enable FIPS mode by default
107 if(0 == FIPS_mode_set(1)) {
108 LogError("Failed to set FIPS mode");
113 * entropy sources - /dev/random,/dev/urandom(Default)
117 std::ifstream ifile(DEV_HW_RANDOM_FILE);
119 ret= RAND_load_file(DEV_HW_RANDOM_FILE, RANDOM_BUFFER_LEN);
121 if(ret != RANDOM_BUFFER_LEN ){
122 LogWarning("Error in HW_RAND file load");
123 ret = RAND_load_file(DEV_URANDOM_FILE, RANDOM_BUFFER_LEN);
125 if(ret != RANDOM_BUFFER_LEN)
126 LogError("Error in U_RAND_file_load");
129 // Install locks for multithreading support
130 opensslInstallLocks();
133 void deinitOpenSsl() {
134 opensslUninstallLocks();
135 CONF_modules_unload(1);
138 deinitOpenSslThread();
141 void deinitOpenSslThread() {
142 CRYPTO_cleanup_all_ex_data();
143 ERR_remove_thread_state(NULL);
147 std::mutex cryptoInitMutex;
149 void initOpenSslAndDetach();
151 typedef void(*initFnPtr)();
153 // has to be atomic as storing function pointer is not an atomic operation on armv7l
154 std::atomic<initFnPtr> initFn (&initOpenSslAndDetach);
158 void initOpenSslAndDetach() {
160 std::lock_guard<std::mutex> lock(cryptoInitMutex);
162 * We don't care about memory ordering here. Current thread will order it correctly and for
163 * other threads only store matters. Also only one thread can be here at once because of lock.
165 if(initFn.load(std::memory_order_relaxed) != &initEmpty)
170 * Synchronizes with load. Everything that happened before this store in this thread is
171 * visible to everything that happens after load in another thread. We switch to an empty
174 initFn.store(&initEmpty, std::memory_order_release);
178 } // namespace anonymous
180 void initOpenSslOnce() {
182 * Synchronizes with store. Everything that happened before store in another thread will be
183 * visible in this thread after load.
185 initFn.load(std::memory_order_acquire)();
188 } /* namespace CKM */