Revert of Clean up Smart Lock cryptohome keys logic: (patchset #5 id:80001 of https...
[chromium-blink-merge.git] / net / quic / quic_crypto_client_stream.cc
blob6777b2e1524ec6aa8414fc46930985afe035b282
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 "net/quic/crypto/crypto_protocol.h"
9 #include "net/quic/crypto/crypto_utils.h"
10 #include "net/quic/crypto/null_encrypter.h"
11 #include "net/quic/quic_client_session_base.h"
12 #include "net/quic/quic_protocol.h"
13 #include "net/quic/quic_session.h"
15 using std::string;
17 namespace net {
19 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
20 ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream)
21 : stream_(stream) {}
23 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
24 ~ChannelIDSourceCallbackImpl() {}
26 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
27 scoped_ptr<ChannelIDKey>* channel_id_key) {
28 if (stream_ == nullptr) {
29 return;
32 stream_->channel_id_key_.reset(channel_id_key->release());
33 stream_->channel_id_source_callback_run_ = true;
34 stream_->channel_id_source_callback_ = nullptr;
35 stream_->DoHandshakeLoop(nullptr);
37 // The ChannelIDSource owns this object and will delete it when this method
38 // returns.
41 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
42 stream_ = nullptr;
45 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
46 QuicCryptoClientStream* stream)
47 : stream_(stream) {}
49 QuicCryptoClientStream::ProofVerifierCallbackImpl::
50 ~ProofVerifierCallbackImpl() {}
52 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
53 bool ok,
54 const string& error_details,
55 scoped_ptr<ProofVerifyDetails>* details) {
56 if (stream_ == nullptr) {
57 return;
60 stream_->verify_ok_ = ok;
61 stream_->verify_error_details_ = error_details;
62 stream_->verify_details_.reset(details->release());
63 stream_->proof_verify_callback_ = nullptr;
64 stream_->DoHandshakeLoop(nullptr);
66 // The ProofVerifier owns this object and will delete it when this method
67 // returns.
70 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
71 stream_ = nullptr;
74 QuicCryptoClientStream::QuicCryptoClientStream(
75 const QuicServerId& server_id,
76 QuicClientSessionBase* session,
77 ProofVerifyContext* verify_context,
78 QuicCryptoClientConfig* crypto_config)
79 : QuicCryptoStream(session),
80 next_state_(STATE_IDLE),
81 num_client_hellos_(0),
82 crypto_config_(crypto_config),
83 server_id_(server_id),
84 generation_counter_(0),
85 channel_id_sent_(false),
86 channel_id_source_callback_run_(false),
87 channel_id_source_callback_(nullptr),
88 verify_context_(verify_context),
89 proof_verify_callback_(nullptr) {}
91 QuicCryptoClientStream::~QuicCryptoClientStream() {
92 if (channel_id_source_callback_) {
93 channel_id_source_callback_->Cancel();
95 if (proof_verify_callback_) {
96 proof_verify_callback_->Cancel();
100 void QuicCryptoClientStream::OnHandshakeMessage(
101 const CryptoHandshakeMessage& message) {
102 QuicCryptoStream::OnHandshakeMessage(message);
104 if (message.tag() == kSCUP) {
105 if (!handshake_confirmed()) {
106 CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
107 return;
110 // |message| is an update from the server, so we treat it differently from a
111 // handshake message.
112 HandleServerConfigUpdateMessage(message);
113 return;
116 // Do not process handshake messages after the handshake is confirmed.
117 if (handshake_confirmed()) {
118 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
119 return;
122 DoHandshakeLoop(&message);
125 bool QuicCryptoClientStream::CryptoConnect() {
126 next_state_ = STATE_INITIALIZE;
127 DoHandshakeLoop(nullptr);
128 return true;
131 int QuicCryptoClientStream::num_sent_client_hellos() const {
132 return num_client_hellos_;
135 bool QuicCryptoClientStream::WasChannelIDSent() const {
136 return channel_id_sent_;
139 bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
140 return channel_id_source_callback_run_;
143 void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
144 const CryptoHandshakeMessage& server_config_update) {
145 DCHECK(server_config_update.tag() == kSCUP);
146 string error_details;
147 QuicCryptoClientConfig::CachedState* cached =
148 crypto_config_->LookupOrCreate(server_id_);
149 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
150 server_config_update,
151 session()->connection()->clock()->WallNow(),
152 cached,
153 &crypto_negotiated_params_,
154 &error_details);
156 if (error != QUIC_NO_ERROR) {
157 CloseConnectionWithDetails(
158 error, "Server config update invalid: " + error_details);
159 return;
162 DCHECK(handshake_confirmed());
163 if (proof_verify_callback_) {
164 proof_verify_callback_->Cancel();
166 next_state_ = STATE_INITIALIZE_SCUP;
167 DoHandshakeLoop(nullptr);
170 // kMaxClientHellos is the maximum number of times that we'll send a client
171 // hello. The value 3 accounts for:
172 // * One failure due to an incorrect or missing source-address token.
173 // * One failure due the server's certificate chain being unavailible and the
174 // server being unwilling to send it without a valid source-address token.
175 static const int kMaxClientHellos = 3;
177 void QuicCryptoClientStream::DoHandshakeLoop(
178 const CryptoHandshakeMessage* in) {
179 QuicCryptoClientConfig::CachedState* cached =
180 crypto_config_->LookupOrCreate(server_id_);
182 QuicAsyncStatus rv = QUIC_SUCCESS;
183 do {
184 CHECK_NE(STATE_NONE, next_state_);
185 const State state = next_state_;
186 next_state_ = STATE_IDLE;
187 rv = QUIC_SUCCESS;
188 switch (state) {
189 case STATE_INITIALIZE:
190 DoInitialize(cached);
191 break;
192 case STATE_SEND_CHLO:
193 DoSendCHLO(in, cached);
194 return;
195 case STATE_RECV_REJ:
196 DoReceiveREJ(in, cached);
197 break;
198 case STATE_VERIFY_PROOF:
199 rv = DoVerifyProof(cached);
200 break;
201 case STATE_VERIFY_PROOF_COMPLETE:
202 DoVerifyProofComplete(cached);
203 break;
204 case STATE_GET_CHANNEL_ID:
205 rv = DoGetChannelID(cached);
206 break;
207 case STATE_GET_CHANNEL_ID_COMPLETE:
208 DoGetChannelIDComplete();
209 break;
210 case STATE_RECV_SHLO:
211 DoReceiveSHLO(in, cached);
212 break;
213 case STATE_IDLE:
214 // This means that the peer sent us a message that we weren't expecting.
215 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
216 return;
217 case STATE_INITIALIZE_SCUP:
218 DoInitializeServerConfigUpdate(cached);
219 break;
220 case STATE_NONE:
221 NOTREACHED();
222 return; // We are done.
224 } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
227 void QuicCryptoClientStream::DoInitialize(
228 QuicCryptoClientConfig::CachedState* cached) {
229 if (!cached->IsEmpty() && !cached->signature().empty() &&
230 server_id_.is_https()) {
231 // Note that we verify the proof even if the cached proof is valid.
232 // This allows us to respond to CA trust changes or certificate
233 // expiration because it may have been a while since we last verified
234 // the proof.
235 DCHECK(crypto_config_->proof_verifier());
236 // If the cached state needs to be verified, do it now.
237 next_state_ = STATE_VERIFY_PROOF;
238 } else {
239 next_state_ = STATE_GET_CHANNEL_ID;
243 void QuicCryptoClientStream::DoSendCHLO(
244 const CryptoHandshakeMessage* in,
245 QuicCryptoClientConfig::CachedState* cached) {
246 // Send the client hello in plaintext.
247 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
248 if (num_client_hellos_ > kMaxClientHellos) {
249 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
250 return;
252 num_client_hellos_++;
254 CryptoHandshakeMessage out;
255 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
256 crypto_config_->FillInchoateClientHello(
257 server_id_,
258 session()->connection()->supported_versions().front(),
259 cached, &crypto_negotiated_params_, &out);
260 // Pad the inchoate client hello to fill up a packet.
261 const QuicByteCount kFramingOverhead = 50; // A rough estimate.
262 const QuicByteCount max_packet_size =
263 session()->connection()->max_packet_length();
264 if (max_packet_size <= kFramingOverhead) {
265 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
266 << ") has no room for framing overhead.";
267 CloseConnection(QUIC_INTERNAL_ERROR);
268 return;
270 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
271 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
272 CloseConnection(QUIC_INTERNAL_ERROR);
273 return;
275 out.set_minimum_size(
276 static_cast<size_t>(max_packet_size - kFramingOverhead));
277 next_state_ = STATE_RECV_REJ;
278 SendHandshakeMessage(out);
279 return;
282 session()->config()->ToHandshakeMessage(&out);
283 string error_details;
284 QuicErrorCode error = crypto_config_->FillClientHello(
285 server_id_,
286 session()->connection()->connection_id(),
287 session()->connection()->supported_versions().front(),
288 cached,
289 session()->connection()->clock()->WallNow(),
290 session()->connection()->random_generator(),
291 channel_id_key_.get(),
292 &crypto_negotiated_params_,
293 &out,
294 &error_details);
295 if (error != QUIC_NO_ERROR) {
296 // Flush the cached config so that, if it's bad, the server has a
297 // chance to send us another in the future.
298 cached->InvalidateServerConfig();
299 CloseConnectionWithDetails(error, error_details);
300 return;
302 channel_id_sent_ = (channel_id_key_.get() != nullptr);
303 if (cached->proof_verify_details()) {
304 client_session()->OnProofVerifyDetailsAvailable(
305 *cached->proof_verify_details());
307 next_state_ = STATE_RECV_SHLO;
308 SendHandshakeMessage(out);
309 // Be prepared to decrypt with the new server write key.
310 session()->connection()->SetAlternativeDecrypter(
311 crypto_negotiated_params_.initial_crypters.decrypter.release(),
312 ENCRYPTION_INITIAL,
313 true /* latch once used */);
314 // Send subsequent packets under encryption on the assumption that the
315 // server will accept the handshake.
316 session()->connection()->SetEncrypter(
317 ENCRYPTION_INITIAL,
318 crypto_negotiated_params_.initial_crypters.encrypter.release());
319 session()->connection()->SetDefaultEncryptionLevel(
320 ENCRYPTION_INITIAL);
321 if (!encryption_established_) {
322 encryption_established_ = true;
323 session()->OnCryptoHandshakeEvent(
324 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
325 } else {
326 session()->OnCryptoHandshakeEvent(
327 QuicSession::ENCRYPTION_REESTABLISHED);
331 void QuicCryptoClientStream::DoReceiveREJ(
332 const CryptoHandshakeMessage* in,
333 QuicCryptoClientConfig::CachedState* cached) {
334 // We sent a dummy CHLO because we didn't have enough information to
335 // perform a handshake, or we sent a full hello that the server
336 // rejected. Here we hope to have a REJ that contains the information
337 // that we need.
338 if (in->tag() != kREJ) {
339 next_state_ = STATE_NONE;
340 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
341 "Expected REJ");
342 return;
344 string error_details;
345 QuicErrorCode error = crypto_config_->ProcessRejection(
346 *in, session()->connection()->clock()->WallNow(), cached,
347 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
348 if (error != QUIC_NO_ERROR) {
349 next_state_ = STATE_NONE;
350 CloseConnectionWithDetails(error, error_details);
351 return;
353 if (!cached->proof_valid()) {
354 if (!server_id_.is_https()) {
355 // We don't check the certificates for insecure QUIC connections.
356 SetCachedProofValid(cached);
357 } else if (!cached->signature().empty()) {
358 // Note that we only verify the proof if the cached proof is not
359 // valid. If the cached proof is valid here, someone else must have
360 // just added the server config to the cache and verified the proof,
361 // so we can assume no CA trust changes or certificate expiration
362 // has happened since then.
363 next_state_ = STATE_VERIFY_PROOF;
364 return;
367 next_state_ = STATE_GET_CHANNEL_ID;
370 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
371 QuicCryptoClientConfig::CachedState* cached) {
372 ProofVerifier* verifier = crypto_config_->proof_verifier();
373 DCHECK(verifier);
374 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
375 generation_counter_ = cached->generation_counter();
377 ProofVerifierCallbackImpl* proof_verify_callback =
378 new ProofVerifierCallbackImpl(this);
380 verify_ok_ = false;
382 QuicAsyncStatus status = verifier->VerifyProof(
383 server_id_.host(),
384 cached->server_config(),
385 cached->certs(),
386 cached->signature(),
387 verify_context_.get(),
388 &verify_error_details_,
389 &verify_details_,
390 proof_verify_callback);
392 switch (status) {
393 case QUIC_PENDING:
394 proof_verify_callback_ = proof_verify_callback;
395 DVLOG(1) << "Doing VerifyProof";
396 break;
397 case QUIC_FAILURE:
398 delete proof_verify_callback;
399 break;
400 case QUIC_SUCCESS:
401 delete proof_verify_callback;
402 verify_ok_ = true;
403 break;
405 return status;
408 void QuicCryptoClientStream::DoVerifyProofComplete(
409 QuicCryptoClientConfig::CachedState* cached) {
410 if (!verify_ok_) {
411 next_state_ = STATE_NONE;
412 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
413 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
414 handshake_confirmed());
415 CloseConnectionWithDetails(
416 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
417 return;
420 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
421 // STATE_VERIFY_PROOF_COMPLETE state changes.
422 if (generation_counter_ != cached->generation_counter()) {
423 next_state_ = STATE_VERIFY_PROOF;
424 } else {
425 SetCachedProofValid(cached);
426 cached->SetProofVerifyDetails(verify_details_.release());
427 if (!handshake_confirmed()) {
428 next_state_ = STATE_GET_CHANNEL_ID;
429 } else {
430 next_state_ = STATE_NONE;
435 QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
436 QuicCryptoClientConfig::CachedState* cached) {
437 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
438 channel_id_key_.reset();
439 if (!RequiresChannelID(cached)) {
440 next_state_ = STATE_SEND_CHLO;
441 return QUIC_SUCCESS;
444 ChannelIDSourceCallbackImpl* channel_id_source_callback =
445 new ChannelIDSourceCallbackImpl(this);
446 QuicAsyncStatus status =
447 crypto_config_->channel_id_source()->GetChannelIDKey(
448 server_id_.host(), &channel_id_key_,
449 channel_id_source_callback);
451 switch (status) {
452 case QUIC_PENDING:
453 channel_id_source_callback_ = channel_id_source_callback;
454 DVLOG(1) << "Looking up channel ID";
455 break;
456 case QUIC_FAILURE:
457 next_state_ = STATE_NONE;
458 delete channel_id_source_callback;
459 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
460 "Channel ID lookup failed");
461 break;
462 case QUIC_SUCCESS:
463 delete channel_id_source_callback;
464 break;
466 return status;
469 void QuicCryptoClientStream::DoGetChannelIDComplete() {
470 if (!channel_id_key_.get()) {
471 next_state_ = STATE_NONE;
472 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
473 "Channel ID lookup failed");
474 return;
476 next_state_ = STATE_SEND_CHLO;
479 void QuicCryptoClientStream::DoReceiveSHLO(
480 const CryptoHandshakeMessage* in,
481 QuicCryptoClientConfig::CachedState* cached) {
482 next_state_ = STATE_NONE;
483 // We sent a CHLO that we expected to be accepted and now we're hoping
484 // for a SHLO from the server to confirm that.
485 if (in->tag() == kREJ) {
486 // alternative_decrypter will be nullptr if the original alternative
487 // decrypter latched and became the primary decrypter. That happens
488 // if we received a message encrypted with the INITIAL key.
489 if (session()->connection()->alternative_decrypter() == nullptr) {
490 // The rejection was sent encrypted!
491 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
492 "encrypted REJ message");
493 return;
495 next_state_ = STATE_RECV_REJ;
496 return;
499 if (in->tag() != kSHLO) {
500 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
501 "Expected SHLO or REJ");
502 return;
505 // alternative_decrypter will be nullptr if the original alternative
506 // decrypter latched and became the primary decrypter. That happens
507 // if we received a message encrypted with the INITIAL key.
508 if (session()->connection()->alternative_decrypter() != nullptr) {
509 // The server hello was sent without encryption.
510 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
511 "unencrypted SHLO message");
512 return;
515 string error_details;
516 QuicErrorCode error = crypto_config_->ProcessServerHello(
517 *in, session()->connection()->connection_id(),
518 session()->connection()->server_supported_versions(),
519 cached, &crypto_negotiated_params_, &error_details);
521 if (error != QUIC_NO_ERROR) {
522 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
523 return;
525 error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
526 if (error != QUIC_NO_ERROR) {
527 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
528 return;
530 session()->OnConfigNegotiated();
532 CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters;
533 // TODO(agl): we don't currently latch this decrypter because the idea
534 // has been floated that the server shouldn't send packets encrypted
535 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
536 // packet from the client.
537 session()->connection()->SetAlternativeDecrypter(
538 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
539 false /* don't latch */);
540 session()->connection()->SetEncrypter(
541 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
542 session()->connection()->SetDefaultEncryptionLevel(
543 ENCRYPTION_FORWARD_SECURE);
545 handshake_confirmed_ = true;
546 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
547 session()->connection()->OnHandshakeComplete();
550 void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
551 QuicCryptoClientConfig::CachedState* cached) {
552 bool update_ignored = false;
553 if (!server_id_.is_https()) {
554 // We don't check the certificates for insecure QUIC connections.
555 SetCachedProofValid(cached);
556 next_state_ = STATE_NONE;
557 } else if (!cached->IsEmpty() && !cached->signature().empty()) {
558 // Note that we verify the proof even if the cached proof is valid.
559 DCHECK(crypto_config_->proof_verifier());
560 next_state_ = STATE_VERIFY_PROOF;
561 } else {
562 update_ignored = true;
563 next_state_ = STATE_NONE;
565 UMA_HISTOGRAM_COUNTS("Net.QuicNumServerConfig.UpdateMessagesIgnored",
566 update_ignored);
569 void QuicCryptoClientStream::SetCachedProofValid(
570 QuicCryptoClientConfig::CachedState* cached) {
571 cached->SetProofValid();
572 client_session()->OnProofValid(*cached);
575 bool QuicCryptoClientStream::RequiresChannelID(
576 QuicCryptoClientConfig::CachedState* cached) {
577 if (!server_id_.is_https() ||
578 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
579 !crypto_config_->channel_id_source()) {
580 return false;
582 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
583 if (!scfg) { // scfg may be null when we send an inchoate CHLO.
584 return false;
586 const QuicTag* their_proof_demands;
587 size_t num_their_proof_demands;
588 if (scfg->GetTaglist(kPDMD, &their_proof_demands,
589 &num_their_proof_demands) != QUIC_NO_ERROR) {
590 return false;
592 for (size_t i = 0; i < num_their_proof_demands; i++) {
593 if (their_proof_demands[i] == kCHID) {
594 return true;
597 return false;
600 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
601 return reinterpret_cast<QuicClientSessionBase*>(session());
604 } // namespace net