| 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/core/crypto/quic_crypto_client_config.h" | 5 #include "net/quic/core/crypto/quic_crypto_client_config.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 13 #include "net/quic/core/crypto/cert_compressor.h" | 13 #include "net/quic/core/crypto/cert_compressor.h" |
| 14 #include "net/quic/core/crypto/chacha20_poly1305_encrypter.h" | 14 #include "net/quic/core/crypto/chacha20_poly1305_encrypter.h" |
| 15 #include "net/quic/core/crypto/channel_id.h" | 15 #include "net/quic/core/crypto/channel_id.h" |
| 16 #include "net/quic/core/crypto/common_cert_set.h" | 16 #include "net/quic/core/crypto/common_cert_set.h" |
| 17 #include "net/quic/core/crypto/crypto_framer.h" | 17 #include "net/quic/core/crypto/crypto_framer.h" |
| 18 #include "net/quic/core/crypto/crypto_utils.h" | 18 #include "net/quic/core/crypto/crypto_utils.h" |
| 19 #include "net/quic/core/crypto/curve25519_key_exchange.h" | 19 #include "net/quic/core/crypto/curve25519_key_exchange.h" |
| 20 #include "net/quic/core/crypto/key_exchange.h" | 20 #include "net/quic/core/crypto/key_exchange.h" |
| 21 #include "net/quic/core/crypto/p256_key_exchange.h" | 21 #include "net/quic/core/crypto/p256_key_exchange.h" |
| 22 #include "net/quic/core/crypto/proof_verifier.h" | 22 #include "net/quic/core/crypto/proof_verifier.h" |
| 23 #include "net/quic/core/crypto/quic_encrypter.h" | 23 #include "net/quic/core/crypto/quic_encrypter.h" |
| 24 #include "net/quic/core/crypto/quic_random.h" | 24 #include "net/quic/core/crypto/quic_random.h" |
| 25 #include "net/quic/core/quic_bug_tracker.h" | 25 #include "net/quic/core/quic_bug_tracker.h" |
| 26 #include "net/quic/core/quic_flags.h" | 26 #include "net/quic/core/quic_flags.h" |
| 27 #include "net/quic/core/quic_utils.h" | 27 #include "net/quic/core/quic_utils.h" |
| 28 | 28 |
| 29 using base::StringPiece; | 29 using base::StringPiece; |
| 30 using std::map; | |
| 31 using std::string; | 30 using std::string; |
| 32 using std::queue; | |
| 33 using std::vector; | |
| 34 | 31 |
| 35 namespace net { | 32 namespace net { |
| 36 | 33 |
| 37 namespace { | 34 namespace { |
| 38 | 35 |
| 39 // Tracks the reason (the state of the server config) for sending inchoate | 36 // Tracks the reason (the state of the server config) for sending inchoate |
| 40 // ClientHello to the server. | 37 // ClientHello to the server. |
| 41 void RecordInchoateClientHelloReason( | 38 void RecordInchoateClientHelloReason( |
| 42 QuicCryptoClientConfig::CachedState::ServerConfigState state) { | 39 QuicCryptoClientConfig::CachedState::ServerConfigState state) { |
| 43 UMA_HISTOGRAM_ENUMERATION( | 40 UMA_HISTOGRAM_ENUMERATION( |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 SetProofInvalid(); | 182 SetProofInvalid(); |
| 186 scfg_.reset(new_scfg_storage.release()); | 183 scfg_.reset(new_scfg_storage.release()); |
| 187 } | 184 } |
| 188 return SERVER_CONFIG_VALID; | 185 return SERVER_CONFIG_VALID; |
| 189 } | 186 } |
| 190 | 187 |
| 191 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { | 188 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { |
| 192 server_config_.clear(); | 189 server_config_.clear(); |
| 193 scfg_.reset(); | 190 scfg_.reset(); |
| 194 SetProofInvalid(); | 191 SetProofInvalid(); |
| 195 queue<QuicConnectionId> empty_queue; | 192 std::queue<QuicConnectionId> empty_queue; |
| 196 swap(server_designated_connection_ids_, empty_queue); | 193 swap(server_designated_connection_ids_, empty_queue); |
| 197 } | 194 } |
| 198 | 195 |
| 199 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs, | 196 void QuicCryptoClientConfig::CachedState::SetProof( |
| 200 StringPiece cert_sct, | 197 const std::vector<string>& certs, |
| 201 StringPiece chlo_hash, | 198 StringPiece cert_sct, |
| 202 StringPiece signature) { | 199 StringPiece chlo_hash, |
| 200 StringPiece signature) { |
| 203 bool has_changed = signature != server_config_sig_ || | 201 bool has_changed = signature != server_config_sig_ || |
| 204 chlo_hash != chlo_hash_ || certs_.size() != certs.size(); | 202 chlo_hash != chlo_hash_ || certs_.size() != certs.size(); |
| 205 | 203 |
| 206 if (!has_changed) { | 204 if (!has_changed) { |
| 207 for (size_t i = 0; i < certs_.size(); i++) { | 205 for (size_t i = 0; i < certs_.size(); i++) { |
| 208 if (certs_[i] != certs[i]) { | 206 if (certs_[i] != certs[i]) { |
| 209 has_changed = true; | 207 has_changed = true; |
| 210 break; | 208 break; |
| 211 } | 209 } |
| 212 } | 210 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 228 server_config_.clear(); | 226 server_config_.clear(); |
| 229 source_address_token_.clear(); | 227 source_address_token_.clear(); |
| 230 certs_.clear(); | 228 certs_.clear(); |
| 231 cert_sct_.clear(); | 229 cert_sct_.clear(); |
| 232 chlo_hash_.clear(); | 230 chlo_hash_.clear(); |
| 233 server_config_sig_.clear(); | 231 server_config_sig_.clear(); |
| 234 server_config_valid_ = false; | 232 server_config_valid_ = false; |
| 235 proof_verify_details_.reset(); | 233 proof_verify_details_.reset(); |
| 236 scfg_.reset(); | 234 scfg_.reset(); |
| 237 ++generation_counter_; | 235 ++generation_counter_; |
| 238 queue<QuicConnectionId> empty_queue; | 236 std::queue<QuicConnectionId> empty_queue; |
| 239 swap(server_designated_connection_ids_, empty_queue); | 237 swap(server_designated_connection_ids_, empty_queue); |
| 240 } | 238 } |
| 241 | 239 |
| 242 void QuicCryptoClientConfig::CachedState::ClearProof() { | 240 void QuicCryptoClientConfig::CachedState::ClearProof() { |
| 243 SetProofInvalid(); | 241 SetProofInvalid(); |
| 244 certs_.clear(); | 242 certs_.clear(); |
| 245 cert_sct_.clear(); | 243 cert_sct_.clear(); |
| 246 chlo_hash_.clear(); | 244 chlo_hash_.clear(); |
| 247 server_config_sig_.clear(); | 245 server_config_sig_.clear(); |
| 248 } | 246 } |
| 249 | 247 |
| 250 void QuicCryptoClientConfig::CachedState::SetProofValid() { | 248 void QuicCryptoClientConfig::CachedState::SetProofValid() { |
| 251 server_config_valid_ = true; | 249 server_config_valid_ = true; |
| 252 } | 250 } |
| 253 | 251 |
| 254 void QuicCryptoClientConfig::CachedState::SetProofInvalid() { | 252 void QuicCryptoClientConfig::CachedState::SetProofInvalid() { |
| 255 server_config_valid_ = false; | 253 server_config_valid_ = false; |
| 256 ++generation_counter_; | 254 ++generation_counter_; |
| 257 } | 255 } |
| 258 | 256 |
| 259 bool QuicCryptoClientConfig::CachedState::Initialize( | 257 bool QuicCryptoClientConfig::CachedState::Initialize( |
| 260 StringPiece server_config, | 258 StringPiece server_config, |
| 261 StringPiece source_address_token, | 259 StringPiece source_address_token, |
| 262 const vector<string>& certs, | 260 const std::vector<string>& certs, |
| 263 StringPiece cert_sct, | 261 const string& cert_sct, |
| 264 StringPiece chlo_hash, | 262 StringPiece chlo_hash, |
| 265 StringPiece signature, | 263 StringPiece signature, |
| 266 QuicWallTime now, | 264 QuicWallTime now, |
| 267 QuicWallTime expiration_time) { | 265 QuicWallTime expiration_time) { |
| 268 DCHECK(server_config_.empty()); | 266 DCHECK(server_config_.empty()); |
| 269 | 267 |
| 270 if (server_config.empty()) { | 268 if (server_config.empty()) { |
| 271 RecordDiskCacheServerConfigState(SERVER_CONFIG_EMPTY); | 269 RecordDiskCacheServerConfigState(SERVER_CONFIG_EMPTY); |
| 272 return false; | 270 return false; |
| 273 } | 271 } |
| 274 | 272 |
| 275 string error_details; | 273 string error_details; |
| 276 ServerConfigState state = | 274 ServerConfigState state = |
| 277 SetServerConfig(server_config, now, expiration_time, &error_details); | 275 SetServerConfig(server_config, now, expiration_time, &error_details); |
| 278 RecordDiskCacheServerConfigState(state); | 276 RecordDiskCacheServerConfigState(state); |
| 279 if (state != SERVER_CONFIG_VALID) { | 277 if (state != SERVER_CONFIG_VALID) { |
| 280 DVLOG(1) << "SetServerConfig failed with " << error_details; | 278 DVLOG(1) << "SetServerConfig failed with " << error_details; |
| 281 return false; | 279 return false; |
| 282 } | 280 } |
| 283 | 281 |
| 282 chlo_hash.CopyToString(&chlo_hash_); |
| 284 signature.CopyToString(&server_config_sig_); | 283 signature.CopyToString(&server_config_sig_); |
| 285 source_address_token.CopyToString(&source_address_token_); | 284 source_address_token.CopyToString(&source_address_token_); |
| 286 cert_sct.CopyToString(&cert_sct_); | |
| 287 chlo_hash.CopyToString(&chlo_hash_); | |
| 288 certs_ = certs; | 285 certs_ = certs; |
| 286 cert_sct_ = cert_sct; |
| 289 return true; | 287 return true; |
| 290 } | 288 } |
| 291 | 289 |
| 292 const string& QuicCryptoClientConfig::CachedState::server_config() const { | 290 const string& QuicCryptoClientConfig::CachedState::server_config() const { |
| 293 return server_config_; | 291 return server_config_; |
| 294 } | 292 } |
| 295 | 293 |
| 296 const string& QuicCryptoClientConfig::CachedState::source_address_token() | 294 const string& QuicCryptoClientConfig::CachedState::source_address_token() |
| 297 const { | 295 const { |
| 298 return source_address_token_; | 296 return source_address_token_; |
| 299 } | 297 } |
| 300 | 298 |
| 301 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { | 299 const std::vector<string>& QuicCryptoClientConfig::CachedState::certs() const { |
| 302 return certs_; | 300 return certs_; |
| 303 } | 301 } |
| 304 | 302 |
| 305 const string& QuicCryptoClientConfig::CachedState::cert_sct() const { | 303 const string& QuicCryptoClientConfig::CachedState::cert_sct() const { |
| 306 return cert_sct_; | 304 return cert_sct_; |
| 307 } | 305 } |
| 308 | 306 |
| 309 const string& QuicCryptoClientConfig::CachedState::chlo_hash() const { | 307 const string& QuicCryptoClientConfig::CachedState::chlo_hash() const { |
| 310 return chlo_hash_; | 308 return chlo_hash_; |
| 311 } | 309 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 out->SetStringPiece(kNONP, StringPiece(proof_nonce, arraysize(proof_nonce))); | 459 out->SetStringPiece(kNONP, StringPiece(proof_nonce, arraysize(proof_nonce))); |
| 462 | 460 |
| 463 out->SetVector(kPDMD, QuicTagVector{kX509}); | 461 out->SetVector(kPDMD, QuicTagVector{kX509}); |
| 464 | 462 |
| 465 if (common_cert_sets) { | 463 if (common_cert_sets) { |
| 466 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); | 464 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); |
| 467 } | 465 } |
| 468 | 466 |
| 469 out->SetStringPiece(kCertificateSCTTag, ""); | 467 out->SetStringPiece(kCertificateSCTTag, ""); |
| 470 | 468 |
| 471 const vector<string>& certs = cached->certs(); | 469 const std::vector<string>& certs = cached->certs(); |
| 472 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the | 470 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the |
| 473 // client config is being used for multiple connections, another connection | 471 // client config is being used for multiple connections, another connection |
| 474 // doesn't update the cached certificates and cause us to be unable to | 472 // doesn't update the cached certificates and cause us to be unable to |
| 475 // process the server's compressed certificate chain. | 473 // process the server's compressed certificate chain. |
| 476 out_params->cached_certs = certs; | 474 out_params->cached_certs = certs; |
| 477 if (!certs.empty()) { | 475 if (!certs.empty()) { |
| 478 vector<uint64_t> hashes; | 476 std::vector<uint64_t> hashes; |
| 479 hashes.reserve(certs.size()); | 477 hashes.reserve(certs.size()); |
| 480 for (vector<string>::const_iterator i = certs.begin(); i != certs.end(); | 478 for (std::vector<string>::const_iterator i = certs.begin(); |
| 481 ++i) { | 479 i != certs.end(); ++i) { |
| 482 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); | 480 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); |
| 483 } | 481 } |
| 484 out->SetVector(kCCRT, hashes); | 482 out->SetVector(kCCRT, hashes); |
| 485 } | 483 } |
| 486 } | 484 } |
| 487 | 485 |
| 488 QuicErrorCode QuicCryptoClientConfig::FillClientHello( | 486 QuicErrorCode QuicCryptoClientConfig::FillClientHello( |
| 489 const QuicServerId& server_id, | 487 const QuicServerId& server_id, |
| 490 QuicConnectionId connection_id, | 488 QuicConnectionId connection_id, |
| 491 const QuicVersion actual_version, | 489 const QuicVersion actual_version, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 return QUIC_CRYPTO_INTERNAL_ERROR; | 603 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 606 } | 604 } |
| 607 | 605 |
| 608 if (!out_params->client_key_exchange->CalculateSharedKey( | 606 if (!out_params->client_key_exchange->CalculateSharedKey( |
| 609 public_value, &out_params->initial_premaster_secret)) { | 607 public_value, &out_params->initial_premaster_secret)) { |
| 610 *error_details = "Key exchange failure"; | 608 *error_details = "Key exchange failure"; |
| 611 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 609 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 612 } | 610 } |
| 613 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); | 611 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); |
| 614 | 612 |
| 615 const vector<string>& certs = cached->certs(); | 613 const std::vector<string>& certs = cached->certs(); |
| 616 if (certs.empty()) { | 614 if (certs.empty()) { |
| 617 *error_details = "No certs to calculate XLCT"; | 615 *error_details = "No certs to calculate XLCT"; |
| 618 return QUIC_CRYPTO_INTERNAL_ERROR; | 616 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 619 } | 617 } |
| 620 out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0])); | 618 out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0])); |
| 621 | 619 |
| 622 if (channel_id_key) { | 620 if (channel_id_key) { |
| 623 // In order to calculate the encryption key for the CETV block we need to | 621 // In order to calculate the encryption key for the CETV block we need to |
| 624 // serialise the client hello as it currently is (i.e. without the CETV | 622 // serialise the client hello as it currently is (i.e. without the CETV |
| 625 // block). For this, the client hello is serialized without padding. | 623 // block). For this, the client hello is serialized without padding. |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 } | 717 } |
| 720 | 718 |
| 721 return QUIC_NO_ERROR; | 719 return QUIC_NO_ERROR; |
| 722 } | 720 } |
| 723 | 721 |
| 724 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( | 722 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( |
| 725 const CryptoHandshakeMessage& message, | 723 const CryptoHandshakeMessage& message, |
| 726 QuicWallTime now, | 724 QuicWallTime now, |
| 727 QuicVersion version, | 725 QuicVersion version, |
| 728 StringPiece chlo_hash, | 726 StringPiece chlo_hash, |
| 729 const vector<string>& cached_certs, | 727 const std::vector<string>& cached_certs, |
| 730 CachedState* cached, | 728 CachedState* cached, |
| 731 string* error_details) { | 729 string* error_details) { |
| 732 DCHECK(error_details != nullptr); | 730 DCHECK(error_details != nullptr); |
| 733 | 731 |
| 734 StringPiece scfg; | 732 StringPiece scfg; |
| 735 if (!message.GetStringPiece(kSCFG, &scfg)) { | 733 if (!message.GetStringPiece(kSCFG, &scfg)) { |
| 736 *error_details = "Missing SCFG"; | 734 *error_details = "Missing SCFG"; |
| 737 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 735 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 738 } | 736 } |
| 739 | 737 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 756 | 754 |
| 757 StringPiece token; | 755 StringPiece token; |
| 758 if (message.GetStringPiece(kSourceAddressTokenTag, &token)) { | 756 if (message.GetStringPiece(kSourceAddressTokenTag, &token)) { |
| 759 cached->set_source_address_token(token); | 757 cached->set_source_address_token(token); |
| 760 } | 758 } |
| 761 | 759 |
| 762 StringPiece proof, cert_bytes, cert_sct; | 760 StringPiece proof, cert_bytes, cert_sct; |
| 763 bool has_proof = message.GetStringPiece(kPROF, &proof); | 761 bool has_proof = message.GetStringPiece(kPROF, &proof); |
| 764 bool has_cert = message.GetStringPiece(kCertificateTag, &cert_bytes); | 762 bool has_cert = message.GetStringPiece(kCertificateTag, &cert_bytes); |
| 765 if (has_proof && has_cert) { | 763 if (has_proof && has_cert) { |
| 766 vector<string> certs; | 764 std::vector<string> certs; |
| 767 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, | 765 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, |
| 768 common_cert_sets, &certs)) { | 766 common_cert_sets, &certs)) { |
| 769 *error_details = "Certificate data invalid"; | 767 *error_details = "Certificate data invalid"; |
| 770 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 768 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 771 } | 769 } |
| 772 | 770 |
| 773 message.GetStringPiece(kCertificateSCTTag, &cert_sct); | 771 message.GetStringPiece(kCertificateSCTTag, &cert_sct); |
| 774 cached->SetProof(certs, cert_sct, chlo_hash, proof); | 772 cached->SetProof(certs, cert_sct, chlo_hash, proof); |
| 775 } else { | 773 } else { |
| 776 // Secure QUIC: clear existing proof as we have been sent a new SCFG | 774 // Secure QUIC: clear existing proof as we have been sent a new SCFG |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 } | 986 } |
| 989 | 987 |
| 990 // Update canonical version to point at the "most recent" entry. | 988 // Update canonical version to point at the "most recent" entry. |
| 991 canonical_server_map_[suffix_server_id] = server_id; | 989 canonical_server_map_[suffix_server_id] = server_id; |
| 992 | 990 |
| 993 server_state->InitializeFrom(*canonical_state); | 991 server_state->InitializeFrom(*canonical_state); |
| 994 return true; | 992 return true; |
| 995 } | 993 } |
| 996 | 994 |
| 997 } // namespace net | 995 } // namespace net |
| OLD | NEW |