[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "net/quic/quic_crypto_server_stream.h" |
| 6 | |
| 7 | #include <map> |
| 8 | #include <vector> |
| 9 | |
| 10 | #include "base/memory/scoped_ptr.h" |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 11 | #include "base/stl_util.h" |
[email protected] | 0bbeb697 | 2013-05-23 04:10:21 | [diff] [blame] | 12 | #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 13 | #include "net/quic/crypto/crypto_framer.h" |
| 14 | #include "net/quic/crypto/crypto_handshake.h" |
| 15 | #include "net/quic/crypto/crypto_protocol.h" |
| 16 | #include "net/quic/crypto/crypto_utils.h" |
[email protected] | 8e01c06 | 2013-10-31 07:35:31 | [diff] [blame] | 17 | #include "net/quic/crypto/quic_crypto_server_config.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 18 | #include "net/quic/crypto/quic_decrypter.h" |
| 19 | #include "net/quic/crypto/quic_encrypter.h" |
[email protected] | b06431078 | 2013-05-30 21:12:17 | [diff] [blame] | 20 | #include "net/quic/crypto/quic_random.h" |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 21 | #include "net/quic/quic_crypto_client_stream.h" |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 22 | #include "net/quic/quic_flags.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 23 | #include "net/quic/quic_protocol.h" |
| 24 | #include "net/quic/quic_session.h" |
| 25 | #include "net/quic/test_tools/crypto_test_utils.h" |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 26 | #include "net/quic/test_tools/delayed_verify_strike_register_client.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 27 | #include "net/quic/test_tools/quic_test_utils.h" |
| 28 | #include "testing/gmock/include/gmock/gmock.h" |
| 29 | #include "testing/gtest/include/gtest/gtest.h" |
| 30 | |
| 31 | namespace net { |
| 32 | class QuicConnection; |
| 33 | class ReliableQuicStream; |
| 34 | } // namespace net |
| 35 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 36 | using std::pair; |
halton.huo | e4e4574 | 2014-12-08 07:55:46 | [diff] [blame] | 37 | using std::string; |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 38 | using testing::_; |
| 39 | |
| 40 | namespace net { |
| 41 | namespace test { |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 42 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 43 | class QuicCryptoServerConfigPeer { |
| 44 | public: |
| 45 | static string GetPrimaryOrbit(const QuicCryptoServerConfig& config) { |
| 46 | base::AutoLock lock(config.configs_lock_); |
rtenneti | be63573 | 2014-10-02 22:51:42 | [diff] [blame] | 47 | CHECK(config.primary_config_.get() != nullptr); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 48 | return string(reinterpret_cast<const char*>(config.primary_config_->orbit), |
| 49 | kOrbitSize); |
| 50 | } |
| 51 | }; |
| 52 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 53 | class QuicCryptoServerStreamPeer { |
| 54 | public: |
| 55 | static bool DoesPeerSupportStatelessRejects( |
| 56 | const CryptoHandshakeMessage& message) { |
| 57 | return net::QuicCryptoServerStream::DoesPeerSupportStatelessRejects( |
| 58 | message); |
| 59 | } |
| 60 | }; |
| 61 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 62 | namespace { |
| 63 | |
[email protected] | e4c3ea6 | 2014-03-15 00:45:14 | [diff] [blame] | 64 | const char kServerHostname[] = "test.example.com"; |
zhongyi | c92bc49 | 2015-09-22 19:14:36 | [diff] [blame] | 65 | const uint16 kServerPort = 443; |
[email protected] | e4c3ea6 | 2014-03-15 00:45:14 | [diff] [blame] | 66 | |
[email protected] | 5d03bbd | 2014-03-07 16:19:16 | [diff] [blame] | 67 | class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 68 | public: |
| 69 | QuicCryptoServerStreamTest() |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 70 | : server_crypto_config_(QuicCryptoServerConfig::TESTING, |
rch | 1fe2eeb | 2015-10-26 14:45:57 | [diff] [blame] | 71 | QuicRandom::GetInstance(), |
| 72 | CryptoTestUtils::ProofSourceForTesting()), |
| 73 | server_id_(kServerHostname, kServerPort, PRIVACY_MODE_DISABLED), |
| 74 | client_crypto_config_(CryptoTestUtils::ProofVerifierForTesting()) { |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 75 | FLAGS_enable_quic_stateless_reject_support = false; |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 76 | server_crypto_config_.set_strike_register_no_startup_period(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 77 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 78 | InitializeServer(); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 79 | |
| 80 | if (AsyncStrikeRegisterVerification()) { |
| 81 | string orbit = |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 82 | QuicCryptoServerConfigPeer::GetPrimaryOrbit(server_crypto_config_); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 83 | strike_register_client_ = new DelayedVerifyStrikeRegisterClient( |
| 84 | 10000, // strike_register_max_entries |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 85 | static_cast<uint32>( |
| 86 | server_connection_->clock()->WallNow().ToUNIXSeconds()), |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 87 | 60, // strike_register_window_secs |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 88 | reinterpret_cast<const uint8*>(orbit.data()), |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 89 | StrikeRegister::NO_STARTUP_PERIOD_NEEDED); |
| 90 | strike_register_client_->StartDelayingVerification(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 91 | server_crypto_config_.SetStrikeRegisterClient(strike_register_client_); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 92 | } |
| 93 | } |
| 94 | |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 95 | ~QuicCryptoServerStreamTest() override { STLDeleteElements(&helpers_); } |
| 96 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 97 | // Initializes the crypto server stream state for testing. May be |
| 98 | // called multiple times. |
| 99 | void InitializeServer() { |
rtenneti | b865eb8 | 2015-06-17 20:21:46 | [diff] [blame] | 100 | TestQuicSpdyServerSession* server_session = nullptr; |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 101 | helpers_.push_back(new MockConnectionHelper); |
| 102 | |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 103 | CreateServerSessionForTest(server_id_, QuicTime::Delta::FromSeconds(100000), |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 104 | helpers_.back(), &server_crypto_config_, |
| 105 | &server_connection_, &server_session); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 106 | CHECK(server_session); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 107 | server_session_.reset(server_session); |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 108 | CryptoTestUtils::FakeServerOptions options; |
| 109 | options.token_binding_enabled = true; |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 110 | CryptoTestUtils::SetupCryptoServerConfigForTest( |
| 111 | server_connection_->clock(), server_connection_->random_generator(), |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 112 | server_session_->config(), &server_crypto_config_, options); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 113 | } |
| 114 | |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 115 | QuicCryptoServerStream* server_stream() { |
| 116 | return server_session_->GetCryptoStream(); |
| 117 | } |
| 118 | |
| 119 | QuicCryptoClientStream* client_stream() { |
| 120 | return client_session_->GetCryptoStream(); |
| 121 | } |
| 122 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 123 | // Initializes a fake client, and all its associated state, for |
| 124 | // testing. May be called multiple times. |
| 125 | void InitializeFakeClient(bool supports_stateless_rejects) { |
rtenneti | b865eb8 | 2015-06-17 20:21:46 | [diff] [blame] | 126 | TestQuicSpdyClientSession* client_session = nullptr; |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 127 | helpers_.push_back(new MockConnectionHelper); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 128 | CreateClientSessionForTest(server_id_, supports_stateless_rejects, |
| 129 | QuicTime::Delta::FromSeconds(100000), |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 130 | helpers_.back(), &client_crypto_config_, |
| 131 | &client_connection_, &client_session); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 132 | CHECK(client_session); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 133 | client_session_.reset(client_session); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 134 | } |
| 135 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 136 | bool AsyncStrikeRegisterVerification() { |
rtenneti | 5ca6eee | 2015-10-15 21:54:30 | [diff] [blame] | 137 | if (server_connection_->version() > QUIC_VERSION_26) { |
| 138 | return false; |
| 139 | } |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 140 | return GetParam(); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | void ConstructHandshakeMessage() { |
| 144 | CryptoFramer framer; |
| 145 | message_data_.reset(framer.ConstructHandshakeMessage(message_)); |
| 146 | } |
| 147 | |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 148 | int CompleteCryptoHandshake() { |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 149 | CHECK(server_connection_); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 150 | CHECK(server_session_ != nullptr); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 151 | return CryptoTestUtils::HandshakeWithFakeClient( |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 152 | helpers_.back(), server_connection_, server_stream(), server_id_, |
| 153 | client_options_); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | // Performs a single round of handshake message-exchange between the |
| 157 | // client and server. |
| 158 | void AdvanceHandshakeWithFakeClient() { |
| 159 | CHECK(server_connection_); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 160 | CHECK(client_session_ != nullptr); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 161 | |
| 162 | EXPECT_CALL(*client_session_, OnProofValid(_)).Times(testing::AnyNumber()); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 163 | client_stream()->CryptoConnect(); |
| 164 | CryptoTestUtils::AdvanceHandshake(client_connection_, client_stream(), 0, |
| 165 | server_connection_, server_stream(), 0); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | protected: |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 169 | // Every connection gets its own MockConnectionHelper, tracked separately |
| 170 | // from the server and client state so their lifetimes persist through the |
| 171 | // whole test. |
| 172 | std::vector<MockConnectionHelper*> helpers_; |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 173 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 174 | // Server state |
| 175 | PacketSavingConnection* server_connection_; |
rtenneti | b865eb8 | 2015-06-17 20:21:46 | [diff] [blame] | 176 | scoped_ptr<TestQuicSpdyServerSession> server_session_; |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 177 | QuicCryptoServerConfig server_crypto_config_; |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 178 | QuicServerId server_id_; |
| 179 | |
| 180 | // Client state |
| 181 | PacketSavingConnection* client_connection_; |
| 182 | QuicCryptoClientConfig client_crypto_config_; |
rtenneti | b865eb8 | 2015-06-17 20:21:46 | [diff] [blame] | 183 | scoped_ptr<TestQuicSpdyClientSession> client_session_; |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 184 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 185 | CryptoHandshakeMessage message_; |
| 186 | scoped_ptr<QuicData> message_data_; |
[email protected] | 89995165 | 2013-05-16 12:52:39 | [diff] [blame] | 187 | CryptoTestUtils::FakeClientOptions client_options_; |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 188 | DelayedVerifyStrikeRegisterClient* strike_register_client_; |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 189 | }; |
| 190 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 191 | INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool()); |
| 192 | |
| 193 | TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) { |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 194 | EXPECT_FALSE(server_stream()->encryption_established()); |
| 195 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 196 | } |
| 197 | |
| 198 | TEST_P(QuicCryptoServerStreamTest, NotInitiallySendingStatelessRejects) { |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 199 | EXPECT_FALSE(server_stream()->UseStatelessRejectsIfPeerSupported()); |
| 200 | EXPECT_FALSE(server_stream()->PeerSupportsStatelessRejects()); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 201 | } |
| 202 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 203 | TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) { |
[email protected] | a57e027 | 2013-04-26 07:31:47 | [diff] [blame] | 204 | // CompleteCryptoHandshake returns the number of client hellos sent. This |
| 205 | // test should send: |
[email protected] | 4887809 | 2013-07-26 14:51:56 | [diff] [blame] | 206 | // * One to get a source-address token and certificates. |
[email protected] | a57e027 | 2013-04-26 07:31:47 | [diff] [blame] | 207 | // * One to complete the handshake. |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 208 | EXPECT_EQ(2, CompleteCryptoHandshake()); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 209 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 210 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 211 | } |
| 212 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 213 | TEST_P(QuicCryptoServerStreamTest, StatelessRejectAfterCHLO) { |
| 214 | ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, |
| 215 | true); |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 216 | InitializeServer(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 217 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 218 | InitializeFakeClient(/* supports_stateless_rejects= */ true); |
| 219 | AdvanceHandshakeWithFakeClient(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 220 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 221 | // Check the server to make the sure the handshake did not succeed. |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 222 | EXPECT_FALSE(server_stream()->encryption_established()); |
| 223 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 224 | |
rtenneti | 85816fdf | 2015-05-25 03:01:10 | [diff] [blame] | 225 | // Check the client state to make sure that it received a server-designated |
| 226 | // connection id. |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 227 | QuicCryptoClientConfig::CachedState* client_state = |
| 228 | client_crypto_config_.LookupOrCreate(server_id_); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 229 | |
rtenneti | 85816fdf | 2015-05-25 03:01:10 | [diff] [blame] | 230 | ASSERT_TRUE(client_state->has_server_nonce()); |
| 231 | ASSERT_FALSE(client_state->GetNextServerNonce().empty()); |
| 232 | ASSERT_FALSE(client_state->has_server_nonce()); |
| 233 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 234 | ASSERT_TRUE(client_state->has_server_designated_connection_id()); |
| 235 | const QuicConnectionId server_designated_connection_id = |
| 236 | client_state->GetNextServerDesignatedConnectionId(); |
| 237 | const QuicConnectionId expected_id = |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 238 | server_connection_->random_generator()->RandUint64(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 239 | EXPECT_EQ(expected_id, server_designated_connection_id); |
| 240 | EXPECT_FALSE(client_state->has_server_designated_connection_id()); |
| 241 | ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); |
ckrasic | ea295fe | 2015-10-31 05:03:27 | [diff] [blame] | 242 | EXPECT_FALSE(server_connection_->connected()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 243 | } |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 244 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 245 | TEST_P(QuicCryptoServerStreamTest, ConnectedAfterStatelessHandshake) { |
| 246 | ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, |
| 247 | true); |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 248 | InitializeServer(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 249 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 250 | InitializeFakeClient(/* supports_stateless_rejects= */ true); |
| 251 | AdvanceHandshakeWithFakeClient(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 252 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 253 | // On the first round, encryption will not be established. |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 254 | EXPECT_FALSE(server_stream()->encryption_established()); |
| 255 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 256 | EXPECT_EQ(1, server_stream()->NumHandshakeMessages()); |
| 257 | EXPECT_EQ(0, server_stream()->NumHandshakeMessagesWithServerNonces()); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 258 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 259 | // Now check the client state. |
| 260 | QuicCryptoClientConfig::CachedState* client_state = |
| 261 | client_crypto_config_.LookupOrCreate(server_id_); |
[email protected] | 2532de1 | 2013-05-09 12:29:33 | [diff] [blame] | 262 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 263 | ASSERT_TRUE(client_state->has_server_designated_connection_id()); |
| 264 | const QuicConnectionId server_designated_connection_id = |
| 265 | client_state->GetNextServerDesignatedConnectionId(); |
| 266 | const QuicConnectionId expected_id = |
rtenneti | 8a4a073 | 2015-10-18 00:45:51 | [diff] [blame] | 267 | server_connection_->random_generator()->RandUint64(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 268 | EXPECT_EQ(expected_id, server_designated_connection_id); |
| 269 | EXPECT_FALSE(client_state->has_server_designated_connection_id()); |
| 270 | ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 271 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 272 | // Now create new client and server streams with the existing config |
| 273 | // and try the handshake again (0-RTT handshake). |
| 274 | InitializeServer(); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 275 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 276 | InitializeFakeClient(/* supports_stateless_rejects= */ true); |
| 277 | |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 278 | client_stream()->CryptoConnect(); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 279 | |
rtenneti | 85816fdf | 2015-05-25 03:01:10 | [diff] [blame] | 280 | // In the stateless case, the second handshake contains a server-nonce, so the |
| 281 | // AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT |
| 282 | // handshake). |
| 283 | AdvanceHandshakeWithFakeClient(); |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 284 | |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 285 | // On the second round, encryption will be established. |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 286 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 287 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 288 | EXPECT_EQ(2, server_stream()->NumHandshakeMessages()); |
| 289 | EXPECT_EQ(1, server_stream()->NumHandshakeMessagesWithServerNonces()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | TEST_P(QuicCryptoServerStreamTest, NoStatelessRejectIfNoClientSupport) { |
| 293 | ValueRestore<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support, |
| 294 | true); |
rch | 99b644c | 2015-11-04 05:25:28 | [diff] [blame] | 295 | InitializeServer(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 296 | |
rtenneti | 85816fdf | 2015-05-25 03:01:10 | [diff] [blame] | 297 | // The server is configured to use stateless rejects, but the client does not |
| 298 | // support it. |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 299 | InitializeFakeClient(/* supports_stateless_rejects= */ false); |
| 300 | AdvanceHandshakeWithFakeClient(); |
| 301 | |
| 302 | // Check the server to make the sure the handshake did not succeed. |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 303 | EXPECT_FALSE(server_stream()->encryption_established()); |
| 304 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 305 | |
| 306 | // Check the client state to make sure that it did not receive a |
| 307 | // server-designated connection id. |
| 308 | QuicCryptoClientConfig::CachedState* client_state = |
| 309 | client_crypto_config_.LookupOrCreate(server_id_); |
| 310 | |
| 311 | ASSERT_FALSE(client_state->has_server_designated_connection_id()); |
| 312 | ASSERT_TRUE(client_state->IsComplete(QuicWallTime::FromUNIXSeconds(0))); |
| 313 | } |
| 314 | |
| 315 | TEST_P(QuicCryptoServerStreamTest, ZeroRTT) { |
| 316 | InitializeFakeClient(/* supports_stateless_rejects= */ false); |
| 317 | |
| 318 | // Do a first handshake in order to prime the client config with the server's |
| 319 | // information. |
| 320 | AdvanceHandshakeWithFakeClient(); |
| 321 | |
| 322 | // Now do another handshake, hopefully in 0-RTT. |
| 323 | DVLOG(1) << "Resetting for 0-RTT handshake attempt"; |
| 324 | InitializeFakeClient(/* supports_stateless_rejects= */ false); |
| 325 | InitializeServer(); |
| 326 | |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 327 | client_stream()->CryptoConnect(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 328 | |
| 329 | if (AsyncStrikeRegisterVerification()) { |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 330 | EXPECT_FALSE(client_stream()->handshake_confirmed()); |
| 331 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 332 | |
rtenneti | 85816fdf | 2015-05-25 03:01:10 | [diff] [blame] | 333 | // Advance the handshake. Expect that the server will be stuck waiting for |
| 334 | // client nonce verification to complete. |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 335 | pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake( |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 336 | client_connection_, client_stream(), 0, server_connection_, |
| 337 | server_stream(), 0); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 338 | EXPECT_EQ(1u, messages_moved.first); |
| 339 | EXPECT_EQ(0u, messages_moved.second); |
| 340 | EXPECT_EQ(1, strike_register_client_->PendingVerifications()); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 341 | EXPECT_FALSE(client_stream()->handshake_confirmed()); |
| 342 | EXPECT_FALSE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 343 | |
| 344 | // The server handshake completes once the nonce verification completes. |
| 345 | strike_register_client_->RunPendingVerifications(); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 346 | EXPECT_FALSE(client_stream()->handshake_confirmed()); |
| 347 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 348 | |
| 349 | messages_moved = CryptoTestUtils::AdvanceHandshake( |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 350 | client_connection_, client_stream(), messages_moved.first, |
| 351 | server_connection_, server_stream(), messages_moved.second); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 352 | EXPECT_EQ(1u, messages_moved.first); |
| 353 | EXPECT_EQ(1u, messages_moved.second); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 354 | EXPECT_TRUE(client_stream()->handshake_confirmed()); |
| 355 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 356 | } else { |
| 357 | CryptoTestUtils::CommunicateHandshakeMessages( |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 358 | client_connection_, client_stream(), server_connection_, |
| 359 | server_stream()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 360 | } |
| 361 | |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 362 | EXPECT_EQ(1, client_stream()->num_sent_client_hellos()); |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 363 | } |
| 364 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 365 | TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) { |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 366 | CompleteCryptoHandshake(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 367 | EXPECT_CALL( |
| 368 | *server_connection_, |
| 369 | SendConnectionClose(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE)); |
[email protected] | ccc66e8a | 2013-03-26 08:26:14 | [diff] [blame] | 370 | message_.set_tag(kCHLO); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 371 | ConstructHandshakeMessage(); |
rch | b27683c | 2015-07-29 23:53:50 | [diff] [blame] | 372 | server_stream()->OnStreamFrame( |
| 373 | QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0, |
| 374 | message_data_->AsStringPiece())); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 375 | } |
| 376 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 377 | TEST_P(QuicCryptoServerStreamTest, BadMessageType) { |
[email protected] | ccc66e8a | 2013-03-26 08:26:14 | [diff] [blame] | 378 | message_.set_tag(kSHLO); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 379 | ConstructHandshakeMessage(); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 380 | EXPECT_CALL(*server_connection_, |
| 381 | SendConnectionClose(QUIC_INVALID_CRYPTO_MESSAGE_TYPE)); |
rch | b27683c | 2015-07-29 23:53:50 | [diff] [blame] | 382 | server_stream()->OnStreamFrame( |
| 383 | QuicStreamFrame(kCryptoStreamId, /*fin=*/false, /*offset=*/0, |
| 384 | message_data_->AsStringPiece())); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 385 | } |
| 386 | |
[email protected] | 691f45a98 | 2013-11-19 10:52:04 | [diff] [blame] | 387 | TEST_P(QuicCryptoServerStreamTest, ChannelID) { |
[email protected] | b06431078 | 2013-05-30 21:12:17 | [diff] [blame] | 388 | client_options_.channel_id_enabled = true; |
[email protected] | 6fc79ea | 2014-07-10 04:30:23 | [diff] [blame] | 389 | client_options_.channel_id_source_async = false; |
| 390 | // CompleteCryptoHandshake verifies |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 391 | // server_stream()->crypto_negotiated_params().channel_id is correct. |
[email protected] | 6fc79ea | 2014-07-10 04:30:23 | [diff] [blame] | 392 | EXPECT_EQ(2, CompleteCryptoHandshake()); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 393 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 394 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
[email protected] | 6fc79ea | 2014-07-10 04:30:23 | [diff] [blame] | 395 | } |
| 396 | |
| 397 | TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) { |
| 398 | client_options_.channel_id_enabled = true; |
| 399 | client_options_.channel_id_source_async = true; |
[email protected] | 38b3fd1 | 2013-06-18 08:19:01 | [diff] [blame] | 400 | // CompleteCryptoHandshake verifies |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 401 | // server_stream()->crypto_negotiated_params().channel_id is correct. |
[email protected] | b06431078 | 2013-05-30 21:12:17 | [diff] [blame] | 402 | EXPECT_EQ(2, CompleteCryptoHandshake()); |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 403 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 404 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
[email protected] | b06431078 | 2013-05-30 21:12:17 | [diff] [blame] | 405 | } |
| 406 | |
rtenneti | dd4bf8f | 2014-09-03 00:45:16 | [diff] [blame] | 407 | TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) { |
| 408 | // An attempt to send a SCUP before completing handshake should fail. |
rtenneti | d39bd76 | 2015-06-12 01:05:52 | [diff] [blame] | 409 | server_stream()->SendServerConfigUpdate(nullptr); |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 410 | EXPECT_EQ(0, server_stream()->NumServerConfigUpdateMessagesSent()); |
rtenneti | a2ea916 | 2015-05-15 19:26:44 | [diff] [blame] | 411 | } |
| 412 | |
| 413 | TEST_P(QuicCryptoServerStreamTest, DoesPeerSupportStatelessRejects) { |
| 414 | ConstructHandshakeMessage(); |
| 415 | QuicConfig stateless_reject_config = DefaultQuicConfigStatelessRejects(); |
| 416 | stateless_reject_config.ToHandshakeMessage(&message_); |
| 417 | EXPECT_TRUE( |
| 418 | QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_)); |
| 419 | |
| 420 | message_.Clear(); |
| 421 | QuicConfig stateful_reject_config = DefaultQuicConfig(); |
| 422 | stateful_reject_config.ToHandshakeMessage(&message_); |
| 423 | EXPECT_FALSE( |
| 424 | QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_)); |
rtenneti | dd4bf8f | 2014-09-03 00:45:16 | [diff] [blame] | 425 | } |
| 426 | |
rjshade | c86dbfa | 2015-11-12 20:16:25 | [diff] [blame] | 427 | TEST_P(QuicCryptoServerStreamTest, TokenBindingNegotiated) { |
| 428 | client_options_.token_binding_enabled = true; |
| 429 | CompleteCryptoHandshake(); |
| 430 | EXPECT_EQ( |
| 431 | kP256, |
| 432 | server_stream()->crypto_negotiated_params().token_binding_key_param); |
| 433 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 434 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
| 435 | } |
| 436 | |
| 437 | TEST_P(QuicCryptoServerStreamTest, NoTokenBindingWithoutClientSupport) { |
| 438 | CompleteCryptoHandshake(); |
| 439 | EXPECT_EQ( |
| 440 | 0u, server_stream()->crypto_negotiated_params().token_binding_key_param); |
| 441 | EXPECT_TRUE(server_stream()->encryption_established()); |
| 442 | EXPECT_TRUE(server_stream()->handshake_confirmed()); |
| 443 | } |
| 444 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 445 | } // namespace |
rch | 1fe2eeb | 2015-10-26 14:45:57 | [diff] [blame] | 446 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 447 | } // namespace test |
| 448 | } // namespace net |