| 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 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 primary_config_(nullptr), | 216 primary_config_(nullptr), |
| 217 next_config_promotion_time_(QuicWallTime::Zero()), | 217 next_config_promotion_time_(QuicWallTime::Zero()), |
| 218 server_nonce_strike_register_lock_(), | 218 server_nonce_strike_register_lock_(), |
| 219 proof_source_(proof_source), | 219 proof_source_(proof_source), |
| 220 strike_register_no_startup_period_(false), | 220 strike_register_no_startup_period_(false), |
| 221 strike_register_max_entries_(1 << 10), | 221 strike_register_max_entries_(1 << 10), |
| 222 strike_register_window_secs_(600), | 222 strike_register_window_secs_(600), |
| 223 source_address_token_future_secs_(3600), | 223 source_address_token_future_secs_(3600), |
| 224 source_address_token_lifetime_secs_(86400), | 224 source_address_token_lifetime_secs_(86400), |
| 225 server_nonce_strike_register_max_entries_(1 << 10), | 225 server_nonce_strike_register_max_entries_(1 << 10), |
| 226 server_nonce_strike_register_window_secs_(120) { | 226 server_nonce_strike_register_window_secs_(120), |
| 227 enable_serving_sct_(false) { |
| 227 DCHECK(proof_source_.get()); | 228 DCHECK(proof_source_.get()); |
| 228 default_source_address_token_boxer_.SetKey( | 229 default_source_address_token_boxer_.SetKey( |
| 229 DeriveSourceAddressTokenKey(source_address_token_secret)); | 230 DeriveSourceAddressTokenKey(source_address_token_secret)); |
| 230 | 231 |
| 231 // Generate a random key and orbit for server nonces. | 232 // Generate a random key and orbit for server nonces. |
| 232 server_nonce_entropy->RandBytes(server_nonce_orbit_, | 233 server_nonce_entropy->RandBytes(server_nonce_orbit_, |
| 233 sizeof(server_nonce_orbit_)); | 234 sizeof(server_nonce_orbit_)); |
| 234 const size_t key_size = server_nonce_boxer_.GetKeySize(); | 235 const size_t key_size = server_nonce_boxer_.GetKeySize(); |
| 235 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); | 236 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); |
| 236 server_nonce_entropy->RandBytes(key_bytes.get(), key_size); | 237 server_nonce_entropy->RandBytes(key_bytes.get(), key_size); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 | 605 |
| 605 out->Clear(); | 606 out->Clear(); |
| 606 | 607 |
| 607 bool x509_supported = false; | 608 bool x509_supported = false; |
| 608 bool x509_ecdsa_supported = false; | 609 bool x509_ecdsa_supported = false; |
| 609 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); | 610 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); |
| 610 DCHECK(proof_source_.get()); | 611 DCHECK(proof_source_.get()); |
| 611 if (!crypto_proof->certs && | 612 if (!crypto_proof->certs && |
| 612 !proof_source_->GetProof(server_ip, info.sni.as_string(), | 613 !proof_source_->GetProof(server_ip, info.sni.as_string(), |
| 613 primary_config->serialized, x509_ecdsa_supported, | 614 primary_config->serialized, x509_ecdsa_supported, |
| 614 &crypto_proof->certs, | 615 &crypto_proof->certs, &crypto_proof->signature, |
| 615 &crypto_proof->signature)) { | 616 &crypto_proof->cert_sct)) { |
| 616 return QUIC_HANDSHAKE_FAILED; | 617 return QUIC_HANDSHAKE_FAILED; |
| 617 } | 618 } |
| 618 | 619 |
| 620 if (version > QUIC_VERSION_29) { |
| 621 StringPiece cert_sct; |
| 622 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && |
| 623 cert_sct.empty()) { |
| 624 params->sct_supported_by_client = true; |
| 625 } |
| 626 } |
| 627 |
| 619 if (!info.reject_reasons.empty() || !requested_config.get()) { | 628 if (!info.reject_reasons.empty() || !requested_config.get()) { |
| 620 BuildRejection(*primary_config, client_hello, info, | 629 BuildRejection(version, *primary_config, client_hello, info, |
| 621 validate_chlo_result.cached_network_params, | 630 validate_chlo_result.cached_network_params, |
| 622 use_stateless_rejects, server_designated_connection_id, rand, | 631 use_stateless_rejects, server_designated_connection_id, rand, |
| 623 params, *crypto_proof, out); | 632 params, *crypto_proof, out); |
| 624 return QUIC_NO_ERROR; | 633 return QUIC_NO_ERROR; |
| 625 } | 634 } |
| 626 | 635 |
| 627 const QuicTag* their_aeads; | 636 const QuicTag* their_aeads; |
| 628 const QuicTag* their_key_exchanges; | 637 const QuicTag* their_key_exchanges; |
| 629 size_t num_their_aeads, num_their_key_exchanges; | 638 size_t num_their_aeads, num_their_key_exchanges; |
| 630 if (client_hello.GetTaglist(kAEAD, &their_aeads, | 639 if (client_hello.GetTaglist(kAEAD, &their_aeads, |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1007 helper.ValidationComplete(QUIC_NO_ERROR, ""); | 1016 helper.ValidationComplete(QUIC_NO_ERROR, ""); |
| 1008 return; | 1017 return; |
| 1009 } | 1018 } |
| 1010 found_error = true; | 1019 found_error = true; |
| 1011 } | 1020 } |
| 1012 | 1021 |
| 1013 if (version > QUIC_VERSION_25) { | 1022 if (version > QUIC_VERSION_25) { |
| 1014 bool x509_supported = false; | 1023 bool x509_supported = false; |
| 1015 bool x509_ecdsa_supported = false; | 1024 bool x509_ecdsa_supported = false; |
| 1016 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); | 1025 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); |
| 1017 if (!proof_source_->GetProof(server_ip, info->sni.as_string(), | 1026 if (!proof_source_->GetProof( |
| 1018 requested_config->serialized, | 1027 server_ip, info->sni.as_string(), requested_config->serialized, |
| 1019 x509_ecdsa_supported, &crypto_proof->certs, | 1028 x509_ecdsa_supported, &crypto_proof->certs, |
| 1020 &crypto_proof->signature)) { | 1029 &crypto_proof->signature, &crypto_proof->cert_sct)) { |
| 1021 found_error = true; | 1030 found_error = true; |
| 1022 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); | 1031 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); |
| 1023 } | 1032 } |
| 1024 | 1033 |
| 1025 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { | 1034 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { |
| 1026 found_error = true; | 1035 found_error = true; |
| 1027 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); | 1036 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); |
| 1028 } | 1037 } |
| 1029 } | 1038 } |
| 1030 | 1039 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1108 } | 1117 } |
| 1109 | 1118 |
| 1110 strike_register_client->VerifyNonceIsValidAndUnique( | 1119 strike_register_client->VerifyNonceIsValidAndUnique( |
| 1111 info->client_nonce, | 1120 info->client_nonce, |
| 1112 info->now, | 1121 info->now, |
| 1113 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); | 1122 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); |
| 1114 helper.StartedAsyncCallback(); | 1123 helper.StartedAsyncCallback(); |
| 1115 } | 1124 } |
| 1116 | 1125 |
| 1117 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( | 1126 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( |
| 1127 QuicVersion version, |
| 1118 const SourceAddressTokens& previous_source_address_tokens, | 1128 const SourceAddressTokens& previous_source_address_tokens, |
| 1119 const IPAddressNumber& server_ip, | 1129 const IPAddressNumber& server_ip, |
| 1120 const IPAddressNumber& client_ip, | 1130 const IPAddressNumber& client_ip, |
| 1121 const QuicClock* clock, | 1131 const QuicClock* clock, |
| 1122 QuicRandom* rand, | 1132 QuicRandom* rand, |
| 1123 const QuicCryptoNegotiatedParameters& params, | 1133 const QuicCryptoNegotiatedParameters& params, |
| 1124 const CachedNetworkParameters* cached_network_params, | 1134 const CachedNetworkParameters* cached_network_params, |
| 1125 CryptoHandshakeMessage* out) const { | 1135 CryptoHandshakeMessage* out) const { |
| 1126 base::AutoLock locked(configs_lock_); | 1136 base::AutoLock locked(configs_lock_); |
| 1127 out->set_tag(kSCUP); | 1137 out->set_tag(kSCUP); |
| 1128 out->SetStringPiece(kSCFG, primary_config_->serialized); | 1138 out->SetStringPiece(kSCFG, primary_config_->serialized); |
| 1129 out->SetStringPiece( | 1139 out->SetStringPiece( |
| 1130 kSourceAddressTokenTag, | 1140 kSourceAddressTokenTag, |
| 1131 NewSourceAddressToken(*primary_config_.get(), | 1141 NewSourceAddressToken(*primary_config_.get(), |
| 1132 previous_source_address_tokens, client_ip, rand, | 1142 previous_source_address_tokens, client_ip, rand, |
| 1133 clock->WallNow(), cached_network_params)); | 1143 clock->WallNow(), cached_network_params)); |
| 1134 | 1144 |
| 1135 const vector<string>* certs; | 1145 const vector<string>* certs; |
| 1136 string signature; | 1146 string signature; |
| 1147 string cert_sct; |
| 1137 if (!proof_source_->GetProof( | 1148 if (!proof_source_->GetProof( |
| 1138 server_ip, params.sni, primary_config_->serialized, | 1149 server_ip, params.sni, primary_config_->serialized, |
| 1139 params.x509_ecdsa_supported, &certs, &signature)) { | 1150 params.x509_ecdsa_supported, &certs, &signature, &cert_sct)) { |
| 1140 DVLOG(1) << "Server: failed to get proof."; | 1151 DVLOG(1) << "Server: failed to get proof."; |
| 1141 return false; | 1152 return false; |
| 1142 } | 1153 } |
| 1143 | 1154 |
| 1144 const string compressed = CertCompressor::CompressChain( | 1155 const string compressed = CertCompressor::CompressChain( |
| 1145 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes, | 1156 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes, |
| 1146 primary_config_->common_cert_sets); | 1157 primary_config_->common_cert_sets); |
| 1147 | 1158 |
| 1148 out->SetStringPiece(kCertificateTag, compressed); | 1159 out->SetStringPiece(kCertificateTag, compressed); |
| 1149 out->SetStringPiece(kPROF, signature); | 1160 out->SetStringPiece(kPROF, signature); |
| 1161 if (params.sct_supported_by_client && version > QUIC_VERSION_29 && |
| 1162 enable_serving_sct_) { |
| 1163 if (cert_sct.empty()) { |
| 1164 DLOG(WARNING) << "SCT is expected but it is empty."; |
| 1165 } else { |
| 1166 out->SetStringPiece(kCertificateSCTTag, cert_sct); |
| 1167 } |
| 1168 } |
| 1150 return true; | 1169 return true; |
| 1151 } | 1170 } |
| 1152 | 1171 |
| 1153 void QuicCryptoServerConfig::BuildRejection( | 1172 void QuicCryptoServerConfig::BuildRejection( |
| 1173 QuicVersion version, |
| 1154 const Config& config, | 1174 const Config& config, |
| 1155 const CryptoHandshakeMessage& client_hello, | 1175 const CryptoHandshakeMessage& client_hello, |
| 1156 const ClientHelloInfo& info, | 1176 const ClientHelloInfo& info, |
| 1157 const CachedNetworkParameters& cached_network_params, | 1177 const CachedNetworkParameters& cached_network_params, |
| 1158 bool use_stateless_rejects, | 1178 bool use_stateless_rejects, |
| 1159 QuicConnectionId server_designated_connection_id, | 1179 QuicConnectionId server_designated_connection_id, |
| 1160 QuicRandom* rand, | 1180 QuicRandom* rand, |
| 1161 QuicCryptoNegotiatedParameters* params, | 1181 QuicCryptoNegotiatedParameters* params, |
| 1162 const QuicCryptoProof& crypto_proof, | 1182 const QuicCryptoProof& crypto_proof, |
| 1163 CryptoHandshakeMessage* out) const { | 1183 CryptoHandshakeMessage* out) const { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1208 // kREJOverheadBytes is a very rough estimate of how much of a REJ | 1228 // kREJOverheadBytes is a very rough estimate of how much of a REJ |
| 1209 // message is taken up by things other than the certificates. | 1229 // message is taken up by things other than the certificates. |
| 1210 // STK: 56 bytes | 1230 // STK: 56 bytes |
| 1211 // SNO: 56 bytes | 1231 // SNO: 56 bytes |
| 1212 // SCFG | 1232 // SCFG |
| 1213 // SCID: 16 bytes | 1233 // SCID: 16 bytes |
| 1214 // PUBS: 38 bytes | 1234 // PUBS: 38 bytes |
| 1215 const size_t kREJOverheadBytes = 166; | 1235 const size_t kREJOverheadBytes = 166; |
| 1216 // kMultiplier is the multiple of the CHLO message size that a REJ message | 1236 // kMultiplier is the multiple of the CHLO message size that a REJ message |
| 1217 // must stay under when the client doesn't present a valid source-address | 1237 // must stay under when the client doesn't present a valid source-address |
| 1218 // token. | 1238 // token. This is used to protect QUIC from amplification attacks. |
| 1219 const size_t kMultiplier = 2; | 1239 const size_t kMultiplier = 2; |
| 1220 // max_unverified_size is the number of bytes that the certificate chain | 1240 // max_unverified_size is the number of bytes that the certificate chain, |
| 1221 // and signature can consume before we will demand a valid source-address | 1241 // signature, and (optionally) signed certificate timestamp can consume before |
| 1222 // token. | 1242 // we will demand a valid source-address token. |
| 1223 const size_t max_unverified_size = | 1243 const size_t max_unverified_size = |
| 1224 client_hello.size() * kMultiplier - kREJOverheadBytes; | 1244 client_hello.size() * kMultiplier - kREJOverheadBytes; |
| 1225 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, | 1245 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, |
| 1226 "overhead calculation may overflow"); | 1246 "overhead calculation may underflow"); |
| 1247 bool should_return_sct = params->sct_supported_by_client && |
| 1248 version > QUIC_VERSION_29 && enable_serving_sct_; |
| 1249 const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0; |
| 1227 if (info.valid_source_address_token || | 1250 if (info.valid_source_address_token || |
| 1228 crypto_proof.signature.size() + compressed.size() < max_unverified_size) { | 1251 crypto_proof.signature.size() + compressed.size() + sct_size < |
| 1252 max_unverified_size) { |
| 1229 out->SetStringPiece(kCertificateTag, compressed); | 1253 out->SetStringPiece(kCertificateTag, compressed); |
| 1230 out->SetStringPiece(kPROF, crypto_proof.signature); | 1254 out->SetStringPiece(kPROF, crypto_proof.signature); |
| 1255 if (should_return_sct) { |
| 1256 if (crypto_proof.cert_sct.empty()) { |
| 1257 DLOG(WARNING) << "SCT is expected but it is empty."; |
| 1258 } else { |
| 1259 out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct); |
| 1260 } |
| 1261 } |
| 1231 } | 1262 } |
| 1232 } | 1263 } |
| 1233 | 1264 |
| 1234 scoped_refptr<QuicCryptoServerConfig::Config> | 1265 scoped_refptr<QuicCryptoServerConfig::Config> |
| 1235 QuicCryptoServerConfig::ParseConfigProtobuf( | 1266 QuicCryptoServerConfig::ParseConfigProtobuf( |
| 1236 QuicServerConfigProtobuf* protobuf) { | 1267 QuicServerConfigProtobuf* protobuf) { |
| 1237 scoped_ptr<CryptoHandshakeMessage> msg( | 1268 scoped_ptr<CryptoHandshakeMessage> msg( |
| 1238 CryptoFramer::ParseMessage(protobuf->config())); | 1269 CryptoFramer::ParseMessage(protobuf->config())); |
| 1239 | 1270 |
| 1240 if (msg->tag() != kSCFG) { | 1271 if (msg->tag() != kSCFG) { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 DCHECK(!server_nonce_strike_register_.get()); | 1476 DCHECK(!server_nonce_strike_register_.get()); |
| 1446 server_nonce_strike_register_max_entries_ = max_entries; | 1477 server_nonce_strike_register_max_entries_ = max_entries; |
| 1447 } | 1478 } |
| 1448 | 1479 |
| 1449 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs( | 1480 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs( |
| 1450 uint32 window_secs) { | 1481 uint32 window_secs) { |
| 1451 DCHECK(!server_nonce_strike_register_.get()); | 1482 DCHECK(!server_nonce_strike_register_.get()); |
| 1452 server_nonce_strike_register_window_secs_ = window_secs; | 1483 server_nonce_strike_register_window_secs_ = window_secs; |
| 1453 } | 1484 } |
| 1454 | 1485 |
| 1486 void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) { |
| 1487 enable_serving_sct_ = enable_serving_sct; |
| 1488 } |
| 1489 |
| 1455 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( | 1490 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( |
| 1456 PrimaryConfigChangedCallback* cb) { | 1491 PrimaryConfigChangedCallback* cb) { |
| 1457 base::AutoLock locked(configs_lock_); | 1492 base::AutoLock locked(configs_lock_); |
| 1458 primary_config_changed_cb_.reset(cb); | 1493 primary_config_changed_cb_.reset(cb); |
| 1459 } | 1494 } |
| 1460 | 1495 |
| 1461 string QuicCryptoServerConfig::NewSourceAddressToken( | 1496 string QuicCryptoServerConfig::NewSourceAddressToken( |
| 1462 const Config& config, | 1497 const Config& config, |
| 1463 const SourceAddressTokens& previous_tokens, | 1498 const SourceAddressTokens& previous_tokens, |
| 1464 const IPAddressNumber& ip, | 1499 const IPAddressNumber& ip, |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1706 QuicCryptoServerConfig::Config::Config() | 1741 QuicCryptoServerConfig::Config::Config() |
| 1707 : channel_id_enabled(false), | 1742 : channel_id_enabled(false), |
| 1708 is_primary(false), | 1743 is_primary(false), |
| 1709 primary_time(QuicWallTime::Zero()), | 1744 primary_time(QuicWallTime::Zero()), |
| 1710 priority(0), | 1745 priority(0), |
| 1711 source_address_token_boxer(nullptr) {} | 1746 source_address_token_boxer(nullptr) {} |
| 1712 | 1747 |
| 1713 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } | 1748 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } |
| 1714 | 1749 |
| 1715 } // namespace net | 1750 } // namespace net |
| OLD | NEW |