OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/crypto/quic_crypto_client_config.h" | 5 #include "net/quic/crypto/quic_crypto_client_config.h" |
6 | 6 |
7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
8 #include "base/metrics/sparse_histogram.h" | 8 #include "base/metrics/sparse_histogram.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 return true; | 104 return true; |
105 } | 105 } |
106 | 106 |
107 bool QuicCryptoClientConfig::CachedState::IsEmpty() const { | 107 bool QuicCryptoClientConfig::CachedState::IsEmpty() const { |
108 return server_config_.empty(); | 108 return server_config_.empty(); |
109 } | 109 } |
110 | 110 |
111 const CryptoHandshakeMessage* | 111 const CryptoHandshakeMessage* |
112 QuicCryptoClientConfig::CachedState::GetServerConfig() const { | 112 QuicCryptoClientConfig::CachedState::GetServerConfig() const { |
113 if (server_config_.empty()) { | 113 if (server_config_.empty()) { |
114 return NULL; | 114 return nullptr; |
115 } | 115 } |
116 | 116 |
117 if (!scfg_.get()) { | 117 if (!scfg_.get()) { |
118 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); | 118 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); |
119 DCHECK(scfg_.get()); | 119 DCHECK(scfg_.get()); |
120 } | 120 } |
121 return scfg_.get(); | 121 return scfg_.get(); |
122 } | 122 } |
123 | 123 |
124 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( | 124 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 | 285 |
286 void QuicCryptoClientConfig::CachedState::InitializeFrom( | 286 void QuicCryptoClientConfig::CachedState::InitializeFrom( |
287 const QuicCryptoClientConfig::CachedState& other) { | 287 const QuicCryptoClientConfig::CachedState& other) { |
288 DCHECK(server_config_.empty()); | 288 DCHECK(server_config_.empty()); |
289 DCHECK(!server_config_valid_); | 289 DCHECK(!server_config_valid_); |
290 server_config_ = other.server_config_; | 290 server_config_ = other.server_config_; |
291 source_address_token_ = other.source_address_token_; | 291 source_address_token_ = other.source_address_token_; |
292 certs_ = other.certs_; | 292 certs_ = other.certs_; |
293 server_config_sig_ = other.server_config_sig_; | 293 server_config_sig_ = other.server_config_sig_; |
294 server_config_valid_ = other.server_config_valid_; | 294 server_config_valid_ = other.server_config_valid_; |
295 if (other.proof_verify_details_.get() != NULL) { | 295 if (other.proof_verify_details_.get() != nullptr) { |
296 proof_verify_details_.reset(other.proof_verify_details_->Clone()); | 296 proof_verify_details_.reset(other.proof_verify_details_->Clone()); |
297 } | 297 } |
298 ++generation_counter_; | 298 ++generation_counter_; |
299 } | 299 } |
300 | 300 |
301 void QuicCryptoClientConfig::SetDefaults() { | 301 void QuicCryptoClientConfig::SetDefaults() { |
302 // Key exchange methods. | 302 // Key exchange methods. |
303 kexs.resize(2); | 303 kexs.resize(2); |
304 kexs[0] = kC255; | 304 kexs[0] = kC255; |
305 kexs[1] = kP256; | 305 kexs[1] = kP256; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 const QuicServerId& server_id, | 391 const QuicServerId& server_id, |
392 QuicConnectionId connection_id, | 392 QuicConnectionId connection_id, |
393 const QuicVersion preferred_version, | 393 const QuicVersion preferred_version, |
394 const CachedState* cached, | 394 const CachedState* cached, |
395 QuicWallTime now, | 395 QuicWallTime now, |
396 QuicRandom* rand, | 396 QuicRandom* rand, |
397 const ChannelIDKey* channel_id_key, | 397 const ChannelIDKey* channel_id_key, |
398 QuicCryptoNegotiatedParameters* out_params, | 398 QuicCryptoNegotiatedParameters* out_params, |
399 CryptoHandshakeMessage* out, | 399 CryptoHandshakeMessage* out, |
400 string* error_details) const { | 400 string* error_details) const { |
401 DCHECK(error_details != NULL); | 401 DCHECK(error_details != nullptr); |
402 | 402 |
403 FillInchoateClientHello(server_id, preferred_version, cached, | 403 FillInchoateClientHello(server_id, preferred_version, cached, |
404 out_params, out); | 404 out_params, out); |
405 | 405 |
406 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 406 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
407 if (!scfg) { | 407 if (!scfg) { |
408 // This should never happen as our caller should have checked | 408 // This should never happen as our caller should have checked |
409 // cached->IsComplete() before calling this function. | 409 // cached->IsComplete() before calling this function. |
410 *error_details = "Handshake not ready"; | 410 *error_details = "Handshake not ready"; |
411 return QUIC_CRYPTO_INTERNAL_ERROR; | 411 return QUIC_CRYPTO_INTERNAL_ERROR; |
(...skipping 18 matching lines...) Expand all Loading... |
430 } | 430 } |
431 | 431 |
432 // AEAD: the work loads on the client and server are symmetric. Since the | 432 // AEAD: the work loads on the client and server are symmetric. Since the |
433 // client is more likely to be CPU-constrained, break the tie by favoring | 433 // client is more likely to be CPU-constrained, break the tie by favoring |
434 // the client's preference. | 434 // the client's preference. |
435 // Key exchange: the client does more work than the server, so favor the | 435 // Key exchange: the client does more work than the server, so favor the |
436 // client's preference. | 436 // client's preference. |
437 size_t key_exchange_index; | 437 size_t key_exchange_index; |
438 if (!QuicUtils::FindMutualTag( | 438 if (!QuicUtils::FindMutualTag( |
439 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY, | 439 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY, |
440 &out_params->aead, NULL) || | 440 &out_params->aead, nullptr) || |
441 !QuicUtils::FindMutualTag( | 441 !QuicUtils::FindMutualTag( |
442 kexs, their_key_exchanges, num_their_key_exchanges, | 442 kexs, their_key_exchanges, num_their_key_exchanges, |
443 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange, | 443 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange, |
444 &key_exchange_index)) { | 444 &key_exchange_index)) { |
445 *error_details = "Unsupported AEAD or KEXS"; | 445 *error_details = "Unsupported AEAD or KEXS"; |
446 return QUIC_CRYPTO_NO_SUPPORT; | 446 return QUIC_CRYPTO_NO_SUPPORT; |
447 } | 447 } |
448 out->SetTaglist(kAEAD, out_params->aead, 0); | 448 out->SetTaglist(kAEAD, out_params->aead, 0); |
449 out->SetTaglist(kKEXS, out_params->key_exchange, 0); | 449 out->SetTaglist(kKEXS, out_params->key_exchange, 0); |
450 | 450 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 } | 517 } |
518 | 518 |
519 cetv.SetStringPiece(kCIDK, key); | 519 cetv.SetStringPiece(kCIDK, key); |
520 cetv.SetStringPiece(kCIDS, signature); | 520 cetv.SetStringPiece(kCIDS, signature); |
521 | 521 |
522 CrypterPair crypters; | 522 CrypterPair crypters; |
523 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, | 523 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
524 out_params->aead, out_params->client_nonce, | 524 out_params->aead, out_params->client_nonce, |
525 out_params->server_nonce, hkdf_input, | 525 out_params->server_nonce, hkdf_input, |
526 CryptoUtils::CLIENT, &crypters, | 526 CryptoUtils::CLIENT, &crypters, |
527 NULL /* subkey secret */)) { | 527 nullptr /* subkey secret */)) { |
528 *error_details = "Symmetric key setup failed"; | 528 *error_details = "Symmetric key setup failed"; |
529 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 529 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
530 } | 530 } |
531 | 531 |
532 const QuicData& cetv_plaintext = cetv.GetSerialized(); | 532 const QuicData& cetv_plaintext = cetv.GetSerialized(); |
533 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( | 533 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( |
534 0 /* sequence number */, | 534 0 /* sequence number */, |
535 StringPiece() /* associated data */, | 535 StringPiece() /* associated data */, |
536 cetv_plaintext.AsStringPiece())); | 536 cetv_plaintext.AsStringPiece())); |
537 if (!cetv_ciphertext.get()) { | 537 if (!cetv_ciphertext.get()) { |
(...skipping 22 matching lines...) Expand all Loading... |
560 string hkdf_input; | 560 string hkdf_input; |
561 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; | 561 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; |
562 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 562 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
563 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); | 563 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); |
564 hkdf_input.append(out_params->hkdf_input_suffix); | 564 hkdf_input.append(out_params->hkdf_input_suffix); |
565 | 565 |
566 if (!CryptoUtils::DeriveKeys( | 566 if (!CryptoUtils::DeriveKeys( |
567 out_params->initial_premaster_secret, out_params->aead, | 567 out_params->initial_premaster_secret, out_params->aead, |
568 out_params->client_nonce, out_params->server_nonce, hkdf_input, | 568 out_params->client_nonce, out_params->server_nonce, hkdf_input, |
569 CryptoUtils::CLIENT, &out_params->initial_crypters, | 569 CryptoUtils::CLIENT, &out_params->initial_crypters, |
570 NULL /* subkey secret */)) { | 570 nullptr /* subkey secret */)) { |
571 *error_details = "Symmetric key setup failed"; | 571 *error_details = "Symmetric key setup failed"; |
572 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 572 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
573 } | 573 } |
574 | 574 |
575 return QUIC_NO_ERROR; | 575 return QUIC_NO_ERROR; |
576 } | 576 } |
577 | 577 |
578 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( | 578 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( |
579 const CryptoHandshakeMessage& message, | 579 const CryptoHandshakeMessage& message, |
580 QuicWallTime now, | 580 QuicWallTime now, |
581 const vector<string>& cached_certs, | 581 const vector<string>& cached_certs, |
582 CachedState* cached, | 582 CachedState* cached, |
583 string* error_details) { | 583 string* error_details) { |
584 DCHECK(error_details != NULL); | 584 DCHECK(error_details != nullptr); |
585 | 585 |
586 StringPiece scfg; | 586 StringPiece scfg; |
587 if (!message.GetStringPiece(kSCFG, &scfg)) { | 587 if (!message.GetStringPiece(kSCFG, &scfg)) { |
588 *error_details = "Missing SCFG"; | 588 *error_details = "Missing SCFG"; |
589 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 589 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
590 } | 590 } |
591 | 591 |
592 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); | 592 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); |
593 if (error != QUIC_NO_ERROR) { | 593 if (error != QUIC_NO_ERROR) { |
594 return error; | 594 return error; |
(...skipping 10 matching lines...) Expand all Loading... |
605 if (has_proof && has_cert) { | 605 if (has_proof && has_cert) { |
606 vector<string> certs; | 606 vector<string> certs; |
607 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, | 607 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, |
608 common_cert_sets, &certs)) { | 608 common_cert_sets, &certs)) { |
609 *error_details = "Certificate data invalid"; | 609 *error_details = "Certificate data invalid"; |
610 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 610 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
611 } | 611 } |
612 | 612 |
613 cached->SetProof(certs, proof); | 613 cached->SetProof(certs, proof); |
614 } else { | 614 } else { |
615 if (proof_verifier() != NULL) { | 615 if (proof_verifier() != nullptr) { |
616 // Secure QUIC: clear existing proof as we have been sent a new SCFG | 616 // Secure QUIC: clear existing proof as we have been sent a new SCFG |
617 // without matching proof/certs. | 617 // without matching proof/certs. |
618 cached->ClearProof(); | 618 cached->ClearProof(); |
619 } | 619 } |
620 | 620 |
621 if (has_proof && !has_cert) { | 621 if (has_proof && !has_cert) { |
622 *error_details = "Certificate missing"; | 622 *error_details = "Certificate missing"; |
623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
624 } | 624 } |
625 | 625 |
626 if (!has_proof && has_cert) { | 626 if (!has_proof && has_cert) { |
627 *error_details = "Proof missing"; | 627 *error_details = "Proof missing"; |
628 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 628 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
629 } | 629 } |
630 } | 630 } |
631 | 631 |
632 return QUIC_NO_ERROR; | 632 return QUIC_NO_ERROR; |
633 } | 633 } |
634 | 634 |
635 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 635 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
636 const CryptoHandshakeMessage& rej, | 636 const CryptoHandshakeMessage& rej, |
637 QuicWallTime now, | 637 QuicWallTime now, |
638 CachedState* cached, | 638 CachedState* cached, |
639 bool is_https, | 639 bool is_https, |
640 QuicCryptoNegotiatedParameters* out_params, | 640 QuicCryptoNegotiatedParameters* out_params, |
641 string* error_details) { | 641 string* error_details) { |
642 DCHECK(error_details != NULL); | 642 DCHECK(error_details != nullptr); |
643 | 643 |
644 if (rej.tag() != kREJ) { | 644 if (rej.tag() != kREJ) { |
645 *error_details = "Message is not REJ"; | 645 *error_details = "Message is not REJ"; |
646 return QUIC_CRYPTO_INTERNAL_ERROR; | 646 return QUIC_CRYPTO_INTERNAL_ERROR; |
647 } | 647 } |
648 | 648 |
649 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, | 649 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, |
650 cached, error_details); | 650 cached, error_details); |
651 if (error != QUIC_NO_ERROR) { | 651 if (error != QUIC_NO_ERROR) { |
652 return error; | 652 return error; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 return QUIC_NO_ERROR; | 685 return QUIC_NO_ERROR; |
686 } | 686 } |
687 | 687 |
688 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( | 688 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( |
689 const CryptoHandshakeMessage& server_hello, | 689 const CryptoHandshakeMessage& server_hello, |
690 QuicConnectionId connection_id, | 690 QuicConnectionId connection_id, |
691 const QuicVersionVector& negotiated_versions, | 691 const QuicVersionVector& negotiated_versions, |
692 CachedState* cached, | 692 CachedState* cached, |
693 QuicCryptoNegotiatedParameters* out_params, | 693 QuicCryptoNegotiatedParameters* out_params, |
694 string* error_details) { | 694 string* error_details) { |
695 DCHECK(error_details != NULL); | 695 DCHECK(error_details != nullptr); |
696 | 696 |
697 if (server_hello.tag() != kSHLO) { | 697 if (server_hello.tag() != kSHLO) { |
698 *error_details = "Bad tag"; | 698 *error_details = "Bad tag"; |
699 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; | 699 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; |
700 } | 700 } |
701 | 701 |
702 const QuicTag* supported_version_tags; | 702 const QuicTag* supported_version_tags; |
703 size_t num_supported_versions; | 703 size_t num_supported_versions; |
704 | 704 |
705 if (server_hello.GetTaglist(kVER, &supported_version_tags, | 705 if (server_hello.GetTaglist(kVER, &supported_version_tags, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 | 760 |
761 return QUIC_NO_ERROR; | 761 return QUIC_NO_ERROR; |
762 } | 762 } |
763 | 763 |
764 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate( | 764 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate( |
765 const CryptoHandshakeMessage& server_config_update, | 765 const CryptoHandshakeMessage& server_config_update, |
766 QuicWallTime now, | 766 QuicWallTime now, |
767 CachedState* cached, | 767 CachedState* cached, |
768 QuicCryptoNegotiatedParameters* out_params, | 768 QuicCryptoNegotiatedParameters* out_params, |
769 string* error_details) { | 769 string* error_details) { |
770 DCHECK(error_details != NULL); | 770 DCHECK(error_details != nullptr); |
771 | 771 |
772 if (server_config_update.tag() != kSCUP) { | 772 if (server_config_update.tag() != kSCUP) { |
773 *error_details = "ServerConfigUpdate must have kSCUP tag."; | 773 *error_details = "ServerConfigUpdate must have kSCUP tag."; |
774 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; | 774 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; |
775 } | 775 } |
776 | 776 |
777 return CacheNewServerConfig(server_config_update, now, | 777 return CacheNewServerConfig(server_config_update, now, |
778 out_params->cached_certs, cached, error_details); | 778 out_params->cached_certs, cached, error_details); |
779 } | 779 } |
780 | 780 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 return; | 857 return; |
858 } | 858 } |
859 | 859 |
860 // Update canonical version to point at the "most recent" entry. | 860 // Update canonical version to point at the "most recent" entry. |
861 canonical_server_map_[suffix_server_id] = server_id; | 861 canonical_server_map_[suffix_server_id] = server_id; |
862 | 862 |
863 server_state->InitializeFrom(*canonical_state); | 863 server_state->InitializeFrom(*canonical_state); |
864 } | 864 } |
865 | 865 |
866 } // namespace net | 866 } // namespace net |
OLD | NEW |