blob: ec6a22639a32846db111fd9f3d33158366425288 [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{
112 TlsConnection::SetEncryptionSecretCallback,
113 TlsConnection::WriteMessageCallback, TlsConnection::FlushFlightCallback,
114 TlsConnection::SendAlertCallback};
115
116// static
117int TlsConnection::SetEncryptionSecretCallback(
118 SSL* ssl,
119 enum ssl_encryption_level_t level,
120 const uint8_t* read_key,
121 const uint8_t* write_key,
122 size_t key_length) {
123 // TODO(nharper): replace these vectors and memcpys with spans (which
124 // unfortunately doesn't yet exist in quic/platform/api).
125 std::vector<uint8_t> read_secret(key_length), write_secret(key_length);
126 memcpy(read_secret.data(), read_key, key_length);
127 memcpy(write_secret.data(), write_key, key_length);
fayangd2866522020-02-12 11:15:27 -0800128 if (!ConnectionFromSsl(ssl)->delegate_->SetEncryptionSecret(
129 QuicEncryptionLevel(level), read_secret, write_secret)) {
130 return 0;
131 }
nharper6ebe83b2019-06-13 17:43:52 -0700132 return 1;
133}
134
135// static
136int TlsConnection::WriteMessageCallback(SSL* ssl,
137 enum ssl_encryption_level_t level,
138 const uint8_t* data,
139 size_t len) {
140 ConnectionFromSsl(ssl)->delegate_->WriteMessage(
141 QuicEncryptionLevel(level),
dmcardle904ef182019-12-13 08:34:33 -0800142 quiche::QuicheStringPiece(reinterpret_cast<const char*>(data), len));
nharper6ebe83b2019-06-13 17:43:52 -0700143 return 1;
144}
145
146// static
147int TlsConnection::FlushFlightCallback(SSL* ssl) {
148 ConnectionFromSsl(ssl)->delegate_->FlushFlight();
149 return 1;
150}
151
152// static
153int TlsConnection::SendAlertCallback(SSL* ssl,
154 enum ssl_encryption_level_t level,
155 uint8_t desc) {
156 ConnectionFromSsl(ssl)->delegate_->SendAlert(QuicEncryptionLevel(level),
157 desc);
158 return 1;
159}
160
161} // namespace quic