MacViews: Get c/b/ui/views/tabs to build on Mac
[chromium-blink-merge.git] / net / quic / quic_crypto_client_stream.cc
blob1c41e0a6e08ca352d3ca06dfe9098820e843997b
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 namespace net {
17 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
18 ChannelIDSourceCallbackImpl(QuicCryptoClientStream* stream)
19 : stream_(stream) {}
21 QuicCryptoClientStream::ChannelIDSourceCallbackImpl::
22 ~ChannelIDSourceCallbackImpl() {}
24 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Run(
25 scoped_ptr<ChannelIDKey>* channel_id_key) {
26 if (stream_ == nullptr) {
27 return;
30 stream_->channel_id_key_.reset(channel_id_key->release());
31 stream_->channel_id_source_callback_run_ = true;
32 stream_->channel_id_source_callback_ = nullptr;
33 stream_->DoHandshakeLoop(nullptr);
35 // The ChannelIDSource owns this object and will delete it when this method
36 // returns.
39 void QuicCryptoClientStream::ChannelIDSourceCallbackImpl::Cancel() {
40 stream_ = nullptr;
43 QuicCryptoClientStream::ProofVerifierCallbackImpl::ProofVerifierCallbackImpl(
44 QuicCryptoClientStream* stream)
45 : stream_(stream) {}
47 QuicCryptoClientStream::ProofVerifierCallbackImpl::
48 ~ProofVerifierCallbackImpl() {}
50 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Run(
51 bool ok,
52 const string& error_details,
53 scoped_ptr<ProofVerifyDetails>* details) {
54 if (stream_ == nullptr) {
55 return;
58 stream_->verify_ok_ = ok;
59 stream_->verify_error_details_ = error_details;
60 stream_->verify_details_.reset(details->release());
61 stream_->proof_verify_callback_ = nullptr;
62 stream_->DoHandshakeLoop(nullptr);
64 // The ProofVerifier owns this object and will delete it when this method
65 // returns.
68 void QuicCryptoClientStream::ProofVerifierCallbackImpl::Cancel() {
69 stream_ = nullptr;
72 QuicCryptoClientStream::QuicCryptoClientStream(
73 const QuicServerId& server_id,
74 QuicClientSessionBase* session,
75 ProofVerifyContext* verify_context,
76 QuicCryptoClientConfig* crypto_config)
77 : QuicCryptoStream(session),
78 next_state_(STATE_IDLE),
79 num_client_hellos_(0),
80 crypto_config_(crypto_config),
81 server_id_(server_id),
82 generation_counter_(0),
83 channel_id_sent_(false),
84 channel_id_source_callback_run_(false),
85 channel_id_source_callback_(nullptr),
86 verify_context_(verify_context),
87 proof_verify_callback_(nullptr) {}
89 QuicCryptoClientStream::~QuicCryptoClientStream() {
90 if (channel_id_source_callback_) {
91 channel_id_source_callback_->Cancel();
93 if (proof_verify_callback_) {
94 proof_verify_callback_->Cancel();
98 void QuicCryptoClientStream::OnHandshakeMessage(
99 const CryptoHandshakeMessage& message) {
100 QuicCryptoStream::OnHandshakeMessage(message);
102 if (message.tag() == kSCUP) {
103 if (!handshake_confirmed()) {
104 CloseConnection(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE);
105 return;
108 // |message| is an update from the server, so we treat it differently from a
109 // handshake message.
110 HandleServerConfigUpdateMessage(message);
111 return;
114 // Do not process handshake messages after the handshake is confirmed.
115 if (handshake_confirmed()) {
116 CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
117 return;
120 DoHandshakeLoop(&message);
123 bool QuicCryptoClientStream::CryptoConnect() {
124 next_state_ = STATE_INITIALIZE;
125 DoHandshakeLoop(nullptr);
126 return true;
129 int QuicCryptoClientStream::num_sent_client_hellos() const {
130 return num_client_hellos_;
133 bool QuicCryptoClientStream::WasChannelIDSent() const {
134 return channel_id_sent_;
137 bool QuicCryptoClientStream::WasChannelIDSourceCallbackRun() const {
138 return channel_id_source_callback_run_;
141 void QuicCryptoClientStream::HandleServerConfigUpdateMessage(
142 const CryptoHandshakeMessage& server_config_update) {
143 DCHECK(server_config_update.tag() == kSCUP);
144 string error_details;
145 QuicCryptoClientConfig::CachedState* cached =
146 crypto_config_->LookupOrCreate(server_id_);
147 QuicErrorCode error = crypto_config_->ProcessServerConfigUpdate(
148 server_config_update,
149 session()->connection()->clock()->WallNow(),
150 cached,
151 &crypto_negotiated_params_,
152 &error_details);
154 if (error != QUIC_NO_ERROR) {
155 CloseConnectionWithDetails(
156 error, "Server config update invalid: " + error_details);
157 return;
160 DCHECK(handshake_confirmed());
161 if (proof_verify_callback_) {
162 proof_verify_callback_->Cancel();
164 next_state_ = STATE_INITIALIZE_SCUP;
165 DoHandshakeLoop(nullptr);
168 // kMaxClientHellos is the maximum number of times that we'll send a client
169 // hello. The value 3 accounts for:
170 // * One failure due to an incorrect or missing source-address token.
171 // * One failure due the server's certificate chain being unavailible and the
172 // server being unwilling to send it without a valid source-address token.
173 static const int kMaxClientHellos = 3;
175 void QuicCryptoClientStream::DoHandshakeLoop(
176 const CryptoHandshakeMessage* in) {
177 QuicCryptoClientConfig::CachedState* cached =
178 crypto_config_->LookupOrCreate(server_id_);
180 QuicAsyncStatus rv = QUIC_SUCCESS;
181 do {
182 CHECK_NE(STATE_NONE, next_state_);
183 const State state = next_state_;
184 next_state_ = STATE_IDLE;
185 rv = QUIC_SUCCESS;
186 switch (state) {
187 case STATE_INITIALIZE:
188 DoInitialize(cached);
189 break;
190 case STATE_SEND_CHLO:
191 DoSendCHLO(in, cached);
192 return;
193 case STATE_RECV_REJ:
194 DoReceiveREJ(in, cached);
195 break;
196 case STATE_VERIFY_PROOF:
197 rv = DoVerifyProof(cached);
198 break;
199 case STATE_VERIFY_PROOF_COMPLETE:
200 DoVerifyProofComplete(cached);
201 break;
202 case STATE_GET_CHANNEL_ID:
203 rv = DoGetChannelID(cached);
204 break;
205 case STATE_GET_CHANNEL_ID_COMPLETE:
206 DoGetChannelIDComplete();
207 break;
208 case STATE_RECV_SHLO:
209 DoReceiveSHLO(in, cached);
210 break;
211 case STATE_IDLE:
212 // This means that the peer sent us a message that we weren't expecting.
213 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
214 return;
215 case STATE_INITIALIZE_SCUP:
216 DoInitializeServerConfigUpdate(cached);
217 break;
218 case STATE_NONE:
219 NOTREACHED();
220 return; // We are done.
222 } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
225 void QuicCryptoClientStream::DoInitialize(
226 QuicCryptoClientConfig::CachedState* cached) {
227 if (!cached->IsEmpty() && !cached->signature().empty() &&
228 server_id_.is_https()) {
229 // Note that we verify the proof even if the cached proof is valid.
230 // This allows us to respond to CA trust changes or certificate
231 // expiration because it may have been a while since we last verified
232 // the proof.
233 DCHECK(crypto_config_->proof_verifier());
234 // If the cached state needs to be verified, do it now.
235 next_state_ = STATE_VERIFY_PROOF;
236 } else {
237 next_state_ = STATE_GET_CHANNEL_ID;
241 void QuicCryptoClientStream::DoSendCHLO(
242 const CryptoHandshakeMessage* in,
243 QuicCryptoClientConfig::CachedState* cached) {
244 // Send the client hello in plaintext.
245 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
246 if (num_client_hellos_ > kMaxClientHellos) {
247 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
248 return;
250 num_client_hellos_++;
252 CryptoHandshakeMessage out;
253 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
254 crypto_config_->FillInchoateClientHello(
255 server_id_,
256 session()->connection()->supported_versions().front(),
257 cached, &crypto_negotiated_params_, &out);
258 // Pad the inchoate client hello to fill up a packet.
259 const size_t kFramingOverhead = 50; // A rough estimate.
260 const size_t max_packet_size =
261 session()->connection()->max_packet_length();
262 if (max_packet_size <= kFramingOverhead) {
263 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
264 << ") has no room for framing overhead.";
265 CloseConnection(QUIC_INTERNAL_ERROR);
266 return;
268 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
269 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
270 CloseConnection(QUIC_INTERNAL_ERROR);
271 return;
273 out.set_minimum_size(max_packet_size - kFramingOverhead);
274 next_state_ = STATE_RECV_REJ;
275 SendHandshakeMessage(out);
276 return;
279 session()->config()->ToHandshakeMessage(&out);
280 string error_details;
281 QuicErrorCode error = crypto_config_->FillClientHello(
282 server_id_,
283 session()->connection()->connection_id(),
284 session()->connection()->supported_versions().front(),
285 cached,
286 session()->connection()->clock()->WallNow(),
287 session()->connection()->random_generator(),
288 channel_id_key_.get(),
289 &crypto_negotiated_params_,
290 &out,
291 &error_details);
292 if (error != QUIC_NO_ERROR) {
293 // Flush the cached config so that, if it's bad, the server has a
294 // chance to send us another in the future.
295 cached->InvalidateServerConfig();
296 CloseConnectionWithDetails(error, error_details);
297 return;
299 channel_id_sent_ = (channel_id_key_.get() != nullptr);
300 if (cached->proof_verify_details()) {
301 client_session()->OnProofVerifyDetailsAvailable(
302 *cached->proof_verify_details());
304 next_state_ = STATE_RECV_SHLO;
305 SendHandshakeMessage(out);
306 // Be prepared to decrypt with the new server write key.
307 session()->connection()->SetAlternativeDecrypter(
308 crypto_negotiated_params_.initial_crypters.decrypter.release(),
309 ENCRYPTION_INITIAL,
310 true /* latch once used */);
311 // Send subsequent packets under encryption on the assumption that the
312 // server will accept the handshake.
313 session()->connection()->SetEncrypter(
314 ENCRYPTION_INITIAL,
315 crypto_negotiated_params_.initial_crypters.encrypter.release());
316 session()->connection()->SetDefaultEncryptionLevel(
317 ENCRYPTION_INITIAL);
318 if (!encryption_established_) {
319 encryption_established_ = true;
320 session()->OnCryptoHandshakeEvent(
321 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
322 } else {
323 session()->OnCryptoHandshakeEvent(
324 QuicSession::ENCRYPTION_REESTABLISHED);
328 void QuicCryptoClientStream::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.
335 if (in->tag() != kREJ) {
336 next_state_ = STATE_NONE;
337 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
338 "Expected REJ");
339 return;
341 string error_details;
342 QuicErrorCode error = crypto_config_->ProcessRejection(
343 *in, session()->connection()->clock()->WallNow(), cached,
344 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
345 if (error != QUIC_NO_ERROR) {
346 next_state_ = STATE_NONE;
347 CloseConnectionWithDetails(error, error_details);
348 return;
350 if (!cached->proof_valid()) {
351 if (!server_id_.is_https()) {
352 // We don't check the certificates for insecure QUIC connections.
353 SetCachedProofValid(cached);
354 } else if (!cached->signature().empty()) {
355 // Note that we only verify the proof if the cached proof is not
356 // valid. If the cached proof is valid here, someone else must have
357 // just added the server config to the cache and verified the proof,
358 // so we can assume no CA trust changes or certificate expiration
359 // has happened since then.
360 next_state_ = STATE_VERIFY_PROOF;
361 return;
364 next_state_ = STATE_GET_CHANNEL_ID;
367 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
368 QuicCryptoClientConfig::CachedState* cached) {
369 ProofVerifier* verifier = crypto_config_->proof_verifier();
370 DCHECK(verifier);
371 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
372 generation_counter_ = cached->generation_counter();
374 ProofVerifierCallbackImpl* proof_verify_callback =
375 new ProofVerifierCallbackImpl(this);
377 verify_ok_ = false;
379 QuicAsyncStatus status = verifier->VerifyProof(
380 server_id_.host(),
381 cached->server_config(),
382 cached->certs(),
383 cached->signature(),
384 verify_context_.get(),
385 &verify_error_details_,
386 &verify_details_,
387 proof_verify_callback);
389 switch (status) {
390 case QUIC_PENDING:
391 proof_verify_callback_ = proof_verify_callback;
392 DVLOG(1) << "Doing VerifyProof";
393 break;
394 case QUIC_FAILURE:
395 delete proof_verify_callback;
396 break;
397 case QUIC_SUCCESS:
398 delete proof_verify_callback;
399 verify_ok_ = true;
400 break;
402 return status;
405 void QuicCryptoClientStream::DoVerifyProofComplete(
406 QuicCryptoClientConfig::CachedState* cached) {
407 if (!verify_ok_) {
408 next_state_ = STATE_NONE;
409 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
410 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
411 handshake_confirmed());
412 CloseConnectionWithDetails(
413 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
414 return;
417 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
418 // STATE_VERIFY_PROOF_COMPLETE state changes.
419 if (generation_counter_ != cached->generation_counter()) {
420 next_state_ = STATE_VERIFY_PROOF;
421 } else {
422 SetCachedProofValid(cached);
423 cached->SetProofVerifyDetails(verify_details_.release());
424 if (!handshake_confirmed()) {
425 next_state_ = STATE_GET_CHANNEL_ID;
426 } else {
427 next_state_ = STATE_NONE;
432 QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
433 QuicCryptoClientConfig::CachedState* cached) {
434 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
435 channel_id_key_.reset();
436 if (!RequiresChannelID(cached)) {
437 next_state_ = STATE_SEND_CHLO;
438 return QUIC_SUCCESS;
441 ChannelIDSourceCallbackImpl* channel_id_source_callback =
442 new ChannelIDSourceCallbackImpl(this);
443 QuicAsyncStatus status =
444 crypto_config_->channel_id_source()->GetChannelIDKey(
445 server_id_.host(), &channel_id_key_,
446 channel_id_source_callback);
448 switch (status) {
449 case QUIC_PENDING:
450 channel_id_source_callback_ = channel_id_source_callback;
451 DVLOG(1) << "Looking up channel ID";
452 break;
453 case QUIC_FAILURE:
454 next_state_ = STATE_NONE;
455 delete channel_id_source_callback;
456 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
457 "Channel ID lookup failed");
458 break;
459 case QUIC_SUCCESS:
460 delete channel_id_source_callback;
461 break;
463 return status;
466 void QuicCryptoClientStream::DoGetChannelIDComplete() {
467 if (!channel_id_key_.get()) {
468 next_state_ = STATE_NONE;
469 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
470 "Channel ID lookup failed");
471 return;
473 next_state_ = STATE_SEND_CHLO;
476 void QuicCryptoClientStream::DoReceiveSHLO(
477 const CryptoHandshakeMessage* in,
478 QuicCryptoClientConfig::CachedState* cached) {
479 next_state_ = STATE_NONE;
480 // We sent a CHLO that we expected to be accepted and now we're hoping
481 // for a SHLO from the server to confirm that.
482 if (in->tag() == kREJ) {
483 // alternative_decrypter will be nullptr if the original alternative
484 // decrypter latched and became the primary decrypter. That happens
485 // if we received a message encrypted with the INITIAL key.
486 if (session()->connection()->alternative_decrypter() == nullptr) {
487 // The rejection was sent encrypted!
488 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
489 "encrypted REJ message");
490 return;
492 next_state_ = STATE_RECV_REJ;
493 return;
496 if (in->tag() != kSHLO) {
497 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
498 "Expected SHLO or REJ");
499 return;
502 // alternative_decrypter will be nullptr if the original alternative
503 // decrypter latched and became the primary decrypter. That happens
504 // if we received a message encrypted with the INITIAL key.
505 if (session()->connection()->alternative_decrypter() != nullptr) {
506 // The server hello was sent without encryption.
507 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
508 "unencrypted SHLO message");
509 return;
512 string error_details;
513 QuicErrorCode error = crypto_config_->ProcessServerHello(
514 *in, session()->connection()->connection_id(),
515 session()->connection()->server_supported_versions(),
516 cached, &crypto_negotiated_params_, &error_details);
518 if (error != QUIC_NO_ERROR) {
519 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
520 return;
522 error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
523 if (error != QUIC_NO_ERROR) {
524 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
525 return;
527 session()->OnConfigNegotiated();
529 CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters;
530 // TODO(agl): we don't currently latch this decrypter because the idea
531 // has been floated that the server shouldn't send packets encrypted
532 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
533 // packet from the client.
534 session()->connection()->SetAlternativeDecrypter(
535 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
536 false /* don't latch */);
537 session()->connection()->SetEncrypter(
538 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
539 session()->connection()->SetDefaultEncryptionLevel(
540 ENCRYPTION_FORWARD_SECURE);
542 handshake_confirmed_ = true;
543 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
544 session()->connection()->OnHandshakeComplete();
547 void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
548 QuicCryptoClientConfig::CachedState* cached) {
549 bool update_ignored = false;
550 if (!server_id_.is_https()) {
551 // We don't check the certificates for insecure QUIC connections.
552 SetCachedProofValid(cached);
553 next_state_ = STATE_NONE;
554 } else if (!cached->IsEmpty() && !cached->signature().empty()) {
555 // Note that we verify the proof even if the cached proof is valid.
556 DCHECK(crypto_config_->proof_verifier());
557 next_state_ = STATE_VERIFY_PROOF;
558 } else {
559 update_ignored = true;
560 next_state_ = STATE_NONE;
562 UMA_HISTOGRAM_COUNTS("Net.QuicNumServerConfig.UpdateMessagesIgnored",
563 update_ignored);
566 void QuicCryptoClientStream::SetCachedProofValid(
567 QuicCryptoClientConfig::CachedState* cached) {
568 cached->SetProofValid();
569 client_session()->OnProofValid(*cached);
572 bool QuicCryptoClientStream::RequiresChannelID(
573 QuicCryptoClientConfig::CachedState* cached) {
574 if (!server_id_.is_https() ||
575 server_id_.privacy_mode() == PRIVACY_MODE_ENABLED ||
576 !crypto_config_->channel_id_source()) {
577 return false;
579 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
580 if (!scfg) { // scfg may be null when we send an inchoate CHLO.
581 return false;
583 const QuicTag* their_proof_demands;
584 size_t num_their_proof_demands;
585 if (scfg->GetTaglist(kPDMD, &their_proof_demands,
586 &num_their_proof_demands) != QUIC_NO_ERROR) {
587 return false;
589 for (size_t i = 0; i < num_their_proof_demands; i++) {
590 if (their_proof_demands[i] == kCHID) {
591 return true;
594 return false;
597 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
598 return reinterpret_cast<QuicClientSessionBase*>(session());
601 } // namespace net