blob: fdda21f705f516310e0ecc7db72f18a2a013c3ec [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 CrypterPair crypters;
59 CryptoUtils::CreateTlsInitialCrypters(
60 Perspective::IS_SERVER, session->connection()->transport_version(),
61 session->connection_id(), &crypters);
QUICHE team6987b4a2019-03-15 16:23:04 -070062 session->connection()->SetEncrypter(ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 std::move(crypters.encrypter));
zhongyi546cc452019-04-12 15:27:49 -070064 session->connection()->InstallDecrypter(ENCRYPTION_INITIAL,
65 std::move(crypters.decrypter));
QUICHE teama6ef0a62019-03-07 20:34:33 -050066
67 // Configure the SSL to be a server.
68 SSL_set_accept_state(ssl());
69
70 if (!SetTransportParameters()) {
71 CloseConnection(QUIC_HANDSHAKE_FAILED,
72 "Failed to set Transport Parameters");
73 }
74}
75
76TlsServerHandshaker::~TlsServerHandshaker() {
77 CancelOutstandingCallbacks();
78}
79
80void TlsServerHandshaker::CancelOutstandingCallbacks() {
81 if (signature_callback_) {
82 signature_callback_->Cancel();
83 signature_callback_ = nullptr;
84 }
85}
86
87bool TlsServerHandshaker::GetBase64SHA256ClientChannelID(
vasilvvc48c8712019-03-11 13:38:16 -070088 std::string* output) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050089 // Channel ID is not supported when TLS is used in QUIC.
90 return false;
91}
92
93void TlsServerHandshaker::SendServerConfigUpdate(
94 const CachedNetworkParameters* cached_network_params) {
95 // SCUP messages aren't supported when using the TLS handshake.
96}
97
98uint8_t TlsServerHandshaker::NumHandshakeMessages() const {
99 // TODO(nharper): Return a sensible value here.
100 return 0;
101}
102
103uint8_t TlsServerHandshaker::NumHandshakeMessagesWithServerNonces() const {
104 // TODO(nharper): Return a sensible value here.
105 return 0;
106}
107
108int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
109 // SCUP messages aren't supported when using the TLS handshake.
110 return 0;
111}
112
113const CachedNetworkParameters*
114TlsServerHandshaker::PreviousCachedNetworkParams() const {
115 return nullptr;
116}
117
118bool TlsServerHandshaker::ZeroRttAttempted() const {
119 // TODO(nharper): Support 0-RTT with TLS 1.3 in QUIC.
120 return false;
121}
122
123void TlsServerHandshaker::SetPreviousCachedNetworkParams(
124 CachedNetworkParameters cached_network_params) {}
125
126bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
127 return false;
128}
129
130bool TlsServerHandshaker::encryption_established() const {
131 return encryption_established_;
132}
133
134bool TlsServerHandshaker::handshake_confirmed() const {
135 return handshake_confirmed_;
136}
137
138const QuicCryptoNegotiatedParameters&
139TlsServerHandshaker::crypto_negotiated_params() const {
140 return *crypto_negotiated_params_;
141}
142
143CryptoMessageParser* TlsServerHandshaker::crypto_message_parser() {
144 return TlsHandshaker::crypto_message_parser();
145}
146
147void TlsServerHandshaker::AdvanceHandshake() {
148 if (state_ == STATE_CONNECTION_CLOSED) {
149 QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
150 "connection was closed";
151 return;
152 }
153 if (state_ == STATE_HANDSHAKE_COMPLETE) {
154 // TODO(nharper): Handle post-handshake messages.
155 return;
156 }
157
158 int rv = SSL_do_handshake(ssl());
159 if (rv == 1) {
160 FinishHandshake();
161 return;
162 }
163
164 int ssl_error = SSL_get_error(ssl(), rv);
165 bool should_close = true;
166 switch (state_) {
167 case STATE_LISTENING:
168 case STATE_SIGNATURE_COMPLETE:
169 should_close = ssl_error != SSL_ERROR_WANT_READ;
170 break;
171 case STATE_SIGNATURE_PENDING:
172 should_close = ssl_error != SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
173 break;
174 default:
175 should_close = true;
176 }
177 if (should_close && state_ != STATE_CONNECTION_CLOSED) {
178 QUIC_LOG(WARNING) << "SSL_do_handshake failed; SSL_get_error returns "
179 << ssl_error << ", state_ = " << state_;
180 ERR_print_errors_fp(stderr);
181 CloseConnection(QUIC_HANDSHAKE_FAILED, "TLS handshake failed");
182 }
183}
184
185void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700186 const std::string& reason_phrase) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500187 state_ = STATE_CONNECTION_CLOSED;
188 stream()->CloseConnectionWithDetails(error, reason_phrase);
189}
190
191bool TlsServerHandshaker::ProcessTransportParameters(
vasilvvc48c8712019-03-11 13:38:16 -0700192 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 TransportParameters client_params;
194 const uint8_t* client_params_bytes;
195 size_t params_bytes_len;
196 SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
197 &params_bytes_len);
198 if (params_bytes_len == 0 ||
199 !ParseTransportParameters(client_params_bytes, params_bytes_len,
200 Perspective::IS_CLIENT, &client_params)) {
201 *error_details = "Unable to parse Transport Parameters";
202 return false;
203 }
dschinazi6cf4d2a2019-04-30 16:20:23 -0700204
205 // When interoperating with non-Google implementations that do not send
206 // the version extension, set it to what we expect.
207 if (client_params.version == 0) {
208 client_params.version =
209 CreateQuicVersionLabel(session()->connection()->version());
210 }
211
QUICHE teama6ef0a62019-03-07 20:34:33 -0500212 if (CryptoUtils::ValidateClientHelloVersion(
213 client_params.version, session()->connection()->version(),
214 session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
215 session()->config()->ProcessTransportParameters(
216 client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
217 return false;
218 }
219
220 session()->OnConfigNegotiated();
221 return true;
222}
223
224bool TlsServerHandshaker::SetTransportParameters() {
225 TransportParameters server_params;
226 server_params.perspective = Perspective::IS_SERVER;
227 server_params.supported_versions =
228 CreateQuicVersionLabelVector(session()->supported_versions());
229 server_params.version =
230 CreateQuicVersionLabel(session()->connection()->version());
231
232 if (!session()->config()->FillTransportParameters(&server_params)) {
233 return false;
234 }
235
236 // TODO(nharper): Provide an actual value for the stateless reset token.
237 server_params.stateless_reset_token.resize(16);
238 std::vector<uint8_t> server_params_bytes;
239 if (!SerializeTransportParameters(server_params, &server_params_bytes) ||
240 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() {
248 QUIC_LOG(INFO) << "Server: handshake finished";
249 state_ = STATE_HANDSHAKE_COMPLETE;
250
251 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
252 session()->NeuterUnencryptedData();
253 encryption_established_ = true;
254 handshake_confirmed_ = true;
255}
256
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
258 uint8_t* out,
259 size_t* out_len,
260 size_t max_out,
261 uint16_t sig_alg,
262 QuicStringPiece in) {
263 signature_callback_ = new SignatureCallback(this);
264 proof_source_->ComputeTlsSignature(
265 session()->connection()->self_address(), hostname_, sig_alg, in,
266 std::unique_ptr<SignatureCallback>(signature_callback_));
267 if (state_ == STATE_SIGNATURE_COMPLETE) {
268 return PrivateKeyComplete(out, out_len, max_out);
269 }
270 state_ = STATE_SIGNATURE_PENDING;
271 return ssl_private_key_retry;
272}
273
QUICHE teama6ef0a62019-03-07 20:34:33 -0500274ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
275 uint8_t* out,
276 size_t* out_len,
277 size_t max_out) {
278 if (state_ == STATE_SIGNATURE_PENDING) {
279 return ssl_private_key_retry;
280 }
281 if (cert_verify_sig_.size() > max_out || cert_verify_sig_.empty()) {
282 return ssl_private_key_failure;
283 }
284 *out_len = cert_verify_sig_.size();
285 memcpy(out, cert_verify_sig_.data(), *out_len);
286 cert_verify_sig_.clear();
287 cert_verify_sig_.shrink_to_fit();
288 return ssl_private_key_success;
289}
290
QUICHE teama6ef0a62019-03-07 20:34:33 -0500291int TlsServerHandshaker::SelectCertificate(int* out_alert) {
292 const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
293 if (hostname) {
294 hostname_ = hostname;
295 } else {
296 QUIC_LOG(INFO) << "No hostname indicated in SNI";
297 }
298
299 QuicReferenceCountedPointer<ProofSource::Chain> chain =
300 proof_source_->GetCertChain(session()->connection()->self_address(),
301 hostname_);
302 if (chain->certs.empty()) {
303 QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
304 return SSL_TLSEXT_ERR_ALERT_FATAL;
305 }
306
307 std::vector<CRYPTO_BUFFER*> certs;
308 certs.resize(chain->certs.size());
309 for (size_t i = 0; i < certs.size(); i++) {
310 certs[i] = CRYPTO_BUFFER_new(
311 reinterpret_cast<const uint8_t*>(chain->certs[i].data()),
312 chain->certs[i].length(), nullptr);
313 }
314
nharper6ebe83b2019-06-13 17:43:52 -0700315 tls_connection_.SetCertChain(certs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500316
317 for (size_t i = 0; i < certs.size(); i++) {
318 CRYPTO_BUFFER_free(certs[i]);
319 }
320
vasilvvc48c8712019-03-11 13:38:16 -0700321 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500322 if (!ProcessTransportParameters(&error_details)) {
323 CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
324 *out_alert = SSL_AD_INTERNAL_ERROR;
325 return SSL_TLSEXT_ERR_ALERT_FATAL;
326 }
327
328 QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
329 return SSL_TLSEXT_ERR_OK;
330}
331
dschinazi35e749e2019-04-09 09:36:04 -0700332int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
333 uint8_t* out_len,
334 const uint8_t* in,
335 unsigned in_len) {
336 // |in| contains a sequence of 1-byte-length-prefixed values.
337 // We currently simply return the first provided ALPN value.
338 // TODO(b/130164908) Act on ALPN.
339 if (in_len == 0) {
340 *out_len = 0;
341 *out = nullptr;
342 QUIC_DLOG(INFO) << "No ALPN provided";
343 return SSL_TLSEXT_ERR_OK;
344 }
345 const uint8_t first_alpn_length = in[0];
346 if (static_cast<unsigned>(first_alpn_length) > in_len - 1) {
347 QUIC_LOG(ERROR) << "Failed to parse ALPN";
348 return SSL_TLSEXT_ERR_ALERT_FATAL;
349 }
350 *out_len = first_alpn_length;
351 *out = in + 1;
352 QUIC_DLOG(INFO) << "Server selecting ALPN '"
353 << QuicStringPiece(reinterpret_cast<const char*>(*out),
354 *out_len)
355 << "'";
356 return SSL_TLSEXT_ERR_OK;
357}
358
QUICHE teama6ef0a62019-03-07 20:34:33 -0500359} // namespace quic