blob: 16c84b148a3f6d7dfc4b3c82efd701be5e594fe9 [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);
54 return ssl_ctx;
55}
56
57TlsServerHandshaker::TlsServerHandshaker(QuicCryptoStream* stream,
58 QuicSession* session,
59 SSL_CTX* ssl_ctx,
60 ProofSource* proof_source)
61 : TlsHandshaker(stream, session, ssl_ctx),
62 proof_source_(proof_source),
63 crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {
64 CrypterPair crypters;
65 CryptoUtils::CreateTlsInitialCrypters(
66 Perspective::IS_SERVER, session->connection()->transport_version(),
67 session->connection_id(), &crypters);
QUICHE team6987b4a2019-03-15 16:23:04 -070068 session->connection()->SetEncrypter(ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -050069 std::move(crypters.encrypter));
QUICHE team6987b4a2019-03-15 16:23:04 -070070 session->connection()->SetDecrypter(ENCRYPTION_INITIAL,
QUICHE teama6ef0a62019-03-07 20:34:33 -050071 std::move(crypters.decrypter));
72
73 // Configure the SSL to be a server.
74 SSL_set_accept_state(ssl());
75
76 if (!SetTransportParameters()) {
77 CloseConnection(QUIC_HANDSHAKE_FAILED,
78 "Failed to set Transport Parameters");
79 }
80}
81
82TlsServerHandshaker::~TlsServerHandshaker() {
83 CancelOutstandingCallbacks();
84}
85
86void TlsServerHandshaker::CancelOutstandingCallbacks() {
87 if (signature_callback_) {
88 signature_callback_->Cancel();
89 signature_callback_ = nullptr;
90 }
91}
92
93bool TlsServerHandshaker::GetBase64SHA256ClientChannelID(
vasilvvc48c8712019-03-11 13:38:16 -070094 std::string* output) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -050095 // Channel ID is not supported when TLS is used in QUIC.
96 return false;
97}
98
99void TlsServerHandshaker::SendServerConfigUpdate(
100 const CachedNetworkParameters* cached_network_params) {
101 // SCUP messages aren't supported when using the TLS handshake.
102}
103
104uint8_t TlsServerHandshaker::NumHandshakeMessages() const {
105 // TODO(nharper): Return a sensible value here.
106 return 0;
107}
108
109uint8_t TlsServerHandshaker::NumHandshakeMessagesWithServerNonces() const {
110 // TODO(nharper): Return a sensible value here.
111 return 0;
112}
113
114int TlsServerHandshaker::NumServerConfigUpdateMessagesSent() const {
115 // SCUP messages aren't supported when using the TLS handshake.
116 return 0;
117}
118
119const CachedNetworkParameters*
120TlsServerHandshaker::PreviousCachedNetworkParams() const {
121 return nullptr;
122}
123
124bool TlsServerHandshaker::ZeroRttAttempted() const {
125 // TODO(nharper): Support 0-RTT with TLS 1.3 in QUIC.
126 return false;
127}
128
129void TlsServerHandshaker::SetPreviousCachedNetworkParams(
130 CachedNetworkParameters cached_network_params) {}
131
132bool TlsServerHandshaker::ShouldSendExpectCTHeader() const {
133 return false;
134}
135
136bool TlsServerHandshaker::encryption_established() const {
137 return encryption_established_;
138}
139
140bool TlsServerHandshaker::handshake_confirmed() const {
141 return handshake_confirmed_;
142}
143
144const QuicCryptoNegotiatedParameters&
145TlsServerHandshaker::crypto_negotiated_params() const {
146 return *crypto_negotiated_params_;
147}
148
149CryptoMessageParser* TlsServerHandshaker::crypto_message_parser() {
150 return TlsHandshaker::crypto_message_parser();
151}
152
153void TlsServerHandshaker::AdvanceHandshake() {
154 if (state_ == STATE_CONNECTION_CLOSED) {
155 QUIC_LOG(INFO) << "TlsServerHandshaker received handshake message after "
156 "connection was closed";
157 return;
158 }
159 if (state_ == STATE_HANDSHAKE_COMPLETE) {
160 // TODO(nharper): Handle post-handshake messages.
161 return;
162 }
163
164 int rv = SSL_do_handshake(ssl());
165 if (rv == 1) {
166 FinishHandshake();
167 return;
168 }
169
170 int ssl_error = SSL_get_error(ssl(), rv);
171 bool should_close = true;
172 switch (state_) {
173 case STATE_LISTENING:
174 case STATE_SIGNATURE_COMPLETE:
175 should_close = ssl_error != SSL_ERROR_WANT_READ;
176 break;
177 case STATE_SIGNATURE_PENDING:
178 should_close = ssl_error != SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
179 break;
180 default:
181 should_close = true;
182 }
183 if (should_close && state_ != STATE_CONNECTION_CLOSED) {
184 QUIC_LOG(WARNING) << "SSL_do_handshake failed; SSL_get_error returns "
185 << ssl_error << ", state_ = " << state_;
186 ERR_print_errors_fp(stderr);
187 CloseConnection(QUIC_HANDSHAKE_FAILED, "TLS handshake failed");
188 }
189}
190
191void TlsServerHandshaker::CloseConnection(QuicErrorCode error,
vasilvvc48c8712019-03-11 13:38:16 -0700192 const std::string& reason_phrase) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500193 state_ = STATE_CONNECTION_CLOSED;
194 stream()->CloseConnectionWithDetails(error, reason_phrase);
195}
196
197bool TlsServerHandshaker::ProcessTransportParameters(
vasilvvc48c8712019-03-11 13:38:16 -0700198 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 TransportParameters client_params;
200 const uint8_t* client_params_bytes;
201 size_t params_bytes_len;
202 SSL_get_peer_quic_transport_params(ssl(), &client_params_bytes,
203 &params_bytes_len);
204 if (params_bytes_len == 0 ||
205 !ParseTransportParameters(client_params_bytes, params_bytes_len,
206 Perspective::IS_CLIENT, &client_params)) {
207 *error_details = "Unable to parse Transport Parameters";
208 return false;
209 }
210 if (CryptoUtils::ValidateClientHelloVersion(
211 client_params.version, session()->connection()->version(),
212 session()->supported_versions(), error_details) != QUIC_NO_ERROR ||
213 session()->config()->ProcessTransportParameters(
214 client_params, CLIENT, error_details) != QUIC_NO_ERROR) {
215 return false;
216 }
217
218 session()->OnConfigNegotiated();
219 return true;
220}
221
222bool TlsServerHandshaker::SetTransportParameters() {
223 TransportParameters server_params;
224 server_params.perspective = Perspective::IS_SERVER;
225 server_params.supported_versions =
226 CreateQuicVersionLabelVector(session()->supported_versions());
227 server_params.version =
228 CreateQuicVersionLabel(session()->connection()->version());
229
230 if (!session()->config()->FillTransportParameters(&server_params)) {
231 return false;
232 }
233
234 // TODO(nharper): Provide an actual value for the stateless reset token.
235 server_params.stateless_reset_token.resize(16);
236 std::vector<uint8_t> server_params_bytes;
237 if (!SerializeTransportParameters(server_params, &server_params_bytes) ||
238 SSL_set_quic_transport_params(ssl(), server_params_bytes.data(),
239 server_params_bytes.size()) != 1) {
240 return false;
241 }
242 return true;
243}
244
245void TlsServerHandshaker::FinishHandshake() {
246 QUIC_LOG(INFO) << "Server: handshake finished";
247 state_ = STATE_HANDSHAKE_COMPLETE;
248
249 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
250 session()->NeuterUnencryptedData();
251 encryption_established_ = true;
252 handshake_confirmed_ = true;
253}
254
255// static
256TlsServerHandshaker* TlsServerHandshaker::HandshakerFromSsl(SSL* ssl) {
257 return static_cast<TlsServerHandshaker*>(
258 TlsHandshaker::HandshakerFromSsl(ssl));
259}
260
261// static
262ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(SSL* ssl,
263 uint8_t* out,
264 size_t* out_len,
265 size_t max_out,
266 uint16_t sig_alg,
267 const uint8_t* in,
268 size_t in_len) {
269 return HandshakerFromSsl(ssl)->PrivateKeySign(
270 out, out_len, max_out, sig_alg,
271 QuicStringPiece(reinterpret_cast<const char*>(in), in_len));
272}
273
274ssl_private_key_result_t TlsServerHandshaker::PrivateKeySign(
275 uint8_t* out,
276 size_t* out_len,
277 size_t max_out,
278 uint16_t sig_alg,
279 QuicStringPiece in) {
280 signature_callback_ = new SignatureCallback(this);
281 proof_source_->ComputeTlsSignature(
282 session()->connection()->self_address(), hostname_, sig_alg, in,
283 std::unique_ptr<SignatureCallback>(signature_callback_));
284 if (state_ == STATE_SIGNATURE_COMPLETE) {
285 return PrivateKeyComplete(out, out_len, max_out);
286 }
287 state_ = STATE_SIGNATURE_PENDING;
288 return ssl_private_key_retry;
289}
290
291// static
292ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
293 SSL* ssl,
294 uint8_t* out,
295 size_t* out_len,
296 size_t max_out) {
297 return HandshakerFromSsl(ssl)->PrivateKeyComplete(out, out_len, max_out);
298}
299
300ssl_private_key_result_t TlsServerHandshaker::PrivateKeyComplete(
301 uint8_t* out,
302 size_t* out_len,
303 size_t max_out) {
304 if (state_ == STATE_SIGNATURE_PENDING) {
305 return ssl_private_key_retry;
306 }
307 if (cert_verify_sig_.size() > max_out || cert_verify_sig_.empty()) {
308 return ssl_private_key_failure;
309 }
310 *out_len = cert_verify_sig_.size();
311 memcpy(out, cert_verify_sig_.data(), *out_len);
312 cert_verify_sig_.clear();
313 cert_verify_sig_.shrink_to_fit();
314 return ssl_private_key_success;
315}
316
317// static
318int TlsServerHandshaker::SelectCertificateCallback(SSL* ssl,
319 int* out_alert,
320 void* arg) {
321 return HandshakerFromSsl(ssl)->SelectCertificate(out_alert);
322}
323
324int TlsServerHandshaker::SelectCertificate(int* out_alert) {
325 const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
326 if (hostname) {
327 hostname_ = hostname;
328 } else {
329 QUIC_LOG(INFO) << "No hostname indicated in SNI";
330 }
331
332 QuicReferenceCountedPointer<ProofSource::Chain> chain =
333 proof_source_->GetCertChain(session()->connection()->self_address(),
334 hostname_);
335 if (chain->certs.empty()) {
336 QUIC_LOG(ERROR) << "No certs provided for host '" << hostname_ << "'";
337 return SSL_TLSEXT_ERR_ALERT_FATAL;
338 }
339
340 std::vector<CRYPTO_BUFFER*> certs;
341 certs.resize(chain->certs.size());
342 for (size_t i = 0; i < certs.size(); i++) {
343 certs[i] = CRYPTO_BUFFER_new(
344 reinterpret_cast<const uint8_t*>(chain->certs[i].data()),
345 chain->certs[i].length(), nullptr);
346 }
347
348 SSL_set_chain_and_key(ssl(), certs.data(), certs.size(), nullptr,
349 &kPrivateKeyMethod);
350
351 for (size_t i = 0; i < certs.size(); i++) {
352 CRYPTO_BUFFER_free(certs[i]);
353 }
354
vasilvvc48c8712019-03-11 13:38:16 -0700355 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356 if (!ProcessTransportParameters(&error_details)) {
357 CloseConnection(QUIC_HANDSHAKE_FAILED, error_details);
358 *out_alert = SSL_AD_INTERNAL_ERROR;
359 return SSL_TLSEXT_ERR_ALERT_FATAL;
360 }
361
362 QUIC_LOG(INFO) << "Set " << chain->certs.size() << " certs for server";
363 return SSL_TLSEXT_ERR_OK;
364}
365
366} // namespace quic