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" 11 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 12 #include "net/quic/crypto/crypto_framer.h" 13 #include "net/quic/crypto/crypto_handshake.h" 14 #include "net/quic/crypto/crypto_protocol.h" 15 #include "net/quic/crypto/crypto_utils.h" 16 #include "net/quic/crypto/quic_crypto_server_config.h" 17 #include "net/quic/crypto/quic_decrypter.h" 18 #include "net/quic/crypto/quic_encrypter.h" 19 #include "net/quic/crypto/quic_random.h" 20 #include "net/quic/quic_crypto_client_stream.h" 21 #include "net/quic/quic_protocol.h" 22 #include "net/quic/quic_session.h" 23 #include "net/quic/test_tools/crypto_test_utils.h" 24 #include "net/quic/test_tools/delayed_verify_strike_register_client.h" 25 #include "net/quic/test_tools/quic_test_utils.h" 26 #include "testing/gmock/include/gmock/gmock.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 namespace net { 30 class QuicConnection; 31 class ReliableQuicStream; 32 } // namespace net 33 34 using std::pair; 35 using testing::_; 36 37 namespace net { 38 namespace test { 39 40 class QuicCryptoServerConfigPeer { 41 public: 42 static string GetPrimaryOrbit(const QuicCryptoServerConfig& config) { 43 base::AutoLock lock(config.configs_lock_); 44 CHECK(config.primary_config_.get() != NULL); 45 return string(reinterpret_cast<const char*>(config.primary_config_->orbit), 46 kOrbitSize); 47 } 48 }; 49 50 namespace { 51 52 const char kServerHostname[] = "test.example.com"; 53 const uint16 kServerPort = 80; 54 55 class QuicCryptoServerStreamTest : public ::testing::TestWithParam<bool> { 56 public: 57 QuicCryptoServerStreamTest() 58 : connection_(new PacketSavingConnection(true)), 59 session_(connection_, DefaultQuicConfig()), 60 crypto_config_(QuicCryptoServerConfig::TESTING, 61 QuicRandom::GetInstance()), 62 stream_(crypto_config_, &session_), 63 strike_register_client_(NULL) { 64 config_.SetDefaults(); 65 session_.config()->SetDefaults(); 66 session_.SetCryptoStream(&stream_); 67 // We advance the clock initially because the default time is zero and the 68 // strike register worries that we've just overflowed a uint32 time. 69 connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000)); 70 // TODO(wtc): replace this with ProofSourceForTesting() when Chromium has 71 // a working ProofSourceForTesting(). 72 crypto_config_.SetProofSource(CryptoTestUtils::FakeProofSourceForTesting()); 73 crypto_config_.set_strike_register_no_startup_period(); 74 75 CryptoTestUtils::SetupCryptoServerConfigForTest( 76 connection_->clock(), connection_->random_generator(), 77 session_.config(), &crypto_config_); 78 79 if (AsyncStrikeRegisterVerification()) { 80 string orbit = 81 QuicCryptoServerConfigPeer::GetPrimaryOrbit(crypto_config_); 82 strike_register_client_ = new DelayedVerifyStrikeRegisterClient( 83 10000, // strike_register_max_entries 84 static_cast<uint32>(connection_->clock()->WallNow().ToUNIXSeconds()), 85 60, // strike_register_window_secs 86 reinterpret_cast<const uint8 *>(orbit.data()), 87 StrikeRegister::NO_STARTUP_PERIOD_NEEDED); 88 strike_register_client_->StartDelayingVerification(); 89 crypto_config_.SetStrikeRegisterClient(strike_register_client_); 90 } 91 } 92 93 bool AsyncStrikeRegisterVerification() { 94 return GetParam(); 95 } 96 97 void ConstructHandshakeMessage() { 98 CryptoFramer framer; 99 message_data_.reset(framer.ConstructHandshakeMessage(message_)); 100 } 101 102 int CompleteCryptoHandshake() { 103 return CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_, 104 client_options_); 105 } 106 107 protected: 108 PacketSavingConnection* connection_; 109 TestClientSession session_; 110 QuicConfig config_; 111 QuicCryptoServerConfig crypto_config_; 112 QuicCryptoServerStream stream_; 113 CryptoHandshakeMessage message_; 114 scoped_ptr<QuicData> message_data_; 115 CryptoTestUtils::FakeClientOptions client_options_; 116 DelayedVerifyStrikeRegisterClient* strike_register_client_; 117 }; 118 119 INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool()); 120 121 TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) { 122 EXPECT_FALSE(stream_.encryption_established()); 123 EXPECT_FALSE(stream_.handshake_confirmed()); 124 } 125 126 TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) { 127 // CompleteCryptoHandshake returns the number of client hellos sent. This 128 // test should send: 129 // * One to get a source-address token and certificates. 130 // * One to complete the handshake. 131 EXPECT_EQ(2, CompleteCryptoHandshake()); 132 EXPECT_TRUE(stream_.encryption_established()); 133 EXPECT_TRUE(stream_.handshake_confirmed()); 134 EXPECT_EQ(1, stream_.num_server_config_update_messages_sent()); 135 } 136 137 TEST_P(QuicCryptoServerStreamTest, ZeroRTT) { 138 PacketSavingConnection* client_conn = new PacketSavingConnection(false); 139 PacketSavingConnection* server_conn = new PacketSavingConnection(false); 140 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000)); 141 server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000)); 142 143 QuicConfig client_config; 144 client_config.SetDefaults(); 145 scoped_ptr<TestClientSession> client_session( 146 new TestClientSession(client_conn, client_config)); 147 QuicCryptoClientConfig client_crypto_config; 148 client_crypto_config.SetDefaults(); 149 150 QuicServerId server_id(kServerHostname, kServerPort, false, 151 PRIVACY_MODE_DISABLED); 152 scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream( 153 server_id, client_session.get(), NULL, &client_crypto_config)); 154 client_session->SetCryptoStream(client.get()); 155 156 // Do a first handshake in order to prime the client config with the server's 157 // information. 158 CHECK(client->CryptoConnect()); 159 CHECK_EQ(1u, client_conn->packets_.size()); 160 161 scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_)); 162 scoped_ptr<QuicCryptoServerStream> server( 163 new QuicCryptoServerStream(crypto_config_, server_session.get())); 164 server_session->SetCryptoStream(server.get()); 165 166 CryptoTestUtils::CommunicateHandshakeMessages( 167 client_conn, client.get(), server_conn, server.get()); 168 EXPECT_EQ(2, client->num_sent_client_hellos()); 169 170 // Now do another handshake, hopefully in 0-RTT. 171 LOG(INFO) << "Resetting for 0-RTT handshake attempt"; 172 173 client_conn = new PacketSavingConnection(false); 174 server_conn = new PacketSavingConnection(false); 175 // We need to advance time past the strike-server window so that it's 176 // authoritative in this time span. 177 client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000)); 178 server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000)); 179 180 // This causes the client's nonce to be different and thus stops the 181 // strike-register from rejecting the repeated nonce. 182 reinterpret_cast<MockRandom*>(client_conn->random_generator())->ChangeValue(); 183 client_session.reset(new TestClientSession(client_conn, client_config)); 184 server_session.reset(new TestSession(server_conn, config_)); 185 client.reset(new QuicCryptoClientStream( 186 server_id, client_session.get(), NULL, &client_crypto_config)); 187 client_session->SetCryptoStream(client.get()); 188 189 server.reset(new QuicCryptoServerStream(crypto_config_, 190 server_session.get())); 191 server_session->SetCryptoStream(server.get()); 192 193 CHECK(client->CryptoConnect()); 194 195 if (AsyncStrikeRegisterVerification()) { 196 EXPECT_FALSE(client->handshake_confirmed()); 197 EXPECT_FALSE(server->handshake_confirmed()); 198 199 // Advance the handshake. Expect that the server will be stuck 200 // waiting for client nonce verification to complete. 201 pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake( 202 client_conn, client.get(), 0, server_conn, server.get(), 0); 203 EXPECT_EQ(1u, messages_moved.first); 204 EXPECT_EQ(0u, messages_moved.second); 205 EXPECT_EQ(1, strike_register_client_->PendingVerifications()); 206 EXPECT_FALSE(client->handshake_confirmed()); 207 EXPECT_FALSE(server->handshake_confirmed()); 208 209 // The server handshake completes once the nonce verification completes. 210 strike_register_client_->RunPendingVerifications(); 211 EXPECT_FALSE(client->handshake_confirmed()); 212 EXPECT_TRUE(server->handshake_confirmed()); 213 214 messages_moved = CryptoTestUtils::AdvanceHandshake( 215 client_conn, client.get(), messages_moved.first, 216 server_conn, server.get(), messages_moved.second); 217 EXPECT_EQ(1u, messages_moved.first); 218 EXPECT_EQ(1u, messages_moved.second); 219 EXPECT_TRUE(client->handshake_confirmed()); 220 EXPECT_TRUE(server->handshake_confirmed()); 221 } else { 222 CryptoTestUtils::CommunicateHandshakeMessages( 223 client_conn, client.get(), server_conn, server.get()); 224 } 225 226 EXPECT_EQ(1, client->num_sent_client_hellos()); 227 EXPECT_EQ(1, server->num_server_config_update_messages_sent()); 228 } 229 230 TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) { 231 CompleteCryptoHandshake(); 232 EXPECT_CALL(*connection_, SendConnectionClose( 233 QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE)); 234 message_.set_tag(kCHLO); 235 ConstructHandshakeMessage(); 236 stream_.ProcessRawData(message_data_->data(), message_data_->length()); 237 } 238 239 TEST_P(QuicCryptoServerStreamTest, BadMessageType) { 240 message_.set_tag(kSHLO); 241 ConstructHandshakeMessage(); 242 EXPECT_CALL(*connection_, SendConnectionClose( 243 QUIC_INVALID_CRYPTO_MESSAGE_TYPE)); 244 stream_.ProcessRawData(message_data_->data(), message_data_->length()); 245 } 246 247 TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) { 248 crypto_config_.SetProofSource(NULL); 249 client_options_.dont_verify_certs = true; 250 251 // Only 2 client hellos need to be sent in the no-certs case: one to get the 252 // source-address token and the second to finish. 253 EXPECT_EQ(2, CompleteCryptoHandshake()); 254 EXPECT_TRUE(stream_.encryption_established()); 255 EXPECT_TRUE(stream_.handshake_confirmed()); 256 } 257 258 TEST_P(QuicCryptoServerStreamTest, ChannelID) { 259 client_options_.channel_id_enabled = true; 260 client_options_.channel_id_source_async = false; 261 // CompleteCryptoHandshake verifies 262 // stream_.crypto_negotiated_params().channel_id is correct. 263 EXPECT_EQ(2, CompleteCryptoHandshake()); 264 EXPECT_TRUE(stream_.encryption_established()); 265 EXPECT_TRUE(stream_.handshake_confirmed()); 266 } 267 268 TEST_P(QuicCryptoServerStreamTest, ChannelIDAsync) { 269 client_options_.channel_id_enabled = true; 270 client_options_.channel_id_source_async = true; 271 // CompleteCryptoHandshake verifies 272 // stream_.crypto_negotiated_params().channel_id is correct. 273 EXPECT_EQ(2, CompleteCryptoHandshake()); 274 EXPECT_TRUE(stream_.encryption_established()); 275 EXPECT_TRUE(stream_.handshake_confirmed()); 276 } 277 278 TEST_P(QuicCryptoServerStreamTest, OnlySendSCUPAfterHandshakeComplete) { 279 // An attempt to send a SCUP before completing handshake should fail. 280 stream_.SendServerConfigUpdate(NULL); 281 EXPECT_EQ(0, stream_.num_server_config_update_messages_sent()); 282 } 283 284 } // namespace 285 } // namespace test 286 } // namespace net 287