Index: net/quic/crypto/crypto_server_test.cc |
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc |
index f1892d3b6ac7813f9029df6a82829ef32ccddfca..19bb67bdc15e0898852df3998a5caf2974b75e02 100644 |
--- a/net/quic/crypto/crypto_server_test.cc |
+++ b/net/quic/crypto/crypto_server_test.cc |
@@ -2,12 +2,16 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include <ostream> |
+#include <vector> |
+ |
#include "base/basictypes.h" |
#include "base/strings/string_number_conversions.h" |
#include "crypto/secure_hash.h" |
#include "net/quic/crypto/crypto_utils.h" |
#include "net/quic/crypto/quic_crypto_server_config.h" |
#include "net/quic/crypto/quic_random.h" |
+#include "net/quic/quic_flags.h" |
#include "net/quic/quic_socket_address_coder.h" |
#include "net/quic/quic_utils.h" |
#include "net/quic/test_tools/crypto_test_utils.h" |
@@ -18,7 +22,9 @@ |
#include "testing/gtest/include/gtest/gtest.h" |
using base::StringPiece; |
+using std::ostream; |
using std::string; |
+using std::vector; |
namespace net { |
namespace test { |
@@ -36,7 +42,40 @@ class QuicCryptoServerConfigPeer { |
QuicCryptoServerConfig* server_config_; |
}; |
-class CryptoServerTest : public ::testing::Test { |
+// Run tests with combinations of |
+// {FLAGS_use_early_return_when_verifying_chlo, |
+// FLAGS_send_quic_crypto_reject_reason}. |
+struct TestParams { |
+ TestParams(bool use_early_return_when_verifying_chlo, |
+ bool send_quic_crypto_reject_reason) |
+ : use_early_return_when_verifying_chlo( |
+ use_early_return_when_verifying_chlo), |
+ send_quic_crypto_reject_reason(send_quic_crypto_reject_reason) { |
+ } |
+ |
+ friend ostream& operator<<(ostream& os, const TestParams& p) { |
+ os << "{ use_early_return_when_verifying_chlo: " |
+ << p.use_early_return_when_verifying_chlo |
+ << " send_quic_crypto_reject_reason: " |
+ << p.send_quic_crypto_reject_reason << " }"; |
+ return os; |
+ } |
+ |
+ bool use_early_return_when_verifying_chlo; |
+ bool send_quic_crypto_reject_reason; |
+}; |
+ |
+// Constructs various test permutations. |
+vector<TestParams> GetTestParams() { |
+ vector<TestParams> params; |
+ params.push_back(TestParams(false, false)); |
+ params.push_back(TestParams(false, true)); |
+ params.push_back(TestParams(true, false)); |
+ params.push_back(TestParams(true, true)); |
+ return params; |
+} |
+ |
+class CryptoServerTest : public ::testing::TestWithParam<TestParams> { |
public: |
CryptoServerTest() |
: rand_(QuicRandom::GetInstance()), |
@@ -46,6 +85,11 @@ class CryptoServerTest : public ::testing::Test { |
supported_versions_ = QuicSupportedVersions(); |
client_version_ = QuicUtils::TagToString( |
QuicVersionToQuicTag(supported_versions_.front())); |
+ |
+ FLAGS_use_early_return_when_verifying_chlo = |
+ GetParam().use_early_return_when_verifying_chlo; |
+ FLAGS_send_quic_crypto_reject_reason = |
+ GetParam().send_quic_crypto_reject_reason; |
} |
virtual void SetUp() { |
@@ -78,6 +122,10 @@ class CryptoServerTest : public ::testing::Test { |
// The message should be rejected because the source-address token is |
// missing. |
ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
StringPiece srct; |
ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct)); |
@@ -219,6 +267,29 @@ class CryptoServerTest : public ::testing::Test { |
return nonce; |
} |
+ void CheckRejectReasons( |
+ const HandshakeFailureReason* expected_handshake_failures, |
+ size_t expected_count) { |
+ const QuicTag* reject_reason_tags; |
wtc
2014/06/19 19:58:42
Nit: also rename this variable "reject_reasons".
ramant (doing other things)
2014/06/20 23:20:47
Fixed in CL: https://codereview.chromium.org/33627
|
+ size_t num_reject_reasons; |
+ QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reason_tags, |
+ &num_reject_reasons); |
+ if (!FLAGS_send_quic_crypto_reject_reason) { |
+ ASSERT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, error_code); |
+ return; |
+ } |
+ ASSERT_EQ(QUIC_NO_ERROR, error_code); |
+ |
+ if (FLAGS_use_early_return_when_verifying_chlo) { |
+ EXPECT_EQ(1u, num_reject_reasons); |
+ } else { |
+ EXPECT_EQ(expected_count, num_reject_reasons); |
+ } |
+ for (size_t i = 0; i < num_reject_reasons; ++i) { |
+ EXPECT_EQ(expected_handshake_failures[i], reject_reason_tags[i]); |
+ } |
+ } |
+ |
protected: |
QuicRandom* const rand_; |
MockClock clock_; |
@@ -237,7 +308,14 @@ class CryptoServerTest : public ::testing::Test { |
scoped_ptr<CryptoHandshakeMessage> server_config_; |
}; |
-TEST_F(CryptoServerTest, BadSNI) { |
+// Run all CryptoServerTest with all combinations of |
+// FLAGS_use_early_return_when_verifying_chlo and |
+// FLAGS_send_quic_crypto_reject_reason. |
+INSTANTIATE_TEST_CASE_P(CryptoServerTests, |
+ CryptoServerTest, |
+ ::testing::ValuesIn(GetTestParams())); |
+ |
+TEST_P(CryptoServerTest, BadSNI) { |
static const char* kBadSNIs[] = { |
"", |
"foo", |
@@ -256,6 +334,10 @@ TEST_F(CryptoServerTest, BadSNI) { |
"SNI", kBadSNIs[i], |
"VER\0", client_version.data(), |
NULL)); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
} |
@@ -281,16 +363,24 @@ TEST_F(CryptoServerTest, DISABLED_DefaultCert) { |
EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); |
EXPECT_NE(0u, cert.size()); |
EXPECT_NE(0u, proof.size()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ CLIENT_NONCE_UNKNOWN_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
-TEST_F(CryptoServerTest, TooSmall) { |
+TEST_P(CryptoServerTest, TooSmall) { |
ShouldFailMentioning("too small", CryptoTestUtils::Message( |
"CHLO", |
"VER\0", client_version_.data(), |
NULL)); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
-TEST_F(CryptoServerTest, BadSourceAddressToken) { |
+TEST_P(CryptoServerTest, BadSourceAddressToken) { |
// Invalid source-address tokens should be ignored. |
static const char* kBadSourceAddressTokens[] = { |
"", |
@@ -305,10 +395,14 @@ TEST_F(CryptoServerTest, BadSourceAddressToken) { |
"STK", kBadSourceAddressTokens[i], |
"VER\0", client_version_.data(), |
NULL)); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
} |
-TEST_F(CryptoServerTest, BadClientNonce) { |
+TEST_P(CryptoServerTest, BadClientNonce) { |
// Invalid nonces should be ignored. |
static const char* kBadNonces[] = { |
"", |
@@ -322,10 +416,14 @@ TEST_F(CryptoServerTest, BadClientNonce) { |
"NONC", kBadNonces[i], |
"VER\0", client_version_.data(), |
NULL)); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
} |
-TEST_F(CryptoServerTest, DowngradeAttack) { |
+TEST_P(CryptoServerTest, DowngradeAttack) { |
if (supported_versions_.size() == 1) { |
// No downgrade attack is possible if the server only supports one version. |
return; |
@@ -339,9 +437,101 @@ TEST_F(CryptoServerTest, DowngradeAttack) { |
"CHLO", |
"VER\0", bad_version.data(), |
NULL)); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_INCHOATE_HELLO_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
-TEST_F(CryptoServerTest, ReplayProtection) { |
+TEST_P(CryptoServerTest, CorruptServerConfig) { |
+ // This tests corrupted server config. |
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
+ "CHLO", |
+ "AEAD", "AESG", |
+ "KEXS", "C255", |
+ "SCID", (string(1, 'X') + scid_hex_).c_str(), |
+ "#004b5453", srct_hex_.c_str(), |
+ "PUBS", pub_hex_.c_str(), |
+ "NONC", nonce_hex_.c_str(), |
+ "VER\0", client_version_.data(), |
+ "$padding", static_cast<int>(kClientHelloMinimumSize), |
+ NULL); |
+ ShouldSucceed(msg); |
+ ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
+} |
+ |
+TEST_P(CryptoServerTest, CorruptSourceAddressToken) { |
+ // This tests corrupted source address token. |
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
+ "CHLO", |
+ "AEAD", "AESG", |
+ "KEXS", "C255", |
+ "SCID", scid_hex_.c_str(), |
+ "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
+ "PUBS", pub_hex_.c_str(), |
+ "NONC", nonce_hex_.c_str(), |
+ "VER\0", client_version_.data(), |
+ "$padding", static_cast<int>(kClientHelloMinimumSize), |
+ NULL); |
+ ShouldSucceed(msg); |
+ ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
+} |
+ |
+TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) { |
+ // This test corrupts client nonce and source address token. |
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
+ "CHLO", |
+ "AEAD", "AESG", |
+ "KEXS", "C255", |
+ "SCID", scid_hex_.c_str(), |
+ "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
+ "PUBS", pub_hex_.c_str(), |
+ "NONC", (string(1, 'X') + nonce_hex_).c_str(), |
+ "VER\0", client_version_.data(), |
+ "$padding", static_cast<int>(kClientHelloMinimumSize), |
+ NULL); |
+ ShouldSucceed(msg); |
+ ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, |
+ CLIENT_NONCE_INVALID_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
+} |
+ |
+TEST_P(CryptoServerTest, CorruptMultipleTags) { |
+ // This test corrupts client nonce, server nonce and source address token. |
+ CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
+ "CHLO", |
+ "AEAD", "AESG", |
+ "KEXS", "C255", |
+ "SCID", scid_hex_.c_str(), |
+ "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
+ "PUBS", pub_hex_.c_str(), |
+ "NONC", (string(1, 'X') + nonce_hex_).c_str(), |
+ "SNO\0", (string(1, 'X') + nonce_hex_).c_str(), |
+ "VER\0", client_version_.data(), |
+ "$padding", static_cast<int>(kClientHelloMinimumSize), |
+ NULL); |
+ ShouldSucceed(msg); |
+ ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, |
+ CLIENT_NONCE_INVALID_FAILURE, |
+ SERVER_NONCE_DECRYPTION_FAILURE, |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
+} |
+ |
+TEST_P(CryptoServerTest, ReplayProtection) { |
// This tests that disabling replay protection works. |
CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
"CHLO", |
@@ -359,6 +549,11 @@ TEST_F(CryptoServerTest, ReplayProtection) { |
// quiescent. |
ASSERT_EQ(kREJ, out_.tag()); |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ CLIENT_NONCE_UNKNOWN_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
+ |
config_.set_replay_protection(false); |
ShouldSucceed(msg); |
@@ -449,11 +644,16 @@ class CryptoServerTestNoConfig : public CryptoServerTest { |
} |
}; |
-TEST_F(CryptoServerTestNoConfig, DontCrash) { |
- ShouldFailMentioning("No config", InchoateClientHello( |
- "CHLO", |
- "VER\0", client_version_.data(), |
- NULL)); |
+TEST_P(CryptoServerTestNoConfig, DontCrash) { |
+ ShouldFailMentioning("No config", InchoateClientHello( |
+ "CHLO", |
+ "VER\0", client_version_.data(), |
+ NULL)); |
+ |
+ const HandshakeFailureReason kRejectReasons[] = { |
+ CLIENT_NONCE_UNKNOWN_FAILURE |
+ }; |
+ CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
} |
class AsyncStrikeServerVerificationTest : public CryptoServerTest { |
@@ -478,7 +678,7 @@ class AsyncStrikeServerVerificationTest : public CryptoServerTest { |
DelayedVerifyStrikeRegisterClient* strike_register_client_; |
}; |
-TEST_F(AsyncStrikeServerVerificationTest, AsyncReplayProtection) { |
+TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) { |
// This tests async validation with a strike register works. |
CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
"CHLO", |