blob: 27438590069e4b4075500ab3faa606dfea902245 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:261/*
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
Steve Anton10542f22019-01-11 17:11:0011#include "rtc_base/openssl_adapter.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2612
Yves Gerey988cc082018-10-23 10:03:0113#include <errno.h>
henrike@webrtc.orgf0488722014-05-13 18:00:2614#include <openssl/bio.h>
henrike@webrtc.orgf0488722014-05-13 18:00:2615#include <openssl/err.h>
Ali Tofigh7fa90572022-03-17 14:47:4916
17#include "absl/strings/string_view.h"
Taylor Brandstetter165c6182020-12-11 00:23:0318#ifdef OPENSSL_IS_BORINGSSL
19#include <openssl/pool.h>
20#endif
henrike@webrtc.orgf0488722014-05-13 18:00:2621#include <openssl/rand.h>
henrike@webrtc.orgd5a05062014-06-30 20:38:5622#include <openssl/x509.h>
Yves Gerey988cc082018-10-23 10:03:0123#include <string.h>
24#include <time.h>
25
Mirko Bonadei317a1f02019-09-17 15:06:1826#include <memory>
27
Taylor Brandstetter165c6182020-12-11 00:23:0328// Use CRYPTO_BUFFER APIs if available and we have no dependency on X509
29// objects.
30#if defined(OPENSSL_IS_BORINGSSL) && \
31 defined(WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS)
32#define WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
33#endif
34
Harald Alvestrand8515d5a2020-03-20 21:51:3235#include "absl/memory/memory.h"
Danil Chapovalove7280c32022-08-18 10:01:3036#include "api/units/time_delta.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3137#include "rtc_base/checks.h"
38#include "rtc_base/logging.h"
Karl Wiberge40468b2017-11-22 09:42:2639#include "rtc_base/numerics/safe_conversions.h"
Jonas Olssona4d87372019-07-05 17:08:3340#include "rtc_base/openssl.h"
Taylor Brandstetter165c6182020-12-11 00:23:0341#ifdef OPENSSL_IS_BORINGSSL
42#include "rtc_base/boringssl_identity.h"
43#else
44#include "rtc_base/openssl_identity.h"
45#endif
Steve Anton10542f22019-01-11 17:11:0046#include "rtc_base/openssl_utility.h"
Sergey Silkinebc4d3e2023-11-15 10:04:4847#include "rtc_base/strings/str_join.h"
Niels Möller9aa46c62022-05-11 13:02:5548#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3149#include "rtc_base/thread.h"
henrike@webrtc.orgf0488722014-05-13 18:00:2650
henrike@webrtc.orgf0488722014-05-13 18:00:2651//////////////////////////////////////////////////////////////////////
52// SocketBIO
53//////////////////////////////////////////////////////////////////////
54
55static int socket_write(BIO* h, const char* buf, int num);
56static int socket_read(BIO* h, char* buf, int size);
57static int socket_puts(BIO* h, const char* str);
Benjamin Wrightd6f86e82018-05-08 20:12:2558static long socket_ctrl(BIO* h, int cmd, long arg1, void* arg2); // NOLINT
henrike@webrtc.orgf0488722014-05-13 18:00:2659static int socket_new(BIO* h);
60static int socket_free(BIO* data);
61
Jiawei Oueb0df082018-02-02 22:51:1862static BIO_METHOD* BIO_socket_method() {
63 static BIO_METHOD* methods = [] {
64 BIO_METHOD* methods = BIO_meth_new(BIO_TYPE_BIO, "socket");
65 BIO_meth_set_write(methods, socket_write);
66 BIO_meth_set_read(methods, socket_read);
67 BIO_meth_set_puts(methods, socket_puts);
68 BIO_meth_set_ctrl(methods, socket_ctrl);
69 BIO_meth_set_create(methods, socket_new);
70 BIO_meth_set_destroy(methods, socket_free);
71 return methods;
72 }();
73 return methods;
74}
henrike@webrtc.orgf0488722014-05-13 18:00:2675
Niels Möllerd0b88792021-08-12 08:32:3076static BIO* BIO_new_socket(rtc::Socket* socket) {
Jiawei Oueb0df082018-02-02 22:51:1877 BIO* ret = BIO_new(BIO_socket_method());
deadbeef37f5ecf2017-02-27 22:06:4178 if (ret == nullptr) {
79 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:2680 }
Jiawei Oueb0df082018-02-02 22:51:1881 BIO_set_data(ret, socket);
henrike@webrtc.orgf0488722014-05-13 18:00:2682 return ret;
83}
84
85static int socket_new(BIO* b) {
Jiawei Oueb0df082018-02-02 22:51:1886 BIO_set_shutdown(b, 0);
87 BIO_set_init(b, 1);
88 BIO_set_data(b, 0);
henrike@webrtc.orgf0488722014-05-13 18:00:2689 return 1;
90}
91
92static int socket_free(BIO* b) {
deadbeef37f5ecf2017-02-27 22:06:4193 if (b == nullptr)
henrike@webrtc.orgf0488722014-05-13 18:00:2694 return 0;
95 return 1;
96}
97
98static int socket_read(BIO* b, char* out, int outl) {
99 if (!out)
100 return -1;
Niels Möllerd0b88792021-08-12 08:32:30101 rtc::Socket* socket = static_cast<rtc::Socket*>(BIO_get_data(b));
henrike@webrtc.orgf0488722014-05-13 18:00:26102 BIO_clear_retry_flags(b);
Stefan Holmer9131efd2016-05-23 16:19:26103 int result = socket->Recv(out, outl, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26104 if (result > 0) {
105 return result;
henrike@webrtc.orgf0488722014-05-13 18:00:26106 } else if (socket->IsBlocking()) {
107 BIO_set_retry_read(b);
108 }
109 return -1;
110}
111
112static int socket_write(BIO* b, const char* in, int inl) {
113 if (!in)
114 return -1;
Niels Möllerd0b88792021-08-12 08:32:30115 rtc::Socket* socket = static_cast<rtc::Socket*>(BIO_get_data(b));
henrike@webrtc.orgf0488722014-05-13 18:00:26116 BIO_clear_retry_flags(b);
117 int result = socket->Send(in, inl);
118 if (result > 0) {
119 return result;
120 } else if (socket->IsBlocking()) {
121 BIO_set_retry_write(b);
122 }
123 return -1;
124}
125
126static int socket_puts(BIO* b, const char* str) {
henrike@webrtc.orgd89b69a2014-11-06 17:23:09127 return socket_write(b, str, rtc::checked_cast<int>(strlen(str)));
henrike@webrtc.orgf0488722014-05-13 18:00:26128}
129
Benjamin Wrightd6f86e82018-05-08 20:12:25130static long socket_ctrl(BIO* b, int cmd, long num, void* ptr) { // NOLINT
henrike@webrtc.orgf0488722014-05-13 18:00:26131 switch (cmd) {
Yves Gerey665174f2018-06-19 13:03:05132 case BIO_CTRL_RESET:
133 return 0;
134 case BIO_CTRL_EOF: {
Niels Möllerd0b88792021-08-12 08:32:30135 rtc::Socket* socket = static_cast<rtc::Socket*>(ptr);
Yves Gerey665174f2018-06-19 13:03:05136 // 1 means socket closed.
Niels Möllerd0b88792021-08-12 08:32:30137 return (socket->GetState() == rtc::Socket::CS_CLOSED) ? 1 : 0;
Yves Gerey665174f2018-06-19 13:03:05138 }
139 case BIO_CTRL_WPENDING:
140 case BIO_CTRL_PENDING:
141 return 0;
142 case BIO_CTRL_FLUSH:
143 return 1;
144 default:
145 return 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26146 }
147}
148
deadbeefed3b9862017-06-02 17:33:16149static void LogSslError() {
150 // Walk down the error stack to find the SSL error.
151 uint32_t error_code;
152 const char* file;
153 int line;
154 do {
155 error_code = ERR_get_error_line(&file, &line);
156 if (ERR_GET_LIB(error_code) == ERR_LIB_SSL) {
Mirko Bonadei675513b2017-11-09 10:09:25157 RTC_LOG(LS_ERROR) << "ERR_LIB_SSL: " << error_code << ", " << file << ":"
158 << line;
deadbeefed3b9862017-06-02 17:33:16159 break;
160 }
161 } while (error_code != 0);
162}
163
henrike@webrtc.orgf0488722014-05-13 18:00:26164/////////////////////////////////////////////////////////////////////////////
165// OpenSSLAdapter
166/////////////////////////////////////////////////////////////////////////////
167
168namespace rtc {
169
Danil Chapovalove7280c32022-08-18 10:01:30170using ::webrtc::TimeDelta;
171
Benjamin Wrightd6f86e82018-05-08 20:12:25172bool OpenSSLAdapter::InitializeSSL() {
Philipp Hancke2cb3c542024-05-08 18:52:05173 // TODO: https://issues.webrtc.org/issues/339300437 - remove once
174 // BoringSSL no longer requires this after
175 // https://bugs.chromium.org/p/boringssl/issues/detail?id=35
176 // In OpenSSL it is supposed to be a no-op as of 1.1:
177 // https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_init_ssl.html
178 return OPENSSL_init_ssl(0, nullptr);
henrike@webrtc.orgf0488722014-05-13 18:00:26179}
180
Torbjorn Granlund9adc91d2016-03-24 13:05:06181bool OpenSSLAdapter::CleanupSSL() {
Torbjorn Granlund9adc91d2016-03-24 13:05:06182 return true;
183}
184
Niels Möllerd0b88792021-08-12 08:32:30185OpenSSLAdapter::OpenSSLAdapter(Socket* socket,
Benjamin Wrightd6f86e82018-05-08 20:12:25186 OpenSSLSessionCache* ssl_session_cache,
187 SSLCertificateVerifier* ssl_cert_verifier)
deadbeef37f5ecf2017-02-27 22:06:41188 : SSLAdapter(socket),
Benjamin Wright19aab2e2018-04-05 22:39:06189 ssl_session_cache_(ssl_session_cache),
Benjamin Wrightd6f86e82018-05-08 20:12:25190 ssl_cert_verifier_(ssl_cert_verifier),
deadbeef37f5ecf2017-02-27 22:06:41191 state_(SSL_NONE),
Steve Anton786de702017-08-17 22:15:46192 role_(SSL_CLIENT),
deadbeef37f5ecf2017-02-27 22:06:41193 ssl_read_needs_write_(false),
194 ssl_write_needs_read_(false),
deadbeef37f5ecf2017-02-27 22:06:41195 ssl_(nullptr),
196 ssl_ctx_(nullptr),
197 ssl_mode_(SSL_MODE_TLS),
Sergey Silkin9c147dd2018-09-12 10:45:38198 ignore_bad_cert_(false),
Benjamin Wrightd6f86e82018-05-08 20:12:25199 custom_cert_verifier_status_(false) {
Justin Uberti1d445502017-08-15 00:04:34200 // If a factory is used, take a reference on the factory's SSL_CTX.
201 // Otherwise, we'll create our own later.
202 // Either way, we'll release our reference via SSL_CTX_free() in Cleanup().
Benjamin Wright19aab2e2018-04-05 22:39:06203 if (ssl_session_cache_ != nullptr) {
204 ssl_ctx_ = ssl_session_cache_->GetSSLContext();
Justin Uberti1d445502017-08-15 00:04:34205 RTC_DCHECK(ssl_ctx_);
206 // Note: if using OpenSSL, requires version 1.1.0 or later.
207 SSL_CTX_up_ref(ssl_ctx_);
208 }
209}
henrike@webrtc.orgf0488722014-05-13 18:00:26210
211OpenSSLAdapter::~OpenSSLAdapter() {
212 Cleanup();
213}
214
Sergey Silkin9c147dd2018-09-12 10:45:38215void OpenSSLAdapter::SetIgnoreBadCert(bool ignore) {
216 ignore_bad_cert_ = ignore;
217}
218
219void OpenSSLAdapter::SetAlpnProtocols(const std::vector<std::string>& protos) {
220 alpn_protocols_ = protos;
221}
222
223void OpenSSLAdapter::SetEllipticCurves(const std::vector<std::string>& curves) {
224 elliptic_curves_ = curves;
Diogo Real7bd1f1b2017-09-08 19:50:41225}
226
Justin Uberti1d445502017-08-15 00:04:34227void OpenSSLAdapter::SetMode(SSLMode mode) {
228 RTC_DCHECK(!ssl_ctx_);
nisseede5da42017-01-12 13:15:36229 RTC_DCHECK(state_ == SSL_NONE);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14230 ssl_mode_ = mode;
231}
232
Benjamin Wrightd6f86e82018-05-08 20:12:25233void OpenSSLAdapter::SetCertVerifier(
234 SSLCertificateVerifier* ssl_cert_verifier) {
235 RTC_DCHECK(!ssl_ctx_);
236 ssl_cert_verifier_ = ssl_cert_verifier;
237}
238
Harald Alvestrand8515d5a2020-03-20 21:51:32239void OpenSSLAdapter::SetIdentity(std::unique_ptr<SSLIdentity> identity) {
240 RTC_DCHECK(!identity_);
Taylor Brandstetter165c6182020-12-11 00:23:03241#ifdef OPENSSL_IS_BORINGSSL
242 identity_ =
243 absl::WrapUnique(static_cast<BoringSSLIdentity*>(identity.release()));
244#else
Harald Alvestrand8515d5a2020-03-20 21:51:32245 identity_ =
246 absl::WrapUnique(static_cast<OpenSSLIdentity*>(identity.release()));
Taylor Brandstetter165c6182020-12-11 00:23:03247#endif
Harald Alvestrand8515d5a2020-03-20 21:51:32248}
249
Steve Anton786de702017-08-17 22:15:46250void OpenSSLAdapter::SetRole(SSLRole role) {
251 role_ = role;
252}
253
Ali Tofigh2ab914c2022-04-13 10:55:15254int OpenSSLAdapter::StartSSL(absl::string_view hostname) {
henrike@webrtc.orgf0488722014-05-13 18:00:26255 if (state_ != SSL_NONE)
256 return -1;
257
Ali Tofigh2ab914c2022-04-13 10:55:15258 ssl_host_name_.assign(hostname.data(), hostname.size());
henrike@webrtc.orgf0488722014-05-13 18:00:26259
Niels Möller8729d782021-08-11 09:22:44260 if (GetSocket()->GetState() != Socket::CS_CONNECTED) {
henrike@webrtc.orgf0488722014-05-13 18:00:26261 state_ = SSL_WAIT;
262 return 0;
263 }
264
265 state_ = SSL_CONNECTING;
266 if (int err = BeginSSL()) {
267 Error("BeginSSL", err, false);
268 return err;
269 }
270
271 return 0;
272}
273
Justin Uberti1d445502017-08-15 00:04:34274int OpenSSLAdapter::BeginSSL() {
Mirko Bonadei675513b2017-11-09 10:09:25275 RTC_LOG(LS_INFO) << "OpenSSLAdapter::BeginSSL: " << ssl_host_name_;
nisseede5da42017-01-12 13:15:36276 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26277
Vojin Ilicf11f0e02021-06-30 12:22:11278 // Cleanup action to deal with on error cleanup a bit cleaner.
279 EarlyExitCatcher early_exit_catcher(*this);
henrike@webrtc.orgf0488722014-05-13 18:00:26280
Justin Uberti1d445502017-08-15 00:04:34281 // First set up the context. We should either have a factory, with its own
282 // pre-existing context, or be running standalone, in which case we will
Artem Titov96e3b992021-07-26 14:03:14283 // need to create one, and specify `false` to disable session caching.
Benjamin Wright19aab2e2018-04-05 22:39:06284 if (ssl_session_cache_ == nullptr) {
Justin Uberti1d445502017-08-15 00:04:34285 RTC_DCHECK(!ssl_ctx_);
286 ssl_ctx_ = CreateContext(ssl_mode_, false);
287 }
Benjamin Wrightd6f86e82018-05-08 20:12:25288
henrike@webrtc.orgf0488722014-05-13 18:00:26289 if (!ssl_ctx_) {
Vojin Ilicf11f0e02021-06-30 12:22:11290 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26291 }
292
Steve Anton786de702017-08-17 22:15:46293 if (identity_ && !identity_->ConfigureIdentity(ssl_ctx_)) {
Vojin Ilicf11f0e02021-06-30 12:22:11294 return -1;
Steve Anton786de702017-08-17 22:15:46295 }
296
Niels Möller8729d782021-08-11 09:22:44297 std::unique_ptr<BIO, decltype(&::BIO_free)> bio{BIO_new_socket(GetSocket()),
Vojin Ilicf11f0e02021-06-30 12:22:11298 ::BIO_free};
henrike@webrtc.orgf0488722014-05-13 18:00:26299 if (!bio) {
Vojin Ilicf11f0e02021-06-30 12:22:11300 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26301 }
302
303 ssl_ = SSL_new(ssl_ctx_);
304 if (!ssl_) {
Vojin Ilicf11f0e02021-06-30 12:22:11305 return -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26306 }
307
308 SSL_set_app_data(ssl_, this);
309
deadbeefed3b9862017-06-02 17:33:16310 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER allows different buffers to be passed
311 // into SSL_write when a record could only be partially transmitted (and thus
312 // requires another call to SSL_write to finish transmission). This allows us
313 // to copy the data into our own buffer when this occurs, since the original
314 // buffer can't safely be accessed after control exits Send.
315 // TODO(deadbeef): Do we want SSL_MODE_ENABLE_PARTIAL_WRITE? It doesn't
316 // appear Send handles partial writes properly, though maybe we never notice
317 // since we never send more than 16KB at once..
henrike@webrtc.orgf0488722014-05-13 18:00:26318 SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
Yves Gerey665174f2018-06-19 13:03:05319 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
henrike@webrtc.orgf0488722014-05-13 18:00:26320
Justin Uberti1d445502017-08-15 00:04:34321 // Enable SNI, if a hostname is supplied.
Emad Omaradab1d2d2017-06-16 22:43:11322 if (!ssl_host_name_.empty()) {
323 SSL_set_tlsext_host_name(ssl_, ssl_host_name_.c_str());
Justin Uberti1d445502017-08-15 00:04:34324
325 // Enable session caching, if configured and a hostname is supplied.
Benjamin Wright19aab2e2018-04-05 22:39:06326 if (ssl_session_cache_ != nullptr) {
327 SSL_SESSION* cached = ssl_session_cache_->LookupSession(ssl_host_name_);
Justin Uberti1d445502017-08-15 00:04:34328 if (cached) {
329 if (SSL_set_session(ssl_, cached) == 0) {
Mirko Bonadei675513b2017-11-09 10:09:25330 RTC_LOG(LS_WARNING) << "Failed to apply SSL session from cache";
Vojin Ilicf11f0e02021-06-30 12:22:11331 return -1;
Justin Uberti1d445502017-08-15 00:04:34332 }
333
Mirko Bonadei675513b2017-11-09 10:09:25334 RTC_LOG(LS_INFO) << "Attempting to resume SSL session to "
335 << ssl_host_name_;
Justin Uberti1d445502017-08-15 00:04:34336 }
337 }
Emad Omaradab1d2d2017-06-16 22:43:11338 }
339
Jiawei Oueb0df082018-02-02 22:51:18340#ifdef OPENSSL_IS_BORINGSSL
Sergey Silkin9c147dd2018-09-12 10:45:38341 // Set a couple common TLS extensions; even though we don't use them yet.
342 SSL_enable_ocsp_stapling(ssl_);
343 SSL_enable_signed_cert_timestamps(ssl_);
Jiawei Oueb0df082018-02-02 22:51:18344#endif
Emad Omaracb79d232017-07-20 23:34:34345
Sergey Silkin9c147dd2018-09-12 10:45:38346 if (!alpn_protocols_.empty()) {
347 std::string tls_alpn_string = TransformAlpnProtocols(alpn_protocols_);
Diogo Real1dca9d52017-08-29 19:18:32348 if (!tls_alpn_string.empty()) {
349 SSL_set_alpn_protos(
350 ssl_, reinterpret_cast<const unsigned char*>(tls_alpn_string.data()),
Mirko Bonadeia041f922018-05-23 08:22:36351 rtc::dchecked_cast<unsigned>(tls_alpn_string.size()));
Diogo Real1dca9d52017-08-29 19:18:32352 }
353 }
354
Sergey Silkin9c147dd2018-09-12 10:45:38355 if (!elliptic_curves_.empty()) {
Sergey Silkinebc4d3e2023-11-15 10:04:48356 SSL_set1_curves_list(ssl_, webrtc::StrJoin(elliptic_curves_, ":").c_str());
Diogo Real7bd1f1b2017-09-08 19:50:41357 }
358
Artem Titov96e3b992021-07-26 14:03:14359 // Now that the initial config is done, transfer ownership of `bio` to the
Justin Uberti1d445502017-08-15 00:04:34360 // SSL object. If ContinueSSL() fails, the bio will be freed in Cleanup().
Vojin Ilicf11f0e02021-06-30 12:22:11361 SSL_set_bio(ssl_, bio.get(), bio.get());
362 bio.release();
henrike@webrtc.orgf0488722014-05-13 18:00:26363
Justin Uberti1d445502017-08-15 00:04:34364 // Do the connect.
Vojin Ilicf11f0e02021-06-30 12:22:11365 int err = ContinueSSL();
Benjamin Wright243cabe2018-10-16 08:55:28366 if (err != 0) {
Vojin Ilicf11f0e02021-06-30 12:22:11367 return err;
Benjamin Wright243cabe2018-10-16 08:55:28368 }
Vojin Ilicf11f0e02021-06-30 12:22:11369 early_exit_catcher.disable();
370 return 0;
henrike@webrtc.orgf0488722014-05-13 18:00:26371}
372
Justin Uberti1d445502017-08-15 00:04:34373int OpenSSLAdapter::ContinueSSL() {
nisseede5da42017-01-12 13:15:36374 RTC_DCHECK(state_ == SSL_CONNECTING);
henrike@webrtc.orgf0488722014-05-13 18:00:26375
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14376 // Clear the DTLS timer
Danil Chapovalove7280c32022-08-18 10:01:30377 timer_.reset();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14378
Steve Anton786de702017-08-17 22:15:46379 int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
henrike@webrtc.orgf0488722014-05-13 18:00:26380 switch (SSL_get_error(ssl_, code)) {
Yves Gerey665174f2018-06-19 13:03:05381 case SSL_ERROR_NONE:
382 if (!SSLPostConnectionCheck(ssl_, ssl_host_name_)) {
383 RTC_LOG(LS_ERROR) << "TLS post connection check failed";
384 // make sure we close the socket
385 Cleanup();
386 // The connect failed so return -1 to shut down the socket
387 return -1;
388 }
henrike@webrtc.orgf0488722014-05-13 18:00:26389
Yves Gerey665174f2018-06-19 13:03:05390 state_ = SSL_CONNECTED;
391 AsyncSocketAdapter::OnConnectEvent(this);
Benjamin Wright243cabe2018-10-16 08:55:28392 // TODO(benwright): Refactor this code path.
393 // Don't let ourselves go away during the callbacks
394 // PRefPtr<OpenSSLAdapter> lock(this);
395 // RTC_LOG(LS_INFO) << " -- onStreamReadable";
396 // AsyncSocketAdapter::OnReadEvent(this);
397 // RTC_LOG(LS_INFO) << " -- onStreamWriteable";
398 // AsyncSocketAdapter::OnWriteEvent(this);
Yves Gerey665174f2018-06-19 13:03:05399 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26400
Yves Gerey665174f2018-06-19 13:03:05401 case SSL_ERROR_WANT_READ:
402 RTC_LOG(LS_VERBOSE) << " -- error want read";
403 struct timeval timeout;
404 if (DTLSv1_get_timeout(ssl_, &timeout)) {
Danil Chapovalove7280c32022-08-18 10:01:30405 TimeDelta delay = TimeDelta::Seconds(timeout.tv_sec) +
406 TimeDelta::Micros(timeout.tv_usec);
407 Thread::Current()->PostDelayedTask(
408 SafeTask(timer_.flag(), [this] { OnTimeout(); }), delay);
Yves Gerey665174f2018-06-19 13:03:05409 }
410 break;
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14411
Yves Gerey665174f2018-06-19 13:03:05412 case SSL_ERROR_WANT_WRITE:
413 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26414
Yves Gerey665174f2018-06-19 13:03:05415 case SSL_ERROR_ZERO_RETURN:
416 default:
417 RTC_LOG(LS_WARNING) << "ContinueSSL -- error " << code;
418 return (code != 0) ? code : -1;
henrike@webrtc.orgf0488722014-05-13 18:00:26419 }
420
421 return 0;
422}
423
Ali Tofigh2ab914c2022-04-13 10:55:15424void OpenSSLAdapter::Error(absl::string_view context, int err, bool signal) {
Mirko Bonadei675513b2017-11-09 10:09:25425 RTC_LOG(LS_WARNING) << "OpenSSLAdapter::Error(" << context << ", " << err
426 << ")";
henrike@webrtc.orgf0488722014-05-13 18:00:26427 state_ = SSL_ERROR;
428 SetError(err);
Benjamin Wright243cabe2018-10-16 08:55:28429 if (signal) {
henrike@webrtc.orgf0488722014-05-13 18:00:26430 AsyncSocketAdapter::OnCloseEvent(this, err);
Benjamin Wright243cabe2018-10-16 08:55:28431 }
henrike@webrtc.orgf0488722014-05-13 18:00:26432}
433
Justin Uberti1d445502017-08-15 00:04:34434void OpenSSLAdapter::Cleanup() {
Mirko Bonadei675513b2017-11-09 10:09:25435 RTC_LOG(LS_INFO) << "OpenSSLAdapter::Cleanup";
henrike@webrtc.orgf0488722014-05-13 18:00:26436
437 state_ = SSL_NONE;
438 ssl_read_needs_write_ = false;
439 ssl_write_needs_read_ = false;
Benjamin Wrightd6f86e82018-05-08 20:12:25440 custom_cert_verifier_status_ = false;
deadbeefed3b9862017-06-02 17:33:16441 pending_data_.Clear();
henrike@webrtc.orgf0488722014-05-13 18:00:26442
443 if (ssl_) {
444 SSL_free(ssl_);
deadbeef37f5ecf2017-02-27 22:06:41445 ssl_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26446 }
447
448 if (ssl_ctx_) {
449 SSL_CTX_free(ssl_ctx_);
deadbeef37f5ecf2017-02-27 22:06:41450 ssl_ctx_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26451 }
Steve Anton786de702017-08-17 22:15:46452 identity_.reset();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14453
454 // Clear the DTLS timer
Danil Chapovalove7280c32022-08-18 10:01:30455 timer_.reset();
henrike@webrtc.orgf0488722014-05-13 18:00:26456}
457
deadbeefed3b9862017-06-02 17:33:16458int OpenSSLAdapter::DoSslWrite(const void* pv, size_t cb, int* error) {
459 // If we have pending data (that was previously only partially written by
460 // SSL_write), we shouldn't be attempting to write anything else.
461 RTC_DCHECK(pending_data_.empty() || pv == pending_data_.data());
462 RTC_DCHECK(error != nullptr);
463
464 ssl_write_needs_read_ = false;
465 int ret = SSL_write(ssl_, pv, checked_cast<int>(cb));
466 *error = SSL_get_error(ssl_, ret);
467 switch (*error) {
468 case SSL_ERROR_NONE:
469 // Success!
470 return ret;
471 case SSL_ERROR_WANT_READ:
Mirko Bonadei675513b2017-11-09 10:09:25472 RTC_LOG(LS_INFO) << " -- error want read";
deadbeefed3b9862017-06-02 17:33:16473 ssl_write_needs_read_ = true;
474 SetError(EWOULDBLOCK);
475 break;
476 case SSL_ERROR_WANT_WRITE:
Mirko Bonadei675513b2017-11-09 10:09:25477 RTC_LOG(LS_INFO) << " -- error want write";
deadbeefed3b9862017-06-02 17:33:16478 SetError(EWOULDBLOCK);
479 break;
480 case SSL_ERROR_ZERO_RETURN:
deadbeefed3b9862017-06-02 17:33:16481 SetError(EWOULDBLOCK);
482 // do we need to signal closure?
483 break;
484 case SSL_ERROR_SSL:
485 LogSslError();
486 Error("SSL_write", ret ? ret : -1, false);
487 break;
488 default:
deadbeefed3b9862017-06-02 17:33:16489 Error("SSL_write", ret ? ret : -1, false);
490 break;
491 }
492
493 return SOCKET_ERROR;
494}
495
Benjamin Wright243cabe2018-10-16 08:55:28496///////////////////////////////////////////////////////////////////////////////
Niels Möllerd0b88792021-08-12 08:32:30497// Socket Implementation
Benjamin Wright243cabe2018-10-16 08:55:28498///////////////////////////////////////////////////////////////////////////////
henrike@webrtc.orgf0488722014-05-13 18:00:26499
Justin Uberti1d445502017-08-15 00:04:34500int OpenSSLAdapter::Send(const void* pv, size_t cb) {
henrike@webrtc.orgf0488722014-05-13 18:00:26501 switch (state_) {
Yves Gerey665174f2018-06-19 13:03:05502 case SSL_NONE:
503 return AsyncSocketAdapter::Send(pv, cb);
Yves Gerey665174f2018-06-19 13:03:05504 case SSL_WAIT:
505 case SSL_CONNECTING:
506 SetError(ENOTCONN);
507 return SOCKET_ERROR;
Yves Gerey665174f2018-06-19 13:03:05508 case SSL_CONNECTED:
509 break;
Yves Gerey665174f2018-06-19 13:03:05510 case SSL_ERROR:
511 default:
512 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26513 }
514
deadbeefed3b9862017-06-02 17:33:16515 int ret;
516 int error;
517
518 if (!pending_data_.empty()) {
519 ret = DoSslWrite(pending_data_.data(), pending_data_.size(), &error);
520 if (ret != static_cast<int>(pending_data_.size())) {
521 // We couldn't finish sending the pending data, so we definitely can't
522 // send any more data. Return with an EWOULDBLOCK error.
523 SetError(EWOULDBLOCK);
524 return SOCKET_ERROR;
525 }
526 // We completed sending the data previously passed into SSL_write! Now
527 // we're allowed to send more data.
528 pending_data_.Clear();
529 }
530
henrike@webrtc.orgf0488722014-05-13 18:00:26531 // OpenSSL will return an error if we try to write zero bytes
Benjamin Wright243cabe2018-10-16 08:55:28532 if (cb == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26533 return 0;
Benjamin Wright243cabe2018-10-16 08:55:28534 }
henrike@webrtc.orgf0488722014-05-13 18:00:26535
deadbeefed3b9862017-06-02 17:33:16536 ret = DoSslWrite(pv, cb, &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26537
deadbeefed3b9862017-06-02 17:33:16538 // If SSL_write fails with SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, this
539 // means the underlying socket is blocked on reading or (more typically)
540 // writing. When this happens, OpenSSL requires that the next call to
541 // SSL_write uses the same arguments (though, with
542 // SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, the actual buffer pointer may be
543 // different).
544 //
545 // However, after Send exits, we will have lost access to data the user of
546 // this class is trying to send, and there's no guarantee that the user of
547 // this class will call Send with the same arguements when it fails. So, we
548 // buffer the data ourselves. When we know the underlying socket is writable
549 // again from OnWriteEvent (or if Send is called again before that happens),
550 // we'll retry sending this buffered data.
deadbeefe5dce2b2017-06-02 18:52:06551 if (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) {
552 // Shouldn't be able to get to this point if we already have pending data.
553 RTC_DCHECK(pending_data_.empty());
Mirko Bonadei675513b2017-11-09 10:09:25554 RTC_LOG(LS_WARNING)
deadbeefed3b9862017-06-02 17:33:16555 << "SSL_write couldn't write to the underlying socket; buffering data.";
556 pending_data_.SetData(static_cast<const uint8_t*>(pv), cb);
557 // Since we're taking responsibility for sending this data, return its full
558 // size. The user of this class can consider it sent.
Mirko Bonadeia041f922018-05-23 08:22:36559 return rtc::dchecked_cast<int>(cb);
henrike@webrtc.orgf0488722014-05-13 18:00:26560 }
deadbeefed3b9862017-06-02 17:33:16561 return ret;
henrike@webrtc.orgf0488722014-05-13 18:00:26562}
563
Justin Uberti1d445502017-08-15 00:04:34564int OpenSSLAdapter::SendTo(const void* pv,
565 size_t cb,
566 const SocketAddress& addr) {
Niels Möller8729d782021-08-11 09:22:44567 if (GetSocket()->GetState() == Socket::CS_CONNECTED &&
568 addr == GetSocket()->GetRemoteAddress()) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14569 return Send(pv, cb);
570 }
571
572 SetError(ENOTCONN);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14573 return SOCKET_ERROR;
574}
575
Stefan Holmer9131efd2016-05-23 16:19:26576int OpenSSLAdapter::Recv(void* pv, size_t cb, int64_t* timestamp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26577 switch (state_) {
Yves Gerey665174f2018-06-19 13:03:05578 case SSL_NONE:
579 return AsyncSocketAdapter::Recv(pv, cb, timestamp);
Yves Gerey665174f2018-06-19 13:03:05580 case SSL_WAIT:
581 case SSL_CONNECTING:
582 SetError(ENOTCONN);
583 return SOCKET_ERROR;
Yves Gerey665174f2018-06-19 13:03:05584 case SSL_CONNECTED:
585 break;
Yves Gerey665174f2018-06-19 13:03:05586 case SSL_ERROR:
587 default:
588 return SOCKET_ERROR;
henrike@webrtc.orgf0488722014-05-13 18:00:26589 }
590
591 // Don't trust OpenSSL with zero byte reads
Benjamin Wright243cabe2018-10-16 08:55:28592 if (cb == 0) {
henrike@webrtc.orgf0488722014-05-13 18:00:26593 return 0;
Benjamin Wright243cabe2018-10-16 08:55:28594 }
henrike@webrtc.orgf0488722014-05-13 18:00:26595
596 ssl_read_needs_write_ = false;
henrike@webrtc.orgd89b69a2014-11-06 17:23:09597 int code = SSL_read(ssl_, pv, checked_cast<int>(cb));
deadbeefed3b9862017-06-02 17:33:16598 int error = SSL_get_error(ssl_, code);
Benjamin Wright243cabe2018-10-16 08:55:28599
deadbeefed3b9862017-06-02 17:33:16600 switch (error) {
601 case SSL_ERROR_NONE:
deadbeefed3b9862017-06-02 17:33:16602 return code;
603 case SSL_ERROR_WANT_READ:
deadbeefed3b9862017-06-02 17:33:16604 SetError(EWOULDBLOCK);
605 break;
606 case SSL_ERROR_WANT_WRITE:
deadbeefed3b9862017-06-02 17:33:16607 ssl_read_needs_write_ = true;
608 SetError(EWOULDBLOCK);
609 break;
610 case SSL_ERROR_ZERO_RETURN:
deadbeefed3b9862017-06-02 17:33:16611 SetError(EWOULDBLOCK);
612 // do we need to signal closure?
613 break;
614 case SSL_ERROR_SSL:
615 LogSslError();
616 Error("SSL_read", (code ? code : -1), false);
617 break;
618 default:
deadbeefed3b9862017-06-02 17:33:16619 Error("SSL_read", (code ? code : -1), false);
620 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26621 }
henrike@webrtc.orgf0488722014-05-13 18:00:26622 return SOCKET_ERROR;
623}
624
Stefan Holmer9131efd2016-05-23 16:19:26625int OpenSSLAdapter::RecvFrom(void* pv,
626 size_t cb,
627 SocketAddress* paddr,
628 int64_t* timestamp) {
Niels Möller8729d782021-08-11 09:22:44629 if (GetSocket()->GetState() == Socket::CS_CONNECTED) {
Stefan Holmer9131efd2016-05-23 16:19:26630 int ret = Recv(pv, cb, timestamp);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14631 *paddr = GetRemoteAddress();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14632 return ret;
633 }
634
635 SetError(ENOTCONN);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14636 return SOCKET_ERROR;
637}
638
Justin Uberti1d445502017-08-15 00:04:34639int OpenSSLAdapter::Close() {
henrike@webrtc.orgf0488722014-05-13 18:00:26640 Cleanup();
Mirko Bonadei2d2c2942020-04-10 22:01:43641 state_ = SSL_NONE;
henrike@webrtc.orgf0488722014-05-13 18:00:26642 return AsyncSocketAdapter::Close();
643}
644
Justin Uberti1d445502017-08-15 00:04:34645Socket::ConnState OpenSSLAdapter::GetState() const {
Niels Möller8729d782021-08-11 09:22:44646 ConnState state = GetSocket()->GetState();
Yves Gerey665174f2018-06-19 13:03:05647 if ((state == CS_CONNECTED) &&
Benjamin Wright243cabe2018-10-16 08:55:28648 ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING))) {
henrike@webrtc.orgf0488722014-05-13 18:00:26649 state = CS_CONNECTING;
Benjamin Wright243cabe2018-10-16 08:55:28650 }
henrike@webrtc.orgf0488722014-05-13 18:00:26651 return state;
652}
653
Justin Uberti1d445502017-08-15 00:04:34654bool OpenSSLAdapter::IsResumedSession() {
655 return (ssl_ && SSL_session_reused(ssl_) == 1);
656}
657
Danil Chapovalove7280c32022-08-18 10:01:30658void OpenSSLAdapter::OnTimeout() {
659 RTC_LOG(LS_INFO) << "DTLS timeout expired";
660 DTLSv1_handle_timeout(ssl_);
661 ContinueSSL();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14662}
663
Niels Möllerd0b88792021-08-12 08:32:30664void OpenSSLAdapter::OnConnectEvent(Socket* socket) {
Mirko Bonadei675513b2017-11-09 10:09:25665 RTC_LOG(LS_INFO) << "OpenSSLAdapter::OnConnectEvent";
henrike@webrtc.orgf0488722014-05-13 18:00:26666 if (state_ != SSL_WAIT) {
nisseede5da42017-01-12 13:15:36667 RTC_DCHECK(state_ == SSL_NONE);
henrike@webrtc.orgf0488722014-05-13 18:00:26668 AsyncSocketAdapter::OnConnectEvent(socket);
669 return;
670 }
671
672 state_ = SSL_CONNECTING;
673 if (int err = BeginSSL()) {
674 AsyncSocketAdapter::OnCloseEvent(socket, err);
675 }
676}
677
Niels Möllerd0b88792021-08-12 08:32:30678void OpenSSLAdapter::OnReadEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26679 if (state_ == SSL_NONE) {
680 AsyncSocketAdapter::OnReadEvent(socket);
681 return;
682 }
683
684 if (state_ == SSL_CONNECTING) {
685 if (int err = ContinueSSL()) {
686 Error("ContinueSSL", err);
687 }
688 return;
689 }
690
Benjamin Wright243cabe2018-10-16 08:55:28691 if (state_ != SSL_CONNECTED) {
henrike@webrtc.orgf0488722014-05-13 18:00:26692 return;
Benjamin Wright243cabe2018-10-16 08:55:28693 }
henrike@webrtc.orgf0488722014-05-13 18:00:26694
695 // Don't let ourselves go away during the callbacks
Benjamin Wrightd6f86e82018-05-08 20:12:25696 // PRefPtr<OpenSSLAdapter> lock(this); // TODO(benwright): fix this
Yves Gerey665174f2018-06-19 13:03:05697 if (ssl_write_needs_read_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26698 AsyncSocketAdapter::OnWriteEvent(socket);
699 }
700
henrike@webrtc.orgf0488722014-05-13 18:00:26701 AsyncSocketAdapter::OnReadEvent(socket);
702}
703
Niels Möllerd0b88792021-08-12 08:32:30704void OpenSSLAdapter::OnWriteEvent(Socket* socket) {
henrike@webrtc.orgf0488722014-05-13 18:00:26705 if (state_ == SSL_NONE) {
706 AsyncSocketAdapter::OnWriteEvent(socket);
707 return;
708 }
709
710 if (state_ == SSL_CONNECTING) {
711 if (int err = ContinueSSL()) {
712 Error("ContinueSSL", err);
713 }
714 return;
715 }
716
Benjamin Wright243cabe2018-10-16 08:55:28717 if (state_ != SSL_CONNECTED) {
henrike@webrtc.orgf0488722014-05-13 18:00:26718 return;
Benjamin Wright243cabe2018-10-16 08:55:28719 }
henrike@webrtc.orgf0488722014-05-13 18:00:26720
721 // Don't let ourselves go away during the callbacks
Benjamin Wrightd6f86e82018-05-08 20:12:25722 // PRefPtr<OpenSSLAdapter> lock(this); // TODO(benwright): fix this
henrike@webrtc.orgf0488722014-05-13 18:00:26723
Yves Gerey665174f2018-06-19 13:03:05724 if (ssl_read_needs_write_) {
henrike@webrtc.orgf0488722014-05-13 18:00:26725 AsyncSocketAdapter::OnReadEvent(socket);
726 }
727
deadbeefed3b9862017-06-02 17:33:16728 // If a previous SSL_write failed due to the underlying socket being blocked,
729 // this will attempt finishing the write operation.
730 if (!pending_data_.empty()) {
731 int error;
732 if (DoSslWrite(pending_data_.data(), pending_data_.size(), &error) ==
733 static_cast<int>(pending_data_.size())) {
734 pending_data_.Clear();
735 }
736 }
737
henrike@webrtc.orgf0488722014-05-13 18:00:26738 AsyncSocketAdapter::OnWriteEvent(socket);
739}
740
Niels Möllerd0b88792021-08-12 08:32:30741void OpenSSLAdapter::OnCloseEvent(Socket* socket, int err) {
Mirko Bonadei675513b2017-11-09 10:09:25742 RTC_LOG(LS_INFO) << "OpenSSLAdapter::OnCloseEvent(" << err << ")";
henrike@webrtc.orgf0488722014-05-13 18:00:26743 AsyncSocketAdapter::OnCloseEvent(socket, err);
744}
745
Ali Tofigh7fa90572022-03-17 14:47:49746bool OpenSSLAdapter::SSLPostConnectionCheck(SSL* ssl, absl::string_view host) {
Benjamin Wrightd6f86e82018-05-08 20:12:25747 bool is_valid_cert_name =
748 openssl::VerifyPeerCertMatchesHost(ssl, host) &&
749 (SSL_get_verify_result(ssl) == X509_V_OK || custom_cert_verifier_status_);
henrike@webrtc.orgf0488722014-05-13 18:00:26750
Sergey Silkin9c147dd2018-09-12 10:45:38751 if (!is_valid_cert_name && ignore_bad_cert_) {
Benjamin Wrightd6f86e82018-05-08 20:12:25752 RTC_DLOG(LS_WARNING) << "Other TLS post connection checks failed. "
Sergey Silkin9c147dd2018-09-12 10:45:38753 "ignore_bad_cert_ set to true. Overriding name "
754 "verification failure!";
Benjamin Wright9201d1a2018-04-05 19:12:26755 is_valid_cert_name = true;
henrike@webrtc.orgf0488722014-05-13 18:00:26756 }
Benjamin Wright9201d1a2018-04-05 19:12:26757 return is_valid_cert_name;
henrike@webrtc.orgf0488722014-05-13 18:00:26758}
759
Per Kd1771e92023-04-24 10:44:27760void OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int value) {
761 std::string type;
762 bool info_log = false;
763 bool alert_log = false;
764 switch (where) {
765 case SSL_CB_EXIT:
766 info_log = true;
767 type = "exit";
768 break;
769 case SSL_CB_ALERT:
770 alert_log = true;
771 type = "alert";
772 break;
773 case SSL_CB_READ_ALERT:
774 alert_log = true;
775 type = "read_alert";
776 break;
777 case SSL_CB_WRITE_ALERT:
778 alert_log = true;
779 type = "write_alert";
780 break;
781 case SSL_CB_ACCEPT_LOOP:
782 info_log = true;
783 type = "accept_loop";
784 break;
785 case SSL_CB_ACCEPT_EXIT:
786 info_log = true;
787 type = "accept_exit";
788 break;
789 case SSL_CB_CONNECT_LOOP:
790 info_log = true;
791 type = "connect_loop";
792 break;
793 case SSL_CB_CONNECT_EXIT:
794 info_log = true;
795 type = "connect_exit";
796 break;
797 case SSL_CB_HANDSHAKE_START:
798 info_log = true;
799 type = "handshake_start";
800 break;
801 case SSL_CB_HANDSHAKE_DONE:
802 info_log = true;
803 type = "handshake_done";
804 break;
805 case SSL_CB_LOOP:
806 case SSL_CB_READ:
807 case SSL_CB_WRITE:
808 default:
809 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26810 }
Per Kd1771e92023-04-24 10:44:27811
812 if (info_log) {
813 RTC_LOG(LS_INFO) << type << " " << SSL_state_string_long(s);
814 }
815 if (alert_log) {
816 RTC_LOG(LS_WARNING) << type << " " << SSL_alert_type_string_long(value)
817 << " " << SSL_alert_desc_string_long(value) << " "
818 << SSL_state_string_long(s);
henrike@webrtc.orgf0488722014-05-13 18:00:26819 }
820}
821
Taylor Brandstetter165c6182020-12-11 00:23:03822#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
823// static
824enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyCallback(SSL* ssl,
825 uint8_t* out_alert) {
826 // Get our stream pointer from the SSL context.
827 OpenSSLAdapter* stream =
828 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
829
830 ssl_verify_result_t ret = stream->SSLVerifyInternal(ssl, out_alert);
831
832 // Should only be used for debugging and development.
833 if (ret != ssl_verify_ok && stream->ignore_bad_cert_) {
834 RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
835 return ssl_verify_ok;
836 }
837
838 return ret;
839}
840
841enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyInternal(SSL* ssl,
842 uint8_t* out_alert) {
843 if (ssl_cert_verifier_ == nullptr) {
844 RTC_LOG(LS_WARNING) << "Built-in trusted root certificates disabled but no "
845 "SSL verify callback provided.";
846 return ssl_verify_invalid;
847 }
848
849 RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback.";
850 const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
851 if (sk_CRYPTO_BUFFER_num(chain) == 0) {
852 RTC_LOG(LS_ERROR) << "Peer certificate chain empty?";
853 return ssl_verify_invalid;
854 }
855
856 BoringSSLCertificate cert(bssl::UpRef(sk_CRYPTO_BUFFER_value(chain, 0)));
857 if (!ssl_cert_verifier_->Verify(cert)) {
858 RTC_LOG(LS_WARNING) << "Failed to verify certificate using custom callback";
859 return ssl_verify_invalid;
860 }
861
862 custom_cert_verifier_status_ = true;
863 RTC_LOG(LS_INFO) << "Validated certificate using custom callback";
864 return ssl_verify_ok;
865}
866#else // WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
Harald Alvestrandb32650e2021-09-10 08:03:22867int OpenSSLAdapter::SSLVerifyCallback(int status, X509_STORE_CTX* store) {
Taylor Brandstetter165c6182020-12-11 00:23:03868 // Get our stream pointer from the store
869 SSL* ssl = reinterpret_cast<SSL*>(
870 X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()));
871
872 OpenSSLAdapter* stream =
873 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
Harald Alvestrandb32650e2021-09-10 08:03:22874 // Update status with the custom verifier.
875 // Status is unchanged if verification fails.
876 status = stream->SSLVerifyInternal(status, ssl, store);
Taylor Brandstetter165c6182020-12-11 00:23:03877
878 // Should only be used for debugging and development.
Harald Alvestrandb32650e2021-09-10 08:03:22879 if (!status && stream->ignore_bad_cert_) {
Taylor Brandstetter165c6182020-12-11 00:23:03880 RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
881 return 1;
882 }
883
Harald Alvestrandb32650e2021-09-10 08:03:22884 return status;
Taylor Brandstetter165c6182020-12-11 00:23:03885}
886
Taylor Brandstetterbd917a12021-09-14 22:22:41887int OpenSSLAdapter::SSLVerifyInternal(int previous_status,
Harald Alvestrandb32650e2021-09-10 08:03:22888 SSL* ssl,
889 X509_STORE_CTX* store) {
tfarinaa41ab932015-10-30 23:08:48890#if !defined(NDEBUG)
Taylor Brandstetterbd917a12021-09-14 22:22:41891 if (!previous_status) {
henrike@webrtc.orgf0488722014-05-13 18:00:26892 char data[256];
893 X509* cert = X509_STORE_CTX_get_current_cert(store);
894 int depth = X509_STORE_CTX_get_error_depth(store);
895 int err = X509_STORE_CTX_get_error(store);
896
Jonas Olssonaddc3802018-02-01 08:53:06897 RTC_DLOG(LS_INFO) << "Error with certificate at depth: " << depth;
henrike@webrtc.orgf0488722014-05-13 18:00:26898 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
Jonas Olssonaddc3802018-02-01 08:53:06899 RTC_DLOG(LS_INFO) << " issuer = " << data;
henrike@webrtc.orgf0488722014-05-13 18:00:26900 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
Jonas Olssonaddc3802018-02-01 08:53:06901 RTC_DLOG(LS_INFO) << " subject = " << data;
902 RTC_DLOG(LS_INFO) << " err = " << err << ":"
903 << X509_verify_cert_error_string(err);
henrike@webrtc.orgf0488722014-05-13 18:00:26904 }
905#endif
Taylor Brandstetterbd917a12021-09-14 22:22:41906 // `ssl_cert_verifier_` is used to override errors; if there is no error
907 // there is no reason to call it.
908 if (previous_status || ssl_cert_verifier_ == nullptr) {
909 return previous_status;
henrike@webrtc.orgf0488722014-05-13 18:00:26910 }
911
Taylor Brandstetter165c6182020-12-11 00:23:03912 RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback.";
913#ifdef OPENSSL_IS_BORINGSSL
914 // Convert X509 to CRYPTO_BUFFER.
915 uint8_t* data = nullptr;
916 int length = i2d_X509(X509_STORE_CTX_get_current_cert(store), &data);
917 if (length < 0) {
918 RTC_LOG(LS_ERROR) << "Failed to encode X509.";
Taylor Brandstetterbd917a12021-09-14 22:22:41919 return previous_status;
Taylor Brandstetter165c6182020-12-11 00:23:03920 }
921 bssl::UniquePtr<uint8_t> owned_data(data);
922 bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer(
923 CRYPTO_BUFFER_new(data, length, openssl::GetBufferPool()));
924 if (!crypto_buffer) {
925 RTC_LOG(LS_ERROR) << "Failed to allocate CRYPTO_BUFFER.";
Taylor Brandstetterbd917a12021-09-14 22:22:41926 return previous_status;
Taylor Brandstetter165c6182020-12-11 00:23:03927 }
928 const BoringSSLCertificate cert(std::move(crypto_buffer));
929#else
930 const OpenSSLCertificate cert(X509_STORE_CTX_get_current_cert(store));
931#endif
932 if (!ssl_cert_verifier_->Verify(cert)) {
933 RTC_LOG(LS_INFO) << "Failed to verify certificate using custom callback";
Taylor Brandstetterbd917a12021-09-14 22:22:41934 return previous_status;
henrike@webrtc.orgf0488722014-05-13 18:00:26935 }
936
Taylor Brandstetter165c6182020-12-11 00:23:03937 custom_cert_verifier_status_ = true;
938 RTC_LOG(LS_INFO) << "Validated certificate using custom callback";
939 return 1;
henrike@webrtc.orgf0488722014-05-13 18:00:26940}
Taylor Brandstetter165c6182020-12-11 00:23:03941#endif // !defined(WEBRTC_USE_CRYPTO_BUFFER_CALLBACK)
henrike@webrtc.orgf0488722014-05-13 18:00:26942
Justin Uberti1d445502017-08-15 00:04:34943int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) {
944 OpenSSLAdapter* stream =
945 reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
Benjamin Wright19aab2e2018-04-05 22:39:06946 RTC_DCHECK(stream->ssl_session_cache_);
Mirko Bonadei675513b2017-11-09 10:09:25947 RTC_LOG(LS_INFO) << "Caching SSL session for " << stream->ssl_host_name_;
Benjamin Wright19aab2e2018-04-05 22:39:06948 stream->ssl_session_cache_->AddSession(stream->ssl_host_name_, session);
Justin Uberti1d445502017-08-15 00:04:34949 return 1; // We've taken ownership of the session; OpenSSL shouldn't free it.
950}
951
Justin Uberti1d445502017-08-15 00:04:34952SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
Taylor Brandstetter165c6182020-12-11 00:23:03953#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
954 // If X509 objects aren't used, we can use these methods to avoid
955 // linking the sizable crypto/x509 code.
956 SSL_CTX* ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_with_buffers_method()
957 : TLS_with_buffers_method());
958#else
David Benjamin170a4b32019-01-30 15:46:16959 SSL_CTX* ctx =
960 SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
Taylor Brandstetter165c6182020-12-11 00:23:03961#endif
deadbeef37f5ecf2017-02-27 22:06:41962 if (ctx == nullptr) {
henrike@webrtc.orgf0488722014-05-13 18:00:26963 unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL.
Mirko Bonadei675513b2017-11-09 10:09:25964 RTC_LOG(LS_WARNING) << "SSL_CTX creation failed: " << '"'
Jonas Olssonb2b20312020-01-14 11:11:31965 << ERR_reason_error_string(error)
966 << "\" "
967 "(error="
968 << error << ')';
deadbeef37f5ecf2017-02-27 22:06:41969 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26970 }
Benjamin Wrightd6f86e82018-05-08 20:12:25971
Mirko Bonadeib889a202018-08-15 09:41:27972#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
Benjamin Wrightd6f86e82018-05-08 20:12:25973 if (!openssl::LoadBuiltinSSLRootCertificates(ctx)) {
974 RTC_LOG(LS_ERROR) << "SSL_CTX creation failed: Failed to load any trusted "
975 "ssl root certificates.";
henrike@webrtc.orgf0488722014-05-13 18:00:26976 SSL_CTX_free(ctx);
deadbeef37f5ecf2017-02-27 22:06:41977 return nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26978 }
Mirko Bonadeib889a202018-08-15 09:41:27979#endif // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
henrike@webrtc.orgf0488722014-05-13 18:00:26980
tfarinaa41ab932015-10-30 23:08:48981#if !defined(NDEBUG)
henrike@webrtc.orgf0488722014-05-13 18:00:26982 SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
983#endif
984
Taylor Brandstetter165c6182020-12-11 00:23:03985#ifdef OPENSSL_IS_BORINGSSL
986 SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool());
987#endif
988
989#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
990 SSL_CTX_set_custom_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
991#else
henrike@webrtc.orgf0488722014-05-13 18:00:26992 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
Philipp Hanckeae278d42021-06-16 08:26:56993 // Verify certificate chains up to a depth of 4. This is not
994 // needed for DTLS-SRTP which uses self-signed certificates
995 // (so the depth is 0) but is required to support TURN/TLS.
henrike@webrtc.orgf0488722014-05-13 18:00:26996 SSL_CTX_set_verify_depth(ctx, 4);
Taylor Brandstetter165c6182020-12-11 00:23:03997#endif
Emad Omarac6de0c92017-06-21 23:40:56998 // Use defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers
999 // (note that SHA256 and SHA384 only select legacy CBC ciphers).
1000 // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining
David Benjamin7a46cc52021-08-17 20:56:201001 // CBC-mode ECDSA ciphers. Finally, disable 3DES.
Emad Omarac6de0c92017-06-21 23:40:561002 SSL_CTX_set_cipher_list(
David Benjamin7a46cc52021-08-17 20:56:201003 ctx, "ALL:!SHA256:!SHA384:!aPSK:!ECDSA+SHA1:!ADH:!LOW:!EXP:!MD5:!3DES");
henrike@webrtc.orgf0488722014-05-13 18:00:261004
Justin Uberti1d445502017-08-15 00:04:341005 if (mode == SSL_MODE_DTLS) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:141006 SSL_CTX_set_read_ahead(ctx, 1);
1007 }
1008
Justin Uberti1d445502017-08-15 00:04:341009 if (enable_cache) {
1010 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT);
1011 SSL_CTX_sess_set_new_cb(ctx, &OpenSSLAdapter::NewSSLSessionCallback);
1012 }
1013
henrike@webrtc.orgf0488722014-05-13 18:00:261014 return ctx;
1015}
1016
Diogo Real1dca9d52017-08-29 19:18:321017std::string TransformAlpnProtocols(
1018 const std::vector<std::string>& alpn_protocols) {
1019 // Transforms the alpn_protocols list to the format expected by
1020 // Open/BoringSSL. This requires joining the protocols into a single string
1021 // and prepending a character with the size of the protocol string before
1022 // each protocol.
1023 std::string transformed_alpn;
1024 for (const std::string& proto : alpn_protocols) {
1025 if (proto.size() == 0 || proto.size() > 0xFF) {
Mirko Bonadei675513b2017-11-09 10:09:251026 RTC_LOG(LS_ERROR) << "OpenSSLAdapter::Error("
Jonas Olssonb2b20312020-01-14 11:11:311027 "TransformAlpnProtocols received proto with size "
Mirko Bonadei675513b2017-11-09 10:09:251028 << proto.size() << ")";
Diogo Real1dca9d52017-08-29 19:18:321029 return "";
1030 }
1031 transformed_alpn += static_cast<char>(proto.size());
1032 transformed_alpn += proto;
Mirko Bonadei675513b2017-11-09 10:09:251033 RTC_LOG(LS_VERBOSE) << "TransformAlpnProtocols: Adding proto: " << proto;
Diogo Real1dca9d52017-08-29 19:18:321034 }
1035 return transformed_alpn;
1036}
1037
Justin Uberti1d445502017-08-15 00:04:341038//////////////////////////////////////////////////////////////////////
1039// OpenSSLAdapterFactory
1040//////////////////////////////////////////////////////////////////////
1041
Benjamin Wright19aab2e2018-04-05 22:39:061042OpenSSLAdapterFactory::OpenSSLAdapterFactory() = default;
Benjamin Wrightd6f86e82018-05-08 20:12:251043
Benjamin Wright19aab2e2018-04-05 22:39:061044OpenSSLAdapterFactory::~OpenSSLAdapterFactory() = default;
Justin Uberti1d445502017-08-15 00:04:341045
1046void OpenSSLAdapterFactory::SetMode(SSLMode mode) {
Benjamin Wright19aab2e2018-04-05 22:39:061047 RTC_DCHECK(!ssl_session_cache_);
Justin Uberti1d445502017-08-15 00:04:341048 ssl_mode_ = mode;
1049}
1050
Benjamin Wrightd6f86e82018-05-08 20:12:251051void OpenSSLAdapterFactory::SetCertVerifier(
1052 SSLCertificateVerifier* ssl_cert_verifier) {
1053 RTC_DCHECK(!ssl_session_cache_);
1054 ssl_cert_verifier_ = ssl_cert_verifier;
1055}
1056
Niels Möllerac9a2882021-10-20 13:25:091057void OpenSSLAdapterFactory::SetIdentity(std::unique_ptr<SSLIdentity> identity) {
1058 RTC_DCHECK(!ssl_session_cache_);
1059 identity_ = std::move(identity);
1060}
1061
1062void OpenSSLAdapterFactory::SetRole(SSLRole role) {
1063 RTC_DCHECK(!ssl_session_cache_);
1064 ssl_role_ = role;
1065}
1066
1067void OpenSSLAdapterFactory::SetIgnoreBadCert(bool ignore) {
1068 RTC_DCHECK(!ssl_session_cache_);
1069 ignore_bad_cert_ = ignore;
1070}
1071
Niels Möllerd0b88792021-08-12 08:32:301072OpenSSLAdapter* OpenSSLAdapterFactory::CreateAdapter(Socket* socket) {
Benjamin Wright19aab2e2018-04-05 22:39:061073 if (ssl_session_cache_ == nullptr) {
Benjamin Wrightd6f86e82018-05-08 20:12:251074 SSL_CTX* ssl_ctx = OpenSSLAdapter::CreateContext(ssl_mode_, true);
Benjamin Wright19aab2e2018-04-05 22:39:061075 if (ssl_ctx == nullptr) {
Justin Uberti1d445502017-08-15 00:04:341076 return nullptr;
1077 }
Benjamin Wright19aab2e2018-04-05 22:39:061078 // The OpenSSLSessionCache will upref the ssl_ctx.
Karl Wiberg918f50c2018-07-05 09:40:331079 ssl_session_cache_ =
Mirko Bonadei317a1f02019-09-17 15:06:181080 std::make_unique<OpenSSLSessionCache>(ssl_mode_, ssl_ctx);
Benjamin Wright19aab2e2018-04-05 22:39:061081 SSL_CTX_free(ssl_ctx);
Justin Uberti1d445502017-08-15 00:04:341082 }
Niels Möllerac9a2882021-10-20 13:25:091083 OpenSSLAdapter* ssl_adapter =
1084 new OpenSSLAdapter(socket, ssl_session_cache_.get(), ssl_cert_verifier_);
1085 ssl_adapter->SetRole(ssl_role_);
1086 ssl_adapter->SetIgnoreBadCert(ignore_bad_cert_);
1087 if (identity_) {
1088 ssl_adapter->SetIdentity(identity_->Clone());
1089 }
1090 return ssl_adapter;
Justin Uberti1d445502017-08-15 00:04:341091}
1092
Vojin Ilicf11f0e02021-06-30 12:22:111093OpenSSLAdapter::EarlyExitCatcher::EarlyExitCatcher(OpenSSLAdapter& adapter_ptr)
1094 : adapter_ptr_(adapter_ptr) {}
1095
1096void OpenSSLAdapter::EarlyExitCatcher::disable() {
1097 disabled_ = true;
1098}
1099
1100OpenSSLAdapter::EarlyExitCatcher::~EarlyExitCatcher() {
1101 if (!disabled_) {
1102 adapter_ptr_.Cleanup();
1103 }
1104}
1105
Benjamin Wright19aab2e2018-04-05 22:39:061106} // namespace rtc