Revert of Remove code interfacing legacy openssl. (patchset #3 id:40001 of https://codereview.webrtc.org/1808763002/ )

Reason for revert:
We will make it possible to link to BoringSSL for WebRTC's usages of the crypto APIs and OpenSSL for other usages in the same binary. Once that is completed, we will reland this.

Original issue's description:
> Remove code interfacing legacy openssl.
>
> BUG=webrtc:5664
>
> Committed: https://crrev.com/4cd331beade6de16c073dcdaf89c4e038bdbf73f
> Cr-Commit-Position: refs/heads/master@{#12041}

TBR=tommi@webrtc.org,davidben@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:5664

Review URL: https://codereview.webrtc.org/1828773003 .

Cr-Commit-Position: refs/heads/master@{#12117}
This commit is contained in:
Torbjorn Granlund 2016-03-24 14:05:06 +01:00
parent 4a3a135e68
commit 9adc91d9cc
6 changed files with 333 additions and 3 deletions

View File

@ -13,4 +13,8 @@
#include <openssl/ssl.h>
#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
#error OpenSSL is older than 1.0.0, which is the minimum supported version.
#endif
#endif // WEBRTC_BASE_OPENSSL_H_

View File

@ -40,6 +40,34 @@
#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,14 +177,105 @@ static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
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;
}
OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
: SSLAdapter(socket),
state_(SSL_NONE),

View File

@ -27,6 +27,8 @@ namespace rtc {
class OpenSSLAdapter : public SSLAdapter, public MessageHandler {
public:
static bool InitializeSSL(VerificationCallback callback);
static bool InitializeSSLThread();
static bool CleanupSSL();
OpenSSLAdapter(AsyncSocket* socket);
~OpenSSLAdapter() override;

View File

@ -174,7 +174,11 @@ OpenSSLKeyPair* OpenSSLKeyPair::GetReference() {
}
void OpenSSLKeyPair::AddReference() {
#if defined(OPENSSL_IS_BORINGSSL)
EVP_PKEY_up_ref(pkey_);
#else
CRYPTO_add(&pkey_->references, 1, CRYPTO_LOCK_EVP_PKEY);
#endif
}
#if !defined(NDEBUG)
@ -357,7 +361,11 @@ void OpenSSLCertificate::ToDER(Buffer* der_buffer) const {
void OpenSSLCertificate::AddReference() const {
ASSERT(x509_ != NULL);
#if defined(OPENSSL_IS_BORINGSSL)
X509_up_ref(x509_);
#else
CRYPTO_add(&x509_->references, 1, CRYPTO_LOCK_X509);
#endif
}
// Documented in sslidentity.h.

View File

@ -38,6 +38,11 @@
namespace rtc {
#if (OPENSSL_VERSION_NUMBER >= 0x10001000L)
#define HAVE_DTLS_SRTP
#endif
#ifdef HAVE_DTLS_SRTP
// SRTP cipher suite table. |internal_name| is used to construct a
// colon-separated profile strings which is needed by
// SSL_CTX_set_tlsext_use_srtp().
@ -51,6 +56,90 @@ static SrtpCipherMapEntry SrtpCipherMap[] = {
{"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80},
{"SRTP_AES128_CM_SHA1_32", SRTP_AES128_CM_SHA1_32},
{nullptr, 0}};
#endif
#ifndef OPENSSL_IS_BORINGSSL
// Cipher name table. Maps internal OpenSSL cipher ids to the RFC name.
struct SslCipherMapEntry {
uint32_t openssl_id;
const char* rfc_name;
};
#define DEFINE_CIPHER_ENTRY_SSL3(name) {SSL3_CK_##name, "TLS_"#name}
#define DEFINE_CIPHER_ENTRY_TLS1(name) {TLS1_CK_##name, "TLS_"#name}
// There currently is no method available to get a RFC-compliant name for a
// cipher suite from BoringSSL, so we need to define the mapping manually here.
// This should go away once BoringSSL supports "SSL_CIPHER_standard_name"
// (as available in OpenSSL if compiled with tracing enabled) or a similar
// method.
static const SslCipherMapEntry kSslCipherMap[] = {
// TLS v1.0 ciphersuites from RFC2246.
DEFINE_CIPHER_ENTRY_SSL3(RSA_RC4_128_SHA),
{SSL3_CK_RSA_DES_192_CBC3_SHA,
"TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
// AES ciphersuites from RFC3268.
{TLS1_CK_RSA_WITH_AES_128_SHA,
"TLS_RSA_WITH_AES_128_CBC_SHA"},
{TLS1_CK_DHE_RSA_WITH_AES_128_SHA,
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
{TLS1_CK_RSA_WITH_AES_256_SHA,
"TLS_RSA_WITH_AES_256_CBC_SHA"},
{TLS1_CK_DHE_RSA_WITH_AES_256_SHA,
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
// ECC ciphersuites from RFC4492.
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_RC4_128_SHA),
{TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_RC4_128_SHA),
{TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_CBC_SHA),
// TLS v1.2 ciphersuites.
{TLS1_CK_RSA_WITH_AES_128_SHA256,
"TLS_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_RSA_WITH_AES_256_SHA256,
"TLS_RSA_WITH_AES_256_CBC_SHA256"},
{TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
// TLS v1.2 GCM ciphersuites from RFC5288.
DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_256_GCM_SHA384),
// ECDH HMAC based ciphersuites from RFC5289.
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
// ECDH GCM based ciphersuites from RFC5289.
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_GCM_SHA384),
{0, NULL}
};
#endif // #ifndef OPENSSL_IS_BORINGSSL
#if defined(_MSC_VER)
#pragma warning(push)
@ -237,6 +326,7 @@ bool OpenSSLStreamAdapter::SetPeerCertificateDigest(const std::string
}
std::string OpenSSLStreamAdapter::SslCipherSuiteToName(int cipher_suite) {
#ifdef OPENSSL_IS_BORINGSSL
const SSL_CIPHER* ssl_cipher = SSL_get_cipher_by_value(cipher_suite);
if (!ssl_cipher) {
return std::string();
@ -245,6 +335,15 @@ std::string OpenSSLStreamAdapter::SslCipherSuiteToName(int cipher_suite) {
std::string rfc_name = std::string(cipher_name);
OPENSSL_free(cipher_name);
return rfc_name;
#else
for (const SslCipherMapEntry* entry = kSslCipherMap; entry->rfc_name;
++entry) {
if (cipher_suite == static_cast<int>(entry->openssl_id)) {
return entry->rfc_name;
}
}
return std::string();
#endif
}
bool OpenSSLStreamAdapter::GetSslCipherSuite(int* cipher_suite) {
@ -289,6 +388,7 @@ bool OpenSSLStreamAdapter::ExportKeyingMaterial(const std::string& label,
bool use_context,
uint8_t* result,
size_t result_len) {
#ifdef HAVE_DTLS_SRTP
int i;
i = SSL_export_keying_material(ssl_, result, result_len, label.c_str(),
@ -299,10 +399,14 @@ bool OpenSSLStreamAdapter::ExportKeyingMaterial(const std::string& label,
return false;
return true;
#else
return false;
#endif
}
bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
const std::vector<int>& ciphers) {
#ifdef HAVE_DTLS_SRTP
std::string internal_ciphers;
if (state_ != SSL_NONE)
@ -333,9 +437,13 @@ bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
srtp_ciphers_ = internal_ciphers;
return true;
#else
return false;
#endif
}
bool OpenSSLStreamAdapter::GetDtlsSrtpCryptoSuite(int* crypto_suite) {
#ifdef HAVE_DTLS_SRTP
ASSERT(state_ == SSL_CONNECTED);
if (state_ != SSL_CONNECTED)
return false;
@ -349,6 +457,9 @@ bool OpenSSLStreamAdapter::GetDtlsSrtpCryptoSuite(int* crypto_suite) {
*crypto_suite = srtp_profile->id;
ASSERT(!SrtpCryptoSuiteToName(*crypto_suite).empty());
return true;
#else
return false;
#endif
}
int OpenSSLStreamAdapter::StartSSLWithServer(const char* server_name) {
@ -661,6 +772,13 @@ int OpenSSLStreamAdapter::BeginSSL() {
SSL_set_app_data(ssl_, this);
SSL_set_bio(ssl_, bio, bio); // the SSL object owns the bio now.
#ifndef OPENSSL_IS_BORINGSSL
if (ssl_mode_ == SSL_MODE_DTLS) {
// Enable read-ahead for DTLS so whole packets are read from internal BIO
// before parsing. This is done internally by BoringSSL for DTLS.
SSL_set_read_ahead(ssl_, 1);
}
#endif
SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
@ -780,13 +898,73 @@ void OpenSSLStreamAdapter::OnMessage(Message* msg) {
SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
SSL_CTX *ctx = NULL;
#ifdef OPENSSL_IS_BORINGSSL
ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
DTLS_method() : TLS_method());
// Version limiting for BoringSSL will be done below.
#else
const SSL_METHOD* method;
switch (ssl_max_version_) {
case SSL_PROTOCOL_TLS_10:
case SSL_PROTOCOL_TLS_11:
// OpenSSL doesn't support setting min/max versions, so we always use
// (D)TLS 1.0 if a max. version below the max. available is requested.
if (ssl_mode_ == SSL_MODE_DTLS) {
if (role_ == SSL_CLIENT) {
method = DTLSv1_client_method();
} else {
method = DTLSv1_server_method();
}
} else {
if (role_ == SSL_CLIENT) {
method = TLSv1_client_method();
} else {
method = TLSv1_server_method();
}
}
break;
case SSL_PROTOCOL_TLS_12:
default:
if (ssl_mode_ == SSL_MODE_DTLS) {
#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
// DTLS 1.2 only available starting from OpenSSL 1.0.2
if (role_ == SSL_CLIENT) {
method = DTLS_client_method();
} else {
method = DTLS_server_method();
}
#else
if (role_ == SSL_CLIENT) {
method = DTLSv1_client_method();
} else {
method = DTLSv1_server_method();
}
#endif
} else {
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
// New API only available starting from OpenSSL 1.1.0
if (role_ == SSL_CLIENT) {
method = TLS_client_method();
} else {
method = TLS_server_method();
}
#else
if (role_ == SSL_CLIENT) {
method = SSLv23_client_method();
} else {
method = SSLv23_server_method();
}
#endif
}
break;
}
ctx = SSL_CTX_new(method);
#endif // OPENSSL_IS_BORINGSSL
if (ctx == NULL)
return NULL;
#ifdef OPENSSL_IS_BORINGSSL
SSL_CTX_set_min_version(ctx, ssl_mode_ == SSL_MODE_DTLS ?
DTLS1_VERSION : TLS1_VERSION);
switch (ssl_max_version_) {
@ -804,6 +982,7 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
DTLS1_2_VERSION : TLS1_2_VERSION);
break;
}
#endif
if (identity_ && !identity_->ConfigureIdentity(ctx)) {
SSL_CTX_free(ctx);
@ -831,12 +1010,14 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
SSL_CTX_set_cipher_list(ctx,
"DEFAULT:!NULL:!aNULL:!SHA256:!SHA384:!aECDH:!AESGCM+AES256:!aPSK");
#ifdef HAVE_DTLS_SRTP
if (!srtp_ciphers_.empty()) {
if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_ciphers_.c_str())) {
SSL_CTX_free(ctx);
return NULL;
}
}
#endif
return ctx;
}
@ -928,11 +1109,19 @@ bool OpenSSLStreamAdapter::HaveDtls() {
}
bool OpenSSLStreamAdapter::HaveDtlsSrtp() {
#ifdef HAVE_DTLS_SRTP
return true;
#else
return false;
#endif
}
bool OpenSSLStreamAdapter::HaveExporter() {
#ifdef HAVE_DTLS_SRTP
return true;
#else
return false;
#endif
}
#define CDEF(X) \

View File

@ -44,14 +44,20 @@ bool InitializeSSL(VerificationCallback callback) {
return OpenSSLAdapter::InitializeSSL(callback);
}
bool InitializeSSLThread() {
return OpenSSLAdapter::InitializeSSLThread();
}
bool CleanupSSL() {
return OpenSSLAdapter::CleanupSSL();
}
#else // !SSL_USE_OPENSSL
bool InitializeSSL(VerificationCallback callback) {
return true;
}
#endif // SSL_USE_OPENSSL
bool InitializeSSLThread() {
return true;
}
@ -60,6 +66,8 @@ bool CleanupSSL() {
return true;
}
#endif // SSL_USE_OPENSSL
///////////////////////////////////////////////////////////////////////////////
} // namespace rtc