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 return ssl_ctx;
136 }
137
138 // static
ConnectionFromSsl(const SSL * ssl)139 TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) {
140 return reinterpret_cast<TlsConnection*>(SSL_get_ex_data(
141 ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection()));
142 }
143
144 // static
VerifyCallback(SSL * ssl,uint8_t * out_alert)145 enum ssl_verify_result_t TlsConnection::VerifyCallback(SSL* ssl,
146 uint8_t* out_alert) {
147 return ConnectionFromSsl(ssl)->delegate_->VerifyCert(out_alert);
148 }
149
150 const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{
151 TlsConnection::SetReadSecretCallback, TlsConnection::SetWriteSecretCallback,
152 TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
153 TlsConnection::SendAlertCallback};
154
155 // static
SetReadSecretCallback(SSL * ssl,enum ssl_encryption_level_t level,const SSL_CIPHER * cipher,const uint8_t * secret,size_t secret_length)156 int TlsConnection::SetReadSecretCallback(SSL* ssl,
157 enum ssl_encryption_level_t level,
158 const SSL_CIPHER* cipher,
159 const uint8_t* secret,
160 size_t secret_length) {
161 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
162 if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher,
163 absl::MakeSpan(secret, secret_length))) {
164 return 0;
165 }
166 return 1;
167 }
168
169 // static
SetWriteSecretCallback(SSL * ssl,enum ssl_encryption_level_t level,const SSL_CIPHER * cipher,const uint8_t * secret,size_t secret_length)170 int TlsConnection::SetWriteSecretCallback(SSL* ssl,
171 enum ssl_encryption_level_t level,
172 const SSL_CIPHER* cipher,
173 const uint8_t* secret,
174 size_t secret_length) {
175 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
176 delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher,
177 absl::MakeSpan(secret, secret_length));
178 return 1;
179 }
180
181 // static
WriteMessageCallback(SSL * ssl,enum ssl_encryption_level_t level,const uint8_t * data,size_t len)182 int TlsConnection::WriteMessageCallback(SSL* ssl,
183 enum ssl_encryption_level_t level,
184 const uint8_t* data, size_t len) {
185 ConnectionFromSsl(ssl)->delegate_->WriteMessage(
186 QuicEncryptionLevel(level),
187 absl::string_view(reinterpret_cast<const char*>(data), len));
188 return 1;
189 }
190
191 // static
FlushFlightCallback(SSL * ssl)192 int TlsConnection::FlushFlightCallback(SSL* ssl) {
193 ConnectionFromSsl(ssl)->delegate_->FlushFlight();
194 return 1;
195 }
196
197 // static
SendAlertCallback(SSL * ssl,enum ssl_encryption_level_t level,uint8_t desc)198 int TlsConnection::SendAlertCallback(SSL* ssl,
199 enum ssl_encryption_level_t level,
200 uint8_t desc) {
201 ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level),
202 desc);
203 return 1;
204 }
205
206 } // namespace quic
207