1 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/crypto/tls_connection.h"
6
7 #include "absl/strings/string_view.h"
8 #include "openssl/ssl.h"
9 #include "quiche/quic/platform/api/quic_bug_tracker.h"
10
11 namespace quic {
12
13 namespace {
14
15 // BoringSSL allows storing extra data off of some of its data structures,
16 // including the SSL struct. To allow for multiple callers to store data, each
17 // caller can use a different index for setting and getting data. These indices
18 // are globals handed out by calling SSL_get_ex_new_index.
19 //
20 // SslIndexSingleton calls SSL_get_ex_new_index on its construction, and then
21 // provides this index to be used in calls to SSL_get_ex_data/SSL_set_ex_data.
22 // This is used to store in the SSL struct a pointer to the TlsConnection which
23 // owns it.
24 class SslIndexSingleton {
25 public:
GetInstance()26 static SslIndexSingleton* GetInstance() {
27 static SslIndexSingleton* instance = new SslIndexSingleton();
28 return instance;
29 }
30
ssl_ex_data_index_connection() const31 int ssl_ex_data_index_connection() const {
32 return ssl_ex_data_index_connection_;
33 }
34
35 private:
SslIndexSingleton()36 SslIndexSingleton() {
37 CRYPTO_library_init();
38 ssl_ex_data_index_connection_ =
39 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
40 QUICHE_CHECK_LE(0, ssl_ex_data_index_connection_);
41 }
42
43 SslIndexSingleton(const SslIndexSingleton&) = delete;
44 SslIndexSingleton& operator=(const SslIndexSingleton&) = delete;
45
46 // The index to supply to SSL_get_ex_data/SSL_set_ex_data for getting/setting
47 // the TlsConnection pointer.
48 int ssl_ex_data_index_connection_;
49 };
50
51 } // namespace
52
53 // static
QuicEncryptionLevel(enum ssl_encryption_level_t level)54 EncryptionLevel TlsConnection::QuicEncryptionLevel(
55 enum ssl_encryption_level_t level) {
56 switch (level) {
57 case ssl_encryption_initial:
58 return ENCRYPTION_INITIAL;
59 case ssl_encryption_early_data:
60 return ENCRYPTION_ZERO_RTT;
61 case ssl_encryption_handshake:
62 return ENCRYPTION_HANDSHAKE;
63 case ssl_encryption_application:
64 return ENCRYPTION_FORWARD_SECURE;
65 default:
66 QUIC_BUG(quic_bug_10698_1)
67 << "Invalid ssl_encryption_level_t " << static_cast<int>(level);
68 return ENCRYPTION_INITIAL;
69 }
70 }
71
72 // static
BoringEncryptionLevel(EncryptionLevel level)73 enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel(
74 EncryptionLevel level) {
75 switch (level) {
76 case ENCRYPTION_INITIAL:
77 return ssl_encryption_initial;
78 case ENCRYPTION_HANDSHAKE:
79 return ssl_encryption_handshake;
80 case ENCRYPTION_ZERO_RTT:
81 return ssl_encryption_early_data;
82 case ENCRYPTION_FORWARD_SECURE:
83 return ssl_encryption_application;
84 default:
85 QUIC_BUG(quic_bug_10698_2)
86 << "Invalid encryption level " << static_cast<int>(level);
87 return ssl_encryption_initial;
88 }
89 }
90
TlsConnection(SSL_CTX * ssl_ctx,TlsConnection::Delegate * delegate,QuicSSLConfig ssl_config)91 TlsConnection::TlsConnection(SSL_CTX* ssl_ctx,
92 TlsConnection::Delegate* delegate,
93 QuicSSLConfig ssl_config)
94 : delegate_(delegate),
95 ssl_(SSL_new(ssl_ctx)),
96 ssl_config_(std::move(ssl_config)) {
97 SSL_set_ex_data(
98 ssl(), SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection(),
99 this);
100 if (ssl_config_.early_data_enabled.has_value()) {
101 const int early_data_enabled = *ssl_config_.early_data_enabled ? 1 : 0;
102 SSL_set_early_data_enabled(ssl(), early_data_enabled);
103 }
104 if (ssl_config_.signing_algorithm_prefs.has_value()) {
105 SSL_set_signing_algorithm_prefs(
106 ssl(), ssl_config_.signing_algorithm_prefs->data(),
107 ssl_config_.signing_algorithm_prefs->size());
108 }
109 if (ssl_config_.disable_ticket_support.has_value()) {
110 if (*ssl_config_.disable_ticket_support) {
111 SSL_set_options(ssl(), SSL_OP_NO_TICKET);
112 }
113 }
114 }
115
EnableInfoCallback()116 void TlsConnection::EnableInfoCallback() {
117 SSL_set_info_callback(
118 ssl(), +[](const SSL* ssl, int type, int value) {
119 ConnectionFromSsl(ssl)->delegate_->InfoCallback(type, value);
120 });
121 }
122
DisableTicketSupport()123 void TlsConnection::DisableTicketSupport() {
124 ssl_config_.disable_ticket_support = true;
125 SSL_set_options(ssl(), SSL_OP_NO_TICKET);
126 }
127
128 // static
CreateSslCtx()129 bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx() {
130 CRYPTO_library_init();
131 bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_with_buffers_method()));
132 SSL_CTX_set_min_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
133 SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
134 SSL_CTX_set_quic_method(ssl_ctx.get(), &kSslQuicMethod);
135 SSL_CTX_set_msg_callback(ssl_ctx.get(), &MessageCallback);
136 return ssl_ctx;
137 }
138
139 // static
ConnectionFromSsl(const SSL * ssl)140 TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) {
141 return reinterpret_cast<TlsConnection*>(SSL_get_ex_data(
142 ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection()));
143 }
144
145 // static
VerifyCallback(SSL * ssl,uint8_t * out_alert)146 enum ssl_verify_result_t TlsConnection::VerifyCallback(SSL* ssl,
147 uint8_t* out_alert) {
148 return ConnectionFromSsl(ssl)->delegate_->VerifyCert(out_alert);
149 }
150
151 const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{
152 TlsConnection::SetReadSecretCallback, TlsConnection::SetWriteSecretCallback,
153 TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
154 TlsConnection::SendAlertCallback};
155
156 // static
SetReadSecretCallback(SSL * ssl,enum ssl_encryption_level_t level,const SSL_CIPHER * cipher,const uint8_t * secret,size_t secret_length)157 int TlsConnection::SetReadSecretCallback(SSL* ssl,
158 enum ssl_encryption_level_t level,
159 const SSL_CIPHER* cipher,
160 const uint8_t* secret,
161 size_t secret_length) {
162 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
163 if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher,
164 absl::MakeSpan(secret, secret_length))) {
165 return 0;
166 }
167 return 1;
168 }
169
170 // static
SetWriteSecretCallback(SSL * ssl,enum ssl_encryption_level_t level,const SSL_CIPHER * cipher,const uint8_t * secret,size_t secret_length)171 int TlsConnection::SetWriteSecretCallback(SSL* ssl,
172 enum ssl_encryption_level_t level,
173 const SSL_CIPHER* cipher,
174 const uint8_t* secret,
175 size_t secret_length) {
176 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
177 delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher,
178 absl::MakeSpan(secret, secret_length));
179 return 1;
180 }
181
182 // static
WriteMessageCallback(SSL * ssl,enum ssl_encryption_level_t level,const uint8_t * data,size_t len)183 int TlsConnection::WriteMessageCallback(SSL* ssl,
184 enum ssl_encryption_level_t level,
185 const uint8_t* data, size_t len) {
186 ConnectionFromSsl(ssl)->delegate_->WriteMessage(
187 QuicEncryptionLevel(level),
188 absl::string_view(reinterpret_cast<const char*>(data), len));
189 return 1;
190 }
191
192 // static
FlushFlightCallback(SSL * ssl)193 int TlsConnection::FlushFlightCallback(SSL* ssl) {
194 ConnectionFromSsl(ssl)->delegate_->FlushFlight();
195 return 1;
196 }
197
198 // static
SendAlertCallback(SSL * ssl,enum ssl_encryption_level_t level,uint8_t desc)199 int TlsConnection::SendAlertCallback(SSL* ssl,
200 enum ssl_encryption_level_t level,
201 uint8_t desc) {
202 ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level),
203 desc);
204 return 1;
205 }
206
207 // static
MessageCallback(int is_write,int version,int content_type,const void * buf,size_t len,SSL * ssl,void *)208 void TlsConnection::MessageCallback(int is_write, int version, int content_type,
209 const void* buf, size_t len, SSL* ssl,
210 void*) {
211 ConnectionFromSsl(ssl)->delegate_->MessageCallback(
212 is_write != 0, version, content_type,
213 absl::string_view(static_cast<const char*>(buf), len));
214 }
215
216 } // namespace quic
217