blob: 9164258692b942e9a787eebd31f61d684f740adb [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
2 * Copyright 2008 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
kjellandere96c45b2017-06-30 10:45:21 -070011#include "webrtc/rtc_base/openssladapter.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#if defined(WEBRTC_POSIX)
14#include <unistd.h>
15#endif
16
17// Must be included first before openssl headers.
kjellandere96c45b2017-06-30 10:45:21 -070018#include "webrtc/rtc_base/win32.h" // NOLINT
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000019
20#include <openssl/bio.h>
21#include <openssl/crypto.h>
22#include <openssl/err.h>
23#include <openssl/opensslv.h>
24#include <openssl/rand.h>
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +000025#include <openssl/x509.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026#include <openssl/x509v3.h>
27
kjellandere96c45b2017-06-30 10:45:21 -070028#include "webrtc/rtc_base/arraysize.h"
29#include "webrtc/rtc_base/checks.h"
30#include "webrtc/rtc_base/logging.h"
31#include "webrtc/rtc_base/openssl.h"
32#include "webrtc/rtc_base/safe_conversions.h"
33#include "webrtc/rtc_base/sslroots.h"
34#include "webrtc/rtc_base/stringutils.h"
35#include "webrtc/rtc_base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000036
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010037#ifndef OPENSSL_IS_BORINGSSL
38
39// TODO: Use a nicer abstraction for mutex.
40
41#if defined(WEBRTC_WIN)
42 #define MUTEX_TYPE HANDLE
deadbeef37f5ecf2017-02-27 14:06:41 -080043#define MUTEX_SETUP(x) (x) = CreateMutex(nullptr, FALSE, nullptr)
44#define MUTEX_CLEANUP(x) CloseHandle(x)
45#define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
46#define MUTEX_UNLOCK(x) ReleaseMutex(x)
47#define THREAD_ID GetCurrentThreadId()
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010048#elif defined(WEBRTC_POSIX)
49 #define MUTEX_TYPE pthread_mutex_t
deadbeef37f5ecf2017-02-27 14:06:41 -080050 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), nullptr)
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010051 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
52 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
53 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
54 #define THREAD_ID pthread_self()
55#else
56 #error You must define mutex operations appropriate for your platform!
57#endif
58
59struct CRYPTO_dynlock_value {
60 MUTEX_TYPE mutex;
61};
62
63#endif // #ifndef OPENSSL_IS_BORINGSSL
64
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000065//////////////////////////////////////////////////////////////////////
66// SocketBIO
67//////////////////////////////////////////////////////////////////////
68
69static int socket_write(BIO* h, const char* buf, int num);
70static int socket_read(BIO* h, char* buf, int size);
71static int socket_puts(BIO* h, const char* str);
72static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
73static int socket_new(BIO* h);
74static int socket_free(BIO* data);
75
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000076// TODO(davidben): This should be const once BoringSSL is assumed.
77static BIO_METHOD methods_socket = {
deadbeef37f5ecf2017-02-27 14:06:41 -080078 BIO_TYPE_BIO, "socket", socket_write, socket_read, socket_puts, 0,
79 socket_ctrl, socket_new, socket_free, nullptr,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000080};
81
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000082static BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000083
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +000084static BIO* BIO_new_socket(rtc::AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000085 BIO* ret = BIO_new(BIO_s_socket2());
deadbeef37f5ecf2017-02-27 14:06:41 -080086 if (ret == nullptr) {
87 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 }
89 ret->ptr = socket;
90 return ret;
91}
92
93static int socket_new(BIO* b) {
94 b->shutdown = 0;
95 b->init = 1;
96 b->num = 0; // 1 means socket closed
97 b->ptr = 0;
98 return 1;
99}
100
101static int socket_free(BIO* b) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800102 if (b == nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000103 return 0;
104 return 1;
105}
106
107static int socket_read(BIO* b, char* out, int outl) {
108 if (!out)
109 return -1;
110 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
111 BIO_clear_retry_flags(b);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200112 int result = socket->Recv(out, outl, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000113 if (result > 0) {
114 return result;
115 } else if (result == 0) {
116 b->num = 1;
117 } else if (socket->IsBlocking()) {
118 BIO_set_retry_read(b);
119 }
120 return -1;
121}
122
123static int socket_write(BIO* b, const char* in, int inl) {
124 if (!in)
125 return -1;
126 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
127 BIO_clear_retry_flags(b);
128 int result = socket->Send(in, inl);
129 if (result > 0) {
130 return result;
131 } else if (socket->IsBlocking()) {
132 BIO_set_retry_write(b);
133 }
134 return -1;
135}
136
137static int socket_puts(BIO* b, const char* str) {
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000138 return socket_write(b, str, rtc::checked_cast<int>(strlen(str)));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000139}
140
141static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000142 switch (cmd) {
143 case BIO_CTRL_RESET:
144 return 0;
145 case BIO_CTRL_EOF:
146 return b->num;
147 case BIO_CTRL_WPENDING:
148 case BIO_CTRL_PENDING:
149 return 0;
150 case BIO_CTRL_FLUSH:
151 return 1;
152 default:
153 return 0;
154 }
155}
156
deadbeefed3b9862017-06-02 10:33:16 -0700157static void LogSslError() {
158 // Walk down the error stack to find the SSL error.
159 uint32_t error_code;
160 const char* file;
161 int line;
162 do {
163 error_code = ERR_get_error_line(&file, &line);
164 if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) {
165 LOG(LS_ERROR) << "ERR_LIB_SSL: " << error_code << ", " << file << ":"
166 << line;
167 break;
168 }
169 } while (error_code != 0);
170}
171
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000172/////////////////////////////////////////////////////////////////////////////
173// OpenSSLAdapter
174/////////////////////////////////////////////////////////////////////////////
175
176namespace rtc {
177
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100178#ifndef OPENSSL_IS_BORINGSSL
179
180// This array will store all of the mutexes available to OpenSSL.
deadbeef37f5ecf2017-02-27 14:06:41 -0800181static MUTEX_TYPE* mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100182
183static void locking_function(int mode, int n, const char * file, int line) {
184 if (mode & CRYPTO_LOCK) {
185 MUTEX_LOCK(mutex_buf[n]);
186 } else {
187 MUTEX_UNLOCK(mutex_buf[n]);
188 }
189}
190
191static unsigned long id_function() { // NOLINT
192 // Use old-style C cast because THREAD_ID's type varies with the platform,
193 // in some cases requiring static_cast, and in others requiring
194 // reinterpret_cast.
195 return (unsigned long)THREAD_ID; // NOLINT
196}
197
198static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
199 CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
200 if (!value)
deadbeef37f5ecf2017-02-27 14:06:41 -0800201 return nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100202 MUTEX_SETUP(value->mutex);
203 return value;
204}
205
206static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
207 const char* file, int line) {
208 if (mode & CRYPTO_LOCK) {
209 MUTEX_LOCK(l->mutex);
210 } else {
211 MUTEX_UNLOCK(l->mutex);
212 }
213}
214
215static void dyn_destroy_function(CRYPTO_dynlock_value* l,
216 const char* file, int line) {
217 MUTEX_CLEANUP(l->mutex);
218 delete l;
219}
220
221#endif // #ifndef OPENSSL_IS_BORINGSSL
222
deadbeef37f5ecf2017-02-27 14:06:41 -0800223VerificationCallback OpenSSLAdapter::custom_verify_callback_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000224
225bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100226 if (!InitializeSSLThread() || !SSL_library_init())
227 return false;
228#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
229 // Loading the error strings crashes mac_asan. Omit this debugging aid there.
230 SSL_load_error_strings();
231#endif
232 ERR_load_BIO_strings();
233 OpenSSL_add_all_algorithms();
234 RAND_poll();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000235 custom_verify_callback_ = callback;
236 return true;
237}
238
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100239bool OpenSSLAdapter::InitializeSSLThread() {
240 // BoringSSL is doing the locking internally, so the callbacks are not used
241 // in this case (and are no-ops anyways).
242#ifndef OPENSSL_IS_BORINGSSL
243 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
244 if (!mutex_buf)
245 return false;
246 for (int i = 0; i < CRYPTO_num_locks(); ++i)
247 MUTEX_SETUP(mutex_buf[i]);
248
249 // we need to cast our id_function to return an unsigned long -- pthread_t is
250 // a pointer
251 CRYPTO_set_id_callback(id_function);
252 CRYPTO_set_locking_callback(locking_function);
253 CRYPTO_set_dynlock_create_callback(dyn_create_function);
254 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
255 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
256#endif // #ifndef OPENSSL_IS_BORINGSSL
257 return true;
258}
259
260bool OpenSSLAdapter::CleanupSSL() {
261#ifndef OPENSSL_IS_BORINGSSL
262 if (!mutex_buf)
263 return false;
deadbeef37f5ecf2017-02-27 14:06:41 -0800264 CRYPTO_set_id_callback(nullptr);
265 CRYPTO_set_locking_callback(nullptr);
266 CRYPTO_set_dynlock_create_callback(nullptr);
267 CRYPTO_set_dynlock_lock_callback(nullptr);
268 CRYPTO_set_dynlock_destroy_callback(nullptr);
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100269 for (int i = 0; i < CRYPTO_num_locks(); ++i)
270 MUTEX_CLEANUP(mutex_buf[i]);
271 delete [] mutex_buf;
deadbeef37f5ecf2017-02-27 14:06:41 -0800272 mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100273#endif // #ifndef OPENSSL_IS_BORINGSSL
274 return true;
275}
276
Justin Uberti1d445502017-08-14 17:04:34 -0700277OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket,
278 OpenSSLAdapterFactory* factory)
deadbeef37f5ecf2017-02-27 14:06:41 -0800279 : SSLAdapter(socket),
Justin Uberti1d445502017-08-14 17:04:34 -0700280 factory_(factory),
deadbeef37f5ecf2017-02-27 14:06:41 -0800281 state_(SSL_NONE),
Steve Anton786de702017-08-17 15:15:46 -0700282 role_(SSL_CLIENT),
deadbeef37f5ecf2017-02-27 14:06:41 -0800283 ssl_read_needs_write_(false),
284 ssl_write_needs_read_(false),
285 restartable_(false),
286 ssl_(nullptr),
287 ssl_ctx_(nullptr),
288 ssl_mode_(SSL_MODE_TLS),
Diogo Real1dca9d52017-08-29 12:18:32 -0700289 ignore_bad_cert_(false),
Justin Uberti1d445502017-08-14 17:04:34 -0700290 custom_verification_succeeded_(false) {
291 // If a factory is used, take a reference on the factory's SSL_CTX.
292 // Otherwise, we'll create our own later.
293 // Either way, we'll release our reference via SSL_CTX_free() in Cleanup().
294 if (factory_) {
295 ssl_ctx_ = factory_->ssl_ctx();
296 RTC_DCHECK(ssl_ctx_);
297 // Note: if using OpenSSL, requires version 1.1.0 or later.
298 SSL_CTX_up_ref(ssl_ctx_);
299 }
300}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000301
302OpenSSLAdapter::~OpenSSLAdapter() {
303 Cleanup();
304}
305
Diogo Real1dca9d52017-08-29 12:18:32 -0700306void OpenSSLAdapter::SetIgnoreBadCert(bool ignore) {
307 ignore_bad_cert_ = ignore;
308}
309
310void OpenSSLAdapter::SetAlpnProtocols(const std::vector<std::string>& protos) {
311 alpn_protocols_ = protos;
312}
313
Justin Uberti1d445502017-08-14 17:04:34 -0700314void OpenSSLAdapter::SetMode(SSLMode mode) {
315 RTC_DCHECK(!ssl_ctx_);
nisseede5da42017-01-12 05:15:36 -0800316 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000317 ssl_mode_ = mode;
318}
319
Steve Anton786de702017-08-17 15:15:46 -0700320void OpenSSLAdapter::SetIdentity(SSLIdentity* identity) {
321 RTC_DCHECK(!identity_);
322 identity_.reset(static_cast<OpenSSLIdentity*>(identity));
323}
324
325void OpenSSLAdapter::SetRole(SSLRole role) {
326 role_ = role;
327}
328
329AsyncSocket* OpenSSLAdapter::Accept(SocketAddress* paddr) {
330 RTC_DCHECK(role_ == SSL_SERVER);
331 AsyncSocket* socket = SSLAdapter::Accept(paddr);
332 if (!socket) {
333 return nullptr;
334 }
335
336 SSLAdapter* adapter = SSLAdapter::Create(socket);
337 adapter->SetIdentity(identity_->GetReference());
338 adapter->SetRole(rtc::SSL_SERVER);
Diogo Real1dca9d52017-08-29 12:18:32 -0700339 adapter->SetIgnoreBadCert(ignore_bad_cert_);
Steve Anton786de702017-08-17 15:15:46 -0700340 adapter->StartSSL("", false);
341 return adapter;
342}
343
Justin Uberti1d445502017-08-14 17:04:34 -0700344int OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000345 if (state_ != SSL_NONE)
346 return -1;
347
348 ssl_host_name_ = hostname;
349 restartable_ = restartable;
350
351 if (socket_->GetState() != Socket::CS_CONNECTED) {
352 state_ = SSL_WAIT;
353 return 0;
354 }
355
356 state_ = SSL_CONNECTING;
357 if (int err = BeginSSL()) {
358 Error("BeginSSL", err, false);
359 return err;
360 }
361
362 return 0;
363}
364
Justin Uberti1d445502017-08-14 17:04:34 -0700365int OpenSSLAdapter::BeginSSL() {
366 LOG(LS_INFO) << "OpenSSLAdapter::BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 05:15:36 -0800367 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000368
369 int err = 0;
deadbeef37f5ecf2017-02-27 14:06:41 -0800370 BIO* bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000371
Justin Uberti1d445502017-08-14 17:04:34 -0700372 // First set up the context. We should either have a factory, with its own
373 // pre-existing context, or be running standalone, in which case we will
374 // need to create one, and specify |false| to disable session caching.
375 if (!factory_) {
376 RTC_DCHECK(!ssl_ctx_);
377 ssl_ctx_ = CreateContext(ssl_mode_, false);
378 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000379 if (!ssl_ctx_) {
380 err = -1;
381 goto ssl_error;
382 }
383
Steve Anton786de702017-08-17 15:15:46 -0700384 if (identity_ && !identity_->ConfigureIdentity(ssl_ctx_)) {
385 SSL_CTX_free(ssl_ctx_);
386 err = -1;
387 goto ssl_error;
388 }
389
Peter Boström0b518bf2016-01-27 12:35:40 +0100390 bio = BIO_new_socket(socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000391 if (!bio) {
392 err = -1;
393 goto ssl_error;
394 }
395
396 ssl_ = SSL_new(ssl_ctx_);
397 if (!ssl_) {
398 err = -1;
399 goto ssl_error;
400 }
401
402 SSL_set_app_data(ssl_, this);
403
deadbeefed3b9862017-06-02 10:33:16 -0700404 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER allows different buffers to be passed
405 // into SSL_write when a record could only be partially transmitted (and thus
406 // requires another call to SSL_write to finish transmission). This allows us
407 // to copy the data into our own buffer when this occurs, since the original
408 // buffer can't safely be accessed after control exits Send.
409 // TODO(deadbeef): Do we want SSL_MODE_ENABLE_PARTIAL_WRITE? It doesn't
410 // appear Send handles partial writes properly, though maybe we never notice
411 // since we never send more than 16KB at once..
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000412 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
413 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
414
Justin Uberti1d445502017-08-14 17:04:34 -0700415 // Enable SNI, if a hostname is supplied.
Emad Omaradab1d2d2017-06-16 15:43:11 -0700416 if (!ssl_host_name_.empty()) {
417 SSL_set_tlsext_host_name(ssl_, ssl_host_name_.c_str());
Justin Uberti1d445502017-08-14 17:04:34 -0700418
419 // Enable session caching, if configured and a hostname is supplied.
420 if (factory_) {
421 SSL_SESSION* cached = factory_->LookupSession(ssl_host_name_);
422 if (cached) {
423 if (SSL_set_session(ssl_, cached) == 0) {
424 LOG(LS_WARNING) << "Failed to apply SSL session from cache";
425 err = -1;
426 goto ssl_error;
427 }
428
429 LOG(LS_INFO) << "Attempting to resume SSL session to "
430 << ssl_host_name_;
431 }
432 }
Emad Omaradab1d2d2017-06-16 15:43:11 -0700433 }
434
Emad Omaracb79d232017-07-20 16:34:34 -0700435 // Set a couple common TLS extensions; even though we don't use them yet.
Emad Omaracb79d232017-07-20 16:34:34 -0700436 SSL_enable_ocsp_stapling(ssl_);
437 SSL_enable_signed_cert_timestamps(ssl_);
438
Diogo Real1dca9d52017-08-29 12:18:32 -0700439 if (!alpn_protocols_.empty()) {
440 std::string tls_alpn_string = TransformAlpnProtocols(alpn_protocols_);
441 if (!tls_alpn_string.empty()) {
442 SSL_set_alpn_protos(
443 ssl_, reinterpret_cast<const unsigned char*>(tls_alpn_string.data()),
444 tls_alpn_string.size());
445 }
446 }
447
Justin Uberti1d445502017-08-14 17:04:34 -0700448 // Now that the initial config is done, transfer ownership of |bio| to the
449 // SSL object. If ContinueSSL() fails, the bio will be freed in Cleanup().
450 SSL_set_bio(ssl_, bio, bio);
deadbeef37f5ecf2017-02-27 14:06:41 -0800451 bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000452
Justin Uberti1d445502017-08-14 17:04:34 -0700453 // Do the connect.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000454 err = ContinueSSL();
455 if (err != 0)
456 goto ssl_error;
457
458 return err;
459
460ssl_error:
461 Cleanup();
462 if (bio)
463 BIO_free(bio);
464
465 return err;
466}
467
Justin Uberti1d445502017-08-14 17:04:34 -0700468int OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 05:15:36 -0800469 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000470
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000471 // Clear the DTLS timer
472 Thread::Current()->Clear(this, MSG_TIMEOUT);
473
Steve Anton786de702017-08-17 15:15:46 -0700474 int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000475 switch (SSL_get_error(ssl_, code)) {
476 case SSL_ERROR_NONE:
477 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
478 LOG(LS_ERROR) << "TLS post connection check failed";
479 // make sure we close the socket
480 Cleanup();
481 // The connect failed so return -1 to shut down the socket
482 return -1;
483 }
484
485 state_ = SSL_CONNECTED;
486 AsyncSocketAdapter::OnConnectEvent(this);
487#if 0 // TODO: worry about this
488 // Don't let ourselves go away during the callbacks
489 PRefPtr<OpenSSLAdapter> lock(this);
490 LOG(LS_INFO) << " -- onStreamReadable";
491 AsyncSocketAdapter::OnReadEvent(this);
492 LOG(LS_INFO) << " -- onStreamWriteable";
493 AsyncSocketAdapter::OnWriteEvent(this);
494#endif
495 break;
496
497 case SSL_ERROR_WANT_READ:
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000498 LOG(LS_VERBOSE) << " -- error want read";
499 struct timeval timeout;
500 if (DTLSv1_get_timeout(ssl_, &timeout)) {
501 int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
502
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700503 Thread::Current()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_TIMEOUT,
504 0);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000505 }
506 break;
507
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000508 case SSL_ERROR_WANT_WRITE:
509 break;
510
511 case SSL_ERROR_ZERO_RETURN:
512 default:
513 LOG(LS_WARNING) << "ContinueSSL -- error " << code;
514 return (code != 0) ? code : -1;
515 }
516
517 return 0;
518}
519
Justin Uberti1d445502017-08-14 17:04:34 -0700520void OpenSSLAdapter::Error(const char* context, int err, bool signal) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000521 LOG(LS_WARNING) << "OpenSSLAdapter::Error("
522 << context << ", " << err << ")";
523 state_ = SSL_ERROR;
524 SetError(err);
525 if (signal)
526 AsyncSocketAdapter::OnCloseEvent(this, err);
527}
528
Justin Uberti1d445502017-08-14 17:04:34 -0700529void OpenSSLAdapter::Cleanup() {
530 LOG(LS_INFO) << "OpenSSLAdapter::Cleanup";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000531
532 state_ = SSL_NONE;
533 ssl_read_needs_write_ = false;
534 ssl_write_needs_read_ = false;
535 custom_verification_succeeded_ = false;
deadbeefed3b9862017-06-02 10:33:16 -0700536 pending_data_.Clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000537
538 if (ssl_) {
539 SSL_free(ssl_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800540 ssl_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000541 }
542
543 if (ssl_ctx_) {
544 SSL_CTX_free(ssl_ctx_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800545 ssl_ctx_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000546 }
Steve Anton786de702017-08-17 15:15:46 -0700547 identity_.reset();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000548
549 // Clear the DTLS timer
550 Thread::Current()->Clear(this, MSG_TIMEOUT);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000551}
552
deadbeefed3b9862017-06-02 10:33:16 -0700553int OpenSSLAdapter::DoSslWrite(const void* pv, size_t cb, int* error) {
554 // If we have pending data (that was previously only partially written by
555 // SSL_write), we shouldn't be attempting to write anything else.
556 RTC_DCHECK(pending_data_.empty() || pv == pending_data_.data());
557 RTC_DCHECK(error != nullptr);
558
559 ssl_write_needs_read_ = false;
560 int ret = SSL_write(ssl_, pv, checked_cast<int>(cb));
561 *error = SSL_get_error(ssl_, ret);
562 switch (*error) {
563 case SSL_ERROR_NONE:
564 // Success!
565 return ret;
566 case SSL_ERROR_WANT_READ:
567 LOG(LS_INFO) << " -- error want read";
568 ssl_write_needs_read_ = true;
569 SetError(EWOULDBLOCK);
570 break;
571 case SSL_ERROR_WANT_WRITE:
572 LOG(LS_INFO) << " -- error want write";
573 SetError(EWOULDBLOCK);
574 break;
575 case SSL_ERROR_ZERO_RETURN:
576 // LOG(LS_INFO) << " -- remote side closed";
577 SetError(EWOULDBLOCK);
578 // do we need to signal closure?
579 break;
580 case SSL_ERROR_SSL:
581 LogSslError();
582 Error("SSL_write", ret ? ret : -1, false);
583 break;
584 default:
585 LOG(LS_WARNING) << "Unknown error from SSL_write: " << *error;
586 Error("SSL_write", ret ? ret : -1, false);
587 break;
588 }
589
590 return SOCKET_ERROR;
591}
592
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000593//
594// AsyncSocket Implementation
595//
596
Justin Uberti1d445502017-08-14 17:04:34 -0700597int OpenSSLAdapter::Send(const void* pv, size_t cb) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000598 //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
599
600 switch (state_) {
601 case SSL_NONE:
602 return AsyncSocketAdapter::Send(pv, cb);
603
604 case SSL_WAIT:
605 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700606 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000607 return SOCKET_ERROR;
608
609 case SSL_CONNECTED:
610 break;
611
612 case SSL_ERROR:
613 default:
614 return SOCKET_ERROR;
615 }
616
deadbeefed3b9862017-06-02 10:33:16 -0700617 int ret;
618 int error;
619
620 if (!pending_data_.empty()) {
621 ret = DoSslWrite(pending_data_.data(), pending_data_.size(), &error);
622 if (ret != static_cast<int>(pending_data_.size())) {
623 // We couldn't finish sending the pending data, so we definitely can't
624 // send any more data. Return with an EWOULDBLOCK error.
625 SetError(EWOULDBLOCK);
626 return SOCKET_ERROR;
627 }
628 // We completed sending the data previously passed into SSL_write! Now
629 // we're allowed to send more data.
630 pending_data_.Clear();
631 }
632
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000633 // OpenSSL will return an error if we try to write zero bytes
634 if (cb == 0)
635 return 0;
636
deadbeefed3b9862017-06-02 10:33:16 -0700637 ret = DoSslWrite(pv, cb, &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000638
deadbeefed3b9862017-06-02 10:33:16 -0700639 // If SSL_write fails with SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, this
640 // means the underlying socket is blocked on reading or (more typically)
641 // writing. When this happens, OpenSSL requires that the next call to
642 // SSL_write uses the same arguments (though, with
643 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, the actual buffer pointer may be
644 // different).
645 //
646 // However, after Send exits, we will have lost access to data the user of
647 // this class is trying to send, and there's no guarantee that the user of
648 // this class will call Send with the same arguements when it fails. So, we
649 // buffer the data ourselves. When we know the underlying socket is writable
650 // again from OnWriteEvent (or if Send is called again before that happens),
651 // we'll retry sending this buffered data.
deadbeefe5dce2b2017-06-02 11:52:06 -0700652 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
653 // Shouldn't be able to get to this point if we already have pending data.
654 RTC_DCHECK(pending_data_.empty());
deadbeefed3b9862017-06-02 10:33:16 -0700655 LOG(LS_WARNING)
656 << "SSL_write couldn't write to the underlying socket; buffering data.";
657 pending_data_.SetData(static_cast<const uint8_t*>(pv), cb);
658 // Since we're taking responsibility for sending this data, return its full
659 // size. The user of this class can consider it sent.
660 return cb;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000661 }
662
deadbeefed3b9862017-06-02 10:33:16 -0700663 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000664}
665
Justin Uberti1d445502017-08-14 17:04:34 -0700666int OpenSSLAdapter::SendTo(const void* pv,
667 size_t cb,
668 const SocketAddress& addr) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000669 if (socket_->GetState() == Socket::CS_CONNECTED &&
670 addr == socket_->GetRemoteAddress()) {
671 return Send(pv, cb);
672 }
673
674 SetError(ENOTCONN);
675
676 return SOCKET_ERROR;
677}
678
Stefan Holmer9131efd2016-05-23 18:19:26 +0200679int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000680 //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
681 switch (state_) {
682
683 case SSL_NONE:
Stefan Holmer9131efd2016-05-23 18:19:26 +0200684 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000685
686 case SSL_WAIT:
687 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700688 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000689 return SOCKET_ERROR;
690
691 case SSL_CONNECTED:
692 break;
693
694 case SSL_ERROR:
695 default:
696 return SOCKET_ERROR;
697 }
698
699 // Don't trust OpenSSL with zero byte reads
700 if (cb == 0)
701 return 0;
702
703 ssl_read_needs_write_ = false;
704
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000705 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
deadbeefed3b9862017-06-02 10:33:16 -0700706 int error = SSL_get_error(ssl_, code);
707 switch (error) {
708 case SSL_ERROR_NONE:
709 // LOG(LS_INFO) << " -- success";
710 return code;
711 case SSL_ERROR_WANT_READ:
712 // LOG(LS_INFO) << " -- error want read";
713 SetError(EWOULDBLOCK);
714 break;
715 case SSL_ERROR_WANT_WRITE:
716 // LOG(LS_INFO) << " -- error want write";
717 ssl_read_needs_write_ = true;
718 SetError(EWOULDBLOCK);
719 break;
720 case SSL_ERROR_ZERO_RETURN:
721 // LOG(LS_INFO) << " -- remote side closed";
722 SetError(EWOULDBLOCK);
723 // do we need to signal closure?
724 break;
725 case SSL_ERROR_SSL:
726 LogSslError();
727 Error("SSL_read", (code ? code : -1), false);
728 break;
729 default:
730 LOG(LS_WARNING) << "Unknown error from SSL_read: " << error;
731 Error("SSL_read", (code ? code : -1), false);
732 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000733 }
734
735 return SOCKET_ERROR;
736}
737
Stefan Holmer9131efd2016-05-23 18:19:26 +0200738int OpenSSLAdapter::RecvFrom(void* pv,
739 size_t cb,
740 SocketAddress* paddr,
741 int64_t* timestamp) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000742 if (socket_->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 18:19:26 +0200743 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000744
745 *paddr = GetRemoteAddress();
746
747 return ret;
748 }
749
750 SetError(ENOTCONN);
751
752 return SOCKET_ERROR;
753}
754
Justin Uberti1d445502017-08-14 17:04:34 -0700755int OpenSSLAdapter::Close() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000756 Cleanup();
757 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
758 return AsyncSocketAdapter::Close();
759}
760
Justin Uberti1d445502017-08-14 17:04:34 -0700761Socket::ConnState OpenSSLAdapter::GetState() const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000762 //if (signal_close_)
763 // return CS_CONNECTED;
764 ConnState state = socket_->GetState();
765 if ((state == CS_CONNECTED)
766 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
767 state = CS_CONNECTING;
768 return state;
769}
770
Justin Uberti1d445502017-08-14 17:04:34 -0700771bool OpenSSLAdapter::IsResumedSession() {
772 return (ssl_ && SSL_session_reused(ssl_) == 1);
773}
774
775void OpenSSLAdapter::OnMessage(Message* msg) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000776 if (MSG_TIMEOUT == msg->message_id) {
777 LOG(LS_INFO) << "DTLS timeout expired";
778 DTLSv1_handle_timeout(ssl_);
779 ContinueSSL();
780 }
781}
782
Justin Uberti1d445502017-08-14 17:04:34 -0700783void OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000784 LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
785 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 05:15:36 -0800786 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000787 AsyncSocketAdapter::OnConnectEvent(socket);
788 return;
789 }
790
791 state_ = SSL_CONNECTING;
792 if (int err = BeginSSL()) {
793 AsyncSocketAdapter::OnCloseEvent(socket, err);
794 }
795}
796
Justin Uberti1d445502017-08-14 17:04:34 -0700797void OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000798 //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
799
800 if (state_ == SSL_NONE) {
801 AsyncSocketAdapter::OnReadEvent(socket);
802 return;
803 }
804
805 if (state_ == SSL_CONNECTING) {
806 if (int err = ContinueSSL()) {
807 Error("ContinueSSL", err);
808 }
809 return;
810 }
811
812 if (state_ != SSL_CONNECTED)
813 return;
814
815 // Don't let ourselves go away during the callbacks
816 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
817 if (ssl_write_needs_read_) {
818 //LOG(LS_INFO) << " -- onStreamWriteable";
819 AsyncSocketAdapter::OnWriteEvent(socket);
820 }
821
822 //LOG(LS_INFO) << " -- onStreamReadable";
823 AsyncSocketAdapter::OnReadEvent(socket);
824}
825
Justin Uberti1d445502017-08-14 17:04:34 -0700826void OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000827 //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
828
829 if (state_ == SSL_NONE) {
830 AsyncSocketAdapter::OnWriteEvent(socket);
831 return;
832 }
833
834 if (state_ == SSL_CONNECTING) {
835 if (int err = ContinueSSL()) {
836 Error("ContinueSSL", err);
837 }
838 return;
839 }
840
841 if (state_ != SSL_CONNECTED)
842 return;
843
844 // Don't let ourselves go away during the callbacks
845 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
846
847 if (ssl_read_needs_write_) {
848 //LOG(LS_INFO) << " -- onStreamReadable";
849 AsyncSocketAdapter::OnReadEvent(socket);
850 }
851
deadbeefed3b9862017-06-02 10:33:16 -0700852 // If a previous SSL_write failed due to the underlying socket being blocked,
853 // this will attempt finishing the write operation.
854 if (!pending_data_.empty()) {
855 int error;
856 if (DoSslWrite(pending_data_.data(), pending_data_.size(), &error) ==
857 static_cast<int>(pending_data_.size())) {
858 pending_data_.Clear();
859 }
860 }
861
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000862 //LOG(LS_INFO) << " -- onStreamWriteable";
863 AsyncSocketAdapter::OnWriteEvent(socket);
864}
865
Justin Uberti1d445502017-08-14 17:04:34 -0700866void OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000867 LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
868 AsyncSocketAdapter::OnCloseEvent(socket, err);
869}
870
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000871bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
872 bool ignore_bad_cert) {
873 if (!host)
874 return false;
875
876 // Checking the return from SSL_get_peer_certificate here is not strictly
877 // necessary. With our setup, it is not possible for it to return
deadbeef37f5ecf2017-02-27 14:06:41 -0800878 // null. However, it is good form to check the return.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000879 X509* certificate = SSL_get_peer_certificate(ssl);
880 if (!certificate)
881 return false;
882
883 // Logging certificates is extremely verbose. So it is disabled by default.
884#ifdef LOG_CERTIFICATES
885 {
886 LOG(LS_INFO) << "Certificate from server:";
887 BIO* mem = BIO_new(BIO_s_mem());
888 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
889 BIO_write(mem, "\0", 1);
890 char* buffer;
891 BIO_get_mem_data(mem, &buffer);
892 LOG(LS_INFO) << buffer;
893 BIO_free(mem);
894
895 char* cipher_description =
deadbeef37f5ecf2017-02-27 14:06:41 -0800896 SSL_CIPHER_description(SSL_get_current_cipher(ssl), nullptr, 128);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000897 LOG(LS_INFO) << "Cipher: " << cipher_description;
898 OPENSSL_free(cipher_description);
899 }
900#endif
901
902 bool ok = false;
davidben4ef903d2017-02-17 13:04:43 -0800903 GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(
904 X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr));
905 if (names) {
906 for (size_t i = 0; i < sk_GENERAL_NAME_num(names); i++) {
907 const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
908 if (name->type != GEN_DNS)
909 continue;
910 std::string value(
911 reinterpret_cast<const char*>(ASN1_STRING_data(name->d.dNSName)),
912 ASN1_STRING_length(name->d.dNSName));
913 // string_match takes NUL-terminated strings, so check for embedded NULs.
914 if (value.find('\0') != std::string::npos)
915 continue;
916 if (string_match(host, value.c_str())) {
917 ok = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000918 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000919 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000920 }
davidben4ef903d2017-02-17 13:04:43 -0800921 GENERAL_NAMES_free(names);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000922 }
923
924 char data[256];
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +0000925 X509_NAME* subject;
deadbeef37f5ecf2017-02-27 14:06:41 -0800926 if (!ok && ((subject = X509_get_subject_name(certificate)) != nullptr) &&
927 (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) >
928 0)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000929 data[sizeof(data)-1] = 0;
930 if (_stricmp(data, host) == 0)
931 ok = true;
932 }
933
934 X509_free(certificate);
935
936 // This should only ever be turned on for debugging and development.
937 if (!ok && ignore_bad_cert) {
938 LOG(LS_WARNING) << "TLS certificate check FAILED. "
939 << "Allowing connection anyway.";
940 ok = true;
941 }
942
943 return ok;
944}
945
946bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
Diogo Real1dca9d52017-08-29 12:18:32 -0700947 bool ok = VerifyServerName(ssl, host, ignore_bad_cert_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000948
949 if (ok) {
950 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
951 custom_verification_succeeded_);
952 }
953
Diogo Real1dca9d52017-08-29 12:18:32 -0700954 if (!ok && ignore_bad_cert_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000955 LOG(LS_INFO) << "Other TLS post connection checks failed.";
956 ok = true;
957 }
958
959 return ok;
960}
961
tfarinaa41ab932015-10-30 16:08:48 -0700962#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000963
964// We only use this for tracing and so it is only needed in debug mode
965
Justin Uberti1d445502017-08-14 17:04:34 -0700966void OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000967 const char* str = "undefined";
968 int w = where & ~SSL_ST_MASK;
969 if (w & SSL_ST_CONNECT) {
970 str = "SSL_connect";
971 } else if (w & SSL_ST_ACCEPT) {
972 str = "SSL_accept";
973 }
974 if (where & SSL_CB_LOOP) {
975 LOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
976 } else if (where & SSL_CB_ALERT) {
977 str = (where & SSL_CB_READ) ? "read" : "write";
978 LOG(LS_INFO) << "SSL3 alert " << str
979 << ":" << SSL_alert_type_string_long(ret)
980 << ":" << SSL_alert_desc_string_long(ret);
981 } else if (where & SSL_CB_EXIT) {
982 if (ret == 0) {
983 LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
984 } else if (ret < 0) {
985 LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
986 }
987 }
988}
989
tfarinaa41ab932015-10-30 16:08:48 -0700990#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000991
Justin Uberti1d445502017-08-14 17:04:34 -0700992int OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 16:08:48 -0700993#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000994 if (!ok) {
995 char data[256];
996 X509* cert = X509_STORE_CTX_get_current_cert(store);
997 int depth = X509_STORE_CTX_get_error_depth(store);
998 int err = X509_STORE_CTX_get_error(store);
999
1000 LOG(LS_INFO) << "Error with certificate at depth: " << depth;
1001 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
1002 LOG(LS_INFO) << " issuer = " << data;
1003 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
1004 LOG(LS_INFO) << " subject = " << data;
1005 LOG(LS_INFO) << " err = " << err
1006 << ":" << X509_verify_cert_error_string(err);
1007 }
1008#endif
1009
1010 // Get our stream pointer from the store
1011 SSL* ssl = reinterpret_cast<SSL*>(
1012 X509_STORE_CTX_get_ex_data(store,
1013 SSL_get_ex_data_X509_STORE_CTX_idx()));
1014
1015 OpenSSLAdapter* stream =
1016 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
1017
1018 if (!ok && custom_verify_callback_) {
1019 void* cert =
1020 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
1021 if (custom_verify_callback_(cert)) {
1022 stream->custom_verification_succeeded_ = true;
1023 LOG(LS_INFO) << "validated certificate using custom callback";
1024 ok = true;
1025 }
1026 }
1027
1028 // Should only be used for debugging and development.
Diogo Real1dca9d52017-08-29 12:18:32 -07001029 if (!ok && stream->ignore_bad_cert_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001030 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
1031 ok = 1;
1032 }
1033
1034 return ok;
1035}
1036
Justin Uberti1d445502017-08-14 17:04:34 -07001037int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) {
1038 OpenSSLAdapter* stream =
1039 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
1040 RTC_DCHECK(stream->factory_);
1041 LOG(LS_INFO) << "Caching SSL session for " << stream->ssl_host_name_;
1042 stream->factory_->AddSession(stream->ssl_host_name_, session);
1043 return 1; // We've taken ownership of the session; OpenSSL shouldn't free it.
1044}
1045
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001046bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
1047 // Add the root cert that we care about to the SSL context
1048 int count_of_added_certs = 0;
tfarina5237aaf2015-11-10 23:44:30 -08001049 for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001050 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
1051 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
deadbeef37f5ecf2017-02-27 14:06:41 -08001052 X509* cert =
1053 d2i_X509(nullptr, &cert_buffer, checked_cast<long>(cert_buffer_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001054 if (cert) {
1055 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
1056 if (return_value == 0) {
1057 LOG(LS_WARNING) << "Unable to add certificate.";
1058 } else {
1059 count_of_added_certs++;
1060 }
1061 X509_free(cert);
1062 }
1063 }
1064 return count_of_added_certs > 0;
1065}
1066
Justin Uberti1d445502017-08-14 17:04:34 -07001067SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
Emad Omarac6de0c92017-06-21 16:40:56 -07001068 // Use (D)TLS 1.2.
1069 // Note: BoringSSL supports a range of versions by setting max/min version
1070 // (Default V1.0 to V1.2). However (D)TLSv1_2_client_method functions used
1071 // below in OpenSSL only support V1.2.
1072 SSL_CTX* ctx = nullptr;
1073#ifdef OPENSSL_IS_BORINGSSL
Justin Uberti1d445502017-08-14 17:04:34 -07001074 ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
Emad Omarac6de0c92017-06-21 16:40:56 -07001075#else
Justin Uberti1d445502017-08-14 17:04:34 -07001076 ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLSv1_2_client_method()
1077 : TLSv1_2_client_method());
Emad Omarac6de0c92017-06-21 16:40:56 -07001078#endif // OPENSSL_IS_BORINGSSL
deadbeef37f5ecf2017-02-27 14:06:41 -08001079 if (ctx == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001080 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
1081 LOG(LS_WARNING) << "SSL_CTX creation failed: "
1082 << '"' << ERR_reason_error_string(error) << "\" "
1083 << "(error=" << error << ')';
deadbeef37f5ecf2017-02-27 14:06:41 -08001084 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001085 }
1086 if (!ConfigureTrustedRootCertificates(ctx)) {
1087 SSL_CTX_free(ctx);
deadbeef37f5ecf2017-02-27 14:06:41 -08001088 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001089 }
1090
tfarinaa41ab932015-10-30 16:08:48 -07001091#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001092 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
1093#endif
1094
1095 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
1096 SSL_CTX_set_verify_depth(ctx, 4);
Emad Omarac6de0c92017-06-21 16:40:56 -07001097 // Use defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers
1098 // (note that SHA256 and SHA384 only select legacy CBC ciphers).
1099 // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining
1100 // CBC-mode ECDSA ciphers.
1101 SSL_CTX_set_cipher_list(
1102 ctx, "ALL:!SHA256:!SHA384:!aPSK:!ECDSA+SHA1:!ADH:!LOW:!EXP:!MD5");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001103
Justin Uberti1d445502017-08-14 17:04:34 -07001104 if (mode == SSL_MODE_DTLS) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +00001105 SSL_CTX_set_read_ahead(ctx, 1);
1106 }
1107
Justin Uberti1d445502017-08-14 17:04:34 -07001108 if (enable_cache) {
1109 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);
1110 SSL_CTX_sess_set_new_cb(ctx, &OpenSSLAdapter::NewSSLSessionCallback);
1111 }
1112
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001113 return ctx;
1114}
1115
Diogo Real1dca9d52017-08-29 12:18:32 -07001116std::string TransformAlpnProtocols(
1117 const std::vector<std::string>& alpn_protocols) {
1118 // Transforms the alpn_protocols list to the format expected by
1119 // Open/BoringSSL. This requires joining the protocols into a single string
1120 // and prepending a character with the size of the protocol string before
1121 // each protocol.
1122 std::string transformed_alpn;
1123 for (const std::string& proto : alpn_protocols) {
1124 if (proto.size() == 0 || proto.size() > 0xFF) {
1125 LOG(LS_ERROR) << "OpenSSLAdapter::Error("
1126 << "TransformAlpnProtocols received proto with size "
1127 << proto.size() << ")";
1128 return "";
1129 }
1130 transformed_alpn += static_cast<char>(proto.size());
1131 transformed_alpn += proto;
1132 LOG(LS_VERBOSE) << "TransformAlpnProtocols: Adding proto: " << proto;
1133 }
1134 return transformed_alpn;
1135}
1136
Justin Uberti1d445502017-08-14 17:04:34 -07001137//////////////////////////////////////////////////////////////////////
1138// OpenSSLAdapterFactory
1139//////////////////////////////////////////////////////////////////////
1140
1141OpenSSLAdapterFactory::OpenSSLAdapterFactory()
1142 : ssl_mode_(SSL_MODE_TLS), ssl_ctx_(nullptr) {}
1143
1144OpenSSLAdapterFactory::~OpenSSLAdapterFactory() {
1145 for (auto it : sessions_) {
1146 SSL_SESSION_free(it.second);
1147 }
1148 SSL_CTX_free(ssl_ctx_);
1149}
1150
1151void OpenSSLAdapterFactory::SetMode(SSLMode mode) {
1152 RTC_DCHECK(!ssl_ctx_);
1153 ssl_mode_ = mode;
1154}
1155
1156OpenSSLAdapter* OpenSSLAdapterFactory::CreateAdapter(AsyncSocket* socket) {
1157 if (!ssl_ctx_) {
1158 bool enable_cache = true;
1159 ssl_ctx_ = OpenSSLAdapter::CreateContext(ssl_mode_, enable_cache);
1160 if (!ssl_ctx_) {
1161 return nullptr;
1162 }
1163 }
1164
1165 return new OpenSSLAdapter(socket, this);
1166}
1167
1168SSL_SESSION* OpenSSLAdapterFactory::LookupSession(const std::string& hostname) {
1169 auto it = sessions_.find(hostname);
1170 return (it != sessions_.end()) ? it->second : nullptr;
1171}
1172
1173void OpenSSLAdapterFactory::AddSession(const std::string& hostname,
1174 SSL_SESSION* new_session) {
1175 SSL_SESSION* old_session = LookupSession(hostname);
1176 SSL_SESSION_free(old_session);
1177 sessions_[hostname] = new_session;
1178}
1179
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001180} // namespace rtc