blob: e1d0a5802eef4cf019531ba3a0bde7acc491c957 [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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000011#include "webrtc/base/openssladapter.h"
12
13#if defined(WEBRTC_POSIX)
14#include <unistd.h>
15#endif
16
17// Must be included first before openssl headers.
18#include "webrtc/base/win32.h" // NOLINT
19
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
tfarina5237aaf2015-11-10 23:44:30 -080028#include "webrtc/base/arraysize.h"
nisseede5da42017-01-12 05:15:36 -080029#include "webrtc/base/checks.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000030#include "webrtc/base/logging.h"
31#include "webrtc/base/openssl.h"
Tommid44c0772016-03-11 17:12:32 -080032#include "webrtc/base/safe_conversions.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033#include "webrtc/base/sslroots.h"
34#include "webrtc/base/stringutils.h"
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +000035#include "webrtc/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
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000277OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
deadbeef37f5ecf2017-02-27 14:06:41 -0800278 : SSLAdapter(socket),
279 state_(SSL_NONE),
280 ssl_read_needs_write_(false),
281 ssl_write_needs_read_(false),
282 restartable_(false),
283 ssl_(nullptr),
284 ssl_ctx_(nullptr),
285 ssl_mode_(SSL_MODE_TLS),
286 custom_verification_succeeded_(false) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000287
288OpenSSLAdapter::~OpenSSLAdapter() {
289 Cleanup();
290}
291
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000292void
293OpenSSLAdapter::SetMode(SSLMode mode) {
nisseede5da42017-01-12 05:15:36 -0800294 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000295 ssl_mode_ = mode;
296}
297
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000298int
299OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
300 if (state_ != SSL_NONE)
301 return -1;
302
303 ssl_host_name_ = hostname;
304 restartable_ = restartable;
305
306 if (socket_->GetState() != Socket::CS_CONNECTED) {
307 state_ = SSL_WAIT;
308 return 0;
309 }
310
311 state_ = SSL_CONNECTING;
312 if (int err = BeginSSL()) {
313 Error("BeginSSL", err, false);
314 return err;
315 }
316
317 return 0;
318}
319
320int
321OpenSSLAdapter::BeginSSL() {
322 LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 05:15:36 -0800323 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000324
325 int err = 0;
deadbeef37f5ecf2017-02-27 14:06:41 -0800326 BIO* bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000327
328 // First set up the context
329 if (!ssl_ctx_)
330 ssl_ctx_ = SetupSSLContext();
331
332 if (!ssl_ctx_) {
333 err = -1;
334 goto ssl_error;
335 }
336
Peter Boström0b518bf2016-01-27 12:35:40 +0100337 bio = BIO_new_socket(socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000338 if (!bio) {
339 err = -1;
340 goto ssl_error;
341 }
342
343 ssl_ = SSL_new(ssl_ctx_);
344 if (!ssl_) {
345 err = -1;
346 goto ssl_error;
347 }
348
349 SSL_set_app_data(ssl_, this);
350
351 SSL_set_bio(ssl_, bio, bio);
deadbeefed3b9862017-06-02 10:33:16 -0700352 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER allows different buffers to be passed
353 // into SSL_write when a record could only be partially transmitted (and thus
354 // requires another call to SSL_write to finish transmission). This allows us
355 // to copy the data into our own buffer when this occurs, since the original
356 // buffer can't safely be accessed after control exits Send.
357 // TODO(deadbeef): Do we want SSL_MODE_ENABLE_PARTIAL_WRITE? It doesn't
358 // appear Send handles partial writes properly, though maybe we never notice
359 // since we never send more than 16KB at once..
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000360 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
361 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
362
363 // the SSL object owns the bio now
deadbeef37f5ecf2017-02-27 14:06:41 -0800364 bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000365
366 // Do the connect
367 err = ContinueSSL();
368 if (err != 0)
369 goto ssl_error;
370
371 return err;
372
373ssl_error:
374 Cleanup();
375 if (bio)
376 BIO_free(bio);
377
378 return err;
379}
380
381int
382OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 05:15:36 -0800383 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000384
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000385 // Clear the DTLS timer
386 Thread::Current()->Clear(this, MSG_TIMEOUT);
387
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000388 int code = SSL_connect(ssl_);
389 switch (SSL_get_error(ssl_, code)) {
390 case SSL_ERROR_NONE:
391 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
392 LOG(LS_ERROR) << "TLS post connection check failed";
393 // make sure we close the socket
394 Cleanup();
395 // The connect failed so return -1 to shut down the socket
396 return -1;
397 }
398
399 state_ = SSL_CONNECTED;
400 AsyncSocketAdapter::OnConnectEvent(this);
401#if 0 // TODO: worry about this
402 // Don't let ourselves go away during the callbacks
403 PRefPtr<OpenSSLAdapter> lock(this);
404 LOG(LS_INFO) << " -- onStreamReadable";
405 AsyncSocketAdapter::OnReadEvent(this);
406 LOG(LS_INFO) << " -- onStreamWriteable";
407 AsyncSocketAdapter::OnWriteEvent(this);
408#endif
409 break;
410
411 case SSL_ERROR_WANT_READ:
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000412 LOG(LS_VERBOSE) << " -- error want read";
413 struct timeval timeout;
414 if (DTLSv1_get_timeout(ssl_, &timeout)) {
415 int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
416
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700417 Thread::Current()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_TIMEOUT,
418 0);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000419 }
420 break;
421
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000422 case SSL_ERROR_WANT_WRITE:
423 break;
424
425 case SSL_ERROR_ZERO_RETURN:
426 default:
427 LOG(LS_WARNING) << "ContinueSSL -- error " << code;
428 return (code != 0) ? code : -1;
429 }
430
431 return 0;
432}
433
434void
435OpenSSLAdapter::Error(const char* context, int err, bool signal) {
436 LOG(LS_WARNING) << "OpenSSLAdapter::Error("
437 << context << ", " << err << ")";
438 state_ = SSL_ERROR;
439 SetError(err);
440 if (signal)
441 AsyncSocketAdapter::OnCloseEvent(this, err);
442}
443
444void
445OpenSSLAdapter::Cleanup() {
446 LOG(LS_INFO) << "Cleanup";
447
448 state_ = SSL_NONE;
449 ssl_read_needs_write_ = false;
450 ssl_write_needs_read_ = false;
451 custom_verification_succeeded_ = false;
deadbeefed3b9862017-06-02 10:33:16 -0700452 pending_data_.Clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000453
454 if (ssl_) {
455 SSL_free(ssl_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800456 ssl_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000457 }
458
459 if (ssl_ctx_) {
460 SSL_CTX_free(ssl_ctx_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800461 ssl_ctx_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000462 }
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000463
464 // Clear the DTLS timer
465 Thread::Current()->Clear(this, MSG_TIMEOUT);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000466}
467
deadbeefed3b9862017-06-02 10:33:16 -0700468int OpenSSLAdapter::DoSslWrite(const void* pv, size_t cb, int* error) {
469 // If we have pending data (that was previously only partially written by
470 // SSL_write), we shouldn't be attempting to write anything else.
471 RTC_DCHECK(pending_data_.empty() || pv == pending_data_.data());
472 RTC_DCHECK(error != nullptr);
473
474 ssl_write_needs_read_ = false;
475 int ret = SSL_write(ssl_, pv, checked_cast<int>(cb));
476 *error = SSL_get_error(ssl_, ret);
477 switch (*error) {
478 case SSL_ERROR_NONE:
479 // Success!
480 return ret;
481 case SSL_ERROR_WANT_READ:
482 LOG(LS_INFO) << " -- error want read";
483 ssl_write_needs_read_ = true;
484 SetError(EWOULDBLOCK);
485 break;
486 case SSL_ERROR_WANT_WRITE:
487 LOG(LS_INFO) << " -- error want write";
488 SetError(EWOULDBLOCK);
489 break;
490 case SSL_ERROR_ZERO_RETURN:
491 // LOG(LS_INFO) << " -- remote side closed";
492 SetError(EWOULDBLOCK);
493 // do we need to signal closure?
494 break;
495 case SSL_ERROR_SSL:
496 LogSslError();
497 Error("SSL_write", ret ? ret : -1, false);
498 break;
499 default:
500 LOG(LS_WARNING) << "Unknown error from SSL_write: " << *error;
501 Error("SSL_write", ret ? ret : -1, false);
502 break;
503 }
504
505 return SOCKET_ERROR;
506}
507
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000508//
509// AsyncSocket Implementation
510//
511
512int
513OpenSSLAdapter::Send(const void* pv, size_t cb) {
514 //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
515
516 switch (state_) {
517 case SSL_NONE:
518 return AsyncSocketAdapter::Send(pv, cb);
519
520 case SSL_WAIT:
521 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700522 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000523 return SOCKET_ERROR;
524
525 case SSL_CONNECTED:
526 break;
527
528 case SSL_ERROR:
529 default:
530 return SOCKET_ERROR;
531 }
532
deadbeefed3b9862017-06-02 10:33:16 -0700533 int ret;
534 int error;
535
536 if (!pending_data_.empty()) {
537 ret = DoSslWrite(pending_data_.data(), pending_data_.size(), &error);
538 if (ret != static_cast<int>(pending_data_.size())) {
539 // We couldn't finish sending the pending data, so we definitely can't
540 // send any more data. Return with an EWOULDBLOCK error.
541 SetError(EWOULDBLOCK);
542 return SOCKET_ERROR;
543 }
544 // We completed sending the data previously passed into SSL_write! Now
545 // we're allowed to send more data.
546 pending_data_.Clear();
547 }
548
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000549 // OpenSSL will return an error if we try to write zero bytes
550 if (cb == 0)
551 return 0;
552
deadbeefed3b9862017-06-02 10:33:16 -0700553 ret = DoSslWrite(pv, cb, &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000554
deadbeefed3b9862017-06-02 10:33:16 -0700555 // If SSL_write fails with SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, this
556 // means the underlying socket is blocked on reading or (more typically)
557 // writing. When this happens, OpenSSL requires that the next call to
558 // SSL_write uses the same arguments (though, with
559 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, the actual buffer pointer may be
560 // different).
561 //
562 // However, after Send exits, we will have lost access to data the user of
563 // this class is trying to send, and there's no guarantee that the user of
564 // this class will call Send with the same arguements when it fails. So, we
565 // buffer the data ourselves. When we know the underlying socket is writable
566 // again from OnWriteEvent (or if Send is called again before that happens),
567 // we'll retry sending this buffered data.
deadbeefe5dce2b2017-06-02 11:52:06 -0700568 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
569 // Shouldn't be able to get to this point if we already have pending data.
570 RTC_DCHECK(pending_data_.empty());
deadbeefed3b9862017-06-02 10:33:16 -0700571 LOG(LS_WARNING)
572 << "SSL_write couldn't write to the underlying socket; buffering data.";
573 pending_data_.SetData(static_cast<const uint8_t*>(pv), cb);
574 // Since we're taking responsibility for sending this data, return its full
575 // size. The user of this class can consider it sent.
576 return cb;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000577 }
578
deadbeefed3b9862017-06-02 10:33:16 -0700579 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000580}
581
582int
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000583OpenSSLAdapter::SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
584 if (socket_->GetState() == Socket::CS_CONNECTED &&
585 addr == socket_->GetRemoteAddress()) {
586 return Send(pv, cb);
587 }
588
589 SetError(ENOTCONN);
590
591 return SOCKET_ERROR;
592}
593
Stefan Holmer9131efd2016-05-23 18:19:26 +0200594int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000595 //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
596 switch (state_) {
597
598 case SSL_NONE:
Stefan Holmer9131efd2016-05-23 18:19:26 +0200599 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000600
601 case SSL_WAIT:
602 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700603 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000604 return SOCKET_ERROR;
605
606 case SSL_CONNECTED:
607 break;
608
609 case SSL_ERROR:
610 default:
611 return SOCKET_ERROR;
612 }
613
614 // Don't trust OpenSSL with zero byte reads
615 if (cb == 0)
616 return 0;
617
618 ssl_read_needs_write_ = false;
619
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000620 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
deadbeefed3b9862017-06-02 10:33:16 -0700621 int error = SSL_get_error(ssl_, code);
622 switch (error) {
623 case SSL_ERROR_NONE:
624 // LOG(LS_INFO) << " -- success";
625 return code;
626 case SSL_ERROR_WANT_READ:
627 // LOG(LS_INFO) << " -- error want read";
628 SetError(EWOULDBLOCK);
629 break;
630 case SSL_ERROR_WANT_WRITE:
631 // LOG(LS_INFO) << " -- error want write";
632 ssl_read_needs_write_ = true;
633 SetError(EWOULDBLOCK);
634 break;
635 case SSL_ERROR_ZERO_RETURN:
636 // LOG(LS_INFO) << " -- remote side closed";
637 SetError(EWOULDBLOCK);
638 // do we need to signal closure?
639 break;
640 case SSL_ERROR_SSL:
641 LogSslError();
642 Error("SSL_read", (code ? code : -1), false);
643 break;
644 default:
645 LOG(LS_WARNING) << "Unknown error from SSL_read: " << error;
646 Error("SSL_read", (code ? code : -1), false);
647 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000648 }
649
650 return SOCKET_ERROR;
651}
652
Stefan Holmer9131efd2016-05-23 18:19:26 +0200653int OpenSSLAdapter::RecvFrom(void* pv,
654 size_t cb,
655 SocketAddress* paddr,
656 int64_t* timestamp) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000657 if (socket_->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 18:19:26 +0200658 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000659
660 *paddr = GetRemoteAddress();
661
662 return ret;
663 }
664
665 SetError(ENOTCONN);
666
667 return SOCKET_ERROR;
668}
669
670int
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000671OpenSSLAdapter::Close() {
672 Cleanup();
673 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
674 return AsyncSocketAdapter::Close();
675}
676
677Socket::ConnState
678OpenSSLAdapter::GetState() const {
679 //if (signal_close_)
680 // return CS_CONNECTED;
681 ConnState state = socket_->GetState();
682 if ((state == CS_CONNECTED)
683 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
684 state = CS_CONNECTING;
685 return state;
686}
687
688void
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000689OpenSSLAdapter::OnMessage(Message* msg) {
690 if (MSG_TIMEOUT == msg->message_id) {
691 LOG(LS_INFO) << "DTLS timeout expired";
692 DTLSv1_handle_timeout(ssl_);
693 ContinueSSL();
694 }
695}
696
697void
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000698OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
699 LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
700 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 05:15:36 -0800701 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000702 AsyncSocketAdapter::OnConnectEvent(socket);
703 return;
704 }
705
706 state_ = SSL_CONNECTING;
707 if (int err = BeginSSL()) {
708 AsyncSocketAdapter::OnCloseEvent(socket, err);
709 }
710}
711
712void
713OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
714 //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
715
716 if (state_ == SSL_NONE) {
717 AsyncSocketAdapter::OnReadEvent(socket);
718 return;
719 }
720
721 if (state_ == SSL_CONNECTING) {
722 if (int err = ContinueSSL()) {
723 Error("ContinueSSL", err);
724 }
725 return;
726 }
727
728 if (state_ != SSL_CONNECTED)
729 return;
730
731 // Don't let ourselves go away during the callbacks
732 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
733 if (ssl_write_needs_read_) {
734 //LOG(LS_INFO) << " -- onStreamWriteable";
735 AsyncSocketAdapter::OnWriteEvent(socket);
736 }
737
738 //LOG(LS_INFO) << " -- onStreamReadable";
739 AsyncSocketAdapter::OnReadEvent(socket);
740}
741
742void
743OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
744 //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
745
746 if (state_ == SSL_NONE) {
747 AsyncSocketAdapter::OnWriteEvent(socket);
748 return;
749 }
750
751 if (state_ == SSL_CONNECTING) {
752 if (int err = ContinueSSL()) {
753 Error("ContinueSSL", err);
754 }
755 return;
756 }
757
758 if (state_ != SSL_CONNECTED)
759 return;
760
761 // Don't let ourselves go away during the callbacks
762 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
763
764 if (ssl_read_needs_write_) {
765 //LOG(LS_INFO) << " -- onStreamReadable";
766 AsyncSocketAdapter::OnReadEvent(socket);
767 }
768
deadbeefed3b9862017-06-02 10:33:16 -0700769 // If a previous SSL_write failed due to the underlying socket being blocked,
770 // this will attempt finishing the write operation.
771 if (!pending_data_.empty()) {
772 int error;
773 if (DoSslWrite(pending_data_.data(), pending_data_.size(), &error) ==
774 static_cast<int>(pending_data_.size())) {
775 pending_data_.Clear();
776 }
777 }
778
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000779 //LOG(LS_INFO) << " -- onStreamWriteable";
780 AsyncSocketAdapter::OnWriteEvent(socket);
781}
782
783void
784OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
785 LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
786 AsyncSocketAdapter::OnCloseEvent(socket, err);
787}
788
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000789bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
790 bool ignore_bad_cert) {
791 if (!host)
792 return false;
793
794 // Checking the return from SSL_get_peer_certificate here is not strictly
795 // necessary. With our setup, it is not possible for it to return
deadbeef37f5ecf2017-02-27 14:06:41 -0800796 // null. However, it is good form to check the return.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000797 X509* certificate = SSL_get_peer_certificate(ssl);
798 if (!certificate)
799 return false;
800
801 // Logging certificates is extremely verbose. So it is disabled by default.
802#ifdef LOG_CERTIFICATES
803 {
804 LOG(LS_INFO) << "Certificate from server:";
805 BIO* mem = BIO_new(BIO_s_mem());
806 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
807 BIO_write(mem, "\0", 1);
808 char* buffer;
809 BIO_get_mem_data(mem, &buffer);
810 LOG(LS_INFO) << buffer;
811 BIO_free(mem);
812
813 char* cipher_description =
deadbeef37f5ecf2017-02-27 14:06:41 -0800814 SSL_CIPHER_description(SSL_get_current_cipher(ssl), nullptr, 128);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000815 LOG(LS_INFO) << "Cipher: " << cipher_description;
816 OPENSSL_free(cipher_description);
817 }
818#endif
819
820 bool ok = false;
davidben4ef903d2017-02-17 13:04:43 -0800821 GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(
822 X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr));
823 if (names) {
824 for (size_t i = 0; i < sk_GENERAL_NAME_num(names); i++) {
825 const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
826 if (name->type != GEN_DNS)
827 continue;
828 std::string value(
829 reinterpret_cast<const char*>(ASN1_STRING_data(name->d.dNSName)),
830 ASN1_STRING_length(name->d.dNSName));
831 // string_match takes NUL-terminated strings, so check for embedded NULs.
832 if (value.find('\0') != std::string::npos)
833 continue;
834 if (string_match(host, value.c_str())) {
835 ok = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000836 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000837 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000838 }
davidben4ef903d2017-02-17 13:04:43 -0800839 GENERAL_NAMES_free(names);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000840 }
841
842 char data[256];
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +0000843 X509_NAME* subject;
deadbeef37f5ecf2017-02-27 14:06:41 -0800844 if (!ok && ((subject = X509_get_subject_name(certificate)) != nullptr) &&
845 (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) >
846 0)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000847 data[sizeof(data)-1] = 0;
848 if (_stricmp(data, host) == 0)
849 ok = true;
850 }
851
852 X509_free(certificate);
853
854 // This should only ever be turned on for debugging and development.
855 if (!ok && ignore_bad_cert) {
856 LOG(LS_WARNING) << "TLS certificate check FAILED. "
857 << "Allowing connection anyway.";
858 ok = true;
859 }
860
861 return ok;
862}
863
864bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
865 bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
866
867 if (ok) {
868 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
869 custom_verification_succeeded_);
870 }
871
872 if (!ok && ignore_bad_cert()) {
873 LOG(LS_INFO) << "Other TLS post connection checks failed.";
874 ok = true;
875 }
876
877 return ok;
878}
879
tfarinaa41ab932015-10-30 16:08:48 -0700880#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000881
882// We only use this for tracing and so it is only needed in debug mode
883
884void
885OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
886 const char* str = "undefined";
887 int w = where & ~SSL_ST_MASK;
888 if (w & SSL_ST_CONNECT) {
889 str = "SSL_connect";
890 } else if (w & SSL_ST_ACCEPT) {
891 str = "SSL_accept";
892 }
893 if (where & SSL_CB_LOOP) {
894 LOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
895 } else if (where & SSL_CB_ALERT) {
896 str = (where & SSL_CB_READ) ? "read" : "write";
897 LOG(LS_INFO) << "SSL3 alert " << str
898 << ":" << SSL_alert_type_string_long(ret)
899 << ":" << SSL_alert_desc_string_long(ret);
900 } else if (where & SSL_CB_EXIT) {
901 if (ret == 0) {
902 LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
903 } else if (ret < 0) {
904 LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
905 }
906 }
907}
908
tfarinaa41ab932015-10-30 16:08:48 -0700909#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000910
911int
912OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 16:08:48 -0700913#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000914 if (!ok) {
915 char data[256];
916 X509* cert = X509_STORE_CTX_get_current_cert(store);
917 int depth = X509_STORE_CTX_get_error_depth(store);
918 int err = X509_STORE_CTX_get_error(store);
919
920 LOG(LS_INFO) << "Error with certificate at depth: " << depth;
921 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
922 LOG(LS_INFO) << " issuer = " << data;
923 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
924 LOG(LS_INFO) << " subject = " << data;
925 LOG(LS_INFO) << " err = " << err
926 << ":" << X509_verify_cert_error_string(err);
927 }
928#endif
929
930 // Get our stream pointer from the store
931 SSL* ssl = reinterpret_cast<SSL*>(
932 X509_STORE_CTX_get_ex_data(store,
933 SSL_get_ex_data_X509_STORE_CTX_idx()));
934
935 OpenSSLAdapter* stream =
936 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
937
938 if (!ok && custom_verify_callback_) {
939 void* cert =
940 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
941 if (custom_verify_callback_(cert)) {
942 stream->custom_verification_succeeded_ = true;
943 LOG(LS_INFO) << "validated certificate using custom callback";
944 ok = true;
945 }
946 }
947
948 // Should only be used for debugging and development.
949 if (!ok && stream->ignore_bad_cert()) {
950 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
951 ok = 1;
952 }
953
954 return ok;
955}
956
957bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
958 // Add the root cert that we care about to the SSL context
959 int count_of_added_certs = 0;
tfarina5237aaf2015-11-10 23:44:30 -0800960 for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000961 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
962 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
deadbeef37f5ecf2017-02-27 14:06:41 -0800963 X509* cert =
964 d2i_X509(nullptr, &cert_buffer, checked_cast<long>(cert_buffer_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000965 if (cert) {
966 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
967 if (return_value == 0) {
968 LOG(LS_WARNING) << "Unable to add certificate.";
969 } else {
970 count_of_added_certs++;
971 }
972 X509_free(cert);
973 }
974 }
975 return count_of_added_certs > 0;
976}
977
978SSL_CTX*
979OpenSSLAdapter::SetupSSLContext() {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000980 SSL_CTX* ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
981 DTLSv1_client_method() : TLSv1_client_method());
deadbeef37f5ecf2017-02-27 14:06:41 -0800982 if (ctx == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000983 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
984 LOG(LS_WARNING) << "SSL_CTX creation failed: "
985 << '"' << ERR_reason_error_string(error) << "\" "
986 << "(error=" << error << ')';
deadbeef37f5ecf2017-02-27 14:06:41 -0800987 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000988 }
989 if (!ConfigureTrustedRootCertificates(ctx)) {
990 SSL_CTX_free(ctx);
deadbeef37f5ecf2017-02-27 14:06:41 -0800991 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000992 }
993
tfarinaa41ab932015-10-30 16:08:48 -0700994#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000995 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
996#endif
997
998 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
999 SSL_CTX_set_verify_depth(ctx, 4);
1000 SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
1001
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +00001002 if (ssl_mode_ == SSL_MODE_DTLS) {
1003 SSL_CTX_set_read_ahead(ctx, 1);
1004 }
1005
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001006 return ctx;
1007}
1008
1009} // namespace rtc