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