Update SSL call sites to compile with both OpenSSL 1.1.0 and BoringSSL

OpenSSL is making a lot of data structure opaque, so we can no longer directly access internal data structure. Fortunately, API methods are provided for this purpose.

BoringSSL is sharing the same API.

Bug: webrtc:8817
Change-Id: Ia5090200f0e7c352f82e8191720ac4c14fbb5a85
Reviewed-on: https://webrtc-review.googlesource.com/47321
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Justin Uberti <juberti@webrtc.org>
Reviewed-by: Emad Omara <emadomara@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21895}
This commit is contained in:
Jiawei Ou
2018-02-02 14:51:18 -08:00
committed by Commit Bot
parent 0501e1cd97
commit eb0df088ca
8 changed files with 57 additions and 133 deletions

View File

@ -76,27 +76,33 @@ static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
static int socket_new(BIO* h);
static int socket_free(BIO* data);
// TODO(davidben): This should be const once BoringSSL is assumed.
static BIO_METHOD methods_socket = {
BIO_TYPE_BIO, "socket", socket_write, socket_read, socket_puts, 0,
socket_ctrl, socket_new, socket_free, nullptr,
};
static BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
static BIO_METHOD* BIO_socket_method() {
static BIO_METHOD* methods = [] {
BIO_METHOD* methods = BIO_meth_new(BIO_TYPE_BIO, "socket");
BIO_meth_set_write(methods, socket_write);
BIO_meth_set_read(methods, socket_read);
BIO_meth_set_puts(methods, socket_puts);
BIO_meth_set_ctrl(methods, socket_ctrl);
BIO_meth_set_create(methods, socket_new);
BIO_meth_set_destroy(methods, socket_free);
return methods;
}();
return methods;
}
static BIO* BIO_new_socket(rtc::AsyncSocket* socket) {
BIO* ret = BIO_new(BIO_s_socket2());
BIO* ret = BIO_new(BIO_socket_method());
if (ret == nullptr) {
return nullptr;
}
ret->ptr = socket;
BIO_set_data(ret, socket);
return ret;
}
static int socket_new(BIO* b) {
b->shutdown = 0;
b->init = 1;
b->ptr = 0;
BIO_set_shutdown(b, 0);
BIO_set_init(b, 1);
BIO_set_data(b, 0);
return 1;
}
@ -109,7 +115,7 @@ static int socket_free(BIO* b) {
static int socket_read(BIO* b, char* out, int outl) {
if (!out)
return -1;
rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(BIO_get_data(b));
BIO_clear_retry_flags(b);
int result = socket->Recv(out, outl, nullptr);
if (result > 0) {
@ -123,7 +129,7 @@ static int socket_read(BIO* b, char* out, int outl) {
static int socket_write(BIO* b, const char* in, int inl) {
if (!in)
return -1;
rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(BIO_get_data(b));
BIO_clear_retry_flags(b);
int result = socket->Send(in, inl);
if (result > 0) {
@ -178,56 +184,11 @@ static void LogSslError() {
namespace rtc {
#ifndef OPENSSL_IS_BORINGSSL
// This array will store all of the mutexes available to OpenSSL.
static MUTEX_TYPE* mutex_buf = nullptr;
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 nullptr;
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_ = nullptr;
bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
if (!InitializeSSLThread() || !SSL_library_init())
return false;
if (!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();
@ -239,41 +200,7 @@ bool OpenSSLAdapter::InitializeSSL(VerificationCallback 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(nullptr);
CRYPTO_set_locking_callback(nullptr);
CRYPTO_set_dynlock_create_callback(nullptr);
CRYPTO_set_dynlock_lock_callback(nullptr);
CRYPTO_set_dynlock_destroy_callback(nullptr);
for (int i = 0; i < CRYPTO_num_locks(); ++i)
MUTEX_CLEANUP(mutex_buf[i]);
delete [] mutex_buf;
mutex_buf = nullptr;
#endif // #ifndef OPENSSL_IS_BORINGSSL
return true;
}
@ -439,9 +366,11 @@ int OpenSSLAdapter::BeginSSL() {
}
}
#ifdef OPENSSL_IS_BORINGSSL
// Set a couple common TLS extensions; even though we don't use them yet.
SSL_enable_ocsp_stapling(ssl_);
SSL_enable_signed_cert_timestamps(ssl_);
#endif
if (!alpn_protocols_.empty()) {
std::string tls_alpn_string = TransformAlpnProtocols(alpn_protocols_);
@ -896,7 +825,8 @@ bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(
X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr));
if (names) {
for (size_t i = 0; i < sk_GENERAL_NAME_num(names); i++) {
for (size_t i = 0; i < static_cast<size_t>(sk_GENERAL_NAME_num(names));
i++) {
const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
if (name->type != GEN_DNS)
continue;