blob: ca56e4dd3d2c4a465eeb846de3d949265d1d7186 [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
43const SSL_PRIVATE_KEY_METHOD TlsServerHandshaker::kPrivateKeyMethod{
44 &TlsServerHandshaker::PrivateKeySign,
45 nullptr, // decrypt
46 &TlsServerHandshaker::PrivateKeyComplete,
47};
48
49// static
50bssl::UniquePtr<SSL_CTX> TlsServerHandshaker::CreateSslCtx() {
51 bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsHandshaker::CreateSslCtx();
52 SSL_CTX_set_tlsext_servername_callback(
53 ssl_ctx.get(), TlsServerHandshaker::SelectCertificateCallback);
dschinazi35e749e2019-04-09 09:36:04 -070054 SSL_CTX_set_alpn_select_cb(ssl_ctx.get(),
55 TlsServerHandshaker::SelectAlpnCallback, nullptr);
QUICHE teama6ef0a62019-03-07 20:34:33 -050056 return ssl_ctx;
57}
58
59TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
60 QuicSession* session,
61 SSL_CTX* ssl_ctx,
62 ProofSource* proof_source)
63 : TlsHandshaker(stream, session, ssl_ctx),
64 proof_source_(proof_source),
65 crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {
zhongyi546cc452019-04-12 15:27:49 -070066 DCHECK_EQ(PROTOCOL_TLS1_3,
67 session->connection()->version().handshake_protocol);
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 CrypterPair crypters;
69 CryptoUtils::CreateTlsInitialCrypters(
70 Perspective::IS_SERVER, session->connection()->transport_version(),
71 session->connection_id(), &crypters);
QUICHE team6987b4a2019-03-15 16:23:04 -070072 session->connection()->SetEncrypter(ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 std::move(crypters.encrypter));
zhongyi546cc452019-04-12 15:27:49 -070074 session->connection()->InstallDecrypter(ENCRYPTION_INITIAL,
75 std::move(crypters.decrypter));
QUICHE teama6ef0a62019-03-07 20:34:33 -050076
77 // Configure the SSL to be a server.
78 SSL_set_accept_state(ssl());
79
80 if (!SetTransportParameters()) {
81 CloseConnection(QUIC_HANDSHAKE_FAILED,
82 "Failed to set Transport Parameters");
83 }
84}
85
86TlsServerHandshaker::~TlsServerHandshaker() {
87 CancelOutstandingCallbacks();
88}
89
90void TlsServerHandshaker::CancelOutstandingCallbacks() {
91 if (signature_callback_) {
92 signature_callback_->Cancel();
93 signature_callback_ = nullptr;
94 }
95}
96
97bool TlsServerHandshaker::GetBase64SHA256ClientChannelID(
vasilvvc48c8712019-03-11 13:38:16 -070098 std::string* output) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050099 // Channel ID is not supported when TLS is used in QUIC.
100 return false;
101}
102
103void TlsServerHandshaker::SendServerConfigUpdate(
104 const CachedNetworkParameters* cached_network_params) {
105 // SCUP messages aren't supported when using the TLS handshake.
106}
107
108uint8_t TlsServerHandshaker::NumHandshakeMessages() const {
109 // TODO(nharper): Return a sensible value here.
110 return 0;
111}
112
113uint8_t TlsServerHandshaker::NumHandshakeMessagesWithServerNonces() const {
114 // TODO(nharper): Return a sensible value here.
115 return 0;
116}
117
118int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
119 // SCUP messages aren't supported when using the TLS handshake.
120 return 0;
121}
122
123const CachedNetworkParameters*
124TlsServerHandshaker::PreviousCachedNetworkParams() const {
125 return nullptr;
126}
127
128bool TlsServerHandshaker::ZeroRttAttempted() const {
129 // TODO(nharper): Support 0-RTT with TLS 1.3 in QUIC.
130 return false;
131}
132
133void TlsServerHandshaker::SetPreviousCachedNetworkParams(
134 CachedNetworkParameters cached_network_params) {}
135
136bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
137 return false;
138}
139
140bool TlsServerHandshaker::encryption_established() const {
141 return encryption_established_;
142}
143
144bool TlsServerHandshaker::handshake_confirmed() const {
145 return handshake_confirmed_;
146}
147
148const QuicCryptoNegotiatedParameters&
149TlsServerHandshaker::crypto_negotiated_params() const {
150 return *crypto_negotiated_params_;
151}
152
153CryptoMessageParser* TlsServerHandshaker::crypto_message_parser() {
154 return TlsHandshaker::crypto_message_parser();
155}
156
157void TlsServerHandshaker::AdvanceHandshake() {
158 if (state_ == STATE_CONNECTION_CLOSED) {
159 QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
160 "connection was closed";
161 return;
162 }
163 if (state_ == STATE_HANDSHAKE_COMPLETE) {
164 // TODO(nharper): Handle post-handshake messages.
165 return;
166 }
167
168 int rv = SSL_do_handshake(ssl());
169 if (rv == 1) {
170 FinishHandshake();
171 return;
172 }
173
174 int ssl_error = SSL_get_error(ssl(), rv);
175 bool should_close = true;
176 switch (state_) {
177 case STATE_LISTENING:
178 case STATE_SIGNATURE_COMPLETE:
179 should_close = ssl_error != SSL_ERROR_WANT_READ;
180 break;
181 case STATE_SIGNATURE_PENDING:
182 should_close = ssl_error != SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
183 break;
184 default:
185 should_close = true;
186 }
187 if (should_close && state_ != STATE_CONNECTION_CLOSED) {
188 QUIC_LOG(WARNING) << "SSL_do_handshake failed; SSL_get_error returns "
189 << ssl_error << ", state_ = " << state_;
190 ERR_print_errors_fp(stderr);
191 CloseConnection(QUIC_HANDSHAKE_FAILED, "TLS handshake failed");
192 }
193}
194
195void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700196 const std::string& reason_phrase) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500197 state_ = STATE_CONNECTION_CLOSED;
198 stream()->CloseConnectionWithDetails(error, reason_phrase);
199}
200
201bool TlsServerHandshaker::ProcessTransportParameters(
vasilvvc48c8712019-03-11 13:38:16 -0700202 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500203 TransportParameters client_params;
204 const uint8_t* client_params_bytes;
205 size_t params_bytes_len;
206 SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
207 &params_bytes_len);
208 if (params_bytes_len == 0 ||
209 !ParseTransportParameters(client_params_bytes, params_bytes_len,
210 Perspective::IS_CLIENT, &client_params)) {
211 *error_details = "Unable to parse Transport Parameters";
212 return false;
213 }
dschinazi6cf4d2a2019-04-30 16:20:23 -0700214
215 // When interoperating with non-Google implementations that do not send
216 // the version extension, set it to what we expect.
217 if (client_params.version == 0) {
218 client_params.version =
219 CreateQuicVersionLabel(session()->connection()->version());
220 }
221
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222 if (CryptoUtils::ValidateClientHelloVersion(
223 client_params.version, session()->connection()->version(),
224 session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
225 session()->config()->ProcessTransportParameters(
226 client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
227 return false;
228 }
229
230 session()->OnConfigNegotiated();
231 return true;
232}
233
234bool TlsServerHandshaker::SetTransportParameters() {
235 TransportParameters server_params;
236 server_params.perspective = Perspective::IS_SERVER;
237 server_params.supported_versions =
238 CreateQuicVersionLabelVector(session()->supported_versions());
239 server_params.version =
240 CreateQuicVersionLabel(session()->connection()->version());
241
242 if (!session()->config()->FillTransportParameters(&server_params)) {
243 return false;
244 }
245
246 // TODO(nharper): Provide an actual value for the stateless reset token.
247 server_params.stateless_reset_token.resize(16);
248 std::vector<uint8_t> server_params_bytes;
249 if (!SerializeTransportParameters(server_params, &server_params_bytes) ||
250 SSL_set_quic_transport_params(ssl(), server_params_bytes.data(),
251 server_params_bytes.size()) != 1) {
252 return false;
253 }
254 return true;
255}
256
257void TlsServerHandshaker::FinishHandshake() {
258 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;
265}
266
267// static
268TlsServerHandshaker* TlsServerHandshaker::HandshakerFromSsl(SSL* ssl) {
269 return static_cast<TlsServerHandshaker*>(
270 TlsHandshaker::HandshakerFromSsl(ssl));
271}
272
273// static
274ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(SSL* ssl,
275 uint8_t* out,
276 size_t* out_len,
277 size_t max_out,
278 uint16_t sig_alg,
279 const uint8_t* in,
280 size_t in_len) {
281 return HandshakerFromSsl(ssl)->PrivateKeySign(
282 out, out_len, max_out, sig_alg,
283 QuicStringPiece(reinterpret_cast<const char*>(in), in_len));
284}
285
286ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
287 uint8_t* out,
288 size_t* out_len,
289 size_t max_out,
290 uint16_t sig_alg,
291 QuicStringPiece in) {
292 signature_callback_ = new SignatureCallback(this);
293 proof_source_->ComputeTlsSignature(
294 session()->connection()->self_address(), hostname_, sig_alg, in,
295 std::unique_ptr<SignatureCallback>(signature_callback_));
296 if (state_ == STATE_SIGNATURE_COMPLETE) {
297 return PrivateKeyComplete(out, out_len, max_out);
298 }
299 state_ = STATE_SIGNATURE_PENDING;
300 return ssl_private_key_retry;
301}
302
303// static
304ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
305 SSL* ssl,
306 uint8_t* out,
307 size_t* out_len,
308 size_t max_out) {
309 return HandshakerFromSsl(ssl)->PrivateKeyComplete(out, out_len, max_out);
310}
311
312ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
313 uint8_t* out,
314 size_t* out_len,
315 size_t max_out) {
316 if (state_ == STATE_SIGNATURE_PENDING) {
317 return ssl_private_key_retry;
318 }
319 if (cert_verify_sig_.size() > max_out || cert_verify_sig_.empty()) {
320 return ssl_private_key_failure;
321 }
322 *out_len = cert_verify_sig_.size();
323 memcpy(out, cert_verify_sig_.data(), *out_len);
324 cert_verify_sig_.clear();
325 cert_verify_sig_.shrink_to_fit();
326 return ssl_private_key_success;
327}
328
329// static
330int TlsServerHandshaker::SelectCertificateCallback(SSL* ssl,
331 int* out_alert,
332 void* arg) {
333 return HandshakerFromSsl(ssl)->SelectCertificate(out_alert);
334}
335
336int TlsServerHandshaker::SelectCertificate(int* out_alert) {
337 const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
338 if (hostname) {
339 hostname_ = hostname;
340 } else {
341 QUIC_LOG(INFO) << "No hostname indicated in SNI";
342 }
343
344 QuicReferenceCountedPointer<ProofSource::Chain> chain =
345 proof_source_->GetCertChain(session()->connection()->self_address(),
346 hostname_);
347 if (chain->certs.empty()) {
348 QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
349 return SSL_TLSEXT_ERR_ALERT_FATAL;
350 }
351
352 std::vector<CRYPTO_BUFFER*> certs;
353 certs.resize(chain->certs.size());
354 for (size_t i = 0; i < certs.size(); i++) {
355 certs[i] = CRYPTO_BUFFER_new(
356 reinterpret_cast<const uint8_t*>(chain->certs[i].data()),
357 chain->certs[i].length(), nullptr);
358 }
359
360 SSL_set_chain_and_key(ssl(), certs.data(), certs.size(), nullptr,
361 &kPrivateKeyMethod);
362
363 for (size_t i = 0; i < certs.size(); i++) {
364 CRYPTO_BUFFER_free(certs[i]);
365 }
366
vasilvvc48c8712019-03-11 13:38:16 -0700367 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500368 if (!ProcessTransportParameters(&error_details)) {
369 CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
370 *out_alert = SSL_AD_INTERNAL_ERROR;
371 return SSL_TLSEXT_ERR_ALERT_FATAL;
372 }
373
374 QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
375 return SSL_TLSEXT_ERR_OK;
376}
377
dschinazi35e749e2019-04-09 09:36:04 -0700378// static
379int TlsServerHandshaker::SelectAlpnCallback(SSL* ssl,
380 const uint8_t** out,
381 uint8_t* out_len,
382 const uint8_t* in,
383 unsigned in_len,
384 void* arg) {
385 return HandshakerFromSsl(ssl)->SelectAlpn(out, out_len, in, in_len);
386}
387
388int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
389 uint8_t* out_len,
390 const uint8_t* in,
391 unsigned in_len) {
392 // |in| contains a sequence of 1-byte-length-prefixed values.
393 // We currently simply return the first provided ALPN value.
394 // TODO(b/130164908) Act on ALPN.
395 if (in_len == 0) {
396 *out_len = 0;
397 *out = nullptr;
398 QUIC_DLOG(INFO) << "No ALPN provided";
399 return SSL_TLSEXT_ERR_OK;
400 }
401 const uint8_t first_alpn_length = in[0];
402 if (static_cast<unsigned>(first_alpn_length) > in_len - 1) {
403 QUIC_LOG(ERROR) << "Failed to parse ALPN";
404 return SSL_TLSEXT_ERR_ALERT_FATAL;
405 }
406 *out_len = first_alpn_length;
407 *out = in + 1;
408 QUIC_DLOG(INFO) << "Server selecting ALPN '"
409 << QuicStringPiece(reinterpret_cast<const char*>(*out),
410 *out_len)
411 << "'";
412 return SSL_TLSEXT_ERR_OK;
413}
414
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415} // namespace quic