blob: ca5984a84a4e1b0fc874c6ed4a91545bcc8d1c85 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "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
Mirko Bonadeie0623852018-02-01 11:17:40 +010017#if defined(WEBRTC_WIN)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018// Must be included first before openssl headers.
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/win32.h" // NOLINT
Mirko Bonadeie0623852018-02-01 11:17:40 +010020#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021
22#include <openssl/bio.h>
23#include <openssl/crypto.h>
24#include <openssl/err.h>
25#include <openssl/opensslv.h>
26#include <openssl/rand.h>
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +000027#include <openssl/x509.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000028#include <openssl/x509v3.h>
29
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/arraysize.h"
31#include "rtc_base/checks.h"
32#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 10:42:26 +010033#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/openssl.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020035#include "rtc_base/sslroots.h"
36#include "rtc_base/stringencode.h"
37#include "rtc_base/stringutils.h"
38#include "rtc_base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000039
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010040#ifndef OPENSSL_IS_BORINGSSL
41
42// TODO: Use a nicer abstraction for mutex.
43
44#if defined(WEBRTC_WIN)
45 #define MUTEX_TYPE HANDLE
deadbeef37f5ecf2017-02-27 14:06:41 -080046#define MUTEX_SETUP(x) (x) = CreateMutex(nullptr, FALSE, nullptr)
47#define MUTEX_CLEANUP(x) CloseHandle(x)
48#define MUTEX_LOCK(x) WaitForSingleObject((x), INFINITE)
49#define MUTEX_UNLOCK(x) ReleaseMutex(x)
50#define THREAD_ID GetCurrentThreadId()
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010051#elif defined(WEBRTC_POSIX)
52 #define MUTEX_TYPE pthread_mutex_t
deadbeef37f5ecf2017-02-27 14:06:41 -080053 #define MUTEX_SETUP(x) pthread_mutex_init(&(x), nullptr)
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +010054 #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x))
55 #define MUTEX_LOCK(x) pthread_mutex_lock(&(x))
56 #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
57 #define THREAD_ID pthread_self()
58#else
59 #error You must define mutex operations appropriate for your platform!
60#endif
61
62struct CRYPTO_dynlock_value {
63 MUTEX_TYPE mutex;
64};
65
66#endif // #ifndef OPENSSL_IS_BORINGSSL
67
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000068//////////////////////////////////////////////////////////////////////
69// SocketBIO
70//////////////////////////////////////////////////////////////////////
71
72static int socket_write(BIO* h, const char* buf, int num);
73static int socket_read(BIO* h, char* buf, int size);
74static int socket_puts(BIO* h, const char* str);
75static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2);
76static int socket_new(BIO* h);
77static int socket_free(BIO* data);
78
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000079// TODO(davidben): This should be const once BoringSSL is assumed.
80static BIO_METHOD methods_socket = {
deadbeef37f5ecf2017-02-27 14:06:41 -080081 BIO_TYPE_BIO, "socket", socket_write, socket_read, socket_puts, 0,
82 socket_ctrl, socket_new, socket_free, nullptr,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000083};
84
davidben@webrtc.org36d5c3c2015-01-22 23:06:17 +000085static BIO_METHOD* BIO_s_socket2() { return(&methods_socket); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000086
henrike@webrtc.orgc50bf7c2014-05-14 18:24:13 +000087static BIO* BIO_new_socket(rtc::AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 BIO* ret = BIO_new(BIO_s_socket2());
deadbeef37f5ecf2017-02-27 14:06:41 -080089 if (ret == nullptr) {
90 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000091 }
92 ret->ptr = socket;
93 return ret;
94}
95
96static int socket_new(BIO* b) {
97 b->shutdown = 0;
98 b->init = 1;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000099 b->ptr = 0;
100 return 1;
101}
102
103static int socket_free(BIO* b) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800104 if (b == nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000105 return 0;
106 return 1;
107}
108
109static int socket_read(BIO* b, char* out, int outl) {
110 if (!out)
111 return -1;
112 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(b->ptr);
113 BIO_clear_retry_flags(b);
Stefan Holmer9131efd2016-05-23 18:19:26 +0200114 int result = socket->Recv(out, outl, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000115 if (result > 0) {
116 return result;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000117 } 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;
Jiawei Ou018dd6e2018-01-30 12:13:48 -0800145 case BIO_CTRL_EOF: {
146 rtc::AsyncSocket* socket = static_cast<rtc::AsyncSocket*>(ptr);
147 // 1 means socket closed.
148 return (socket->GetState() == rtc::AsyncSocket::CS_CLOSED) ? 1 : 0;
149 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000150 case BIO_CTRL_WPENDING:
151 case BIO_CTRL_PENDING:
152 return 0;
153 case BIO_CTRL_FLUSH:
154 return 1;
155 default:
156 return 0;
157 }
158}
159
deadbeefed3b9862017-06-02 10:33:16 -0700160static void LogSslError() {
161 // Walk down the error stack to find the SSL error.
162 uint32_t error_code;
163 const char* file;
164 int line;
165 do {
166 error_code = ERR_get_error_line(&file, &line);
167 if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100168 RTC_LOG(LS_ERROR) << "ERR_LIB_SSL: " << error_code << ", " << file << ":"
169 << line;
deadbeefed3b9862017-06-02 10:33:16 -0700170 break;
171 }
172 } while (error_code != 0);
173}
174
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000175/////////////////////////////////////////////////////////////////////////////
176// OpenSSLAdapter
177/////////////////////////////////////////////////////////////////////////////
178
179namespace rtc {
180
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100181#ifndef OPENSSL_IS_BORINGSSL
182
183// This array will store all of the mutexes available to OpenSSL.
deadbeef37f5ecf2017-02-27 14:06:41 -0800184static MUTEX_TYPE* mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100185
186static void locking_function(int mode, int n, const char * file, int line) {
187 if (mode & CRYPTO_LOCK) {
188 MUTEX_LOCK(mutex_buf[n]);
189 } else {
190 MUTEX_UNLOCK(mutex_buf[n]);
191 }
192}
193
194static unsigned long id_function() { // NOLINT
195 // Use old-style C cast because THREAD_ID's type varies with the platform,
196 // in some cases requiring static_cast, and in others requiring
197 // reinterpret_cast.
198 return (unsigned long)THREAD_ID; // NOLINT
199}
200
201static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
202 CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
203 if (!value)
deadbeef37f5ecf2017-02-27 14:06:41 -0800204 return nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100205 MUTEX_SETUP(value->mutex);
206 return value;
207}
208
209static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
210 const char* file, int line) {
211 if (mode & CRYPTO_LOCK) {
212 MUTEX_LOCK(l->mutex);
213 } else {
214 MUTEX_UNLOCK(l->mutex);
215 }
216}
217
218static void dyn_destroy_function(CRYPTO_dynlock_value* l,
219 const char* file, int line) {
220 MUTEX_CLEANUP(l->mutex);
221 delete l;
222}
223
224#endif // #ifndef OPENSSL_IS_BORINGSSL
225
deadbeef37f5ecf2017-02-27 14:06:41 -0800226VerificationCallback OpenSSLAdapter::custom_verify_callback_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000227
228bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100229 if (!InitializeSSLThread() || !SSL_library_init())
230 return false;
231#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
232 // Loading the error strings crashes mac_asan. Omit this debugging aid there.
233 SSL_load_error_strings();
234#endif
235 ERR_load_BIO_strings();
236 OpenSSL_add_all_algorithms();
237 RAND_poll();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000238 custom_verify_callback_ = callback;
239 return true;
240}
241
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100242bool OpenSSLAdapter::InitializeSSLThread() {
243 // BoringSSL is doing the locking internally, so the callbacks are not used
244 // in this case (and are no-ops anyways).
245#ifndef OPENSSL_IS_BORINGSSL
246 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
247 if (!mutex_buf)
248 return false;
249 for (int i = 0; i < CRYPTO_num_locks(); ++i)
250 MUTEX_SETUP(mutex_buf[i]);
251
252 // we need to cast our id_function to return an unsigned long -- pthread_t is
253 // a pointer
254 CRYPTO_set_id_callback(id_function);
255 CRYPTO_set_locking_callback(locking_function);
256 CRYPTO_set_dynlock_create_callback(dyn_create_function);
257 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
258 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
259#endif // #ifndef OPENSSL_IS_BORINGSSL
260 return true;
261}
262
263bool OpenSSLAdapter::CleanupSSL() {
264#ifndef OPENSSL_IS_BORINGSSL
265 if (!mutex_buf)
266 return false;
deadbeef37f5ecf2017-02-27 14:06:41 -0800267 CRYPTO_set_id_callback(nullptr);
268 CRYPTO_set_locking_callback(nullptr);
269 CRYPTO_set_dynlock_create_callback(nullptr);
270 CRYPTO_set_dynlock_lock_callback(nullptr);
271 CRYPTO_set_dynlock_destroy_callback(nullptr);
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100272 for (int i = 0; i < CRYPTO_num_locks(); ++i)
273 MUTEX_CLEANUP(mutex_buf[i]);
274 delete [] mutex_buf;
deadbeef37f5ecf2017-02-27 14:06:41 -0800275 mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100276#endif // #ifndef OPENSSL_IS_BORINGSSL
277 return true;
278}
279
Justin Uberti1d445502017-08-14 17:04:34 -0700280OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket,
281 OpenSSLAdapterFactory* factory)
deadbeef37f5ecf2017-02-27 14:06:41 -0800282 : SSLAdapter(socket),
Justin Uberti1d445502017-08-14 17:04:34 -0700283 factory_(factory),
deadbeef37f5ecf2017-02-27 14:06:41 -0800284 state_(SSL_NONE),
Steve Anton786de702017-08-17 15:15:46 -0700285 role_(SSL_CLIENT),
deadbeef37f5ecf2017-02-27 14:06:41 -0800286 ssl_read_needs_write_(false),
287 ssl_write_needs_read_(false),
288 restartable_(false),
289 ssl_(nullptr),
290 ssl_ctx_(nullptr),
291 ssl_mode_(SSL_MODE_TLS),
Diogo Real1dca9d52017-08-29 12:18:32 -0700292 ignore_bad_cert_(false),
Justin Uberti1d445502017-08-14 17:04:34 -0700293 custom_verification_succeeded_(false) {
294 // If a factory is used, take a reference on the factory's SSL_CTX.
295 // Otherwise, we'll create our own later.
296 // Either way, we'll release our reference via SSL_CTX_free() in Cleanup().
297 if (factory_) {
298 ssl_ctx_ = factory_->ssl_ctx();
299 RTC_DCHECK(ssl_ctx_);
300 // Note: if using OpenSSL, requires version 1.1.0 or later.
301 SSL_CTX_up_ref(ssl_ctx_);
302 }
303}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000304
305OpenSSLAdapter::~OpenSSLAdapter() {
306 Cleanup();
307}
308
Diogo Real1dca9d52017-08-29 12:18:32 -0700309void OpenSSLAdapter::SetIgnoreBadCert(bool ignore) {
310 ignore_bad_cert_ = ignore;
311}
312
313void OpenSSLAdapter::SetAlpnProtocols(const std::vector<std::string>& protos) {
314 alpn_protocols_ = protos;
315}
316
Diogo Real7bd1f1b2017-09-08 12:50:41 -0700317void OpenSSLAdapter::SetEllipticCurves(const std::vector<std::string>& curves) {
318 elliptic_curves_ = curves;
319}
320
Justin Uberti1d445502017-08-14 17:04:34 -0700321void OpenSSLAdapter::SetMode(SSLMode mode) {
322 RTC_DCHECK(!ssl_ctx_);
nisseede5da42017-01-12 05:15:36 -0800323 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000324 ssl_mode_ = mode;
325}
326
Steve Anton786de702017-08-17 15:15:46 -0700327void OpenSSLAdapter::SetIdentity(SSLIdentity* identity) {
328 RTC_DCHECK(!identity_);
329 identity_.reset(static_cast<OpenSSLIdentity*>(identity));
330}
331
332void OpenSSLAdapter::SetRole(SSLRole role) {
333 role_ = role;
334}
335
336AsyncSocket* OpenSSLAdapter::Accept(SocketAddress* paddr) {
337 RTC_DCHECK(role_ == SSL_SERVER);
338 AsyncSocket* socket = SSLAdapter::Accept(paddr);
339 if (!socket) {
340 return nullptr;
341 }
342
343 SSLAdapter* adapter = SSLAdapter::Create(socket);
344 adapter->SetIdentity(identity_->GetReference());
345 adapter->SetRole(rtc::SSL_SERVER);
Diogo Real1dca9d52017-08-29 12:18:32 -0700346 adapter->SetIgnoreBadCert(ignore_bad_cert_);
Steve Anton786de702017-08-17 15:15:46 -0700347 adapter->StartSSL("", false);
348 return adapter;
349}
350
Justin Uberti1d445502017-08-14 17:04:34 -0700351int OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000352 if (state_ != SSL_NONE)
353 return -1;
354
355 ssl_host_name_ = hostname;
356 restartable_ = restartable;
357
358 if (socket_->GetState() != Socket::CS_CONNECTED) {
359 state_ = SSL_WAIT;
360 return 0;
361 }
362
363 state_ = SSL_CONNECTING;
364 if (int err = BeginSSL()) {
365 Error("BeginSSL", err, false);
366 return err;
367 }
368
369 return 0;
370}
371
Justin Uberti1d445502017-08-14 17:04:34 -0700372int OpenSSLAdapter::BeginSSL() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100373 RTC_LOG(LS_INFO) << "OpenSSLAdapter::BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 05:15:36 -0800374 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000375
376 int err = 0;
deadbeef37f5ecf2017-02-27 14:06:41 -0800377 BIO* bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000378
Justin Uberti1d445502017-08-14 17:04:34 -0700379 // First set up the context. We should either have a factory, with its own
380 // pre-existing context, or be running standalone, in which case we will
381 // need to create one, and specify |false| to disable session caching.
382 if (!factory_) {
383 RTC_DCHECK(!ssl_ctx_);
384 ssl_ctx_ = CreateContext(ssl_mode_, false);
385 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000386 if (!ssl_ctx_) {
387 err = -1;
388 goto ssl_error;
389 }
390
Steve Anton786de702017-08-17 15:15:46 -0700391 if (identity_ && !identity_->ConfigureIdentity(ssl_ctx_)) {
392 SSL_CTX_free(ssl_ctx_);
393 err = -1;
394 goto ssl_error;
395 }
396
Peter Boström0b518bf2016-01-27 12:35:40 +0100397 bio = BIO_new_socket(socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000398 if (!bio) {
399 err = -1;
400 goto ssl_error;
401 }
402
403 ssl_ = SSL_new(ssl_ctx_);
404 if (!ssl_) {
405 err = -1;
406 goto ssl_error;
407 }
408
409 SSL_set_app_data(ssl_, this);
410
deadbeefed3b9862017-06-02 10:33:16 -0700411 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER allows different buffers to be passed
412 // into SSL_write when a record could only be partially transmitted (and thus
413 // requires another call to SSL_write to finish transmission). This allows us
414 // to copy the data into our own buffer when this occurs, since the original
415 // buffer can't safely be accessed after control exits Send.
416 // TODO(deadbeef): Do we want SSL_MODE_ENABLE_PARTIAL_WRITE? It doesn't
417 // appear Send handles partial writes properly, though maybe we never notice
418 // since we never send more than 16KB at once..
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000419 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
420 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
421
Justin Uberti1d445502017-08-14 17:04:34 -0700422 // Enable SNI, if a hostname is supplied.
Emad Omaradab1d2d2017-06-16 15:43:11 -0700423 if (!ssl_host_name_.empty()) {
424 SSL_set_tlsext_host_name(ssl_, ssl_host_name_.c_str());
Justin Uberti1d445502017-08-14 17:04:34 -0700425
426 // Enable session caching, if configured and a hostname is supplied.
427 if (factory_) {
428 SSL_SESSION* cached = factory_->LookupSession(ssl_host_name_);
429 if (cached) {
430 if (SSL_set_session(ssl_, cached) == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100431 RTC_LOG(LS_WARNING) << "Failed to apply SSL session from cache";
Justin Uberti1d445502017-08-14 17:04:34 -0700432 err = -1;
433 goto ssl_error;
434 }
435
Mirko Bonadei675513b2017-11-09 11:09:25 +0100436 RTC_LOG(LS_INFO) << "Attempting to resume SSL session to "
437 << ssl_host_name_;
Justin Uberti1d445502017-08-14 17:04:34 -0700438 }
439 }
Emad Omaradab1d2d2017-06-16 15:43:11 -0700440 }
441
Emad Omaracb79d232017-07-20 16:34:34 -0700442 // Set a couple common TLS extensions; even though we don't use them yet.
Emad Omaracb79d232017-07-20 16:34:34 -0700443 SSL_enable_ocsp_stapling(ssl_);
444 SSL_enable_signed_cert_timestamps(ssl_);
445
Diogo Real1dca9d52017-08-29 12:18:32 -0700446 if (!alpn_protocols_.empty()) {
447 std::string tls_alpn_string = TransformAlpnProtocols(alpn_protocols_);
448 if (!tls_alpn_string.empty()) {
449 SSL_set_alpn_protos(
450 ssl_, reinterpret_cast<const unsigned char*>(tls_alpn_string.data()),
451 tls_alpn_string.size());
452 }
453 }
454
Diogo Real7bd1f1b2017-09-08 12:50:41 -0700455 if (!elliptic_curves_.empty()) {
456 SSL_set1_curves_list(ssl_, rtc::join(elliptic_curves_, ':').c_str());
457 }
458
Justin Uberti1d445502017-08-14 17:04:34 -0700459 // Now that the initial config is done, transfer ownership of |bio| to the
460 // SSL object. If ContinueSSL() fails, the bio will be freed in Cleanup().
461 SSL_set_bio(ssl_, bio, bio);
deadbeef37f5ecf2017-02-27 14:06:41 -0800462 bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000463
Justin Uberti1d445502017-08-14 17:04:34 -0700464 // Do the connect.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000465 err = ContinueSSL();
466 if (err != 0)
467 goto ssl_error;
468
469 return err;
470
471ssl_error:
472 Cleanup();
473 if (bio)
474 BIO_free(bio);
475
476 return err;
477}
478
Justin Uberti1d445502017-08-14 17:04:34 -0700479int OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 05:15:36 -0800480 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000481
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000482 // Clear the DTLS timer
483 Thread::Current()->Clear(this, MSG_TIMEOUT);
484
Steve Anton786de702017-08-17 15:15:46 -0700485 int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000486 switch (SSL_get_error(ssl_, code)) {
487 case SSL_ERROR_NONE:
488 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100489 RTC_LOG(LS_ERROR) << "TLS post connection check failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000490 // make sure we close the socket
491 Cleanup();
492 // The connect failed so return -1 to shut down the socket
493 return -1;
494 }
495
496 state_ = SSL_CONNECTED;
497 AsyncSocketAdapter::OnConnectEvent(this);
498#if 0 // TODO: worry about this
499 // Don't let ourselves go away during the callbacks
500 PRefPtr<OpenSSLAdapter> lock(this);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100501 RTC_LOG(LS_INFO) << " -- onStreamReadable";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000502 AsyncSocketAdapter::OnReadEvent(this);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100503 RTC_LOG(LS_INFO) << " -- onStreamWriteable";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000504 AsyncSocketAdapter::OnWriteEvent(this);
505#endif
506 break;
507
508 case SSL_ERROR_WANT_READ:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100509 RTC_LOG(LS_VERBOSE) << " -- error want read";
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000510 struct timeval timeout;
511 if (DTLSv1_get_timeout(ssl_, &timeout)) {
512 int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
513
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700514 Thread::Current()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_TIMEOUT,
515 0);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000516 }
517 break;
518
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000519 case SSL_ERROR_WANT_WRITE:
520 break;
521
522 case SSL_ERROR_ZERO_RETURN:
523 default:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100524 RTC_LOG(LS_WARNING) << "ContinueSSL -- error " << code;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000525 return (code != 0) ? code : -1;
526 }
527
528 return 0;
529}
530
Justin Uberti1d445502017-08-14 17:04:34 -0700531void OpenSSLAdapter::Error(const char* context, int err, bool signal) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100532 RTC_LOG(LS_WARNING) << "OpenSSLAdapter::Error(" << context << ", " << err
533 << ")";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000534 state_ = SSL_ERROR;
535 SetError(err);
536 if (signal)
537 AsyncSocketAdapter::OnCloseEvent(this, err);
538}
539
Justin Uberti1d445502017-08-14 17:04:34 -0700540void OpenSSLAdapter::Cleanup() {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100541 RTC_LOG(LS_INFO) << "OpenSSLAdapter::Cleanup";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000542
543 state_ = SSL_NONE;
544 ssl_read_needs_write_ = false;
545 ssl_write_needs_read_ = false;
546 custom_verification_succeeded_ = false;
deadbeefed3b9862017-06-02 10:33:16 -0700547 pending_data_.Clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000548
549 if (ssl_) {
550 SSL_free(ssl_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800551 ssl_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000552 }
553
554 if (ssl_ctx_) {
555 SSL_CTX_free(ssl_ctx_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800556 ssl_ctx_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000557 }
Steve Anton786de702017-08-17 15:15:46 -0700558 identity_.reset();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000559
560 // Clear the DTLS timer
561 Thread::Current()->Clear(this, MSG_TIMEOUT);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000562}
563
deadbeefed3b9862017-06-02 10:33:16 -0700564int OpenSSLAdapter::DoSslWrite(const void* pv, size_t cb, int* error) {
565 // If we have pending data (that was previously only partially written by
566 // SSL_write), we shouldn't be attempting to write anything else.
567 RTC_DCHECK(pending_data_.empty() || pv == pending_data_.data());
568 RTC_DCHECK(error != nullptr);
569
570 ssl_write_needs_read_ = false;
571 int ret = SSL_write(ssl_, pv, checked_cast<int>(cb));
572 *error = SSL_get_error(ssl_, ret);
573 switch (*error) {
574 case SSL_ERROR_NONE:
575 // Success!
576 return ret;
577 case SSL_ERROR_WANT_READ:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100578 RTC_LOG(LS_INFO) << " -- error want read";
deadbeefed3b9862017-06-02 10:33:16 -0700579 ssl_write_needs_read_ = true;
580 SetError(EWOULDBLOCK);
581 break;
582 case SSL_ERROR_WANT_WRITE:
Mirko Bonadei675513b2017-11-09 11:09:25 +0100583 RTC_LOG(LS_INFO) << " -- error want write";
deadbeefed3b9862017-06-02 10:33:16 -0700584 SetError(EWOULDBLOCK);
585 break;
586 case SSL_ERROR_ZERO_RETURN:
deadbeefed3b9862017-06-02 10:33:16 -0700587 SetError(EWOULDBLOCK);
588 // do we need to signal closure?
589 break;
590 case SSL_ERROR_SSL:
591 LogSslError();
592 Error("SSL_write", ret ? ret : -1, false);
593 break;
594 default:
deadbeefed3b9862017-06-02 10:33:16 -0700595 Error("SSL_write", ret ? ret : -1, false);
596 break;
597 }
598
599 return SOCKET_ERROR;
600}
601
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000602//
603// AsyncSocket Implementation
604//
605
Justin Uberti1d445502017-08-14 17:04:34 -0700606int OpenSSLAdapter::Send(const void* pv, size_t cb) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000607 switch (state_) {
608 case SSL_NONE:
609 return AsyncSocketAdapter::Send(pv, cb);
610
611 case SSL_WAIT:
612 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700613 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000614 return SOCKET_ERROR;
615
616 case SSL_CONNECTED:
617 break;
618
619 case SSL_ERROR:
620 default:
621 return SOCKET_ERROR;
622 }
623
deadbeefed3b9862017-06-02 10:33:16 -0700624 int ret;
625 int error;
626
627 if (!pending_data_.empty()) {
628 ret = DoSslWrite(pending_data_.data(), pending_data_.size(), &error);
629 if (ret != static_cast<int>(pending_data_.size())) {
630 // We couldn't finish sending the pending data, so we definitely can't
631 // send any more data. Return with an EWOULDBLOCK error.
632 SetError(EWOULDBLOCK);
633 return SOCKET_ERROR;
634 }
635 // We completed sending the data previously passed into SSL_write! Now
636 // we're allowed to send more data.
637 pending_data_.Clear();
638 }
639
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000640 // OpenSSL will return an error if we try to write zero bytes
641 if (cb == 0)
642 return 0;
643
deadbeefed3b9862017-06-02 10:33:16 -0700644 ret = DoSslWrite(pv, cb, &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000645
deadbeefed3b9862017-06-02 10:33:16 -0700646 // If SSL_write fails with SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, this
647 // means the underlying socket is blocked on reading or (more typically)
648 // writing. When this happens, OpenSSL requires that the next call to
649 // SSL_write uses the same arguments (though, with
650 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, the actual buffer pointer may be
651 // different).
652 //
653 // However, after Send exits, we will have lost access to data the user of
654 // this class is trying to send, and there's no guarantee that the user of
655 // this class will call Send with the same arguements when it fails. So, we
656 // buffer the data ourselves. When we know the underlying socket is writable
657 // again from OnWriteEvent (or if Send is called again before that happens),
658 // we'll retry sending this buffered data.
deadbeefe5dce2b2017-06-02 11:52:06 -0700659 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
660 // Shouldn't be able to get to this point if we already have pending data.
661 RTC_DCHECK(pending_data_.empty());
Mirko Bonadei675513b2017-11-09 11:09:25 +0100662 RTC_LOG(LS_WARNING)
deadbeefed3b9862017-06-02 10:33:16 -0700663 << "SSL_write couldn't write to the underlying socket; buffering data.";
664 pending_data_.SetData(static_cast<const uint8_t*>(pv), cb);
665 // Since we're taking responsibility for sending this data, return its full
666 // size. The user of this class can consider it sent.
667 return cb;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000668 }
669
deadbeefed3b9862017-06-02 10:33:16 -0700670 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000671}
672
Justin Uberti1d445502017-08-14 17:04:34 -0700673int OpenSSLAdapter::SendTo(const void* pv,
674 size_t cb,
675 const SocketAddress& addr) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000676 if (socket_->GetState() == Socket::CS_CONNECTED &&
677 addr == socket_->GetRemoteAddress()) {
678 return Send(pv, cb);
679 }
680
681 SetError(ENOTCONN);
682
683 return SOCKET_ERROR;
684}
685
Stefan Holmer9131efd2016-05-23 18:19:26 +0200686int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000687 switch (state_) {
688
689 case SSL_NONE:
Stefan Holmer9131efd2016-05-23 18:19:26 +0200690 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000691
692 case SSL_WAIT:
693 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700694 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000695 return SOCKET_ERROR;
696
697 case SSL_CONNECTED:
698 break;
699
700 case SSL_ERROR:
701 default:
702 return SOCKET_ERROR;
703 }
704
705 // Don't trust OpenSSL with zero byte reads
706 if (cb == 0)
707 return 0;
708
709 ssl_read_needs_write_ = false;
710
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000711 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
deadbeefed3b9862017-06-02 10:33:16 -0700712 int error = SSL_get_error(ssl_, code);
713 switch (error) {
714 case SSL_ERROR_NONE:
deadbeefed3b9862017-06-02 10:33:16 -0700715 return code;
716 case SSL_ERROR_WANT_READ:
deadbeefed3b9862017-06-02 10:33:16 -0700717 SetError(EWOULDBLOCK);
718 break;
719 case SSL_ERROR_WANT_WRITE:
deadbeefed3b9862017-06-02 10:33:16 -0700720 ssl_read_needs_write_ = true;
721 SetError(EWOULDBLOCK);
722 break;
723 case SSL_ERROR_ZERO_RETURN:
deadbeefed3b9862017-06-02 10:33:16 -0700724 SetError(EWOULDBLOCK);
725 // do we need to signal closure?
726 break;
727 case SSL_ERROR_SSL:
728 LogSslError();
729 Error("SSL_read", (code ? code : -1), false);
730 break;
731 default:
deadbeefed3b9862017-06-02 10:33:16 -0700732 Error("SSL_read", (code ? code : -1), false);
733 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000734 }
735
736 return SOCKET_ERROR;
737}
738
Stefan Holmer9131efd2016-05-23 18:19:26 +0200739int OpenSSLAdapter::RecvFrom(void* pv,
740 size_t cb,
741 SocketAddress* paddr,
742 int64_t* timestamp) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000743 if (socket_->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 18:19:26 +0200744 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000745
746 *paddr = GetRemoteAddress();
747
748 return ret;
749 }
750
751 SetError(ENOTCONN);
752
753 return SOCKET_ERROR;
754}
755
Justin Uberti1d445502017-08-14 17:04:34 -0700756int OpenSSLAdapter::Close() {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000757 Cleanup();
758 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
759 return AsyncSocketAdapter::Close();
760}
761
Justin Uberti1d445502017-08-14 17:04:34 -0700762Socket::ConnState OpenSSLAdapter::GetState() const {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000763 //if (signal_close_)
764 // return CS_CONNECTED;
765 ConnState state = socket_->GetState();
766 if ((state == CS_CONNECTED)
767 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
768 state = CS_CONNECTING;
769 return state;
770}
771
Justin Uberti1d445502017-08-14 17:04:34 -0700772bool OpenSSLAdapter::IsResumedSession() {
773 return (ssl_ && SSL_session_reused(ssl_) == 1);
774}
775
776void OpenSSLAdapter::OnMessage(Message* msg) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000777 if (MSG_TIMEOUT == msg->message_id) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100778 RTC_LOG(LS_INFO) << "DTLS timeout expired";
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000779 DTLSv1_handle_timeout(ssl_);
780 ContinueSSL();
781 }
782}
783
Justin Uberti1d445502017-08-14 17:04:34 -0700784void OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100785 RTC_LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000786 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 05:15:36 -0800787 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000788 AsyncSocketAdapter::OnConnectEvent(socket);
789 return;
790 }
791
792 state_ = SSL_CONNECTING;
793 if (int err = BeginSSL()) {
794 AsyncSocketAdapter::OnCloseEvent(socket, err);
795 }
796}
797
Justin Uberti1d445502017-08-14 17:04:34 -0700798void OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000799 if (state_ == SSL_NONE) {
800 AsyncSocketAdapter::OnReadEvent(socket);
801 return;
802 }
803
804 if (state_ == SSL_CONNECTING) {
805 if (int err = ContinueSSL()) {
806 Error("ContinueSSL", err);
807 }
808 return;
809 }
810
811 if (state_ != SSL_CONNECTED)
812 return;
813
814 // Don't let ourselves go away during the callbacks
815 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
816 if (ssl_write_needs_read_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000817 AsyncSocketAdapter::OnWriteEvent(socket);
818 }
819
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000820 AsyncSocketAdapter::OnReadEvent(socket);
821}
822
Justin Uberti1d445502017-08-14 17:04:34 -0700823void OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000824 if (state_ == SSL_NONE) {
825 AsyncSocketAdapter::OnWriteEvent(socket);
826 return;
827 }
828
829 if (state_ == SSL_CONNECTING) {
830 if (int err = ContinueSSL()) {
831 Error("ContinueSSL", err);
832 }
833 return;
834 }
835
836 if (state_ != SSL_CONNECTED)
837 return;
838
839 // Don't let ourselves go away during the callbacks
840 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
841
842 if (ssl_read_needs_write_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000843 AsyncSocketAdapter::OnReadEvent(socket);
844 }
845
deadbeefed3b9862017-06-02 10:33:16 -0700846 // If a previous SSL_write failed due to the underlying socket being blocked,
847 // this will attempt finishing the write operation.
848 if (!pending_data_.empty()) {
849 int error;
850 if (DoSslWrite(pending_data_.data(), pending_data_.size(), &error) ==
851 static_cast<int>(pending_data_.size())) {
852 pending_data_.Clear();
853 }
854 }
855
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000856 AsyncSocketAdapter::OnWriteEvent(socket);
857}
858
Justin Uberti1d445502017-08-14 17:04:34 -0700859void OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100860 RTC_LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000861 AsyncSocketAdapter::OnCloseEvent(socket, err);
862}
863
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000864bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
865 bool ignore_bad_cert) {
866 if (!host)
867 return false;
868
869 // Checking the return from SSL_get_peer_certificate here is not strictly
870 // necessary. With our setup, it is not possible for it to return
deadbeef37f5ecf2017-02-27 14:06:41 -0800871 // null. However, it is good form to check the return.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000872 X509* certificate = SSL_get_peer_certificate(ssl);
873 if (!certificate)
874 return false;
875
876 // Logging certificates is extremely verbose. So it is disabled by default.
877#ifdef LOG_CERTIFICATES
878 {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100879 RTC_DLOG(LS_INFO) << "Certificate from server:";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000880 BIO* mem = BIO_new(BIO_s_mem());
881 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
882 BIO_write(mem, "\0", 1);
883 char* buffer;
884 BIO_get_mem_data(mem, &buffer);
Jonas Olssonaddc3802018-02-01 09:53:06 +0100885 RTC_DLOG(LS_INFO) << buffer;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000886 BIO_free(mem);
887
888 char* cipher_description =
deadbeef37f5ecf2017-02-27 14:06:41 -0800889 SSL_CIPHER_description(SSL_get_current_cipher(ssl), nullptr, 128);
Jonas Olssonaddc3802018-02-01 09:53:06 +0100890 RTC_DLOG(LS_INFO) << "Cipher: " << cipher_description;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000891 OPENSSL_free(cipher_description);
892 }
893#endif
894
895 bool ok = false;
davidben4ef903d2017-02-17 13:04:43 -0800896 GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(
897 X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr));
898 if (names) {
899 for (size_t i = 0; i < sk_GENERAL_NAME_num(names); i++) {
900 const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
901 if (name->type != GEN_DNS)
902 continue;
903 std::string value(
904 reinterpret_cast<const char*>(ASN1_STRING_data(name->d.dNSName)),
905 ASN1_STRING_length(name->d.dNSName));
906 // string_match takes NUL-terminated strings, so check for embedded NULs.
907 if (value.find('\0') != std::string::npos)
908 continue;
909 if (string_match(host, value.c_str())) {
910 ok = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000911 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000912 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000913 }
davidben4ef903d2017-02-17 13:04:43 -0800914 GENERAL_NAMES_free(names);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000915 }
916
917 char data[256];
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +0000918 X509_NAME* subject;
deadbeef37f5ecf2017-02-27 14:06:41 -0800919 if (!ok && ((subject = X509_get_subject_name(certificate)) != nullptr) &&
920 (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) >
921 0)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000922 data[sizeof(data)-1] = 0;
923 if (_stricmp(data, host) == 0)
924 ok = true;
925 }
926
927 X509_free(certificate);
928
929 // This should only ever be turned on for debugging and development.
930 if (!ok && ignore_bad_cert) {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100931 RTC_DLOG(LS_WARNING) << "TLS certificate check FAILED. "
932 << "Allowing connection anyway.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000933 ok = true;
934 }
935
936 return ok;
937}
938
939bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
Diogo Real1dca9d52017-08-29 12:18:32 -0700940 bool ok = VerifyServerName(ssl, host, ignore_bad_cert_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000941
942 if (ok) {
943 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
944 custom_verification_succeeded_);
945 }
946
Diogo Real1dca9d52017-08-29 12:18:32 -0700947 if (!ok && ignore_bad_cert_) {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100948 RTC_DLOG(LS_INFO) << "Other TLS post connection checks failed.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000949 ok = true;
950 }
951
952 return ok;
953}
954
tfarinaa41ab932015-10-30 16:08:48 -0700955#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000956
957// We only use this for tracing and so it is only needed in debug mode
958
Justin Uberti1d445502017-08-14 17:04:34 -0700959void OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000960 const char* str = "undefined";
961 int w = where & ~SSL_ST_MASK;
962 if (w & SSL_ST_CONNECT) {
963 str = "SSL_connect";
964 } else if (w & SSL_ST_ACCEPT) {
965 str = "SSL_accept";
966 }
967 if (where & SSL_CB_LOOP) {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100968 RTC_DLOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000969 } else if (where & SSL_CB_ALERT) {
970 str = (where & SSL_CB_READ) ? "read" : "write";
Jonas Olssonaddc3802018-02-01 09:53:06 +0100971 RTC_DLOG(LS_INFO) << "SSL3 alert " << str << ":"
972 << SSL_alert_type_string_long(ret) << ":"
973 << SSL_alert_desc_string_long(ret);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000974 } else if (where & SSL_CB_EXIT) {
975 if (ret == 0) {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100976 RTC_DLOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000977 } else if (ret < 0) {
Jonas Olssonaddc3802018-02-01 09:53:06 +0100978 RTC_DLOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000979 }
980 }
981}
982
tfarinaa41ab932015-10-30 16:08:48 -0700983#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000984
Justin Uberti1d445502017-08-14 17:04:34 -0700985int OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 16:08:48 -0700986#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000987 if (!ok) {
988 char data[256];
989 X509* cert = X509_STORE_CTX_get_current_cert(store);
990 int depth = X509_STORE_CTX_get_error_depth(store);
991 int err = X509_STORE_CTX_get_error(store);
992
Jonas Olssonaddc3802018-02-01 09:53:06 +0100993 RTC_DLOG(LS_INFO) << "Error with certificate at depth: " << depth;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000994 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
Jonas Olssonaddc3802018-02-01 09:53:06 +0100995 RTC_DLOG(LS_INFO) << " issuer = " << data;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000996 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
Jonas Olssonaddc3802018-02-01 09:53:06 +0100997 RTC_DLOG(LS_INFO) << " subject = " << data;
998 RTC_DLOG(LS_INFO) << " err = " << err << ":"
999 << X509_verify_cert_error_string(err);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001000 }
1001#endif
1002
1003 // Get our stream pointer from the store
1004 SSL* ssl = reinterpret_cast<SSL*>(
1005 X509_STORE_CTX_get_ex_data(store,
1006 SSL_get_ex_data_X509_STORE_CTX_idx()));
1007
1008 OpenSSLAdapter* stream =
1009 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
1010
1011 if (!ok && custom_verify_callback_) {
1012 void* cert =
1013 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
1014 if (custom_verify_callback_(cert)) {
1015 stream->custom_verification_succeeded_ = true;
Mirko Bonadei675513b2017-11-09 11:09:25 +01001016 RTC_LOG(LS_INFO) << "validated certificate using custom callback";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001017 ok = true;
1018 }
1019 }
1020
1021 // Should only be used for debugging and development.
Diogo Real1dca9d52017-08-29 12:18:32 -07001022 if (!ok && stream->ignore_bad_cert_) {
Jonas Olssonaddc3802018-02-01 09:53:06 +01001023 RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001024 ok = 1;
1025 }
1026
1027 return ok;
1028}
1029
Justin Uberti1d445502017-08-14 17:04:34 -07001030int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) {
1031 OpenSSLAdapter* stream =
1032 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
1033 RTC_DCHECK(stream->factory_);
Mirko Bonadei675513b2017-11-09 11:09:25 +01001034 RTC_LOG(LS_INFO) << "Caching SSL session for " << stream->ssl_host_name_;
Justin Uberti1d445502017-08-14 17:04:34 -07001035 stream->factory_->AddSession(stream->ssl_host_name_, session);
1036 return 1; // We've taken ownership of the session; OpenSSL shouldn't free it.
1037}
1038
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001039bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
1040 // Add the root cert that we care about to the SSL context
1041 int count_of_added_certs = 0;
tfarina5237aaf2015-11-10 23:44:30 -08001042 for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001043 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
1044 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
deadbeef37f5ecf2017-02-27 14:06:41 -08001045 X509* cert =
1046 d2i_X509(nullptr, &cert_buffer, checked_cast<long>(cert_buffer_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001047 if (cert) {
1048 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
1049 if (return_value == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001050 RTC_LOG(LS_WARNING) << "Unable to add certificate.";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001051 } else {
1052 count_of_added_certs++;
1053 }
1054 X509_free(cert);
1055 }
1056 }
1057 return count_of_added_certs > 0;
1058}
1059
Justin Uberti1d445502017-08-14 17:04:34 -07001060SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
Emad Omarac6de0c92017-06-21 16:40:56 -07001061 // Use (D)TLS 1.2.
1062 // Note: BoringSSL supports a range of versions by setting max/min version
1063 // (Default V1.0 to V1.2). However (D)TLSv1_2_client_method functions used
1064 // below in OpenSSL only support V1.2.
1065 SSL_CTX* ctx = nullptr;
1066#ifdef OPENSSL_IS_BORINGSSL
Justin Uberti1d445502017-08-14 17:04:34 -07001067 ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
Emad Omarac6de0c92017-06-21 16:40:56 -07001068#else
Justin Uberti1d445502017-08-14 17:04:34 -07001069 ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLSv1_2_client_method()
1070 : TLSv1_2_client_method());
Emad Omarac6de0c92017-06-21 16:40:56 -07001071#endif // OPENSSL_IS_BORINGSSL
deadbeef37f5ecf2017-02-27 14:06:41 -08001072 if (ctx == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001073 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
Mirko Bonadei675513b2017-11-09 11:09:25 +01001074 RTC_LOG(LS_WARNING) << "SSL_CTX creation failed: " << '"'
1075 << ERR_reason_error_string(error) << "\" "
1076 << "(error=" << error << ')';
deadbeef37f5ecf2017-02-27 14:06:41 -08001077 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001078 }
1079 if (!ConfigureTrustedRootCertificates(ctx)) {
1080 SSL_CTX_free(ctx);
deadbeef37f5ecf2017-02-27 14:06:41 -08001081 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001082 }
1083
tfarinaa41ab932015-10-30 16:08:48 -07001084#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001085 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
1086#endif
1087
1088 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
1089 SSL_CTX_set_verify_depth(ctx, 4);
Emad Omarac6de0c92017-06-21 16:40:56 -07001090 // Use defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers
1091 // (note that SHA256 and SHA384 only select legacy CBC ciphers).
1092 // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining
1093 // CBC-mode ECDSA ciphers.
1094 SSL_CTX_set_cipher_list(
1095 ctx, "ALL:!SHA256:!SHA384:!aPSK:!ECDSA+SHA1:!ADH:!LOW:!EXP:!MD5");
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001096
Justin Uberti1d445502017-08-14 17:04:34 -07001097 if (mode == SSL_MODE_DTLS) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +00001098 SSL_CTX_set_read_ahead(ctx, 1);
1099 }
1100
Justin Uberti1d445502017-08-14 17:04:34 -07001101 if (enable_cache) {
1102 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);
1103 SSL_CTX_sess_set_new_cb(ctx, &OpenSSLAdapter::NewSSLSessionCallback);
1104 }
1105
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001106 return ctx;
1107}
1108
Diogo Real1dca9d52017-08-29 12:18:32 -07001109std::string TransformAlpnProtocols(
1110 const std::vector<std::string>& alpn_protocols) {
1111 // Transforms the alpn_protocols list to the format expected by
1112 // Open/BoringSSL. This requires joining the protocols into a single string
1113 // and prepending a character with the size of the protocol string before
1114 // each protocol.
1115 std::string transformed_alpn;
1116 for (const std::string& proto : alpn_protocols) {
1117 if (proto.size() == 0 || proto.size() > 0xFF) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001118 RTC_LOG(LS_ERROR) << "OpenSSLAdapter::Error("
1119 << "TransformAlpnProtocols received proto with size "
1120 << proto.size() << ")";
Diogo Real1dca9d52017-08-29 12:18:32 -07001121 return "";
1122 }
1123 transformed_alpn += static_cast<char>(proto.size());
1124 transformed_alpn += proto;
Mirko Bonadei675513b2017-11-09 11:09:25 +01001125 RTC_LOG(LS_VERBOSE) << "TransformAlpnProtocols: Adding proto: " << proto;
Diogo Real1dca9d52017-08-29 12:18:32 -07001126 }
1127 return transformed_alpn;
1128}
1129
Justin Uberti1d445502017-08-14 17:04:34 -07001130//////////////////////////////////////////////////////////////////////
1131// OpenSSLAdapterFactory
1132//////////////////////////////////////////////////////////////////////
1133
1134OpenSSLAdapterFactory::OpenSSLAdapterFactory()
1135 : ssl_mode_(SSL_MODE_TLS), ssl_ctx_(nullptr) {}
1136
1137OpenSSLAdapterFactory::~OpenSSLAdapterFactory() {
1138 for (auto it : sessions_) {
1139 SSL_SESSION_free(it.second);
1140 }
1141 SSL_CTX_free(ssl_ctx_);
1142}
1143
1144void OpenSSLAdapterFactory::SetMode(SSLMode mode) {
1145 RTC_DCHECK(!ssl_ctx_);
1146 ssl_mode_ = mode;
1147}
1148
1149OpenSSLAdapter* OpenSSLAdapterFactory::CreateAdapter(AsyncSocket* socket) {
1150 if (!ssl_ctx_) {
1151 bool enable_cache = true;
1152 ssl_ctx_ = OpenSSLAdapter::CreateContext(ssl_mode_, enable_cache);
1153 if (!ssl_ctx_) {
1154 return nullptr;
1155 }
1156 }
1157
1158 return new OpenSSLAdapter(socket, this);
1159}
1160
1161SSL_SESSION* OpenSSLAdapterFactory::LookupSession(const std::string& hostname) {
1162 auto it = sessions_.find(hostname);
1163 return (it != sessions_.end()) ? it->second : nullptr;
1164}
1165
1166void OpenSSLAdapterFactory::AddSession(const std::string& hostname,
1167 SSL_SESSION* new_session) {
1168 SSL_SESSION* old_session = LookupSession(hostname);
1169 SSL_SESSION_free(old_session);
1170 sessions_[hostname] = new_session;
1171}
1172
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001173} // namespace rtc