| 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_server_config.h" | 5 #include "net/quic/crypto/quic_crypto_server_config.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 | 9 |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 delete this; | 208 delete this; |
| 209 } | 209 } |
| 210 | 210 |
| 211 QuicCryptoServerConfig::ConfigOptions::ConfigOptions() | 211 QuicCryptoServerConfig::ConfigOptions::ConfigOptions() |
| 212 : expiry_time(QuicWallTime::Zero()), | 212 : expiry_time(QuicWallTime::Zero()), |
| 213 channel_id_enabled(false), | 213 channel_id_enabled(false), |
| 214 p256(false) {} | 214 p256(false) {} |
| 215 | 215 |
| 216 QuicCryptoServerConfig::QuicCryptoServerConfig( | 216 QuicCryptoServerConfig::QuicCryptoServerConfig( |
| 217 StringPiece source_address_token_secret, | 217 StringPiece source_address_token_secret, |
| 218 QuicRandom* rand) | 218 QuicRandom* server_nonce_entropy, |
| 219 ProofSource* proof_source) |
| 219 : replay_protection_(true), | 220 : replay_protection_(true), |
| 220 configs_lock_(), | 221 configs_lock_(), |
| 221 primary_config_(nullptr), | 222 primary_config_(nullptr), |
| 222 next_config_promotion_time_(QuicWallTime::Zero()), | 223 next_config_promotion_time_(QuicWallTime::Zero()), |
| 223 server_nonce_strike_register_lock_(), | 224 server_nonce_strike_register_lock_(), |
| 225 proof_source_(proof_source), |
| 224 strike_register_no_startup_period_(false), | 226 strike_register_no_startup_period_(false), |
| 225 strike_register_max_entries_(1 << 10), | 227 strike_register_max_entries_(1 << 10), |
| 226 strike_register_window_secs_(600), | 228 strike_register_window_secs_(600), |
| 227 source_address_token_future_secs_(3600), | 229 source_address_token_future_secs_(3600), |
| 228 source_address_token_lifetime_secs_(86400), | 230 source_address_token_lifetime_secs_(86400), |
| 229 server_nonce_strike_register_max_entries_(1 << 10), | 231 server_nonce_strike_register_max_entries_(1 << 10), |
| 230 server_nonce_strike_register_window_secs_(120) { | 232 server_nonce_strike_register_window_secs_(120) { |
| 233 DCHECK(proof_source_.get()); |
| 231 default_source_address_token_boxer_.SetKey( | 234 default_source_address_token_boxer_.SetKey( |
| 232 DeriveSourceAddressTokenKey(source_address_token_secret)); | 235 DeriveSourceAddressTokenKey(source_address_token_secret)); |
| 233 | 236 |
| 234 // Generate a random key and orbit for server nonces. | 237 // Generate a random key and orbit for server nonces. |
| 235 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_)); | 238 server_nonce_entropy->RandBytes(server_nonce_orbit_, |
| 239 sizeof(server_nonce_orbit_)); |
| 236 const size_t key_size = server_nonce_boxer_.GetKeySize(); | 240 const size_t key_size = server_nonce_boxer_.GetKeySize(); |
| 237 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); | 241 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); |
| 238 rand->RandBytes(key_bytes.get(), key_size); | 242 server_nonce_entropy->RandBytes(key_bytes.get(), key_size); |
| 239 | 243 |
| 240 server_nonce_boxer_.SetKey( | 244 server_nonce_boxer_.SetKey( |
| 241 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size)); | 245 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size)); |
| 242 } | 246 } |
| 243 | 247 |
| 244 QuicCryptoServerConfig::~QuicCryptoServerConfig() { | 248 QuicCryptoServerConfig::~QuicCryptoServerConfig() { |
| 245 primary_config_ = nullptr; | 249 primary_config_ = nullptr; |
| 246 } | 250 } |
| 247 | 251 |
| 248 // static | 252 // static |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 if (validate_chlo_result.error_code != QUIC_NO_ERROR) { | 606 if (validate_chlo_result.error_code != QUIC_NO_ERROR) { |
| 603 *error_details = validate_chlo_result.error_details; | 607 *error_details = validate_chlo_result.error_details; |
| 604 return validate_chlo_result.error_code; | 608 return validate_chlo_result.error_code; |
| 605 } | 609 } |
| 606 | 610 |
| 607 out->Clear(); | 611 out->Clear(); |
| 608 | 612 |
| 609 bool x509_supported = false; | 613 bool x509_supported = false; |
| 610 bool x509_ecdsa_supported = false; | 614 bool x509_ecdsa_supported = false; |
| 611 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); | 615 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); |
| 612 if (proof_source_.get() && !crypto_proof->certs && | 616 DCHECK(proof_source_.get()); |
| 617 if (!crypto_proof->certs && |
| 613 !proof_source_->GetProof(server_ip, info.sni.as_string(), | 618 !proof_source_->GetProof(server_ip, info.sni.as_string(), |
| 614 primary_config->serialized, x509_ecdsa_supported, | 619 primary_config->serialized, x509_ecdsa_supported, |
| 615 &crypto_proof->certs, | 620 &crypto_proof->certs, |
| 616 &crypto_proof->signature)) { | 621 &crypto_proof->signature)) { |
| 617 return QUIC_HANDSHAKE_FAILED; | 622 return QUIC_HANDSHAKE_FAILED; |
| 618 } | 623 } |
| 619 | 624 |
| 620 if (!info.valid_source_address_token || | 625 if (!info.valid_source_address_token || |
| 621 !info.client_nonce_well_formed || | 626 !info.client_nonce_well_formed || |
| 622 !info.unique || | 627 !info.unique || |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id), | 686 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id), |
| 682 sizeof(connection_id)); | 687 sizeof(connection_id)); |
| 683 hkdf_suffix.append(client_hello_serialized.data(), | 688 hkdf_suffix.append(client_hello_serialized.data(), |
| 684 client_hello_serialized.length()); | 689 client_hello_serialized.length()); |
| 685 hkdf_suffix.append(requested_config->serialized); | 690 hkdf_suffix.append(requested_config->serialized); |
| 686 // The addition of x509_supported in this if statement is so that an insecure | 691 // The addition of x509_supported in this if statement is so that an insecure |
| 687 // quic client talking to a secure quic server will not result in the secure | 692 // quic client talking to a secure quic server will not result in the secure |
| 688 // quic server adding the cert to the kdf. | 693 // quic server adding the cert to the kdf. |
| 689 // TODO(nharper): Should a server that is configured to be secure (i.e. one | 694 // TODO(nharper): Should a server that is configured to be secure (i.e. one |
| 690 // that has a proof_source_) be accepting responses from an insecure client? | 695 // that has a proof_source_) be accepting responses from an insecure client? |
| 691 if (version > QUIC_VERSION_25 && proof_source_.get() && x509_supported) { | 696 DCHECK(proof_source_.get()); |
| 697 if (version > QUIC_VERSION_25 && x509_supported) { |
| 692 if (crypto_proof->certs->empty()) { | 698 if (crypto_proof->certs->empty()) { |
| 693 *error_details = "Failed to get certs"; | 699 *error_details = "Failed to get certs"; |
| 694 return QUIC_CRYPTO_INTERNAL_ERROR; | 700 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 695 } | 701 } |
| 696 hkdf_suffix.append(crypto_proof->certs->at(0)); | 702 hkdf_suffix.append(crypto_proof->certs->at(0)); |
| 697 } | 703 } |
| 698 | 704 |
| 699 StringPiece cetv_ciphertext; | 705 StringPiece cetv_ciphertext; |
| 700 if (requested_config->channel_id_enabled && | 706 if (requested_config->channel_id_enabled && |
| 701 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) { | 707 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 helper.ValidationComplete(QUIC_NO_ERROR, ""); | 1016 helper.ValidationComplete(QUIC_NO_ERROR, ""); |
| 1011 return; | 1017 return; |
| 1012 } | 1018 } |
| 1013 found_error = true; | 1019 found_error = true; |
| 1014 } | 1020 } |
| 1015 | 1021 |
| 1016 if (version > QUIC_VERSION_25) { | 1022 if (version > QUIC_VERSION_25) { |
| 1017 bool x509_supported = false; | 1023 bool x509_supported = false; |
| 1018 bool x509_ecdsa_supported = false; | 1024 bool x509_ecdsa_supported = false; |
| 1019 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); | 1025 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); |
| 1020 if (proof_source_.get() && | 1026 if (!proof_source_->GetProof(server_ip, info->sni.as_string(), |
| 1021 !proof_source_->GetProof(server_ip, info->sni.as_string(), | |
| 1022 requested_config->serialized, | 1027 requested_config->serialized, |
| 1023 x509_ecdsa_supported, &crypto_proof->certs, | 1028 x509_ecdsa_supported, &crypto_proof->certs, |
| 1024 &crypto_proof->signature)) { | 1029 &crypto_proof->signature)) { |
| 1025 found_error = true; | 1030 found_error = true; |
| 1026 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); | 1031 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); |
| 1027 } | 1032 } |
| 1028 | 1033 |
| 1029 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { | 1034 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { |
| 1030 found_error = true; | 1035 found_error = true; |
| 1031 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); | 1036 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 CryptoHandshakeMessage* out) const { | 1127 CryptoHandshakeMessage* out) const { |
| 1123 base::AutoLock locked(configs_lock_); | 1128 base::AutoLock locked(configs_lock_); |
| 1124 out->set_tag(kSCUP); | 1129 out->set_tag(kSCUP); |
| 1125 out->SetStringPiece(kSCFG, primary_config_->serialized); | 1130 out->SetStringPiece(kSCFG, primary_config_->serialized); |
| 1126 out->SetStringPiece( | 1131 out->SetStringPiece( |
| 1127 kSourceAddressTokenTag, | 1132 kSourceAddressTokenTag, |
| 1128 NewSourceAddressToken(*primary_config_.get(), | 1133 NewSourceAddressToken(*primary_config_.get(), |
| 1129 previous_source_address_tokens, client_ip, rand, | 1134 previous_source_address_tokens, client_ip, rand, |
| 1130 clock->WallNow(), cached_network_params)); | 1135 clock->WallNow(), cached_network_params)); |
| 1131 | 1136 |
| 1132 if (proof_source_ == nullptr) { | |
| 1133 // Insecure QUIC, can send SCFG without proof. | |
| 1134 return true; | |
| 1135 } | |
| 1136 | |
| 1137 const vector<string>* certs; | 1137 const vector<string>* certs; |
| 1138 string signature; | 1138 string signature; |
| 1139 if (!proof_source_->GetProof( | 1139 if (!proof_source_->GetProof( |
| 1140 server_ip, params.sni, primary_config_->serialized, | 1140 server_ip, params.sni, primary_config_->serialized, |
| 1141 params.x509_ecdsa_supported, &certs, &signature)) { | 1141 params.x509_ecdsa_supported, &certs, &signature)) { |
| 1142 DVLOG(1) << "Server: failed to get proof."; | 1142 DVLOG(1) << "Server: failed to get proof."; |
| 1143 return false; | 1143 return false; |
| 1144 } | 1144 } |
| 1145 | 1145 |
| 1146 const string compressed = CertCompressor::CompressChain( | 1146 const string compressed = CertCompressor::CompressChain( |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 out->SetVector(kRREJ, info.reject_reasons); | 1186 out->SetVector(kRREJ, info.reject_reasons); |
| 1187 | 1187 |
| 1188 // The client may have requested a certificate chain. | 1188 // The client may have requested a certificate chain. |
| 1189 bool x509_supported = false; | 1189 bool x509_supported = false; |
| 1190 ParseProofDemand(client_hello, &x509_supported, | 1190 ParseProofDemand(client_hello, &x509_supported, |
| 1191 ¶ms->x509_ecdsa_supported); | 1191 ¶ms->x509_ecdsa_supported); |
| 1192 if (!x509_supported) { | 1192 if (!x509_supported) { |
| 1193 return; | 1193 return; |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 if (!proof_source_.get()) { | |
| 1197 return; | |
| 1198 } | |
| 1199 | |
| 1200 StringPiece client_common_set_hashes; | 1196 StringPiece client_common_set_hashes; |
| 1201 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) { | 1197 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) { |
| 1202 params->client_common_set_hashes = client_common_set_hashes.as_string(); | 1198 params->client_common_set_hashes = client_common_set_hashes.as_string(); |
| 1203 } | 1199 } |
| 1204 | 1200 |
| 1205 StringPiece client_cached_cert_hashes; | 1201 StringPiece client_cached_cert_hashes; |
| 1206 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) { | 1202 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) { |
| 1207 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string(); | 1203 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string(); |
| 1208 } | 1204 } |
| 1209 | 1205 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1393 return nullptr; | 1389 return nullptr; |
| 1394 } | 1390 } |
| 1395 } | 1391 } |
| 1396 | 1392 |
| 1397 config->key_exchanges.push_back(ka.release()); | 1393 config->key_exchanges.push_back(ka.release()); |
| 1398 } | 1394 } |
| 1399 | 1395 |
| 1400 return config; | 1396 return config; |
| 1401 } | 1397 } |
| 1402 | 1398 |
| 1403 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) { | |
| 1404 proof_source_.reset(proof_source); | |
| 1405 } | |
| 1406 | |
| 1407 void QuicCryptoServerConfig::SetEphemeralKeySource( | 1399 void QuicCryptoServerConfig::SetEphemeralKeySource( |
| 1408 EphemeralKeySource* ephemeral_key_source) { | 1400 EphemeralKeySource* ephemeral_key_source) { |
| 1409 ephemeral_key_source_.reset(ephemeral_key_source); | 1401 ephemeral_key_source_.reset(ephemeral_key_source); |
| 1410 } | 1402 } |
| 1411 | 1403 |
| 1412 void QuicCryptoServerConfig::SetStrikeRegisterClient( | 1404 void QuicCryptoServerConfig::SetStrikeRegisterClient( |
| 1413 StrikeRegisterClient* strike_register_client) { | 1405 StrikeRegisterClient* strike_register_client) { |
| 1414 base::AutoLock locker(strike_register_client_lock_); | 1406 base::AutoLock locker(strike_register_client_lock_); |
| 1415 DCHECK(!strike_register_client_.get()); | 1407 DCHECK(!strike_register_client_.get()); |
| 1416 strike_register_client_.reset(strike_register_client); | 1408 strike_register_client_.reset(strike_register_client); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 continue; | 1491 continue; |
| 1500 } | 1492 } |
| 1501 | 1493 |
| 1502 *(source_address_tokens.add_tokens()) = token; | 1494 *(source_address_tokens.add_tokens()) = token; |
| 1503 } | 1495 } |
| 1504 | 1496 |
| 1505 return config.source_address_token_boxer->Box( | 1497 return config.source_address_token_boxer->Box( |
| 1506 rand, source_address_tokens.SerializeAsString()); | 1498 rand, source_address_tokens.SerializeAsString()); |
| 1507 } | 1499 } |
| 1508 | 1500 |
| 1509 bool QuicCryptoServerConfig::HasProofSource() const { | |
| 1510 return proof_source_ != nullptr; | |
| 1511 } | |
| 1512 | |
| 1513 int QuicCryptoServerConfig::NumberOfConfigs() const { | 1501 int QuicCryptoServerConfig::NumberOfConfigs() const { |
| 1514 base::AutoLock locked(configs_lock_); | 1502 base::AutoLock locked(configs_lock_); |
| 1515 return configs_.size(); | 1503 return configs_.size(); |
| 1516 } | 1504 } |
| 1517 | 1505 |
| 1518 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken( | 1506 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken( |
| 1519 const Config& config, | 1507 const Config& config, |
| 1520 StringPiece token, | 1508 StringPiece token, |
| 1521 SourceAddressTokens* tokens) const { | 1509 SourceAddressTokens* tokens) const { |
| 1522 string storage; | 1510 string storage; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1672 case STRIKE_REGISTER_FAILURE: | 1660 case STRIKE_REGISTER_FAILURE: |
| 1673 default: | 1661 default: |
| 1674 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error; | 1662 LOG(DFATAL) << "Unexpected server nonce error: " << nonce_error; |
| 1675 return SERVER_NONCE_NOT_UNIQUE_FAILURE; | 1663 return SERVER_NONCE_NOT_UNIQUE_FAILURE; |
| 1676 } | 1664 } |
| 1677 } | 1665 } |
| 1678 | 1666 |
| 1679 bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate( | 1667 bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate( |
| 1680 const CryptoHandshakeMessage& client_hello, | 1668 const CryptoHandshakeMessage& client_hello, |
| 1681 const QuicCryptoProof& crypto_proof) const { | 1669 const QuicCryptoProof& crypto_proof) const { |
| 1682 // If the server doesn't use https, then the client won't send XLCT and | |
| 1683 // proof_source_ will be null, so in this case return true. | |
| 1684 if (!proof_source_.get()) { | |
| 1685 return true; | |
| 1686 } | |
| 1687 if (crypto_proof.certs->empty()) { | 1670 if (crypto_proof.certs->empty()) { |
| 1688 return false; | 1671 return false; |
| 1689 } | 1672 } |
| 1690 | 1673 |
| 1691 uint64 hash_from_client; | 1674 uint64 hash_from_client; |
| 1692 if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) { | 1675 if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) { |
| 1693 return false; | 1676 return false; |
| 1694 } | 1677 } |
| 1695 return CryptoUtils::ComputeLeafCertHash(crypto_proof.certs->at(0)) == | 1678 return CryptoUtils::ComputeLeafCertHash(crypto_proof.certs->at(0)) == |
| 1696 hash_from_client; | 1679 hash_from_client; |
| 1697 } | 1680 } |
| 1698 | 1681 |
| 1699 void QuicCryptoServerConfig::ParseProofDemand( | 1682 void QuicCryptoServerConfig::ParseProofDemand( |
| 1700 const CryptoHandshakeMessage& client_hello, | 1683 const CryptoHandshakeMessage& client_hello, |
| 1701 bool* x509_supported, | 1684 bool* x509_supported, |
| 1702 bool* x509_ecdsa_supported) const { | 1685 bool* x509_ecdsa_supported) const { |
| 1703 const QuicTag* their_proof_demands; | 1686 const QuicTag* their_proof_demands; |
| 1704 size_t num_their_proof_demands; | 1687 size_t num_their_proof_demands; |
| 1705 | 1688 |
| 1706 if (proof_source_.get() == nullptr || | 1689 if (client_hello.GetTaglist(kPDMD, &their_proof_demands, |
| 1707 client_hello.GetTaglist(kPDMD, &their_proof_demands, | |
| 1708 &num_their_proof_demands) != QUIC_NO_ERROR) { | 1690 &num_their_proof_demands) != QUIC_NO_ERROR) { |
| 1709 return; | 1691 return; |
| 1710 } | 1692 } |
| 1711 | 1693 |
| 1712 *x509_supported = false; | 1694 *x509_supported = false; |
| 1713 for (size_t i = 0; i < num_their_proof_demands; i++) { | 1695 for (size_t i = 0; i < num_their_proof_demands; i++) { |
| 1714 switch (their_proof_demands[i]) { | 1696 switch (their_proof_demands[i]) { |
| 1715 case kX509: | 1697 case kX509: |
| 1716 *x509_supported = true; | 1698 *x509_supported = true; |
| 1717 *x509_ecdsa_supported = true; | 1699 *x509_ecdsa_supported = true; |
| 1718 break; | 1700 break; |
| 1719 case kX59R: | 1701 case kX59R: |
| 1720 *x509_supported = true; | 1702 *x509_supported = true; |
| 1721 break; | 1703 break; |
| 1722 } | 1704 } |
| 1723 } | 1705 } |
| 1724 } | 1706 } |
| 1725 | 1707 |
| 1726 QuicCryptoServerConfig::Config::Config() | 1708 QuicCryptoServerConfig::Config::Config() |
| 1727 : channel_id_enabled(false), | 1709 : channel_id_enabled(false), |
| 1728 is_primary(false), | 1710 is_primary(false), |
| 1729 primary_time(QuicWallTime::Zero()), | 1711 primary_time(QuicWallTime::Zero()), |
| 1730 priority(0), | 1712 priority(0), |
| 1731 source_address_token_boxer(nullptr) {} | 1713 source_address_token_boxer(nullptr) {} |
| 1732 | 1714 |
| 1733 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } | 1715 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } |
| 1734 | 1716 |
| 1735 } // namespace net | 1717 } // namespace net |
| OLD | NEW |