blob: 0b4215d3b04ab13ec1462b578d677ff741989428 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2017 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/tls_server_handshaker.h"
6
7#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009
10#include "third_party/boringssl/src/include/openssl/pool.h"
11#include "third_party/boringssl/src/include/openssl/ssl.h"
12#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
13#include "net/third_party/quiche/src/quic/core/crypto/transport_parameters.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016
17namespace quic {
18
19TlsServerHandshaker::SignatureCallback::SignatureCallback(
20 TlsServerHandshaker* handshaker)
21 : handshaker_(handshaker) {}
22
23void TlsServerHandshaker::SignatureCallback::Run(bool ok,
vasilvvc48c8712019-03-11 13:38:16 -070024 std::string signature) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 if (handshaker_ == nullptr) {
26 return;
27 }
28 if (ok) {
29 handshaker_->cert_verify_sig_ = std::move(signature);
30 }
31 State last_state = handshaker_->state_;
32 handshaker_->state_ = STATE_SIGNATURE_COMPLETE;
33 handshaker_->signature_callback_ = nullptr;
34 if (last_state == STATE_SIGNATURE_PENDING) {
35 handshaker_->AdvanceHandshake();
36 }
37}
38
39void TlsServerHandshaker::SignatureCallback::Cancel() {
40 handshaker_ = nullptr;
41}
42
QUICHE teama6ef0a62019-03-07 20:34:33 -050043// static
44bssl::UniquePtr<SSL_CTX> TlsServerHandshaker::CreateSslCtx() {
nharper6ebe83b2019-06-13 17:43:52 -070045 return TlsServerConnection::CreateSslCtx();
QUICHE teama6ef0a62019-03-07 20:34:33 -050046}
47
48TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
49 QuicSession* session,
50 SSL_CTX* ssl_ctx,
51 ProofSource* proof_source)
52 : TlsHandshaker(stream, session, ssl_ctx),
53 proof_source_(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -070054 crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
55 tls_connection_(ssl_ctx, this) {
zhongyi546cc452019-04-12 15:27:49 -070056 DCHECK_EQ(PROTOCOL_TLS1_3,
57 session->connection()->version().handshake_protocol);
QUICHE teama6ef0a62019-03-07 20:34:33 -050058
59 // Configure the SSL to be a server.
60 SSL_set_accept_state(ssl());
61
62 if (!SetTransportParameters()) {
63 CloseConnection(QUIC_HANDSHAKE_FAILED,
dschinazi91453642019-08-01 11:12:15 -070064 "Server failed to set Transport Parameters");
QUICHE teama6ef0a62019-03-07 20:34:33 -050065 }
66}
67
68TlsServerHandshaker::~TlsServerHandshaker() {
69 CancelOutstandingCallbacks();
70}
71
72void TlsServerHandshaker::CancelOutstandingCallbacks() {
73 if (signature_callback_) {
74 signature_callback_->Cancel();
75 signature_callback_ = nullptr;
76 }
77}
78
79bool TlsServerHandshaker::GetBase64SHA256ClientChannelID(
dschinazi17d42422019-06-18 16:35:07 -070080 std::string* /*output*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 // Channel ID is not supported when TLS is used in QUIC.
82 return false;
83}
84
85void TlsServerHandshaker::SendServerConfigUpdate(
dschinazi17d42422019-06-18 16:35:07 -070086 const CachedNetworkParameters* /*cached_network_params*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 // SCUP messages aren't supported when using the TLS handshake.
88}
89
90uint8_t TlsServerHandshaker::NumHandshakeMessages() const {
91 // TODO(nharper): Return a sensible value here.
92 return 0;
93}
94
95uint8_t TlsServerHandshaker::NumHandshakeMessagesWithServerNonces() const {
96 // TODO(nharper): Return a sensible value here.
97 return 0;
98}
99
100int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
101 // SCUP messages aren't supported when using the TLS handshake.
102 return 0;
103}
104
105const CachedNetworkParameters*
106TlsServerHandshaker::PreviousCachedNetworkParams() const {
107 return nullptr;
108}
109
110bool TlsServerHandshaker::ZeroRttAttempted() const {
111 // TODO(nharper): Support 0-RTT with TLS 1.3 in QUIC.
112 return false;
113}
114
115void TlsServerHandshaker::SetPreviousCachedNetworkParams(
dschinazi17d42422019-06-18 16:35:07 -0700116 CachedNetworkParameters /*cached_network_params*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117
118bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
119 return false;
120}
121
122bool TlsServerHandshaker::encryption_established() const {
123 return encryption_established_;
124}
125
126bool TlsServerHandshaker::handshake_confirmed() const {
127 return handshake_confirmed_;
128}
129
130const QuicCryptoNegotiatedParameters&
131TlsServerHandshaker::crypto_negotiated_params() const {
132 return *crypto_negotiated_params_;
133}
134
135CryptoMessageParser* TlsServerHandshaker::crypto_message_parser() {
136 return TlsHandshaker::crypto_message_parser();
137}
138
nharper486a8a92019-08-28 16:25:10 -0700139size_t TlsServerHandshaker::BufferSizeLimitForLevel(
140 EncryptionLevel level) const {
141 return TlsHandshaker::BufferSizeLimitForLevel(level);
142}
143
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144void TlsServerHandshaker::AdvanceHandshake() {
145 if (state_ == STATE_CONNECTION_CLOSED) {
146 QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
147 "connection was closed";
148 return;
149 }
150 if (state_ == STATE_HANDSHAKE_COMPLETE) {
151 // TODO(nharper): Handle post-handshake messages.
152 return;
153 }
154
155 int rv = SSL_do_handshake(ssl());
156 if (rv == 1) {
157 FinishHandshake();
158 return;
159 }
160
161 int ssl_error = SSL_get_error(ssl(), rv);
162 bool should_close = true;
163 switch (state_) {
164 case STATE_LISTENING:
165 case STATE_SIGNATURE_COMPLETE:
166 should_close = ssl_error != SSL_ERROR_WANT_READ;
167 break;
168 case STATE_SIGNATURE_PENDING:
169 should_close = ssl_error != SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
170 break;
171 default:
172 should_close = true;
173 }
174 if (should_close && state_ != STATE_CONNECTION_CLOSED) {
175 QUIC_LOG(WARNING) << "SSL_do_handshake failed; SSL_get_error returns "
176 << ssl_error << ", state_ = " << state_;
177 ERR_print_errors_fp(stderr);
dschinazi91453642019-08-01 11:12:15 -0700178 CloseConnection(QUIC_HANDSHAKE_FAILED,
179 "Server observed TLS handshake failure");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500180 }
181}
182
183void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700184 const std::string& reason_phrase) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 state_ = STATE_CONNECTION_CLOSED;
186 stream()->CloseConnectionWithDetails(error, reason_phrase);
187}
188
189bool TlsServerHandshaker::ProcessTransportParameters(
vasilvvc48c8712019-03-11 13:38:16 -0700190 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500191 TransportParameters client_params;
192 const uint8_t* client_params_bytes;
193 size_t params_bytes_len;
194 SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
195 &params_bytes_len);
196 if (params_bytes_len == 0 ||
dschinazi6c84c142019-07-31 09:11:49 -0700197 !ParseTransportParameters(session()->connection()->version(),
198 Perspective::IS_CLIENT, client_params_bytes,
199 params_bytes_len, &client_params)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500200 *error_details = "Unable to parse Transport Parameters";
201 return false;
202 }
dschinazi6cf4d2a2019-04-30 16:20:23 -0700203
204 // When interoperating with non-Google implementations that do not send
205 // the version extension, set it to what we expect.
206 if (client_params.version == 0) {
207 client_params.version =
208 CreateQuicVersionLabel(session()->connection()->version());
209 }
210
QUICHE teama6ef0a62019-03-07 20:34:33 -0500211 if (CryptoUtils::ValidateClientHelloVersion(
212 client_params.version, session()->connection()->version(),
213 session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
214 session()->config()->ProcessTransportParameters(
215 client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
216 return false;
217 }
218
219 session()->OnConfigNegotiated();
220 return true;
221}
222
223bool TlsServerHandshaker::SetTransportParameters() {
224 TransportParameters server_params;
225 server_params.perspective = Perspective::IS_SERVER;
226 server_params.supported_versions =
227 CreateQuicVersionLabelVector(session()->supported_versions());
228 server_params.version =
229 CreateQuicVersionLabel(session()->connection()->version());
230
231 if (!session()->config()->FillTransportParameters(&server_params)) {
232 return false;
233 }
234
235 // TODO(nharper): Provide an actual value for the stateless reset token.
236 server_params.stateless_reset_token.resize(16);
237 std::vector<uint8_t> server_params_bytes;
dschinazi6c84c142019-07-31 09:11:49 -0700238 if (!SerializeTransportParameters(session()->connection()->version(),
239 server_params, &server_params_bytes) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 SSL_set_quic_transport_params(ssl(), server_params_bytes.data(),
241 server_params_bytes.size()) != 1) {
242 return false;
243 }
244 return true;
245}
246
247void TlsServerHandshaker::FinishHandshake() {
dschinazi91453642019-08-01 11:12:15 -0700248 if (!valid_alpn_received_) {
249 QUIC_DLOG(ERROR)
250 << "Server: handshake finished without receiving a known ALPN";
251 // TODO(b/130164908) this should send no_application_protocol
252 // instead of QUIC_HANDSHAKE_FAILED.
253 CloseConnection(QUIC_HANDSHAKE_FAILED,
254 "Server did not receive a known ALPN");
255 return;
256 }
257
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 QUIC_LOG(INFO) << "Server: handshake finished";
259 state_ = STATE_HANDSHAKE_COMPLETE;
260
261 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
262 session()->NeuterUnencryptedData();
263 encryption_established_ = true;
264 handshake_confirmed_ = true;
nharper8a72e4f2019-08-13 19:17:08 -0700265 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500266}
267
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
269 uint8_t* out,
270 size_t* out_len,
271 size_t max_out,
272 uint16_t sig_alg,
273 QuicStringPiece in) {
274 signature_callback_ = new SignatureCallback(this);
275 proof_source_->ComputeTlsSignature(
276 session()->connection()->self_address(), hostname_, sig_alg, in,
277 std::unique_ptr<SignatureCallback>(signature_callback_));
278 if (state_ == STATE_SIGNATURE_COMPLETE) {
279 return PrivateKeyComplete(out, out_len, max_out);
280 }
281 state_ = STATE_SIGNATURE_PENDING;
282 return ssl_private_key_retry;
283}
284
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
286 uint8_t* out,
287 size_t* out_len,
288 size_t max_out) {
289 if (state_ == STATE_SIGNATURE_PENDING) {
290 return ssl_private_key_retry;
291 }
292 if (cert_verify_sig_.size() > max_out || cert_verify_sig_.empty()) {
293 return ssl_private_key_failure;
294 }
295 *out_len = cert_verify_sig_.size();
296 memcpy(out, cert_verify_sig_.data(), *out_len);
297 cert_verify_sig_.clear();
298 cert_verify_sig_.shrink_to_fit();
299 return ssl_private_key_success;
300}
301
QUICHE teama6ef0a62019-03-07 20:34:33 -0500302int TlsServerHandshaker::SelectCertificate(int* out_alert) {
303 const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
304 if (hostname) {
305 hostname_ = hostname;
306 } else {
307 QUIC_LOG(INFO) << "No hostname indicated in SNI";
308 }
309
310 QuicReferenceCountedPointer<ProofSource::Chain> chain =
311 proof_source_->GetCertChain(session()->connection()->self_address(),
312 hostname_);
313 if (chain->certs.empty()) {
314 QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
315 return SSL_TLSEXT_ERR_ALERT_FATAL;
316 }
317
318 std::vector<CRYPTO_BUFFER*> certs;
319 certs.resize(chain->certs.size());
320 for (size_t i = 0; i < certs.size(); i++) {
321 certs[i] = CRYPTO_BUFFER_new(
322 reinterpret_cast<const uint8_t*>(chain->certs[i].data()),
323 chain->certs[i].length(), nullptr);
324 }
325
nharper6ebe83b2019-06-13 17:43:52 -0700326 tls_connection_.SetCertChain(certs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327
328 for (size_t i = 0; i < certs.size(); i++) {
329 CRYPTO_BUFFER_free(certs[i]);
330 }
331
vasilvvc48c8712019-03-11 13:38:16 -0700332 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333 if (!ProcessTransportParameters(&error_details)) {
334 CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
335 *out_alert = SSL_AD_INTERNAL_ERROR;
336 return SSL_TLSEXT_ERR_ALERT_FATAL;
337 }
338
339 QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
340 return SSL_TLSEXT_ERR_OK;
341}
342
dschinazi35e749e2019-04-09 09:36:04 -0700343int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
344 uint8_t* out_len,
345 const uint8_t* in,
346 unsigned in_len) {
347 // |in| contains a sequence of 1-byte-length-prefixed values.
dschinazi91453642019-08-01 11:12:15 -0700348 *out_len = 0;
349 *out = nullptr;
dschinazi35e749e2019-04-09 09:36:04 -0700350 if (in_len == 0) {
dschinazi91453642019-08-01 11:12:15 -0700351 QUIC_DLOG(ERROR) << "No ALPN provided by client";
352 return SSL_TLSEXT_ERR_NOACK;
dschinazi35e749e2019-04-09 09:36:04 -0700353 }
dschinazi91453642019-08-01 11:12:15 -0700354
dschinazi91453642019-08-01 11:12:15 -0700355 CBS all_alpns;
356 CBS_init(&all_alpns, in, in_len);
357
vasilvvad7424f2019-08-30 00:27:14 -0700358 std::vector<QuicStringPiece> alpns;
dschinazi91453642019-08-01 11:12:15 -0700359 while (CBS_len(&all_alpns) > 0) {
360 CBS alpn;
361 if (!CBS_get_u8_length_prefixed(&all_alpns, &alpn)) {
362 QUIC_DLOG(ERROR) << "Failed to parse ALPN length";
363 return SSL_TLSEXT_ERR_NOACK;
364 }
vasilvvad7424f2019-08-30 00:27:14 -0700365
dschinazi91453642019-08-01 11:12:15 -0700366 const size_t alpn_length = CBS_len(&alpn);
dschinazi91453642019-08-01 11:12:15 -0700367 if (alpn_length == 0) {
368 QUIC_DLOG(ERROR) << "Received invalid zero-length ALPN";
369 return SSL_TLSEXT_ERR_NOACK;
370 }
vasilvvad7424f2019-08-30 00:27:14 -0700371
372 alpns.emplace_back(reinterpret_cast<const char*>(CBS_data(&alpn)),
373 alpn_length);
dschinazi35e749e2019-04-09 09:36:04 -0700374 }
dschinazi91453642019-08-01 11:12:15 -0700375
vasilvvad7424f2019-08-30 00:27:14 -0700376 auto selected_alpn = session()->SelectAlpn(alpns);
377 if (selected_alpn == alpns.end()) {
378 QUIC_DLOG(ERROR) << "No known ALPN provided by client";
379 return SSL_TLSEXT_ERR_NOACK;
380 }
381
382 session()->OnAlpnSelected(*selected_alpn);
383 valid_alpn_received_ = true;
384 *out_len = selected_alpn->size();
385 *out = reinterpret_cast<const uint8_t*>(selected_alpn->data());
386 return SSL_TLSEXT_ERR_OK;
dschinazi35e749e2019-04-09 09:36:04 -0700387}
388
QUICHE teama6ef0a62019-03-07 20:34:33 -0500389} // namespace quic