ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / net / quic / quic_crypto_client_stream.cc
blobeaff5289f4065935a1c1c30a2236cdcc0483aa77
1 // 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.
5 #include "net/quic/quic_crypto_client_stream.h"
7 #include "base/metrics/histogram.h"
8 #include "base/profiler/scoped_tracker.h"
9 #include "net/quic/crypto/crypto_protocol.h"
10 #include "net/quic/crypto/crypto_utils.h"
11 #include "net/quic/crypto/null_encrypter.h"
12 #include "net/quic/quic_client_session_base.h"
13 #include "net/quic/quic_protocol.h"
14 #include "net/quic/quic_session.h"
16 using std::string;
18 namespace net {
20 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
21 ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream)
22 : stream_(stream) {}
24 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
25 ~ChannelIDSourceCallbackImpl() {}
27 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
28 scoped_ptr<ChannelIDKey>* channel_id_key) {
29 if (stream_ == nullptr) {
30 return;
33 stream_->channel_id_key_.reset(channel_id_key->release());
34 stream_->channel_id_source_callback_run_ = true;
35 stream_->channel_id_source_callback_ = nullptr;
36 stream_->DoHandshakeLoop(nullptr);
38 // The ChannelIDSource owns this object and will delete it when this method
39 // returns.
42 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
43 stream_ = nullptr;
46 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
47 QuicCryptoClientStream* stream)
48 : stream_(stream) {}
50 QuicCryptoClientStream::ProofVerifierCallbackImpl::
51 ~ProofVerifierCallbackImpl() {}
53 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
54 bool ok,
55 const string& error_details,
56 scoped_ptr<ProofVerifyDetails>* details) {
57 if (stream_ == nullptr) {
58 return;
61 stream_->verify_ok_ = ok;
62 stream_->verify_error_details_ = error_details;
63 stream_->verify_details_.reset(details->release());
64 stream_->proof_verify_callback_ = nullptr;
65 stream_->DoHandshakeLoop(nullptr);
67 // The ProofVerifier owns this object and will delete it when this method
68 // returns.
71 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
72 stream_ = nullptr;
75 QuicCryptoClientStream::QuicCryptoClientStream(
76 const QuicServerId& server_id,
77 QuicClientSessionBase* session,
78 ProofVerifyContext* verify_context,
79 QuicCryptoClientConfig* crypto_config)
80 : QuicCryptoStream(session),
81 next_state_(STATE_IDLE),
82 num_client_hellos_(0),
83 crypto_config_(crypto_config),
84 server_id_(server_id),
85 generation_counter_(0),
86 channel_id_sent_(false),
87 channel_id_source_callback_run_(false),
88 channel_id_source_callback_(nullptr),
89 verify_context_(verify_context),
90 proof_verify_callback_(nullptr) {
91 DCHECK(!session->connection()->is_server());
94 QuicCryptoClientStream::~QuicCryptoClientStream() {
95 if (channel_id_source_callback_) {
96 channel_id_source_callback_->Cancel();
98 if (proof_verify_callback_) {
99 proof_verify_callback_->Cancel();
103 void QuicCryptoClientStream::OnHandshakeMessage(
104 const CryptoHandshakeMessage& message) {
105 QuicCryptoStream::OnHandshakeMessage(message);
107 if (message.tag() == kSCUP) {
108 if (!handshake_confirmed()) {
109 CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
110 return;
113 // |message| is an update from the server, so we treat it differently from a
114 // handshake message.
115 HandleServerConfigUpdateMessage(message);
116 return;
119 // Do not process handshake messages after the handshake is confirmed.
120 if (handshake_confirmed()) {
121 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
122 return;
125 DoHandshakeLoop(&message);
128 void QuicCryptoClientStream::CryptoConnect() {
129 next_state_ = STATE_INITIALIZE;
130 DoHandshakeLoop(nullptr);
133 int QuicCryptoClientStream::num_sent_client_hellos() const {
134 return num_client_hellos_;
137 // Used in Chromium, but not in the server.
138 bool QuicCryptoClientStream::WasChannelIDSent() const {
139 return channel_id_sent_;
142 bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
143 return channel_id_source_callback_run_;
146 void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
147 const CryptoHandshakeMessage& server_config_update) {
148 DCHECK(server_config_update.tag() == kSCUP);
149 string error_details;
150 QuicCryptoClientConfig::CachedState* cached =
151 crypto_config_->LookupOrCreate(server_id_);
152 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
153 server_config_update,
154 session()->connection()->clock()->WallNow(),
155 cached,
156 &crypto_negotiated_params_,
157 &error_details);
159 if (error != QUIC_NO_ERROR) {
160 CloseConnectionWithDetails(
161 error, "Server config update invalid: " + error_details);
162 return;
165 DCHECK(handshake_confirmed());
166 if (proof_verify_callback_) {
167 proof_verify_callback_->Cancel();
169 next_state_ = STATE_INITIALIZE_SCUP;
170 DoHandshakeLoop(nullptr);
173 // kMaxClientHellos is the maximum number of times that we'll send a client
174 // hello. The value 3 accounts for:
175 // * One failure due to an incorrect or missing source-address token.
176 // * One failure due the server's certificate chain being unavailible and the
177 // server being unwilling to send it without a valid source-address token.
178 static const int kMaxClientHellos = 3;
180 void QuicCryptoClientStream::DoHandshakeLoop(
181 const CryptoHandshakeMessage* in) {
182 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
183 tracked_objects::ScopedTracker tracking_profile(
184 FROM_HERE_WITH_EXPLICIT_FUNCTION(
185 "422516 QuicCryptoClientStream::DoHandshakeLoop"));
187 QuicCryptoClientConfig::CachedState* cached =
188 crypto_config_->LookupOrCreate(server_id_);
190 QuicAsyncStatus rv = QUIC_SUCCESS;
191 do {
192 CHECK_NE(STATE_NONE, next_state_);
193 const State state = next_state_;
194 next_state_ = STATE_IDLE;
195 rv = QUIC_SUCCESS;
196 switch (state) {
197 case STATE_INITIALIZE:
198 DoInitialize(cached);
199 break;
200 case STATE_SEND_CHLO:
201 DoSendCHLO(in, cached);
202 return; // return waiting to hear from server.
203 case STATE_RECV_REJ:
204 DoReceiveREJ(in, cached);
205 break;
206 case STATE_VERIFY_PROOF:
207 rv = DoVerifyProof(cached);
208 break;
209 case STATE_VERIFY_PROOF_COMPLETE:
210 DoVerifyProofComplete(cached);
211 break;
212 case STATE_GET_CHANNEL_ID:
213 rv = DoGetChannelID(cached);
214 break;
215 case STATE_GET_CHANNEL_ID_COMPLETE:
216 DoGetChannelIDComplete();
217 break;
218 case STATE_RECV_SHLO:
219 DoReceiveSHLO(in, cached);
220 break;
221 case STATE_IDLE:
222 // This means that the peer sent us a message that we weren't expecting.
223 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
224 return;
225 case STATE_INITIALIZE_SCUP:
226 DoInitializeServerConfigUpdate(cached);
227 break;
228 case STATE_NONE:
229 NOTREACHED();
230 return; // We are done.
232 } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
235 void QuicCryptoClientStream::DoInitialize(
236 QuicCryptoClientConfig::CachedState* cached) {
237 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
238 tracked_objects::ScopedTracker tracking_profile(
239 FROM_HERE_WITH_EXPLICIT_FUNCTION(
240 "422516 QuicCryptoClientStream::DoInitialize"));
242 if (!cached->IsEmpty() && !cached->signature().empty() &&
243 server_id_.is_https()) {
244 // Note that we verify the proof even if the cached proof is valid.
245 // This allows us to respond to CA trust changes or certificate
246 // expiration because it may have been a while since we last verified
247 // the proof.
248 DCHECK(crypto_config_->proof_verifier());
249 // If the cached state needs to be verified, do it now.
250 next_state_ = STATE_VERIFY_PROOF;
251 } else {
252 next_state_ = STATE_GET_CHANNEL_ID;
256 void QuicCryptoClientStream::DoSendCHLO(
257 const CryptoHandshakeMessage* in,
258 QuicCryptoClientConfig::CachedState* cached) {
259 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
260 tracked_objects::ScopedTracker tracking_profile1(
261 FROM_HERE_WITH_EXPLICIT_FUNCTION(
262 "422516 QuicCryptoClientStream::DoSendCHLO1"));
264 // Send the client hello in plaintext.
265 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
266 if (num_client_hellos_ > kMaxClientHellos) {
267 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
268 return;
270 num_client_hellos_++;
272 CryptoHandshakeMessage out;
273 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
274 crypto_config_->FillInchoateClientHello(
275 server_id_,
276 session()->connection()->supported_versions().front(),
277 cached, &crypto_negotiated_params_, &out);
278 // Pad the inchoate client hello to fill up a packet.
279 const QuicByteCount kFramingOverhead = 50; // A rough estimate.
280 const QuicByteCount max_packet_size =
281 session()->connection()->max_packet_length();
282 if (max_packet_size <= kFramingOverhead) {
283 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
284 << ") has no room for framing overhead.";
285 CloseConnection(QUIC_INTERNAL_ERROR);
286 return;
288 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
289 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
290 CloseConnection(QUIC_INTERNAL_ERROR);
291 return;
293 out.set_minimum_size(
294 static_cast<size_t>(max_packet_size - kFramingOverhead));
295 next_state_ = STATE_RECV_REJ;
296 SendHandshakeMessage(out);
297 return;
300 session()->config()->ToHandshakeMessage(&out);
301 string error_details;
302 QuicErrorCode error = crypto_config_->FillClientHello(
303 server_id_,
304 session()->connection()->connection_id(),
305 session()->connection()->supported_versions().front(),
306 cached,
307 session()->connection()->clock()->WallNow(),
308 session()->connection()->random_generator(),
309 channel_id_key_.get(),
310 &crypto_negotiated_params_,
311 &out,
312 &error_details);
314 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
315 tracked_objects::ScopedTracker tracking_profile2(
316 FROM_HERE_WITH_EXPLICIT_FUNCTION(
317 "422516 QuicCryptoClientStream::DoSendCHLO2"));
319 if (error != QUIC_NO_ERROR) {
320 // Flush the cached config so that, if it's bad, the server has a
321 // chance to send us another in the future.
322 cached->InvalidateServerConfig();
323 CloseConnectionWithDetails(error, error_details);
324 return;
326 channel_id_sent_ = (channel_id_key_.get() != nullptr);
327 if (cached->proof_verify_details()) {
328 client_session()->OnProofVerifyDetailsAvailable(
329 *cached->proof_verify_details());
331 next_state_ = STATE_RECV_SHLO;
332 SendHandshakeMessage(out);
333 // Be prepared to decrypt with the new server write key.
334 session()->connection()->SetAlternativeDecrypter(
335 crypto_negotiated_params_.initial_crypters.decrypter.release(),
336 ENCRYPTION_INITIAL,
337 true /* latch once used */);
338 // Send subsequent packets under encryption on the assumption that the
339 // server will accept the handshake.
340 session()->connection()->SetEncrypter(
341 ENCRYPTION_INITIAL,
342 crypto_negotiated_params_.initial_crypters.encrypter.release());
343 session()->connection()->SetDefaultEncryptionLevel(
344 ENCRYPTION_INITIAL);
345 if (!encryption_established_) {
346 encryption_established_ = true;
347 session()->OnCryptoHandshakeEvent(
348 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
349 } else {
350 session()->OnCryptoHandshakeEvent(
351 QuicSession::ENCRYPTION_REESTABLISHED);
355 void QuicCryptoClientStream::DoReceiveREJ(
356 const CryptoHandshakeMessage* in,
357 QuicCryptoClientConfig::CachedState* cached) {
358 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
359 tracked_objects::ScopedTracker tracking_profile(
360 FROM_HERE_WITH_EXPLICIT_FUNCTION(
361 "422516 QuicCryptoClientStream::DoReceiveREJ"));
363 // We sent a dummy CHLO because we didn't have enough information to
364 // perform a handshake, or we sent a full hello that the server
365 // rejected. Here we hope to have a REJ that contains the information
366 // that we need.
367 if (in->tag() != kREJ) {
368 next_state_ = STATE_NONE;
369 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
370 "Expected REJ");
371 return;
373 string error_details;
374 QuicErrorCode error = crypto_config_->ProcessRejection(
375 *in, session()->connection()->clock()->WallNow(), cached,
376 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
377 if (error != QUIC_NO_ERROR) {
378 next_state_ = STATE_NONE;
379 CloseConnectionWithDetails(error, error_details);
380 return;
382 if (!cached->proof_valid()) {
383 if (!server_id_.is_https()) {
384 // We don't check the certificates for insecure QUIC connections.
385 SetCachedProofValid(cached);
386 } else if (!cached->signature().empty()) {
387 // Note that we only verify the proof if the cached proof is not
388 // valid. If the cached proof is valid here, someone else must have
389 // just added the server config to the cache and verified the proof,
390 // so we can assume no CA trust changes or certificate expiration
391 // has happened since then.
392 next_state_ = STATE_VERIFY_PROOF;
393 return;
396 next_state_ = STATE_GET_CHANNEL_ID;
399 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
400 QuicCryptoClientConfig::CachedState* cached) {
401 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
402 tracked_objects::ScopedTracker tracking_profile(
403 FROM_HERE_WITH_EXPLICIT_FUNCTION(
404 "422516 QuicCryptoClientStream::DoVerifyProof"));
406 ProofVerifier* verifier = crypto_config_->proof_verifier();
407 DCHECK(verifier);
408 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
409 generation_counter_ = cached->generation_counter();
411 ProofVerifierCallbackImpl* proof_verify_callback =
412 new ProofVerifierCallbackImpl(this);
414 verify_ok_ = false;
416 QuicAsyncStatus status = verifier->VerifyProof(
417 server_id_.host(),
418 cached->server_config(),
419 cached->certs(),
420 cached->signature(),
421 verify_context_.get(),
422 &verify_error_details_,
423 &verify_details_,
424 proof_verify_callback);
426 switch (status) {
427 case QUIC_PENDING:
428 proof_verify_callback_ = proof_verify_callback;
429 DVLOG(1) << "Doing VerifyProof";
430 break;
431 case QUIC_FAILURE:
432 delete proof_verify_callback;
433 break;
434 case QUIC_SUCCESS:
435 delete proof_verify_callback;
436 verify_ok_ = true;
437 break;
439 return status;
442 void QuicCryptoClientStream::DoVerifyProofComplete(
443 QuicCryptoClientConfig::CachedState* cached) {
444 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
445 tracked_objects::ScopedTracker tracking_profile(
446 FROM_HERE_WITH_EXPLICIT_FUNCTION(
447 "422516 QuicCryptoClientStream::DoVerifyProofComplete"));
449 if (!verify_ok_) {
450 next_state_ = STATE_NONE;
451 if (verify_details_.get()) {
452 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
454 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
455 handshake_confirmed());
456 CloseConnectionWithDetails(
457 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
458 return;
461 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
462 // STATE_VERIFY_PROOF_COMPLETE state changes.
463 if (generation_counter_ != cached->generation_counter()) {
464 next_state_ = STATE_VERIFY_PROOF;
465 } else {
466 SetCachedProofValid(cached);
467 cached->SetProofVerifyDetails(verify_details_.release());
468 if (!handshake_confirmed()) {
469 next_state_ = STATE_GET_CHANNEL_ID;
470 } else {
471 next_state_ = STATE_NONE;
476 QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
477 QuicCryptoClientConfig::CachedState* cached) {
478 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
479 tracked_objects::ScopedTracker tracking_profile(
480 FROM_HERE_WITH_EXPLICIT_FUNCTION(
481 "422516 QuicCryptoClientStream::DoGetChannelID"));
483 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
484 channel_id_key_.reset();
485 if (!RequiresChannelID(cached)) {
486 next_state_ = STATE_SEND_CHLO;
487 return QUIC_SUCCESS;
490 ChannelIDSourceCallbackImpl* channel_id_source_callback =
491 new ChannelIDSourceCallbackImpl(this);
492 QuicAsyncStatus status =
493 crypto_config_->channel_id_source()->GetChannelIDKey(
494 server_id_.host(), &channel_id_key_,
495 channel_id_source_callback);
497 switch (status) {
498 case QUIC_PENDING:
499 channel_id_source_callback_ = channel_id_source_callback;
500 DVLOG(1) << "Looking up channel ID";
501 break;
502 case QUIC_FAILURE:
503 next_state_ = STATE_NONE;
504 delete channel_id_source_callback;
505 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
506 "Channel ID lookup failed");
507 break;
508 case QUIC_SUCCESS:
509 delete channel_id_source_callback;
510 break;
512 return status;
515 void QuicCryptoClientStream::DoGetChannelIDComplete() {
516 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
517 tracked_objects::ScopedTracker tracking_profile(
518 FROM_HERE_WITH_EXPLICIT_FUNCTION(
519 "422516 QuicCryptoClientStream::DoGetChannelIDComplete"));
521 if (!channel_id_key_.get()) {
522 next_state_ = STATE_NONE;
523 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
524 "Channel ID lookup failed");
525 return;
527 next_state_ = STATE_SEND_CHLO;
530 void QuicCryptoClientStream::DoReceiveSHLO(
531 const CryptoHandshakeMessage* in,
532 QuicCryptoClientConfig::CachedState* cached) {
533 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
534 tracked_objects::ScopedTracker tracking_profile(
535 FROM_HERE_WITH_EXPLICIT_FUNCTION(
536 "422516 QuicCryptoClientStream::DoReceiveSHLO"));
538 next_state_ = STATE_NONE;
539 // We sent a CHLO that we expected to be accepted and now we're hoping
540 // for a SHLO from the server to confirm that.
541 if (in->tag() == kREJ) {
542 // alternative_decrypter will be nullptr if the original alternative
543 // decrypter latched and became the primary decrypter. That happens
544 // if we received a message encrypted with the INITIAL key.
545 if (session()->connection()->alternative_decrypter() == nullptr) {
546 // The rejection was sent encrypted!
547 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
548 "encrypted REJ message");
549 return;
551 next_state_ = STATE_RECV_REJ;
552 return;
555 if (in->tag() != kSHLO) {
556 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
557 "Expected SHLO or REJ");
558 return;
561 // alternative_decrypter will be nullptr if the original alternative
562 // decrypter latched and became the primary decrypter. That happens
563 // if we received a message encrypted with the INITIAL key.
564 if (session()->connection()->alternative_decrypter() != nullptr) {
565 // The server hello was sent without encryption.
566 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
567 "unencrypted SHLO message");
568 return;
571 string error_details;
572 QuicErrorCode error = crypto_config_->ProcessServerHello(
573 *in, session()->connection()->connection_id(),
574 session()->connection()->server_supported_versions(),
575 cached, &crypto_negotiated_params_, &error_details);
577 if (error != QUIC_NO_ERROR) {
578 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
579 return;
581 error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
582 if (error != QUIC_NO_ERROR) {
583 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
584 return;
586 session()->OnConfigNegotiated();
588 CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters;
589 // TODO(agl): we don't currently latch this decrypter because the idea
590 // has been floated that the server shouldn't send packets encrypted
591 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
592 // packet from the client.
593 session()->connection()->SetAlternativeDecrypter(
594 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
595 false /* don't latch */);
596 session()->connection()->SetEncrypter(
597 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
598 session()->connection()->SetDefaultEncryptionLevel(
599 ENCRYPTION_FORWARD_SECURE);
601 handshake_confirmed_ = true;
602 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
603 session()->connection()->OnHandshakeComplete();
606 void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
607 QuicCryptoClientConfig::CachedState* cached) {
608 // TODO(vadimt): Remove ScopedTracker below once crbug.com/422516 is fixed.
609 tracked_objects::ScopedTracker tracking_profile(
610 FROM_HERE_WITH_EXPLICIT_FUNCTION(
611 "422516 QuicCryptoClientStream::DoInitializeServerConfigUpdate"));
613 bool update_ignored = false;
614 if (!server_id_.is_https()) {
615 // We don't check the certificates for insecure QUIC connections.
616 SetCachedProofValid(cached);
617 next_state_ = STATE_NONE;
618 } else if (!cached->IsEmpty() && !cached->signature().empty()) {
619 // Note that we verify the proof even if the cached proof is valid.
620 DCHECK(crypto_config_->proof_verifier());
621 next_state_ = STATE_VERIFY_PROOF;
622 } else {
623 update_ignored = true;
624 next_state_ = STATE_NONE;
626 UMA_HISTOGRAM_COUNTS("Net.QuicNumServerConfig.UpdateMessagesIgnored",
627 update_ignored);
630 void QuicCryptoClientStream::SetCachedProofValid(
631 QuicCryptoClientConfig::CachedState* cached) {
632 cached->SetProofValid();
633 client_session()->OnProofValid(*cached);
636 bool QuicCryptoClientStream::RequiresChannelID(
637 QuicCryptoClientConfig::CachedState* cached) {
638 if (!server_id_.is_https() ||
639 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
640 !crypto_config_->channel_id_source()) {
641 return false;
643 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
644 if (!scfg) { // scfg may be null then we send an inchoate CHLO.
645 return false;
647 const QuicTag* their_proof_demands;
648 size_t num_their_proof_demands;
649 if (scfg->GetTaglist(kPDMD, &their_proof_demands,
650 &num_their_proof_demands) != QUIC_NO_ERROR) {
651 return false;
653 for (size_t i = 0; i < num_their_proof_demands; i++) {
654 if (their_proof_demands[i] == kCHID) {
655 return true;
658 return false;
661 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
662 return reinterpret_cast<QuicClientSessionBase*>(session());
665 } // namespace net