xref: /aosp_15_r20/external/webrtc/rtc_base/openssl_stream_adapter.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_stream_adapter.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <openssl/bio.h>
14*d9f75844SAndroid Build Coastguard Worker #include <openssl/crypto.h>
15*d9f75844SAndroid Build Coastguard Worker #include <openssl/err.h>
16*d9f75844SAndroid Build Coastguard Worker #include <openssl/rand.h>
17*d9f75844SAndroid Build Coastguard Worker #include <openssl/tls1.h>
18*d9f75844SAndroid Build Coastguard Worker #include <openssl/x509v3.h>
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
21*d9f75844SAndroid Build Coastguard Worker #ifndef OPENSSL_IS_BORINGSSL
22*d9f75844SAndroid Build Coastguard Worker #include <openssl/dtls1.h>
23*d9f75844SAndroid Build Coastguard Worker #include <openssl/ssl.h>
24*d9f75844SAndroid Build Coastguard Worker #endif
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker #include <atomic>
27*d9f75844SAndroid Build Coastguard Worker #include <memory>
28*d9f75844SAndroid Build Coastguard Worker #include <utility>
29*d9f75844SAndroid Build Coastguard Worker #include <vector>
30*d9f75844SAndroid Build Coastguard Worker 
31*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl.h"
36*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_adapter.h"
37*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_digest.h"
38*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
39*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/boringssl_identity.h"
40*d9f75844SAndroid Build Coastguard Worker #else
41*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_identity.h"
42*d9f75844SAndroid Build Coastguard Worker #endif
43*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/openssl_utility.h"
44*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_certificate.h"
45*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/stream.h"
46*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
47*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/thread.h"
48*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
49*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/field_trial.h"
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
52*d9f75844SAndroid Build Coastguard Worker #error "webrtc requires at least OpenSSL version 1.1.0, to support DTLS-SRTP"
53*d9f75844SAndroid Build Coastguard Worker #endif
54*d9f75844SAndroid Build Coastguard Worker 
55*d9f75844SAndroid Build Coastguard Worker // Defines for the TLS Cipher Suite Map.
56*d9f75844SAndroid Build Coastguard Worker #define DEFINE_CIPHER_ENTRY_SSL3(name) \
57*d9f75844SAndroid Build Coastguard Worker   { SSL3_CK_##name, "TLS_" #name }
58*d9f75844SAndroid Build Coastguard Worker #define DEFINE_CIPHER_ENTRY_TLS1(name) \
59*d9f75844SAndroid Build Coastguard Worker   { TLS1_CK_##name, "TLS_" #name }
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker namespace rtc {
62*d9f75844SAndroid Build Coastguard Worker namespace {
63*d9f75844SAndroid Build Coastguard Worker using ::webrtc::SafeTask;
64*d9f75844SAndroid Build Coastguard Worker // SRTP cipher suite table. `internal_name` is used to construct a
65*d9f75844SAndroid Build Coastguard Worker // colon-separated profile strings which is needed by
66*d9f75844SAndroid Build Coastguard Worker // SSL_CTX_set_tlsext_use_srtp().
67*d9f75844SAndroid Build Coastguard Worker struct SrtpCipherMapEntry {
68*d9f75844SAndroid Build Coastguard Worker   const char* internal_name;
69*d9f75844SAndroid Build Coastguard Worker   const int id;
70*d9f75844SAndroid Build Coastguard Worker };
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker // Cipher name table. Maps internal OpenSSL cipher ids to the RFC name.
73*d9f75844SAndroid Build Coastguard Worker struct SslCipherMapEntry {
74*d9f75844SAndroid Build Coastguard Worker   uint32_t openssl_id;
75*d9f75844SAndroid Build Coastguard Worker   const char* rfc_name;
76*d9f75844SAndroid Build Coastguard Worker };
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker // This isn't elegant, but it's better than an external reference
79*d9f75844SAndroid Build Coastguard Worker constexpr SrtpCipherMapEntry kSrtpCipherMap[] = {
80*d9f75844SAndroid Build Coastguard Worker     {"SRTP_AES128_CM_SHA1_80", kSrtpAes128CmSha1_80},
81*d9f75844SAndroid Build Coastguard Worker     {"SRTP_AES128_CM_SHA1_32", kSrtpAes128CmSha1_32},
82*d9f75844SAndroid Build Coastguard Worker     {"SRTP_AEAD_AES_128_GCM", kSrtpAeadAes128Gcm},
83*d9f75844SAndroid Build Coastguard Worker     {"SRTP_AEAD_AES_256_GCM", kSrtpAeadAes256Gcm}};
84*d9f75844SAndroid Build Coastguard Worker 
85*d9f75844SAndroid Build Coastguard Worker #ifndef OPENSSL_IS_BORINGSSL
86*d9f75844SAndroid Build Coastguard Worker // The "SSL_CIPHER_standard_name" function is only available in OpenSSL when
87*d9f75844SAndroid Build Coastguard Worker // compiled with tracing, so we need to define the mapping manually here.
88*d9f75844SAndroid Build Coastguard Worker constexpr SslCipherMapEntry kSslCipherMap[] = {
89*d9f75844SAndroid Build Coastguard Worker     // TLS v1.0 ciphersuites from RFC2246.
90*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_SSL3(RSA_RC4_128_SHA),
91*d9f75844SAndroid Build Coastguard Worker     {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker     // AES ciphersuites from RFC3268.
94*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
95*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_DHE_RSA_WITH_AES_128_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
96*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_RSA_WITH_AES_256_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
97*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker     // ECC ciphersuites from RFC4492.
100*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_RC4_128_SHA),
101*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
102*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"},
103*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
104*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_RC4_128_SHA),
107*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
108*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"},
109*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_CBC_SHA),
110*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_CBC_SHA),
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker     // TLS v1.2 ciphersuites.
113*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_RSA_WITH_AES_128_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
114*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_RSA_WITH_AES_256_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
115*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
116*d9f75844SAndroid Build Coastguard Worker      "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
117*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
118*d9f75844SAndroid Build Coastguard Worker      "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker     // TLS v1.2 GCM ciphersuites from RFC5288.
121*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_128_GCM_SHA256),
122*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_256_GCM_SHA384),
123*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_128_GCM_SHA256),
124*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_256_GCM_SHA384),
125*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_128_GCM_SHA256),
126*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_256_GCM_SHA384),
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker     // ECDH HMAC based ciphersuites from RFC5289.
129*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
130*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"},
131*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
132*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"},
133*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
134*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
135*d9f75844SAndroid Build Coastguard Worker     {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
136*d9f75844SAndroid Build Coastguard Worker      "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
137*d9f75844SAndroid Build Coastguard Worker 
138*d9f75844SAndroid Build Coastguard Worker     // ECDH GCM based ciphersuites from RFC5289.
139*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
140*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
141*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_GCM_SHA256),
142*d9f75844SAndroid Build Coastguard Worker     DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_GCM_SHA384),
143*d9f75844SAndroid Build Coastguard Worker 
144*d9f75844SAndroid Build Coastguard Worker     {0, nullptr}};
145*d9f75844SAndroid Build Coastguard Worker #endif  // #ifndef OPENSSL_IS_BORINGSSL
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
148*d9f75844SAndroid Build Coastguard Worker // Enabled by EnableTimeCallbackForTesting. Should never be set in production
149*d9f75844SAndroid Build Coastguard Worker // code.
150*d9f75844SAndroid Build Coastguard Worker bool g_use_time_callback_for_testing = false;
151*d9f75844SAndroid Build Coastguard Worker // Not used in production code. Actual time should be relative to Jan 1, 1970.
TimeCallbackForTesting(const SSL * ssl,struct timeval * out_clock)152*d9f75844SAndroid Build Coastguard Worker void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) {
153*d9f75844SAndroid Build Coastguard Worker   int64_t time = TimeNanos();
154*d9f75844SAndroid Build Coastguard Worker   out_clock->tv_sec = time / kNumNanosecsPerSec;
155*d9f75844SAndroid Build Coastguard Worker   out_clock->tv_usec = (time % kNumNanosecsPerSec) / kNumNanosecsPerMicrosec;
156*d9f75844SAndroid Build Coastguard Worker }
157*d9f75844SAndroid Build Coastguard Worker #endif
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker }  // namespace
160*d9f75844SAndroid Build Coastguard Worker 
161*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
162*d9f75844SAndroid Build Coastguard Worker // StreamBIO
163*d9f75844SAndroid Build Coastguard Worker //////////////////////////////////////////////////////////////////////
164*d9f75844SAndroid Build Coastguard Worker 
165*d9f75844SAndroid Build Coastguard Worker static int stream_write(BIO* h, const char* buf, int num);
166*d9f75844SAndroid Build Coastguard Worker static int stream_read(BIO* h, char* buf, int size);
167*d9f75844SAndroid Build Coastguard Worker static int stream_puts(BIO* h, const char* str);
168*d9f75844SAndroid Build Coastguard Worker static long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);
169*d9f75844SAndroid Build Coastguard Worker static int stream_new(BIO* h);
170*d9f75844SAndroid Build Coastguard Worker static int stream_free(BIO* data);
171*d9f75844SAndroid Build Coastguard Worker 
BIO_stream_method()172*d9f75844SAndroid Build Coastguard Worker static BIO_METHOD* BIO_stream_method() {
173*d9f75844SAndroid Build Coastguard Worker   static BIO_METHOD* method = [] {
174*d9f75844SAndroid Build Coastguard Worker     BIO_METHOD* method = BIO_meth_new(BIO_TYPE_BIO, "stream");
175*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_write(method, stream_write);
176*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_read(method, stream_read);
177*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_puts(method, stream_puts);
178*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_ctrl(method, stream_ctrl);
179*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_create(method, stream_new);
180*d9f75844SAndroid Build Coastguard Worker     BIO_meth_set_destroy(method, stream_free);
181*d9f75844SAndroid Build Coastguard Worker     return method;
182*d9f75844SAndroid Build Coastguard Worker   }();
183*d9f75844SAndroid Build Coastguard Worker   return method;
184*d9f75844SAndroid Build Coastguard Worker }
185*d9f75844SAndroid Build Coastguard Worker 
BIO_new_stream(StreamInterface * stream)186*d9f75844SAndroid Build Coastguard Worker static BIO* BIO_new_stream(StreamInterface* stream) {
187*d9f75844SAndroid Build Coastguard Worker   BIO* ret = BIO_new(BIO_stream_method());
188*d9f75844SAndroid Build Coastguard Worker   if (ret == nullptr) {
189*d9f75844SAndroid Build Coastguard Worker     return nullptr;
190*d9f75844SAndroid Build Coastguard Worker   }
191*d9f75844SAndroid Build Coastguard Worker   BIO_set_data(ret, stream);
192*d9f75844SAndroid Build Coastguard Worker   return ret;
193*d9f75844SAndroid Build Coastguard Worker }
194*d9f75844SAndroid Build Coastguard Worker 
195*d9f75844SAndroid Build Coastguard Worker // bio methods return 1 (or at least non-zero) on success and 0 on failure.
196*d9f75844SAndroid Build Coastguard Worker 
stream_new(BIO * b)197*d9f75844SAndroid Build Coastguard Worker static int stream_new(BIO* b) {
198*d9f75844SAndroid Build Coastguard Worker   BIO_set_shutdown(b, 0);
199*d9f75844SAndroid Build Coastguard Worker   BIO_set_init(b, 1);
200*d9f75844SAndroid Build Coastguard Worker   BIO_set_data(b, 0);
201*d9f75844SAndroid Build Coastguard Worker   return 1;
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker 
stream_free(BIO * b)204*d9f75844SAndroid Build Coastguard Worker static int stream_free(BIO* b) {
205*d9f75844SAndroid Build Coastguard Worker   if (b == nullptr) {
206*d9f75844SAndroid Build Coastguard Worker     return 0;
207*d9f75844SAndroid Build Coastguard Worker   }
208*d9f75844SAndroid Build Coastguard Worker   return 1;
209*d9f75844SAndroid Build Coastguard Worker }
210*d9f75844SAndroid Build Coastguard Worker 
stream_read(BIO * b,char * out,int outl)211*d9f75844SAndroid Build Coastguard Worker static int stream_read(BIO* b, char* out, int outl) {
212*d9f75844SAndroid Build Coastguard Worker   if (!out) {
213*d9f75844SAndroid Build Coastguard Worker     return -1;
214*d9f75844SAndroid Build Coastguard Worker   }
215*d9f75844SAndroid Build Coastguard Worker   StreamInterface* stream = static_cast<StreamInterface*>(BIO_get_data(b));
216*d9f75844SAndroid Build Coastguard Worker   BIO_clear_retry_flags(b);
217*d9f75844SAndroid Build Coastguard Worker   size_t read;
218*d9f75844SAndroid Build Coastguard Worker   int error;
219*d9f75844SAndroid Build Coastguard Worker   StreamResult result = stream->Read(
220*d9f75844SAndroid Build Coastguard Worker       rtc::MakeArrayView(reinterpret_cast<uint8_t*>(out), outl), read, error);
221*d9f75844SAndroid Build Coastguard Worker   if (result == SR_SUCCESS) {
222*d9f75844SAndroid Build Coastguard Worker     return checked_cast<int>(read);
223*d9f75844SAndroid Build Coastguard Worker   } else if (result == SR_BLOCK) {
224*d9f75844SAndroid Build Coastguard Worker     BIO_set_retry_read(b);
225*d9f75844SAndroid Build Coastguard Worker   }
226*d9f75844SAndroid Build Coastguard Worker   return -1;
227*d9f75844SAndroid Build Coastguard Worker }
228*d9f75844SAndroid Build Coastguard Worker 
stream_write(BIO * b,const char * in,int inl)229*d9f75844SAndroid Build Coastguard Worker static int stream_write(BIO* b, const char* in, int inl) {
230*d9f75844SAndroid Build Coastguard Worker   if (!in) {
231*d9f75844SAndroid Build Coastguard Worker     return -1;
232*d9f75844SAndroid Build Coastguard Worker   }
233*d9f75844SAndroid Build Coastguard Worker   StreamInterface* stream = static_cast<StreamInterface*>(BIO_get_data(b));
234*d9f75844SAndroid Build Coastguard Worker   BIO_clear_retry_flags(b);
235*d9f75844SAndroid Build Coastguard Worker   size_t written;
236*d9f75844SAndroid Build Coastguard Worker   int error;
237*d9f75844SAndroid Build Coastguard Worker   StreamResult result = stream->Write(
238*d9f75844SAndroid Build Coastguard Worker       rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(in), inl), written,
239*d9f75844SAndroid Build Coastguard Worker       error);
240*d9f75844SAndroid Build Coastguard Worker   if (result == SR_SUCCESS) {
241*d9f75844SAndroid Build Coastguard Worker     return checked_cast<int>(written);
242*d9f75844SAndroid Build Coastguard Worker   } else if (result == SR_BLOCK) {
243*d9f75844SAndroid Build Coastguard Worker     BIO_set_retry_write(b);
244*d9f75844SAndroid Build Coastguard Worker   }
245*d9f75844SAndroid Build Coastguard Worker   return -1;
246*d9f75844SAndroid Build Coastguard Worker }
247*d9f75844SAndroid Build Coastguard Worker 
stream_puts(BIO * b,const char * str)248*d9f75844SAndroid Build Coastguard Worker static int stream_puts(BIO* b, const char* str) {
249*d9f75844SAndroid Build Coastguard Worker   return stream_write(b, str, checked_cast<int>(strlen(str)));
250*d9f75844SAndroid Build Coastguard Worker }
251*d9f75844SAndroid Build Coastguard Worker 
stream_ctrl(BIO * b,int cmd,long num,void * ptr)252*d9f75844SAndroid Build Coastguard Worker static long stream_ctrl(BIO* b, int cmd, long num, void* ptr) {
253*d9f75844SAndroid Build Coastguard Worker   switch (cmd) {
254*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_RESET:
255*d9f75844SAndroid Build Coastguard Worker       return 0;
256*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_EOF: {
257*d9f75844SAndroid Build Coastguard Worker       StreamInterface* stream = static_cast<StreamInterface*>(ptr);
258*d9f75844SAndroid Build Coastguard Worker       // 1 means end-of-stream.
259*d9f75844SAndroid Build Coastguard Worker       return (stream->GetState() == SS_CLOSED) ? 1 : 0;
260*d9f75844SAndroid Build Coastguard Worker     }
261*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_WPENDING:
262*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_PENDING:
263*d9f75844SAndroid Build Coastguard Worker       return 0;
264*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_FLUSH:
265*d9f75844SAndroid Build Coastguard Worker       return 1;
266*d9f75844SAndroid Build Coastguard Worker     case BIO_CTRL_DGRAM_QUERY_MTU:
267*d9f75844SAndroid Build Coastguard Worker       // openssl defaults to mtu=256 unless we return something here.
268*d9f75844SAndroid Build Coastguard Worker       // The handshake doesn't actually need to send packets above 1k,
269*d9f75844SAndroid Build Coastguard Worker       // so this seems like a sensible value that should work in most cases.
270*d9f75844SAndroid Build Coastguard Worker       // Webrtc uses the same value for video packets.
271*d9f75844SAndroid Build Coastguard Worker       return 1200;
272*d9f75844SAndroid Build Coastguard Worker     default:
273*d9f75844SAndroid Build Coastguard Worker       return 0;
274*d9f75844SAndroid Build Coastguard Worker   }
275*d9f75844SAndroid Build Coastguard Worker }
276*d9f75844SAndroid Build Coastguard Worker 
277*d9f75844SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////
278*d9f75844SAndroid Build Coastguard Worker // OpenSSLStreamAdapter
279*d9f75844SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////
280*d9f75844SAndroid Build Coastguard Worker 
281*d9f75844SAndroid Build Coastguard Worker static std::atomic<bool> g_use_legacy_tls_protocols_override(false);
282*d9f75844SAndroid Build Coastguard Worker static std::atomic<bool> g_allow_legacy_tls_protocols(false);
283*d9f75844SAndroid Build Coastguard Worker 
SetAllowLegacyTLSProtocols(const absl::optional<bool> & allow)284*d9f75844SAndroid Build Coastguard Worker void SetAllowLegacyTLSProtocols(const absl::optional<bool>& allow) {
285*d9f75844SAndroid Build Coastguard Worker   g_use_legacy_tls_protocols_override.store(allow.has_value());
286*d9f75844SAndroid Build Coastguard Worker   if (allow.has_value())
287*d9f75844SAndroid Build Coastguard Worker     g_allow_legacy_tls_protocols.store(allow.value());
288*d9f75844SAndroid Build Coastguard Worker }
289*d9f75844SAndroid Build Coastguard Worker 
ShouldAllowLegacyTLSProtocols()290*d9f75844SAndroid Build Coastguard Worker bool ShouldAllowLegacyTLSProtocols() {
291*d9f75844SAndroid Build Coastguard Worker   return g_use_legacy_tls_protocols_override.load()
292*d9f75844SAndroid Build Coastguard Worker              ? g_allow_legacy_tls_protocols.load()
293*d9f75844SAndroid Build Coastguard Worker              : webrtc::field_trial::IsEnabled("WebRTC-LegacyTlsProtocols");
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker 
OpenSSLStreamAdapter(std::unique_ptr<StreamInterface> stream)296*d9f75844SAndroid Build Coastguard Worker OpenSSLStreamAdapter::OpenSSLStreamAdapter(
297*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<StreamInterface> stream)
298*d9f75844SAndroid Build Coastguard Worker     : stream_(std::move(stream)),
299*d9f75844SAndroid Build Coastguard Worker       owner_(rtc::Thread::Current()),
300*d9f75844SAndroid Build Coastguard Worker       state_(SSL_NONE),
301*d9f75844SAndroid Build Coastguard Worker       role_(SSL_CLIENT),
302*d9f75844SAndroid Build Coastguard Worker       ssl_read_needs_write_(false),
303*d9f75844SAndroid Build Coastguard Worker       ssl_write_needs_read_(false),
304*d9f75844SAndroid Build Coastguard Worker       ssl_(nullptr),
305*d9f75844SAndroid Build Coastguard Worker       ssl_ctx_(nullptr),
306*d9f75844SAndroid Build Coastguard Worker       ssl_mode_(SSL_MODE_TLS),
307*d9f75844SAndroid Build Coastguard Worker       ssl_max_version_(SSL_PROTOCOL_TLS_12),
308*d9f75844SAndroid Build Coastguard Worker       // Default is to support legacy TLS protocols.
309*d9f75844SAndroid Build Coastguard Worker       // This will be changed to default non-support in M82 or M83.
310*d9f75844SAndroid Build Coastguard Worker       support_legacy_tls_protocols_flag_(ShouldAllowLegacyTLSProtocols()) {
311*d9f75844SAndroid Build Coastguard Worker   stream_->SignalEvent.connect(this, &OpenSSLStreamAdapter::OnEvent);
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker 
~OpenSSLStreamAdapter()314*d9f75844SAndroid Build Coastguard Worker OpenSSLStreamAdapter::~OpenSSLStreamAdapter() {
315*d9f75844SAndroid Build Coastguard Worker   timeout_task_.Stop();
316*d9f75844SAndroid Build Coastguard Worker   Cleanup(0);
317*d9f75844SAndroid Build Coastguard Worker }
318*d9f75844SAndroid Build Coastguard Worker 
SetIdentity(std::unique_ptr<SSLIdentity> identity)319*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetIdentity(std::unique_ptr<SSLIdentity> identity) {
320*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!identity_);
321*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
322*d9f75844SAndroid Build Coastguard Worker   identity_.reset(static_cast<BoringSSLIdentity*>(identity.release()));
323*d9f75844SAndroid Build Coastguard Worker #else
324*d9f75844SAndroid Build Coastguard Worker   identity_.reset(static_cast<OpenSSLIdentity*>(identity.release()));
325*d9f75844SAndroid Build Coastguard Worker #endif
326*d9f75844SAndroid Build Coastguard Worker }
327*d9f75844SAndroid Build Coastguard Worker 
GetIdentityForTesting() const328*d9f75844SAndroid Build Coastguard Worker SSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const {
329*d9f75844SAndroid Build Coastguard Worker   return identity_.get();
330*d9f75844SAndroid Build Coastguard Worker }
331*d9f75844SAndroid Build Coastguard Worker 
SetServerRole(SSLRole role)332*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetServerRole(SSLRole role) {
333*d9f75844SAndroid Build Coastguard Worker   role_ = role;
334*d9f75844SAndroid Build Coastguard Worker }
335*d9f75844SAndroid Build Coastguard Worker 
SetPeerCertificateDigest(absl::string_view digest_alg,const unsigned char * digest_val,size_t digest_len,SSLPeerCertificateDigestError * error)336*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::SetPeerCertificateDigest(
337*d9f75844SAndroid Build Coastguard Worker     absl::string_view digest_alg,
338*d9f75844SAndroid Build Coastguard Worker     const unsigned char* digest_val,
339*d9f75844SAndroid Build Coastguard Worker     size_t digest_len,
340*d9f75844SAndroid Build Coastguard Worker     SSLPeerCertificateDigestError* error) {
341*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!peer_certificate_verified_);
342*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!HasPeerCertificateDigest());
343*d9f75844SAndroid Build Coastguard Worker   size_t expected_len;
344*d9f75844SAndroid Build Coastguard Worker   if (error) {
345*d9f75844SAndroid Build Coastguard Worker     *error = SSLPeerCertificateDigestError::NONE;
346*d9f75844SAndroid Build Coastguard Worker   }
347*d9f75844SAndroid Build Coastguard Worker 
348*d9f75844SAndroid Build Coastguard Worker   if (!OpenSSLDigest::GetDigestSize(digest_alg, &expected_len)) {
349*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Unknown digest algorithm: " << digest_alg;
350*d9f75844SAndroid Build Coastguard Worker     if (error) {
351*d9f75844SAndroid Build Coastguard Worker       *error = SSLPeerCertificateDigestError::UNKNOWN_ALGORITHM;
352*d9f75844SAndroid Build Coastguard Worker     }
353*d9f75844SAndroid Build Coastguard Worker     return false;
354*d9f75844SAndroid Build Coastguard Worker   }
355*d9f75844SAndroid Build Coastguard Worker   if (expected_len != digest_len) {
356*d9f75844SAndroid Build Coastguard Worker     if (error) {
357*d9f75844SAndroid Build Coastguard Worker       *error = SSLPeerCertificateDigestError::INVALID_LENGTH;
358*d9f75844SAndroid Build Coastguard Worker     }
359*d9f75844SAndroid Build Coastguard Worker     return false;
360*d9f75844SAndroid Build Coastguard Worker   }
361*d9f75844SAndroid Build Coastguard Worker 
362*d9f75844SAndroid Build Coastguard Worker   peer_certificate_digest_value_.SetData(digest_val, digest_len);
363*d9f75844SAndroid Build Coastguard Worker   peer_certificate_digest_algorithm_ = std::string(digest_alg);
364*d9f75844SAndroid Build Coastguard Worker 
365*d9f75844SAndroid Build Coastguard Worker   if (!peer_cert_chain_) {
366*d9f75844SAndroid Build Coastguard Worker     // Normal case, where the digest is set before we obtain the certificate
367*d9f75844SAndroid Build Coastguard Worker     // from the handshake.
368*d9f75844SAndroid Build Coastguard Worker     return true;
369*d9f75844SAndroid Build Coastguard Worker   }
370*d9f75844SAndroid Build Coastguard Worker 
371*d9f75844SAndroid Build Coastguard Worker   if (!VerifyPeerCertificate()) {
372*d9f75844SAndroid Build Coastguard Worker     Error("SetPeerCertificateDigest", -1, SSL_AD_BAD_CERTIFICATE, false);
373*d9f75844SAndroid Build Coastguard Worker     if (error) {
374*d9f75844SAndroid Build Coastguard Worker       *error = SSLPeerCertificateDigestError::VERIFICATION_FAILED;
375*d9f75844SAndroid Build Coastguard Worker     }
376*d9f75844SAndroid Build Coastguard Worker     return false;
377*d9f75844SAndroid Build Coastguard Worker   }
378*d9f75844SAndroid Build Coastguard Worker 
379*d9f75844SAndroid Build Coastguard Worker   if (state_ == SSL_CONNECTED) {
380*d9f75844SAndroid Build Coastguard Worker     // Post the event asynchronously to unwind the stack. The caller
381*d9f75844SAndroid Build Coastguard Worker     // of ContinueSSL may be the same object listening for these
382*d9f75844SAndroid Build Coastguard Worker     // events and may not be prepared for reentrancy.
383*d9f75844SAndroid Build Coastguard Worker     PostEvent(SE_OPEN | SE_READ | SE_WRITE, 0);
384*d9f75844SAndroid Build Coastguard Worker   }
385*d9f75844SAndroid Build Coastguard Worker 
386*d9f75844SAndroid Build Coastguard Worker   return true;
387*d9f75844SAndroid Build Coastguard Worker }
388*d9f75844SAndroid Build Coastguard Worker 
SslCipherSuiteToName(int cipher_suite)389*d9f75844SAndroid Build Coastguard Worker std::string OpenSSLStreamAdapter::SslCipherSuiteToName(int cipher_suite) {
390*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
391*d9f75844SAndroid Build Coastguard Worker   const SSL_CIPHER* ssl_cipher = SSL_get_cipher_by_value(cipher_suite);
392*d9f75844SAndroid Build Coastguard Worker   if (!ssl_cipher) {
393*d9f75844SAndroid Build Coastguard Worker     return std::string();
394*d9f75844SAndroid Build Coastguard Worker   }
395*d9f75844SAndroid Build Coastguard Worker   return SSL_CIPHER_standard_name(ssl_cipher);
396*d9f75844SAndroid Build Coastguard Worker #else
397*d9f75844SAndroid Build Coastguard Worker   const int openssl_cipher_id = 0x03000000L | cipher_suite;
398*d9f75844SAndroid Build Coastguard Worker   for (const SslCipherMapEntry* entry = kSslCipherMap; entry->rfc_name;
399*d9f75844SAndroid Build Coastguard Worker        ++entry) {
400*d9f75844SAndroid Build Coastguard Worker     if (openssl_cipher_id == static_cast<int>(entry->openssl_id)) {
401*d9f75844SAndroid Build Coastguard Worker       return entry->rfc_name;
402*d9f75844SAndroid Build Coastguard Worker     }
403*d9f75844SAndroid Build Coastguard Worker   }
404*d9f75844SAndroid Build Coastguard Worker   return std::string();
405*d9f75844SAndroid Build Coastguard Worker #endif
406*d9f75844SAndroid Build Coastguard Worker }
407*d9f75844SAndroid Build Coastguard Worker 
GetSslCipherSuite(int * cipher_suite)408*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::GetSslCipherSuite(int* cipher_suite) {
409*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_CONNECTED) {
410*d9f75844SAndroid Build Coastguard Worker     return false;
411*d9f75844SAndroid Build Coastguard Worker   }
412*d9f75844SAndroid Build Coastguard Worker 
413*d9f75844SAndroid Build Coastguard Worker   const SSL_CIPHER* current_cipher = SSL_get_current_cipher(ssl_);
414*d9f75844SAndroid Build Coastguard Worker   if (current_cipher == nullptr) {
415*d9f75844SAndroid Build Coastguard Worker     return false;
416*d9f75844SAndroid Build Coastguard Worker   }
417*d9f75844SAndroid Build Coastguard Worker 
418*d9f75844SAndroid Build Coastguard Worker   *cipher_suite = static_cast<uint16_t>(SSL_CIPHER_get_id(current_cipher));
419*d9f75844SAndroid Build Coastguard Worker   return true;
420*d9f75844SAndroid Build Coastguard Worker }
421*d9f75844SAndroid Build Coastguard Worker 
GetSslVersion() const422*d9f75844SAndroid Build Coastguard Worker SSLProtocolVersion OpenSSLStreamAdapter::GetSslVersion() const {
423*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_CONNECTED) {
424*d9f75844SAndroid Build Coastguard Worker     return SSL_PROTOCOL_NOT_GIVEN;
425*d9f75844SAndroid Build Coastguard Worker   }
426*d9f75844SAndroid Build Coastguard Worker 
427*d9f75844SAndroid Build Coastguard Worker   int ssl_version = SSL_version(ssl_);
428*d9f75844SAndroid Build Coastguard Worker   if (ssl_mode_ == SSL_MODE_DTLS) {
429*d9f75844SAndroid Build Coastguard Worker     if (ssl_version == DTLS1_VERSION) {
430*d9f75844SAndroid Build Coastguard Worker       return SSL_PROTOCOL_DTLS_10;
431*d9f75844SAndroid Build Coastguard Worker     } else if (ssl_version == DTLS1_2_VERSION) {
432*d9f75844SAndroid Build Coastguard Worker       return SSL_PROTOCOL_DTLS_12;
433*d9f75844SAndroid Build Coastguard Worker     }
434*d9f75844SAndroid Build Coastguard Worker   } else {
435*d9f75844SAndroid Build Coastguard Worker     if (ssl_version == TLS1_VERSION) {
436*d9f75844SAndroid Build Coastguard Worker       return SSL_PROTOCOL_TLS_10;
437*d9f75844SAndroid Build Coastguard Worker     } else if (ssl_version == TLS1_1_VERSION) {
438*d9f75844SAndroid Build Coastguard Worker       return SSL_PROTOCOL_TLS_11;
439*d9f75844SAndroid Build Coastguard Worker     } else if (ssl_version == TLS1_2_VERSION) {
440*d9f75844SAndroid Build Coastguard Worker       return SSL_PROTOCOL_TLS_12;
441*d9f75844SAndroid Build Coastguard Worker     }
442*d9f75844SAndroid Build Coastguard Worker   }
443*d9f75844SAndroid Build Coastguard Worker 
444*d9f75844SAndroid Build Coastguard Worker   return SSL_PROTOCOL_NOT_GIVEN;
445*d9f75844SAndroid Build Coastguard Worker }
446*d9f75844SAndroid Build Coastguard Worker 
GetSslVersionBytes(int * version) const447*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::GetSslVersionBytes(int* version) const {
448*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_CONNECTED) {
449*d9f75844SAndroid Build Coastguard Worker     return false;
450*d9f75844SAndroid Build Coastguard Worker   }
451*d9f75844SAndroid Build Coastguard Worker   *version = SSL_version(ssl_);
452*d9f75844SAndroid Build Coastguard Worker   return true;
453*d9f75844SAndroid Build Coastguard Worker }
454*d9f75844SAndroid Build Coastguard Worker 
455*d9f75844SAndroid Build Coastguard Worker // Key Extractor interface
ExportKeyingMaterial(absl::string_view label,const uint8_t * context,size_t context_len,bool use_context,uint8_t * result,size_t result_len)456*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::ExportKeyingMaterial(absl::string_view label,
457*d9f75844SAndroid Build Coastguard Worker                                                 const uint8_t* context,
458*d9f75844SAndroid Build Coastguard Worker                                                 size_t context_len,
459*d9f75844SAndroid Build Coastguard Worker                                                 bool use_context,
460*d9f75844SAndroid Build Coastguard Worker                                                 uint8_t* result,
461*d9f75844SAndroid Build Coastguard Worker                                                 size_t result_len) {
462*d9f75844SAndroid Build Coastguard Worker   if (SSL_export_keying_material(ssl_, result, result_len, label.data(),
463*d9f75844SAndroid Build Coastguard Worker                                  label.length(), context, context_len,
464*d9f75844SAndroid Build Coastguard Worker                                  use_context) != 1) {
465*d9f75844SAndroid Build Coastguard Worker     return false;
466*d9f75844SAndroid Build Coastguard Worker   }
467*d9f75844SAndroid Build Coastguard Worker   return true;
468*d9f75844SAndroid Build Coastguard Worker }
469*d9f75844SAndroid Build Coastguard Worker 
SetDtlsSrtpCryptoSuites(const std::vector<int> & ciphers)470*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
471*d9f75844SAndroid Build Coastguard Worker     const std::vector<int>& ciphers) {
472*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_NONE) {
473*d9f75844SAndroid Build Coastguard Worker     return false;
474*d9f75844SAndroid Build Coastguard Worker   }
475*d9f75844SAndroid Build Coastguard Worker 
476*d9f75844SAndroid Build Coastguard Worker   std::string internal_ciphers;
477*d9f75844SAndroid Build Coastguard Worker   for (const int cipher : ciphers) {
478*d9f75844SAndroid Build Coastguard Worker     bool found = false;
479*d9f75844SAndroid Build Coastguard Worker     for (const auto& entry : kSrtpCipherMap) {
480*d9f75844SAndroid Build Coastguard Worker       if (cipher == entry.id) {
481*d9f75844SAndroid Build Coastguard Worker         found = true;
482*d9f75844SAndroid Build Coastguard Worker         if (!internal_ciphers.empty()) {
483*d9f75844SAndroid Build Coastguard Worker           internal_ciphers += ":";
484*d9f75844SAndroid Build Coastguard Worker         }
485*d9f75844SAndroid Build Coastguard Worker         internal_ciphers += entry.internal_name;
486*d9f75844SAndroid Build Coastguard Worker         break;
487*d9f75844SAndroid Build Coastguard Worker       }
488*d9f75844SAndroid Build Coastguard Worker     }
489*d9f75844SAndroid Build Coastguard Worker 
490*d9f75844SAndroid Build Coastguard Worker     if (!found) {
491*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Could not find cipher: " << cipher;
492*d9f75844SAndroid Build Coastguard Worker       return false;
493*d9f75844SAndroid Build Coastguard Worker     }
494*d9f75844SAndroid Build Coastguard Worker   }
495*d9f75844SAndroid Build Coastguard Worker 
496*d9f75844SAndroid Build Coastguard Worker   if (internal_ciphers.empty()) {
497*d9f75844SAndroid Build Coastguard Worker     return false;
498*d9f75844SAndroid Build Coastguard Worker   }
499*d9f75844SAndroid Build Coastguard Worker 
500*d9f75844SAndroid Build Coastguard Worker   srtp_ciphers_ = internal_ciphers;
501*d9f75844SAndroid Build Coastguard Worker   return true;
502*d9f75844SAndroid Build Coastguard Worker }
503*d9f75844SAndroid Build Coastguard Worker 
GetDtlsSrtpCryptoSuite(int * crypto_suite)504*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::GetDtlsSrtpCryptoSuite(int* crypto_suite) {
505*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == SSL_CONNECTED);
506*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_CONNECTED) {
507*d9f75844SAndroid Build Coastguard Worker     return false;
508*d9f75844SAndroid Build Coastguard Worker   }
509*d9f75844SAndroid Build Coastguard Worker 
510*d9f75844SAndroid Build Coastguard Worker   const SRTP_PROTECTION_PROFILE* srtp_profile =
511*d9f75844SAndroid Build Coastguard Worker       SSL_get_selected_srtp_profile(ssl_);
512*d9f75844SAndroid Build Coastguard Worker 
513*d9f75844SAndroid Build Coastguard Worker   if (!srtp_profile) {
514*d9f75844SAndroid Build Coastguard Worker     return false;
515*d9f75844SAndroid Build Coastguard Worker   }
516*d9f75844SAndroid Build Coastguard Worker 
517*d9f75844SAndroid Build Coastguard Worker   *crypto_suite = srtp_profile->id;
518*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!SrtpCryptoSuiteToName(*crypto_suite).empty());
519*d9f75844SAndroid Build Coastguard Worker   return true;
520*d9f75844SAndroid Build Coastguard Worker }
521*d9f75844SAndroid Build Coastguard Worker 
IsTlsConnected()522*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::IsTlsConnected() {
523*d9f75844SAndroid Build Coastguard Worker   return state_ == SSL_CONNECTED;
524*d9f75844SAndroid Build Coastguard Worker }
525*d9f75844SAndroid Build Coastguard Worker 
StartSSL()526*d9f75844SAndroid Build Coastguard Worker int OpenSSLStreamAdapter::StartSSL() {
527*d9f75844SAndroid Build Coastguard Worker   // Don't allow StartSSL to be called twice.
528*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_NONE) {
529*d9f75844SAndroid Build Coastguard Worker     return -1;
530*d9f75844SAndroid Build Coastguard Worker   }
531*d9f75844SAndroid Build Coastguard Worker 
532*d9f75844SAndroid Build Coastguard Worker   if (stream_->GetState() != SS_OPEN) {
533*d9f75844SAndroid Build Coastguard Worker     state_ = SSL_WAIT;
534*d9f75844SAndroid Build Coastguard Worker     return 0;
535*d9f75844SAndroid Build Coastguard Worker   }
536*d9f75844SAndroid Build Coastguard Worker 
537*d9f75844SAndroid Build Coastguard Worker   state_ = SSL_CONNECTING;
538*d9f75844SAndroid Build Coastguard Worker   if (int err = BeginSSL()) {
539*d9f75844SAndroid Build Coastguard Worker     Error("BeginSSL", err, 0, false);
540*d9f75844SAndroid Build Coastguard Worker     return err;
541*d9f75844SAndroid Build Coastguard Worker   }
542*d9f75844SAndroid Build Coastguard Worker 
543*d9f75844SAndroid Build Coastguard Worker   return 0;
544*d9f75844SAndroid Build Coastguard Worker }
545*d9f75844SAndroid Build Coastguard Worker 
SetMode(SSLMode mode)546*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetMode(SSLMode mode) {
547*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == SSL_NONE);
548*d9f75844SAndroid Build Coastguard Worker   ssl_mode_ = mode;
549*d9f75844SAndroid Build Coastguard Worker }
550*d9f75844SAndroid Build Coastguard Worker 
SetMaxProtocolVersion(SSLProtocolVersion version)551*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetMaxProtocolVersion(SSLProtocolVersion version) {
552*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ssl_ctx_ == nullptr);
553*d9f75844SAndroid Build Coastguard Worker   ssl_max_version_ = version;
554*d9f75844SAndroid Build Coastguard Worker }
555*d9f75844SAndroid Build Coastguard Worker 
SetInitialRetransmissionTimeout(int timeout_ms)556*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetInitialRetransmissionTimeout(int timeout_ms) {
557*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ssl_ctx_ == nullptr);
558*d9f75844SAndroid Build Coastguard Worker   dtls_handshake_timeout_ms_ = timeout_ms;
559*d9f75844SAndroid Build Coastguard Worker }
560*d9f75844SAndroid Build Coastguard Worker 
561*d9f75844SAndroid Build Coastguard Worker //
562*d9f75844SAndroid Build Coastguard Worker // StreamInterface Implementation
563*d9f75844SAndroid Build Coastguard Worker //
Write(rtc::ArrayView<const uint8_t> data,size_t & written,int & error)564*d9f75844SAndroid Build Coastguard Worker StreamResult OpenSSLStreamAdapter::Write(rtc::ArrayView<const uint8_t> data,
565*d9f75844SAndroid Build Coastguard Worker                                          size_t& written,
566*d9f75844SAndroid Build Coastguard Worker                                          int& error) {
567*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_VERBOSE) << "OpenSSLStreamAdapter::Write(" << data.size() << ")";
568*d9f75844SAndroid Build Coastguard Worker 
569*d9f75844SAndroid Build Coastguard Worker   switch (state_) {
570*d9f75844SAndroid Build Coastguard Worker     case SSL_NONE:
571*d9f75844SAndroid Build Coastguard Worker       // pass-through in clear text
572*d9f75844SAndroid Build Coastguard Worker       return stream_->Write(data, written, error);
573*d9f75844SAndroid Build Coastguard Worker 
574*d9f75844SAndroid Build Coastguard Worker     case SSL_WAIT:
575*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTING:
576*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
577*d9f75844SAndroid Build Coastguard Worker 
578*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTED:
579*d9f75844SAndroid Build Coastguard Worker       if (WaitingToVerifyPeerCertificate()) {
580*d9f75844SAndroid Build Coastguard Worker         return SR_BLOCK;
581*d9f75844SAndroid Build Coastguard Worker       }
582*d9f75844SAndroid Build Coastguard Worker       break;
583*d9f75844SAndroid Build Coastguard Worker 
584*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR:
585*d9f75844SAndroid Build Coastguard Worker     case SSL_CLOSED:
586*d9f75844SAndroid Build Coastguard Worker     default:
587*d9f75844SAndroid Build Coastguard Worker       error = ssl_error_code_;
588*d9f75844SAndroid Build Coastguard Worker       return SR_ERROR;
589*d9f75844SAndroid Build Coastguard Worker   }
590*d9f75844SAndroid Build Coastguard Worker 
591*d9f75844SAndroid Build Coastguard Worker   // OpenSSL will return an error if we try to write zero bytes
592*d9f75844SAndroid Build Coastguard Worker   if (data.size() == 0) {
593*d9f75844SAndroid Build Coastguard Worker     written = 0;
594*d9f75844SAndroid Build Coastguard Worker     return SR_SUCCESS;
595*d9f75844SAndroid Build Coastguard Worker   }
596*d9f75844SAndroid Build Coastguard Worker 
597*d9f75844SAndroid Build Coastguard Worker   ssl_write_needs_read_ = false;
598*d9f75844SAndroid Build Coastguard Worker 
599*d9f75844SAndroid Build Coastguard Worker   int code = SSL_write(ssl_, data.data(), checked_cast<int>(data.size()));
600*d9f75844SAndroid Build Coastguard Worker   int ssl_error = SSL_get_error(ssl_, code);
601*d9f75844SAndroid Build Coastguard Worker   switch (ssl_error) {
602*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_NONE:
603*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- success";
604*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_GT(code, 0);
605*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_LE(code, data.size());
606*d9f75844SAndroid Build Coastguard Worker       written = code;
607*d9f75844SAndroid Build Coastguard Worker       return SR_SUCCESS;
608*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_READ:
609*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want read";
610*d9f75844SAndroid Build Coastguard Worker       ssl_write_needs_read_ = true;
611*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
612*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_WRITE:
613*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want write";
614*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
615*d9f75844SAndroid Build Coastguard Worker 
616*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_ZERO_RETURN:
617*d9f75844SAndroid Build Coastguard Worker     default:
618*d9f75844SAndroid Build Coastguard Worker       Error("SSL_write", (ssl_error ? ssl_error : -1), 0, false);
619*d9f75844SAndroid Build Coastguard Worker       error = ssl_error_code_;
620*d9f75844SAndroid Build Coastguard Worker       return SR_ERROR;
621*d9f75844SAndroid Build Coastguard Worker   }
622*d9f75844SAndroid Build Coastguard Worker   // not reached
623*d9f75844SAndroid Build Coastguard Worker }
624*d9f75844SAndroid Build Coastguard Worker 
Read(rtc::ArrayView<uint8_t> data,size_t & read,int & error)625*d9f75844SAndroid Build Coastguard Worker StreamResult OpenSSLStreamAdapter::Read(rtc::ArrayView<uint8_t> data,
626*d9f75844SAndroid Build Coastguard Worker                                         size_t& read,
627*d9f75844SAndroid Build Coastguard Worker                                         int& error) {
628*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_VERBOSE) << "OpenSSLStreamAdapter::Read(" << data.size() << ")";
629*d9f75844SAndroid Build Coastguard Worker   switch (state_) {
630*d9f75844SAndroid Build Coastguard Worker     case SSL_NONE:
631*d9f75844SAndroid Build Coastguard Worker       // pass-through in clear text
632*d9f75844SAndroid Build Coastguard Worker       return stream_->Read(data, read, error);
633*d9f75844SAndroid Build Coastguard Worker     case SSL_WAIT:
634*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTING:
635*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
636*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTED:
637*d9f75844SAndroid Build Coastguard Worker       if (WaitingToVerifyPeerCertificate()) {
638*d9f75844SAndroid Build Coastguard Worker         return SR_BLOCK;
639*d9f75844SAndroid Build Coastguard Worker       }
640*d9f75844SAndroid Build Coastguard Worker       break;
641*d9f75844SAndroid Build Coastguard Worker     case SSL_CLOSED:
642*d9f75844SAndroid Build Coastguard Worker       return SR_EOS;
643*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR:
644*d9f75844SAndroid Build Coastguard Worker     default:
645*d9f75844SAndroid Build Coastguard Worker       error = ssl_error_code_;
646*d9f75844SAndroid Build Coastguard Worker       return SR_ERROR;
647*d9f75844SAndroid Build Coastguard Worker   }
648*d9f75844SAndroid Build Coastguard Worker 
649*d9f75844SAndroid Build Coastguard Worker   // Don't trust OpenSSL with zero byte reads
650*d9f75844SAndroid Build Coastguard Worker   if (data.size() == 0) {
651*d9f75844SAndroid Build Coastguard Worker     read = 0;
652*d9f75844SAndroid Build Coastguard Worker     return SR_SUCCESS;
653*d9f75844SAndroid Build Coastguard Worker   }
654*d9f75844SAndroid Build Coastguard Worker 
655*d9f75844SAndroid Build Coastguard Worker   ssl_read_needs_write_ = false;
656*d9f75844SAndroid Build Coastguard Worker 
657*d9f75844SAndroid Build Coastguard Worker   const int code = SSL_read(ssl_, data.data(), checked_cast<int>(data.size()));
658*d9f75844SAndroid Build Coastguard Worker   const int ssl_error = SSL_get_error(ssl_, code);
659*d9f75844SAndroid Build Coastguard Worker 
660*d9f75844SAndroid Build Coastguard Worker   switch (ssl_error) {
661*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_NONE:
662*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- success";
663*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_GT(code, 0);
664*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_LE(code, data.size());
665*d9f75844SAndroid Build Coastguard Worker       read = code;
666*d9f75844SAndroid Build Coastguard Worker 
667*d9f75844SAndroid Build Coastguard Worker       if (ssl_mode_ == SSL_MODE_DTLS) {
668*d9f75844SAndroid Build Coastguard Worker         // Enforce atomic reads -- this is a short read
669*d9f75844SAndroid Build Coastguard Worker         unsigned int pending = SSL_pending(ssl_);
670*d9f75844SAndroid Build Coastguard Worker 
671*d9f75844SAndroid Build Coastguard Worker         if (pending) {
672*d9f75844SAndroid Build Coastguard Worker           RTC_DLOG(LS_INFO) << " -- short DTLS read. flushing";
673*d9f75844SAndroid Build Coastguard Worker           FlushInput(pending);
674*d9f75844SAndroid Build Coastguard Worker           error = SSE_MSG_TRUNC;
675*d9f75844SAndroid Build Coastguard Worker           return SR_ERROR;
676*d9f75844SAndroid Build Coastguard Worker         }
677*d9f75844SAndroid Build Coastguard Worker       }
678*d9f75844SAndroid Build Coastguard Worker       return SR_SUCCESS;
679*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_READ:
680*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want read";
681*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
682*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_WRITE:
683*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want write";
684*d9f75844SAndroid Build Coastguard Worker       ssl_read_needs_write_ = true;
685*d9f75844SAndroid Build Coastguard Worker       return SR_BLOCK;
686*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_ZERO_RETURN:
687*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- remote side closed";
688*d9f75844SAndroid Build Coastguard Worker       Close();
689*d9f75844SAndroid Build Coastguard Worker       return SR_EOS;
690*d9f75844SAndroid Build Coastguard Worker     default:
691*d9f75844SAndroid Build Coastguard Worker       Error("SSL_read", (ssl_error ? ssl_error : -1), 0, false);
692*d9f75844SAndroid Build Coastguard Worker       error = ssl_error_code_;
693*d9f75844SAndroid Build Coastguard Worker       return SR_ERROR;
694*d9f75844SAndroid Build Coastguard Worker   }
695*d9f75844SAndroid Build Coastguard Worker   // not reached
696*d9f75844SAndroid Build Coastguard Worker }
697*d9f75844SAndroid Build Coastguard Worker 
FlushInput(unsigned int left)698*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::FlushInput(unsigned int left) {
699*d9f75844SAndroid Build Coastguard Worker   unsigned char buf[2048];
700*d9f75844SAndroid Build Coastguard Worker 
701*d9f75844SAndroid Build Coastguard Worker   while (left) {
702*d9f75844SAndroid Build Coastguard Worker     // This should always succeed
703*d9f75844SAndroid Build Coastguard Worker     const int toread = (sizeof(buf) < left) ? sizeof(buf) : left;
704*d9f75844SAndroid Build Coastguard Worker     const int code = SSL_read(ssl_, buf, toread);
705*d9f75844SAndroid Build Coastguard Worker 
706*d9f75844SAndroid Build Coastguard Worker     const int ssl_error = SSL_get_error(ssl_, code);
707*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(ssl_error == SSL_ERROR_NONE);
708*d9f75844SAndroid Build Coastguard Worker 
709*d9f75844SAndroid Build Coastguard Worker     if (ssl_error != SSL_ERROR_NONE) {
710*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error " << code;
711*d9f75844SAndroid Build Coastguard Worker       Error("SSL_read", (ssl_error ? ssl_error : -1), 0, false);
712*d9f75844SAndroid Build Coastguard Worker       return;
713*d9f75844SAndroid Build Coastguard Worker     }
714*d9f75844SAndroid Build Coastguard Worker 
715*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_VERBOSE) << " -- flushed " << code << " bytes";
716*d9f75844SAndroid Build Coastguard Worker     left -= code;
717*d9f75844SAndroid Build Coastguard Worker   }
718*d9f75844SAndroid Build Coastguard Worker }
719*d9f75844SAndroid Build Coastguard Worker 
Close()720*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::Close() {
721*d9f75844SAndroid Build Coastguard Worker   Cleanup(0);
722*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == SSL_CLOSED || state_ == SSL_ERROR);
723*d9f75844SAndroid Build Coastguard Worker   // When we're closed at SSL layer, also close the stream level which
724*d9f75844SAndroid Build Coastguard Worker   // performs necessary clean up. Otherwise, a new incoming packet after
725*d9f75844SAndroid Build Coastguard Worker   // this could overflow the stream buffer.
726*d9f75844SAndroid Build Coastguard Worker   stream_->Close();
727*d9f75844SAndroid Build Coastguard Worker }
728*d9f75844SAndroid Build Coastguard Worker 
GetState() const729*d9f75844SAndroid Build Coastguard Worker StreamState OpenSSLStreamAdapter::GetState() const {
730*d9f75844SAndroid Build Coastguard Worker   switch (state_) {
731*d9f75844SAndroid Build Coastguard Worker     case SSL_WAIT:
732*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTING:
733*d9f75844SAndroid Build Coastguard Worker       return SS_OPENING;
734*d9f75844SAndroid Build Coastguard Worker     case SSL_CONNECTED:
735*d9f75844SAndroid Build Coastguard Worker       if (WaitingToVerifyPeerCertificate()) {
736*d9f75844SAndroid Build Coastguard Worker         return SS_OPENING;
737*d9f75844SAndroid Build Coastguard Worker       }
738*d9f75844SAndroid Build Coastguard Worker       return SS_OPEN;
739*d9f75844SAndroid Build Coastguard Worker     default:
740*d9f75844SAndroid Build Coastguard Worker       return SS_CLOSED;
741*d9f75844SAndroid Build Coastguard Worker   }
742*d9f75844SAndroid Build Coastguard Worker   // not reached
743*d9f75844SAndroid Build Coastguard Worker }
744*d9f75844SAndroid Build Coastguard Worker 
OnEvent(StreamInterface * stream,int events,int err)745*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::OnEvent(StreamInterface* stream,
746*d9f75844SAndroid Build Coastguard Worker                                    int events,
747*d9f75844SAndroid Build Coastguard Worker                                    int err) {
748*d9f75844SAndroid Build Coastguard Worker   int events_to_signal = 0;
749*d9f75844SAndroid Build Coastguard Worker   int signal_error = 0;
750*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(stream == stream_.get());
751*d9f75844SAndroid Build Coastguard Worker 
752*d9f75844SAndroid Build Coastguard Worker   if ((events & SE_OPEN)) {
753*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent SE_OPEN";
754*d9f75844SAndroid Build Coastguard Worker     if (state_ != SSL_WAIT) {
755*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(state_ == SSL_NONE);
756*d9f75844SAndroid Build Coastguard Worker       events_to_signal |= SE_OPEN;
757*d9f75844SAndroid Build Coastguard Worker     } else {
758*d9f75844SAndroid Build Coastguard Worker       state_ = SSL_CONNECTING;
759*d9f75844SAndroid Build Coastguard Worker       if (int err = BeginSSL()) {
760*d9f75844SAndroid Build Coastguard Worker         Error("BeginSSL", err, 0, true);
761*d9f75844SAndroid Build Coastguard Worker         return;
762*d9f75844SAndroid Build Coastguard Worker       }
763*d9f75844SAndroid Build Coastguard Worker     }
764*d9f75844SAndroid Build Coastguard Worker   }
765*d9f75844SAndroid Build Coastguard Worker 
766*d9f75844SAndroid Build Coastguard Worker   if ((events & (SE_READ | SE_WRITE))) {
767*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent"
768*d9f75844SAndroid Build Coastguard Worker                          << ((events & SE_READ) ? " SE_READ" : "")
769*d9f75844SAndroid Build Coastguard Worker                          << ((events & SE_WRITE) ? " SE_WRITE" : "");
770*d9f75844SAndroid Build Coastguard Worker     if (state_ == SSL_NONE) {
771*d9f75844SAndroid Build Coastguard Worker       events_to_signal |= events & (SE_READ | SE_WRITE);
772*d9f75844SAndroid Build Coastguard Worker     } else if (state_ == SSL_CONNECTING) {
773*d9f75844SAndroid Build Coastguard Worker       if (int err = ContinueSSL()) {
774*d9f75844SAndroid Build Coastguard Worker         Error("ContinueSSL", err, 0, true);
775*d9f75844SAndroid Build Coastguard Worker         return;
776*d9f75844SAndroid Build Coastguard Worker       }
777*d9f75844SAndroid Build Coastguard Worker     } else if (state_ == SSL_CONNECTED) {
778*d9f75844SAndroid Build Coastguard Worker       if (((events & SE_READ) && ssl_write_needs_read_) ||
779*d9f75844SAndroid Build Coastguard Worker           (events & SE_WRITE)) {
780*d9f75844SAndroid Build Coastguard Worker         RTC_DLOG(LS_VERBOSE) << " -- onStreamWriteable";
781*d9f75844SAndroid Build Coastguard Worker         events_to_signal |= SE_WRITE;
782*d9f75844SAndroid Build Coastguard Worker       }
783*d9f75844SAndroid Build Coastguard Worker       if (((events & SE_WRITE) && ssl_read_needs_write_) ||
784*d9f75844SAndroid Build Coastguard Worker           (events & SE_READ)) {
785*d9f75844SAndroid Build Coastguard Worker         RTC_DLOG(LS_VERBOSE) << " -- onStreamReadable";
786*d9f75844SAndroid Build Coastguard Worker         events_to_signal |= SE_READ;
787*d9f75844SAndroid Build Coastguard Worker       }
788*d9f75844SAndroid Build Coastguard Worker     }
789*d9f75844SAndroid Build Coastguard Worker   }
790*d9f75844SAndroid Build Coastguard Worker 
791*d9f75844SAndroid Build Coastguard Worker   if ((events & SE_CLOSE)) {
792*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_VERBOSE) << "OpenSSLStreamAdapter::OnEvent(SE_CLOSE, " << err
793*d9f75844SAndroid Build Coastguard Worker                          << ")";
794*d9f75844SAndroid Build Coastguard Worker     Cleanup(0);
795*d9f75844SAndroid Build Coastguard Worker     events_to_signal |= SE_CLOSE;
796*d9f75844SAndroid Build Coastguard Worker     // SE_CLOSE is the only event that uses the final parameter to OnEvent().
797*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(signal_error == 0);
798*d9f75844SAndroid Build Coastguard Worker     signal_error = err;
799*d9f75844SAndroid Build Coastguard Worker   }
800*d9f75844SAndroid Build Coastguard Worker 
801*d9f75844SAndroid Build Coastguard Worker   if (events_to_signal) {
802*d9f75844SAndroid Build Coastguard Worker     // Note that the adapter presents itself as the origin of the stream events,
803*d9f75844SAndroid Build Coastguard Worker     // since users of the adapter may not recognize the adapted object.
804*d9f75844SAndroid Build Coastguard Worker     SignalEvent(this, events_to_signal, signal_error);
805*d9f75844SAndroid Build Coastguard Worker   }
806*d9f75844SAndroid Build Coastguard Worker }
807*d9f75844SAndroid Build Coastguard Worker 
PostEvent(int events,int err)808*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::PostEvent(int events, int err) {
809*d9f75844SAndroid Build Coastguard Worker   owner_->PostTask(SafeTask(task_safety_.flag(), [this, events, err]() {
810*d9f75844SAndroid Build Coastguard Worker     SignalEvent(this, events, err);
811*d9f75844SAndroid Build Coastguard Worker   }));
812*d9f75844SAndroid Build Coastguard Worker }
813*d9f75844SAndroid Build Coastguard Worker 
SetTimeout(int delay_ms)814*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::SetTimeout(int delay_ms) {
815*d9f75844SAndroid Build Coastguard Worker   // We need to accept 0 delay here as well as >0 delay, because
816*d9f75844SAndroid Build Coastguard Worker   // DTLSv1_get_timeout seems to frequently return 0 ms.
817*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(delay_ms, 0);
818*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(!timeout_task_.Running());
819*d9f75844SAndroid Build Coastguard Worker 
820*d9f75844SAndroid Build Coastguard Worker   timeout_task_ = webrtc::RepeatingTaskHandle::DelayedStart(
821*d9f75844SAndroid Build Coastguard Worker       owner_, webrtc::TimeDelta::Millis(delay_ms),
822*d9f75844SAndroid Build Coastguard Worker       [flag = task_safety_.flag(), this]() {
823*d9f75844SAndroid Build Coastguard Worker         if (flag->alive()) {
824*d9f75844SAndroid Build Coastguard Worker           RTC_DLOG(LS_INFO) << "DTLS timeout expired";
825*d9f75844SAndroid Build Coastguard Worker           timeout_task_.Stop();
826*d9f75844SAndroid Build Coastguard Worker           int res = DTLSv1_handle_timeout(ssl_);
827*d9f75844SAndroid Build Coastguard Worker           if (res > 0) {
828*d9f75844SAndroid Build Coastguard Worker             RTC_LOG(LS_INFO) << "DTLS retransmission";
829*d9f75844SAndroid Build Coastguard Worker           } else if (res < 0) {
830*d9f75844SAndroid Build Coastguard Worker             RTC_LOG(LS_INFO) << "DTLSv1_handle_timeout() return -1";
831*d9f75844SAndroid Build Coastguard Worker             Error("DTLSv1_handle_timeout", res, -1, true);
832*d9f75844SAndroid Build Coastguard Worker             return webrtc::TimeDelta::PlusInfinity();
833*d9f75844SAndroid Build Coastguard Worker           }
834*d9f75844SAndroid Build Coastguard Worker           ContinueSSL();
835*d9f75844SAndroid Build Coastguard Worker         } else {
836*d9f75844SAndroid Build Coastguard Worker           RTC_DCHECK_NOTREACHED();
837*d9f75844SAndroid Build Coastguard Worker         }
838*d9f75844SAndroid Build Coastguard Worker         // This callback will never run again (stopped above).
839*d9f75844SAndroid Build Coastguard Worker         return webrtc::TimeDelta::PlusInfinity();
840*d9f75844SAndroid Build Coastguard Worker       });
841*d9f75844SAndroid Build Coastguard Worker }
842*d9f75844SAndroid Build Coastguard Worker 
BeginSSL()843*d9f75844SAndroid Build Coastguard Worker int OpenSSLStreamAdapter::BeginSSL() {
844*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == SSL_CONNECTING);
845*d9f75844SAndroid Build Coastguard Worker   // The underlying stream has opened.
846*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_INFO) << "BeginSSL with peer.";
847*d9f75844SAndroid Build Coastguard Worker 
848*d9f75844SAndroid Build Coastguard Worker   BIO* bio = nullptr;
849*d9f75844SAndroid Build Coastguard Worker 
850*d9f75844SAndroid Build Coastguard Worker   // First set up the context.
851*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ssl_ctx_ == nullptr);
852*d9f75844SAndroid Build Coastguard Worker   ssl_ctx_ = SetupSSLContext();
853*d9f75844SAndroid Build Coastguard Worker   if (!ssl_ctx_) {
854*d9f75844SAndroid Build Coastguard Worker     return -1;
855*d9f75844SAndroid Build Coastguard Worker   }
856*d9f75844SAndroid Build Coastguard Worker 
857*d9f75844SAndroid Build Coastguard Worker   bio = BIO_new_stream(stream_.get());
858*d9f75844SAndroid Build Coastguard Worker   if (!bio) {
859*d9f75844SAndroid Build Coastguard Worker     return -1;
860*d9f75844SAndroid Build Coastguard Worker   }
861*d9f75844SAndroid Build Coastguard Worker 
862*d9f75844SAndroid Build Coastguard Worker   ssl_ = SSL_new(ssl_ctx_);
863*d9f75844SAndroid Build Coastguard Worker   if (!ssl_) {
864*d9f75844SAndroid Build Coastguard Worker     BIO_free(bio);
865*d9f75844SAndroid Build Coastguard Worker     return -1;
866*d9f75844SAndroid Build Coastguard Worker   }
867*d9f75844SAndroid Build Coastguard Worker 
868*d9f75844SAndroid Build Coastguard Worker   SSL_set_app_data(ssl_, this);
869*d9f75844SAndroid Build Coastguard Worker 
870*d9f75844SAndroid Build Coastguard Worker   SSL_set_bio(ssl_, bio, bio);  // the SSL object owns the bio now.
871*d9f75844SAndroid Build Coastguard Worker   if (ssl_mode_ == SSL_MODE_DTLS) {
872*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
873*d9f75844SAndroid Build Coastguard Worker     DTLSv1_set_initial_timeout_duration(ssl_, dtls_handshake_timeout_ms_);
874*d9f75844SAndroid Build Coastguard Worker #else
875*d9f75844SAndroid Build Coastguard Worker     // Enable read-ahead for DTLS so whole packets are read from internal BIO
876*d9f75844SAndroid Build Coastguard Worker     // before parsing. This is done internally by BoringSSL for DTLS.
877*d9f75844SAndroid Build Coastguard Worker     SSL_set_read_ahead(ssl_, 1);
878*d9f75844SAndroid Build Coastguard Worker #endif
879*d9f75844SAndroid Build Coastguard Worker   }
880*d9f75844SAndroid Build Coastguard Worker 
881*d9f75844SAndroid Build Coastguard Worker   SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE |
882*d9f75844SAndroid Build Coastguard Worker                          SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
883*d9f75844SAndroid Build Coastguard Worker 
884*d9f75844SAndroid Build Coastguard Worker   // Do the connect
885*d9f75844SAndroid Build Coastguard Worker   return ContinueSSL();
886*d9f75844SAndroid Build Coastguard Worker }
887*d9f75844SAndroid Build Coastguard Worker 
ContinueSSL()888*d9f75844SAndroid Build Coastguard Worker int OpenSSLStreamAdapter::ContinueSSL() {
889*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_VERBOSE) << "ContinueSSL";
890*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(state_ == SSL_CONNECTING);
891*d9f75844SAndroid Build Coastguard Worker 
892*d9f75844SAndroid Build Coastguard Worker   // Clear the DTLS timer
893*d9f75844SAndroid Build Coastguard Worker   timeout_task_.Stop();
894*d9f75844SAndroid Build Coastguard Worker 
895*d9f75844SAndroid Build Coastguard Worker   const int code = (role_ == SSL_CLIENT) ? SSL_connect(ssl_) : SSL_accept(ssl_);
896*d9f75844SAndroid Build Coastguard Worker   const int ssl_error = SSL_get_error(ssl_, code);
897*d9f75844SAndroid Build Coastguard Worker 
898*d9f75844SAndroid Build Coastguard Worker   switch (ssl_error) {
899*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_NONE:
900*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- success";
901*d9f75844SAndroid Build Coastguard Worker       // By this point, OpenSSL should have given us a certificate, or errored
902*d9f75844SAndroid Build Coastguard Worker       // out if one was missing.
903*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK(peer_cert_chain_ || !GetClientAuthEnabled());
904*d9f75844SAndroid Build Coastguard Worker 
905*d9f75844SAndroid Build Coastguard Worker       state_ = SSL_CONNECTED;
906*d9f75844SAndroid Build Coastguard Worker       if (!WaitingToVerifyPeerCertificate()) {
907*d9f75844SAndroid Build Coastguard Worker         // We have everything we need to start the connection, so signal
908*d9f75844SAndroid Build Coastguard Worker         // SE_OPEN. If we need a client certificate fingerprint and don't have
909*d9f75844SAndroid Build Coastguard Worker         // it yet, we'll instead signal SE_OPEN in SetPeerCertificateDigest.
910*d9f75844SAndroid Build Coastguard Worker         //
911*d9f75844SAndroid Build Coastguard Worker         // TODO(deadbeef): Post this event asynchronously to unwind the stack.
912*d9f75844SAndroid Build Coastguard Worker         // The caller of ContinueSSL may be the same object listening for these
913*d9f75844SAndroid Build Coastguard Worker         // events and may not be prepared for reentrancy.
914*d9f75844SAndroid Build Coastguard Worker         // PostEvent(SE_OPEN | SE_READ | SE_WRITE, 0);
915*d9f75844SAndroid Build Coastguard Worker         SignalEvent(this, SE_OPEN | SE_READ | SE_WRITE, 0);
916*d9f75844SAndroid Build Coastguard Worker       }
917*d9f75844SAndroid Build Coastguard Worker       break;
918*d9f75844SAndroid Build Coastguard Worker 
919*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_READ: {
920*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want read";
921*d9f75844SAndroid Build Coastguard Worker       struct timeval timeout;
922*d9f75844SAndroid Build Coastguard Worker       if (DTLSv1_get_timeout(ssl_, &timeout)) {
923*d9f75844SAndroid Build Coastguard Worker         int delay = timeout.tv_sec * 1000 + timeout.tv_usec / 1000;
924*d9f75844SAndroid Build Coastguard Worker         SetTimeout(delay);
925*d9f75844SAndroid Build Coastguard Worker       }
926*d9f75844SAndroid Build Coastguard Worker     } break;
927*d9f75844SAndroid Build Coastguard Worker 
928*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_WANT_WRITE:
929*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error want write";
930*d9f75844SAndroid Build Coastguard Worker       break;
931*d9f75844SAndroid Build Coastguard Worker 
932*d9f75844SAndroid Build Coastguard Worker     case SSL_ERROR_ZERO_RETURN:
933*d9f75844SAndroid Build Coastguard Worker     default:
934*d9f75844SAndroid Build Coastguard Worker       SSLHandshakeError ssl_handshake_err = SSLHandshakeError::UNKNOWN;
935*d9f75844SAndroid Build Coastguard Worker       int err_code = ERR_peek_last_error();
936*d9f75844SAndroid Build Coastguard Worker       if (err_code != 0 && ERR_GET_REASON(err_code) == SSL_R_NO_SHARED_CIPHER) {
937*d9f75844SAndroid Build Coastguard Worker         ssl_handshake_err = SSLHandshakeError::INCOMPATIBLE_CIPHERSUITE;
938*d9f75844SAndroid Build Coastguard Worker       }
939*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_VERBOSE) << " -- error " << code << ", " << err_code << ", "
940*d9f75844SAndroid Build Coastguard Worker                            << ERR_GET_REASON(err_code);
941*d9f75844SAndroid Build Coastguard Worker       SignalSSLHandshakeError(ssl_handshake_err);
942*d9f75844SAndroid Build Coastguard Worker       return (ssl_error != 0) ? ssl_error : -1;
943*d9f75844SAndroid Build Coastguard Worker   }
944*d9f75844SAndroid Build Coastguard Worker 
945*d9f75844SAndroid Build Coastguard Worker   return 0;
946*d9f75844SAndroid Build Coastguard Worker }
947*d9f75844SAndroid Build Coastguard Worker 
Error(absl::string_view context,int err,uint8_t alert,bool signal)948*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::Error(absl::string_view context,
949*d9f75844SAndroid Build Coastguard Worker                                  int err,
950*d9f75844SAndroid Build Coastguard Worker                                  uint8_t alert,
951*d9f75844SAndroid Build Coastguard Worker                                  bool signal) {
952*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_WARNING) << "OpenSSLStreamAdapter::Error(" << context << ", "
953*d9f75844SAndroid Build Coastguard Worker                       << err << ", " << static_cast<int>(alert) << ")";
954*d9f75844SAndroid Build Coastguard Worker   state_ = SSL_ERROR;
955*d9f75844SAndroid Build Coastguard Worker   ssl_error_code_ = err;
956*d9f75844SAndroid Build Coastguard Worker   Cleanup(alert);
957*d9f75844SAndroid Build Coastguard Worker   if (signal) {
958*d9f75844SAndroid Build Coastguard Worker     SignalEvent(this, SE_CLOSE, err);
959*d9f75844SAndroid Build Coastguard Worker   }
960*d9f75844SAndroid Build Coastguard Worker }
961*d9f75844SAndroid Build Coastguard Worker 
Cleanup(uint8_t alert)962*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::Cleanup(uint8_t alert) {
963*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_INFO) << "Cleanup";
964*d9f75844SAndroid Build Coastguard Worker 
965*d9f75844SAndroid Build Coastguard Worker   if (state_ != SSL_ERROR) {
966*d9f75844SAndroid Build Coastguard Worker     state_ = SSL_CLOSED;
967*d9f75844SAndroid Build Coastguard Worker     ssl_error_code_ = 0;
968*d9f75844SAndroid Build Coastguard Worker   }
969*d9f75844SAndroid Build Coastguard Worker 
970*d9f75844SAndroid Build Coastguard Worker   if (ssl_) {
971*d9f75844SAndroid Build Coastguard Worker     int ret;
972*d9f75844SAndroid Build Coastguard Worker // SSL_send_fatal_alert is only available in BoringSSL.
973*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
974*d9f75844SAndroid Build Coastguard Worker     if (alert) {
975*d9f75844SAndroid Build Coastguard Worker       ret = SSL_send_fatal_alert(ssl_, alert);
976*d9f75844SAndroid Build Coastguard Worker       if (ret < 0) {
977*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING) << "SSL_send_fatal_alert failed, error = "
978*d9f75844SAndroid Build Coastguard Worker                             << SSL_get_error(ssl_, ret);
979*d9f75844SAndroid Build Coastguard Worker       }
980*d9f75844SAndroid Build Coastguard Worker     } else {
981*d9f75844SAndroid Build Coastguard Worker #endif
982*d9f75844SAndroid Build Coastguard Worker       ret = SSL_shutdown(ssl_);
983*d9f75844SAndroid Build Coastguard Worker       if (ret < 0) {
984*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_WARNING)
985*d9f75844SAndroid Build Coastguard Worker             << "SSL_shutdown failed, error = " << SSL_get_error(ssl_, ret);
986*d9f75844SAndroid Build Coastguard Worker       }
987*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
988*d9f75844SAndroid Build Coastguard Worker     }
989*d9f75844SAndroid Build Coastguard Worker #endif
990*d9f75844SAndroid Build Coastguard Worker     SSL_free(ssl_);
991*d9f75844SAndroid Build Coastguard Worker     ssl_ = nullptr;
992*d9f75844SAndroid Build Coastguard Worker   }
993*d9f75844SAndroid Build Coastguard Worker   if (ssl_ctx_) {
994*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_free(ssl_ctx_);
995*d9f75844SAndroid Build Coastguard Worker     ssl_ctx_ = nullptr;
996*d9f75844SAndroid Build Coastguard Worker   }
997*d9f75844SAndroid Build Coastguard Worker   identity_.reset();
998*d9f75844SAndroid Build Coastguard Worker   peer_cert_chain_.reset();
999*d9f75844SAndroid Build Coastguard Worker 
1000*d9f75844SAndroid Build Coastguard Worker   // Clear the DTLS timer
1001*d9f75844SAndroid Build Coastguard Worker   timeout_task_.Stop();
1002*d9f75844SAndroid Build Coastguard Worker }
1003*d9f75844SAndroid Build Coastguard Worker 
SetupSSLContext()1004*d9f75844SAndroid Build Coastguard Worker SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
1005*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
1006*d9f75844SAndroid Build Coastguard Worker   // If X509 objects aren't used, we can use these methods to avoid
1007*d9f75844SAndroid Build Coastguard Worker   // linking the sizable crypto/x509 code, using CRYPTO_BUFFER instead.
1008*d9f75844SAndroid Build Coastguard Worker   SSL_CTX* ctx =
1009*d9f75844SAndroid Build Coastguard Worker       SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_with_buffers_method()
1010*d9f75844SAndroid Build Coastguard Worker                                              : TLS_with_buffers_method());
1011*d9f75844SAndroid Build Coastguard Worker #else
1012*d9f75844SAndroid Build Coastguard Worker   SSL_CTX* ctx =
1013*d9f75844SAndroid Build Coastguard Worker       SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
1014*d9f75844SAndroid Build Coastguard Worker #endif
1015*d9f75844SAndroid Build Coastguard Worker   if (ctx == nullptr) {
1016*d9f75844SAndroid Build Coastguard Worker     return nullptr;
1017*d9f75844SAndroid Build Coastguard Worker   }
1018*d9f75844SAndroid Build Coastguard Worker 
1019*d9f75844SAndroid Build Coastguard Worker   if (support_legacy_tls_protocols_flag_) {
1020*d9f75844SAndroid Build Coastguard Worker     // TODO(https://bugs.webrtc.org/10261): Completely remove this branch in
1021*d9f75844SAndroid Build Coastguard Worker     // M84.
1022*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_set_min_proto_version(
1023*d9f75844SAndroid Build Coastguard Worker         ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
1024*d9f75844SAndroid Build Coastguard Worker     switch (ssl_max_version_) {
1025*d9f75844SAndroid Build Coastguard Worker       case SSL_PROTOCOL_TLS_10:
1026*d9f75844SAndroid Build Coastguard Worker         SSL_CTX_set_max_proto_version(
1027*d9f75844SAndroid Build Coastguard Worker             ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_VERSION);
1028*d9f75844SAndroid Build Coastguard Worker         break;
1029*d9f75844SAndroid Build Coastguard Worker       case SSL_PROTOCOL_TLS_11:
1030*d9f75844SAndroid Build Coastguard Worker         SSL_CTX_set_max_proto_version(
1031*d9f75844SAndroid Build Coastguard Worker             ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_VERSION : TLS1_1_VERSION);
1032*d9f75844SAndroid Build Coastguard Worker         break;
1033*d9f75844SAndroid Build Coastguard Worker       case SSL_PROTOCOL_TLS_12:
1034*d9f75844SAndroid Build Coastguard Worker       default:
1035*d9f75844SAndroid Build Coastguard Worker         SSL_CTX_set_max_proto_version(
1036*d9f75844SAndroid Build Coastguard Worker             ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
1037*d9f75844SAndroid Build Coastguard Worker         break;
1038*d9f75844SAndroid Build Coastguard Worker     }
1039*d9f75844SAndroid Build Coastguard Worker   } else {
1040*d9f75844SAndroid Build Coastguard Worker     // TODO(https://bugs.webrtc.org/10261): Make this the default in M84.
1041*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_set_min_proto_version(
1042*d9f75844SAndroid Build Coastguard Worker         ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
1043*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_set_max_proto_version(
1044*d9f75844SAndroid Build Coastguard Worker         ctx, ssl_mode_ == SSL_MODE_DTLS ? DTLS1_2_VERSION : TLS1_2_VERSION);
1045*d9f75844SAndroid Build Coastguard Worker   }
1046*d9f75844SAndroid Build Coastguard Worker 
1047*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
1048*d9f75844SAndroid Build Coastguard Worker   // SSL_CTX_set_current_time_cb is only supported in BoringSSL.
1049*d9f75844SAndroid Build Coastguard Worker   if (g_use_time_callback_for_testing) {
1050*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting);
1051*d9f75844SAndroid Build Coastguard Worker   }
1052*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool());
1053*d9f75844SAndroid Build Coastguard Worker #endif
1054*d9f75844SAndroid Build Coastguard Worker 
1055*d9f75844SAndroid Build Coastguard Worker   if (identity_ && !identity_->ConfigureIdentity(ctx)) {
1056*d9f75844SAndroid Build Coastguard Worker     SSL_CTX_free(ctx);
1057*d9f75844SAndroid Build Coastguard Worker     return nullptr;
1058*d9f75844SAndroid Build Coastguard Worker   }
1059*d9f75844SAndroid Build Coastguard Worker 
1060*d9f75844SAndroid Build Coastguard Worker #if !defined(NDEBUG)
1061*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set_info_callback(ctx, OpenSSLAdapter::SSLInfoCallback);
1062*d9f75844SAndroid Build Coastguard Worker #endif
1063*d9f75844SAndroid Build Coastguard Worker 
1064*d9f75844SAndroid Build Coastguard Worker   int mode = SSL_VERIFY_PEER;
1065*d9f75844SAndroid Build Coastguard Worker   if (GetClientAuthEnabled()) {
1066*d9f75844SAndroid Build Coastguard Worker     // Require a certificate from the client.
1067*d9f75844SAndroid Build Coastguard Worker     // Note: Normally this is always true in production, but it may be disabled
1068*d9f75844SAndroid Build Coastguard Worker     // for testing purposes (e.g. SSLAdapter unit tests).
1069*d9f75844SAndroid Build Coastguard Worker     mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
1070*d9f75844SAndroid Build Coastguard Worker   }
1071*d9f75844SAndroid Build Coastguard Worker 
1072*d9f75844SAndroid Build Coastguard Worker   // Configure a custom certificate verification callback to check the peer
1073*d9f75844SAndroid Build Coastguard Worker   // certificate digest.
1074*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
1075*d9f75844SAndroid Build Coastguard Worker   // Use CRYPTO_BUFFER version of the callback if building with BoringSSL.
1076*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set_custom_verify(ctx, mode, SSLVerifyCallback);
1077*d9f75844SAndroid Build Coastguard Worker #else
1078*d9f75844SAndroid Build Coastguard Worker   // Note the second argument to SSL_CTX_set_verify is to override individual
1079*d9f75844SAndroid Build Coastguard Worker   // errors in the default verification logic, which is not what we want here.
1080*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set_verify(ctx, mode, nullptr);
1081*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set_cert_verify_callback(ctx, SSLVerifyCallback, nullptr);
1082*d9f75844SAndroid Build Coastguard Worker #endif
1083*d9f75844SAndroid Build Coastguard Worker 
1084*d9f75844SAndroid Build Coastguard Worker   // Select list of available ciphers. Note that !SHA256 and !SHA384 only
1085*d9f75844SAndroid Build Coastguard Worker   // remove HMAC-SHA256 and HMAC-SHA384 cipher suites, not GCM cipher suites
1086*d9f75844SAndroid Build Coastguard Worker   // with SHA256 or SHA384 as the handshake hash.
1087*d9f75844SAndroid Build Coastguard Worker   // This matches the list of SSLClientSocketImpl in Chromium.
1088*d9f75844SAndroid Build Coastguard Worker   SSL_CTX_set_cipher_list(
1089*d9f75844SAndroid Build Coastguard Worker       ctx,
1090*d9f75844SAndroid Build Coastguard Worker       "DEFAULT:!NULL:!aNULL:!SHA256:!SHA384:!aECDH:!AESGCM+AES256:!aPSK:!3DES");
1091*d9f75844SAndroid Build Coastguard Worker 
1092*d9f75844SAndroid Build Coastguard Worker   if (!srtp_ciphers_.empty()) {
1093*d9f75844SAndroid Build Coastguard Worker     if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_ciphers_.c_str())) {
1094*d9f75844SAndroid Build Coastguard Worker       SSL_CTX_free(ctx);
1095*d9f75844SAndroid Build Coastguard Worker       return nullptr;
1096*d9f75844SAndroid Build Coastguard Worker     }
1097*d9f75844SAndroid Build Coastguard Worker   }
1098*d9f75844SAndroid Build Coastguard Worker 
1099*d9f75844SAndroid Build Coastguard Worker   return ctx;
1100*d9f75844SAndroid Build Coastguard Worker }
1101*d9f75844SAndroid Build Coastguard Worker 
VerifyPeerCertificate()1102*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::VerifyPeerCertificate() {
1103*d9f75844SAndroid Build Coastguard Worker   if (!HasPeerCertificateDigest() || !peer_cert_chain_ ||
1104*d9f75844SAndroid Build Coastguard Worker       !peer_cert_chain_->GetSize()) {
1105*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Missing digest or peer certificate.";
1106*d9f75844SAndroid Build Coastguard Worker     return false;
1107*d9f75844SAndroid Build Coastguard Worker   }
1108*d9f75844SAndroid Build Coastguard Worker 
1109*d9f75844SAndroid Build Coastguard Worker   unsigned char digest[EVP_MAX_MD_SIZE];
1110*d9f75844SAndroid Build Coastguard Worker   size_t digest_length;
1111*d9f75844SAndroid Build Coastguard Worker   if (!peer_cert_chain_->Get(0).ComputeDigest(
1112*d9f75844SAndroid Build Coastguard Worker           peer_certificate_digest_algorithm_, digest, sizeof(digest),
1113*d9f75844SAndroid Build Coastguard Worker           &digest_length)) {
1114*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Failed to compute peer cert digest.";
1115*d9f75844SAndroid Build Coastguard Worker     return false;
1116*d9f75844SAndroid Build Coastguard Worker   }
1117*d9f75844SAndroid Build Coastguard Worker 
1118*d9f75844SAndroid Build Coastguard Worker   Buffer computed_digest(digest, digest_length);
1119*d9f75844SAndroid Build Coastguard Worker   if (computed_digest != peer_certificate_digest_value_) {
1120*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING)
1121*d9f75844SAndroid Build Coastguard Worker         << "Rejected peer certificate due to mismatched digest using "
1122*d9f75844SAndroid Build Coastguard Worker         << peer_certificate_digest_algorithm_ << ". Expected "
1123*d9f75844SAndroid Build Coastguard Worker         << rtc::hex_encode_with_delimiter(peer_certificate_digest_value_, ':')
1124*d9f75844SAndroid Build Coastguard Worker         << " got " << rtc::hex_encode_with_delimiter(computed_digest, ':');
1125*d9f75844SAndroid Build Coastguard Worker     return false;
1126*d9f75844SAndroid Build Coastguard Worker   }
1127*d9f75844SAndroid Build Coastguard Worker   // Ignore any verification error if the digest matches, since there is no
1128*d9f75844SAndroid Build Coastguard Worker   // value in checking the validity of a self-signed cert issued by untrusted
1129*d9f75844SAndroid Build Coastguard Worker   // sources.
1130*d9f75844SAndroid Build Coastguard Worker   RTC_DLOG(LS_INFO) << "Accepted peer certificate.";
1131*d9f75844SAndroid Build Coastguard Worker   peer_certificate_verified_ = true;
1132*d9f75844SAndroid Build Coastguard Worker   return true;
1133*d9f75844SAndroid Build Coastguard Worker }
1134*d9f75844SAndroid Build Coastguard Worker 
GetPeerSSLCertChain() const1135*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SSLCertChain> OpenSSLStreamAdapter::GetPeerSSLCertChain()
1136*d9f75844SAndroid Build Coastguard Worker     const {
1137*d9f75844SAndroid Build Coastguard Worker   return peer_cert_chain_ ? peer_cert_chain_->Clone() : nullptr;
1138*d9f75844SAndroid Build Coastguard Worker }
1139*d9f75844SAndroid Build Coastguard Worker 
1140*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
SSLVerifyCallback(SSL * ssl,uint8_t * out_alert)1141*d9f75844SAndroid Build Coastguard Worker enum ssl_verify_result_t OpenSSLStreamAdapter::SSLVerifyCallback(
1142*d9f75844SAndroid Build Coastguard Worker     SSL* ssl,
1143*d9f75844SAndroid Build Coastguard Worker     uint8_t* out_alert) {
1144*d9f75844SAndroid Build Coastguard Worker   // Get our OpenSSLStreamAdapter from the context.
1145*d9f75844SAndroid Build Coastguard Worker   OpenSSLStreamAdapter* stream =
1146*d9f75844SAndroid Build Coastguard Worker       reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
1147*d9f75844SAndroid Build Coastguard Worker   const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
1148*d9f75844SAndroid Build Coastguard Worker   // Creates certificate chain.
1149*d9f75844SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<SSLCertificate>> cert_chain;
1150*d9f75844SAndroid Build Coastguard Worker   for (CRYPTO_BUFFER* cert : chain) {
1151*d9f75844SAndroid Build Coastguard Worker     cert_chain.emplace_back(new BoringSSLCertificate(bssl::UpRef(cert)));
1152*d9f75844SAndroid Build Coastguard Worker   }
1153*d9f75844SAndroid Build Coastguard Worker   stream->peer_cert_chain_.reset(new SSLCertChain(std::move(cert_chain)));
1154*d9f75844SAndroid Build Coastguard Worker 
1155*d9f75844SAndroid Build Coastguard Worker   // If the peer certificate digest isn't known yet, we'll wait to verify
1156*d9f75844SAndroid Build Coastguard Worker   // until it's known, and for now just return a success status.
1157*d9f75844SAndroid Build Coastguard Worker   if (stream->peer_certificate_digest_algorithm_.empty()) {
1158*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "Waiting to verify certificate until digest is known.";
1159*d9f75844SAndroid Build Coastguard Worker     // TODO(deadbeef): Use ssl_verify_retry?
1160*d9f75844SAndroid Build Coastguard Worker     return ssl_verify_ok;
1161*d9f75844SAndroid Build Coastguard Worker   }
1162*d9f75844SAndroid Build Coastguard Worker 
1163*d9f75844SAndroid Build Coastguard Worker   if (!stream->VerifyPeerCertificate()) {
1164*d9f75844SAndroid Build Coastguard Worker     return ssl_verify_invalid;
1165*d9f75844SAndroid Build Coastguard Worker   }
1166*d9f75844SAndroid Build Coastguard Worker 
1167*d9f75844SAndroid Build Coastguard Worker   return ssl_verify_ok;
1168*d9f75844SAndroid Build Coastguard Worker }
1169*d9f75844SAndroid Build Coastguard Worker #else   // OPENSSL_IS_BORINGSSL
SSLVerifyCallback(X509_STORE_CTX * store,void * arg)1170*d9f75844SAndroid Build Coastguard Worker int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
1171*d9f75844SAndroid Build Coastguard Worker   // Get our SSL structure and OpenSSLStreamAdapter from the store.
1172*d9f75844SAndroid Build Coastguard Worker   SSL* ssl = reinterpret_cast<SSL*>(
1173*d9f75844SAndroid Build Coastguard Worker       X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()));
1174*d9f75844SAndroid Build Coastguard Worker   OpenSSLStreamAdapter* stream =
1175*d9f75844SAndroid Build Coastguard Worker       reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
1176*d9f75844SAndroid Build Coastguard Worker 
1177*d9f75844SAndroid Build Coastguard Worker   // Record the peer's certificate.
1178*d9f75844SAndroid Build Coastguard Worker   X509* cert = X509_STORE_CTX_get0_cert(store);
1179*d9f75844SAndroid Build Coastguard Worker   stream->peer_cert_chain_.reset(
1180*d9f75844SAndroid Build Coastguard Worker       new SSLCertChain(std::make_unique<OpenSSLCertificate>(cert)));
1181*d9f75844SAndroid Build Coastguard Worker 
1182*d9f75844SAndroid Build Coastguard Worker   // If the peer certificate digest isn't known yet, we'll wait to verify
1183*d9f75844SAndroid Build Coastguard Worker   // until it's known, and for now just return a success status.
1184*d9f75844SAndroid Build Coastguard Worker   if (stream->peer_certificate_digest_algorithm_.empty()) {
1185*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_INFO) << "Waiting to verify certificate until digest is known.";
1186*d9f75844SAndroid Build Coastguard Worker     return 1;
1187*d9f75844SAndroid Build Coastguard Worker   }
1188*d9f75844SAndroid Build Coastguard Worker 
1189*d9f75844SAndroid Build Coastguard Worker   if (!stream->VerifyPeerCertificate()) {
1190*d9f75844SAndroid Build Coastguard Worker     X509_STORE_CTX_set_error(store, X509_V_ERR_CERT_REJECTED);
1191*d9f75844SAndroid Build Coastguard Worker     return 0;
1192*d9f75844SAndroid Build Coastguard Worker   }
1193*d9f75844SAndroid Build Coastguard Worker 
1194*d9f75844SAndroid Build Coastguard Worker   return 1;
1195*d9f75844SAndroid Build Coastguard Worker }
1196*d9f75844SAndroid Build Coastguard Worker #endif  // !OPENSSL_IS_BORINGSSL
1197*d9f75844SAndroid Build Coastguard Worker 
IsBoringSsl()1198*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::IsBoringSsl() {
1199*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
1200*d9f75844SAndroid Build Coastguard Worker   return true;
1201*d9f75844SAndroid Build Coastguard Worker #else
1202*d9f75844SAndroid Build Coastguard Worker   return false;
1203*d9f75844SAndroid Build Coastguard Worker #endif
1204*d9f75844SAndroid Build Coastguard Worker }
1205*d9f75844SAndroid Build Coastguard Worker 
1206*d9f75844SAndroid Build Coastguard Worker #define CDEF(X) \
1207*d9f75844SAndroid Build Coastguard Worker   { static_cast<uint16_t>(TLS1_CK_##X & 0xffff), "TLS_" #X }
1208*d9f75844SAndroid Build Coastguard Worker 
1209*d9f75844SAndroid Build Coastguard Worker struct cipher_list {
1210*d9f75844SAndroid Build Coastguard Worker   uint16_t cipher;
1211*d9f75844SAndroid Build Coastguard Worker   const char* cipher_str;
1212*d9f75844SAndroid Build Coastguard Worker };
1213*d9f75844SAndroid Build Coastguard Worker 
1214*d9f75844SAndroid Build Coastguard Worker // TODO(torbjorng): Perhaps add more cipher suites to these lists.
1215*d9f75844SAndroid Build Coastguard Worker static const cipher_list OK_RSA_ciphers[] = {
1216*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_RSA_WITH_AES_128_CBC_SHA),
1217*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_RSA_WITH_AES_256_CBC_SHA),
1218*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_RSA_WITH_AES_128_GCM_SHA256),
1219*d9f75844SAndroid Build Coastguard Worker #ifdef TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA256
1220*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_RSA_WITH_AES_256_GCM_SHA256),
1221*d9f75844SAndroid Build Coastguard Worker #endif
1222*d9f75844SAndroid Build Coastguard Worker #ifdef TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
1223*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
1224*d9f75844SAndroid Build Coastguard Worker #endif
1225*d9f75844SAndroid Build Coastguard Worker };
1226*d9f75844SAndroid Build Coastguard Worker 
1227*d9f75844SAndroid Build Coastguard Worker static const cipher_list OK_ECDSA_ciphers[] = {
1228*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
1229*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
1230*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
1231*d9f75844SAndroid Build Coastguard Worker #ifdef TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA256
1232*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_ECDSA_WITH_AES_256_GCM_SHA256),
1233*d9f75844SAndroid Build Coastguard Worker #endif
1234*d9f75844SAndroid Build Coastguard Worker #ifdef TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
1235*d9f75844SAndroid Build Coastguard Worker     CDEF(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
1236*d9f75844SAndroid Build Coastguard Worker #endif
1237*d9f75844SAndroid Build Coastguard Worker };
1238*d9f75844SAndroid Build Coastguard Worker #undef CDEF
1239*d9f75844SAndroid Build Coastguard Worker 
IsAcceptableCipher(int cipher,KeyType key_type)1240*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::IsAcceptableCipher(int cipher, KeyType key_type) {
1241*d9f75844SAndroid Build Coastguard Worker   if (key_type == KT_RSA) {
1242*d9f75844SAndroid Build Coastguard Worker     for (const cipher_list& c : OK_RSA_ciphers) {
1243*d9f75844SAndroid Build Coastguard Worker       if (cipher == c.cipher) {
1244*d9f75844SAndroid Build Coastguard Worker         return true;
1245*d9f75844SAndroid Build Coastguard Worker       }
1246*d9f75844SAndroid Build Coastguard Worker     }
1247*d9f75844SAndroid Build Coastguard Worker   }
1248*d9f75844SAndroid Build Coastguard Worker 
1249*d9f75844SAndroid Build Coastguard Worker   if (key_type == KT_ECDSA) {
1250*d9f75844SAndroid Build Coastguard Worker     for (const cipher_list& c : OK_ECDSA_ciphers) {
1251*d9f75844SAndroid Build Coastguard Worker       if (cipher == c.cipher) {
1252*d9f75844SAndroid Build Coastguard Worker         return true;
1253*d9f75844SAndroid Build Coastguard Worker       }
1254*d9f75844SAndroid Build Coastguard Worker     }
1255*d9f75844SAndroid Build Coastguard Worker   }
1256*d9f75844SAndroid Build Coastguard Worker 
1257*d9f75844SAndroid Build Coastguard Worker   return false;
1258*d9f75844SAndroid Build Coastguard Worker }
1259*d9f75844SAndroid Build Coastguard Worker 
IsAcceptableCipher(absl::string_view cipher,KeyType key_type)1260*d9f75844SAndroid Build Coastguard Worker bool OpenSSLStreamAdapter::IsAcceptableCipher(absl::string_view cipher,
1261*d9f75844SAndroid Build Coastguard Worker                                               KeyType key_type) {
1262*d9f75844SAndroid Build Coastguard Worker   if (key_type == KT_RSA) {
1263*d9f75844SAndroid Build Coastguard Worker     for (const cipher_list& c : OK_RSA_ciphers) {
1264*d9f75844SAndroid Build Coastguard Worker       if (cipher == c.cipher_str) {
1265*d9f75844SAndroid Build Coastguard Worker         return true;
1266*d9f75844SAndroid Build Coastguard Worker       }
1267*d9f75844SAndroid Build Coastguard Worker     }
1268*d9f75844SAndroid Build Coastguard Worker   }
1269*d9f75844SAndroid Build Coastguard Worker 
1270*d9f75844SAndroid Build Coastguard Worker   if (key_type == KT_ECDSA) {
1271*d9f75844SAndroid Build Coastguard Worker     for (const cipher_list& c : OK_ECDSA_ciphers) {
1272*d9f75844SAndroid Build Coastguard Worker       if (cipher == c.cipher_str) {
1273*d9f75844SAndroid Build Coastguard Worker         return true;
1274*d9f75844SAndroid Build Coastguard Worker       }
1275*d9f75844SAndroid Build Coastguard Worker     }
1276*d9f75844SAndroid Build Coastguard Worker   }
1277*d9f75844SAndroid Build Coastguard Worker 
1278*d9f75844SAndroid Build Coastguard Worker   return false;
1279*d9f75844SAndroid Build Coastguard Worker }
1280*d9f75844SAndroid Build Coastguard Worker 
EnableTimeCallbackForTesting()1281*d9f75844SAndroid Build Coastguard Worker void OpenSSLStreamAdapter::EnableTimeCallbackForTesting() {
1282*d9f75844SAndroid Build Coastguard Worker #ifdef OPENSSL_IS_BORINGSSL
1283*d9f75844SAndroid Build Coastguard Worker   g_use_time_callback_for_testing = true;
1284*d9f75844SAndroid Build Coastguard Worker #endif
1285*d9f75844SAndroid Build Coastguard Worker }
1286*d9f75844SAndroid Build Coastguard Worker 
1287*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
1288