+ case STATE_INITIALIZE_SCUP:
+ DoInitializeServerConfigUpdate(cached);
+ break;
+ case STATE_VERIFY_PROOF_DONE:
+ return; // We are done.
+ }
+ }
+}
+
+void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
+ QuicCryptoClientConfig::CachedState* cached) {
+ bool update_ignored = false;
+ if (!server_id_.is_https()) {
+ // We don't check the certificates for insecure QUIC connections.
+ SetCachedProofValid(cached);
+ next_state_ = STATE_VERIFY_PROOF_DONE;
+ } else if (!cached->IsEmpty() && !cached->signature().empty()) {
+ // Note that we verify the proof even if the cached proof is valid.
+ DCHECK(crypto_config_->proof_verifier());
+ next_state_ = STATE_VERIFY_PROOF;
+ } else {
+ update_ignored = true;
+ next_state_ = STATE_VERIFY_PROOF_DONE;
+ }
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicNumServerConfig.UpdateMessagesIgnored",
+ update_ignored);
+}
+
+QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
+ QuicCryptoClientConfig::CachedState* cached) {
+ ProofVerifier* verifier = crypto_config_->proof_verifier();
+ DCHECK(verifier);
+ next_state_ = STATE_VERIFY_PROOF_COMPLETE;
+ generation_counter_ = cached->generation_counter();
+
+ ProofVerifierCallbackImpl* proof_verify_callback =
+ new ProofVerifierCallbackImpl(this);
+
+ verify_ok_ = false;
+
+ QuicAsyncStatus status = verifier->VerifyProof(
+ server_id_.host(),
+ cached->server_config(),
+ cached->certs(),
+ cached->signature(),
+ verify_context_.get(),
+ &verify_error_details_,
+ &verify_details_,
+ proof_verify_callback);
+
+ switch (status) {
+ case QUIC_PENDING:
+ proof_verify_callback_ = proof_verify_callback;
+ DVLOG(1) << "Doing VerifyProof";
+ break;
+ case QUIC_FAILURE:
+ delete proof_verify_callback;
+ break;
+ case QUIC_SUCCESS:
+ delete proof_verify_callback;
+ verify_ok_ = true;
+ break;
+ }
+ return status;
+}
+
+QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete(
+ QuicCryptoClientConfig::CachedState* cached) {
+ if (!verify_ok_) {
+ client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
+ UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
+ handshake_confirmed());
+ CloseConnectionWithDetails(
+ QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
+ return QUIC_PROOF_INVALID;
+ }
+
+ // Check if generation_counter has changed between STATE_VERIFY_PROOF and
+ // STATE_VERIFY_PROOF_COMPLETE state changes.
+ if (generation_counter_ != cached->generation_counter()) {
+ next_state_ = STATE_VERIFY_PROOF;
+ } else {
+ SetCachedProofValid(cached);
+ cached->SetProofVerifyDetails(verify_details_.release());
+ if (!handshake_confirmed()) {
+ next_state_ = STATE_GET_CHANNEL_ID;
+ } else {
+ next_state_ = STATE_VERIFY_PROOF_DONE;