BoringSSL depends on the platform's locking APIs to make internal global state thread-safe, including the PRNG. On some single-threaded embedded platforms, locking APIs may not exist, so this dependency may be disabled with a build flag. Doing so means the consumer promises the library will never be used in any multi-threaded address space. It causes BoringSSL to be globally thread-unsafe. Setting it inappropriately will subtly and unpredictably corrupt memory and leak secret keys. Unfortunately, folks sometimes misinterpreted OPENSSL_NO_THREADS as skipping an internal thread pool or disabling an optionally extra-thread-safe mode. This is not and has never been the case. Rename it to OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED to clarify what this option does. Update-Note: As a first step, this CL makes both OPENSSL_NO_THREADS and OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED work. A later CL will remove the old name, so migrate callers after or at the same time as picking up this CL. Change-Id: Ibe4964ae43eb7a52f08fd966fccb330c0cc11a8c Reviewed-on: https://boringssl-review.googlesource.com/32084 Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -132,13 +132,13 @@ | |||||
#endif | #endif | ||||
#endif | #endif | ||||
#if !defined(OPENSSL_NO_THREADS) && \ | |||||
#if defined(OPENSSL_THREADS) && \ | |||||
(!defined(OPENSSL_WINDOWS) || defined(__MINGW32__)) | (!defined(OPENSSL_WINDOWS) || defined(__MINGW32__)) | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#define OPENSSL_PTHREADS | #define OPENSSL_PTHREADS | ||||
#endif | #endif | ||||
#if !defined(OPENSSL_NO_THREADS) && !defined(OPENSSL_PTHREADS) && \ | |||||
#if defined(OPENSSL_THREADS) && !defined(OPENSSL_PTHREADS) && \ | |||||
defined(OPENSSL_WINDOWS) | defined(OPENSSL_WINDOWS) | ||||
#define OPENSSL_WINDOWS_THREADS | #define OPENSSL_WINDOWS_THREADS | ||||
OPENSSL_MSVC_PRAGMA(warning(push, 3)) | OPENSSL_MSVC_PRAGMA(warning(push, 3)) | ||||
@@ -367,7 +367,7 @@ static inline int constant_time_select_int(crypto_word_t mask, int a, int b) { | |||||
// Thread-safe initialisation. | // Thread-safe initialisation. | ||||
#if defined(OPENSSL_NO_THREADS) | |||||
#if !defined(OPENSSL_THREADS) | |||||
typedef uint32_t CRYPTO_once_t; | typedef uint32_t CRYPTO_once_t; | ||||
#define CRYPTO_ONCE_INIT 0 | #define CRYPTO_ONCE_INIT 0 | ||||
#elif defined(OPENSSL_WINDOWS_THREADS) | #elif defined(OPENSSL_WINDOWS_THREADS) | ||||
@@ -423,7 +423,7 @@ OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count); | |||||
// thread.h as a structure large enough to fit the real type. The global lock is | // thread.h as a structure large enough to fit the real type. The global lock is | ||||
// a different type so it may be initialized with platform initializer macros. | // a different type so it may be initialized with platform initializer macros. | ||||
#if defined(OPENSSL_NO_THREADS) | |||||
#if !defined(OPENSSL_THREADS) | |||||
struct CRYPTO_STATIC_MUTEX { | struct CRYPTO_STATIC_MUTEX { | ||||
char padding; // Empty structs have different sizes in C and C++. | char padding; // Empty structs have different sizes in C and C++. | ||||
}; | }; | ||||
@@ -18,7 +18,7 @@ | |||||
#include "../test/test_util.h" | #include "../test/test_util.h" | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
#include <chrono> | #include <chrono> | ||||
#include <thread> | #include <thread> | ||||
#endif | #endif | ||||
@@ -61,7 +61,7 @@ TEST(PoolTest, Pooled) { | |||||
EXPECT_EQ(buf.get(), buf2.get()) << "CRYPTO_BUFFER_POOL did not dedup data."; | EXPECT_EQ(buf.get(), buf2.get()) << "CRYPTO_BUFFER_POOL did not dedup data."; | ||||
} | } | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
TEST(PoolTest, Threads) { | TEST(PoolTest, Threads) { | ||||
bssl::UniquePtr<CRYPTO_BUFFER_POOL> pool(CRYPTO_BUFFER_POOL_new()); | bssl::UniquePtr<CRYPTO_BUFFER_POOL> pool(CRYPTO_BUFFER_POOL_new()); | ||||
ASSERT_TRUE(pool); | ASSERT_TRUE(pool); | ||||
@@ -20,7 +20,7 @@ | |||||
#include "../test/test_util.h" | #include "../test/test_util.h" | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
#include <array> | #include <array> | ||||
#include <thread> | #include <thread> | ||||
#include <vector> | #include <vector> | ||||
@@ -146,7 +146,7 @@ TEST(RandTest, Fork) { | |||||
} | } | ||||
#endif // !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE | #endif // !OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
static void RunConcurrentRands(size_t num_threads) { | static void RunConcurrentRands(size_t num_threads) { | ||||
static const uint8_t kZeros[256] = {0}; | static const uint8_t kZeros[256] = {0}; | ||||
@@ -16,7 +16,7 @@ | |||||
#include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
#include <thread> | #include <thread> | ||||
#endif | #endif | ||||
@@ -43,7 +43,7 @@ TEST(RefCountTest, Basic) { | |||||
EXPECT_EQ(1u, count); | EXPECT_EQ(1u, count); | ||||
} | } | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
// This test is primarily intended to run under ThreadSanitizer. | // This test is primarily intended to run under ThreadSanitizer. | ||||
TEST(RefCountTest, Threads) { | TEST(RefCountTest, Threads) { | ||||
CRYPTO_refcount_t count = 0; | CRYPTO_refcount_t count = 0; | ||||
@@ -72,7 +72,7 @@ | |||||
#include "../internal.h" | #include "../internal.h" | ||||
#include "../test/test_util.h" | #include "../test/test_util.h" | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
#include <thread> | #include <thread> | ||||
#include <vector> | #include <vector> | ||||
#endif | #endif | ||||
@@ -1048,7 +1048,7 @@ TEST(RSATest, SqrtTwo) { | |||||
} | } | ||||
#endif // !BORINGSSL_SHARED_LIBRARY | #endif // !BORINGSSL_SHARED_LIBRARY | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
TEST(RSATest, Threads) { | TEST(RSATest, Threads) { | ||||
bssl::UniquePtr<RSA> rsa_template( | bssl::UniquePtr<RSA> rsa_template( | ||||
RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1)); | RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1)); | ||||
@@ -14,7 +14,7 @@ | |||||
#include "internal.h" | #include "internal.h" | ||||
#if defined(OPENSSL_NO_THREADS) | |||||
#if !defined(OPENSSL_THREADS) | |||||
void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {} | void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {} | ||||
@@ -56,4 +56,4 @@ int CRYPTO_set_thread_local(thread_local_data_t index, void *value, | |||||
return 1; | return 1; | ||||
} | } | ||||
#endif // OPENSSL_NO_THREADS | |||||
#endif // !OPENSSL_THREADS |
@@ -25,7 +25,7 @@ | |||||
#include "test/test_util.h" | #include "test/test_util.h" | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
static unsigned g_once_init_called = 0; | static unsigned g_once_init_called = 0; | ||||
@@ -130,4 +130,4 @@ TEST(ThreadTest, RandState) { | |||||
thread.join(); | thread.join(); | ||||
} | } | ||||
#endif // !OPENSSL_NO_THREADS | |||||
#endif // OPENSSL_THREADS |
@@ -136,14 +136,36 @@ extern "C" { | |||||
#if defined(TRUSTY) | #if defined(TRUSTY) | ||||
#define OPENSSL_TRUSTY | #define OPENSSL_TRUSTY | ||||
#define OPENSSL_NO_THREADS | |||||
#define OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED | |||||
#endif | #endif | ||||
#if defined(__ANDROID_API__) | #if defined(__ANDROID_API__) | ||||
#define OPENSSL_ANDROID | #define OPENSSL_ANDROID | ||||
#endif | #endif | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
// OPENSSL_NO_THREADS has been deprecated in favor of this much longer and | |||||
// louder name, to better reflect exactly what that option did. | |||||
// | |||||
// TODO(davidben): Remove this block when callers have migrated. | |||||
#if defined(OPENSSL_NO_THREADS) && \ | |||||
!defined(OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED) | |||||
#define OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED | |||||
#endif | |||||
// BoringSSL requires platform's locking APIs to make internal global state | |||||
// thread-safe, including the PRNG. On some single-threaded embedded platforms, | |||||
// locking APIs may not exist, so this dependency may be disabled with the | |||||
// following build flag. | |||||
// | |||||
// IMPORTANT: Doing so means the consumer promises the library will never be | |||||
// used in any multi-threaded context. It causes BoringSSL to be globally | |||||
// thread-unsafe. Setting it inappropriately will subtly and unpredictably | |||||
// corrupt memory and leak secret keys. | |||||
// | |||||
// Do not set this flag on any platform where threads are possible. BoringSSL | |||||
// maintainers will not provide support for any consumers that do so. Changes | |||||
// which break such unsupported configurations will not be reverted. | |||||
#if !defined(OPENSSL_NO_THREADS_CORRUPT_MEMORY_AND_LEAK_SECRETS_IF_THREADED) | |||||
#define OPENSSL_THREADS | #define OPENSSL_THREADS | ||||
#endif | #endif | ||||
@@ -66,7 +66,7 @@ extern "C" { | |||||
#endif | #endif | ||||
#if defined(OPENSSL_NO_THREADS) | |||||
#if !defined(OPENSSL_THREADS) | |||||
typedef struct crypto_mutex_st { | typedef struct crypto_mutex_st { | ||||
char padding; // Empty structs have different sizes in C and C++. | char padding; // Empty structs have different sizes in C and C++. | ||||
} CRYPTO_MUTEX; | } CRYPTO_MUTEX; | ||||
@@ -48,7 +48,7 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) | |||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#endif | #endif | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
#include <thread> | #include <thread> | ||||
#endif | #endif | ||||
@@ -4298,7 +4298,7 @@ TEST_P(SSLVersionTest, FakeIDsForTickets) { | |||||
// These tests test multi-threaded behavior. They are intended to run with | // These tests test multi-threaded behavior. They are intended to run with | ||||
// ThreadSanitizer. | // ThreadSanitizer. | ||||
#if !defined(OPENSSL_NO_THREADS) | |||||
#if defined(OPENSSL_THREADS) | |||||
TEST_P(SSLVersionTest, SessionCacheThreads) { | TEST_P(SSLVersionTest, SessionCacheThreads) { | ||||
SSL_CTX_set_options(server_ctx_.get(), SSL_OP_NO_TICKET); | SSL_CTX_set_options(server_ctx_.get(), SSL_OP_NO_TICKET); | ||||
SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH); | SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH); | ||||