[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" |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 11 | #include "net/quic/crypto/aes_128_gcm_encrypter.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 12 | #include "net/quic/crypto/crypto_framer.h" |
| 13 | #include "net/quic/crypto/crypto_handshake.h" |
| 14 | #include "net/quic/crypto/crypto_protocol.h" |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 15 | #include "net/quic/crypto/crypto_server_config.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 16 | #include "net/quic/crypto/crypto_utils.h" |
| 17 | #include "net/quic/crypto/quic_decrypter.h" |
| 18 | #include "net/quic/crypto/quic_encrypter.h" |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 19 | #include "net/quic/quic_crypto_client_stream.h" |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 20 | #include "net/quic/quic_protocol.h" |
| 21 | #include "net/quic/quic_session.h" |
| 22 | #include "net/quic/test_tools/crypto_test_utils.h" |
| 23 | #include "net/quic/test_tools/quic_test_utils.h" |
| 24 | #include "testing/gmock/include/gmock/gmock.h" |
| 25 | #include "testing/gtest/include/gtest/gtest.h" |
| 26 | |
| 27 | namespace net { |
| 28 | class QuicConnection; |
| 29 | class ReliableQuicStream; |
| 30 | } // namespace net |
| 31 | |
| 32 | using testing::_; |
| 33 | |
| 34 | namespace net { |
| 35 | namespace test { |
| 36 | namespace { |
| 37 | |
| 38 | // TODO(agl): Use rch's utility class for parsing a message when committed. |
| 39 | class TestQuicVisitor : public NoOpFramerVisitor { |
| 40 | public: |
| 41 | TestQuicVisitor() {} |
| 42 | |
| 43 | // NoOpFramerVisitor |
[email protected] | a57e027 | 2013-04-26 07:31:47 | [diff] [blame^] | 44 | virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE { |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 45 | frame_ = frame; |
[email protected] | a57e027 | 2013-04-26 07:31:47 | [diff] [blame^] | 46 | return true; |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | QuicStreamFrame* frame() { return &frame_; } |
| 50 | |
| 51 | private: |
| 52 | QuicStreamFrame frame_; |
| 53 | |
| 54 | DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor); |
| 55 | }; |
| 56 | |
| 57 | class TestSession: public QuicSession { |
| 58 | public: |
| 59 | TestSession(QuicConnection* connection, bool is_server) |
| 60 | : QuicSession(connection, is_server) { |
| 61 | } |
| 62 | |
| 63 | MOCK_METHOD1(CreateIncomingReliableStream, |
| 64 | ReliableQuicStream*(QuicStreamId id)); |
| 65 | MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*()); |
| 66 | MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*()); |
| 67 | }; |
| 68 | |
| 69 | class QuicCryptoServerStreamTest : public ::testing::Test { |
| 70 | public: |
| 71 | QuicCryptoServerStreamTest() |
| 72 | : guid_(1), |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 73 | addr_(ParseIPLiteralToNumber("192.0.2.33", &ip_) ? |
| 74 | ip_ : IPAddressNumber(), 1), |
[email protected] | 14e8106c | 2013-03-14 16:25:33 | [diff] [blame] | 75 | connection_(new PacketSavingConnection(guid_, addr_, true)), |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 76 | session_(connection_, true), |
[email protected] | ef95114d | 2013-04-17 17:57:01 | [diff] [blame] | 77 | crypto_config_(QuicCryptoServerConfig::TESTING), |
| 78 | stream_(config_, crypto_config_, &session_) { |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 79 | // We advance the clock initially because the default time is zero and the |
| 80 | // strike register worries that we've just overflowed a uint32 time. |
| 81 | connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000)); |
| 82 | // TODO(rtenneti): Enable testing of ProofSource. |
| 83 | // crypto_config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting()); |
| 84 | |
[email protected] | ef95114d | 2013-04-17 17:57:01 | [diff] [blame] | 85 | CryptoTestUtils::SetupCryptoServerConfigForTest( |
| 86 | connection_->clock(), connection_->random_generator(), &config_, |
| 87 | &crypto_config_); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | void ConstructHandshakeMessage() { |
| 91 | CryptoFramer framer; |
| 92 | message_data_.reset(framer.ConstructHandshakeMessage(message_)); |
| 93 | } |
| 94 | |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 95 | int CompleteCryptoHandshake() { |
| 96 | return CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | protected: |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 100 | IPAddressNumber ip_; |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 101 | QuicGuid guid_; |
| 102 | IPEndPoint addr_; |
| 103 | PacketSavingConnection* connection_; |
| 104 | TestSession session_; |
[email protected] | ef95114d | 2013-04-17 17:57:01 | [diff] [blame] | 105 | QuicConfig config_; |
| 106 | QuicCryptoServerConfig crypto_config_; |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 107 | QuicCryptoServerStream stream_; |
| 108 | CryptoHandshakeMessage message_; |
| 109 | scoped_ptr<QuicData> message_data_; |
| 110 | }; |
| 111 | |
| 112 | TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) { |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 113 | if (!Aes128GcmEncrypter::IsSupported()) { |
| 114 | LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 115 | return; |
| 116 | } |
| 117 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 118 | EXPECT_FALSE(stream_.handshake_complete()); |
| 119 | } |
| 120 | |
| 121 | TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) { |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 122 | if (!Aes128GcmEncrypter::IsSupported()) { |
| 123 | LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 124 | return; |
| 125 | } |
| 126 | |
[email protected] | a57e027 | 2013-04-26 07:31:47 | [diff] [blame^] | 127 | // CompleteCryptoHandshake returns the number of client hellos sent. This |
| 128 | // test should send: |
| 129 | // * One to get a source-address token. |
| 130 | // * One to complete the handshake. |
| 131 | // TODO(rtenneti): Until we set the crypto_config.SetProofVerifier to enable |
| 132 | // ProofVerifier in CryptoTestUtils::HandshakeWithFakeClient, we would not |
| 133 | // have sent the following client hello. |
| 134 | // * One to get the server's certificates |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 135 | EXPECT_EQ(2, CompleteCryptoHandshake()); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 136 | EXPECT_TRUE(stream_.handshake_complete()); |
| 137 | } |
| 138 | |
[email protected] | fe053f9 | 2013-04-23 20:18:55 | [diff] [blame] | 139 | TEST_F(QuicCryptoServerStreamTest, ZeroRTT) { |
| 140 | if (!Aes128GcmEncrypter::IsSupported()) { |
| 141 | LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 142 | return; |
| 143 | } |
| 144 | |
| 145 | QuicGuid guid(1); |
| 146 | IPAddressNumber ip; |
| 147 | ParseIPLiteralToNumber("127.0.0.1", &ip); |
| 148 | IPEndPoint addr(ip, 0); |
| 149 | PacketSavingConnection* client_conn = |
| 150 | new PacketSavingConnection(guid, addr, false); |
| 151 | PacketSavingConnection* server_conn = |
| 152 | new PacketSavingConnection(guid, addr, false); |
| 153 | client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); |
| 154 | server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000)); |
| 155 | |
| 156 | scoped_ptr<TestSession> client_session(new TestSession(client_conn, true)); |
| 157 | scoped_ptr<TestSession> server_session(new TestSession(server_conn, true)); |
| 158 | |
| 159 | QuicConfig client_config; |
| 160 | QuicCryptoClientConfig client_crypto_config; |
| 161 | |
| 162 | client_config.SetDefaults(); |
| 163 | client_crypto_config.SetDefaults(); |
| 164 | |
| 165 | scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream( |
| 166 | "test.example.com", client_config, client_session.get(), |
| 167 | &client_crypto_config)); |
| 168 | |
| 169 | // Do a first handshake in order to prime the client config with the server's |
| 170 | // information. |
| 171 | CHECK(client->CryptoConnect()); |
| 172 | CHECK_EQ(1u, client_conn->packets_.size()); |
| 173 | |
| 174 | scoped_ptr<QuicCryptoServerStream> server( |
| 175 | new QuicCryptoServerStream(config_, crypto_config_, |
| 176 | server_session.get())); |
| 177 | |
| 178 | CryptoTestUtils::CommunicateHandshakeMessages( |
| 179 | client_conn, client.get(), server_conn, server.get()); |
| 180 | EXPECT_EQ(2, client->num_sent_client_hellos()); |
| 181 | |
| 182 | // Now do another handshake, hopefully in 0-RTT. |
| 183 | LOG(INFO) << "Resetting for 0-RTT handshake attempt"; |
| 184 | |
| 185 | client_conn = new PacketSavingConnection(guid, addr, false); |
| 186 | server_conn = new PacketSavingConnection(guid, addr, false); |
| 187 | // We need to advance time past the strike-server window so that it's |
| 188 | // authoritative in this time span. |
| 189 | client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000)); |
| 190 | server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000)); |
| 191 | |
| 192 | // This causes the client's nonce to be different and thus stops the |
| 193 | // strike-register from rejecting the repeated nonce. |
| 194 | client_conn->random_generator()->Reseed(NULL, 0); |
| 195 | client_session.reset(new TestSession(client_conn, true)); |
| 196 | server_session.reset(new TestSession(server_conn, true)); |
| 197 | client.reset(new QuicCryptoClientStream( |
| 198 | "test.example.com", client_config, client_session.get(), |
| 199 | &client_crypto_config)); |
| 200 | server.reset(new QuicCryptoServerStream(config_, crypto_config_, |
| 201 | server_session.get())); |
| 202 | |
| 203 | CHECK(client->CryptoConnect()); |
| 204 | |
| 205 | CryptoTestUtils::CommunicateHandshakeMessages( |
| 206 | client_conn, client.get(), server_conn, server.get()); |
| 207 | EXPECT_EQ(1, client->num_sent_client_hellos()); |
| 208 | } |
| 209 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 210 | TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) { |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 211 | if (!Aes128GcmEncrypter::IsSupported()) { |
| 212 | LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 213 | return; |
| 214 | } |
| 215 | |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 216 | CompleteCryptoHandshake(); |
| 217 | EXPECT_CALL(*connection_, SendConnectionClose( |
| 218 | QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE)); |
[email protected] | ccc66e8a | 2013-03-26 08:26:14 | [diff] [blame] | 219 | message_.set_tag(kCHLO); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 220 | ConstructHandshakeMessage(); |
| 221 | stream_.ProcessData(message_data_->data(), message_data_->length()); |
| 222 | } |
| 223 | |
| 224 | TEST_F(QuicCryptoServerStreamTest, BadMessageType) { |
[email protected] | 74bda14 | 2013-03-31 02:49:11 | [diff] [blame] | 225 | if (!Aes128GcmEncrypter::IsSupported()) { |
| 226 | LOG(INFO) << "AES GCM not supported. Test skipped."; |
| 227 | return; |
| 228 | } |
| 229 | |
[email protected] | ccc66e8a | 2013-03-26 08:26:14 | [diff] [blame] | 230 | message_.set_tag(kSHLO); |
[email protected] | 72818ea | 2013-03-13 03:23:57 | [diff] [blame] | 231 | ConstructHandshakeMessage(); |
| 232 | EXPECT_CALL(*connection_, SendConnectionClose( |
| 233 | QUIC_INVALID_CRYPTO_MESSAGE_TYPE)); |
| 234 | stream_.ProcessData(message_data_->data(), message_data_->length()); |
| 235 | } |
| 236 | |
| 237 | } // namespace |
| 238 | } // namespace test |
| 239 | } // namespace net |