blob: eea6f55b09037fafb72786e0ecad45a9348b6633 [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
139void TlsServerHandshaker::AdvanceHandshake() {
140 if (state_ == STATE_CONNECTION_CLOSED) {
141 QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
142 "connection was closed";
143 return;
144 }
145 if (state_ == STATE_HANDSHAKE_COMPLETE) {
146 // TODO(nharper): Handle post-handshake messages.
147 return;
148 }
149
150 int rv = SSL_do_handshake(ssl());
151 if (rv == 1) {
152 FinishHandshake();
153 return;
154 }
155
156 int ssl_error = SSL_get_error(ssl(), rv);
157 bool should_close = true;
158 switch (state_) {
159 case STATE_LISTENING:
160 case STATE_SIGNATURE_COMPLETE:
161 should_close = ssl_error != SSL_ERROR_WANT_READ;
162 break;
163 case STATE_SIGNATURE_PENDING:
164 should_close = ssl_error != SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
165 break;
166 default:
167 should_close = true;
168 }
169 if (should_close && state_ != STATE_CONNECTION_CLOSED) {
170 QUIC_LOG(WARNING) << "SSL_do_handshake failed; SSL_get_error returns "
171 << ssl_error << ", state_ = " << state_;
172 ERR_print_errors_fp(stderr);
dschinazi91453642019-08-01 11:12:15 -0700173 CloseConnection(QUIC_HANDSHAKE_FAILED,
174 "Server observed TLS handshake failure");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500175 }
176}
177
178void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700179 const std::string& reason_phrase) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500180 state_ = STATE_CONNECTION_CLOSED;
181 stream()->CloseConnectionWithDetails(error, reason_phrase);
182}
183
184bool TlsServerHandshaker::ProcessTransportParameters(
vasilvvc48c8712019-03-11 13:38:16 -0700185 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500186 TransportParameters client_params;
187 const uint8_t* client_params_bytes;
188 size_t params_bytes_len;
189 SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
190 &params_bytes_len);
191 if (params_bytes_len == 0 ||
dschinazi6c84c142019-07-31 09:11:49 -0700192 !ParseTransportParameters(session()->connection()->version(),
193 Perspective::IS_CLIENT, client_params_bytes,
194 params_bytes_len, &client_params)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500195 *error_details = "Unable to parse Transport Parameters";
196 return false;
197 }
dschinazi6cf4d2a2019-04-30 16:20:23 -0700198
199 // When interoperating with non-Google implementations that do not send
200 // the version extension, set it to what we expect.
201 if (client_params.version == 0) {
202 client_params.version =
203 CreateQuicVersionLabel(session()->connection()->version());
204 }
205
QUICHE teama6ef0a62019-03-07 20:34:33 -0500206 if (CryptoUtils::ValidateClientHelloVersion(
207 client_params.version, session()->connection()->version(),
208 session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
209 session()->config()->ProcessTransportParameters(
210 client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
211 return false;
212 }
213
214 session()->OnConfigNegotiated();
215 return true;
216}
217
218bool TlsServerHandshaker::SetTransportParameters() {
219 TransportParameters server_params;
220 server_params.perspective = Perspective::IS_SERVER;
221 server_params.supported_versions =
222 CreateQuicVersionLabelVector(session()->supported_versions());
223 server_params.version =
224 CreateQuicVersionLabel(session()->connection()->version());
225
226 if (!session()->config()->FillTransportParameters(&server_params)) {
227 return false;
228 }
229
230 // TODO(nharper): Provide an actual value for the stateless reset token.
231 server_params.stateless_reset_token.resize(16);
232 std::vector<uint8_t> server_params_bytes;
dschinazi6c84c142019-07-31 09:11:49 -0700233 if (!SerializeTransportParameters(session()->connection()->version(),
234 server_params, &server_params_bytes) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 SSL_set_quic_transport_params(ssl(), server_params_bytes.data(),
236 server_params_bytes.size()) != 1) {
237 return false;
238 }
239 return true;
240}
241
242void TlsServerHandshaker::FinishHandshake() {
dschinazi91453642019-08-01 11:12:15 -0700243 if (!valid_alpn_received_) {
244 QUIC_DLOG(ERROR)
245 << "Server: handshake finished without receiving a known ALPN";
246 // TODO(b/130164908) this should send no_application_protocol
247 // instead of QUIC_HANDSHAKE_FAILED.
248 CloseConnection(QUIC_HANDSHAKE_FAILED,
249 "Server did not receive a known ALPN");
250 return;
251 }
252
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 QUIC_LOG(INFO) << "Server: handshake finished";
254 state_ = STATE_HANDSHAKE_COMPLETE;
255
256 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
257 session()->NeuterUnencryptedData();
258 encryption_established_ = true;
259 handshake_confirmed_ = true;
nharper8a72e4f2019-08-13 19:17:08 -0700260 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261}
262
QUICHE teama6ef0a62019-03-07 20:34:33 -0500263ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
264 uint8_t* out,
265 size_t* out_len,
266 size_t max_out,
267 uint16_t sig_alg,
268 QuicStringPiece in) {
269 signature_callback_ = new SignatureCallback(this);
270 proof_source_->ComputeTlsSignature(
271 session()->connection()->self_address(), hostname_, sig_alg, in,
272 std::unique_ptr<SignatureCallback>(signature_callback_));
273 if (state_ == STATE_SIGNATURE_COMPLETE) {
274 return PrivateKeyComplete(out, out_len, max_out);
275 }
276 state_ = STATE_SIGNATURE_PENDING;
277 return ssl_private_key_retry;
278}
279
QUICHE teama6ef0a62019-03-07 20:34:33 -0500280ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
281 uint8_t* out,
282 size_t* out_len,
283 size_t max_out) {
284 if (state_ == STATE_SIGNATURE_PENDING) {
285 return ssl_private_key_retry;
286 }
287 if (cert_verify_sig_.size() > max_out || cert_verify_sig_.empty()) {
288 return ssl_private_key_failure;
289 }
290 *out_len = cert_verify_sig_.size();
291 memcpy(out, cert_verify_sig_.data(), *out_len);
292 cert_verify_sig_.clear();
293 cert_verify_sig_.shrink_to_fit();
294 return ssl_private_key_success;
295}
296
QUICHE teama6ef0a62019-03-07 20:34:33 -0500297int TlsServerHandshaker::SelectCertificate(int* out_alert) {
298 const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
299 if (hostname) {
300 hostname_ = hostname;
301 } else {
302 QUIC_LOG(INFO) << "No hostname indicated in SNI";
303 }
304
305 QuicReferenceCountedPointer<ProofSource::Chain> chain =
306 proof_source_->GetCertChain(session()->connection()->self_address(),
307 hostname_);
308 if (chain->certs.empty()) {
309 QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
310 return SSL_TLSEXT_ERR_ALERT_FATAL;
311 }
312
313 std::vector<CRYPTO_BUFFER*> certs;
314 certs.resize(chain->certs.size());
315 for (size_t i = 0; i < certs.size(); i++) {
316 certs[i] = CRYPTO_BUFFER_new(
317 reinterpret_cast<const uint8_t*>(chain->certs[i].data()),
318 chain->certs[i].length(), nullptr);
319 }
320
nharper6ebe83b2019-06-13 17:43:52 -0700321 tls_connection_.SetCertChain(certs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500322
323 for (size_t i = 0; i < certs.size(); i++) {
324 CRYPTO_BUFFER_free(certs[i]);
325 }
326
vasilvvc48c8712019-03-11 13:38:16 -0700327 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500328 if (!ProcessTransportParameters(&error_details)) {
329 CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
330 *out_alert = SSL_AD_INTERNAL_ERROR;
331 return SSL_TLSEXT_ERR_ALERT_FATAL;
332 }
333
334 QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
335 return SSL_TLSEXT_ERR_OK;
336}
337
dschinazi35e749e2019-04-09 09:36:04 -0700338int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
339 uint8_t* out_len,
340 const uint8_t* in,
341 unsigned in_len) {
342 // |in| contains a sequence of 1-byte-length-prefixed values.
dschinazi91453642019-08-01 11:12:15 -0700343 *out_len = 0;
344 *out = nullptr;
dschinazi35e749e2019-04-09 09:36:04 -0700345 if (in_len == 0) {
dschinazi91453642019-08-01 11:12:15 -0700346 QUIC_DLOG(ERROR) << "No ALPN provided by client";
347 return SSL_TLSEXT_ERR_NOACK;
dschinazi35e749e2019-04-09 09:36:04 -0700348 }
dschinazi91453642019-08-01 11:12:15 -0700349
350 std::string expected_alpn_string =
351 AlpnForVersion(session()->connection()->version());
352
353 CBS all_alpns;
354 CBS_init(&all_alpns, in, in_len);
355
356 while (CBS_len(&all_alpns) > 0) {
357 CBS alpn;
358 if (!CBS_get_u8_length_prefixed(&all_alpns, &alpn)) {
359 QUIC_DLOG(ERROR) << "Failed to parse ALPN length";
360 return SSL_TLSEXT_ERR_NOACK;
361 }
362 const size_t alpn_length = CBS_len(&alpn);
363 if (alpn_length >
364 static_cast<size_t>(std::numeric_limits<uint8_t>::max())) {
365 QUIC_BUG << "Parsed impossible ALPN length " << alpn_length;
366 return SSL_TLSEXT_ERR_NOACK;
367 }
368 if (alpn_length == 0) {
369 QUIC_DLOG(ERROR) << "Received invalid zero-length ALPN";
370 return SSL_TLSEXT_ERR_NOACK;
371 }
372 std::string alpn_string(reinterpret_cast<const char*>(CBS_data(&alpn)),
373 alpn_length);
374 if (alpn_string == expected_alpn_string) {
375 QUIC_DLOG(INFO) << "Server selecting ALPN '" << alpn_string << "'";
376 *out_len = static_cast<uint8_t>(alpn_length);
377 *out = CBS_data(&alpn);
378 valid_alpn_received_ = true;
379 return SSL_TLSEXT_ERR_OK;
380 }
dschinazi35e749e2019-04-09 09:36:04 -0700381 }
dschinazi91453642019-08-01 11:12:15 -0700382
383 QUIC_DLOG(ERROR) << "No known ALPN provided by client";
384 return SSL_TLSEXT_ERR_NOACK;
dschinazi35e749e2019-04-09 09:36:04 -0700385}
386
QUICHE teama6ef0a62019-03-07 20:34:33 -0500387} // namespace quic