blob: 8e4d391db4be9ad04d88773209cdd5c3db404bd1 [file] [log] [blame]
nharper6ebe83b2019-06-13 17:43:52 -07001// 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 "net/third_party/quiche/src/quic/core/crypto/tls_connection.h"
6
7#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
dmcardle904ef182019-12-13 08:34:33 -08008#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
nharper6ebe83b2019-06-13 17:43:52 -07009
10namespace quic {
11
12namespace {
13
14// BoringSSL allows storing extra data off of some of its data structures,
15// including the SSL struct. To allow for multiple callers to store data, each
16// caller can use a different index for setting and getting data. These indices
17// are globals handed out by calling SSL_get_ex_new_index.
18//
19// SslIndexSingleton calls SSL_get_ex_new_index on its construction, and then
20// provides this index to be used in calls to SSL_get_ex_data/SSL_set_ex_data.
21// This is used to store in the SSL struct a pointer to the TlsConnection which
22// owns it.
23class SslIndexSingleton {
24 public:
25 static SslIndexSingleton* GetInstance() {
26 static SslIndexSingleton* instance = new SslIndexSingleton();
27 return instance;
28 }
29
30 int ssl_ex_data_index_connection() const {
31 return ssl_ex_data_index_connection_;
32 }
33
34 private:
35 SslIndexSingleton() {
36 CRYPTO_library_init();
37 ssl_ex_data_index_connection_ =
38 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
39 CHECK_LE(0, ssl_ex_data_index_connection_);
40 }
41
42 SslIndexSingleton(const SslIndexSingleton&) = delete;
43 SslIndexSingleton& operator=(const SslIndexSingleton&) = delete;
44
45 // The index to supply to SSL_get_ex_data/SSL_set_ex_data for getting/setting
46 // the TlsConnection pointer.
47 int ssl_ex_data_index_connection_;
48};
49
50} // namespace
51
52// static
53EncryptionLevel TlsConnection::QuicEncryptionLevel(
54 enum ssl_encryption_level_t level) {
55 switch (level) {
56 case ssl_encryption_initial:
57 return ENCRYPTION_INITIAL;
58 case ssl_encryption_early_data:
59 return ENCRYPTION_ZERO_RTT;
60 case ssl_encryption_handshake:
61 return ENCRYPTION_HANDSHAKE;
62 case ssl_encryption_application:
63 return ENCRYPTION_FORWARD_SECURE;
64 default:
65 QUIC_BUG << "Invalid ssl_encryption_level_t " << static_cast<int>(level);
66 return ENCRYPTION_INITIAL;
67 }
68}
69
70// static
71enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel(
72 EncryptionLevel level) {
73 switch (level) {
74 case ENCRYPTION_INITIAL:
75 return ssl_encryption_initial;
76 case ENCRYPTION_HANDSHAKE:
77 return ssl_encryption_handshake;
78 case ENCRYPTION_ZERO_RTT:
79 return ssl_encryption_early_data;
80 case ENCRYPTION_FORWARD_SECURE:
81 return ssl_encryption_application;
82 default:
83 QUIC_BUG << "Invalid encryption level " << static_cast<int>(level);
84 return ssl_encryption_initial;
85 }
86}
87
88TlsConnection::TlsConnection(SSL_CTX* ssl_ctx,
89 TlsConnection::Delegate* delegate)
90 : delegate_(delegate), ssl_(SSL_new(ssl_ctx)) {
91 SSL_set_ex_data(
92 ssl(), SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection(),
93 this);
94}
95// static
96bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx() {
97 CRYPTO_library_init();
98 bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_with_buffers_method()));
99 SSL_CTX_set_min_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
100 SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
101 SSL_CTX_set_quic_method(ssl_ctx.get(), &kSslQuicMethod);
102 return ssl_ctx;
103}
104
105// static
106TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) {
107 return reinterpret_cast<TlsConnection*>(SSL_get_ex_data(
108 ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection()));
109}
110
111const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{
nharpera3878e42020-04-02 17:05:21 -0700112 TlsConnection::SetReadSecretCallback, TlsConnection::SetWriteSecretCallback,
113 TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
114 TlsConnection::SendAlertCallback};
nharper6ebe83b2019-06-13 17:43:52 -0700115
116// static
nharper74d96ae2020-02-27 14:11:52 -0800117int TlsConnection::SetReadSecretCallback(SSL* ssl,
118 enum ssl_encryption_level_t level,
119 const SSL_CIPHER* cipher,
120 const uint8_t* secret,
121 size_t secret_length) {
122 // TODO(nharper): replace this vector with a span (which unfortunately doesn't
123 // yet exist in quic/platform/api).
nharperc7e392d2020-03-05 08:18:37 -0800124 std::vector<uint8_t> secret_vec(secret, secret + secret_length);
nharper74d96ae2020-02-27 14:11:52 -0800125 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
126 if (!delegate->SetReadSecret(QuicEncryptionLevel(level), cipher,
127 secret_vec)) {
128 return 0;
129 }
130 return 1;
131}
132
133// static
134int TlsConnection::SetWriteSecretCallback(SSL* ssl,
135 enum ssl_encryption_level_t level,
136 const SSL_CIPHER* cipher,
137 const uint8_t* secret,
138 size_t secret_length) {
139 // TODO(nharper): replace this vector with a span (which unfortunately doesn't
140 // yet exist in quic/platform/api).
nharperc7e392d2020-03-05 08:18:37 -0800141 std::vector<uint8_t> secret_vec(secret, secret + secret_length);
nharper74d96ae2020-02-27 14:11:52 -0800142 TlsConnection::Delegate* delegate = ConnectionFromSsl(ssl)->delegate_;
143 delegate->SetWriteSecret(QuicEncryptionLevel(level), cipher, secret_vec);
144 return 1;
145}
146
147// static
nharper6ebe83b2019-06-13 17:43:52 -0700148int TlsConnection::WriteMessageCallback(SSL* ssl,
149 enum ssl_encryption_level_t level,
150 const uint8_t* data,
151 size_t len) {
152 ConnectionFromSsl(ssl)->delegate_->WriteMessage(
153 QuicEncryptionLevel(level),
dmcardle904ef182019-12-13 08:34:33 -0800154 quiche::QuicheStringPiece(reinterpret_cast<const char*>(data), len));
nharper6ebe83b2019-06-13 17:43:52 -0700155 return 1;
156}
157
158// static
159int TlsConnection::FlushFlightCallback(SSL* ssl) {
160 ConnectionFromSsl(ssl)->delegate_->FlushFlight();
161 return 1;
162}
163
164// static
165int TlsConnection::SendAlertCallback(SSL* ssl,
166 enum ssl_encryption_level_t level,
167 uint8_t desc) {
168 ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level),
169 desc);
170 return 1;
171}
172
173} // namespace quic