Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: net/quic/crypto/quic_crypto_server_config.cc

Issue 1416583005: Add support of serving SCT on the server side in QUIC, gated by QUIC_VERSION_30. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@106687764
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/crypto/quic_crypto_server_config.h ('k') | net/quic/quic_crypto_server_stream.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 delete result; 201 delete result;
202 delete this; 202 delete this;
203 } 203 }
204 204
205 QuicCryptoServerConfig::ConfigOptions::ConfigOptions() 205 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
206 : expiry_time(QuicWallTime::Zero()), 206 : expiry_time(QuicWallTime::Zero()),
207 channel_id_enabled(false), 207 channel_id_enabled(false),
208 p256(false) {} 208 p256(false) {}
209 209
210 QuicCryptoServerConfig::QuicCryptoServerConfig( 210 QuicCryptoServerConfig::QuicCryptoServerConfig(
211 StringPiece source_address_token_secret, 211 StringPiece source_address_token_secret, QuicRandom* server_nonce_entropy,
212 QuicRandom* server_nonce_entropy,
213 ProofSource* proof_source) 212 ProofSource* proof_source)
214 : replay_protection_(true), 213 : replay_protection_(true),
215 configs_lock_(), 214 configs_lock_(),
216 primary_config_(nullptr), 215 primary_config_(nullptr),
217 next_config_promotion_time_(QuicWallTime::Zero()), 216 next_config_promotion_time_(QuicWallTime::Zero()),
218 server_nonce_strike_register_lock_(), 217 server_nonce_strike_register_lock_(),
219 proof_source_(proof_source), 218 proof_source_(proof_source),
220 strike_register_no_startup_period_(false), 219 strike_register_no_startup_period_(false),
221 strike_register_max_entries_(1 << 10), 220 strike_register_max_entries_(1 << 10),
222 strike_register_window_secs_(600), 221 strike_register_window_secs_(600),
223 source_address_token_future_secs_(3600), 222 source_address_token_future_secs_(3600),
224 source_address_token_lifetime_secs_(86400), 223 source_address_token_lifetime_secs_(86400),
225 server_nonce_strike_register_max_entries_(1 << 10), 224 server_nonce_strike_register_max_entries_(1 << 10),
226 server_nonce_strike_register_window_secs_(120) { 225 server_nonce_strike_register_window_secs_(120),
226 enable_serving_sct_(false) {
227 DCHECK(proof_source_.get()); 227 DCHECK(proof_source_.get());
228 default_source_address_token_boxer_.SetKey( 228 default_source_address_token_boxer_.SetKey(
229 DeriveSourceAddressTokenKey(source_address_token_secret)); 229 DeriveSourceAddressTokenKey(source_address_token_secret));
230 230
231 // Generate a random key and orbit for server nonces. 231 // Generate a random key and orbit for server nonces.
232 server_nonce_entropy->RandBytes(server_nonce_orbit_, 232 server_nonce_entropy->RandBytes(server_nonce_orbit_,
233 sizeof(server_nonce_orbit_)); 233 sizeof(server_nonce_orbit_));
234 const size_t key_size = server_nonce_boxer_.GetKeySize(); 234 const size_t key_size = server_nonce_boxer_.GetKeySize();
235 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); 235 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
236 server_nonce_entropy->RandBytes(key_bytes.get(), key_size); 236 server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 604
605 out->Clear(); 605 out->Clear();
606 606
607 bool x509_supported = false; 607 bool x509_supported = false;
608 bool x509_ecdsa_supported = false; 608 bool x509_ecdsa_supported = false;
609 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); 609 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
610 DCHECK(proof_source_.get()); 610 DCHECK(proof_source_.get());
611 if (!crypto_proof->certs && 611 if (!crypto_proof->certs &&
612 !proof_source_->GetProof(server_ip, info.sni.as_string(), 612 !proof_source_->GetProof(server_ip, info.sni.as_string(),
613 primary_config->serialized, x509_ecdsa_supported, 613 primary_config->serialized, x509_ecdsa_supported,
614 &crypto_proof->certs, 614 &crypto_proof->certs, &crypto_proof->signature,
615 &crypto_proof->signature)) { 615 &crypto_proof->cert_sct)) {
616 return QUIC_HANDSHAKE_FAILED; 616 return QUIC_HANDSHAKE_FAILED;
617 } 617 }
618 618
619 if (version > QUIC_VERSION_29) {
620 StringPiece cert_sct;
621 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) &&
622 cert_sct.empty()) {
623 params->sct_supported_by_client = true;
624 }
625 }
626
619 if (!info.reject_reasons.empty() || !requested_config.get()) { 627 if (!info.reject_reasons.empty() || !requested_config.get()) {
620 BuildRejection(*primary_config, client_hello, info, 628 BuildRejection(version, *primary_config, client_hello, info,
621 validate_chlo_result.cached_network_params, 629 validate_chlo_result.cached_network_params,
622 use_stateless_rejects, server_designated_connection_id, rand, 630 use_stateless_rejects, server_designated_connection_id, rand,
623 params, *crypto_proof, out); 631 params, *crypto_proof, out);
624 return QUIC_NO_ERROR; 632 return QUIC_NO_ERROR;
625 } 633 }
626 634
627 const QuicTag* their_aeads; 635 const QuicTag* their_aeads;
628 const QuicTag* their_key_exchanges; 636 const QuicTag* their_key_exchanges;
629 size_t num_their_aeads, num_their_key_exchanges; 637 size_t num_their_aeads, num_their_key_exchanges;
630 if (client_hello.GetTaglist(kAEAD, &their_aeads, 638 if (client_hello.GetTaglist(kAEAD, &their_aeads,
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 helper.ValidationComplete(QUIC_NO_ERROR, ""); 1015 helper.ValidationComplete(QUIC_NO_ERROR, "");
1008 return; 1016 return;
1009 } 1017 }
1010 found_error = true; 1018 found_error = true;
1011 } 1019 }
1012 1020
1013 if (version > QUIC_VERSION_25) { 1021 if (version > QUIC_VERSION_25) {
1014 bool x509_supported = false; 1022 bool x509_supported = false;
1015 bool x509_ecdsa_supported = false; 1023 bool x509_ecdsa_supported = false;
1016 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); 1024 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
1017 if (!proof_source_->GetProof(server_ip, info->sni.as_string(), 1025 if (!proof_source_->GetProof(
1018 requested_config->serialized, 1026 server_ip, info->sni.as_string(), requested_config->serialized,
1019 x509_ecdsa_supported, &crypto_proof->certs, 1027 x509_ecdsa_supported, &crypto_proof->certs,
1020 &crypto_proof->signature)) { 1028 &crypto_proof->signature, &crypto_proof->cert_sct)) {
1021 found_error = true; 1029 found_error = true;
1022 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); 1030 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1023 } 1031 }
1024 1032
1025 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { 1033 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) {
1026 found_error = true; 1034 found_error = true;
1027 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); 1035 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
1028 } 1036 }
1029 } 1037 }
1030 1038
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 } 1116 }
1109 1117
1110 strike_register_client->VerifyNonceIsValidAndUnique( 1118 strike_register_client->VerifyNonceIsValidAndUnique(
1111 info->client_nonce, 1119 info->client_nonce,
1112 info->now, 1120 info->now,
1113 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); 1121 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
1114 helper.StartedAsyncCallback(); 1122 helper.StartedAsyncCallback();
1115 } 1123 }
1116 1124
1117 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( 1125 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1126 QuicVersion version,
1118 const SourceAddressTokens& previous_source_address_tokens, 1127 const SourceAddressTokens& previous_source_address_tokens,
1119 const IPAddressNumber& server_ip, 1128 const IPAddressNumber& server_ip,
1120 const IPAddressNumber& client_ip, 1129 const IPAddressNumber& client_ip,
1121 const QuicClock* clock, 1130 const QuicClock* clock,
1122 QuicRandom* rand, 1131 QuicRandom* rand,
1123 const QuicCryptoNegotiatedParameters& params, 1132 const QuicCryptoNegotiatedParameters& params,
1124 const CachedNetworkParameters* cached_network_params, 1133 const CachedNetworkParameters* cached_network_params,
1125 CryptoHandshakeMessage* out) const { 1134 CryptoHandshakeMessage* out) const {
1126 base::AutoLock locked(configs_lock_); 1135 base::AutoLock locked(configs_lock_);
1127 out->set_tag(kSCUP); 1136 out->set_tag(kSCUP);
1128 out->SetStringPiece(kSCFG, primary_config_->serialized); 1137 out->SetStringPiece(kSCFG, primary_config_->serialized);
1129 out->SetStringPiece( 1138 out->SetStringPiece(
1130 kSourceAddressTokenTag, 1139 kSourceAddressTokenTag,
1131 NewSourceAddressToken(*primary_config_.get(), 1140 NewSourceAddressToken(*primary_config_.get(),
1132 previous_source_address_tokens, client_ip, rand, 1141 previous_source_address_tokens, client_ip, rand,
1133 clock->WallNow(), cached_network_params)); 1142 clock->WallNow(), cached_network_params));
1134 1143
1135 const vector<string>* certs; 1144 const vector<string>* certs;
1136 string signature; 1145 string signature;
1146 string cert_sct;
1137 if (!proof_source_->GetProof( 1147 if (!proof_source_->GetProof(
1138 server_ip, params.sni, primary_config_->serialized, 1148 server_ip, params.sni, primary_config_->serialized,
1139 params.x509_ecdsa_supported, &certs, &signature)) { 1149 params.x509_ecdsa_supported, &certs, &signature, &cert_sct)) {
1140 DVLOG(1) << "Server: failed to get proof."; 1150 DVLOG(1) << "Server: failed to get proof.";
1141 return false; 1151 return false;
1142 } 1152 }
1143 1153
1144 const string compressed = CertCompressor::CompressChain( 1154 const string compressed = CertCompressor::CompressChain(
1145 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes, 1155 *certs, params.client_common_set_hashes, params.client_cached_cert_hashes,
1146 primary_config_->common_cert_sets); 1156 primary_config_->common_cert_sets);
1147 1157
1148 out->SetStringPiece(kCertificateTag, compressed); 1158 out->SetStringPiece(kCertificateTag, compressed);
1149 out->SetStringPiece(kPROF, signature); 1159 out->SetStringPiece(kPROF, signature);
1160 if (params.sct_supported_by_client && version > QUIC_VERSION_29 &&
1161 enable_serving_sct_) {
1162 if (cert_sct.empty()) {
1163 DLOG(WARNING) << "SCT is expected but it is empty.";
1164 } else {
1165 out->SetStringPiece(kCertificateSCTTag, cert_sct);
1166 }
1167 }
1150 return true; 1168 return true;
1151 } 1169 }
1152 1170
1153 void QuicCryptoServerConfig::BuildRejection( 1171 void QuicCryptoServerConfig::BuildRejection(
1154 const Config& config, 1172 QuicVersion version, const Config& config,
1155 const CryptoHandshakeMessage& client_hello, 1173 const CryptoHandshakeMessage& client_hello, const ClientHelloInfo& info,
1156 const ClientHelloInfo& info,
1157 const CachedNetworkParameters& cached_network_params, 1174 const CachedNetworkParameters& cached_network_params,
1158 bool use_stateless_rejects, 1175 bool use_stateless_rejects,
1159 QuicConnectionId server_designated_connection_id, 1176 QuicConnectionId server_designated_connection_id, QuicRandom* rand,
1160 QuicRandom* rand, 1177 QuicCryptoNegotiatedParameters* params, const QuicCryptoProof& crypto_proof,
1161 QuicCryptoNegotiatedParameters* params,
1162 const QuicCryptoProof& crypto_proof,
1163 CryptoHandshakeMessage* out) const { 1178 CryptoHandshakeMessage* out) const {
1164 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) { 1179 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) {
1165 DVLOG(1) << "QUIC Crypto server config returning stateless reject " 1180 DVLOG(1) << "QUIC Crypto server config returning stateless reject "
1166 << "with server-designated connection ID " 1181 << "with server-designated connection ID "
1167 << server_designated_connection_id; 1182 << server_designated_connection_id;
1168 out->set_tag(kSREJ); 1183 out->set_tag(kSREJ);
1169 out->SetValue(kRCID, server_designated_connection_id); 1184 out->SetValue(kRCID, server_designated_connection_id);
1170 } else { 1185 } else {
1171 out->set_tag(kREJ); 1186 out->set_tag(kREJ);
1172 } 1187 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1208 // kREJOverheadBytes is a very rough estimate of how much of a REJ 1223 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1209 // message is taken up by things other than the certificates. 1224 // message is taken up by things other than the certificates.
1210 // STK: 56 bytes 1225 // STK: 56 bytes
1211 // SNO: 56 bytes 1226 // SNO: 56 bytes
1212 // SCFG 1227 // SCFG
1213 // SCID: 16 bytes 1228 // SCID: 16 bytes
1214 // PUBS: 38 bytes 1229 // PUBS: 38 bytes
1215 const size_t kREJOverheadBytes = 166; 1230 const size_t kREJOverheadBytes = 166;
1216 // kMultiplier is the multiple of the CHLO message size that a REJ message 1231 // 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 1232 // must stay under when the client doesn't present a valid source-address
1218 // token. 1233 // token. This is used to protect QUIC from amplification attacks.
1219 const size_t kMultiplier = 2; 1234 const size_t kMultiplier = 2;
1220 // max_unverified_size is the number of bytes that the certificate chain 1235 // 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 1236 // signature, and (optionally) signed certificate timestamp can consume before
1222 // token. 1237 // we will demand a valid source-address token.
1223 const size_t max_unverified_size = 1238 const size_t max_unverified_size =
1224 client_hello.size() * kMultiplier - kREJOverheadBytes; 1239 client_hello.size() * kMultiplier - kREJOverheadBytes;
1225 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, 1240 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1226 "overhead calculation may overflow"); 1241 "overhead calculation may underflow");
1242 bool should_return_sct = params->sct_supported_by_client &&
1243 version > QUIC_VERSION_29 && enable_serving_sct_;
1244 const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0;
1227 if (info.valid_source_address_token || 1245 if (info.valid_source_address_token ||
1228 crypto_proof.signature.size() + compressed.size() < max_unverified_size) { 1246 crypto_proof.signature.size() + compressed.size() + sct_size <
1247 max_unverified_size) {
1229 out->SetStringPiece(kCertificateTag, compressed); 1248 out->SetStringPiece(kCertificateTag, compressed);
1230 out->SetStringPiece(kPROF, crypto_proof.signature); 1249 out->SetStringPiece(kPROF, crypto_proof.signature);
1250 if (should_return_sct) {
1251 if (crypto_proof.cert_sct.empty()) {
1252 DLOG(WARNING) << "SCT is expected but it is empty.";
1253 } else {
1254 out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct);
1255 }
1256 }
1231 } 1257 }
1232 } 1258 }
1233 1259
1234 scoped_refptr<QuicCryptoServerConfig::Config> 1260 scoped_refptr<QuicCryptoServerConfig::Config>
1235 QuicCryptoServerConfig::ParseConfigProtobuf( 1261 QuicCryptoServerConfig::ParseConfigProtobuf(
1236 QuicServerConfigProtobuf* protobuf) { 1262 QuicServerConfigProtobuf* protobuf) {
1237 scoped_ptr<CryptoHandshakeMessage> msg( 1263 scoped_ptr<CryptoHandshakeMessage> msg(
1238 CryptoFramer::ParseMessage(protobuf->config())); 1264 CryptoFramer::ParseMessage(protobuf->config()));
1239 1265
1240 if (msg->tag() != kSCFG) { 1266 if (msg->tag() != kSCFG) {
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1445 DCHECK(!server_nonce_strike_register_.get()); 1471 DCHECK(!server_nonce_strike_register_.get());
1446 server_nonce_strike_register_max_entries_ = max_entries; 1472 server_nonce_strike_register_max_entries_ = max_entries;
1447 } 1473 }
1448 1474
1449 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs( 1475 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1450 uint32 window_secs) { 1476 uint32 window_secs) {
1451 DCHECK(!server_nonce_strike_register_.get()); 1477 DCHECK(!server_nonce_strike_register_.get());
1452 server_nonce_strike_register_window_secs_ = window_secs; 1478 server_nonce_strike_register_window_secs_ = window_secs;
1453 } 1479 }
1454 1480
1481 void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
1482 enable_serving_sct_ = enable_serving_sct;
1483 }
1484
1455 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( 1485 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1456 PrimaryConfigChangedCallback* cb) { 1486 PrimaryConfigChangedCallback* cb) {
1457 base::AutoLock locked(configs_lock_); 1487 base::AutoLock locked(configs_lock_);
1458 primary_config_changed_cb_.reset(cb); 1488 primary_config_changed_cb_.reset(cb);
1459 } 1489 }
1460 1490
1461 string QuicCryptoServerConfig::NewSourceAddressToken( 1491 string QuicCryptoServerConfig::NewSourceAddressToken(
1462 const Config& config, 1492 const Config& config,
1463 const SourceAddressTokens& previous_tokens, 1493 const SourceAddressTokens& previous_tokens,
1464 const IPAddressNumber& ip, 1494 const IPAddressNumber& ip,
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 QuicCryptoServerConfig::Config::Config() 1736 QuicCryptoServerConfig::Config::Config()
1707 : channel_id_enabled(false), 1737 : channel_id_enabled(false),
1708 is_primary(false), 1738 is_primary(false),
1709 primary_time(QuicWallTime::Zero()), 1739 primary_time(QuicWallTime::Zero()),
1710 priority(0), 1740 priority(0),
1711 source_address_token_boxer(nullptr) {} 1741 source_address_token_boxer(nullptr) {}
1712 1742
1713 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } 1743 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
1714 1744
1715 } // namespace net 1745 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/quic_crypto_server_config.h ('k') | net/quic/quic_crypto_server_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698