Index: webrtc/base/openssladapter.cc |
diff --git a/webrtc/base/openssladapter.cc b/webrtc/base/openssladapter.cc |
index 818e326940ff25900fae7736d79c5318fecca16c..264dae9e28b623db4ea6145bcf12af3b9fbbb240 100644 |
--- a/webrtc/base/openssladapter.cc |
+++ b/webrtc/base/openssladapter.cc |
@@ -39,6 +39,34 @@ |
#include "webrtc/base/sslroots.h" |
#include "webrtc/base/stringutils.h" |
#include "webrtc/base/thread.h" |
+ |
+#ifndef OPENSSL_IS_BORINGSSL |
+ |
+// TODO: Use a nicer abstraction for mutex. |
+ |
+#if defined(WEBRTC_WIN) |
+ #define MUTEX_TYPE HANDLE |
+ #define MUTEX_SETUP(x) (x) = CreateMutex(NULL, FALSE, NULL) |
+ #define MUTEX_CLEANUP(x) CloseHandle(x) |
+ #define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE) |
+ #define MUTEX_UNLOCK(x) ReleaseMutex(x) |
+ #define THREAD_ID GetCurrentThreadId() |
+#elif defined(WEBRTC_POSIX) |
+ #define MUTEX_TYPE pthread_mutex_t |
+ #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) |
+ #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) |
+ #define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) |
+ #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) |
+ #define THREAD_ID pthread_self() |
+#else |
+ #error You must define mutex operations appropriate for your platform! |
+#endif |
+ |
+struct CRYPTO_dynlock_value { |
+ MUTEX_TYPE mutex; |
+}; |
+ |
+#endif // #ifndef OPENSSL_IS_BORINGSSL |
////////////////////////////////////////////////////////////////////// |
// SocketBIO |
@@ -149,11 +177,102 @@ |
namespace rtc { |
+#ifndef OPENSSL_IS_BORINGSSL |
+ |
+// This array will store all of the mutexes available to OpenSSL. |
+static MUTEX_TYPE* mutex_buf = NULL; |
+ |
+static void locking_function(int mode, int n, const char * file, int line) { |
+ if (mode & CRYPTO_LOCK) { |
+ MUTEX_LOCK(mutex_buf[n]); |
+ } else { |
+ MUTEX_UNLOCK(mutex_buf[n]); |
+ } |
+} |
+ |
+static unsigned long id_function() { // NOLINT |
+ // Use old-style C cast because THREAD_ID's type varies with the platform, |
+ // in some cases requiring static_cast, and in others requiring |
+ // reinterpret_cast. |
+ return (unsigned long)THREAD_ID; // NOLINT |
+} |
+ |
+static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) { |
+ CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value; |
+ if (!value) |
+ return NULL; |
+ MUTEX_SETUP(value->mutex); |
+ return value; |
+} |
+ |
+static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l, |
+ const char* file, int line) { |
+ if (mode & CRYPTO_LOCK) { |
+ MUTEX_LOCK(l->mutex); |
+ } else { |
+ MUTEX_UNLOCK(l->mutex); |
+ } |
+} |
+ |
+static void dyn_destroy_function(CRYPTO_dynlock_value* l, |
+ const char* file, int line) { |
+ MUTEX_CLEANUP(l->mutex); |
+ delete l; |
+} |
+ |
+#endif // #ifndef OPENSSL_IS_BORINGSSL |
+ |
VerificationCallback OpenSSLAdapter::custom_verify_callback_ = NULL; |
bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) { |
- CRYPTO_library_init(); |
+ if (!InitializeSSLThread() || !SSL_library_init()) |
+ return false; |
+#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS) |
+ // Loading the error strings crashes mac_asan. Omit this debugging aid there. |
+ SSL_load_error_strings(); |
+#endif |
+ ERR_load_BIO_strings(); |
+ OpenSSL_add_all_algorithms(); |
+ RAND_poll(); |
custom_verify_callback_ = callback; |
+ return true; |
+} |
+ |
+bool OpenSSLAdapter::InitializeSSLThread() { |
+ // BoringSSL is doing the locking internally, so the callbacks are not used |
+ // in this case (and are no-ops anyways). |
+#ifndef OPENSSL_IS_BORINGSSL |
+ mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()]; |
+ if (!mutex_buf) |
+ return false; |
+ for (int i = 0; i < CRYPTO_num_locks(); ++i) |
+ MUTEX_SETUP(mutex_buf[i]); |
+ |
+ // we need to cast our id_function to return an unsigned long -- pthread_t is |
+ // a pointer |
+ CRYPTO_set_id_callback(id_function); |
+ CRYPTO_set_locking_callback(locking_function); |
+ CRYPTO_set_dynlock_create_callback(dyn_create_function); |
+ CRYPTO_set_dynlock_lock_callback(dyn_lock_function); |
+ CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); |
+#endif // #ifndef OPENSSL_IS_BORINGSSL |
+ return true; |
+} |
+ |
+bool OpenSSLAdapter::CleanupSSL() { |
+#ifndef OPENSSL_IS_BORINGSSL |
+ if (!mutex_buf) |
+ return false; |
+ CRYPTO_set_id_callback(NULL); |
+ CRYPTO_set_locking_callback(NULL); |
+ CRYPTO_set_dynlock_create_callback(NULL); |
+ CRYPTO_set_dynlock_lock_callback(NULL); |
+ CRYPTO_set_dynlock_destroy_callback(NULL); |
+ for (int i = 0; i < CRYPTO_num_locks(); ++i) |
+ MUTEX_CLEANUP(mutex_buf[i]); |
+ delete [] mutex_buf; |
+ mutex_buf = NULL; |
+#endif // #ifndef OPENSSL_IS_BORINGSSL |
return true; |
} |