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 #include <memory> | 10 #include <memory> |
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); | 618 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); |
619 // No need to get a new proof if one was already generated. | 619 // No need to get a new proof if one was already generated. |
620 if (!crypto_proof->chain && | 620 if (!crypto_proof->chain && |
621 !proof_source_->GetProof( | 621 !proof_source_->GetProof( |
622 server_ip, info.sni.as_string(), primary_config->serialized, version, | 622 server_ip, info.sni.as_string(), primary_config->serialized, version, |
623 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain, | 623 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain, |
624 &crypto_proof->signature, &crypto_proof->cert_sct)) { | 624 &crypto_proof->signature, &crypto_proof->cert_sct)) { |
625 return QUIC_HANDSHAKE_FAILED; | 625 return QUIC_HANDSHAKE_FAILED; |
626 } | 626 } |
627 | 627 |
628 if (version > QUIC_VERSION_29) { | 628 StringPiece cert_sct; |
629 StringPiece cert_sct; | 629 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && |
630 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) && | 630 cert_sct.empty()) { |
631 cert_sct.empty()) { | 631 params->sct_supported_by_client = true; |
632 params->sct_supported_by_client = true; | |
633 } | |
634 } | 632 } |
635 | 633 |
636 if (!info.reject_reasons.empty() || !requested_config.get()) { | 634 if (!info.reject_reasons.empty() || !requested_config.get()) { |
637 BuildRejection(version, *primary_config, client_hello, info, | 635 BuildRejection(version, *primary_config, client_hello, info, |
638 validate_chlo_result.cached_network_params, | 636 validate_chlo_result.cached_network_params, |
639 use_stateless_rejects, server_designated_connection_id, rand, | 637 use_stateless_rejects, server_designated_connection_id, rand, |
640 compressed_certs_cache, params, *crypto_proof, out); | 638 compressed_certs_cache, params, *crypto_proof, out); |
641 return QUIC_NO_ERROR; | 639 return QUIC_NO_ERROR; |
642 } | 640 } |
643 | 641 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
712 string hkdf_suffix; | 710 string hkdf_suffix; |
713 const QuicData& client_hello_serialized = client_hello.GetSerialized(); | 711 const QuicData& client_hello_serialized = client_hello.GetSerialized(); |
714 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() + | 712 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() + |
715 requested_config->serialized.size()); | 713 requested_config->serialized.size()); |
716 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id), | 714 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id), |
717 sizeof(connection_id)); | 715 sizeof(connection_id)); |
718 hkdf_suffix.append(client_hello_serialized.data(), | 716 hkdf_suffix.append(client_hello_serialized.data(), |
719 client_hello_serialized.length()); | 717 client_hello_serialized.length()); |
720 hkdf_suffix.append(requested_config->serialized); | 718 hkdf_suffix.append(requested_config->serialized); |
721 DCHECK(proof_source_.get()); | 719 DCHECK(proof_source_.get()); |
722 if (version > QUIC_VERSION_25) { | 720 if (crypto_proof->chain->certs.empty()) { |
723 if (crypto_proof->chain->certs.empty()) { | 721 *error_details = "Failed to get certs"; |
724 *error_details = "Failed to get certs"; | 722 return QUIC_CRYPTO_INTERNAL_ERROR; |
725 return QUIC_CRYPTO_INTERNAL_ERROR; | |
726 } | |
727 hkdf_suffix.append(crypto_proof->chain->certs.at(0)); | |
728 } | 723 } |
| 724 hkdf_suffix.append(crypto_proof->chain->certs.at(0)); |
729 | 725 |
730 StringPiece cetv_ciphertext; | 726 StringPiece cetv_ciphertext; |
731 if (requested_config->channel_id_enabled && | 727 if (requested_config->channel_id_enabled && |
732 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) { | 728 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) { |
733 CryptoHandshakeMessage client_hello_copy(client_hello); | 729 CryptoHandshakeMessage client_hello_copy(client_hello); |
734 client_hello_copy.Erase(kCETV); | 730 client_hello_copy.Erase(kCETV); |
735 client_hello_copy.Erase(kPAD); | 731 client_hello_copy.Erase(kPAD); |
736 | 732 |
737 const QuicData& client_hello_copy_serialized = | 733 const QuicData& client_hello_copy_serialized = |
738 client_hello_copy.GetSerialized(); | 734 client_hello_copy.GetSerialized(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 } | 823 } |
828 | 824 |
829 string forward_secure_hkdf_input; | 825 string forward_secure_hkdf_input; |
830 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; | 826 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; |
831 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size()); | 827 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size()); |
832 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, | 828 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, |
833 label_len); | 829 label_len); |
834 forward_secure_hkdf_input.append(hkdf_suffix); | 830 forward_secure_hkdf_input.append(hkdf_suffix); |
835 | 831 |
836 string shlo_nonce; | 832 string shlo_nonce; |
837 if (version > QUIC_VERSION_26) { | 833 shlo_nonce = NewServerNonce(rand, info.now); |
838 shlo_nonce = NewServerNonce(rand, info.now); | 834 out->SetStringPiece(kServerNonceTag, shlo_nonce); |
839 out->SetStringPiece(kServerNonceTag, shlo_nonce); | |
840 } | |
841 | 835 |
842 if (!CryptoUtils::DeriveKeys( | 836 if (!CryptoUtils::DeriveKeys( |
843 params->forward_secure_premaster_secret, params->aead, | 837 params->forward_secure_premaster_secret, params->aead, |
844 info.client_nonce, | 838 info.client_nonce, |
845 shlo_nonce.empty() ? info.server_nonce : shlo_nonce, | 839 shlo_nonce.empty() ? info.server_nonce : shlo_nonce, |
846 forward_secure_hkdf_input, Perspective::IS_SERVER, | 840 forward_secure_hkdf_input, Perspective::IS_SERVER, |
847 CryptoUtils::Diversification::Never(), | 841 CryptoUtils::Diversification::Never(), |
848 ¶ms->forward_secure_crypters, ¶ms->subkey_secret)) { | 842 ¶ms->forward_secure_crypters, ¶ms->subkey_secret)) { |
849 *error_details = "Symmetric key setup failed"; | 843 *error_details = "Symmetric key setup failed"; |
850 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 844 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 } | 1100 } |
1107 | 1101 |
1108 bool found_error = false; | 1102 bool found_error = false; |
1109 if (source_address_token_error != HANDSHAKE_OK) { | 1103 if (source_address_token_error != HANDSHAKE_OK) { |
1110 info->reject_reasons.push_back(source_address_token_error); | 1104 info->reject_reasons.push_back(source_address_token_error); |
1111 // No valid source address token. | 1105 // No valid source address token. |
1112 found_error = true; | 1106 found_error = true; |
1113 } | 1107 } |
1114 | 1108 |
1115 bool get_proof_failed = false; | 1109 bool get_proof_failed = false; |
1116 if (version > QUIC_VERSION_25) { | 1110 bool x509_supported = false; |
1117 bool x509_supported = false; | 1111 bool x509_ecdsa_supported = false; |
1118 bool x509_ecdsa_supported = false; | 1112 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); |
1119 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported); | 1113 string serialized_config = primary_config->serialized; |
1120 string serialized_config = primary_config->serialized; | 1114 string chlo_hash; |
1121 string chlo_hash; | 1115 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); |
1122 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); | 1116 bool need_proof = true; |
1123 bool need_proof = true; | 1117 if (FLAGS_quic_refresh_proof) { |
1124 if (FLAGS_quic_refresh_proof) { | 1118 need_proof = !crypto_proof->chain; |
1125 need_proof = !crypto_proof->chain; | 1119 } |
1126 } | 1120 if (FLAGS_enable_async_get_proof) { |
1127 if (FLAGS_enable_async_get_proof) { | 1121 if (need_proof) { |
1128 if (need_proof) { | 1122 // Make an async call to GetProof and setup the callback to trampoline |
1129 // Make an async call to GetProof and setup the callback to trampoline | 1123 // back into EvaluateClientHelloAfterGetProof |
1130 // back into EvaluateClientHelloAfterGetProof | 1124 std::unique_ptr<EvaluateClientHelloCallback> cb( |
1131 std::unique_ptr<EvaluateClientHelloCallback> cb( | 1125 new EvaluateClientHelloCallback( |
1132 new EvaluateClientHelloCallback( | 1126 *this, found_error, server_ip, version, primary_orbit, |
1133 *this, found_error, server_ip, version, primary_orbit, | 1127 requested_config, primary_config, crypto_proof, |
1134 requested_config, primary_config, crypto_proof, | 1128 client_hello_state, done_cb)); |
1135 client_hello_state, done_cb)); | 1129 proof_source_->GetProof(server_ip, info->sni.as_string(), |
1136 proof_source_->GetProof(server_ip, info->sni.as_string(), | 1130 serialized_config, version, chlo_hash, |
1137 serialized_config, version, chlo_hash, | 1131 x509_ecdsa_supported, std::move(cb)); |
1138 x509_ecdsa_supported, std::move(cb)); | 1132 helper.DetachCallback(); |
1139 helper.DetachCallback(); | 1133 return; |
1140 return; | |
1141 } | |
1142 } | |
1143 | |
1144 // No need to get a new proof if one was already generated. | |
1145 if (need_proof && | |
1146 !proof_source_->GetProof( | |
1147 server_ip, info->sni.as_string(), serialized_config, version, | |
1148 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain, | |
1149 &crypto_proof->signature, &crypto_proof->cert_sct)) { | |
1150 get_proof_failed = true; | |
1151 } | 1134 } |
1152 } | 1135 } |
1153 | 1136 |
| 1137 // No need to get a new proof if one was already generated. |
| 1138 if (need_proof && |
| 1139 !proof_source_->GetProof( |
| 1140 server_ip, info->sni.as_string(), serialized_config, version, |
| 1141 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain, |
| 1142 &crypto_proof->signature, &crypto_proof->cert_sct)) { |
| 1143 get_proof_failed = true; |
| 1144 } |
| 1145 |
1154 EvaluateClientHelloAfterGetProof( | 1146 EvaluateClientHelloAfterGetProof( |
1155 found_error, server_ip, version, primary_orbit, requested_config, | 1147 found_error, server_ip, version, primary_orbit, requested_config, |
1156 primary_config, crypto_proof, get_proof_failed, client_hello_state, | 1148 primary_config, crypto_proof, get_proof_failed, client_hello_state, |
1157 done_cb); | 1149 done_cb); |
1158 helper.DetachCallback(); | 1150 helper.DetachCallback(); |
1159 } | 1151 } |
1160 | 1152 |
1161 void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof( | 1153 void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof( |
1162 bool found_error, | 1154 bool found_error, |
1163 const IPAddress& server_ip, | 1155 const IPAddress& server_ip, |
1164 QuicVersion version, | 1156 QuicVersion version, |
1165 const uint8_t* primary_orbit, | 1157 const uint8_t* primary_orbit, |
1166 scoped_refptr<Config> requested_config, | 1158 scoped_refptr<Config> requested_config, |
1167 scoped_refptr<Config> primary_config, | 1159 scoped_refptr<Config> primary_config, |
1168 QuicCryptoProof* crypto_proof, | 1160 QuicCryptoProof* crypto_proof, |
1169 bool get_proof_failed, | 1161 bool get_proof_failed, |
1170 ValidateClientHelloResultCallback::Result* client_hello_state, | 1162 ValidateClientHelloResultCallback::Result* client_hello_state, |
1171 ValidateClientHelloResultCallback* done_cb) const { | 1163 ValidateClientHelloResultCallback* done_cb) const { |
1172 ValidateClientHelloHelper helper(client_hello_state, done_cb); | 1164 ValidateClientHelloHelper helper(client_hello_state, done_cb); |
1173 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello; | 1165 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello; |
1174 ClientHelloInfo* info = &(client_hello_state->info); | 1166 ClientHelloInfo* info = &(client_hello_state->info); |
1175 | 1167 |
1176 if (get_proof_failed) { | 1168 if (get_proof_failed) { |
1177 found_error = true; | 1169 found_error = true; |
1178 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); | 1170 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); |
1179 } | 1171 } |
1180 | 1172 |
1181 if (version > QUIC_VERSION_25) { | 1173 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { |
1182 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) { | 1174 found_error = true; |
1183 found_error = true; | 1175 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); |
1184 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); | |
1185 } | |
1186 } | 1176 } |
1187 | 1177 |
1188 if (info->client_nonce.size() != kNonceSize) { | 1178 if (info->client_nonce.size() != kNonceSize) { |
1189 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); | 1179 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); |
1190 // Invalid client nonce. | 1180 // Invalid client nonce. |
1191 LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString(); | 1181 LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString(); |
1192 DVLOG(1) << "Invalid client nonce."; | 1182 DVLOG(1) << "Invalid client nonce."; |
1193 found_error = true; | 1183 found_error = true; |
1194 } | 1184 } |
1195 | 1185 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1301 DVLOG(1) << "Server: failed to get proof."; | 1291 DVLOG(1) << "Server: failed to get proof."; |
1302 return false; | 1292 return false; |
1303 } | 1293 } |
1304 | 1294 |
1305 const string compressed = CompressChain( | 1295 const string compressed = CompressChain( |
1306 compressed_certs_cache, chain, params.client_common_set_hashes, | 1296 compressed_certs_cache, chain, params.client_common_set_hashes, |
1307 params.client_cached_cert_hashes, common_cert_sets); | 1297 params.client_cached_cert_hashes, common_cert_sets); |
1308 | 1298 |
1309 out->SetStringPiece(kCertificateTag, compressed); | 1299 out->SetStringPiece(kCertificateTag, compressed); |
1310 out->SetStringPiece(kPROF, signature); | 1300 out->SetStringPiece(kPROF, signature); |
1311 if (params.sct_supported_by_client && version > QUIC_VERSION_29 && | 1301 if (params.sct_supported_by_client && enable_serving_sct_) { |
1312 enable_serving_sct_) { | |
1313 if (cert_sct.empty()) { | 1302 if (cert_sct.empty()) { |
1314 DLOG(WARNING) << "SCT is expected but it is empty."; | 1303 DLOG(WARNING) << "SCT is expected but it is empty."; |
1315 } else { | 1304 } else { |
1316 out->SetStringPiece(kCertificateSCTTag, cert_sct); | 1305 out->SetStringPiece(kCertificateSCTTag, cert_sct); |
1317 } | 1306 } |
1318 } | 1307 } |
1319 return true; | 1308 return true; |
1320 } | 1309 } |
1321 | 1310 |
1322 void QuicCryptoServerConfig::BuildServerConfigUpdateMessage( | 1311 void QuicCryptoServerConfig::BuildServerConfigUpdateMessage( |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 cb->Run(false, message); | 1398 cb->Run(false, message); |
1410 return; | 1399 return; |
1411 } | 1400 } |
1412 | 1401 |
1413 const string compressed = | 1402 const string compressed = |
1414 CompressChain(compressed_certs_cache, chain, client_common_set_hashes, | 1403 CompressChain(compressed_certs_cache, chain, client_common_set_hashes, |
1415 client_cached_cert_hashes, common_cert_sets); | 1404 client_cached_cert_hashes, common_cert_sets); |
1416 | 1405 |
1417 message.SetStringPiece(kCertificateTag, compressed); | 1406 message.SetStringPiece(kCertificateTag, compressed); |
1418 message.SetStringPiece(kPROF, signature); | 1407 message.SetStringPiece(kPROF, signature); |
1419 if (sct_supported_by_client && version > QUIC_VERSION_29 && | 1408 if (sct_supported_by_client && enable_serving_sct_) { |
1420 enable_serving_sct_) { | |
1421 if (leaf_cert_sct.empty()) { | 1409 if (leaf_cert_sct.empty()) { |
1422 DLOG(WARNING) << "SCT is expected but it is empty."; | 1410 DLOG(WARNING) << "SCT is expected but it is empty."; |
1423 } else { | 1411 } else { |
1424 message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct); | 1412 message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct); |
1425 } | 1413 } |
1426 } | 1414 } |
1427 | 1415 |
1428 cb->Run(true, message); | 1416 cb->Run(true, message); |
1429 } | 1417 } |
1430 | 1418 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1495 // SCID: 16 bytes | 1483 // SCID: 16 bytes |
1496 // PUBS: 38 bytes | 1484 // PUBS: 38 bytes |
1497 const size_t kREJOverheadBytes = 166; | 1485 const size_t kREJOverheadBytes = 166; |
1498 // max_unverified_size is the number of bytes that the certificate chain, | 1486 // max_unverified_size is the number of bytes that the certificate chain, |
1499 // signature, and (optionally) signed certificate timestamp can consume before | 1487 // signature, and (optionally) signed certificate timestamp can consume before |
1500 // we will demand a valid source-address token. | 1488 // we will demand a valid source-address token. |
1501 const size_t max_unverified_size = | 1489 const size_t max_unverified_size = |
1502 client_hello.size() * chlo_multiplier_ - kREJOverheadBytes; | 1490 client_hello.size() * chlo_multiplier_ - kREJOverheadBytes; |
1503 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, | 1491 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes, |
1504 "overhead calculation may underflow"); | 1492 "overhead calculation may underflow"); |
1505 bool should_return_sct = params->sct_supported_by_client && | 1493 bool should_return_sct = |
1506 version > QUIC_VERSION_29 && enable_serving_sct_; | 1494 params->sct_supported_by_client && enable_serving_sct_; |
1507 const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0; | 1495 const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0; |
1508 if (info.valid_source_address_token || | 1496 if (info.valid_source_address_token || |
1509 crypto_proof.signature.size() + compressed.size() + sct_size < | 1497 crypto_proof.signature.size() + compressed.size() + sct_size < |
1510 max_unverified_size) { | 1498 max_unverified_size) { |
1511 out->SetStringPiece(kCertificateTag, compressed); | 1499 out->SetStringPiece(kCertificateTag, compressed); |
1512 out->SetStringPiece(kPROF, crypto_proof.signature); | 1500 out->SetStringPiece(kPROF, crypto_proof.signature); |
1513 if (should_return_sct) { | 1501 if (should_return_sct) { |
1514 if (crypto_proof.cert_sct.empty()) { | 1502 if (crypto_proof.cert_sct.empty()) { |
1515 DLOG(WARNING) << "SCT is expected but it is empty."; | 1503 DLOG(WARNING) << "SCT is expected but it is empty."; |
1516 } else { | 1504 } else { |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2045 priority(0), | 2033 priority(0), |
2046 source_address_token_boxer(nullptr) {} | 2034 source_address_token_boxer(nullptr) {} |
2047 | 2035 |
2048 QuicCryptoServerConfig::Config::~Config() { | 2036 QuicCryptoServerConfig::Config::~Config() { |
2049 STLDeleteElements(&key_exchanges); | 2037 STLDeleteElements(&key_exchanges); |
2050 } | 2038 } |
2051 | 2039 |
2052 QuicCryptoProof::QuicCryptoProof() {} | 2040 QuicCryptoProof::QuicCryptoProof() {} |
2053 QuicCryptoProof::~QuicCryptoProof() {} | 2041 QuicCryptoProof::~QuicCryptoProof() {} |
2054 } // namespace net | 2042 } // namespace net |
OLD | NEW |