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 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 p256_public_value.size()); | 285 p256_public_value.size()); |
286 } | 286 } |
287 | 287 |
288 msg.set_tag(kSCFG); | 288 msg.set_tag(kSCFG); |
289 if (options.p256) { | 289 if (options.p256) { |
290 msg.SetTaglist(kKEXS, kC255, kP256, 0); | 290 msg.SetTaglist(kKEXS, kC255, kP256, 0); |
291 } else { | 291 } else { |
292 msg.SetTaglist(kKEXS, kC255, 0); | 292 msg.SetTaglist(kKEXS, kC255, 0); |
293 } | 293 } |
294 if (FLAGS_quic_crypto_server_config_default_has_chacha20) { | 294 if (FLAGS_quic_crypto_server_config_default_has_chacha20) { |
295 if (FLAGS_quic_use_rfc7539 && | 295 if (ChaCha20Poly1305Rfc7539Encrypter::IsSupported()) { |
296 ChaCha20Poly1305Rfc7539Encrypter::IsSupported()) { | |
297 msg.SetTaglist(kAEAD, kAESG, kCC12, kCC20, 0); | 296 msg.SetTaglist(kAEAD, kAESG, kCC12, kCC20, 0); |
298 } else { | 297 } else { |
299 msg.SetTaglist(kAEAD, kAESG, kCC12, 0); | 298 msg.SetTaglist(kAEAD, kAESG, kCC12, 0); |
300 } | 299 } |
301 } else { | 300 } else { |
302 msg.SetTaglist(kAEAD, kAESG, 0); | 301 msg.SetTaglist(kAEAD, kAESG, 0); |
303 } | 302 } |
304 msg.SetStringPiece(kPUBS, encoded_public_values); | 303 msg.SetStringPiece(kPUBS, encoded_public_values); |
305 | 304 |
306 if (options.expiry_time.IsZero()) { | 305 if (options.expiry_time.IsZero()) { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 const ValidateClientHelloResultCallback::Result& validate_chlo_result, | 546 const ValidateClientHelloResultCallback::Result& validate_chlo_result, |
548 QuicConnectionId connection_id, | 547 QuicConnectionId connection_id, |
549 const IPAddress& server_ip, | 548 const IPAddress& server_ip, |
550 const IPEndPoint& client_address, | 549 const IPEndPoint& client_address, |
551 QuicVersion version, | 550 QuicVersion version, |
552 const QuicVersionVector& supported_versions, | 551 const QuicVersionVector& supported_versions, |
553 bool use_stateless_rejects, | 552 bool use_stateless_rejects, |
554 QuicConnectionId server_designated_connection_id, | 553 QuicConnectionId server_designated_connection_id, |
555 const QuicClock* clock, | 554 const QuicClock* clock, |
556 QuicRandom* rand, | 555 QuicRandom* rand, |
| 556 QuicCompressedCertsCache* compressed_certs_cache, |
557 QuicCryptoNegotiatedParameters* params, | 557 QuicCryptoNegotiatedParameters* params, |
558 QuicCryptoProof* crypto_proof, | 558 QuicCryptoProof* crypto_proof, |
559 CryptoHandshakeMessage* out, | 559 CryptoHandshakeMessage* out, |
560 string* error_details) const { | 560 string* error_details) const { |
561 DCHECK(error_details); | 561 DCHECK(error_details); |
562 | 562 |
563 const CryptoHandshakeMessage& client_hello = | 563 const CryptoHandshakeMessage& client_hello = |
564 validate_chlo_result.client_hello; | 564 validate_chlo_result.client_hello; |
565 const ClientHelloInfo& info = validate_chlo_result.info; | 565 const ClientHelloInfo& info = validate_chlo_result.info; |
566 | 566 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && | 622 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && |
623 cert_sct.empty()) { | 623 cert_sct.empty()) { |
624 params->sct_supported_by_client = true; | 624 params->sct_supported_by_client = true; |
625 } | 625 } |
626 } | 626 } |
627 | 627 |
628 if (!info.reject_reasons.empty() || !requested_config.get()) { | 628 if (!info.reject_reasons.empty() || !requested_config.get()) { |
629 BuildRejection(version, *primary_config, client_hello, info, | 629 BuildRejection(version, *primary_config, client_hello, info, |
630 validate_chlo_result.cached_network_params, | 630 validate_chlo_result.cached_network_params, |
631 use_stateless_rejects, server_designated_connection_id, rand, | 631 use_stateless_rejects, server_designated_connection_id, rand, |
632 params, *crypto_proof, out); | 632 compressed_certs_cache, params, *crypto_proof, out); |
633 return QUIC_NO_ERROR; | 633 return QUIC_NO_ERROR; |
634 } | 634 } |
635 | 635 |
636 const QuicTag* their_aeads; | 636 const QuicTag* their_aeads; |
637 const QuicTag* their_key_exchanges; | 637 const QuicTag* their_key_exchanges; |
638 size_t num_their_aeads, num_their_key_exchanges; | 638 size_t num_their_aeads, num_their_key_exchanges; |
639 if (client_hello.GetTaglist(kAEAD, &their_aeads, &num_their_aeads) != | 639 if (client_hello.GetTaglist(kAEAD, &their_aeads, &num_their_aeads) != |
640 QUIC_NO_ERROR || | 640 QUIC_NO_ERROR || |
641 client_hello.GetTaglist(kKEXS, &their_key_exchanges, | 641 client_hello.GetTaglist(kKEXS, &their_key_exchanges, |
642 &num_their_key_exchanges) != QUIC_NO_ERROR || | 642 &num_their_key_exchanges) != QUIC_NO_ERROR || |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1057 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { | 1057 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { |
1058 found_error = true; | 1058 found_error = true; |
1059 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); | 1059 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); |
1060 } | 1060 } |
1061 } | 1061 } |
1062 | 1062 |
1063 if (!client_hello.GetStringPiece(kNONC, &info->client_nonce) || | 1063 if (!client_hello.GetStringPiece(kNONC, &info->client_nonce) || |
1064 info->client_nonce.size() != kNonceSize) { | 1064 info->client_nonce.size() != kNonceSize) { |
1065 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); | 1065 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); |
1066 // Invalid client nonce. | 1066 // Invalid client nonce. |
| 1067 LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString(); |
1067 DVLOG(1) << "Invalid client nonce."; | 1068 DVLOG(1) << "Invalid client nonce."; |
1068 if (FLAGS_use_early_return_when_verifying_chlo) { | 1069 if (FLAGS_use_early_return_when_verifying_chlo) { |
1069 helper.ValidationComplete(QUIC_NO_ERROR, ""); | 1070 helper.ValidationComplete(QUIC_NO_ERROR, ""); |
1070 return; | 1071 return; |
1071 } | 1072 } |
1072 found_error = true; | 1073 found_error = true; |
1073 } | 1074 } |
1074 | 1075 |
1075 // Server nonce is optional, and used for key derivation if present. | 1076 // Server nonce is optional, and used for key derivation if present. |
1076 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); | 1077 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1143 helper.StartedAsyncCallback(); | 1144 helper.StartedAsyncCallback(); |
1144 } | 1145 } |
1145 | 1146 |
1146 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( | 1147 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage( |
1147 QuicVersion version, | 1148 QuicVersion version, |
1148 const SourceAddressTokens& previous_source_address_tokens, | 1149 const SourceAddressTokens& previous_source_address_tokens, |
1149 const IPAddress& server_ip, | 1150 const IPAddress& server_ip, |
1150 const IPAddress& client_ip, | 1151 const IPAddress& client_ip, |
1151 const QuicClock* clock, | 1152 const QuicClock* clock, |
1152 QuicRandom* rand, | 1153 QuicRandom* rand, |
| 1154 QuicCompressedCertsCache* compressed_certs_cache, |
1153 const QuicCryptoNegotiatedParameters& params, | 1155 const QuicCryptoNegotiatedParameters& params, |
1154 const CachedNetworkParameters* cached_network_params, | 1156 const CachedNetworkParameters* cached_network_params, |
1155 CryptoHandshakeMessage* out) const { | 1157 CryptoHandshakeMessage* out) const { |
1156 base::AutoLock locked(configs_lock_); | 1158 base::AutoLock locked(configs_lock_); |
1157 out->set_tag(kSCUP); | 1159 out->set_tag(kSCUP); |
1158 out->SetStringPiece(kSCFG, primary_config_->serialized); | 1160 out->SetStringPiece(kSCFG, primary_config_->serialized); |
1159 out->SetStringPiece( | 1161 out->SetStringPiece( |
1160 kSourceAddressTokenTag, | 1162 kSourceAddressTokenTag, |
1161 NewSourceAddressToken(*primary_config_.get(), | 1163 NewSourceAddressToken(*primary_config_.get(), |
1162 previous_source_address_tokens, client_ip, rand, | 1164 previous_source_address_tokens, client_ip, rand, |
1163 clock->WallNow(), cached_network_params)); | 1165 clock->WallNow(), cached_network_params)); |
1164 | 1166 |
1165 scoped_refptr<ProofSource::Chain> chain; | 1167 scoped_refptr<ProofSource::Chain> chain; |
1166 string signature; | 1168 string signature; |
1167 string cert_sct; | 1169 string cert_sct; |
1168 if (!proof_source_->GetProof(server_ip, params.sni, | 1170 if (!proof_source_->GetProof(server_ip, params.sni, |
1169 primary_config_->serialized, version, | 1171 primary_config_->serialized, version, |
1170 params.client_nonce, params.x509_ecdsa_supported, | 1172 params.client_nonce, params.x509_ecdsa_supported, |
1171 &chain, &signature, &cert_sct)) { | 1173 &chain, &signature, &cert_sct)) { |
1172 DVLOG(1) << "Server: failed to get proof."; | 1174 DVLOG(1) << "Server: failed to get proof."; |
1173 return false; | 1175 return false; |
1174 } | 1176 } |
1175 | 1177 |
1176 const string compressed = CertCompressor::CompressChain( | 1178 const string compressed = CompressChain( |
1177 chain->certs, params.client_common_set_hashes, | 1179 compressed_certs_cache, chain, params.client_common_set_hashes, |
1178 params.client_cached_cert_hashes, primary_config_->common_cert_sets); | 1180 params.client_cached_cert_hashes, primary_config_->common_cert_sets); |
1179 | 1181 |
1180 out->SetStringPiece(kCertificateTag, compressed); | 1182 out->SetStringPiece(kCertificateTag, compressed); |
1181 out->SetStringPiece(kPROF, signature); | 1183 out->SetStringPiece(kPROF, signature); |
1182 if (params.sct_supported_by_client && version > QUIC_VERSION_29 && | 1184 if (params.sct_supported_by_client && version > QUIC_VERSION_29 && |
1183 enable_serving_sct_) { | 1185 enable_serving_sct_) { |
1184 if (cert_sct.empty()) { | 1186 if (cert_sct.empty()) { |
1185 DLOG(WARNING) << "SCT is expected but it is empty."; | 1187 DLOG(WARNING) << "SCT is expected but it is empty."; |
1186 } else { | 1188 } else { |
1187 out->SetStringPiece(kCertificateSCTTag, cert_sct); | 1189 out->SetStringPiece(kCertificateSCTTag, cert_sct); |
1188 } | 1190 } |
1189 } | 1191 } |
1190 return true; | 1192 return true; |
1191 } | 1193 } |
1192 | 1194 |
1193 void QuicCryptoServerConfig::BuildRejection( | 1195 void QuicCryptoServerConfig::BuildRejection( |
1194 QuicVersion version, | 1196 QuicVersion version, |
1195 const Config& config, | 1197 const Config& config, |
1196 const CryptoHandshakeMessage& client_hello, | 1198 const CryptoHandshakeMessage& client_hello, |
1197 const ClientHelloInfo& info, | 1199 const ClientHelloInfo& info, |
1198 const CachedNetworkParameters& cached_network_params, | 1200 const CachedNetworkParameters& cached_network_params, |
1199 bool use_stateless_rejects, | 1201 bool use_stateless_rejects, |
1200 QuicConnectionId server_designated_connection_id, | 1202 QuicConnectionId server_designated_connection_id, |
1201 QuicRandom* rand, | 1203 QuicRandom* rand, |
| 1204 QuicCompressedCertsCache* compressed_certs_cache, |
1202 QuicCryptoNegotiatedParameters* params, | 1205 QuicCryptoNegotiatedParameters* params, |
1203 const QuicCryptoProof& crypto_proof, | 1206 const QuicCryptoProof& crypto_proof, |
1204 CryptoHandshakeMessage* out) const { | 1207 CryptoHandshakeMessage* out) const { |
1205 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) { | 1208 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) { |
1206 DVLOG(1) << "QUIC Crypto server config returning stateless reject " | 1209 DVLOG(1) << "QUIC Crypto server config returning stateless reject " |
1207 << "with server-designated connection ID " | 1210 << "with server-designated connection ID " |
1208 << server_designated_connection_id; | 1211 << server_designated_connection_id; |
1209 out->set_tag(kSREJ); | 1212 out->set_tag(kSREJ); |
1210 out->SetValue(kRCID, server_designated_connection_id); | 1213 out->SetValue(kRCID, server_designated_connection_id); |
1211 } else { | 1214 } else { |
(...skipping 23 matching lines...) Expand all Loading... |
1235 StringPiece client_common_set_hashes; | 1238 StringPiece client_common_set_hashes; |
1236 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) { | 1239 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) { |
1237 params->client_common_set_hashes = client_common_set_hashes.as_string(); | 1240 params->client_common_set_hashes = client_common_set_hashes.as_string(); |
1238 } | 1241 } |
1239 | 1242 |
1240 StringPiece client_cached_cert_hashes; | 1243 StringPiece client_cached_cert_hashes; |
1241 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) { | 1244 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) { |
1242 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string(); | 1245 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string(); |
1243 } | 1246 } |
1244 | 1247 |
1245 const string compressed = CertCompressor::CompressChain( | 1248 const string compressed = |
1246 crypto_proof.chain->certs, params->client_common_set_hashes, | 1249 CompressChain(compressed_certs_cache, crypto_proof.chain, |
1247 params->client_cached_cert_hashes, config.common_cert_sets); | 1250 params->client_common_set_hashes, |
| 1251 params->client_cached_cert_hashes, config.common_cert_sets); |
1248 | 1252 |
1249 // kREJOverheadBytes is a very rough estimate of how much of a REJ | 1253 // kREJOverheadBytes is a very rough estimate of how much of a REJ |
1250 // message is taken up by things other than the certificates. | 1254 // message is taken up by things other than the certificates. |
1251 // STK: 56 bytes | 1255 // STK: 56 bytes |
1252 // SNO: 56 bytes | 1256 // SNO: 56 bytes |
1253 // SCFG | 1257 // SCFG |
1254 // SCID: 16 bytes | 1258 // SCID: 16 bytes |
1255 // PUBS: 38 bytes | 1259 // PUBS: 38 bytes |
1256 const size_t kREJOverheadBytes = 166; | 1260 const size_t kREJOverheadBytes = 166; |
1257 // max_unverified_size is the number of bytes that the certificate chain, | 1261 // max_unverified_size is the number of bytes that the certificate chain, |
(...skipping 14 matching lines...) Expand all Loading... |
1272 if (should_return_sct) { | 1276 if (should_return_sct) { |
1273 if (crypto_proof.cert_sct.empty()) { | 1277 if (crypto_proof.cert_sct.empty()) { |
1274 DLOG(WARNING) << "SCT is expected but it is empty."; | 1278 DLOG(WARNING) << "SCT is expected but it is empty."; |
1275 } else { | 1279 } else { |
1276 out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct); | 1280 out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct); |
1277 } | 1281 } |
1278 } | 1282 } |
1279 } | 1283 } |
1280 } | 1284 } |
1281 | 1285 |
| 1286 const string QuicCryptoServerConfig::CompressChain( |
| 1287 QuicCompressedCertsCache* compressed_certs_cache, |
| 1288 const scoped_refptr<ProofSource::Chain>& chain, |
| 1289 const string& client_common_set_hashes, |
| 1290 const string& client_cached_cert_hashes, |
| 1291 const CommonCertSets* common_sets) const { |
| 1292 // Check whether the compressed certs is available in the cache. |
| 1293 if (FLAGS_quic_use_cached_compressed_certs) { |
| 1294 DCHECK(compressed_certs_cache); |
| 1295 const string* cached_value = compressed_certs_cache->GetCompressedCert( |
| 1296 chain, client_common_set_hashes, client_cached_cert_hashes); |
| 1297 if (cached_value) { |
| 1298 return *cached_value; |
| 1299 } |
| 1300 } |
| 1301 |
| 1302 const string compressed = |
| 1303 CertCompressor::CompressChain(chain->certs, client_common_set_hashes, |
| 1304 client_common_set_hashes, common_sets); |
| 1305 |
| 1306 // Insert the newly compressed cert to cache. |
| 1307 if (FLAGS_quic_use_cached_compressed_certs) { |
| 1308 compressed_certs_cache->Insert(chain, client_common_set_hashes, |
| 1309 client_cached_cert_hashes, compressed); |
| 1310 } |
| 1311 return compressed; |
| 1312 } |
| 1313 |
1282 scoped_refptr<QuicCryptoServerConfig::Config> | 1314 scoped_refptr<QuicCryptoServerConfig::Config> |
1283 QuicCryptoServerConfig::ParseConfigProtobuf( | 1315 QuicCryptoServerConfig::ParseConfigProtobuf( |
1284 QuicServerConfigProtobuf* protobuf) { | 1316 QuicServerConfigProtobuf* protobuf) { |
1285 scoped_ptr<CryptoHandshakeMessage> msg( | 1317 scoped_ptr<CryptoHandshakeMessage> msg( |
1286 CryptoFramer::ParseMessage(protobuf->config())); | 1318 CryptoFramer::ParseMessage(protobuf->config())); |
1287 | 1319 |
1288 if (msg->tag() != kSCFG) { | 1320 if (msg->tag() != kSCFG) { |
1289 LOG(WARNING) << "Server config message has tag " << msg->tag() | 1321 LOG(WARNING) << "Server config message has tag " << msg->tag() |
1290 << " expected " << kSCFG; | 1322 << " expected " << kSCFG; |
1291 return nullptr; | 1323 return nullptr; |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 priority(0), | 1812 priority(0), |
1781 source_address_token_boxer(nullptr) {} | 1813 source_address_token_boxer(nullptr) {} |
1782 | 1814 |
1783 QuicCryptoServerConfig::Config::~Config() { | 1815 QuicCryptoServerConfig::Config::~Config() { |
1784 STLDeleteElements(&key_exchanges); | 1816 STLDeleteElements(&key_exchanges); |
1785 } | 1817 } |
1786 | 1818 |
1787 QuicCryptoProof::QuicCryptoProof() {} | 1819 QuicCryptoProof::QuicCryptoProof() {} |
1788 QuicCryptoProof::~QuicCryptoProof() {} | 1820 QuicCryptoProof::~QuicCryptoProof() {} |
1789 } // namespace net | 1821 } // namespace net |
OLD | NEW |