47f99b7355ff74a2d8bf1d7938bcee918b6c1f05
[platform/core/security/key-manager.git] / src / manager / common / crypto-init.cpp
1 /*
2  *  Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16 /*
17  * @file       crypto-init.cpp
18  * @author     Maciej Karpiuk (m.karpiuk2@samsung.com)
19  * @version    1.0
20  */
21
22 #include "crypto-init.h"
23 #include <mutex>
24 #include <openssl/evp.h>
25 #include <atomic>
26
27 namespace CKM {
28
29 namespace {
30 std::mutex cryptoInitMutex;
31
32 void initOpenSSL();
33
34 typedef void(*initFnPtr)();
35
36 // has to be atomic as storing function pointer is not an atomic operation on armv7l
37 std::atomic<initFnPtr> initFn (&initOpenSSL);
38
39 void initEmpty() {}
40
41 void initOpenSSL() {
42     // DCLP
43     std::lock_guard<std::mutex> lock(cryptoInitMutex);
44     /*
45      * We don't care about memory ordering here. Current thread will order it correctly and for
46      * other threads only store matters. Also only one thread can be here at once because of lock.
47      */
48     if(initFn.load(std::memory_order_relaxed) != &initEmpty)
49     {
50         OpenSSL_add_all_ciphers();
51         OpenSSL_add_all_algorithms();
52         OpenSSL_add_all_digests();
53
54         /*
55          * Synchronizes with load. Everything that happened before this store in this thread is
56          * visible to everything that happens after load in another thread. We switch to an empty
57          * function here.
58          */
59         initFn.store(&initEmpty, std::memory_order_release);
60     }
61 }
62
63 } // namespace anonymous
64
65 void initCryptoLib() {
66     /*
67      * Synchronizes with store. Everything that happened before store in another thread will be
68      * visible in this thread after load.
69      */
70     initFn.load(std::memory_order_acquire)();
71 }
72
73 } /* namespace CKM */