blob: bc7b99b97a61449ab785eb24c8697e0dcfdf485b [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
157/////////////////////////////////////////////////////////////////////////////
158// OpenSSLAdapter
159/////////////////////////////////////////////////////////////////////////////
160
161namespace rtc {
162
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100163#ifndef OPENSSL_IS_BORINGSSL
164
165// This array will store all of the mutexes available to OpenSSL.
deadbeef37f5ecf2017-02-27 14:06:41 -0800166static MUTEX_TYPE* mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100167
168static void locking_function(int mode, int n, const char * file, int line) {
169 if (mode & CRYPTO_LOCK) {
170 MUTEX_LOCK(mutex_buf[n]);
171 } else {
172 MUTEX_UNLOCK(mutex_buf[n]);
173 }
174}
175
176static unsigned long id_function() { // NOLINT
177 // Use old-style C cast because THREAD_ID's type varies with the platform,
178 // in some cases requiring static_cast, and in others requiring
179 // reinterpret_cast.
180 return (unsigned long)THREAD_ID; // NOLINT
181}
182
183static CRYPTO_dynlock_value* dyn_create_function(const char* file, int line) {
184 CRYPTO_dynlock_value* value = new CRYPTO_dynlock_value;
185 if (!value)
deadbeef37f5ecf2017-02-27 14:06:41 -0800186 return nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100187 MUTEX_SETUP(value->mutex);
188 return value;
189}
190
191static void dyn_lock_function(int mode, CRYPTO_dynlock_value* l,
192 const char* file, int line) {
193 if (mode & CRYPTO_LOCK) {
194 MUTEX_LOCK(l->mutex);
195 } else {
196 MUTEX_UNLOCK(l->mutex);
197 }
198}
199
200static void dyn_destroy_function(CRYPTO_dynlock_value* l,
201 const char* file, int line) {
202 MUTEX_CLEANUP(l->mutex);
203 delete l;
204}
205
206#endif // #ifndef OPENSSL_IS_BORINGSSL
207
deadbeef37f5ecf2017-02-27 14:06:41 -0800208VerificationCallback OpenSSLAdapter::custom_verify_callback_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000209
210bool OpenSSLAdapter::InitializeSSL(VerificationCallback callback) {
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100211 if (!InitializeSSLThread() || !SSL_library_init())
212 return false;
213#if !defined(ADDRESS_SANITIZER) || !defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
214 // Loading the error strings crashes mac_asan. Omit this debugging aid there.
215 SSL_load_error_strings();
216#endif
217 ERR_load_BIO_strings();
218 OpenSSL_add_all_algorithms();
219 RAND_poll();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000220 custom_verify_callback_ = callback;
221 return true;
222}
223
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100224bool OpenSSLAdapter::InitializeSSLThread() {
225 // BoringSSL is doing the locking internally, so the callbacks are not used
226 // in this case (and are no-ops anyways).
227#ifndef OPENSSL_IS_BORINGSSL
228 mutex_buf = new MUTEX_TYPE[CRYPTO_num_locks()];
229 if (!mutex_buf)
230 return false;
231 for (int i = 0; i < CRYPTO_num_locks(); ++i)
232 MUTEX_SETUP(mutex_buf[i]);
233
234 // we need to cast our id_function to return an unsigned long -- pthread_t is
235 // a pointer
236 CRYPTO_set_id_callback(id_function);
237 CRYPTO_set_locking_callback(locking_function);
238 CRYPTO_set_dynlock_create_callback(dyn_create_function);
239 CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
240 CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
241#endif // #ifndef OPENSSL_IS_BORINGSSL
242 return true;
243}
244
245bool OpenSSLAdapter::CleanupSSL() {
246#ifndef OPENSSL_IS_BORINGSSL
247 if (!mutex_buf)
248 return false;
deadbeef37f5ecf2017-02-27 14:06:41 -0800249 CRYPTO_set_id_callback(nullptr);
250 CRYPTO_set_locking_callback(nullptr);
251 CRYPTO_set_dynlock_create_callback(nullptr);
252 CRYPTO_set_dynlock_lock_callback(nullptr);
253 CRYPTO_set_dynlock_destroy_callback(nullptr);
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100254 for (int i = 0; i < CRYPTO_num_locks(); ++i)
255 MUTEX_CLEANUP(mutex_buf[i]);
256 delete [] mutex_buf;
deadbeef37f5ecf2017-02-27 14:06:41 -0800257 mutex_buf = nullptr;
Torbjorn Granlund9adc91d2016-03-24 14:05:06 +0100258#endif // #ifndef OPENSSL_IS_BORINGSSL
259 return true;
260}
261
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262OpenSSLAdapter::OpenSSLAdapter(AsyncSocket* socket)
deadbeef37f5ecf2017-02-27 14:06:41 -0800263 : SSLAdapter(socket),
264 state_(SSL_NONE),
265 ssl_read_needs_write_(false),
266 ssl_write_needs_read_(false),
267 restartable_(false),
268 ssl_(nullptr),
269 ssl_ctx_(nullptr),
270 ssl_mode_(SSL_MODE_TLS),
271 custom_verification_succeeded_(false) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000272
273OpenSSLAdapter::~OpenSSLAdapter() {
274 Cleanup();
275}
276
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000277void
278OpenSSLAdapter::SetMode(SSLMode mode) {
nisseede5da42017-01-12 05:15:36 -0800279 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000280 ssl_mode_ = mode;
281}
282
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000283int
284OpenSSLAdapter::StartSSL(const char* hostname, bool restartable) {
285 if (state_ != SSL_NONE)
286 return -1;
287
288 ssl_host_name_ = hostname;
289 restartable_ = restartable;
290
291 if (socket_->GetState() != Socket::CS_CONNECTED) {
292 state_ = SSL_WAIT;
293 return 0;
294 }
295
296 state_ = SSL_CONNECTING;
297 if (int err = BeginSSL()) {
298 Error("BeginSSL", err, false);
299 return err;
300 }
301
302 return 0;
303}
304
305int
306OpenSSLAdapter::BeginSSL() {
307 LOG(LS_INFO) << "BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 05:15:36 -0800308 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000309
310 int err = 0;
deadbeef37f5ecf2017-02-27 14:06:41 -0800311 BIO* bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000312
313 // First set up the context
314 if (!ssl_ctx_)
315 ssl_ctx_ = SetupSSLContext();
316
317 if (!ssl_ctx_) {
318 err = -1;
319 goto ssl_error;
320 }
321
Peter Boström0b518bf2016-01-27 12:35:40 +0100322 bio = BIO_new_socket(socket_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000323 if (!bio) {
324 err = -1;
325 goto ssl_error;
326 }
327
328 ssl_ = SSL_new(ssl_ctx_);
329 if (!ssl_) {
330 err = -1;
331 goto ssl_error;
332 }
333
334 SSL_set_app_data(ssl_, this);
335
336 SSL_set_bio(ssl_, bio, bio);
337 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
338 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
339
340 // the SSL object owns the bio now
deadbeef37f5ecf2017-02-27 14:06:41 -0800341 bio = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000342
343 // Do the connect
344 err = ContinueSSL();
345 if (err != 0)
346 goto ssl_error;
347
348 return err;
349
350ssl_error:
351 Cleanup();
352 if (bio)
353 BIO_free(bio);
354
355 return err;
356}
357
358int
359OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 05:15:36 -0800360 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000361
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000362 // Clear the DTLS timer
363 Thread::Current()->Clear(this, MSG_TIMEOUT);
364
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000365 int code = SSL_connect(ssl_);
366 switch (SSL_get_error(ssl_, code)) {
367 case SSL_ERROR_NONE:
368 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_.c_str())) {
369 LOG(LS_ERROR) << "TLS post connection check failed";
370 // make sure we close the socket
371 Cleanup();
372 // The connect failed so return -1 to shut down the socket
373 return -1;
374 }
375
376 state_ = SSL_CONNECTED;
377 AsyncSocketAdapter::OnConnectEvent(this);
378#if 0 // TODO: worry about this
379 // Don't let ourselves go away during the callbacks
380 PRefPtr<OpenSSLAdapter> lock(this);
381 LOG(LS_INFO) << " -- onStreamReadable";
382 AsyncSocketAdapter::OnReadEvent(this);
383 LOG(LS_INFO) << " -- onStreamWriteable";
384 AsyncSocketAdapter::OnWriteEvent(this);
385#endif
386 break;
387
388 case SSL_ERROR_WANT_READ:
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000389 LOG(LS_VERBOSE) << " -- error want read";
390 struct timeval timeout;
391 if (DTLSv1_get_timeout(ssl_, &timeout)) {
392 int delay = timeout.tv_sec * 1000 + timeout.tv_usec/1000;
393
Taylor Brandstetter5d97a9a2016-06-10 14:17:27 -0700394 Thread::Current()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_TIMEOUT,
395 0);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000396 }
397 break;
398
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000399 case SSL_ERROR_WANT_WRITE:
400 break;
401
402 case SSL_ERROR_ZERO_RETURN:
403 default:
404 LOG(LS_WARNING) << "ContinueSSL -- error " << code;
405 return (code != 0) ? code : -1;
406 }
407
408 return 0;
409}
410
411void
412OpenSSLAdapter::Error(const char* context, int err, bool signal) {
413 LOG(LS_WARNING) << "OpenSSLAdapter::Error("
414 << context << ", " << err << ")";
415 state_ = SSL_ERROR;
416 SetError(err);
417 if (signal)
418 AsyncSocketAdapter::OnCloseEvent(this, err);
419}
420
421void
422OpenSSLAdapter::Cleanup() {
423 LOG(LS_INFO) << "Cleanup";
424
425 state_ = SSL_NONE;
426 ssl_read_needs_write_ = false;
427 ssl_write_needs_read_ = false;
428 custom_verification_succeeded_ = false;
429
430 if (ssl_) {
431 SSL_free(ssl_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800432 ssl_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000433 }
434
435 if (ssl_ctx_) {
436 SSL_CTX_free(ssl_ctx_);
deadbeef37f5ecf2017-02-27 14:06:41 -0800437 ssl_ctx_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000438 }
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000439
440 // Clear the DTLS timer
441 Thread::Current()->Clear(this, MSG_TIMEOUT);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000442}
443
444//
445// AsyncSocket Implementation
446//
447
448int
449OpenSSLAdapter::Send(const void* pv, size_t cb) {
450 //LOG(LS_INFO) << "OpenSSLAdapter::Send(" << cb << ")";
451
452 switch (state_) {
453 case SSL_NONE:
454 return AsyncSocketAdapter::Send(pv, cb);
455
456 case SSL_WAIT:
457 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700458 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000459 return SOCKET_ERROR;
460
461 case SSL_CONNECTED:
462 break;
463
464 case SSL_ERROR:
465 default:
466 return SOCKET_ERROR;
467 }
468
469 // OpenSSL will return an error if we try to write zero bytes
470 if (cb == 0)
471 return 0;
472
473 ssl_write_needs_read_ = false;
474
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000475 int code = SSL_write(ssl_, pv, checked_cast<int>(cb));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000476 switch (SSL_get_error(ssl_, code)) {
477 case SSL_ERROR_NONE:
478 //LOG(LS_INFO) << " -- success";
479 return code;
480 case SSL_ERROR_WANT_READ:
481 //LOG(LS_INFO) << " -- error want read";
482 ssl_write_needs_read_ = true;
483 SetError(EWOULDBLOCK);
484 break;
485 case SSL_ERROR_WANT_WRITE:
486 //LOG(LS_INFO) << " -- error want write";
487 SetError(EWOULDBLOCK);
488 break;
489 case SSL_ERROR_ZERO_RETURN:
490 //LOG(LS_INFO) << " -- remote side closed";
491 SetError(EWOULDBLOCK);
492 // do we need to signal closure?
493 break;
494 default:
495 //LOG(LS_INFO) << " -- error " << code;
496 Error("SSL_write", (code ? code : -1), false);
497 break;
498 }
499
500 return SOCKET_ERROR;
501}
502
503int
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000504OpenSSLAdapter::SendTo(const void* pv, size_t cb, const SocketAddress& addr) {
505 if (socket_->GetState() == Socket::CS_CONNECTED &&
506 addr == socket_->GetRemoteAddress()) {
507 return Send(pv, cb);
508 }
509
510 SetError(ENOTCONN);
511
512 return SOCKET_ERROR;
513}
514
Stefan Holmer9131efd2016-05-23 18:19:26 +0200515int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000516 //LOG(LS_INFO) << "OpenSSLAdapter::Recv(" << cb << ")";
517 switch (state_) {
518
519 case SSL_NONE:
Stefan Holmer9131efd2016-05-23 18:19:26 +0200520 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000521
522 case SSL_WAIT:
523 case SSL_CONNECTING:
skvladc309e0e2016-07-28 17:15:20 -0700524 SetError(ENOTCONN);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000525 return SOCKET_ERROR;
526
527 case SSL_CONNECTED:
528 break;
529
530 case SSL_ERROR:
531 default:
532 return SOCKET_ERROR;
533 }
534
535 // Don't trust OpenSSL with zero byte reads
536 if (cb == 0)
537 return 0;
538
539 ssl_read_needs_write_ = false;
540
henrike@webrtc.orgd89b69a2014-11-06 17:23:09 +0000541 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000542 switch (SSL_get_error(ssl_, code)) {
543 case SSL_ERROR_NONE:
544 //LOG(LS_INFO) << " -- success";
545 return code;
546 case SSL_ERROR_WANT_READ:
547 //LOG(LS_INFO) << " -- error want read";
548 SetError(EWOULDBLOCK);
549 break;
550 case SSL_ERROR_WANT_WRITE:
551 //LOG(LS_INFO) << " -- error want write";
552 ssl_read_needs_write_ = true;
553 SetError(EWOULDBLOCK);
554 break;
555 case SSL_ERROR_ZERO_RETURN:
556 //LOG(LS_INFO) << " -- remote side closed";
557 SetError(EWOULDBLOCK);
558 // do we need to signal closure?
559 break;
560 default:
561 //LOG(LS_INFO) << " -- error " << code;
562 Error("SSL_read", (code ? code : -1), false);
563 break;
564 }
565
566 return SOCKET_ERROR;
567}
568
Stefan Holmer9131efd2016-05-23 18:19:26 +0200569int OpenSSLAdapter::RecvFrom(void* pv,
570 size_t cb,
571 SocketAddress* paddr,
572 int64_t* timestamp) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000573 if (socket_->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 18:19:26 +0200574 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000575
576 *paddr = GetRemoteAddress();
577
578 return ret;
579 }
580
581 SetError(ENOTCONN);
582
583 return SOCKET_ERROR;
584}
585
586int
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000587OpenSSLAdapter::Close() {
588 Cleanup();
589 state_ = restartable_ ? SSL_WAIT : SSL_NONE;
590 return AsyncSocketAdapter::Close();
591}
592
593Socket::ConnState
594OpenSSLAdapter::GetState() const {
595 //if (signal_close_)
596 // return CS_CONNECTED;
597 ConnState state = socket_->GetState();
598 if ((state == CS_CONNECTED)
599 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING)))
600 state = CS_CONNECTING;
601 return state;
602}
603
604void
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000605OpenSSLAdapter::OnMessage(Message* msg) {
606 if (MSG_TIMEOUT == msg->message_id) {
607 LOG(LS_INFO) << "DTLS timeout expired";
608 DTLSv1_handle_timeout(ssl_);
609 ContinueSSL();
610 }
611}
612
613void
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000614OpenSSLAdapter::OnConnectEvent(AsyncSocket* socket) {
615 LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
616 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 05:15:36 -0800617 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000618 AsyncSocketAdapter::OnConnectEvent(socket);
619 return;
620 }
621
622 state_ = SSL_CONNECTING;
623 if (int err = BeginSSL()) {
624 AsyncSocketAdapter::OnCloseEvent(socket, err);
625 }
626}
627
628void
629OpenSSLAdapter::OnReadEvent(AsyncSocket* socket) {
630 //LOG(LS_INFO) << "OpenSSLAdapter::OnReadEvent";
631
632 if (state_ == SSL_NONE) {
633 AsyncSocketAdapter::OnReadEvent(socket);
634 return;
635 }
636
637 if (state_ == SSL_CONNECTING) {
638 if (int err = ContinueSSL()) {
639 Error("ContinueSSL", err);
640 }
641 return;
642 }
643
644 if (state_ != SSL_CONNECTED)
645 return;
646
647 // Don't let ourselves go away during the callbacks
648 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
649 if (ssl_write_needs_read_) {
650 //LOG(LS_INFO) << " -- onStreamWriteable";
651 AsyncSocketAdapter::OnWriteEvent(socket);
652 }
653
654 //LOG(LS_INFO) << " -- onStreamReadable";
655 AsyncSocketAdapter::OnReadEvent(socket);
656}
657
658void
659OpenSSLAdapter::OnWriteEvent(AsyncSocket* socket) {
660 //LOG(LS_INFO) << "OpenSSLAdapter::OnWriteEvent";
661
662 if (state_ == SSL_NONE) {
663 AsyncSocketAdapter::OnWriteEvent(socket);
664 return;
665 }
666
667 if (state_ == SSL_CONNECTING) {
668 if (int err = ContinueSSL()) {
669 Error("ContinueSSL", err);
670 }
671 return;
672 }
673
674 if (state_ != SSL_CONNECTED)
675 return;
676
677 // Don't let ourselves go away during the callbacks
678 //PRefPtr<OpenSSLAdapter> lock(this); // TODO: fix this
679
680 if (ssl_read_needs_write_) {
681 //LOG(LS_INFO) << " -- onStreamReadable";
682 AsyncSocketAdapter::OnReadEvent(socket);
683 }
684
685 //LOG(LS_INFO) << " -- onStreamWriteable";
686 AsyncSocketAdapter::OnWriteEvent(socket);
687}
688
689void
690OpenSSLAdapter::OnCloseEvent(AsyncSocket* socket, int err) {
691 LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
692 AsyncSocketAdapter::OnCloseEvent(socket, err);
693}
694
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000695bool OpenSSLAdapter::VerifyServerName(SSL* ssl, const char* host,
696 bool ignore_bad_cert) {
697 if (!host)
698 return false;
699
700 // Checking the return from SSL_get_peer_certificate here is not strictly
701 // necessary. With our setup, it is not possible for it to return
deadbeef37f5ecf2017-02-27 14:06:41 -0800702 // null. However, it is good form to check the return.
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000703 X509* certificate = SSL_get_peer_certificate(ssl);
704 if (!certificate)
705 return false;
706
707 // Logging certificates is extremely verbose. So it is disabled by default.
708#ifdef LOG_CERTIFICATES
709 {
710 LOG(LS_INFO) << "Certificate from server:";
711 BIO* mem = BIO_new(BIO_s_mem());
712 X509_print_ex(mem, certificate, XN_FLAG_SEP_CPLUS_SPC, X509_FLAG_NO_HEADER);
713 BIO_write(mem, "\0", 1);
714 char* buffer;
715 BIO_get_mem_data(mem, &buffer);
716 LOG(LS_INFO) << buffer;
717 BIO_free(mem);
718
719 char* cipher_description =
deadbeef37f5ecf2017-02-27 14:06:41 -0800720 SSL_CIPHER_description(SSL_get_current_cipher(ssl), nullptr, 128);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000721 LOG(LS_INFO) << "Cipher: " << cipher_description;
722 OPENSSL_free(cipher_description);
723 }
724#endif
725
726 bool ok = false;
davidben4ef903d2017-02-17 13:04:43 -0800727 GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(
728 X509_get_ext_d2i(certificate, NID_subject_alt_name, nullptr, nullptr));
729 if (names) {
730 for (size_t i = 0; i < sk_GENERAL_NAME_num(names); i++) {
731 const GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
732 if (name->type != GEN_DNS)
733 continue;
734 std::string value(
735 reinterpret_cast<const char*>(ASN1_STRING_data(name->d.dNSName)),
736 ASN1_STRING_length(name->d.dNSName));
737 // string_match takes NUL-terminated strings, so check for embedded NULs.
738 if (value.find('\0') != std::string::npos)
739 continue;
740 if (string_match(host, value.c_str())) {
741 ok = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000742 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000743 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000744 }
davidben4ef903d2017-02-17 13:04:43 -0800745 GENERAL_NAMES_free(names);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000746 }
747
748 char data[256];
henrike@webrtc.orgd5a05062014-06-30 20:38:56 +0000749 X509_NAME* subject;
deadbeef37f5ecf2017-02-27 14:06:41 -0800750 if (!ok && ((subject = X509_get_subject_name(certificate)) != nullptr) &&
751 (X509_NAME_get_text_by_NID(subject, NID_commonName, data, sizeof(data)) >
752 0)) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000753 data[sizeof(data)-1] = 0;
754 if (_stricmp(data, host) == 0)
755 ok = true;
756 }
757
758 X509_free(certificate);
759
760 // This should only ever be turned on for debugging and development.
761 if (!ok && ignore_bad_cert) {
762 LOG(LS_WARNING) << "TLS certificate check FAILED. "
763 << "Allowing connection anyway.";
764 ok = true;
765 }
766
767 return ok;
768}
769
770bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, const char* host) {
771 bool ok = VerifyServerName(ssl, host, ignore_bad_cert());
772
773 if (ok) {
774 ok = (SSL_get_verify_result(ssl) == X509_V_OK ||
775 custom_verification_succeeded_);
776 }
777
778 if (!ok && ignore_bad_cert()) {
779 LOG(LS_INFO) << "Other TLS post connection checks failed.";
780 ok = true;
781 }
782
783 return ok;
784}
785
tfarinaa41ab932015-10-30 16:08:48 -0700786#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000787
788// We only use this for tracing and so it is only needed in debug mode
789
790void
791OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) {
792 const char* str = "undefined";
793 int w = where & ~SSL_ST_MASK;
794 if (w & SSL_ST_CONNECT) {
795 str = "SSL_connect";
796 } else if (w & SSL_ST_ACCEPT) {
797 str = "SSL_accept";
798 }
799 if (where & SSL_CB_LOOP) {
800 LOG(LS_INFO) << str << ":" << SSL_state_string_long(s);
801 } else if (where & SSL_CB_ALERT) {
802 str = (where & SSL_CB_READ) ? "read" : "write";
803 LOG(LS_INFO) << "SSL3 alert " << str
804 << ":" << SSL_alert_type_string_long(ret)
805 << ":" << SSL_alert_desc_string_long(ret);
806 } else if (where & SSL_CB_EXIT) {
807 if (ret == 0) {
808 LOG(LS_INFO) << str << ":failed in " << SSL_state_string_long(s);
809 } else if (ret < 0) {
810 LOG(LS_INFO) << str << ":error in " << SSL_state_string_long(s);
811 }
812 }
813}
814
tfarinaa41ab932015-10-30 16:08:48 -0700815#endif
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000816
817int
818OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 16:08:48 -0700819#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000820 if (!ok) {
821 char data[256];
822 X509* cert = X509_STORE_CTX_get_current_cert(store);
823 int depth = X509_STORE_CTX_get_error_depth(store);
824 int err = X509_STORE_CTX_get_error(store);
825
826 LOG(LS_INFO) << "Error with certificate at depth: " << depth;
827 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
828 LOG(LS_INFO) << " issuer = " << data;
829 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
830 LOG(LS_INFO) << " subject = " << data;
831 LOG(LS_INFO) << " err = " << err
832 << ":" << X509_verify_cert_error_string(err);
833 }
834#endif
835
836 // Get our stream pointer from the store
837 SSL* ssl = reinterpret_cast<SSL*>(
838 X509_STORE_CTX_get_ex_data(store,
839 SSL_get_ex_data_X509_STORE_CTX_idx()));
840
841 OpenSSLAdapter* stream =
842 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
843
844 if (!ok && custom_verify_callback_) {
845 void* cert =
846 reinterpret_cast<void*>(X509_STORE_CTX_get_current_cert(store));
847 if (custom_verify_callback_(cert)) {
848 stream->custom_verification_succeeded_ = true;
849 LOG(LS_INFO) << "validated certificate using custom callback";
850 ok = true;
851 }
852 }
853
854 // Should only be used for debugging and development.
855 if (!ok && stream->ignore_bad_cert()) {
856 LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
857 ok = 1;
858 }
859
860 return ok;
861}
862
863bool OpenSSLAdapter::ConfigureTrustedRootCertificates(SSL_CTX* ctx) {
864 // Add the root cert that we care about to the SSL context
865 int count_of_added_certs = 0;
tfarina5237aaf2015-11-10 23:44:30 -0800866 for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000867 const unsigned char* cert_buffer = kSSLCertCertificateList[i];
868 size_t cert_buffer_len = kSSLCertCertificateSizeList[i];
deadbeef37f5ecf2017-02-27 14:06:41 -0800869 X509* cert =
870 d2i_X509(nullptr, &cert_buffer, checked_cast<long>(cert_buffer_len));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000871 if (cert) {
872 int return_value = X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx), cert);
873 if (return_value == 0) {
874 LOG(LS_WARNING) << "Unable to add certificate.";
875 } else {
876 count_of_added_certs++;
877 }
878 X509_free(cert);
879 }
880 }
881 return count_of_added_certs > 0;
882}
883
884SSL_CTX*
885OpenSSLAdapter::SetupSSLContext() {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000886 SSL_CTX* ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ?
887 DTLSv1_client_method() : TLSv1_client_method());
deadbeef37f5ecf2017-02-27 14:06:41 -0800888 if (ctx == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000889 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
890 LOG(LS_WARNING) << "SSL_CTX creation failed: "
891 << '"' << ERR_reason_error_string(error) << "\" "
892 << "(error=" << error << ')';
deadbeef37f5ecf2017-02-27 14:06:41 -0800893 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000894 }
895 if (!ConfigureTrustedRootCertificates(ctx)) {
896 SSL_CTX_free(ctx);
deadbeef37f5ecf2017-02-27 14:06:41 -0800897 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000898 }
899
tfarinaa41ab932015-10-30 16:08:48 -0700900#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000901 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
902#endif
903
904 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
905 SSL_CTX_set_verify_depth(ctx, 4);
906 SSL_CTX_set_cipher_list(ctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
907
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000908 if (ssl_mode_ == SSL_MODE_DTLS) {
909 SSL_CTX_set_read_ahead(ctx, 1);
910 }
911
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000912 return ctx;
913}
914
915} // namespace rtc