Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: net/quic/quic_crypto_client_stream.cc

Issue 588443002: QUIC - minor reorg of QuicCryptoClientStream::DoHandshakeLoop. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Return QuicAsyncStatus for async Do... methods Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_crypto_client_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/quic_crypto_client_stream.h" 5 #include "net/quic/quic_crypto_client_stream.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "net/quic/crypto/crypto_protocol.h" 8 #include "net/quic/crypto/crypto_protocol.h"
9 #include "net/quic/crypto/crypto_utils.h" 9 #include "net/quic/crypto/crypto_utils.h"
10 #include "net/quic/crypto/null_encrypter.h" 10 #include "net/quic/crypto/null_encrypter.h"
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 168
169 // kMaxClientHellos is the maximum number of times that we'll send a client 169 // kMaxClientHellos is the maximum number of times that we'll send a client
170 // hello. The value 3 accounts for: 170 // hello. The value 3 accounts for:
171 // * One failure due to an incorrect or missing source-address token. 171 // * One failure due to an incorrect or missing source-address token.
172 // * One failure due the server's certificate chain being unavailible and the 172 // * One failure due the server's certificate chain being unavailible and the
173 // server being unwilling to send it without a valid source-address token. 173 // server being unwilling to send it without a valid source-address token.
174 static const int kMaxClientHellos = 3; 174 static const int kMaxClientHellos = 3;
175 175
176 void QuicCryptoClientStream::DoHandshakeLoop( 176 void QuicCryptoClientStream::DoHandshakeLoop(
177 const CryptoHandshakeMessage* in) { 177 const CryptoHandshakeMessage* in) {
178 CryptoHandshakeMessage out;
179 QuicErrorCode error;
180 string error_details;
181 QuicCryptoClientConfig::CachedState* cached = 178 QuicCryptoClientConfig::CachedState* cached =
182 crypto_config_->LookupOrCreate(server_id_); 179 crypto_config_->LookupOrCreate(server_id_);
183 180
184 for (;;) { 181 QuicAsyncStatus rv = QUIC_SUCCESS;
182 do {
183 CHECK_NE(STATE_NONE, next_state_);
185 const State state = next_state_; 184 const State state = next_state_;
186 next_state_ = STATE_IDLE; 185 next_state_ = STATE_IDLE;
186 rv = QUIC_SUCCESS;
187 switch (state) { 187 switch (state) {
188 case STATE_INITIALIZE: { 188 case STATE_INITIALIZE:
189 if (!cached->IsEmpty() && !cached->signature().empty() && 189 DoInitialize(cached);
190 server_id_.is_https()) {
191 // Note that we verify the proof even if the cached proof is valid.
192 // This allows us to respond to CA trust changes or certificate
193 // expiration because it may have been a while since we last verified
194 // the proof.
195 DCHECK(crypto_config_->proof_verifier());
196 // If the cached state needs to be verified, do it now.
197 next_state_ = STATE_VERIFY_PROOF;
198 } else {
199 next_state_ = STATE_GET_CHANNEL_ID;
200 }
201 break; 190 break;
202 } 191 case STATE_SEND_CHLO:
203 case STATE_SEND_CHLO: { 192 DoSendCHLO(in, cached);
204 // Send the client hello in plaintext.
205 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
206 if (num_client_hellos_ > kMaxClientHellos) {
207 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
208 return;
209 }
210 num_client_hellos_++;
211
212 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
213 crypto_config_->FillInchoateClientHello(
214 server_id_,
215 session()->connection()->supported_versions().front(),
216 cached, &crypto_negotiated_params_, &out);
217 // Pad the inchoate client hello to fill up a packet.
218 const size_t kFramingOverhead = 50; // A rough estimate.
219 const size_t max_packet_size =
220 session()->connection()->max_packet_length();
221 if (max_packet_size <= kFramingOverhead) {
222 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
223 << ") has no room for framing overhead.";
224 CloseConnection(QUIC_INTERNAL_ERROR);
225 return;
226 }
227 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
228 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
229 CloseConnection(QUIC_INTERNAL_ERROR);
230 return;
231 }
232 out.set_minimum_size(max_packet_size - kFramingOverhead);
233 next_state_ = STATE_RECV_REJ;
234 SendHandshakeMessage(out);
235 return;
236 }
237 session()->config()->ToHandshakeMessage(&out);
238 error = crypto_config_->FillClientHello(
239 server_id_,
240 session()->connection()->connection_id(),
241 session()->connection()->supported_versions().front(),
242 cached,
243 session()->connection()->clock()->WallNow(),
244 session()->connection()->random_generator(),
245 channel_id_key_.get(),
246 &crypto_negotiated_params_,
247 &out,
248 &error_details);
249 if (error != QUIC_NO_ERROR) {
250 // Flush the cached config so that, if it's bad, the server has a
251 // chance to send us another in the future.
252 cached->InvalidateServerConfig();
253 CloseConnectionWithDetails(error, error_details);
254 return;
255 }
256 channel_id_sent_ = (channel_id_key_.get() != NULL);
257 if (cached->proof_verify_details()) {
258 client_session()->OnProofVerifyDetailsAvailable(
259 *cached->proof_verify_details());
260 }
261 next_state_ = STATE_RECV_SHLO;
262 SendHandshakeMessage(out);
263 // Be prepared to decrypt with the new server write key.
264 session()->connection()->SetAlternativeDecrypter(
265 crypto_negotiated_params_.initial_crypters.decrypter.release(),
266 ENCRYPTION_INITIAL,
267 true /* latch once used */);
268 // Send subsequent packets under encryption on the assumption that the
269 // server will accept the handshake.
270 session()->connection()->SetEncrypter(
271 ENCRYPTION_INITIAL,
272 crypto_negotiated_params_.initial_crypters.encrypter.release());
273 session()->connection()->SetDefaultEncryptionLevel(
274 ENCRYPTION_INITIAL);
275 if (!encryption_established_) {
276 encryption_established_ = true;
277 session()->OnCryptoHandshakeEvent(
278 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
279 } else {
280 session()->OnCryptoHandshakeEvent(
281 QuicSession::ENCRYPTION_REESTABLISHED);
282 }
283 return; 193 return;
284 }
285 case STATE_RECV_REJ: 194 case STATE_RECV_REJ:
286 // We sent a dummy CHLO because we didn't have enough information to 195 DoReceiveREJ(in, cached);
287 // perform a handshake, or we sent a full hello that the server
288 // rejected. Here we hope to have a REJ that contains the information
289 // that we need.
290 if (in->tag() != kREJ) {
291 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
292 "Expected REJ");
293 return;
294 }
295 error = crypto_config_->ProcessRejection(
296 *in, session()->connection()->clock()->WallNow(), cached,
297 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
298 if (error != QUIC_NO_ERROR) {
299 CloseConnectionWithDetails(error, error_details);
300 return;
301 }
302 if (!cached->proof_valid()) {
303 if (!server_id_.is_https()) {
304 // We don't check the certificates for insecure QUIC connections.
305 SetCachedProofValid(cached);
306 } else if (!cached->signature().empty()) {
307 // Note that we only verify the proof if the cached proof is not
308 // valid. If the cached proof is valid here, someone else must have
309 // just added the server config to the cache and verified the proof,
310 // so we can assume no CA trust changes or certificate expiration
311 // has happened since then.
312 next_state_ = STATE_VERIFY_PROOF;
313 break;
314 }
315 }
316 next_state_ = STATE_GET_CHANNEL_ID;
317 break; 196 break;
318 case STATE_VERIFY_PROOF: { 197 case STATE_VERIFY_PROOF:
319 if (QUIC_PENDING == DoVerifyProof(cached)) { 198 rv = DoVerifyProof(cached);
320 return;
321 }
322 break; 199 break;
323 }
324 case STATE_VERIFY_PROOF_COMPLETE: 200 case STATE_VERIFY_PROOF_COMPLETE:
325 if (QUIC_PROOF_INVALID == DoVerifyProofComplete(cached)) { 201 DoVerifyProofComplete(cached);
326 return;
327 }
328 break; 202 break;
329 case STATE_GET_CHANNEL_ID: { 203 case STATE_GET_CHANNEL_ID:
330 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE; 204 rv = DoGetChannelID(cached);
331 channel_id_key_.reset();
332 if (!RequiresChannelID(cached)) {
333 next_state_ = STATE_SEND_CHLO;
334 break;
335 }
336
337 ChannelIDSourceCallbackImpl* channel_id_source_callback =
338 new ChannelIDSourceCallbackImpl(this);
339 QuicAsyncStatus status =
340 crypto_config_->channel_id_source()->GetChannelIDKey(
341 server_id_.host(), &channel_id_key_,
342 channel_id_source_callback);
343
344 switch (status) {
345 case QUIC_PENDING:
346 channel_id_source_callback_ = channel_id_source_callback;
347 DVLOG(1) << "Looking up channel ID";
348 return;
349 case QUIC_FAILURE:
350 delete channel_id_source_callback;
351 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
352 "Channel ID lookup failed");
353 return;
354 case QUIC_SUCCESS:
355 delete channel_id_source_callback;
356 break;
357 }
358 break; 205 break;
359 }
360 case STATE_GET_CHANNEL_ID_COMPLETE: 206 case STATE_GET_CHANNEL_ID_COMPLETE:
361 if (!channel_id_key_.get()) { 207 DoGetChannelIDComplete();
362 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
363 "Channel ID lookup failed");
364 return;
365 }
366 next_state_ = STATE_SEND_CHLO;
367 break; 208 break;
368 case STATE_RECV_SHLO: { 209 case STATE_RECV_SHLO:
369 // We sent a CHLO that we expected to be accepted and now we're hoping 210 DoReceiveSHLO(in, cached);
370 // for a SHLO from the server to confirm that. 211 break;
371 if (in->tag() == kREJ) {
372 // alternative_decrypter will be NULL if the original alternative
373 // decrypter latched and became the primary decrypter. That happens
374 // if we received a message encrypted with the INITIAL key.
375 if (session()->connection()->alternative_decrypter() == NULL) {
376 // The rejection was sent encrypted!
377 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
378 "encrypted REJ message");
379 return;
380 }
381 next_state_ = STATE_RECV_REJ;
382 break;
383 }
384 if (in->tag() != kSHLO) {
385 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
386 "Expected SHLO or REJ");
387 return;
388 }
389 // alternative_decrypter will be NULL if the original alternative
390 // decrypter latched and became the primary decrypter. That happens
391 // if we received a message encrypted with the INITIAL key.
392 if (session()->connection()->alternative_decrypter() != NULL) {
393 // The server hello was sent without encryption.
394 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
395 "unencrypted SHLO message");
396 return;
397 }
398 error = crypto_config_->ProcessServerHello(
399 *in, session()->connection()->connection_id(),
400 session()->connection()->server_supported_versions(),
401 cached, &crypto_negotiated_params_, &error_details);
402
403 if (error != QUIC_NO_ERROR) {
404 CloseConnectionWithDetails(
405 error, "Server hello invalid: " + error_details);
406 return;
407 }
408 error =
409 session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
410 if (error != QUIC_NO_ERROR) {
411 CloseConnectionWithDetails(
412 error, "Server hello invalid: " + error_details);
413 return;
414 }
415 session()->OnConfigNegotiated();
416
417 CrypterPair* crypters =
418 &crypto_negotiated_params_.forward_secure_crypters;
419 // TODO(agl): we don't currently latch this decrypter because the idea
420 // has been floated that the server shouldn't send packets encrypted
421 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
422 // packet from the client.
423 session()->connection()->SetAlternativeDecrypter(
424 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
425 false /* don't latch */);
426 session()->connection()->SetEncrypter(
427 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
428 session()->connection()->SetDefaultEncryptionLevel(
429 ENCRYPTION_FORWARD_SECURE);
430
431 handshake_confirmed_ = true;
432 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
433 session()->connection()->OnHandshakeComplete();
434 return;
435 }
436 case STATE_IDLE: 212 case STATE_IDLE:
437 // This means that the peer sent us a message that we weren't expecting. 213 // This means that the peer sent us a message that we weren't expecting.
438 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); 214 CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
439 return; 215 return;
440 case STATE_INITIALIZE_SCUP: 216 case STATE_INITIALIZE_SCUP:
441 DoInitializeServerConfigUpdate(cached); 217 DoInitializeServerConfigUpdate(cached);
442 break; 218 break;
443 case STATE_VERIFY_PROOF_DONE: 219 case STATE_NONE:
220 NOTREACHED();
444 return; // We are done. 221 return; // We are done.
445 } 222 }
223 } while (rv != QUIC_PENDING && next_state_ != STATE_NONE);
224 }
225
226 void QuicCryptoClientStream::DoInitialize(
227 QuicCryptoClientConfig::CachedState* cached) {
228 if (!cached->IsEmpty() && !cached->signature().empty() &&
229 server_id_.is_https()) {
230 // Note that we verify the proof even if the cached proof is valid.
231 // This allows us to respond to CA trust changes or certificate
232 // expiration because it may have been a while since we last verified
233 // the proof.
234 DCHECK(crypto_config_->proof_verifier());
235 // If the cached state needs to be verified, do it now.
236 next_state_ = STATE_VERIFY_PROOF;
237 } else {
238 next_state_ = STATE_GET_CHANNEL_ID;
446 } 239 }
447 } 240 }
448 241
449 void QuicCryptoClientStream::DoInitializeServerConfigUpdate( 242 void QuicCryptoClientStream::DoSendCHLO(
243 const CryptoHandshakeMessage* in,
450 QuicCryptoClientConfig::CachedState* cached) { 244 QuicCryptoClientConfig::CachedState* cached) {
451 bool update_ignored = false; 245 // Send the client hello in plaintext.
452 if (!server_id_.is_https()) { 246 session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_NONE);
453 // We don't check the certificates for insecure QUIC connections. 247 if (num_client_hellos_ > kMaxClientHellos) {
454 SetCachedProofValid(cached); 248 CloseConnection(QUIC_CRYPTO_TOO_MANY_REJECTS);
455 next_state_ = STATE_VERIFY_PROOF_DONE; 249 return;
456 } else if (!cached->IsEmpty() && !cached->signature().empty()) { 250 }
457 // Note that we verify the proof even if the cached proof is valid. 251 num_client_hellos_++;
458 DCHECK(crypto_config_->proof_verifier()); 252
459 next_state_ = STATE_VERIFY_PROOF; 253 CryptoHandshakeMessage out;
254 if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
255 crypto_config_->FillInchoateClientHello(
256 server_id_,
257 session()->connection()->supported_versions().front(),
258 cached, &crypto_negotiated_params_, &out);
259 // Pad the inchoate client hello to fill up a packet.
260 const size_t kFramingOverhead = 50; // A rough estimate.
261 const size_t max_packet_size =
262 session()->connection()->max_packet_length();
263 if (max_packet_size <= kFramingOverhead) {
264 DLOG(DFATAL) << "max_packet_length (" << max_packet_size
265 << ") has no room for framing overhead.";
266 CloseConnection(QUIC_INTERNAL_ERROR);
267 return;
268 }
269 if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
270 DLOG(DFATAL) << "Client hello won't fit in a single packet.";
271 CloseConnection(QUIC_INTERNAL_ERROR);
272 return;
273 }
274 out.set_minimum_size(max_packet_size - kFramingOverhead);
275 next_state_ = STATE_RECV_REJ;
276 SendHandshakeMessage(out);
277 return;
278 }
279
280 session()->config()->ToHandshakeMessage(&out);
281 string error_details;
282 QuicErrorCode error = crypto_config_->FillClientHello(
283 server_id_,
284 session()->connection()->connection_id(),
285 session()->connection()->supported_versions().front(),
286 cached,
287 session()->connection()->clock()->WallNow(),
288 session()->connection()->random_generator(),
289 channel_id_key_.get(),
290 &crypto_negotiated_params_,
291 &out,
292 &error_details);
293 if (error != QUIC_NO_ERROR) {
294 // Flush the cached config so that, if it's bad, the server has a
295 // chance to send us another in the future.
296 cached->InvalidateServerConfig();
297 CloseConnectionWithDetails(error, error_details);
298 return;
299 }
300 channel_id_sent_ = (channel_id_key_.get() != NULL);
301 if (cached->proof_verify_details()) {
302 client_session()->OnProofVerifyDetailsAvailable(
303 *cached->proof_verify_details());
304 }
305 next_state_ = STATE_RECV_SHLO;
306 SendHandshakeMessage(out);
307 // Be prepared to decrypt with the new server write key.
308 session()->connection()->SetAlternativeDecrypter(
309 crypto_negotiated_params_.initial_crypters.decrypter.release(),
310 ENCRYPTION_INITIAL,
311 true /* latch once used */);
312 // Send subsequent packets under encryption on the assumption that the
313 // server will accept the handshake.
314 session()->connection()->SetEncrypter(
315 ENCRYPTION_INITIAL,
316 crypto_negotiated_params_.initial_crypters.encrypter.release());
317 session()->connection()->SetDefaultEncryptionLevel(
318 ENCRYPTION_INITIAL);
319 if (!encryption_established_) {
320 encryption_established_ = true;
321 session()->OnCryptoHandshakeEvent(
322 QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
460 } else { 323 } else {
461 update_ignored = true; 324 session()->OnCryptoHandshakeEvent(
462 next_state_ = STATE_VERIFY_PROOF_DONE; 325 QuicSession::ENCRYPTION_REESTABLISHED);
463 } 326 }
464 UMA_HISTOGRAM_BOOLEAN("Net.QuicNumServerConfig.UpdateMessagesIgnored", 327 }
465 update_ignored); 328
329 void QuicCryptoClientStream::DoReceiveREJ(
330 const CryptoHandshakeMessage* in,
331 QuicCryptoClientConfig::CachedState* cached) {
332 // We sent a dummy CHLO because we didn't have enough information to
333 // perform a handshake, or we sent a full hello that the server
334 // rejected. Here we hope to have a REJ that contains the information
335 // that we need.
336 if (in->tag() != kREJ) {
337 next_state_ = STATE_NONE;
338 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
339 "Expected REJ");
340 return;
341 }
342 string error_details;
343 QuicErrorCode error = crypto_config_->ProcessRejection(
344 *in, session()->connection()->clock()->WallNow(), cached,
345 server_id_.is_https(), &crypto_negotiated_params_, &error_details);
346 if (error != QUIC_NO_ERROR) {
347 next_state_ = STATE_NONE;
348 CloseConnectionWithDetails(error, error_details);
349 return;
350 }
351 if (!cached->proof_valid()) {
352 if (!server_id_.is_https()) {
353 // We don't check the certificates for insecure QUIC connections.
354 SetCachedProofValid(cached);
355 } else if (!cached->signature().empty()) {
356 // Note that we only verify the proof if the cached proof is not
357 // valid. If the cached proof is valid here, someone else must have
358 // just added the server config to the cache and verified the proof,
359 // so we can assume no CA trust changes or certificate expiration
360 // has happened since then.
361 next_state_ = STATE_VERIFY_PROOF;
362 return;
363 }
364 }
365 next_state_ = STATE_GET_CHANNEL_ID;
466 } 366 }
467 367
468 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof( 368 QuicAsyncStatus QuicCryptoClientStream::DoVerifyProof(
469 QuicCryptoClientConfig::CachedState* cached) { 369 QuicCryptoClientConfig::CachedState* cached) {
470 ProofVerifier* verifier = crypto_config_->proof_verifier(); 370 ProofVerifier* verifier = crypto_config_->proof_verifier();
471 DCHECK(verifier); 371 DCHECK(verifier);
472 next_state_ = STATE_VERIFY_PROOF_COMPLETE; 372 next_state_ = STATE_VERIFY_PROOF_COMPLETE;
473 generation_counter_ = cached->generation_counter(); 373 generation_counter_ = cached->generation_counter();
474 374
475 ProofVerifierCallbackImpl* proof_verify_callback = 375 ProofVerifierCallbackImpl* proof_verify_callback =
(...skipping 20 matching lines...) Expand all
496 delete proof_verify_callback; 396 delete proof_verify_callback;
497 break; 397 break;
498 case QUIC_SUCCESS: 398 case QUIC_SUCCESS:
499 delete proof_verify_callback; 399 delete proof_verify_callback;
500 verify_ok_ = true; 400 verify_ok_ = true;
501 break; 401 break;
502 } 402 }
503 return status; 403 return status;
504 } 404 }
505 405
506 QuicErrorCode QuicCryptoClientStream::DoVerifyProofComplete( 406 void QuicCryptoClientStream::DoVerifyProofComplete(
507 QuicCryptoClientConfig::CachedState* cached) { 407 QuicCryptoClientConfig::CachedState* cached) {
508 if (!verify_ok_) { 408 if (!verify_ok_) {
409 next_state_ = STATE_NONE;
509 client_session()->OnProofVerifyDetailsAvailable(*verify_details_); 410 client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
510 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed", 411 UMA_HISTOGRAM_BOOLEAN("Net.QuicVerifyProofFailed.HandshakeConfirmed",
511 handshake_confirmed()); 412 handshake_confirmed());
512 CloseConnectionWithDetails( 413 CloseConnectionWithDetails(
513 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_); 414 QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
514 return QUIC_PROOF_INVALID; 415 return;
515 } 416 }
516 417
517 // Check if generation_counter has changed between STATE_VERIFY_PROOF and 418 // Check if generation_counter has changed between STATE_VERIFY_PROOF and
518 // STATE_VERIFY_PROOF_COMPLETE state changes. 419 // STATE_VERIFY_PROOF_COMPLETE state changes.
519 if (generation_counter_ != cached->generation_counter()) { 420 if (generation_counter_ != cached->generation_counter()) {
520 next_state_ = STATE_VERIFY_PROOF; 421 next_state_ = STATE_VERIFY_PROOF;
521 } else { 422 } else {
522 SetCachedProofValid(cached); 423 SetCachedProofValid(cached);
523 cached->SetProofVerifyDetails(verify_details_.release()); 424 cached->SetProofVerifyDetails(verify_details_.release());
524 if (!handshake_confirmed()) { 425 if (!handshake_confirmed()) {
525 next_state_ = STATE_GET_CHANNEL_ID; 426 next_state_ = STATE_GET_CHANNEL_ID;
526 } else { 427 } else {
527 next_state_ = STATE_VERIFY_PROOF_DONE; 428 next_state_ = STATE_NONE;
528 } 429 }
529 } 430 }
530 return QUIC_NO_ERROR; 431 }
432
433 QuicAsyncStatus QuicCryptoClientStream::DoGetChannelID(
434 QuicCryptoClientConfig::CachedState* cached) {
435 next_state_ = STATE_GET_CHANNEL_ID_COMPLETE;
436 channel_id_key_.reset();
437 if (!RequiresChannelID(cached)) {
438 next_state_ = STATE_SEND_CHLO;
439 return QUIC_SUCCESS;
440 }
441
442 ChannelIDSourceCallbackImpl* channel_id_source_callback =
443 new ChannelIDSourceCallbackImpl(this);
444 QuicAsyncStatus status =
445 crypto_config_->channel_id_source()->GetChannelIDKey(
446 server_id_.host(), &channel_id_key_,
447 channel_id_source_callback);
448
449 switch (status) {
450 case QUIC_PENDING:
451 channel_id_source_callback_ = channel_id_source_callback;
452 DVLOG(1) << "Looking up channel ID";
453 break;
454 case QUIC_FAILURE:
455 next_state_ = STATE_NONE;
456 delete channel_id_source_callback;
457 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
458 "Channel ID lookup failed");
459 break;
460 case QUIC_SUCCESS:
461 delete channel_id_source_callback;
462 break;
463 }
464 return status;
465 }
466
467 void QuicCryptoClientStream::DoGetChannelIDComplete() {
468 if (!channel_id_key_.get()) {
469 next_state_ = STATE_NONE;
470 CloseConnectionWithDetails(QUIC_INVALID_CHANNEL_ID_SIGNATURE,
471 "Channel ID lookup failed");
472 return;
473 }
474 next_state_ = STATE_SEND_CHLO;
475 }
476
477 void QuicCryptoClientStream::DoReceiveSHLO(
478 const CryptoHandshakeMessage* in,
479 QuicCryptoClientConfig::CachedState* cached) {
480 next_state_ = STATE_NONE;
481 // We sent a CHLO that we expected to be accepted and now we're hoping
482 // for a SHLO from the server to confirm that.
483 if (in->tag() == kREJ) {
484 // alternative_decrypter will be NULL if the original alternative
485 // decrypter latched and became the primary decrypter. That happens
486 // if we received a message encrypted with the INITIAL key.
487 if (session()->connection()->alternative_decrypter() == NULL) {
488 // The rejection was sent encrypted!
489 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
490 "encrypted REJ message");
491 return;
492 }
493 next_state_ = STATE_RECV_REJ;
494 return;
495 }
496
497 if (in->tag() != kSHLO) {
498 CloseConnectionWithDetails(QUIC_INVALID_CRYPTO_MESSAGE_TYPE,
499 "Expected SHLO or REJ");
500 return;
501 }
502
503 // alternative_decrypter will be NULL if the original alternative
504 // decrypter latched and became the primary decrypter. That happens
505 // if we received a message encrypted with the INITIAL key.
506 if (session()->connection()->alternative_decrypter() != NULL) {
507 // The server hello was sent without encryption.
508 CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
509 "unencrypted SHLO message");
510 return;
511 }
512
513 string error_details;
514 QuicErrorCode error = crypto_config_->ProcessServerHello(
515 *in, session()->connection()->connection_id(),
516 session()->connection()->server_supported_versions(),
517 cached, &crypto_negotiated_params_, &error_details);
518
519 if (error != QUIC_NO_ERROR) {
520 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
521 return;
522 }
523 error = session()->config()->ProcessPeerHello(*in, SERVER, &error_details);
524 if (error != QUIC_NO_ERROR) {
525 CloseConnectionWithDetails(error, "Server hello invalid: " + error_details);
526 return;
527 }
528 session()->OnConfigNegotiated();
529
530 CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters;
531 // TODO(agl): we don't currently latch this decrypter because the idea
532 // has been floated that the server shouldn't send packets encrypted
533 // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
534 // packet from the client.
535 session()->connection()->SetAlternativeDecrypter(
536 crypters->decrypter.release(), ENCRYPTION_FORWARD_SECURE,
537 false /* don't latch */);
538 session()->connection()->SetEncrypter(
539 ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
540 session()->connection()->SetDefaultEncryptionLevel(
541 ENCRYPTION_FORWARD_SECURE);
542
543 handshake_confirmed_ = true;
544 session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
545 session()->connection()->OnHandshakeComplete();
546 }
547
548 void QuicCryptoClientStream::DoInitializeServerConfigUpdate(
549 QuicCryptoClientConfig::CachedState* cached) {
550 bool update_ignored = false;
551 if (!server_id_.is_https()) {
552 // We don't check the certificates for insecure QUIC connections.
553 SetCachedProofValid(cached);
554 next_state_ = STATE_NONE;
555 } else if (!cached->IsEmpty() && !cached->signature().empty()) {
556 // Note that we verify the proof even if the cached proof is valid.
557 DCHECK(crypto_config_->proof_verifier());
558 next_state_ = STATE_VERIFY_PROOF;
559 } else {
560 update_ignored = true;
561 next_state_ = STATE_NONE;
562 }
563 UMA_HISTOGRAM_COUNTS("Net.QuicNumServerConfig.UpdateMessagesIgnored",
564 update_ignored);
531 } 565 }
532 566
533 void QuicCryptoClientStream::SetCachedProofValid( 567 void QuicCryptoClientStream::SetCachedProofValid(
534 QuicCryptoClientConfig::CachedState* cached) { 568 QuicCryptoClientConfig::CachedState* cached) {
535 cached->SetProofValid(); 569 cached->SetProofValid();
536 client_session()->OnProofValid(*cached); 570 client_session()->OnProofValid(*cached);
537 } 571 }
538 572
539 bool QuicCryptoClientStream::RequiresChannelID( 573 bool QuicCryptoClientStream::RequiresChannelID(
540 QuicCryptoClientConfig::CachedState* cached) { 574 QuicCryptoClientConfig::CachedState* cached) {
(...skipping 18 matching lines...) Expand all
559 } 593 }
560 } 594 }
561 return false; 595 return false;
562 } 596 }
563 597
564 QuicClientSessionBase* QuicCryptoClientStream::client_session() { 598 QuicClientSessionBase* QuicCryptoClientStream::client_session() {
565 return reinterpret_cast<QuicClientSessionBase*>(session()); 599 return reinterpret_cast<QuicClientSessionBase*>(session());
566 } 600 }
567 601
568 } // namespace net 602 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_crypto_client_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698