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 |