| 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_macros.h" | 7 #include "base/metrics/histogram_macros.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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 // Tracks the state of the QUIC server information loaded from the disk cache. | 43 // Tracks the state of the QUIC server information loaded from the disk cache. |
| 44 void RecordDiskCacheServerConfigState( | 44 void RecordDiskCacheServerConfigState( |
| 45 QuicCryptoClientConfig::CachedState::ServerConfigState state) { | 45 QuicCryptoClientConfig::CachedState::ServerConfigState state) { |
| 46 UMA_HISTOGRAM_ENUMERATION( | 46 UMA_HISTOGRAM_ENUMERATION( |
| 47 "Net.QuicServerInfo.DiskCacheState", state, | 47 "Net.QuicServerInfo.DiskCacheState", state, |
| 48 QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT); | 48 QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT); |
| 49 } | 49 } |
| 50 | 50 |
| 51 } // namespace | 51 } // namespace |
| 52 | 52 |
| 53 QuicCryptoClientConfig::QuicCryptoClientConfig() | 53 QuicCryptoClientConfig::QuicCryptoClientConfig(ProofVerifier* proof_verifier) |
| 54 : disable_ecdsa_(false) { | 54 : proof_verifier_(proof_verifier), disable_ecdsa_(false) { |
| 55 DCHECK(proof_verifier_.get()); |
| 55 SetDefaults(); | 56 SetDefaults(); |
| 56 } | 57 } |
| 57 | 58 |
| 58 QuicCryptoClientConfig::~QuicCryptoClientConfig() { | 59 QuicCryptoClientConfig::~QuicCryptoClientConfig() { |
| 59 STLDeleteValues(&cached_states_); | 60 STLDeleteValues(&cached_states_); |
| 60 } | 61 } |
| 61 | 62 |
| 62 QuicCryptoClientConfig::CachedState::CachedState() | 63 QuicCryptoClientConfig::CachedState::CachedState() |
| 63 : server_config_valid_(false), | 64 : server_config_valid_(false), |
| 64 generation_counter_(0) {} | 65 generation_counter_(0) {} |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 out->SetValue(kVER, QuicVersionToQuicTag(preferred_version)); | 402 out->SetValue(kVER, QuicVersionToQuicTag(preferred_version)); |
| 402 | 403 |
| 403 if (!user_agent_id_.empty()) { | 404 if (!user_agent_id_.empty()) { |
| 404 out->SetStringPiece(kUAID, user_agent_id_); | 405 out->SetStringPiece(kUAID, user_agent_id_); |
| 405 } | 406 } |
| 406 | 407 |
| 407 if (!cached->source_address_token().empty()) { | 408 if (!cached->source_address_token().empty()) { |
| 408 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); | 409 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); |
| 409 } | 410 } |
| 410 | 411 |
| 411 if (server_id.is_https()) { | 412 if (disable_ecdsa_) { |
| 412 if (disable_ecdsa_) { | 413 out->SetTaglist(kPDMD, kX59R, 0); |
| 413 out->SetTaglist(kPDMD, kX59R, 0); | 414 } else { |
| 414 } else { | 415 out->SetTaglist(kPDMD, kX509, 0); |
| 415 out->SetTaglist(kPDMD, kX509, 0); | |
| 416 } | |
| 417 } | 416 } |
| 418 | 417 |
| 419 if (common_cert_sets) { | 418 if (common_cert_sets) { |
| 420 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); | 419 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); |
| 421 } | 420 } |
| 422 | 421 |
| 423 const vector<string>& certs = cached->certs(); | 422 const vector<string>& certs = cached->certs(); |
| 424 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the | 423 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the |
| 425 // client config is being used for multiple connections, another connection | 424 // client config is being used for multiple connections, another connection |
| 426 // doesn't update the cached certificates and cause us to be unable to | 425 // doesn't update the cached certificates and cause us to be unable to |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 } | 532 } |
| 534 | 533 |
| 535 if (!out_params->client_key_exchange->CalculateSharedKey( | 534 if (!out_params->client_key_exchange->CalculateSharedKey( |
| 536 public_value, &out_params->initial_premaster_secret)) { | 535 public_value, &out_params->initial_premaster_secret)) { |
| 537 *error_details = "Key exchange failure"; | 536 *error_details = "Key exchange failure"; |
| 538 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 537 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 539 } | 538 } |
| 540 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); | 539 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); |
| 541 | 540 |
| 542 const vector<string>& certs = cached->certs(); | 541 const vector<string>& certs = cached->certs(); |
| 543 if (preferred_version > QUIC_VERSION_25 && proof_verifier()) { | 542 if (preferred_version > QUIC_VERSION_25) { |
| 544 if (certs.empty()) { | 543 if (certs.empty()) { |
| 545 *error_details = "No certs to calculate XLCT"; | 544 *error_details = "No certs to calculate XLCT"; |
| 546 return QUIC_CRYPTO_INTERNAL_ERROR; | 545 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 547 } | 546 } |
| 548 out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0])); | 547 out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0])); |
| 549 } | 548 } |
| 550 | 549 |
| 551 if (channel_id_key) { | 550 if (channel_id_key) { |
| 552 // In order to calculate the encryption key for the CETV block we need to | 551 // In order to calculate the encryption key for the CETV block we need to |
| 553 // serialise the client hello as it currently is (i.e. without the CETV | 552 // serialise the client hello as it currently is (i.e. without the CETV |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 // Set the following members of out_params: | 609 // Set the following members of out_params: |
| 611 // out_params->hkdf_input_suffix | 610 // out_params->hkdf_input_suffix |
| 612 // out_params->initial_crypters | 611 // out_params->initial_crypters |
| 613 out_params->hkdf_input_suffix.clear(); | 612 out_params->hkdf_input_suffix.clear(); |
| 614 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id), | 613 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id), |
| 615 sizeof(connection_id)); | 614 sizeof(connection_id)); |
| 616 const QuicData& client_hello_serialized = out->GetSerialized(); | 615 const QuicData& client_hello_serialized = out->GetSerialized(); |
| 617 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), | 616 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), |
| 618 client_hello_serialized.length()); | 617 client_hello_serialized.length()); |
| 619 out_params->hkdf_input_suffix.append(cached->server_config()); | 618 out_params->hkdf_input_suffix.append(cached->server_config()); |
| 620 if (preferred_version > QUIC_VERSION_25 && proof_verifier()) { | 619 if (preferred_version > QUIC_VERSION_25) { |
| 621 if (certs.empty()) { | 620 if (certs.empty()) { |
| 622 *error_details = "No certs found to include in KDF"; | 621 *error_details = "No certs found to include in KDF"; |
| 623 return QUIC_CRYPTO_INTERNAL_ERROR; | 622 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 624 } | 623 } |
| 625 out_params->hkdf_input_suffix.append(certs[0]); | 624 out_params->hkdf_input_suffix.append(certs[0]); |
| 626 } | 625 } |
| 627 | 626 |
| 628 string hkdf_input; | 627 string hkdf_input; |
| 629 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; | 628 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; |
| 630 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 629 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 if (has_proof && has_cert) { | 678 if (has_proof && has_cert) { |
| 680 vector<string> certs; | 679 vector<string> certs; |
| 681 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, | 680 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, |
| 682 common_cert_sets, &certs)) { | 681 common_cert_sets, &certs)) { |
| 683 *error_details = "Certificate data invalid"; | 682 *error_details = "Certificate data invalid"; |
| 684 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 683 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 685 } | 684 } |
| 686 | 685 |
| 687 cached->SetProof(certs, proof); | 686 cached->SetProof(certs, proof); |
| 688 } else { | 687 } else { |
| 689 if (proof_verifier() != nullptr) { | 688 // Secure QUIC: clear existing proof as we have been sent a new SCFG |
| 690 // Secure QUIC: clear existing proof as we have been sent a new SCFG | 689 // without matching proof/certs. |
| 691 // without matching proof/certs. | 690 cached->ClearProof(); |
| 692 cached->ClearProof(); | |
| 693 } | |
| 694 | 691 |
| 695 if (has_proof && !has_cert) { | 692 if (has_proof && !has_cert) { |
| 696 *error_details = "Certificate missing"; | 693 *error_details = "Certificate missing"; |
| 697 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 694 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 698 } | 695 } |
| 699 | 696 |
| 700 if (!has_proof && has_cert) { | 697 if (!has_proof && has_cert) { |
| 701 *error_details = "Proof missing"; | 698 *error_details = "Proof missing"; |
| 702 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 699 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 703 } | 700 } |
| 704 } | 701 } |
| 705 | 702 |
| 706 return QUIC_NO_ERROR; | 703 return QUIC_NO_ERROR; |
| 707 } | 704 } |
| 708 | 705 |
| 709 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 706 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
| 710 const CryptoHandshakeMessage& rej, | 707 const CryptoHandshakeMessage& rej, |
| 711 QuicWallTime now, | 708 QuicWallTime now, |
| 712 CachedState* cached, | 709 CachedState* cached, |
| 713 bool is_https, | |
| 714 QuicCryptoNegotiatedParameters* out_params, | 710 QuicCryptoNegotiatedParameters* out_params, |
| 715 string* error_details) { | 711 string* error_details) { |
| 716 DCHECK(error_details != nullptr); | 712 DCHECK(error_details != nullptr); |
| 717 | 713 |
| 718 if ((rej.tag() != kREJ) && (rej.tag() != kSREJ)) { | 714 if ((rej.tag() != kREJ) && (rej.tag() != kSREJ)) { |
| 719 *error_details = "Message is not REJ or SREJ"; | 715 *error_details = "Message is not REJ or SREJ"; |
| 720 return QUIC_CRYPTO_INTERNAL_ERROR; | 716 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 721 } | 717 } |
| 722 | 718 |
| 723 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, | 719 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 740 for (size_t i = 0; i < num_reject_reasons; ++i) { | 736 for (size_t i = 0; i < num_reject_reasons; ++i) { |
| 741 // HANDSHAKE_OK is 0 and don't report that as error. | 737 // HANDSHAKE_OK is 0 and don't report that as error. |
| 742 if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) { | 738 if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) { |
| 743 continue; | 739 continue; |
| 744 } | 740 } |
| 745 HandshakeFailureReason reason = | 741 HandshakeFailureReason reason = |
| 746 static_cast<HandshakeFailureReason>(reject_reasons[i]); | 742 static_cast<HandshakeFailureReason>(reject_reasons[i]); |
| 747 packed_error |= 1 << (reason - 1); | 743 packed_error |= 1 << (reason - 1); |
| 748 } | 744 } |
| 749 DVLOG(1) << "Reasons for rejection: " << packed_error; | 745 DVLOG(1) << "Reasons for rejection: " << packed_error; |
| 750 if (is_https) { | 746 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure", |
| 751 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Secure", | 747 packed_error); |
| 752 packed_error); | |
| 753 } else { | |
| 754 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicClientHelloRejectReasons.Insecure", | |
| 755 packed_error); | |
| 756 } | |
| 757 } | 748 } |
| 758 | 749 |
| 759 if (rej.tag() == kSREJ) { | 750 if (rej.tag() == kSREJ) { |
| 760 QuicConnectionId connection_id; | 751 QuicConnectionId connection_id; |
| 761 if (rej.GetUint64(kRCID, &connection_id) != QUIC_NO_ERROR) { | 752 if (rej.GetUint64(kRCID, &connection_id) != QUIC_NO_ERROR) { |
| 762 *error_details = "Missing kRCID"; | 753 *error_details = "Missing kRCID"; |
| 763 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 754 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 764 } | 755 } |
| 765 cached->add_server_designated_connection_id(connection_id); | 756 cached->add_server_designated_connection_id(connection_id); |
| 766 if (!nonce.empty()) { | 757 if (!nonce.empty()) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 } | 862 } |
| 872 | 863 |
| 873 return CacheNewServerConfig(server_config_update, now, | 864 return CacheNewServerConfig(server_config_update, now, |
| 874 out_params->cached_certs, cached, error_details); | 865 out_params->cached_certs, cached, error_details); |
| 875 } | 866 } |
| 876 | 867 |
| 877 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { | 868 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { |
| 878 return proof_verifier_.get(); | 869 return proof_verifier_.get(); |
| 879 } | 870 } |
| 880 | 871 |
| 881 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { | |
| 882 proof_verifier_.reset(verifier); | |
| 883 } | |
| 884 | |
| 885 ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const { | 872 ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const { |
| 886 return channel_id_source_.get(); | 873 return channel_id_source_.get(); |
| 887 } | 874 } |
| 888 | 875 |
| 889 void QuicCryptoClientConfig::SetChannelIDSource(ChannelIDSource* source) { | 876 void QuicCryptoClientConfig::SetChannelIDSource(ChannelIDSource* source) { |
| 890 channel_id_source_.reset(source); | 877 channel_id_source_.reset(source); |
| 891 } | 878 } |
| 892 | 879 |
| 893 void QuicCryptoClientConfig::InitializeFrom( | 880 void QuicCryptoClientConfig::InitializeFrom( |
| 894 const QuicServerId& server_id, | 881 const QuicServerId& server_id, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 if (base::EndsWith(server_id.host(), canonical_suffixes_[i], | 919 if (base::EndsWith(server_id.host(), canonical_suffixes_[i], |
| 933 base::CompareCase::INSENSITIVE_ASCII)) { | 920 base::CompareCase::INSENSITIVE_ASCII)) { |
| 934 break; | 921 break; |
| 935 } | 922 } |
| 936 } | 923 } |
| 937 if (i == canonical_suffixes_.size()) { | 924 if (i == canonical_suffixes_.size()) { |
| 938 return false; | 925 return false; |
| 939 } | 926 } |
| 940 | 927 |
| 941 QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(), | 928 QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(), |
| 942 server_id.is_https(), | |
| 943 server_id.privacy_mode()); | 929 server_id.privacy_mode()); |
| 944 if (!ContainsKey(canonical_server_map_, suffix_server_id)) { | 930 if (!ContainsKey(canonical_server_map_, suffix_server_id)) { |
| 945 // This is the first host we've seen which matches the suffix, so make it | 931 // This is the first host we've seen which matches the suffix, so make it |
| 946 // canonical. | 932 // canonical. |
| 947 canonical_server_map_[suffix_server_id] = server_id; | 933 canonical_server_map_[suffix_server_id] = server_id; |
| 948 return false; | 934 return false; |
| 949 } | 935 } |
| 950 | 936 |
| 951 const QuicServerId& canonical_server_id = | 937 const QuicServerId& canonical_server_id = |
| 952 canonical_server_map_[suffix_server_id]; | 938 canonical_server_map_[suffix_server_id]; |
| 953 CachedState* canonical_state = cached_states_[canonical_server_id]; | 939 CachedState* canonical_state = cached_states_[canonical_server_id]; |
| 954 if (!canonical_state->proof_valid()) { | 940 if (!canonical_state->proof_valid()) { |
| 955 return false; | 941 return false; |
| 956 } | 942 } |
| 957 | 943 |
| 958 // Update canonical version to point at the "most recent" entry. | 944 // Update canonical version to point at the "most recent" entry. |
| 959 canonical_server_map_[suffix_server_id] = server_id; | 945 canonical_server_map_[suffix_server_id] = server_id; |
| 960 | 946 |
| 961 server_state->InitializeFrom(*canonical_state); | 947 server_state->InitializeFrom(*canonical_state); |
| 962 return true; | 948 return true; |
| 963 } | 949 } |
| 964 | 950 |
| 965 } // namespace net | 951 } // namespace net |
| OLD | NEW |