OLD | NEW |
| (Empty) |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 // | |
5 // OpenSSL multi-threading initialization | |
6 | |
7 #include "chrome/browser/sync/engine/net/openssl_init.h" | |
8 | |
9 #include <openssl/crypto.h> | |
10 | |
11 #include "base/logging.h" | |
12 #include "chrome/browser/sync/util/compat-pthread.h" | |
13 #include "chrome/browser/sync/util/pthread_helpers.h" | |
14 | |
15 // OpenSSL requires multithreading callbacks to be initialized prior to using | |
16 // the library so that it can manage thread locking as necessary. | |
17 | |
18 // Dynamic lock type | |
19 // | |
20 // This needs to be a struct and in global scope because OpenSSL relies on some | |
21 // macro magic. | |
22 struct CRYPTO_dynlock_value { | |
23 PThreadMutex mutex; | |
24 void Lock() { | |
25 mutex.Lock(); | |
26 } | |
27 void Unlock() { | |
28 mutex.Unlock(); | |
29 } | |
30 }; | |
31 | |
32 namespace { | |
33 | |
34 // This array stores all of the mutexes available to OpenSSL | |
35 PThreadMutex* mutex_buf = NULL; | |
36 | |
37 // OpenSSL mutex handling callback functions | |
38 | |
39 // OpenSSL Callback - Locks/unlocks the specified mutex held by OpenSSL. | |
40 void OpenSslMutexLockControl(int mode, int n, const char* file, int line) { | |
41 if (mode & CRYPTO_LOCK) { | |
42 mutex_buf[n].Lock(); | |
43 } else { | |
44 mutex_buf[n].Unlock(); | |
45 } | |
46 } | |
47 | |
48 // OpenSSL Callback - Returns the thread ID | |
49 unsigned long OpenSslGetThreadID(void) { | |
50 return GetCurrentThreadId(); | |
51 } | |
52 | |
53 // Dynamic locking functions | |
54 | |
55 // Allocate a new lock | |
56 struct CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) { | |
57 return new CRYPTO_dynlock_value; | |
58 } | |
59 | |
60 void dyn_lock_function(int mode, struct CRYPTO_dynlock_value* lock, | |
61 const char* file, int line) { | |
62 if (mode & CRYPTO_LOCK) { | |
63 lock->Lock(); | |
64 } else { | |
65 lock->Unlock(); | |
66 } | |
67 } | |
68 | |
69 void dyn_destroy_function(struct CRYPTO_dynlock_value* lock, | |
70 const char* file, int line) { | |
71 delete lock; | |
72 } | |
73 | |
74 } // namespace | |
75 | |
76 // We want to log the version of the OpenSSL library being used, in particular | |
77 // for the case where it's dynamically linked. We want the version from the | |
78 // library, not from the header files. It seems the OpenSSL folks haven't | |
79 // bothered with an accessor for this, so we just pluck it out. | |
80 #ifdef OS_WINDOWS | |
81 // TODO(sync): Figure out how to get the SSL version string on Windows. | |
82 const char* SSL_version_str = "UNKNOWN"; | |
83 #else | |
84 extern const char* SSL_version_str; | |
85 #endif | |
86 | |
87 namespace browser_sync { | |
88 | |
89 // Initializes the OpenSSL multithreading callbacks. This isn't thread-safe, | |
90 // but it is called early enough that it doesn't matter. | |
91 void InitOpenSslMultithreading() { | |
92 LOG(INFO) << "Using OpenSSL headers version " << OPENSSL_VERSION_TEXT | |
93 << ", lib version " << SSL_version_str; | |
94 | |
95 if (mutex_buf) | |
96 return; | |
97 | |
98 mutex_buf = new PThreadMutex[CRYPTO_num_locks()]; | |
99 CHECK(NULL != mutex_buf); | |
100 | |
101 // OpenSSL has only one single global set of callbacks, so this | |
102 // initialization must be done only once, even though the OpenSSL lib may be | |
103 // used by multiple modules (jingle jabber connections and P2P tunnels). | |
104 CRYPTO_set_id_callback(OpenSslGetThreadID); | |
105 CRYPTO_set_locking_callback(OpenSslMutexLockControl); | |
106 | |
107 CRYPTO_set_dynlock_create_callback(dyn_create_function); | |
108 CRYPTO_set_dynlock_lock_callback(dyn_lock_function); | |
109 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); | |
110 } | |
111 | |
112 // Cleans up the OpenSSL multithreading callbacks. | |
113 void CleanupOpenSslMultithreading() { | |
114 if (!mutex_buf) { | |
115 return; | |
116 } | |
117 | |
118 CRYPTO_set_dynlock_create_callback(NULL); | |
119 CRYPTO_set_dynlock_lock_callback(NULL); | |
120 CRYPTO_set_dynlock_destroy_callback(NULL); | |
121 | |
122 CRYPTO_set_id_callback(NULL); | |
123 CRYPTO_set_locking_callback(NULL); | |
124 | |
125 delete [] mutex_buf; | |
126 mutex_buf = NULL; | |
127 } | |
128 | |
129 } // namespace browser_sync | |
OLD | NEW |