• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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