blob: 158285dc66d3acbfd96dd6264013c1c877e5b28a [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 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/quic_crypto_client_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 "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
11#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
12#include "net/third_party/quiche/src/quic/core/quic_session.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017
18namespace quic {
19
QUICHE teama6ef0a62019-03-07 20:34:33 -050020QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
21 ProofVerifierCallbackImpl(QuicCryptoClientHandshaker* parent)
22 : parent_(parent) {}
23
24QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::
25 ~ProofVerifierCallbackImpl() {}
26
27void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Run(
28 bool ok,
vasilvvc48c8712019-03-11 13:38:16 -070029 const std::string& error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -050030 std::unique_ptr<ProofVerifyDetails>* details) {
31 if (parent_ == nullptr) {
32 return;
33 }
34
35 parent_->verify_ok_ = ok;
36 parent_->verify_error_details_ = error_details;
37 parent_->verify_details_ = std::move(*details);
38 parent_->proof_verify_callback_ = nullptr;
39 parent_->DoHandshakeLoop(nullptr);
40
41 // The ProofVerifier owns this object and will delete it when this method
42 // returns.
43}
44
45void QuicCryptoClientHandshaker::ProofVerifierCallbackImpl::Cancel() {
46 parent_ = nullptr;
47}
48
49QuicCryptoClientHandshaker::QuicCryptoClientHandshaker(
50 const QuicServerId& server_id,
51 QuicCryptoClientStream* stream,
52 QuicSession* session,
53 std::unique_ptr<ProofVerifyContext> verify_context,
54 QuicCryptoClientConfig* crypto_config,
55 QuicCryptoClientStream::ProofHandler* proof_handler)
56 : QuicCryptoHandshaker(stream, session),
57 stream_(stream),
58 session_(session),
59 next_state_(STATE_IDLE),
60 num_client_hellos_(0),
61 crypto_config_(crypto_config),
62 server_id_(server_id),
63 generation_counter_(0),
QUICHE teama6ef0a62019-03-07 20:34:33 -050064 verify_context_(std::move(verify_context)),
65 proof_verify_callback_(nullptr),
66 proof_handler_(proof_handler),
67 verify_ok_(false),
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 proof_verify_start_time_(QuicTime::Zero()),
69 num_scup_messages_received_(0),
70 encryption_established_(false),
71 handshake_confirmed_(false),
72 crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
73
74QuicCryptoClientHandshaker::~QuicCryptoClientHandshaker() {
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 if (proof_verify_callback_) {
76 proof_verify_callback_->Cancel();
77 }
78}
79
80void QuicCryptoClientHandshaker::OnHandshakeMessage(
81 const CryptoHandshakeMessage& message) {
82 QuicCryptoHandshaker::OnHandshakeMessage(message);
83 if (message.tag() == kSCUP) {
84 if (!handshake_confirmed()) {
85 stream_->CloseConnectionWithDetails(
86 QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE,
87 "Early SCUP disallowed");
88 return;
89 }
90
91 // |message| is an update from the server, so we treat it differently from a
92 // handshake message.
93 HandleServerConfigUpdateMessage(message);
94 num_scup_messages_received_++;
95 return;
96 }
97
98 // Do not process handshake messages after the handshake is confirmed.
99 if (handshake_confirmed()) {
100 stream_->CloseConnectionWithDetails(
101 QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
102 "Unexpected handshake message");
103 return;
104 }
105
106 DoHandshakeLoop(&message);
107}
108
109bool QuicCryptoClientHandshaker::CryptoConnect() {
110 next_state_ = STATE_INITIALIZE;
111 DoHandshakeLoop(nullptr);
112 return session()->connection()->connected();
113}
114
115int QuicCryptoClientHandshaker::num_sent_client_hellos() const {
116 return num_client_hellos_;
117}
118
119int QuicCryptoClientHandshaker::num_scup_messages_received() const {
120 return num_scup_messages_received_;
121}
122
vasilvvc48c8712019-03-11 13:38:16 -0700123std::string QuicCryptoClientHandshaker::chlo_hash() const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124 return chlo_hash_;
125}
126
127bool QuicCryptoClientHandshaker::encryption_established() const {
128 return encryption_established_;
129}
130
131bool QuicCryptoClientHandshaker::handshake_confirmed() const {
132 return handshake_confirmed_;
133}
134
135const QuicCryptoNegotiatedParameters&
136QuicCryptoClientHandshaker::crypto_negotiated_params() const {
137 return *crypto_negotiated_params_;
138}
139
140CryptoMessageParser* QuicCryptoClientHandshaker::crypto_message_parser() {
141 return QuicCryptoHandshaker::crypto_message_parser();
142}
143
144void QuicCryptoClientHandshaker::HandleServerConfigUpdateMessage(
145 const CryptoHandshakeMessage& server_config_update) {
146 DCHECK(server_config_update.tag() == kSCUP);
vasilvvc48c8712019-03-11 13:38:16 -0700147 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 QuicCryptoClientConfig::CachedState* cached =
149 crypto_config_->LookupOrCreate(server_id_);
150 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
151 server_config_update, session()->connection()->clock()->WallNow(),
152 session()->connection()->transport_version(), chlo_hash_, cached,
153 crypto_negotiated_params_, &error_details);
154
155 if (error != QUIC_NO_ERROR) {
156 stream_->CloseConnectionWithDetails(
157 error, "Server config update invalid: " + error_details);
158 return;
159 }
160
161 DCHECK(handshake_confirmed());
162 if (proof_verify_callback_) {
163 proof_verify_callback_->Cancel();
164 }
165 next_state_ = STATE_INITIALIZE_SCUP;
166 DoHandshakeLoop(nullptr);
167}
168
169void QuicCryptoClientHandshaker::DoHandshakeLoop(
170 const CryptoHandshakeMessage* in) {
171 QuicCryptoClientConfig::CachedState* cached =
172 crypto_config_->LookupOrCreate(server_id_);
173
174 QuicAsyncStatus rv = QUIC_SUCCESS;
175 do {
176 CHECK_NE(STATE_NONE, next_state_);
177 const State state = next_state_;
178 next_state_ = STATE_IDLE;
179 rv = QUIC_SUCCESS;
180 switch (state) {
181 case STATE_INITIALIZE:
182 DoInitialize(cached);
183 break;
184 case STATE_SEND_CHLO:
185 DoSendCHLO(cached);
186 return; // return waiting to hear from server.
187 case STATE_RECV_REJ:
188 DoReceiveREJ(in, cached);
189 break;
190 case STATE_VERIFY_PROOF:
191 rv = DoVerifyProof(cached);
192 break;
193 case STATE_VERIFY_PROOF_COMPLETE:
194 DoVerifyProofComplete(cached);
195 break;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500196 case STATE_RECV_SHLO:
197 DoReceiveSHLO(in, cached);
198 break;
199 case STATE_IDLE:
200 // This means that the peer sent us a message that we weren't expecting.
201 stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
202 "Handshake in idle state");
203 return;
204 case STATE_INITIALIZE_SCUP:
205 DoInitializeServerConfigUpdate(cached);
206 break;
207 case STATE_NONE:
208 QUIC_NOTREACHED();
209 return; // We are done.
210 }
211 } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
212}
213
214void QuicCryptoClientHandshaker::DoInitialize(
215 QuicCryptoClientConfig::CachedState* cached) {
216 if (!cached->IsEmpty() && !cached->signature().empty()) {
217 // Note that we verify the proof even if the cached proof is valid.
218 // This allows us to respond to CA trust changes or certificate
219 // expiration because it may have been a while since we last verified
220 // the proof.
221 DCHECK(crypto_config_->proof_verifier());
222 // Track proof verification time when cached server config is used.
223 proof_verify_start_time_ = session()->connection()->clock()->Now();
224 chlo_hash_ = cached->chlo_hash();
225 // If the cached state needs to be verified, do it now.
226 next_state_ = STATE_VERIFY_PROOF;
227 } else {
nharper6153bc72019-05-08 12:04:34 -0700228 next_state_ = STATE_SEND_CHLO;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229 }
230}
231
232void QuicCryptoClientHandshaker::DoSendCHLO(
233 QuicCryptoClientConfig::CachedState* cached) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234 // Send the client hello in plaintext.
QUICHE team6987b4a2019-03-15 16:23:04 -0700235 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500236 encryption_established_ = false;
QUICHE team8b353f32019-04-09 13:49:10 -0700237 if (num_client_hellos_ >= QuicCryptoClientStream::kMaxClientHellos) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500238 stream_->CloseConnectionWithDetails(
239 QUIC_CRYPTO_TOO_MANY_REJECTS,
240 QuicStrCat("More than ", QuicCryptoClientStream::kMaxClientHellos,
241 " rejects"));
242 return;
243 }
244 num_client_hellos_++;
245
246 CryptoHandshakeMessage out;
247 DCHECK(session() != nullptr);
248 DCHECK(session()->config() != nullptr);
249 // Send all the options, regardless of whether we're sending an
250 // inchoate or subsequent hello.
fkastenholzd3a1de92019-05-15 07:00:07 -0700251 session()->config()->ToHandshakeMessage(&out, session()->transport_version());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252
253 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
254 crypto_config_->FillInchoateClientHello(
255 server_id_, session()->supported_versions().front(), cached,
256 session()->connection()->random_generator(),
257 /* demand_x509_proof= */ true, crypto_negotiated_params_, &out);
258 // Pad the inchoate client hello to fill up a packet.
259 const QuicByteCount kFramingOverhead = 50; // A rough estimate.
260 const QuicByteCount max_packet_size =
261 session()->connection()->max_packet_length();
262 if (max_packet_size <= kFramingOverhead) {
263 QUIC_DLOG(DFATAL) << "max_packet_length (" << max_packet_size
264 << ") has no room for framing overhead.";
265 stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
266 "max_packet_size too smalll");
267 return;
268 }
269 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
270 QUIC_DLOG(DFATAL) << "Client hello won't fit in a single packet.";
271 stream_->CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
272 "CHLO too large");
273 return;
274 }
275 next_state_ = STATE_RECV_REJ;
QUICHE team84910bd2019-03-15 07:03:40 -0700276 chlo_hash_ = CryptoUtils::HashHandshakeMessage(out, Perspective::IS_CLIENT);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 session()->connection()->set_fully_pad_crypto_hadshake_packets(
278 crypto_config_->pad_inchoate_hello());
279 SendHandshakeMessage(out);
280 return;
281 }
282
vasilvvc48c8712019-03-11 13:38:16 -0700283 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500284 QuicErrorCode error = crypto_config_->FillClientHello(
285 server_id_, session()->connection()->connection_id(),
286 session()->supported_versions().front(), cached,
287 session()->connection()->clock()->WallNow(),
nharper6153bc72019-05-08 12:04:34 -0700288 session()->connection()->random_generator(), crypto_negotiated_params_,
289 &out, &error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500290 if (error != QUIC_NO_ERROR) {
291 // Flush the cached config so that, if it's bad, the server has a
292 // chance to send us another in the future.
293 cached->InvalidateServerConfig();
294 stream_->CloseConnectionWithDetails(error, error_details);
295 return;
296 }
QUICHE team84910bd2019-03-15 07:03:40 -0700297 chlo_hash_ = CryptoUtils::HashHandshakeMessage(out, Perspective::IS_CLIENT);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500298 if (cached->proof_verify_details()) {
299 proof_handler_->OnProofVerifyDetailsAvailable(
300 *cached->proof_verify_details());
301 }
302 next_state_ = STATE_RECV_SHLO;
303 session()->connection()->set_fully_pad_crypto_hadshake_packets(
304 crypto_config_->pad_full_hello());
305 SendHandshakeMessage(out);
306 // Be prepared to decrypt with the new server write key.
zhongyi546cc452019-04-12 15:27:49 -0700307 if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
308 session()->connection()->InstallDecrypter(
309 ENCRYPTION_ZERO_RTT,
310 std::move(crypto_negotiated_params_->initial_crypters.decrypter));
311 } else {
312 session()->connection()->SetAlternativeDecrypter(
313 ENCRYPTION_ZERO_RTT,
314 std::move(crypto_negotiated_params_->initial_crypters.decrypter),
315 true /* latch once used */);
316 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 // Send subsequent packets under encryption on the assumption that the
318 // server will accept the handshake.
319 session()->connection()->SetEncrypter(
320 ENCRYPTION_ZERO_RTT,
321 std::move(crypto_negotiated_params_->initial_crypters.encrypter));
322 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
323
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324 encryption_established_ = true;
renjietangea71d6f2019-08-19 12:22:28 -0700325 session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_ESTABLISHED);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500326}
327
328void QuicCryptoClientHandshaker::DoReceiveREJ(
329 const CryptoHandshakeMessage* in,
330 QuicCryptoClientConfig::CachedState* cached) {
331 // We sent a dummy CHLO because we didn't have enough information to
332 // perform a handshake, or we sent a full hello that the server
333 // rejected. Here we hope to have a REJ that contains the information
334 // that we need.
wub0a4b9c52019-05-28 13:18:58 -0700335 if (in->tag() != kREJ) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500336 next_state_ = STATE_NONE;
337 stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
338 "Expected REJ");
339 return;
340 }
341
342 QuicTagVector reject_reasons;
343 static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
344 if (in->GetTaglist(kRREJ, &reject_reasons) == QUIC_NO_ERROR) {
345 uint32_t packed_error = 0;
346 for (size_t i = 0; i < reject_reasons.size(); ++i) {
347 // HANDSHAKE_OK is 0 and don't report that as error.
348 if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) {
349 continue;
350 }
351 HandshakeFailureReason reason =
352 static_cast<HandshakeFailureReason>(reject_reasons[i]);
353 packed_error |= 1 << (reason - 1);
354 }
bnc5de87052019-05-03 14:21:53 -0700355 QUIC_DVLOG(1) << "Reasons for rejection: " << packed_error;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500356 if (num_client_hellos_ == QuicCryptoClientStream::kMaxClientHellos) {
357 QuicClientSparseHistogram("QuicClientHelloRejectReasons.TooMany",
358 packed_error);
359 }
360 QuicClientSparseHistogram("QuicClientHelloRejectReasons.Secure",
361 packed_error);
362 }
363
364 // Receipt of a REJ message means that the server received the CHLO
365 // so we can cancel and retransmissions.
366 session()->NeuterUnencryptedData();
367
vasilvvc48c8712019-03-11 13:38:16 -0700368 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500369 QuicErrorCode error = crypto_config_->ProcessRejection(
370 *in, session()->connection()->clock()->WallNow(),
371 session()->connection()->transport_version(), chlo_hash_, cached,
372 crypto_negotiated_params_, &error_details);
373
374 if (error != QUIC_NO_ERROR) {
375 next_state_ = STATE_NONE;
376 stream_->CloseConnectionWithDetails(error, error_details);
377 return;
378 }
379 if (!cached->proof_valid()) {
380 if (!cached->signature().empty()) {
381 // Note that we only verify the proof if the cached proof is not
382 // valid. If the cached proof is valid here, someone else must have
383 // just added the server config to the cache and verified the proof,
384 // so we can assume no CA trust changes or certificate expiration
385 // has happened since then.
386 next_state_ = STATE_VERIFY_PROOF;
387 return;
388 }
389 }
nharper6153bc72019-05-08 12:04:34 -0700390 next_state_ = STATE_SEND_CHLO;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500391}
392
393QuicAsyncStatus QuicCryptoClientHandshaker::DoVerifyProof(
394 QuicCryptoClientConfig::CachedState* cached) {
395 ProofVerifier* verifier = crypto_config_->proof_verifier();
396 DCHECK(verifier);
397 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
398 generation_counter_ = cached->generation_counter();
399
400 ProofVerifierCallbackImpl* proof_verify_callback =
401 new ProofVerifierCallbackImpl(this);
402
403 verify_ok_ = false;
404
405 QuicAsyncStatus status = verifier->VerifyProof(
406 server_id_.host(), server_id_.port(), cached->server_config(),
407 session()->connection()->transport_version(), chlo_hash_, cached->certs(),
408 cached->cert_sct(), cached->signature(), verify_context_.get(),
409 &verify_error_details_, &verify_details_,
410 std::unique_ptr<ProofVerifierCallback>(proof_verify_callback));
411
412 switch (status) {
413 case QUIC_PENDING:
414 proof_verify_callback_ = proof_verify_callback;
415 QUIC_DVLOG(1) << "Doing VerifyProof";
416 break;
417 case QUIC_FAILURE:
418 break;
419 case QUIC_SUCCESS:
420 verify_ok_ = true;
421 break;
422 }
423 return status;
424}
425
426void QuicCryptoClientHandshaker::DoVerifyProofComplete(
427 QuicCryptoClientConfig::CachedState* cached) {
428 if (proof_verify_start_time_.IsInitialized()) {
429 QUIC_CLIENT_HISTOGRAM_TIMES(
430 "QuicSession.VerifyProofTime.CachedServerConfig",
431 (session()->connection()->clock()->Now() - proof_verify_start_time_),
432 QuicTime::Delta::FromMilliseconds(1), QuicTime::Delta::FromSeconds(10),
433 50, "");
434 }
435 if (!verify_ok_) {
436 if (verify_details_) {
437 proof_handler_->OnProofVerifyDetailsAvailable(*verify_details_);
438 }
439 if (num_client_hellos_ == 0) {
440 cached->Clear();
441 next_state_ = STATE_INITIALIZE;
442 return;
443 }
444 next_state_ = STATE_NONE;
445 QUIC_CLIENT_HISTOGRAM_BOOL("QuicVerifyProofFailed.HandshakeConfirmed",
446 handshake_confirmed(), "");
447 stream_->CloseConnectionWithDetails(
448 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
449 return;
450 }
451
452 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
453 // STATE_VERIFY_PROOF_COMPLETE state changes.
454 if (generation_counter_ != cached->generation_counter()) {
455 next_state_ = STATE_VERIFY_PROOF;
456 } else {
457 SetCachedProofValid(cached);
458 cached->SetProofVerifyDetails(verify_details_.release());
459 if (!handshake_confirmed()) {
nharper6153bc72019-05-08 12:04:34 -0700460 next_state_ = STATE_SEND_CHLO;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500461 } else {
462 // TODO: Enable Expect-Staple. https://crbug.com/631101
463 next_state_ = STATE_NONE;
464 }
465 }
466}
467
QUICHE teama6ef0a62019-03-07 20:34:33 -0500468void QuicCryptoClientHandshaker::DoReceiveSHLO(
469 const CryptoHandshakeMessage* in,
470 QuicCryptoClientConfig::CachedState* cached) {
471 next_state_ = STATE_NONE;
472 // We sent a CHLO that we expected to be accepted and now we're
473 // hoping for a SHLO from the server to confirm that. First check
474 // to see whether the response was a reject, and if so, move on to
475 // the reject-processing state.
wub0a4b9c52019-05-28 13:18:58 -0700476 if (in->tag() == kREJ) {
zhongyi546cc452019-04-12 15:27:49 -0700477 // A reject message must be sent in ENCRYPTION_INITIAL.
478 if (session()->connection()->last_decrypted_level() != ENCRYPTION_INITIAL) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500479 // The rejection was sent encrypted!
480 stream_->CloseConnectionWithDetails(
481 QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT, "encrypted REJ message");
482 return;
483 }
484 next_state_ = STATE_RECV_REJ;
485 return;
486 }
487
488 if (in->tag() != kSHLO) {
489 stream_->CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
490 "Expected SHLO or REJ");
491 return;
492 }
493
zhongyi546cc452019-04-12 15:27:49 -0700494 if (session()->connection()->last_decrypted_level() == ENCRYPTION_INITIAL) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500495 // The server hello was sent without encryption.
496 stream_->CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
497 "unencrypted SHLO message");
498 return;
499 }
500
vasilvvc48c8712019-03-11 13:38:16 -0700501 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500502 QuicErrorCode error = crypto_config_->ProcessServerHello(
503 *in, session()->connection()->connection_id(),
504 session()->connection()->version(),
505 session()->connection()->server_supported_versions(), cached,
506 crypto_negotiated_params_, &error_details);
507
508 if (error != QUIC_NO_ERROR) {
509 stream_->CloseConnectionWithDetails(
510 error, "Server hello invalid: " + error_details);
511 return;
512 }
513 error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
514 if (error != QUIC_NO_ERROR) {
515 stream_->CloseConnectionWithDetails(
516 error, "Server hello invalid: " + error_details);
517 return;
518 }
519 session()->OnConfigNegotiated();
520
521 CrypterPair* crypters = &crypto_negotiated_params_->forward_secure_crypters;
522 // TODO(agl): we don't currently latch this decrypter because the idea
523 // has been floated that the server shouldn't send packets encrypted
524 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
525 // packet from the client.
zhongyi546cc452019-04-12 15:27:49 -0700526 if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
527 session()->connection()->InstallDecrypter(ENCRYPTION_FORWARD_SECURE,
528 std::move(crypters->decrypter));
529 } else {
530 session()->connection()->SetAlternativeDecrypter(
531 ENCRYPTION_FORWARD_SECURE, std::move(crypters->decrypter),
532 false /* don't latch */);
533 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500534 session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE,
535 std::move(crypters->encrypter));
536 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
537
538 handshake_confirmed_ = true;
539 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
540 session()->connection()->OnHandshakeComplete();
541}
542
543void QuicCryptoClientHandshaker::DoInitializeServerConfigUpdate(
544 QuicCryptoClientConfig::CachedState* cached) {
545 bool update_ignored = false;
546 if (!cached->IsEmpty() && !cached->signature().empty()) {
547 // Note that we verify the proof even if the cached proof is valid.
548 DCHECK(crypto_config_->proof_verifier());
549 next_state_ = STATE_VERIFY_PROOF;
550 } else {
551 update_ignored = true;
552 next_state_ = STATE_NONE;
553 }
554 QUIC_CLIENT_HISTOGRAM_COUNTS("QuicNumServerConfig.UpdateMessagesIgnored",
555 update_ignored, 1, 1000000, 50, "");
556}
557
558void QuicCryptoClientHandshaker::SetCachedProofValid(
559 QuicCryptoClientConfig::CachedState* cached) {
560 cached->SetProofValid();
561 proof_handler_->OnProofValid(*cached);
562}
563
QUICHE teama6ef0a62019-03-07 20:34:33 -0500564} // namespace quic