blob: d28db2292e48cfddb1ceb83dfb152e893aca0343 [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"
8
9namespace quic {
10
11namespace {
12
13// BoringSSL allows storing extra data off of some of its data structures,
14// including the SSL struct. To allow for multiple callers to store data, each
15// caller can use a different index for setting and getting data. These indices
16// are globals handed out by calling SSL_get_ex_new_index.
17//
18// SslIndexSingleton calls SSL_get_ex_new_index on its construction, and then
19// provides this index to be used in calls to SSL_get_ex_data/SSL_set_ex_data.
20// This is used to store in the SSL struct a pointer to the TlsConnection which
21// owns it.
22class SslIndexSingleton {
23 public:
24 static SslIndexSingleton* GetInstance() {
25 static SslIndexSingleton* instance = new SslIndexSingleton();
26 return instance;
27 }
28
29 int ssl_ex_data_index_connection() const {
30 return ssl_ex_data_index_connection_;
31 }
32
33 private:
34 SslIndexSingleton() {
35 CRYPTO_library_init();
36 ssl_ex_data_index_connection_ =
37 SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
38 CHECK_LE(0, ssl_ex_data_index_connection_);
39 }
40
41 SslIndexSingleton(const SslIndexSingleton&) = delete;
42 SslIndexSingleton& operator=(const SslIndexSingleton&) = delete;
43
44 // The index to supply to SSL_get_ex_data/SSL_set_ex_data for getting/setting
45 // the TlsConnection pointer.
46 int ssl_ex_data_index_connection_;
47};
48
49} // namespace
50
51// static
52EncryptionLevel TlsConnection::QuicEncryptionLevel(
53 enum ssl_encryption_level_t level) {
54 switch (level) {
55 case ssl_encryption_initial:
56 return ENCRYPTION_INITIAL;
57 case ssl_encryption_early_data:
58 return ENCRYPTION_ZERO_RTT;
59 case ssl_encryption_handshake:
60 return ENCRYPTION_HANDSHAKE;
61 case ssl_encryption_application:
62 return ENCRYPTION_FORWARD_SECURE;
63 default:
64 QUIC_BUG << "Invalid ssl_encryption_level_t " << static_cast<int>(level);
65 return ENCRYPTION_INITIAL;
66 }
67}
68
69// static
70enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel(
71 EncryptionLevel level) {
72 switch (level) {
73 case ENCRYPTION_INITIAL:
74 return ssl_encryption_initial;
75 case ENCRYPTION_HANDSHAKE:
76 return ssl_encryption_handshake;
77 case ENCRYPTION_ZERO_RTT:
78 return ssl_encryption_early_data;
79 case ENCRYPTION_FORWARD_SECURE:
80 return ssl_encryption_application;
81 default:
82 QUIC_BUG << "Invalid encryption level " << static_cast<int>(level);
83 return ssl_encryption_initial;
84 }
85}
86
87TlsConnection::TlsConnection(SSL_CTX* ssl_ctx,
88 TlsConnection::Delegate* delegate)
89 : delegate_(delegate), ssl_(SSL_new(ssl_ctx)) {
90 SSL_set_ex_data(
91 ssl(), SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection(),
92 this);
93}
94// static
95bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx() {
96 CRYPTO_library_init();
97 bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_with_buffers_method()));
98 SSL_CTX_set_min_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
99 SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION);
100 SSL_CTX_set_quic_method(ssl_ctx.get(), &kSslQuicMethod);
101 return ssl_ctx;
102}
103
104// static
105TlsConnection* TlsConnection::ConnectionFromSsl(const SSL* ssl) {
106 return reinterpret_cast<TlsConnection*>(SSL_get_ex_data(
107 ssl, SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection()));
108}
109
110const SSL_QUIC_METHOD TlsConnection::kSslQuicMethod{
111 TlsConnection::SetEncryptionSecretCallback,
112 TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
113 TlsConnection::SendAlertCallback};
114
115// static
116int TlsConnection::SetEncryptionSecretCallback(
117 SSL* ssl,
118 enum ssl_encryption_level_t level,
119 const uint8_t* read_key,
120 const uint8_t* write_key,
121 size_t key_length) {
122 // TODO(nharper): replace these vectors and memcpys with spans (which
123 // unfortunately doesn't yet exist in quic/platform/api).
124 std::vector<uint8_t> read_secret(key_length), write_secret(key_length);
125 memcpy(read_secret.data(), read_key, key_length);
126 memcpy(write_secret.data(), write_key, key_length);
127 ConnectionFromSsl(ssl)->delegate_->SetEncryptionSecret(
128 QuicEncryptionLevel(level), read_secret, write_secret);
129 return 1;
130}
131
132// static
133int TlsConnection::WriteMessageCallback(SSL* ssl,
134 enum ssl_encryption_level_t level,
135 const uint8_t* data,
136 size_t len) {
137 ConnectionFromSsl(ssl)->delegate_->WriteMessage(
138 QuicEncryptionLevel(level),
139 QuicStringPiece(reinterpret_cast<const char*>(data), len));
140 return 1;
141}
142
143// static
144int TlsConnection::FlushFlightCallback(SSL* ssl) {
145 ConnectionFromSsl(ssl)->delegate_->FlushFlight();
146 return 1;
147}
148
149// static
150int TlsConnection::SendAlertCallback(SSL* ssl,
151 enum ssl_encryption_level_t level,
152 uint8_t desc) {
153 ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level),
154 desc);
155 return 1;
156}
157
158} // namespace quic