summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-09 12:29:33 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-09 12:29:33 +0000
commit2532de12bd5d83ef4de1a50837709086c3a25ca0 (patch)
treea9a8cb66410b96632e1d270ed3420e35131c4ff0
parentda29a20567c029ec25cd7ab7a167532ffd7c0010 (diff)
downloadchromium_src-2532de12bd5d83ef4de1a50837709086c3a25ca0.zip
chromium_src-2532de12bd5d83ef4de1a50837709086c3a25ca0.tar.gz
chromium_src-2532de12bd5d83ef4de1a50837709086c3a25ca0.tar.bz2
Land Recent QUIC changes
QUIC: use QuicTag/QuicTagVector throughout. crypto_protocol.h has had CryptoTag and CryptoTagVector. Then quic_protocol.h got QuicVersionTag and QuicVersionTagList because it didn't want to depend on crypto_protocol.h This change uses a single QuicTag and QuicTagVector throughout the code, including the crypto code. Merge internal change: 45230337 QUIC: move random values to the beginning and the certifiate chain to the end. jar suggested that the certificate chain should have a tag that will cause it to be sorted at the end of any handshake messages because it's likely to be large and the client might be able to get everything that it needs from the small values at the beginning. Likewise he argued that tags with random values should be towards the beginning of the message because the server mightn't hold state for a rejected client hello and therefore the client may have issues reassembling the rejection message in the event that it sent two client hellos. This change tweaks the tag values to achieve that ordering. Merge internal change: 45228375 Removing obselete TODOs Merge internal change: 45219448 Use the idle connection state timeout negotiated in crypto handshake. Merge internal change: 45176251 QUIC: address wtc's followup comments on cl/44792710. This change addresses wtc's comments on cl/44792710. There should be no semantic differences. Merge internal change: 45051718 QUIC - Fixed HasRetransmittableData enum to have the correct values. Fixed comments from rch Merge internal change: 45143336 Change the QUIC version number to a new value which is amenable to frequent i ncrementing. Merge internal change: 45111687 QUIC: run clang-format over .../quic/crypto. I ran: for x in $(ls -1 *.cc *.h) ; do clang-format -i $x -style Google; echo $x; done And then used git add -p to manually review the changes. In the cases where I didn't care, I went with what the tool produced. Merge internal change: 45053104 QUIC: address wtc's followup comments on cl/44792710. This change addresses wtc's comments on cl/44792710. There should be no semantic differences. Merge internal change: 45051718 Minor cleanup of ReliableQuicStreamTest output. Also change MockConnection to create a NiceMock version of the Helper to avoid annoying GMock messages. Merge internal change: 45010564 QUIC: partly deflake EndToEndTest.LargePost Since cl/44690884, some runs of this test have timed out. Everything appears to be working ok, just not fast enough. It's possible that the additional packet `losses' caused by decryption failures when we lose the client hello are convincing the congestion control that the loss rate is very high. However, since I have a trip to NIST this week, this change removes the flake by reverting a tiny part of cl/44690884. Sadly there is another flake in the test which this CL doesn't fix. Details in the bug. Merge internal change: 45008247 Fix a bug in QUIC header compression handling where buffered headers were not handled properly. Merge internal change: 45007035 QUIC: tiny test cleanup. wtc suggested this in a post-submission comment. Merge internal change: 44898354 QUIC: add expiry to server configs and have the GFE generate random server configs. Server configs need an expiry because they are effectively certificates. This change has the GFE generate server configs with the same expiry as the primary certificate. It also switches the GFE to generating random server configs at startup. (Random in the sense of random keys and orbit values.) Originally I wanted to have the server config persist over a restart and so derived them, deterministically, from the primary, private key with a todo to diversify the orbit. However, since we don't have any shared strike registers at the moment that doesn't seem to be worth the complexity. Also, figuring out how to diversify the orbit value in a per-GFE sense is really messy (include the hostname? include the port? Which port?). So this CL goes for simple and secure. Merge internal change: 44898035 QUIC: use 24-bit lengths for public values. If ideal lattices don't work out then we may end up with Diffie-Hellman public values that are larger than 16-bits. (Hopefully not, but you never know.) Merge internal change: 44897191 QUIC: have the client echo the server's nonce. This reflects a comment from wtc previously that this would be a good idea. Merge internal change: 44896699 QUIC: steps 12 and 13, forward secure mode. Merge internal change: 44896363 Fix LOG(DFATAL) when client sends invalid stream frame with fin. Merge internal change: 44871764 R=rch@chromium.org Review URL: https://chromiumcodereview.appspot.com/14816006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@199190 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/net.gyp2
-rw-r--r--net/quic/congestion_control/fix_rate_sender.cc2
-rw-r--r--net/quic/congestion_control/fix_rate_test.cc16
-rw-r--r--net/quic/congestion_control/quic_congestion_manager_test.cc11
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender.cc5
-rw-r--r--net/quic/congestion_control/tcp_cubic_sender_test.cc22
-rw-r--r--net/quic/crypto/aes_128_gcm_decrypter_openssl.cc38
-rw-r--r--net/quic/crypto/aes_128_gcm_decrypter_test.cc29
-rw-r--r--net/quic/crypto/aes_128_gcm_encrypter_openssl.cc33
-rw-r--r--net/quic/crypto/aes_128_gcm_encrypter_test.cc33
-rw-r--r--net/quic/crypto/cert_compressor.cc50
-rw-r--r--net/quic/crypto/cert_compressor.h12
-rw-r--r--net/quic/crypto/cert_compressor_test.cc36
-rw-r--r--net/quic/crypto/common_cert_set.cc22
-rw-r--r--net/quic/crypto/common_cert_set.h28
-rw-r--r--net/quic/crypto/common_cert_set_1_50.inc3
-rw-r--r--net/quic/crypto/common_cert_set_51_100.inc3
-rw-r--r--net/quic/crypto/common_cert_set_test.cc16
-rw-r--r--net/quic/crypto/crypto_framer.cc37
-rw-r--r--net/quic/crypto/crypto_framer.h14
-rw-r--r--net/quic/crypto/crypto_framer_test.cc22
-rw-r--r--net/quic/crypto/crypto_handshake.cc295
-rw-r--r--net/quic/crypto/crypto_handshake.h112
-rw-r--r--net/quic/crypto/crypto_handshake_test.cc15
-rw-r--r--net/quic/crypto/crypto_protocol.h95
-rw-r--r--net/quic/crypto/crypto_server_config.cc255
-rw-r--r--net/quic/crypto/crypto_server_config.h46
-rw-r--r--net/quic/crypto/crypto_server_config_protobuf.h6
-rw-r--r--net/quic/crypto/crypto_utils.cc55
-rw-r--r--net/quic/crypto/crypto_utils.h28
-rw-r--r--net/quic/crypto/curve25519_key_exchange.cc20
-rw-r--r--net/quic/crypto/curve25519_key_exchange.h3
-rw-r--r--net/quic/crypto/curve25519_key_exchange_test.cc7
-rw-r--r--net/quic/crypto/ephemeral_key_source.h42
-rw-r--r--net/quic/crypto/key_exchange.h11
-rw-r--r--net/quic/crypto/null_decrypter.cc12
-rw-r--r--net/quic/crypto/null_decrypter_test.cc24
-rw-r--r--net/quic/crypto/null_encrypter.cc20
-rw-r--r--net/quic/crypto/null_encrypter_test.cc4
-rw-r--r--net/quic/crypto/p256_key_exchange.h3
-rw-r--r--net/quic/crypto/p256_key_exchange_nss.cc15
-rw-r--r--net/quic/crypto/p256_key_exchange_openssl.cc42
-rw-r--r--net/quic/crypto/quic_decrypter.cc2
-rw-r--r--net/quic/crypto/quic_decrypter.h2
-rw-r--r--net/quic/crypto/quic_encrypter.cc2
-rw-r--r--net/quic/crypto/quic_encrypter.h2
-rw-r--r--net/quic/crypto/quic_random.cc4
-rw-r--r--net/quic/crypto/scoped_evp_cipher_ctx.h4
-rw-r--r--net/quic/crypto/strike_register.cc34
-rw-r--r--net/quic/crypto/strike_register_test.cc18
-rw-r--r--net/quic/quic_client_session_test.cc2
-rw-r--r--net/quic/quic_clock.cc5
-rw-r--r--net/quic/quic_clock.h7
-rw-r--r--net/quic/quic_clock_test.cc19
-rw-r--r--net/quic/quic_config.cc4
-rw-r--r--net/quic/quic_config.h9
-rw-r--r--net/quic/quic_connection.cc20
-rw-r--r--net/quic/quic_connection.h25
-rw-r--r--net/quic/quic_connection_helper_test.cc8
-rw-r--r--net/quic/quic_connection_logger.cc3
-rw-r--r--net/quic/quic_connection_logger.h3
-rw-r--r--net/quic/quic_connection_test.cc2
-rw-r--r--net/quic/quic_crypto_client_stream.cc78
-rw-r--r--net/quic/quic_crypto_client_stream.h6
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc19
-rw-r--r--net/quic/quic_crypto_server_stream.cc80
-rw-r--r--net/quic/quic_crypto_server_stream.h6
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc26
-rw-r--r--net/quic/quic_crypto_stream.cc10
-rw-r--r--net/quic/quic_crypto_stream.h7
-rw-r--r--net/quic/quic_crypto_stream_test.cc6
-rw-r--r--net/quic/quic_framer.cc28
-rw-r--r--net/quic/quic_framer.h18
-rw-r--r--net/quic/quic_framer_test.cc15
-rw-r--r--net/quic/quic_packet_creator.cc2
-rw-r--r--net/quic/quic_packet_creator.h2
-rw-r--r--net/quic/quic_packet_creator_test.cc2
-rw-r--r--net/quic/quic_protocol.h29
-rw-r--r--net/quic/quic_protocol_test.cc10
-rw-r--r--net/quic/quic_session.cc4
-rw-r--r--net/quic/quic_time.cc52
-rw-r--r--net/quic/quic_time.h37
-rw-r--r--net/quic/quic_utils.cc2
-rw-r--r--net/quic/reliable_quic_stream.cc49
-rw-r--r--net/quic/reliable_quic_stream.h4
-rw-r--r--net/quic/reliable_quic_stream_test.cc28
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc109
-rw-r--r--net/quic/test_tools/crypto_test_utils.h12
-rw-r--r--net/quic/test_tools/mock_clock.cc5
-rw-r--r--net/quic/test_tools/mock_clock.h2
-rw-r--r--net/quic/test_tools/quic_connection_peer.cc6
-rw-r--r--net/quic/test_tools/quic_connection_peer.h3
-rw-r--r--net/quic/test_tools/quic_framer_peer.cc2
-rw-r--r--net/quic/test_tools/quic_framer_peer.h2
-rw-r--r--net/quic/test_tools/quic_test_utils.cc28
-rw-r--r--net/quic/test_tools/quic_test_utils.h27
-rw-r--r--net/quic/test_tools/simple_quic_framer.cc10
-rw-r--r--net/quic/test_tools/simple_quic_framer.h1
-rw-r--r--net/tools/quic/end_to_end_test.cc15
-rw-r--r--net/tools/quic/quic_client.cc18
-rw-r--r--net/tools/quic/quic_client.h14
-rw-r--r--net/tools/quic/quic_epoll_clock.cc5
-rw-r--r--net/tools/quic/quic_epoll_clock.h7
-rw-r--r--net/tools/quic/quic_epoll_clock_test.cc13
-rw-r--r--net/tools/quic/quic_server.cc5
-rw-r--r--net/tools/quic/quic_spdy_client_stream.cc2
-rw-r--r--net/tools/quic/quic_spdy_server_stream.cc4
-rw-r--r--net/tools/quic/quic_spdy_server_stream_test.cc70
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.cc2
-rw-r--r--net/tools/quic/quic_time_wait_list_manager.h3
-rw-r--r--net/tools/quic/test_tools/quic_test_client.cc13
-rw-r--r--net/tools/quic/test_tools/quic_test_client.h4
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.cc18
-rw-r--r--net/tools/quic/test_tools/quic_test_utils.h23
114 files changed, 1620 insertions, 1042 deletions
diff --git a/net/net.gyp b/net/net.gyp
index 1fef42c..8c6081a 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -729,6 +729,7 @@
'quic/crypto/crypto_utils.h',
'quic/crypto/curve25519_key_exchange.cc',
'quic/crypto/curve25519_key_exchange.h',
+ 'quic/crypto/ephemeral_key_source.h',
'quic/crypto/key_exchange.h',
'quic/crypto/null_decrypter.cc',
'quic/crypto/null_decrypter.h',
@@ -2679,6 +2680,7 @@
'tools/quic/quic_epoll_connection_helper_test.cc',
'tools/quic/quic_reliable_client_stream_test.cc',
'tools/quic/quic_reliable_server_stream_test.cc',
+ 'tools/quic/quic_spdy_server_stream_test.cc',
'tools/quic/test_tools/http_message_test_utils.cc',
'tools/quic/test_tools/http_message_test_utils.h',
'tools/quic/test_tools/mock_epoll_server.cc',
diff --git a/net/quic/congestion_control/fix_rate_sender.cc b/net/quic/congestion_control/fix_rate_sender.cc
index 2ccbc8b..4e3f635 100644
--- a/net/quic/congestion_control/fix_rate_sender.cc
+++ b/net/quic/congestion_control/fix_rate_sender.cc
@@ -61,7 +61,7 @@ void FixRateSender::SentPacket(QuicTime sent_time,
Retransmission is_retransmission) {
fix_rate_leaky_bucket_.Add(sent_time, bytes);
paced_sender_.SentPacket(sent_time, bytes);
- if (!is_retransmission) {
+ if (is_retransmission == NOT_RETRANSMISSION) {
data_in_flight_ += bytes;
}
}
diff --git a/net/quic/congestion_control/fix_rate_test.cc b/net/quic/congestion_control/fix_rate_test.cc
index 4969966..f48dc45 100644
--- a/net/quic/congestion_control/fix_rate_test.cc
+++ b/net/quic/congestion_control/fix_rate_test.cc
@@ -64,23 +64,23 @@ TEST_F(FixRateTest, SenderAPI) {
unused_bandwidth_, unused_packet_map_);
EXPECT_EQ(300000, sender_->BandwidthEstimate().ToBytesPerSecond());
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
sender_->SentPacket(clock_.Now(), 1, kMaxPacketSize, NOT_RETRANSMISSION);
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
sender_->SentPacket(clock_.Now(), 2, kMaxPacketSize, NOT_RETRANSMISSION);
sender_->SentPacket(clock_.Now(), 3, 600, NOT_RETRANSMISSION);
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10), sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
EXPECT_EQ(QuicTime::Delta::Infinite(), sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
sender_->OnIncomingAck(1, kMaxPacketSize, rtt_);
sender_->OnIncomingAck(2, kMaxPacketSize, rtt_);
sender_->OnIncomingAck(3, 600, rtt_);
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
}
TEST_F(FixRateTest, FixRatePacing) {
@@ -96,15 +96,15 @@ TEST_F(FixRateTest, FixRatePacing) {
QuicPacketSequenceNumber sequence_number = 0;
for (int i = 0; i < num_packets; i += 2) {
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
sender_->SentPacket(clock_.Now(), sequence_number++, packet_size,
NOT_RETRANSMISSION);
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
sender_->SentPacket(clock_.Now(), sequence_number++, packet_size,
NOT_RETRANSMISSION);
QuicTime::Delta advance_time = sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
clock_.AdvanceTime(advance_time);
sender_->OnIncomingAck(sequence_number - 1, packet_size, rtt_);
sender_->OnIncomingAck(sequence_number - 2, packet_size, rtt_);
diff --git a/net/quic/congestion_control/quic_congestion_manager_test.cc b/net/quic/congestion_control/quic_congestion_manager_test.cc
index fb6d2e8..8b8f473 100644
--- a/net/quic/congestion_control/quic_congestion_manager_test.cc
+++ b/net/quic/congestion_control/quic_congestion_manager_test.cc
@@ -39,6 +39,9 @@ class QuicCongestionManagerTest : public ::testing::Test {
void SetUpCongestionType(CongestionFeedbackType congestion_type) {
manager_.reset(new QuicCongestionManagerPeer(&clock_, congestion_type));
}
+
+ static const HasRetransmittableData kIgnored = HAS_RETRANSMITTABLE_DATA;
+
MockClock clock_;
scoped_ptr<QuicCongestionManagerPeer> manager_;
};
@@ -55,10 +58,10 @@ TEST_F(QuicCongestionManagerTest, Bandwidth) {
for (int i = 1; i <= 100; ++i) {
QuicTime::Delta advance_time = manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ clock_.Now(), NOT_RETRANSMISSION, kIgnored);
clock_.AdvanceTime(advance_time);
EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, kIgnored).IsZero());
manager_->SentPacket(i, clock_.Now(), 1000, NOT_RETRANSMISSION);
// Ack the packet we sent.
ack.received_info.largest_observed = i;
@@ -83,7 +86,7 @@ TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
++sequence_number) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, kIgnored).IsZero());
manager_->SentPacket(
sequence_number, clock_.Now(), 1000, NOT_RETRANSMISSION);
// Ack the packet we sent.
@@ -101,7 +104,7 @@ TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
EXPECT_TRUE(manager_->SentBandwidth(clock_.Now()).IsZero());
for (int i = 1; i <= 150; ++i) {
EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, kIgnored).IsZero());
manager_->SentPacket(i + 100, clock_.Now(), 1000, NOT_RETRANSMISSION);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
// Ack the packet we sent.
diff --git a/net/quic/congestion_control/tcp_cubic_sender.cc b/net/quic/congestion_control/tcp_cubic_sender.cc
index 4bed7ed..78bd7d9 100644
--- a/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -87,7 +87,7 @@ void TcpCubicSender::SentPacket(QuicTime /*sent_time*/,
QuicByteCount bytes,
Retransmission is_retransmission) {
bytes_in_flight_ += bytes;
- if (!is_retransmission && update_end_sequence_number_) {
+ if (is_retransmission == NOT_RETRANSMISSION && update_end_sequence_number_) {
end_sequence_number_ = sequence_number;
if (AvailableCongestionWindow() == 0) {
update_end_sequence_number_ = false;
@@ -105,7 +105,8 @@ QuicTime::Delta TcpCubicSender::TimeUntilSend(
QuicTime now,
Retransmission is_retransmission,
HasRetransmittableData has_retransmittable_data) {
- if (is_retransmission || !has_retransmittable_data) {
+ if (is_retransmission == IS_RETRANSMISSION ||
+ has_retransmittable_data == NO_RETRANSMITTABLE_DATA) {
// For TCP we can always send a retransmission and/or an ACK immediately.
return QuicTime::Delta::Zero();
}
diff --git a/net/quic/congestion_control/tcp_cubic_sender_test.cc b/net/quic/congestion_control/tcp_cubic_sender_test.cc
index 0cd51fd..71d53c6 100644
--- a/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -44,7 +44,7 @@ class TcpCubicSenderTest : public ::testing::Test {
bytes_to_send -= bytes_in_packet;
if (bytes_to_send > 0) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
- NO_RETRANSMITTABLE_DATA).IsZero());
+ HAS_RETRANSMITTABLE_DATA).IsZero());
}
}
}
@@ -75,20 +75,20 @@ TEST_F(TcpCubicSenderTest, SimpleSender) {
sender_->AvailableCongestionWindow());
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
// Get default QuicCongestionFeedbackFrame from receiver.
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
fake_bandwidth_, not_used_);
// Make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
// And that window is un-affected.
EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableCongestionWindow());
// A retransmitt should always retun 0.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), IS_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), IS_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
}
TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
@@ -96,14 +96,14 @@ TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
QuicCongestionFeedbackFrame feedback;
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
// Get default QuicCongestionFeedbackFrame from receiver.
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
fake_bandwidth_, not_used_);
// Make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
for (int n = 0; n < kNumberOfAck; ++n) {
// Send our full congestion window.
@@ -125,14 +125,14 @@ TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
QuicCongestionFeedbackFrame feedback;
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
// Get default QuicCongestionFeedbackFrame from receiver.
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
fake_bandwidth_, not_used_);
// Make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
for (int n = 0; n < kNumberOfAck; ++n) {
// Send our full congestion window.
@@ -168,14 +168,14 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
QuicCongestionFeedbackFrame feedback;
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
// Get default QuicCongestionFeedbackFrame from receiver.
ASSERT_TRUE(receiver_->GenerateCongestionFeedback(&feedback));
sender_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now(),
fake_bandwidth_, not_used_);
// Make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsZero());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsZero());
for (int i = 0; i < kNumberOfAck; ++i) {
// Send our full congestion window.
@@ -191,7 +191,7 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
// Make sure that we should not send right now.
EXPECT_TRUE(sender_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA).IsInfinite());
+ clock_.Now(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA).IsInfinite());
// We should now have fallen out of slow start.
// We expect window to be cut in half.
diff --git a/net/quic/crypto/aes_128_gcm_decrypter_openssl.cc b/net/quic/crypto/aes_128_gcm_decrypter_openssl.cc
index 105ae8c..0800cb5 100644
--- a/net/quic/crypto/aes_128_gcm_decrypter_openssl.cc
+++ b/net/quic/crypto/aes_128_gcm_decrypter_openssl.cc
@@ -21,13 +21,10 @@ const size_t kAuthTagSize = 16;
} // namespace
-Aes128GcmDecrypter::Aes128GcmDecrypter() {
-}
+Aes128GcmDecrypter::Aes128GcmDecrypter() {}
// static
-bool Aes128GcmDecrypter::IsSupported() {
- return true;
-}
+bool Aes128GcmDecrypter::IsSupported() { return true; }
bool Aes128GcmDecrypter::SetKey(StringPiece key) {
DCHECK_EQ(key.size(), sizeof(key_));
@@ -63,8 +60,7 @@ bool Aes128GcmDecrypter::Decrypt(StringPiece nonce,
ScopedEVPCipherCtx ctx;
// Set the cipher type and the key. The IV (nonce) is set below.
- if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, key_,
- NULL) == 0) {
+ if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, key_, NULL) == 0) {
return false;
}
@@ -74,16 +70,16 @@ bool Aes128GcmDecrypter::Decrypt(StringPiece nonce,
return false;
}
// Set the IV (nonce).
- if (EVP_DecryptInit_ex(ctx.get(), NULL, NULL, NULL,
- reinterpret_cast<const unsigned char*>(
- nonce.data())) == 0) {
+ if (EVP_DecryptInit_ex(
+ ctx.get(), NULL, NULL, NULL,
+ reinterpret_cast<const unsigned char*>(nonce.data())) == 0) {
return false;
}
// Set the authentication tag.
- if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAuthTagSize,
- const_cast<char*>(ciphertext.data()) +
- plaintext_size) == 0) {
+ if (EVP_CIPHER_CTX_ctrl(
+ ctx.get(), EVP_CTRL_GCM_SET_TAG, kAuthTagSize,
+ const_cast<char*>(ciphertext.data()) + plaintext_size) == 0) {
return false;
}
@@ -92,18 +88,18 @@ bool Aes128GcmDecrypter::Decrypt(StringPiece nonce,
if (!associated_data.empty()) {
// Set the associated data. The second argument (output buffer) must be
// NULL.
- if (EVP_DecryptUpdate(ctx.get(), NULL, &len,
- reinterpret_cast<const unsigned char*>(
- associated_data.data()),
- associated_data.size()) == 0) {
+ if (EVP_DecryptUpdate(
+ ctx.get(), NULL, &len,
+ reinterpret_cast<const unsigned char*>(associated_data.data()),
+ associated_data.size()) == 0) {
return false;
}
}
- if (EVP_DecryptUpdate(ctx.get(), output, &len,
- reinterpret_cast<const unsigned char*>(
- ciphertext.data()),
- plaintext_size) == 0) {
+ if (EVP_DecryptUpdate(
+ ctx.get(), output, &len,
+ reinterpret_cast<const unsigned char*>(ciphertext.data()),
+ plaintext_size) == 0) {
return false;
}
output += len;
diff --git a/net/quic/crypto/aes_128_gcm_decrypter_test.cc b/net/quic/crypto/aes_128_gcm_decrypter_test.cc
index 2ab0dd0..156dfb8 100644
--- a/net/quic/crypto/aes_128_gcm_decrypter_test.cc
+++ b/net/quic/crypto/aes_128_gcm_decrypter_test.cc
@@ -333,18 +333,15 @@ TEST(Aes128GcmDecrypterTest, Decrypt) {
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vector[j].key != NULL; j++) {
// Decode the test vector.
- ASSERT_TRUE(DecodeHexString(test_vector[j].key, key, &key_len,
- sizeof(key)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len,
- sizeof(iv)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len,
- sizeof(ct)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].aad, aad, &aad_len,
- sizeof(aad)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].tag, tag, &tag_len,
- sizeof(tag)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len,
- sizeof(pt)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].key, key, &key_len, sizeof(key)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len, sizeof(iv)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len, sizeof(ct)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].aad, aad, &aad_len, sizeof(aad)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].tag, tag, &tag_len, sizeof(tag)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len, sizeof(pt)));
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
@@ -365,8 +362,7 @@ TEST(Aes128GcmDecrypterTest, Decrypt) {
&decrypter, StringPiece(iv, iv_len),
// OpenSSL fails if NULL is set as the AAD, as opposed to a
// zero-length, non-NULL pointer.
- StringPiece(aad_len ? aad : NULL, aad_len),
- ciphertext));
+ StringPiece(aad_len ? aad : NULL, aad_len), ciphertext));
if (!decrypted.get()) {
EXPECT_EQ((size_t)-1, pt_len);
continue;
@@ -374,9 +370,8 @@ TEST(Aes128GcmDecrypterTest, Decrypt) {
ASSERT_NE((size_t)-1, pt_len);
ASSERT_EQ(pt_len, decrypted->length());
- test::CompareCharArraysWithHexError(
- "plaintext", decrypted->data(), pt_len,
- pt, pt_len);
+ test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
+ pt_len, pt, pt_len);
}
}
}
diff --git a/net/quic/crypto/aes_128_gcm_encrypter_openssl.cc b/net/quic/crypto/aes_128_gcm_encrypter_openssl.cc
index daa85f0..b00dec8 100644
--- a/net/quic/crypto/aes_128_gcm_encrypter_openssl.cc
+++ b/net/quic/crypto/aes_128_gcm_encrypter_openssl.cc
@@ -26,9 +26,7 @@ Aes128GcmEncrypter::Aes128GcmEncrypter() {
}
// static
-bool Aes128GcmEncrypter::IsSupported() {
- return true;
-}
+bool Aes128GcmEncrypter::IsSupported() { return true; }
bool Aes128GcmEncrypter::SetKey(StringPiece key) {
DCHECK_EQ(key.size(), sizeof(key_));
@@ -63,8 +61,7 @@ bool Aes128GcmEncrypter::Encrypt(StringPiece nonce,
ScopedEVPCipherCtx ctx;
// Set the cipher type and the key. The IV (nonce) is set below.
- if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, key_,
- NULL) == 0) {
+ if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, key_, NULL) == 0) {
return false;
}
@@ -74,9 +71,9 @@ bool Aes128GcmEncrypter::Encrypt(StringPiece nonce,
return false;
}
// Set the IV (nonce).
- if (EVP_EncryptInit_ex(ctx.get(), NULL, NULL, NULL,
- reinterpret_cast<const unsigned char*>(
- nonce.data())) == 0) {
+ if (EVP_EncryptInit_ex(
+ ctx.get(), NULL, NULL, NULL,
+ reinterpret_cast<const unsigned char*>(nonce.data())) == 0) {
return false;
}
@@ -85,18 +82,18 @@ bool Aes128GcmEncrypter::Encrypt(StringPiece nonce,
if (!associated_data.empty()) {
// Set the associated data. The second argument (output buffer) must be
// NULL.
- if (EVP_EncryptUpdate(ctx.get(), NULL, &output_len,
- reinterpret_cast<const unsigned char*>(
- associated_data.data()),
- associated_data.size()) == 0) {
+ if (EVP_EncryptUpdate(
+ ctx.get(), NULL, &output_len,
+ reinterpret_cast<const unsigned char*>(associated_data.data()),
+ associated_data.size()) == 0) {
return false;
}
}
- if (EVP_EncryptUpdate(ctx.get(), output, &output_len,
- reinterpret_cast<const unsigned char*>(
- plaintext.data()),
- plaintext.size()) == 0) {
+ if (EVP_EncryptUpdate(
+ ctx.get(), output, &output_len,
+ reinterpret_cast<const unsigned char*>(plaintext.data()),
+ plaintext.size()) == 0) {
return false;
}
output += output_len;
@@ -134,9 +131,7 @@ QuicData* Aes128GcmEncrypter::EncryptPacket(
return new QuicData(ciphertext.release(), ciphertext_size, true);
}
-size_t Aes128GcmEncrypter::GetKeySize() const {
- return kKeySize;
-}
+size_t Aes128GcmEncrypter::GetKeySize() const { return kKeySize; }
size_t Aes128GcmEncrypter::GetNoncePrefixSize() const {
return kNoncePrefixSize;
diff --git a/net/quic/crypto/aes_128_gcm_encrypter_test.cc b/net/quic/crypto/aes_128_gcm_encrypter_test.cc
index 0da7a8f..7e07ba9 100644
--- a/net/quic/crypto/aes_128_gcm_encrypter_test.cc
+++ b/net/quic/crypto/aes_128_gcm_encrypter_test.cc
@@ -285,18 +285,15 @@ TEST(Aes128GcmEncrypterTest, Encrypt) {
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vector[j].key != NULL; j++) {
// Decode the test vector.
- ASSERT_TRUE(DecodeHexString(test_vector[j].key, key, &key_len,
- sizeof(key)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len,
- sizeof(iv)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len,
- sizeof(pt)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].aad, aad, &aad_len,
- sizeof(aad)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len,
- sizeof(ct)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].tag, tag, &tag_len,
- sizeof(tag)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].key, key, &key_len, sizeof(key)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len, sizeof(iv)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len, sizeof(pt)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].aad, aad, &aad_len, sizeof(aad)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len, sizeof(ct)));
+ ASSERT_TRUE(
+ DecodeHexString(test_vector[j].tag, tag, &tag_len, sizeof(tag)));
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
@@ -314,16 +311,14 @@ TEST(Aes128GcmEncrypterTest, Encrypt) {
// OpenSSL fails if NULL is set as the AAD, as opposed to a
// zero-length, non-NULL pointer. This deliberately tests that we
// handle this case.
- StringPiece(aad_len ? aad : NULL, aad_len),
- StringPiece(pt, pt_len)));
+ StringPiece(aad_len ? aad : NULL, aad_len), StringPiece(pt, pt_len)));
ASSERT_TRUE(encrypted.get());
ASSERT_EQ(ct_len + tag_len, encrypted->length());
+ test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
+ ct_len, ct, ct_len);
test::CompareCharArraysWithHexError(
- "ciphertext", encrypted->data(), ct_len,
- ct, ct_len);
- test::CompareCharArraysWithHexError(
- "authentication tag", encrypted->data() + ct_len, tag_len,
- tag, tag_len);
+ "authentication tag", encrypted->data() + ct_len, tag_len, tag,
+ tag_len);
}
}
}
diff --git a/net/quic/crypto/cert_compressor.cc b/net/quic/crypto/cert_compressor.cc
index aaa5f55..2f36c19 100644
--- a/net/quic/crypto/cert_compressor.cc
+++ b/net/quic/crypto/cert_compressor.cc
@@ -18,7 +18,8 @@ namespace net {
namespace {
// kCommonCertSubstrings contains ~1500 bytes of common certificate substrings
-// in order to help zlib.
+// in order to help zlib. This was generated via a fairly dumb algorithm from
+// the Alexa Top 5000 set - we could probably do better.
static unsigned char kCommonCertSubstrings[] = {
0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04,
0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
@@ -158,7 +159,7 @@ struct CertEntry {
// be replaced by its 64-bit hash (in |hash|).
CACHED = 2,
// COMMON means that the certificate is in a common certificate set known
- // to the peer with hash |set_hash| and index |index|.
+ // to the peer with hash |set_hash| and certificate index |index|.
COMMON = 3,
};
@@ -171,16 +172,17 @@ struct CertEntry {
// MatchCerts returns a vector of CertEntries describing how to most
// efficiently represent |certs| to a peer who has the common sets identified
// by |client_common_set_hashes| and who has cached the certificates with the
-// 64-bit, FNV-1a hashes in |client_cached|.
+// 64-bit, FNV-1a hashes in |client_cached_cert_hashes|.
vector<CertEntry> MatchCerts(const vector<string>& certs,
StringPiece client_common_set_hashes,
- StringPiece client_cached,
- CommonCertSet* common_set) {
+ StringPiece client_cached_cert_hashes,
+ const CommonCertSets* common_set) {
vector<CertEntry> entries;
entries.reserve(certs.size());
- const bool cached_valid = client_cached.size() % sizeof(uint64) == 0 &&
- !client_cached.empty();
+ const bool cached_valid =
+ client_cached_cert_hashes.size() % sizeof(uint64) == 0 &&
+ !client_cached_cert_hashes.empty();
for (vector<string>::const_iterator i = certs.begin();
i != certs.end(); ++i) {
@@ -191,9 +193,11 @@ vector<CertEntry> MatchCerts(const vector<string>& certs,
uint64 hash = QuicUtils::FNV1a_64_Hash(i->data(), i->size());
// This assumes that the machine is little-endian.
- for (size_t i = 0; i < client_cached.size(); i += sizeof(uint64)) {
+ for (size_t i = 0; i < client_cached_cert_hashes.size();
+ i += sizeof(uint64)) {
uint64 cached_hash;
- memcpy(&cached_hash, client_cached.data() + i, sizeof(uint64));
+ memcpy(&cached_hash, client_cached_cert_hashes.data() + i,
+ sizeof(uint64));
if (hash != cached_hash) {
continue;
}
@@ -210,9 +214,8 @@ vector<CertEntry> MatchCerts(const vector<string>& certs,
}
}
- if (common_set &&
- common_set->MatchCert(*i, client_common_set_hashes, &entry.set_hash,
- &entry.index)) {
+ if (common_set && common_set->MatchCert(*i, client_common_set_hashes,
+ &entry.set_hash, &entry.index)) {
entry.type = CertEntry::COMMON;
entries.push_back(entry);
continue;
@@ -329,7 +332,7 @@ vector<uint64> HashCerts(const vector<string>& certs) {
// |in_out| is updated to contain the trailing data.
bool ParseEntries(StringPiece* in_out,
const vector<string>& cached_certs,
- CommonCertSet* common_set,
+ const CommonCertSets* common_set,
vector<CertEntry>* out_entries,
vector<string>* out_certs) {
StringPiece in = *in_out;
@@ -419,14 +422,9 @@ class ScopedZLib {
DEFLATE,
};
- explicit ScopedZLib(Type type)
- : z_(NULL),
- type_(type) {
- }
+ explicit ScopedZLib(Type type) : z_(NULL), type_(type) {}
- void reset(z_stream* z) {
- z_ = z;
- }
+ void reset(z_stream* z) { z_ = z; }
~ScopedZLib() {
if (z_) {
@@ -450,10 +448,10 @@ class ScopedZLib {
// static
string CertCompressor::CompressChain(const vector<string>& certs,
StringPiece client_common_set_hashes,
- StringPiece client_cached,
- CommonCertSet* common_set) {
+ StringPiece client_cached_cert_hashes,
+ const CommonCertSets* common_set) {
const vector<CertEntry> entries = MatchCerts(
- certs, client_common_set_hashes, client_cached, common_set);
+ certs, client_common_set_hashes, client_cached_cert_hashes, common_set);
DCHECK_EQ(entries.size(), certs.size());
size_t uncompressed_size = 0;
@@ -551,7 +549,7 @@ string CertCompressor::CompressChain(const vector<string>& certs,
// static
bool CertCompressor::DecompressChain(StringPiece in,
const vector<string>& cached_certs,
- CommonCertSet* common_set,
+ const CommonCertSets* common_set,
vector<string>* out_certs) {
vector<CertEntry> entries;
if (!ParseEntries(&in, cached_certs, common_set, &entries, out_certs)) {
@@ -600,9 +598,7 @@ bool CertCompressor::DecompressChain(StringPiece in,
rv = inflate(&z, Z_FINISH);
}
- if (Z_STREAM_END != rv ||
- z.avail_out > 0 ||
- z.avail_in > 0) {
+ if (Z_STREAM_END != rv || z.avail_out > 0 || z.avail_in > 0) {
return false;
}
diff --git a/net/quic/crypto/cert_compressor.h b/net/quic/crypto/cert_compressor.h
index cf8021b..587684d 100644
--- a/net/quic/crypto/cert_compressor.h
+++ b/net/quic/crypto/cert_compressor.h
@@ -22,9 +22,9 @@ namespace net {
// that they already have. In the event that one of them is to be
// compressed, it can be replaced with just the hash.
// 2) The peer may provide a number of hashes that represent sets of
-// pre-shared certificates. If one of those certificates is to be
-// compressed, and it's known to the given CommonCertSet, then it can be
-// replaced with a set hash and index.
+// pre-shared certificates (CommonCertSets). If one of those certificates
+// is to be compressed, and it's known to the given CommonCertSets, then it
+// can be replaced with a set hash and certificate index.
// 3) Otherwise the certificates are compressed with zlib using a pre-shared
// dictionary that consists of the certificates handled with the above
// methods and a small chunk of common substrings.
@@ -37,8 +37,8 @@ class NET_EXPORT_PRIVATE CertCompressor {
// hashes of certificates that the peer already possesses.
static std::string CompressChain(const std::vector<std::string>& certs,
base::StringPiece client_common_set_hashes,
- base::StringPiece client_cached,
- CommonCertSet* common_set);
+ base::StringPiece client_cached_cert_hashes,
+ const CommonCertSets* common_set);
// DecompressChain decompresses the result of |CompressChain|, given in |in|,
// into a series of certificates that are written to |out_certs|.
@@ -46,7 +46,7 @@ class NET_EXPORT_PRIVATE CertCompressor {
// |common_set| contains the common certificate sets known locally.
static bool DecompressChain(base::StringPiece in,
const std::vector<std::string>& cached_certs,
- CommonCertSet* common_set,
+ const CommonCertSets* common_set,
std::vector<std::string>* out_certs);
};
diff --git a/net/quic/crypto/cert_compressor_test.cc b/net/quic/crypto/cert_compressor_test.cc
index c066e61..ef12ccc 100644
--- a/net/quic/crypto/cert_compressor_test.cc
+++ b/net/quic/crypto/cert_compressor_test.cc
@@ -23,8 +23,8 @@ TEST(CertCompressor, EmptyChain) {
EXPECT_EQ("00", base::HexEncode(compressed.data(), compressed.size()));
vector<string> chain2, cached_certs;
- ASSERT_TRUE(CertCompressor::DecompressChain(
- compressed, cached_certs, NULL, &chain2));
+ ASSERT_TRUE(
+ CertCompressor::DecompressChain(compressed, cached_certs, NULL, &chain2));
EXPECT_EQ(chain.size(), chain2.size());
}
@@ -37,8 +37,8 @@ TEST(CertCompressor, Compressed) {
EXPECT_EQ("0100", base::HexEncode(compressed.substr(0, 2).data(), 2));
vector<string> chain2, cached_certs;
- ASSERT_TRUE(CertCompressor::DecompressChain(
- compressed, cached_certs, NULL, &chain2));
+ ASSERT_TRUE(
+ CertCompressor::DecompressChain(compressed, cached_certs, NULL, &chain2));
EXPECT_EQ(chain.size(), chain2.size());
EXPECT_EQ(chain[0], chain2[0]);
}
@@ -47,22 +47,22 @@ TEST(CertCompressor, Common) {
vector<string> chain;
chain.push_back("testcert");
static const uint64 set_hash = 42;
- scoped_ptr<CommonCertSet> common_set(
- CryptoTestUtils::MockCommonCertSet(chain[0], set_hash, 1));
+ scoped_ptr<CommonCertSets> common_set(
+ CryptoTestUtils::MockCommonCertSets(chain[0], set_hash, 1));
const string compressed = CertCompressor::CompressChain(
- chain, StringPiece(reinterpret_cast<const char*>(&set_hash),
- sizeof(set_hash)),
+ chain,
+ StringPiece(reinterpret_cast<const char*>(&set_hash), sizeof(set_hash)),
StringPiece(), common_set.get());
- const string common("03" /* common */
+ const string common("03" /* common */
"2A00000000000000" /* set hash 42 */
- "01000000" /* index 1 */
- "00" /* end of list */);
+ "01000000" /* index 1 */
+ "00" /* end of list */);
EXPECT_EQ(common.data(),
base::HexEncode(compressed.data(), compressed.size()));
vector<string> chain2, cached_certs;
- ASSERT_TRUE(CertCompressor::DecompressChain(
- compressed, cached_certs, common_set.get(), &chain2));
+ ASSERT_TRUE(CertCompressor::DecompressChain(compressed, cached_certs,
+ common_set.get(), &chain2));
EXPECT_EQ(chain.size(), chain2.size());
EXPECT_EQ(chain[0], chain2[0]);
}
@@ -82,8 +82,8 @@ TEST(CertCompressor, Cached) {
vector<string> cached_certs, chain2;
cached_certs.push_back(chain[0]);
- ASSERT_TRUE(CertCompressor::DecompressChain(
- compressed, cached_certs, NULL, &chain2));
+ ASSERT_TRUE(
+ CertCompressor::DecompressChain(compressed, cached_certs, NULL, &chain2));
EXPECT_EQ(chain.size(), chain2.size());
EXPECT_EQ(chain[0], chain2[0]);
}
@@ -116,7 +116,7 @@ TEST(CertCompressor, BadInputs) {
hash_and_index_truncated.size()),
cached_certs, NULL, &chain));
- /* without a CommonCertSet */
+ /* without a CommonCertSets */
const string without_a_common_cert_set(
"03" "0000000000000000" "00000000");
EXPECT_FALSE(CertCompressor::DecompressChain(
@@ -124,8 +124,8 @@ TEST(CertCompressor, BadInputs) {
without_a_common_cert_set.size()),
cached_certs, NULL, &chain));
- scoped_ptr<CommonCertSet> common_set(
- CryptoTestUtils::MockCommonCertSet("foo", 42, 1));
+ scoped_ptr<CommonCertSets> common_set(
+ CryptoTestUtils::MockCommonCertSets("foo", 42, 1));
/* incorrect hash and index */
const string incorrect_hash_and_index(
diff --git a/net/quic/crypto/common_cert_set.cc b/net/quic/crypto/common_cert_set.cc
index a8de6ae..78aa927 100644
--- a/net/quic/crypto/common_cert_set.cc
+++ b/net/quic/crypto/common_cert_set.cc
@@ -16,11 +16,15 @@ namespace common_cert_set_0 {
#include "net/quic/crypto/common_cert_set_0.c"
}
-
struct CertSet {
+ // num_certs contains the number of certificates in this set.
size_t num_certs;
+ // certs is an array of |num_certs| pointers to the DER encoded certificates.
const unsigned char* const* certs;
+ // lens is an array of |num_certs| integers describing the length, in bytes,
+ // of each certificate.
const size_t* lens;
+ // hash contains the 64-bit, FNV-1a hash of this set.
uint64 hash;
};
@@ -37,18 +41,18 @@ static const uint64 kSetHashes[] = {
common_cert_set_0::kHash,
};
-CommonCertSet::~CommonCertSet() {
+CommonCertSets::~CommonCertSets() {
}
-CommonCertSetQUIC::CommonCertSetQUIC() {
+CommonCertSetsQUIC::CommonCertSetsQUIC() {
}
-StringPiece CommonCertSetQUIC::GetCommonHashes() {
+StringPiece CommonCertSetsQUIC::GetCommonHashes() const {
return StringPiece(reinterpret_cast<const char*>(kSetHashes),
sizeof(uint64) * arraysize(kSetHashes));
}
-StringPiece CommonCertSetQUIC::GetCert(uint64 hash, uint32 index) {
+StringPiece CommonCertSetsQUIC::GetCert(uint64 hash, uint32 index) const {
for (size_t i = 0; i < arraysize(kSets); i++) {
if (kSets[i].hash == hash) {
if (index >= kSets[i].num_certs) {
@@ -82,10 +86,10 @@ static int Compare(StringPiece a, const unsigned char* b, size_t b_len) {
return 0;
}
-bool CommonCertSetQUIC::MatchCert(StringPiece cert,
- StringPiece common_set_hashes,
- uint64* out_hash,
- uint32* out_index) {
+bool CommonCertSetsQUIC::MatchCert(StringPiece cert,
+ StringPiece common_set_hashes,
+ uint64* out_hash,
+ uint32* out_index) const {
if (common_set_hashes.size() % sizeof(uint64) != 0) {
return false;
}
diff --git a/net/quic/crypto/common_cert_set.h b/net/quic/crypto/common_cert_set.h
index d4cabd6..6972926 100644
--- a/net/quic/crypto/common_cert_set.h
+++ b/net/quic/crypto/common_cert_set.h
@@ -13,19 +13,19 @@
namespace net {
-// CommonCertSet is an interface to an object that contains a number of common
+// CommonCertSets is an interface to an object that contains a number of common
// certificate sets and can match against them.
-class NET_EXPORT_PRIVATE CommonCertSet {
+class NET_EXPORT_PRIVATE CommonCertSets {
public:
- virtual ~CommonCertSet();
+ virtual ~CommonCertSets();
// GetCommonHashes returns a StringPiece containing the hashes of common sets
// supported by this object.
- virtual base::StringPiece GetCommonHashes() = 0;
+ virtual base::StringPiece GetCommonHashes() const = 0;
// GetCert returns a specific certificate in the common set identified by
// |hash|. If no such certificate is known, an empty StringPiece is returned.
- virtual base::StringPiece GetCert(uint64 hash, uint32 index) = 0;
+ virtual base::StringPiece GetCert(uint64 hash, uint32 index) const = 0;
// MatchCert tries to find |cert| in one of the common certificate sets
// identified by |common_set_hashes|. On success it puts the hash in
@@ -34,27 +34,27 @@ class NET_EXPORT_PRIVATE CommonCertSet {
virtual bool MatchCert(base::StringPiece cert,
base::StringPiece common_set_hashes,
uint64* out_hash,
- uint32* out_index) = 0;
+ uint32* out_index) const = 0;
};
-// CommonCertSetQUIC implements the CommonCertSet interface using the default
+// CommonCertSetsQUIC implements the CommonCertSet interface using the default
// certificate sets.
-class NET_EXPORT_PRIVATE CommonCertSetQUIC : public CommonCertSet {
+class NET_EXPORT_PRIVATE CommonCertSetsQUIC : public CommonCertSets {
public:
- CommonCertSetQUIC();
+ CommonCertSetsQUIC();
- // CommonCertSet interface.
- virtual base::StringPiece GetCommonHashes() OVERRIDE;
+ // CommonCertSets interface.
+ virtual base::StringPiece GetCommonHashes() const OVERRIDE;
- virtual base::StringPiece GetCert(uint64 hash, uint32 index) OVERRIDE;
+ virtual base::StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE;
virtual bool MatchCert(base::StringPiece cert,
base::StringPiece common_set_hashes,
uint64* out_hash,
- uint32* out_index) OVERRIDE;
+ uint32* out_index) const OVERRIDE;
private:
- DISALLOW_COPY_AND_ASSIGN(CommonCertSetQUIC);
+ DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC);
};
} // namespace net
diff --git a/net/quic/crypto/common_cert_set_1_50.inc b/net/quic/crypto/common_cert_set_1_50.inc
index 861c9b4..c151f1e 100644
--- a/net/quic/crypto/common_cert_set_1_50.inc
+++ b/net/quic/crypto/common_cert_set_1_50.inc
@@ -3,6 +3,9 @@
* found in the LICENSE file.
*/
+/* This file contains common certificates. It's designed to be #included in
+ * another file, in a namespace. */
+
#if 0
Certificate:
Data:
diff --git a/net/quic/crypto/common_cert_set_51_100.inc b/net/quic/crypto/common_cert_set_51_100.inc
index e66298b..0a1b0d1a 100644
--- a/net/quic/crypto/common_cert_set_51_100.inc
+++ b/net/quic/crypto/common_cert_set_51_100.inc
@@ -3,6 +3,9 @@
* found in the LICENSE file.
*/
+/* This file contains common certificates. It's designed to be #included in
+ * another file, in a namespace. */
+
#if 0
Certificate:
Data:
diff --git a/net/quic/crypto/common_cert_set_test.cc b/net/quic/crypto/common_cert_set_test.cc
index 0c1b841..51b41d8 100644
--- a/net/quic/crypto/common_cert_set_test.cc
+++ b/net/quic/crypto/common_cert_set_test.cc
@@ -72,18 +72,18 @@ static unsigned char kGIACertificate[] = {
0x95, 0x87, 0xbc, 0xbc, 0x90, 0xf9, 0x50, 0x32,
};
-TEST(CommonCertSet, FindGIA) {
+TEST(CommonCertSets, FindGIA) {
StringPiece gia(reinterpret_cast<const char*>(kGIACertificate),
sizeof(kGIACertificate));
- CommonCertSetQUIC set;
+ CommonCertSetsQUIC set;
const uint64 in_hash = GG_UINT64_C(0xde8086f914a3af54);
uint64 hash;
uint32 index;
ASSERT_TRUE(set.MatchCert(
- gia, StringPiece(reinterpret_cast<const char*>(&in_hash),
- sizeof(in_hash)),
+ gia,
+ StringPiece(reinterpret_cast<const char*>(&in_hash), sizeof(in_hash)),
&hash, &index));
EXPECT_EQ(in_hash, hash);
@@ -93,15 +93,15 @@ TEST(CommonCertSet, FindGIA) {
EXPECT_TRUE(0 == memcmp(gia.data(), gia_copy.data(), gia.size()));
}
-TEST(CommonCertSet, NonMatch) {
- CommonCertSetQUIC set;
+TEST(CommonCertSets, NonMatch) {
+ CommonCertSetsQUIC set;
StringPiece not_a_cert("hello");
const uint64 in_hash = GG_UINT64_C(0xde8086f914a3af54);
uint64 hash;
uint32 index;
EXPECT_FALSE(set.MatchCert(
- not_a_cert, StringPiece(reinterpret_cast<const char*>(&in_hash),
- sizeof(in_hash)),
+ not_a_cert,
+ StringPiece(reinterpret_cast<const char*>(&in_hash), sizeof(in_hash)),
&hash, &index));
}
diff --git a/net/quic/crypto/crypto_framer.cc b/net/quic/crypto/crypto_framer.cc
index cbc1079..4b3ce64 100644
--- a/net/quic/crypto/crypto_framer.cc
+++ b/net/quic/crypto/crypto_framer.cc
@@ -17,7 +17,7 @@ namespace net {
namespace {
-const size_t kCryptoTagSize = sizeof(uint32);
+const size_t kQuicTagSize = sizeof(uint32);
const size_t kCryptoEndOffsetSize = sizeof(uint32);
const size_t kNumEntriesSize = sizeof(uint16);
const size_t kValueLenSize = sizeof(uint16);
@@ -30,18 +30,14 @@ class OneShotVisitor : public CryptoFramerVisitorInterface {
error_(false) {
}
- virtual void OnError(CryptoFramer* framer) OVERRIDE {
- error_ = true;
- }
+ virtual void OnError(CryptoFramer* framer) OVERRIDE { error_ = true; }
virtual void OnHandshakeMessage(
const CryptoHandshakeMessage& message) OVERRIDE {
*out_ = message;
}
- bool error() const {
- return error_;
- }
+ bool error() const { return error_; }
private:
CryptoHandshakeMessage* const out_;
@@ -66,8 +62,7 @@ CryptoHandshakeMessage* CryptoFramer::ParseMessage(StringPiece in) {
CryptoFramer framer;
framer.set_visitor(&visitor);
- if (!framer.ProcessInput(in) ||
- visitor.error() ||
+ if (!framer.ProcessInput(in) || visitor.error() ||
framer.InputBytesRemaining()) {
return NULL;
}
@@ -86,10 +81,10 @@ bool CryptoFramer::ProcessInput(StringPiece input) {
switch (state_) {
case STATE_READING_TAG:
- if (reader.BytesRemaining() < kCryptoTagSize) {
+ if (reader.BytesRemaining() < kQuicTagSize) {
break;
}
- CryptoTag message_tag;
+ QuicTag message_tag;
reader.ReadUInt32(&message_tag);
message_.set_tag(message_tag);
state_ = STATE_READING_NUM_ENTRIES;
@@ -109,14 +104,14 @@ bool CryptoFramer::ProcessInput(StringPiece input) {
state_ = STATE_READING_TAGS_AND_LENGTHS;
values_len_ = 0;
case STATE_READING_TAGS_AND_LENGTHS: {
- if (reader.BytesRemaining() < num_entries_ * (kCryptoTagSize +
- kCryptoEndOffsetSize)) {
+ if (reader.BytesRemaining() <
+ num_entries_ * (kQuicTagSize + kCryptoEndOffsetSize)) {
break;
}
uint32 last_end_offset = 0;
for (unsigned i = 0; i < num_entries_; ++i) {
- CryptoTag tag;
+ QuicTag tag;
reader.ReadUInt32(&tag);
if (i > 0 && tag <= tags_and_lengths_[i-1].first) {
if (tag == tags_and_lengths_[i-1].first) {
@@ -145,7 +140,7 @@ bool CryptoFramer::ProcessInput(StringPiece input) {
if (reader.BytesRemaining() < values_len_) {
break;
}
- for (vector<pair<CryptoTag, size_t> >::const_iterator
+ for (vector<pair<QuicTag, size_t> >::const_iterator
it = tags_and_lengths_.begin(); it != tags_and_lengths_.end();
it++) {
StringPiece value;
@@ -168,14 +163,14 @@ QuicData* CryptoFramer::ConstructHandshakeMessage(
if (message.tag_value_map().size() > kMaxEntries) {
return NULL;
}
- size_t len = kCryptoTagSize; // message tag
- len += sizeof(uint16); // number of map entries
- len += sizeof(uint16); // padding.
- CryptoTagValueMap::const_iterator it = message.tag_value_map().begin();
+ size_t len = kQuicTagSize; // message tag
+ len += sizeof(uint16); // number of map entries
+ len += sizeof(uint16); // padding.
+ QuicTagValueMap::const_iterator it = message.tag_value_map().begin();
while (it != message.tag_value_map().end()) {
- len += kCryptoTagSize; // tag
+ len += kQuicTagSize; // tag
len += kCryptoEndOffsetSize; // end offset
- len += it->second.length(); // value
+ len += it->second.length(); // value
++it;
}
diff --git a/net/quic/crypto/crypto_framer.h b/net/quic/crypto/crypto_framer.h
index 7861284..75cc405 100644
--- a/net/quic/crypto/crypto_framer.h
+++ b/net/quic/crypto/crypto_framer.h
@@ -56,9 +56,7 @@ class NET_EXPORT_PRIVATE CryptoFramer {
visitor_ = visitor;
}
- QuicErrorCode error() const {
- return error_;
- }
+ QuicErrorCode error() const { return error_; }
// Processes input data, which must be delivered in order. Returns
// false if there was an error, and true otherwise.
@@ -66,9 +64,7 @@ class NET_EXPORT_PRIVATE CryptoFramer {
// Returns the number of bytes of buffered input data remaining to be
// parsed.
- size_t InputBytesRemaining() const {
- return buffer_.length();
- }
+ size_t InputBytesRemaining() const { return buffer_.length(); }
// Returns a new QuicData owned by the caller that contains a serialized
// |message|, or NULL if there was an error.
@@ -79,9 +75,7 @@ class NET_EXPORT_PRIVATE CryptoFramer {
// Clears per-message state. Does not clear the visitor.
void Clear();
- void set_error(QuicErrorCode error) {
- error_ = error;
- }
+ void set_error(QuicErrorCode error) { error_ = error; }
// Represents the current state of the parsing state machine.
enum CryptoFramerState {
@@ -105,7 +99,7 @@ class NET_EXPORT_PRIVATE CryptoFramer {
uint16 num_entries_;
// tags_and_lengths_ contains the tags that are currently being parsed and
// their lengths.
- std::vector<std::pair<CryptoTag, size_t> > tags_and_lengths_;
+ std::vector<std::pair<QuicTag, size_t> > tags_and_lengths_;
// Cumulative length of all values in the message currently being parsed.
size_t values_len_;
};
diff --git a/net/quic/crypto/crypto_framer_test.cc b/net/quic/crypto/crypto_framer_test.cc
index 0cdbd40..ca4b92e 100644
--- a/net/quic/crypto/crypto_framer_test.cc
+++ b/net/quic/crypto/crypto_framer_test.cc
@@ -49,16 +49,6 @@ class TestCryptoVisitor : public ::net::CryptoFramerVisitorInterface {
vector<CryptoHandshakeMessage> messages_;
};
-TEST(CryptoFramerTest, MakeCryptoTag) {
- CryptoTag tag = MakeQuicTag('A', 'B', 'C', 'D');
- char bytes[4];
- memcpy(bytes, &tag, 4);
- EXPECT_EQ('A', bytes[0]);
- EXPECT_EQ('B', bytes[1]);
- EXPECT_EQ('C', bytes[2]);
- EXPECT_EQ('D', bytes[3]);
-}
-
TEST(CryptoFramerTest, ConstructHandshakeMessage) {
CryptoHandshakeMessage message;
message.set_tag(0xFFAA7733);
@@ -356,8 +346,8 @@ TEST(CryptoFramerTest, ProcessEndOffsetsOutOfOrder) {
0x00, 0x00, 0x00, 0x00,
};
- EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
- arraysize(input))));
+ EXPECT_FALSE(
+ framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
}
@@ -375,8 +365,8 @@ TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
0x00, 0x00,
};
- EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
- arraysize(input))));
+ EXPECT_FALSE(
+ framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error());
}
@@ -402,8 +392,8 @@ TEST(CryptoFramerTest, ProcessInputZeroLength) {
0x05, 0x00, 0x00, 0x00,
};
- EXPECT_TRUE(framer.ProcessInput(StringPiece(AsChars(input),
- arraysize(input))));
+ EXPECT_TRUE(
+ framer.ProcessInput(StringPiece(AsChars(input), arraysize(input))));
}
} // namespace test
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc
index 0788508..16d32d6 100644
--- a/net/quic/crypto/crypto_handshake.cc
+++ b/net/quic/crypto/crypto_handshake.cc
@@ -23,7 +23,6 @@
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_random.h"
-#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
@@ -69,23 +68,23 @@ const QuicData& CryptoHandshakeMessage::GetSerialized() const {
return *serialized_.get();
}
-void CryptoHandshakeMessage::Insert(CryptoTagValueMap::const_iterator begin,
- CryptoTagValueMap::const_iterator end) {
+void CryptoHandshakeMessage::Insert(QuicTagValueMap::const_iterator begin,
+ QuicTagValueMap::const_iterator end) {
tag_value_map_.insert(begin, end);
}
-void CryptoHandshakeMessage::SetTaglist(CryptoTag tag, ...) {
- // Warning, if sizeof(CryptoTag) > sizeof(int) then this function will break
+void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) {
+ // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break
// because the terminating 0 will only be promoted to int.
- COMPILE_ASSERT(sizeof(CryptoTag) <= sizeof(int),
+ COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int),
crypto_tag_not_be_larger_than_int_or_varargs_will_break);
- vector<CryptoTag> tags;
+ vector<QuicTag> tags;
va_list ap;
va_start(ap, tag);
for (;;) {
- CryptoTag list_item = va_arg(ap, CryptoTag);
+ QuicTag list_item = va_arg(ap, QuicTag);
if (list_item == 0) {
break;
}
@@ -100,20 +99,20 @@ void CryptoHandshakeMessage::SetTaglist(CryptoTag tag, ...) {
va_end(ap);
}
-void CryptoHandshakeMessage::SetStringPiece(CryptoTag tag, StringPiece value) {
+void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) {
tag_value_map_[tag] = value.as_string();
}
-QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag,
- const CryptoTag** out_tags,
+QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag,
+ const QuicTag** out_tags,
size_t* out_len) const {
- CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag);
+ QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
*out_len = 0;
QuicErrorCode ret = QUIC_NO_ERROR;
if (it == tag_value_map_.end()) {
ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
- } else if (it->second.size() % sizeof(CryptoTag) != 0) {
+ } else if (it->second.size() % sizeof(QuicTag) != 0) {
ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
@@ -123,14 +122,14 @@ QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag,
return ret;
}
- *out_tags = reinterpret_cast<const CryptoTag*>(it->second.data());
- *out_len = it->second.size() / sizeof(CryptoTag);
+ *out_tags = reinterpret_cast<const QuicTag*>(it->second.data());
+ *out_len = it->second.size() / sizeof(QuicTag);
return ret;
}
-bool CryptoHandshakeMessage::GetStringPiece(CryptoTag tag,
+bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
StringPiece* out) const {
- CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag);
+ QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
if (it == tag_value_map_.end()) {
return false;
}
@@ -138,7 +137,7 @@ bool CryptoHandshakeMessage::GetStringPiece(CryptoTag tag,
return true;
}
-QuicErrorCode CryptoHandshakeMessage::GetNthValue16(CryptoTag tag,
+QuicErrorCode CryptoHandshakeMessage::GetNthValue24(QuicTag tag,
unsigned index,
StringPiece* out) const {
StringPiece value;
@@ -150,15 +149,16 @@ QuicErrorCode CryptoHandshakeMessage::GetNthValue16(CryptoTag tag,
if (value.empty()) {
return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND;
}
- if (value.size() < 2) {
+ if (value.size() < 3) {
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
const unsigned char* data =
reinterpret_cast<const unsigned char*>(value.data());
size_t size = static_cast<size_t>(data[0]) |
- (static_cast<size_t>(data[1]) << 8);
- value.remove_prefix(2);
+ (static_cast<size_t>(data[1]) << 8) |
+ (static_cast<size_t>(data[2]) << 16);
+ value.remove_prefix(3);
if (value.size() < size) {
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -173,8 +173,8 @@ QuicErrorCode CryptoHandshakeMessage::GetNthValue16(CryptoTag tag,
}
}
-bool CryptoHandshakeMessage::GetString(CryptoTag tag, string* out) const {
- CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag);
+bool CryptoHandshakeMessage::GetString(QuicTag tag, string* out) const {
+ QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
if (it == tag_value_map_.end()) {
return false;
}
@@ -182,23 +182,28 @@ bool CryptoHandshakeMessage::GetString(CryptoTag tag, string* out) const {
return true;
}
-QuicErrorCode CryptoHandshakeMessage::GetUint16(CryptoTag tag,
+QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag,
uint16* out) const {
return GetPOD(tag, out, sizeof(uint16));
}
-QuicErrorCode CryptoHandshakeMessage::GetUint32(CryptoTag tag,
+QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag,
uint32* out) const {
return GetPOD(tag, out, sizeof(uint32));
}
+QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag,
+ uint64* out) const {
+ return GetPOD(tag, out, sizeof(uint64));
+}
+
string CryptoHandshakeMessage::DebugString() const {
return DebugStringInternal(0);
}
QuicErrorCode CryptoHandshakeMessage::GetPOD(
- CryptoTag tag, void* out, size_t len) const {
- CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag);
+ QuicTag tag, void* out, size_t len) const {
+ QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
QuicErrorCode ret = QUIC_NO_ERROR;
if (it == tag_value_map_.end()) {
@@ -220,10 +225,10 @@ QuicErrorCode CryptoHandshakeMessage::GetPOD(
// that converts a tag to a string. It will try to maintain the human friendly
// name if possible (i.e. kABCD -> "ABCD"), or will just treat it as a number
// if not.
-static string TagToString(CryptoTag tag) {
+static string TagToString(QuicTag tag) {
char chars[4];
bool ascii = true;
- const CryptoTag orig_tag = tag;
+ const QuicTag orig_tag = tag;
for (size_t i = 0; i < sizeof(chars); i++) {
chars[i] = tag;
@@ -247,52 +252,52 @@ static string TagToString(CryptoTag tag) {
string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
string ret = string(2 * indent, ' ') + TagToString(tag_) + "<\n";
++indent;
- for (CryptoTagValueMap::const_iterator it = tag_value_map_.begin();
+ for (QuicTagValueMap::const_iterator it = tag_value_map_.begin();
it != tag_value_map_.end(); ++it) {
ret += string(2 * indent, ' ') + TagToString(it->first) + ": ";
bool done = false;
switch (it->first) {
- case kKATO:
- case kVERS:
- // uint32 value
- if (it->second.size() == 4) {
- uint32 value;
- memcpy(&value, it->second.data(), sizeof(value));
- ret += base::UintToString(value);
- done = true;
- }
- break;
- case kKEXS:
- case kAEAD:
- case kCGST:
- case kPDMD:
- // tag lists
- if (it->second.size() % sizeof(CryptoTag) == 0) {
- for (size_t j = 0; j < it->second.size(); j += sizeof(CryptoTag)) {
- CryptoTag tag;
- memcpy(&tag, it->second.data() + j, sizeof(tag));
- if (j > 0) {
- ret += ",";
- }
- ret += TagToString(tag);
+ case kKATO:
+ case kVERS:
+ // uint32 value
+ if (it->second.size() == 4) {
+ uint32 value;
+ memcpy(&value, it->second.data(), sizeof(value));
+ ret += base::UintToString(value);
+ done = true;
}
- done = true;
- }
- break;
- case kSCFG:
- // nested messages.
- if (!it->second.empty()) {
- scoped_ptr<CryptoHandshakeMessage> msg(
- CryptoFramer::ParseMessage(it->second));
- if (msg.get()) {
- ret += "\n";
- ret += msg->DebugStringInternal(indent + 1);
-
+ break;
+ case kKEXS:
+ case kAEAD:
+ case kCGST:
+ case kPDMD:
+ // tag lists
+ if (it->second.size() % sizeof(QuicTag) == 0) {
+ for (size_t j = 0; j < it->second.size(); j += sizeof(QuicTag)) {
+ QuicTag tag;
+ memcpy(&tag, it->second.data() + j, sizeof(tag));
+ if (j > 0) {
+ ret += ",";
+ }
+ ret += TagToString(tag);
+ }
done = true;
}
- }
- break;
+ break;
+ case kSCFG:
+ // nested messages.
+ if (!it->second.empty()) {
+ scoped_ptr<CryptoHandshakeMessage> msg(
+ CryptoFramer::ParseMessage(it->second));
+ if (msg.get()) {
+ ret += "\n";
+ ret += msg->DebugStringInternal(indent + 1);
+
+ done = true;
+ }
+ }
+ break;
}
if (!done) {
@@ -313,16 +318,20 @@ QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters()
aead(0) {
}
-QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {
-}
+QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {}
+CrypterPair::CrypterPair() {}
+CrypterPair::~CrypterPair() {}
// static
-const char QuicCryptoConfig::kLabel[] = "QUIC key expansion";
+const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion";
+
+const char QuicCryptoConfig::kForwardSecureLabel[] =
+ "QUIC forward secure key expansion";
QuicCryptoConfig::QuicCryptoConfig()
: version(0),
- common_cert_set_(new CommonCertSetQUIC) {
+ common_cert_set_(new CommonCertSetsQUIC) {
}
QuicCryptoConfig::~QuicCryptoConfig() {}
@@ -355,8 +364,7 @@ QuicCryptoClientConfig::CachedState::GetServerConfig() const {
return scfg_.get();
}
-bool QuicCryptoClientConfig::CachedState::SetServerConfig(
- StringPiece scfg) {
+bool QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece scfg) {
scfg_.reset(CryptoFramer::ParseMessage(scfg));
if (!scfg_.get()) {
return false;
@@ -365,8 +373,8 @@ bool QuicCryptoClientConfig::CachedState::SetServerConfig(
return true;
}
-void QuicCryptoClientConfig::CachedState::SetProof(
- const vector<string>& certs, StringPiece signature) {
+void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
+ StringPiece signature) {
bool has_changed = signature != server_config_sig_;
if (certs_.size() != certs.size()) {
@@ -395,8 +403,7 @@ void QuicCryptoClientConfig::CachedState::SetProofValid() {
server_config_valid_ = true;
}
-const string&
-QuicCryptoClientConfig::CachedState::server_config() const {
+const string& QuicCryptoClientConfig::CachedState::server_config() const {
return server_config_;
}
@@ -466,7 +473,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
out->SetValue(kVERS, version);
if (!cached->source_address_token().empty()) {
- out->SetStringPiece(kSRCT, cached->source_address_token());
+ out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
}
out->SetTaglist(kPDMD, kX509, 0);
@@ -476,6 +483,7 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
}
const vector<string>& certs = cached->certs();
+ out_params->cached_certs = certs;
if (!certs.empty()) {
vector<uint64> hashes;
hashes.reserve(certs.size());
@@ -488,7 +496,6 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
// client config is being used for multiple connections, another connection
// doesn't update the cached certificates and cause us to be unable to
// process the server's compressed certificate chain.
- out_params->cached_certs = certs;
}
}
@@ -496,7 +503,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
const string& server_hostname,
QuicGuid guid,
const CachedState* cached,
- const QuicClock* clock,
+ QuicWallTime now,
QuicRandom* rand,
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out,
@@ -513,6 +520,17 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
return QUIC_CRYPTO_INTERNAL_ERROR;
}
+ uint64 expiry_seconds;
+ if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
+ *error_details = "SCFG missing EXPY";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ if (static_cast<uint64>(now.ToUNIXSeconds()) >= expiry_seconds) {
+ *error_details = "SCFG expired";
+ return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
+ }
+
StringPiece scid;
if (!scfg->GetStringPiece(kSCID, &scid)) {
*error_details = "SCFG missing SCID";
@@ -527,8 +545,8 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
return QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
}
- const CryptoTag* their_aeads;
- const CryptoTag* their_key_exchanges;
+ const QuicTag* their_aeads;
+ const QuicTag* their_key_exchanges;
size_t num_their_aeads, num_their_key_exchanges;
if (scfg->GetTaglist(kAEAD, &their_aeads,
&num_their_aeads) != QUIC_NO_ERROR ||
@@ -539,16 +557,13 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
}
size_t key_exchange_index;
- if (!CryptoUtils::FindMutualTag(aead,
- their_aeads, num_their_aeads,
- CryptoUtils::PEER_PRIORITY,
- &out_params->aead,
+ if (!CryptoUtils::FindMutualTag(aead, their_aeads, num_their_aeads,
+ CryptoUtils::PEER_PRIORITY, &out_params->aead,
NULL) ||
- !CryptoUtils::FindMutualTag(kexs,
- their_key_exchanges, num_their_key_exchanges,
- CryptoUtils::PEER_PRIORITY,
- &out_params->key_exchange,
- &key_exchange_index)) {
+ !CryptoUtils::FindMutualTag(
+ kexs, their_key_exchanges, num_their_key_exchanges,
+ CryptoUtils::PEER_PRIORITY, &out_params->key_exchange,
+ &key_exchange_index)) {
*error_details = "Unsupported AEAD or KEXS";
return QUIC_CRYPTO_NO_SUPPORT;
}
@@ -556,7 +571,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
out->SetTaglist(kKEXS, out_params->key_exchange, 0);
StringPiece public_value;
- if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) !=
+ if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
QUIC_NO_ERROR) {
*error_details = "Missing public value";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
@@ -568,44 +583,52 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
- string nonce;
- CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit,
- &nonce);
- out->SetStringPiece(kNONC, nonce);
+ CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
+ out->SetStringPiece(kNONC, out_params->client_nonce);
+ if (!out_params->server_nonce.empty()) {
+ out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
+ }
- scoped_ptr<KeyExchange> key_exchange;
switch (out_params->key_exchange) {
- case kC255:
- key_exchange.reset(Curve25519KeyExchange::New(
+ case kC255:
+ out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
Curve25519KeyExchange::NewPrivateKey(rand)));
- break;
- case kP256:
- key_exchange.reset(P256KeyExchange::New(
- P256KeyExchange::NewPrivateKey()));
- break;
- default:
- DCHECK(false);
- *error_details = "Configured to support an unknown key exchange";
- return QUIC_CRYPTO_INTERNAL_ERROR;
+ break;
+ case kP256:
+ out_params->client_key_exchange
+ .reset(P256KeyExchange::New(P256KeyExchange::NewPrivateKey()));
+ break;
+ default:
+ DCHECK(false);
+ *error_details = "Configured to support an unknown key exchange";
+ return QUIC_CRYPTO_INTERNAL_ERROR;
}
- if (!key_exchange->CalculateSharedKey(public_value,
- &out_params->premaster_secret)) {
+ if (!out_params->client_key_exchange->CalculateSharedKey(
+ public_value, &out_params->initial_premaster_secret)) {
*error_details = "Key exchange failure";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
- out->SetStringPiece(kPUBS, key_exchange->public_value());
-
- string hkdf_input(QuicCryptoConfig::kLabel,
- strlen(QuicCryptoConfig::kLabel) + 1);
- hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
+ out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
+ out_params->hkdf_input_suffix.clear();
+ out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid),
+ sizeof(guid));
const QuicData& client_hello_serialized = out->GetSerialized();
- hkdf_input.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- hkdf_input.append(cached->server_config());
+ out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
+ client_hello_serialized.length());
+ out_params->hkdf_input_suffix.append(cached->server_config());
- CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT);
+ string hkdf_input;
+ const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
+ hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
+ hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
+ hkdf_input.append(out_params->hkdf_input_suffix);
+
+ CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
+ out_params->aead, out_params->client_nonce,
+ out_params->server_nonce, hkdf_input,
+ CryptoUtils::CLIENT, &out_params->initial_crypters);
return QUIC_NO_ERROR;
}
@@ -629,19 +652,19 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
}
StringPiece token;
- if (rej.GetStringPiece(kSRCT, &token)) {
+ if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
cached->set_source_address_token(token);
}
StringPiece nonce;
- if (rej.GetStringPiece(kNONC, &nonce) &&
- nonce.size() == kNonceSize) {
+ if (rej.GetStringPiece(kServerNonceTag, &nonce) && nonce.size() ==
+ kNonceSize) {
out_params->server_nonce = nonce.as_string();
}
StringPiece proof, cert_bytes;
if (rej.GetStringPiece(kPROF, &proof) &&
- rej.GetStringPiece(kCERT, &cert_bytes)) {
+ rej.GetStringPiece(kCertificateTag, &cert_bytes)) {
vector<string> certs;
if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
common_cert_set_.get(), &certs)) {
@@ -657,7 +680,7 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
const CryptoHandshakeMessage& server_hello,
- const string& nonce,
+ QuicGuid guid,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
DCHECK(error_details != NULL);
@@ -669,7 +692,29 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
// TODO(agl):
// learn about updated SCFGs.
- // read ephemeral public value for forward-secret keys.
+
+ StringPiece public_value;
+ if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
+ *error_details = "server hello missing forward secure public value";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ if (!out_params->client_key_exchange->CalculateSharedKey(
+ public_value, &out_params->forward_secure_premaster_secret)) {
+ *error_details = "Key exchange failure";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ string hkdf_input;
+ const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
+ hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
+ hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
+ hkdf_input.append(out_params->hkdf_input_suffix);
+
+ CryptoUtils::DeriveKeys(
+ out_params->forward_secure_premaster_secret, out_params->aead,
+ out_params->client_nonce, out_params->server_nonce, hkdf_input,
+ CryptoUtils::CLIENT, &out_params->forward_secure_crypters);
return QUIC_NO_ERROR;
}
diff --git a/net/quic/crypto/crypto_handshake.h b/net/quic/crypto/crypto_handshake.h
index 624471e..6b6c320 100644
--- a/net/quic/crypto/crypto_handshake.h
+++ b/net/quic/crypto/crypto_handshake.h
@@ -18,10 +18,9 @@
namespace net {
-class CommonCertSet;
+class CommonCertSets;
class KeyExchange;
class ProofVerifier;
-class QuicClock;
class QuicDecrypter;
class QuicEncrypter;
class QuicRandom;
@@ -45,14 +44,14 @@ class NET_EXPORT_PRIVATE CryptoHandshakeMessage {
// SetValue sets an element with the given tag to the raw, memory contents of
// |v|.
- template<class T> void SetValue(CryptoTag tag, const T& v) {
- tag_value_map_[tag] = std::string(reinterpret_cast<const char*>(&v),
- sizeof(v));
+ template<class T> void SetValue(QuicTag tag, const T& v) {
+ tag_value_map_[tag] =
+ std::string(reinterpret_cast<const char*>(&v), sizeof(v));
}
// SetVector sets an element with the given tag to the raw contents of an
// array of elements in |v|.
- template<class T> void SetVector(CryptoTag tag, const std::vector<T>& v) {
+ template<class T> void SetVector(QuicTag tag, const std::vector<T>& v) {
if (v.empty()) {
tag_value_map_[tag] = std::string();
} else {
@@ -62,40 +61,41 @@ class NET_EXPORT_PRIVATE CryptoHandshakeMessage {
}
// Returns the message tag.
- CryptoTag tag() const { return tag_; }
+ QuicTag tag() const { return tag_; }
// Sets the message tag.
- void set_tag(CryptoTag tag) { tag_ = tag; }
+ void set_tag(QuicTag tag) { tag_ = tag; }
- const CryptoTagValueMap& tag_value_map() const { return tag_value_map_; }
+ const QuicTagValueMap& tag_value_map() const { return tag_value_map_; }
- void Insert(CryptoTagValueMap::const_iterator begin,
- CryptoTagValueMap::const_iterator end);
+ void Insert(QuicTagValueMap::const_iterator begin,
+ QuicTagValueMap::const_iterator end);
// SetTaglist sets an element with the given tag to contain a list of tags,
// passed as varargs. The argument list must be terminated with a 0 element.
- void SetTaglist(CryptoTag tag, ...);
+ void SetTaglist(QuicTag tag, ...);
- void SetStringPiece(CryptoTag tag, base::StringPiece value);
+ void SetStringPiece(QuicTag tag, base::StringPiece value);
// GetTaglist finds an element with the given tag containing zero or more
// tags. If such a tag doesn't exist, it returns false. Otherwise it sets
// |out_tags| and |out_len| to point to the array of tags and returns true.
// The array points into the CryptoHandshakeMessage and is valid only for as
// long as the CryptoHandshakeMessage exists and is not modified.
- QuicErrorCode GetTaglist(CryptoTag tag, const CryptoTag** out_tags,
+ QuicErrorCode GetTaglist(QuicTag tag, const QuicTag** out_tags,
size_t* out_len) const;
- bool GetStringPiece(CryptoTag tag, base::StringPiece* out) const;
+ bool GetStringPiece(QuicTag tag, base::StringPiece* out) const;
- // GetNthValue16 interprets the value with the given tag to be a series of
- // 16-bit length prefixed values and it returns the subvalue with the given
+ // GetNthValue24 interprets the value with the given tag to be a series of
+ // 24-bit, length prefixed values and it returns the subvalue with the given
// index.
- QuicErrorCode GetNthValue16(CryptoTag tag,
+ QuicErrorCode GetNthValue24(QuicTag tag,
unsigned index,
base::StringPiece* out) const;
- bool GetString(CryptoTag tag, std::string* out) const;
- QuicErrorCode GetUint16(CryptoTag tag, uint16* out) const;
- QuicErrorCode GetUint32(CryptoTag tag, uint32* out) const;
+ bool GetString(QuicTag tag, std::string* out) const;
+ QuicErrorCode GetUint16(QuicTag tag, uint16* out) const;
+ QuicErrorCode GetUint32(QuicTag tag, uint32* out) const;
+ QuicErrorCode GetUint64(QuicTag tag, uint64* out) const;
// DebugString returns a multi-line, string representation of the message
// suitable for including in debug output.
@@ -109,18 +109,26 @@ class NET_EXPORT_PRIVATE CryptoHandshakeMessage {
//
// If used to copy integers then this assumes that the machine is
// little-endian.
- QuicErrorCode GetPOD(CryptoTag tag, void* out, size_t len) const;
+ QuicErrorCode GetPOD(QuicTag tag, void* out, size_t len) const;
std::string DebugStringInternal(size_t indent) const;
- CryptoTag tag_;
- CryptoTagValueMap tag_value_map_;
+ QuicTag tag_;
+ QuicTagValueMap tag_value_map_;
// The serialized form of the handshake message. This member is constructed
// lasily.
mutable scoped_ptr<QuicData> serialized_;
};
+// A CrypterPair contains the encrypter and decrypter for an encryption level.
+struct NET_EXPORT_PRIVATE CrypterPair {
+ CrypterPair();
+ ~CrypterPair();
+ scoped_ptr<QuicEncrypter> encrypter;
+ scoped_ptr<QuicDecrypter> decrypter;
+};
+
// Parameters negotiated by the crypto handshake.
struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters {
// Initializes the members to 0 or empty values.
@@ -128,16 +136,26 @@ struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters {
~QuicCryptoNegotiatedParameters();
uint16 version;
- CryptoTag key_exchange;
- CryptoTag aead;
- std::string premaster_secret;
- scoped_ptr<QuicEncrypter> encrypter;
- scoped_ptr<QuicDecrypter> decrypter;
+ QuicTag key_exchange;
+ QuicTag aead;
+ std::string initial_premaster_secret;
+ std::string forward_secure_premaster_secret;
+ CrypterPair initial_crypters;
+ CrypterPair forward_secure_crypters;
std::string server_config_id;
+ std::string client_nonce;
std::string server_nonce;
+ // hkdf_input_suffix contains the HKDF input following the label: the GUID,
+ // client hello and server config. This is only populated in the client
+ // because only the client needs to derive the forward secure keys at a later
+ // time from the initial keys.
+ std::string hkdf_input_suffix;
// cached_certs contains the cached certificates that a client used when
// sending a client hello.
std::vector<std::string> cached_certs;
+ // client_key_exchange is used by clients to store the ephemeral KeyExchange
+ // for the connection.
+ scoped_ptr<KeyExchange> client_key_exchange;
};
// QuicCryptoConfig contains common configuration between clients and servers.
@@ -149,9 +167,15 @@ class NET_EXPORT_PRIVATE QuicCryptoConfig {
CONFIG_VERSION = 0,
};
- // kLabel is constant that is used in key derivation to tie the resulting key
- // to this protocol.
- static const char kLabel[];
+ // kInitialLabel is a constant that is used when deriving the initial
+ // (non-forward secure) keys for the connection in order to tie the resulting
+ // key to this protocol.
+ static const char kInitialLabel[];
+
+ // kForwardSecureLabel is a constant that is used when deriving the forward
+ // secure keys for the connection in order to tie the resulting key to this
+ // protocol.
+ static const char kForwardSecureLabel[];
QuicCryptoConfig();
~QuicCryptoConfig();
@@ -160,11 +184,11 @@ class NET_EXPORT_PRIVATE QuicCryptoConfig {
uint16 version;
// Key exchange methods. The following two members' values correspond by
// index.
- CryptoTagVector kexs;
+ QuicTagVector kexs;
// Authenticated encryption with associated data (AEAD) algorithms.
- CryptoTagVector aead;
+ QuicTagVector aead;
- scoped_ptr<CommonCertSet> common_cert_set_;
+ scoped_ptr<CommonCertSets> common_cert_set_;
private:
DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig);
@@ -215,12 +239,12 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
void set_source_address_token(base::StringPiece token);
private:
- std::string server_config_id_; // An opaque id from the server.
- std::string server_config_; // A serialized handshake message.
+ std::string server_config_id_; // An opaque id from the server.
+ std::string server_config_; // A serialized handshake message.
std::string source_address_token_; // An opaque proof of IP ownership.
- std::vector<std::string> certs_; // A list of certificates in leaf-first
- // order.
- std::string server_config_sig_; // A signature of |server_config_|.
+ std::vector<std::string> certs_; // A list of certificates in leaf-first
+ // order.
+ std::string server_config_sig_; // A signature of |server_config_|.
bool server_config_valid_; // true if |server_config_| is correctly signed
// and |certs_| has been validated.
@@ -240,7 +264,9 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// FillInchoateClientHello sets |out| to be a CHLO message that elicits a
// source-address token or SCFG from a server. If |cached| is non-NULL, the
- // source-address token will be taken from it.
+ // source-address token will be taken from it. |out_params| is used in order
+ // to store the cached certs that were sent as hints to the server in
+ // |out_params->cached_certs|.
void FillInchoateClientHello(const std::string& server_hostname,
const CachedState* cached,
QuicCryptoNegotiatedParameters* out_params,
@@ -257,7 +283,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
QuicErrorCode FillClientHello(const std::string& server_hostname,
QuicGuid guid,
const CachedState* cached,
- const QuicClock* clock,
+ QuicWallTime now,
QuicRandom* rand,
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out,
@@ -278,7 +304,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// |server_hello| is unacceptable then it puts an error message in
// |error_details| and returns an error code.
QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
- const std::string& nonce,
+ QuicGuid guid,
QuicCryptoNegotiatedParameters* out_params,
std::string* error_details);
diff --git a/net/quic/crypto/crypto_handshake_test.cc b/net/quic/crypto/crypto_handshake_test.cc
index 7ff0b1f..f3d86a5 100644
--- a/net/quic/crypto/crypto_handshake_test.cc
+++ b/net/quic/crypto/crypto_handshake_test.cc
@@ -21,18 +21,17 @@ namespace test {
class QuicCryptoServerConfigPeer {
public:
explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
- : server_config_(server_config) {
- }
+ : server_config_(server_config) {}
string NewSourceAddressToken(IPEndPoint ip,
QuicRandom* rand,
- QuicTime::Delta now) {
+ QuicWallTime now) {
return server_config_->NewSourceAddressToken(ip, rand, now);
}
bool ValidateSourceAddressToken(StringPiece srct,
IPEndPoint ip,
- QuicTime::Delta now) {
+ QuicWallTime now) {
return server_config_->ValidateSourceAddressToken(srct, ip, now);
}
@@ -46,7 +45,8 @@ TEST(QuicCryptoServerConfigTest, ServerConfig) {
CryptoHandshakeMessage extra_tags;
scoped_ptr<CryptoHandshakeMessage>(
- server.AddDefaultConfig(QuicRandom::GetInstance(), &clock, extra_tags));
+ server.AddDefaultConfig(QuicRandom::GetInstance(), &clock, extra_tags,
+ QuicCryptoServerConfig::kDefaultExpiry));
}
TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
@@ -63,10 +63,11 @@ TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
IPEndPoint ip6 = IPEndPoint(ip, 2);
QuicRandom* rand = QuicRandom::GetInstance();
MockClock clock;
+ clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
QuicCryptoServerConfigPeer peer(&server);
- QuicTime::Delta now = clock.NowAsDeltaSinceUnixEpoch();
- const QuicTime::Delta original_time = now;
+ QuicWallTime now = clock.WallNow();
+ const QuicWallTime original_time = now;
const string token4 = peer.NewSourceAddressToken(ip4, rand, now);
const string token6 = peer.NewSourceAddressToken(ip6, rand, now);
diff --git a/net/quic/crypto/crypto_protocol.h b/net/quic/crypto/crypto_protocol.h
index 213e909..32ec7b1 100644
--- a/net/quic/crypto/crypto_protocol.h
+++ b/net/quic/crypto/crypto_protocol.h
@@ -9,8 +9,8 @@
#include <string>
#include <vector>
-#include "base/basictypes.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_protocol.h"
// Version and Crypto tags are written to the wire with a big-endian
// representation of the name of the tag. For example
@@ -20,60 +20,77 @@
// to reverse the order of the bytes.
//
// We use a macro to ensure that no static initialisers are created. Use the
-// QuicTag function in normal code.
+// MakeQuicTag function in normal code.
#define TAG(a, b, c, d) ((d << 24) + (c << 16) + (b << 8) + a)
namespace net {
-// CryptoTag is the type of a tag in the wire protocol.
-typedef uint32 CryptoTag;
typedef std::string ServerConfigID;
-typedef std::map<CryptoTag, std::string> CryptoTagValueMap;
-typedef std::vector<CryptoTag> CryptoTagVector;
+typedef std::map<QuicTag, std::string> QuicTagValueMap;
-const CryptoTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
-const CryptoTag kSHLO = TAG('S', 'H', 'L', 'O'); // Server hello
-const CryptoTag kSCFG = TAG('S', 'C', 'F', 'G'); // Server config
-const CryptoTag kREJ = TAG('R', 'E', 'J', '\0'); // Reject
+const QuicTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
+const QuicTag kSHLO = TAG('S', 'H', 'L', 'O'); // Server hello
+const QuicTag kSCFG = TAG('S', 'C', 'F', 'G'); // Server config
+const QuicTag kREJ = TAG('R', 'E', 'J', '\0'); // Reject
// Key exchange methods
-const CryptoTag kP256 = TAG('P', '2', '5', '6'); // ECDH, Curve P-256
-const CryptoTag kC255 = TAG('C', '2', '5', '5'); // ECDH, Curve25519
+const QuicTag kP256 = TAG('P', '2', '5', '6'); // ECDH, Curve P-256
+const QuicTag kC255 = TAG('C', '2', '5', '5'); // ECDH, Curve25519
// AEAD algorithms
-const CryptoTag kNULL = TAG('N', 'U', 'L', 'L'); // null algorithm
-const CryptoTag kAESG = TAG('A', 'E', 'S', 'G'); // AES128 + GCM
+const QuicTag kNULL = TAG('N', 'U', 'L', 'L'); // null algorithm
+const QuicTag kAESG = TAG('A', 'E', 'S', 'G'); // AES128 + GCM
// Congestion control feedback types
-const CryptoTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
-const CryptoTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
+const QuicTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
+const QuicTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
// Proof types (i.e. certificate types)
-const CryptoTag kX509 = TAG('X', '5', '0', '9'); // X.509 certificate
+const QuicTag kX509 = TAG('X', '5', '0', '9'); // X.509 certificate
// Client hello tags
-const CryptoTag kVERS = TAG('V', 'E', 'R', 'S'); // Version
-const CryptoTag kNONC = TAG('N', 'O', 'N', 'C'); // The connection nonce
-const CryptoTag kSSID = TAG('S', 'S', 'I', 'D'); // Session ID
-const CryptoTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
-const CryptoTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
- // encryption algorithms
-const CryptoTag kCGST = TAG('C', 'G', 'S', 'T'); // Congestion control
- // feedback types
-const CryptoTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle connection state
- // lifetime
-const CryptoTag kKATO = TAG('K', 'A', 'T', 'O'); // Keepalive timeout
-const CryptoTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
- // indication
-const CryptoTag kPUBS = TAG('P', 'U', 'B', 'S'); // Public key values
-const CryptoTag kSCID = TAG('S', 'C', 'I', 'D'); // Server config id
-const CryptoTag kSRCT = TAG('S', 'R', 'C', 'T'); // Source-address token
-const CryptoTag kORBT = TAG('O', 'B', 'I', 'T'); // Server orbit.
-const CryptoTag kPDMD = TAG('P', 'D', 'M', 'D'); // Proof demand.
-const CryptoTag kCERT = TAG('C', 'E', 'R', 'T'); // Certificate chain
-const CryptoTag kPROF = TAG('P', 'R', 'O', 'F'); // Proof (signature).
-const CryptoTag kCCS = TAG('C', 'C', 'S', 0); // Common certificate set
-const CryptoTag kCCRT = TAG('C', 'C', 'R', 'T'); // Cached certificate
+const QuicTag kVERS = TAG('V', 'E', 'R', 'S'); // Version
+const QuicTag kNONC = TAG('N', 'O', 'N', 'C'); // The client's nonce
+const QuicTag kSSID = TAG('S', 'S', 'I', 'D'); // Session ID
+const QuicTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
+const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
+ // encryption algorithms
+const QuicTag kCGST = TAG('C', 'G', 'S', 'T'); // Congestion control
+ // feedback types
+const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle connection state
+ // lifetime
+const QuicTag kKATO = TAG('K', 'A', 'T', 'O'); // Keepalive timeout
+const QuicTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
+ // indication
+const QuicTag kPUBS = TAG('P', 'U', 'B', 'S'); // Public key values
+const QuicTag kSCID = TAG('S', 'C', 'I', 'D'); // Server config id
+const QuicTag kORBT = TAG('O', 'B', 'I', 'T'); // Server orbit.
+const QuicTag kPDMD = TAG('P', 'D', 'M', 'D'); // Proof demand.
+const QuicTag kPROF = TAG('P', 'R', 'O', 'F'); // Proof (signature).
+const QuicTag kCCS = TAG('C', 'C', 'S', 0); // Common certificate set
+const QuicTag kCCRT = TAG('C', 'C', 'R', 'T'); // Cached certificate
+const QuicTag kEXPY = TAG('E', 'X', 'P', 'Y'); // Expiry
+
+// These tags have a special form so that they appear either at the beginning
+// or the end of a handshake message. Since handshake messages are sorted by
+// tag value, the tags with 0 at the end will sort first and those with 255 at
+// the end will sort last.
+//
+// The certificate chain should have a tag that will cause it to be sorted at
+// the end of any handshake messages because it's likely to be large and the
+// client might be able to get everything that it needs from the small values at
+// the beginning.
+//
+// Likewise tags with random values should be towards the beginning of the
+// message because the server mightn't hold state for a rejected client hello
+// and therefore the client may have issues reassembling the rejection message
+// in the event that it sent two client hellos.
+const QuicTag kServerNonceTag =
+ TAG('S', 'N', 'O', 0); // The server's nonce
+const QuicTag kSourceAddressTokenTag =
+ TAG('S', 'T', 'K', 0); // Source-address token
+const QuicTag kCertificateTag =
+ TAG('C', 'R', 'T', 255); // Certificate chain
#undef TAG
diff --git a/net/quic/crypto/crypto_server_config.cc b/net/quic/crypto/crypto_server_config.cc
index 953f57c..e4ee400 100644
--- a/net/quic/crypto/crypto_server_config.cc
+++ b/net/quic/crypto/crypto_server_config.cc
@@ -14,6 +14,7 @@
#include "net/quic/crypto/crypto_server_config_protobuf.h"
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/crypto/curve25519_key_exchange.h"
+#include "net/quic/crypto/ephemeral_key_source.h"
#include "net/quic/crypto/key_exchange.h"
#include "net/quic/crypto/p256_key_exchange.h"
#include "net/quic/crypto/proof_source.h"
@@ -52,7 +53,7 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
: strike_register_lock_(),
source_address_token_encrypter_(new Aes128GcmEncrypter),
source_address_token_decrypter_(new Aes128GcmDecrypter) {
- crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
+ crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
"QUIC source address token key",
source_address_token_encrypter_->GetKeySize(),
0 /* no fixed IV needed */);
@@ -68,7 +69,8 @@ QuicCryptoServerConfig::~QuicCryptoServerConfig() {
QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
QuicRandom* rand,
const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags) {
+ const CryptoHandshakeMessage& extra_tags,
+ uint64 expiry_time) {
CryptoHandshakeMessage msg;
const string curve25519_private_key =
@@ -77,20 +79,20 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
Curve25519KeyExchange::New(curve25519_private_key));
StringPiece curve25519_public_value = curve25519->public_value();
- const string p256_private_key =
- P256KeyExchange::NewPrivateKey();
- scoped_ptr<P256KeyExchange> p256(
- P256KeyExchange::New(p256_private_key));
+ const string p256_private_key = P256KeyExchange::NewPrivateKey();
+ scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
StringPiece p256_public_value = p256->public_value();
string encoded_public_values;
- // First two bytes encode the length of the public value.
+ // First three bytes encode the length of the public value.
encoded_public_values.push_back(curve25519_public_value.size());
encoded_public_values.push_back(curve25519_public_value.size() >> 8);
+ encoded_public_values.push_back(curve25519_public_value.size() >> 16);
encoded_public_values.append(curve25519_public_value.data(),
curve25519_public_value.size());
encoded_public_values.push_back(p256_public_value.size());
encoded_public_values.push_back(p256_public_value.size() >> 8);
+ encoded_public_values.push_back(p256_public_value.size() >> 16);
encoded_public_values.append(p256_public_value.data(),
p256_public_value.size());
@@ -102,6 +104,16 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
msg.Insert(extra_tags.tag_value_map().begin(),
extra_tags.tag_value_map().end());
+ if (expiry_time == 0) {
+ const QuicWallTime now = clock->WallNow();
+ const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
+ 60 * 60 * 24 * 180 /* 180 days, ~six months */));
+ const uint64 expiry_seconds = expiry.ToUNIXSeconds();
+ msg.SetValue(kEXPY, expiry_seconds);
+ } else {
+ msg.SetValue(kEXPY, expiry_time);
+ }
+
char scid_bytes[16];
rand->RandBytes(scid_bytes, sizeof(scid_bytes));
msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
@@ -110,8 +122,7 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
- scoped_ptr<QuicData> serialized(
- CryptoFramer::ConstructHandshakeMessage(msg));
+ scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
config->set_config(serialized->AsStringPiece());
@@ -135,9 +146,8 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
return NULL;
}
if (msg->tag() != kSCFG) {
- LOG(WARNING) << "Server config message has tag "
- << msg->tag() << " expected "
- << kSCFG;
+ LOG(WARNING) << "Server config message has tag " << msg->tag()
+ << " expected " << kSCFG;
return NULL;
}
@@ -151,15 +161,15 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
}
config->id = scid.as_string();
- const CryptoTag* aead_tags;
+ const QuicTag* aead_tags;
size_t aead_len;
if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
LOG(WARNING) << "Server config message is missing AEAD";
return NULL;
}
- config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len);
+ config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
- const CryptoTag* kexs_tags;
+ const QuicTag* kexs_tags;
size_t kexs_len;
if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
LOG(WARNING) << "Server config message is missing KEXS";
@@ -181,16 +191,14 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
if (kexs_len != protobuf->key_size()) {
- LOG(WARNING) << "Server config has "
- << kexs_len
+ LOG(WARNING) << "Server config has " << kexs_len
<< " key exchange methods configured, but "
- << protobuf->key_size()
- << " private keys";
+ << protobuf->key_size() << " private keys";
return NULL;
}
for (size_t i = 0; i < kexs_len; i++) {
- const CryptoTag tag = kexs_tags[i];
+ const QuicTag tag = kexs_tags[i];
string private_key;
config->kexs.push_back(tag);
@@ -205,34 +213,32 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
if (private_key.empty()) {
LOG(WARNING) << "Server config contains key exchange method without "
- "corresponding private key: "
- << tag;
+ "corresponding private key: " << tag;
return NULL;
}
scoped_ptr<KeyExchange> ka;
switch (tag) {
- case kC255:
- ka.reset(Curve25519KeyExchange::New(private_key));
- if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid curve25519"
- " private key.";
- return NULL;
- }
- break;
- case kP256:
- ka.reset(P256KeyExchange::New(private_key));
- if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid P-256"
- " private key.";
+ case kC255:
+ ka.reset(Curve25519KeyExchange::New(private_key));
+ if (!ka.get()) {
+ LOG(WARNING) << "Server config contained an invalid curve25519"
+ " private key.";
+ return NULL;
+ }
+ break;
+ case kP256:
+ ka.reset(P256KeyExchange::New(private_key));
+ if (!ka.get()) {
+ LOG(WARNING) << "Server config contained an invalid P-256"
+ " private key.";
+ return NULL;
+ }
+ break;
+ default:
+ LOG(WARNING) << "Server config message contains unknown key exchange "
+ "method: " << tag;
return NULL;
- }
- break;
- default:
- LOG(WARNING) << "Server config message contains unknown key exchange "
- "method: "
- << tag;
- return NULL;
}
for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
@@ -271,9 +277,10 @@ CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
QuicRandom* rand,
const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags) {
+ const CryptoHandshakeMessage& extra_tags,
+ uint64 expiry_time) {
scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig(
- rand, clock, extra_tags));
+ rand, clock, extra_tags, expiry_time));
return AddConfig(config.get());
}
@@ -281,7 +288,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
const CryptoHandshakeMessage& client_hello,
QuicGuid guid,
const IPEndPoint& client_ip,
- QuicTime::Delta now_since_unix_epoch,
+ const QuicClock* clock,
QuicRandom* rand,
QuicCryptoNegotiatedParameters *params,
CryptoHandshakeMessage* out,
@@ -299,15 +306,16 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
}
const Config* const config(it->second);
+ const QuicWallTime now = clock->WallNow();
bool valid_source_address_token = false;
StringPiece srct;
- if (client_hello.GetStringPiece(kSRCT, &srct) &&
- ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) {
+ if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
+ ValidateSourceAddressToken(srct, client_ip, now)) {
valid_source_address_token = true;
}
const string fresh_source_address_token =
- NewSourceAddressToken(client_ip, rand, now_since_unix_epoch);
+ NewSourceAddressToken(client_ip, rand, now);
// If we previously sent a REJ to this client then we may have stored a
// server nonce in |params|. In which case, we know that the connection
@@ -328,14 +336,18 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
strike_register_.reset(new StrikeRegister(
// TODO(agl): these magic numbers should come from config.
1024 /* max entries */,
- static_cast<uint32>(now_since_unix_epoch.ToSeconds()),
+ static_cast<uint32>(now.ToUNIXSeconds()),
600 /* window secs */, config->orbit));
}
unique_by_strike_register = strike_register_->Insert(
reinterpret_cast<const uint8*>(client_nonce.data()),
- static_cast<uint32>(now_since_unix_epoch.ToSeconds()));
+ static_cast<uint32>(now.ToUNIXSeconds()));
}
+ StringPiece server_nonce;
+ client_hello.GetStringPiece(kServerNonceTag, &server_nonce);
+ const bool server_nonce_matches = server_nonce == params->server_nonce;
+
out->Clear();
StringPiece sni;
@@ -346,6 +358,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
scid.as_string() != config->id ||
!valid_source_address_token ||
!client_nonce_well_formed ||
+ !server_nonce_matches ||
(!unique_by_strike_register &&
!unique_by_server_nonce)) {
// If the client didn't provide a server config ID, or gave the wrong one,
@@ -353,22 +366,20 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
// give the client enough information to do better next time.
out->set_tag(kREJ);
out->SetStringPiece(kSCFG, config->serialized);
- out->SetStringPiece(kSRCT, fresh_source_address_token);
+ out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token);
if (params->server_nonce.empty()) {
CryptoUtils::GenerateNonce(
- now_since_unix_epoch, rand,
- StringPiece(reinterpret_cast<const char*>(config->orbit),
- sizeof(config->orbit)),
+ now, rand, StringPiece(reinterpret_cast<const char*>(config->orbit),
+ sizeof(config->orbit)),
&params->server_nonce);
}
- out->SetStringPiece(kNONC, params->server_nonce);
+ out->SetStringPiece(kServerNonceTag, params->server_nonce);
// The client may have requested a certificate chain.
- const CryptoTag* their_proof_demands;
+ const QuicTag* their_proof_demands;
size_t num_their_proof_demands;
- if (proof_source_.get() != NULL &&
- !sni.empty() &&
+ if (proof_source_.get() != NULL && !sni.empty() &&
client_hello.GetTaglist(kPDMD, &their_proof_demands,
&num_their_proof_demands) == QUIC_NO_ERROR) {
for (size_t i = 0; i < num_their_proof_demands; i++) {
@@ -398,7 +409,7 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
static const size_t kMaxUnverifiedSize = 400;
if (valid_source_address_token ||
signature.size() + compressed.size() < kMaxUnverifiedSize) {
- out->SetStringPiece(kCERT, compressed);
+ out->SetStringPiece(kCertificateTag, compressed);
out->SetStringPiece(kPROF, signature);
}
break;
@@ -408,8 +419,8 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
return QUIC_NO_ERROR;
}
- const CryptoTag* their_aeads;
- const CryptoTag* their_key_exchanges;
+ const QuicTag* their_aeads;
+ const QuicTag* their_key_exchanges;
size_t num_their_aeads, num_their_key_exchanges;
if (client_hello.GetTaglist(kAEAD, &their_aeads,
&num_their_aeads) != QUIC_NO_ERROR ||
@@ -422,16 +433,13 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
}
size_t key_exchange_index;
- if (!CryptoUtils::FindMutualTag(config->aead,
- their_aeads, num_their_aeads,
- CryptoUtils::LOCAL_PRIORITY,
- &params->aead,
+ if (!CryptoUtils::FindMutualTag(config->aead, their_aeads, num_their_aeads,
+ CryptoUtils::LOCAL_PRIORITY, &params->aead,
NULL) ||
- !CryptoUtils::FindMutualTag(config->kexs,
- their_key_exchanges, num_their_key_exchanges,
- CryptoUtils::LOCAL_PRIORITY,
- &params->key_exchange,
- &key_exchange_index)) {
+ !CryptoUtils::FindMutualTag(
+ config->kexs, their_key_exchanges, num_their_key_exchanges,
+ CryptoUtils::LOCAL_PRIORITY, &params->key_exchange,
+ &key_exchange_index)) {
*error_details = "Unsupported AEAD or KEXS";
return QUIC_CRYPTO_NO_SUPPORT;
}
@@ -442,28 +450,67 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
- if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey(
- public_value, &params->premaster_secret)) {
+ const KeyExchange* key_exchange = config->key_exchanges[key_exchange_index];
+ if (!key_exchange->CalculateSharedKey(public_value,
+ &params->initial_premaster_secret)) {
*error_details = "Invalid public value";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
params->server_config_id = scid.as_string();
- string hkdf_input(QuicCryptoConfig::kLabel,
- strlen(QuicCryptoConfig::kLabel) + 1);
- hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
-
+ string hkdf_suffix;
const QuicData& client_hello_serialized = client_hello.GetSerialized();
- hkdf_input.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- hkdf_input.append(config->serialized);
+ hkdf_suffix.reserve(sizeof(guid) + client_hello_serialized.length() +
+ config->serialized.size());
+ hkdf_suffix.append(reinterpret_cast<char*>(&guid), sizeof(guid));
+ hkdf_suffix.append(client_hello_serialized.data(),
+ client_hello_serialized.length());
+ hkdf_suffix.append(config->serialized);
+
+ string hkdf_input;
+ size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
+ hkdf_input.reserve(label_len + hkdf_suffix.size());
+ hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
+ hkdf_input.append(hkdf_suffix);
+
+ CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
+ client_nonce, params->server_nonce, hkdf_input,
+ CryptoUtils::SERVER, &params->initial_crypters);
+
+ string forward_secure_public_value;
+ if (ephemeral_key_source_.get()) {
+ params->forward_secure_premaster_secret =
+ ephemeral_key_source_->CalculateForwardSecureKey(
+ key_exchange, rand, clock->ApproximateNow(), public_value,
+ &forward_secure_public_value);
+ } else {
+ scoped_ptr<KeyExchange> forward_secure_key_exchange(
+ key_exchange->NewKeyPair(rand));
+ forward_secure_public_value =
+ forward_secure_key_exchange->public_value().as_string();
+ if (!forward_secure_key_exchange->CalculateSharedKey(
+ public_value, &params->forward_secure_premaster_secret)) {
+ *error_details = "Invalid public value";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+ }
- CryptoUtils::DeriveKeys(params, client_nonce, hkdf_input,
- CryptoUtils::SERVER);
+ string forward_secure_hkdf_input;
+ label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
+ forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
+ forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
+ label_len);
+ forward_secure_hkdf_input.append(hkdf_suffix);
+
+ CryptoUtils::DeriveKeys(params->forward_secure_premaster_secret, params->aead,
+ client_nonce, params->server_nonce,
+ forward_secure_hkdf_input, CryptoUtils::SERVER,
+ &params->forward_secure_crypters);
out->set_tag(kSHLO);
- out->SetStringPiece(kSRCT, fresh_source_address_token);
+ out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token);
+ out->SetStringPiece(kPUBS, forward_secure_public_value);
return QUIC_NO_ERROR;
}
@@ -471,19 +518,24 @@ void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
proof_source_.reset(proof_source);
}
+void QuicCryptoServerConfig::SetEphemeralKeySource(
+ EphemeralKeySource* ephemeral_key_source) {
+ ephemeral_key_source_.reset(ephemeral_key_source);
+}
+
string QuicCryptoServerConfig::NewSourceAddressToken(
const IPEndPoint& ip,
QuicRandom* rand,
- QuicTime::Delta now_since_epoch) const {
+ QuicWallTime now) const {
SourceAddressToken source_address_token;
source_address_token.set_ip(ip.ToString());
- source_address_token.set_timestamp(now_since_epoch.ToSeconds());
+ source_address_token.set_timestamp(now.ToUNIXSeconds());
string plaintext = source_address_token.SerializeAsString();
char nonce[12];
DCHECK_EQ(sizeof(nonce),
- source_address_token_encrypter_->GetNoncePrefixSize() +
- sizeof(QuicPacketSequenceNumber));
+ source_address_token_encrypter_->GetNoncePrefixSize() +
+ sizeof(QuicPacketSequenceNumber));
rand->RandBytes(nonce, sizeof(nonce));
size_t ciphertext_size =
@@ -493,8 +545,8 @@ string QuicCryptoServerConfig::NewSourceAddressToken(
memcpy(&result[0], &nonce, sizeof(nonce));
if (!source_address_token_encrypter_->Encrypt(
- StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext,
- reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) {
+ StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext,
+ reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) {
DCHECK(false);
return string();
}
@@ -505,11 +557,11 @@ string QuicCryptoServerConfig::NewSourceAddressToken(
bool QuicCryptoServerConfig::ValidateSourceAddressToken(
StringPiece token,
const IPEndPoint& ip,
- QuicTime::Delta now_since_epoch) const {
+ QuicWallTime now) const {
char nonce[12];
DCHECK_EQ(sizeof(nonce),
- source_address_token_encrypter_->GetNoncePrefixSize() +
- sizeof(QuicPacketSequenceNumber));
+ source_address_token_encrypter_->GetNoncePrefixSize() +
+ sizeof(QuicPacketSequenceNumber));
if (token.size() <= sizeof(nonce)) {
return false;
@@ -529,8 +581,8 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken(
size_t plaintext_length;
if (!source_address_token_decrypter_->Decrypt(
- StringPiece(nonce, sizeof(nonce)), StringPiece(), token,
- plaintext, &plaintext_length)) {
+ StringPiece(nonce, sizeof(nonce)), StringPiece(), token, plaintext,
+ &plaintext_length)) {
return false;
}
@@ -544,18 +596,18 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken(
return false;
}
- const QuicTime::Delta delta(now_since_epoch.Subtract(
- QuicTime::Delta::FromSeconds(source_address_token.timestamp())));
- const int64 delta_secs = delta.ToSeconds();
+ const QuicWallTime timestamp(
+ QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
+ const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
// TODO(agl): consider whether and how these magic values should be moved to
// a config.
- if (delta_secs < -3600) {
+ if (now.IsBefore(timestamp) && delta.ToSeconds() > 3600) {
// We only allow timestamps to be from an hour in the future.
return false;
}
- if (delta_secs > 86400) {
+ if (now.IsAfter(timestamp) && delta.ToSeconds() > 86400) {
// We allow one day into the past.
return false;
}
@@ -563,11 +615,8 @@ bool QuicCryptoServerConfig::ValidateSourceAddressToken(
return true;
}
-QuicCryptoServerConfig::Config::Config() {
-}
+QuicCryptoServerConfig::Config::Config() {}
-QuicCryptoServerConfig::Config::~Config() {
- STLDeleteElements(&key_exchanges);
-}
+QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
} // namespace net
diff --git a/net/quic/crypto/crypto_server_config.h b/net/quic/crypto/crypto_server_config.h
index 4986603..588d83d4 100644
--- a/net/quic/crypto/crypto_server_config.h
+++ b/net/quic/crypto/crypto_server_config.h
@@ -16,6 +16,7 @@
namespace net {
+class EphemeralKeySource;
class KeyExchange;
class ProofSource;
class QuicClock;
@@ -36,6 +37,12 @@ class QuicCryptoServerConfigPeer;
// need to consider locking.
class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
public:
+ enum {
+ // kDefaultExpiry can be passed to DefaultConfig to select the default
+ // expiry time.
+ kDefaultExpiry = 0,
+ };
+
// |source_address_token_secret|: secret key material used for encrypting and
// decrypting source address tokens. It can be of any length as it is fed
// into a KDF before use. In tests, use TESTING.
@@ -46,25 +53,29 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// TESTING is a magic parameter for passing to the constructor in tests.
static const char TESTING[];
- // DefaultConfig generates a QuicServerConfigProtobuf protobuf suitable
- // for using in tests. |extra_tags| contains additional key/value pairs that
- // will be inserted into the config.
+ // DefaultConfig generates a QuicServerConfigProtobuf protobuf suitable for
+ // using in tests. |extra_tags| contains additional key/value pairs that will
+ // be inserted into the config. If |expiry_time| is non-zero then it's used
+ // as the expiry for the server config in UNIX epoch seconds. Otherwise the
+ // default expiry time is six months from now.
static QuicServerConfigProtobuf* DefaultConfig(
QuicRandom* rand,
const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags);
+ const CryptoHandshakeMessage& extra_tags,
+ uint64 expiry_time);
// AddConfig adds a QuicServerConfigProtobuf to the availible configurations.
// It returns the SCFG message from the config if successful. The caller
// takes ownership of the CryptoHandshakeMessage.
CryptoHandshakeMessage* AddConfig(QuicServerConfigProtobuf* protobuf);
- // AddDefaultConfig creates a config and then calls AddConfig to
- // add it. Any tags in |extra_tags| will be copied into the config.
+ // AddDefaultConfig creates a config and then calls AddConfig to add it. See
+ // the comment for |DefaultConfig| for details of the arguments.
CryptoHandshakeMessage* AddDefaultConfig(
QuicRandom* rand,
const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags);
+ const CryptoHandshakeMessage& extra_tags,
+ uint64 expiry_time);
// ProcessClientHello processes |client_hello| and decides whether to accept
// or reject the connection. If the connection is to be accepted, |out| is
@@ -76,8 +87,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// guid: the GUID for the connection, which is used in key derivation.
// client_ip: the IP address of the client, which is used to generate and
// validate source-address tokens.
- // now_since_epoch: the current time, as a delta since the unix epoch,
- // which is used to validate client nonces.
+ // clock: used to validate client nonces and ephemeral keys.
// rand: an entropy source
// params: the state of the handshake. This may be updated with a server
// nonce when we send a rejection. After a successful handshake, this will
@@ -87,7 +97,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
QuicGuid guid,
const IPEndPoint& client_ip,
- QuicTime::Delta now_since_epoch,
+ const QuicClock* now,
QuicRandom* rand,
QuicCryptoNegotiatedParameters* params,
CryptoHandshakeMessage* out,
@@ -97,6 +107,12 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// This object takes ownership of |proof_source|.
void SetProofSource(ProofSource* proof_source);
+ // SetEphemeralKeySource installs an object that can cache ephemeral keys for
+ // a short period of time. This object takes ownership of
+ // |ephemeral_key_source|. If not set then ephemeral keys will be generated
+ // per-connection.
+ void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source);
+
private:
friend class test::QuicCryptoServerConfigPeer;
@@ -121,7 +137,7 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
std::vector<KeyExchange*> key_exchanges;
// tag_value_map contains the raw key/value pairs for the config.
- CryptoTagValueMap tag_value_map;
+ QuicTagValueMap tag_value_map;
private:
DISALLOW_COPY_AND_ASSIGN(Config);
@@ -131,14 +147,14 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// IP address.
std::string NewSourceAddressToken(const IPEndPoint& ip,
QuicRandom* rand,
- QuicTime::Delta now_since_epoch) const;
+ QuicWallTime now) const;
// ValidateSourceAddressToken returns true if the source address token in
// |token| is a valid and timely token for the IP address |ip| given that the
// current time is |now|.
bool ValidateSourceAddressToken(base::StringPiece token,
const IPEndPoint& ip,
- QuicTime::Delta now_since_epoch) const;
+ QuicWallTime now) const;
std::map<ServerConfigID, Config*> configs_;
@@ -157,6 +173,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// proof_source_ contains an object that can provide certificate chains and
// signatures.
scoped_ptr<ProofSource> proof_source_;
+
+ // ephemeral_key_source_ contains an object that caches ephemeral keys for a
+ // short period of time.
+ scoped_ptr<EphemeralKeySource> ephemeral_key_source_;
};
} // namespace net
diff --git a/net/quic/crypto/crypto_server_config_protobuf.h b/net/quic/crypto/crypto_server_config_protobuf.h
index a4ef81b..62b7b6f 100644
--- a/net/quic/crypto/crypto_server_config_protobuf.h
+++ b/net/quic/crypto/crypto_server_config_protobuf.h
@@ -19,10 +19,10 @@ class QuicServerConfigProtobuf {
public:
class PrivateKey {
public:
- CryptoTag tag() const {
+ QuicTag tag() const {
return tag_;
}
- void set_tag(CryptoTag tag) {
+ void set_tag(QuicTag tag) {
tag_ = tag;
}
std::string private_key() const {
@@ -33,7 +33,7 @@ class QuicServerConfigProtobuf {
}
private:
- CryptoTag tag_;
+ QuicTag tag_;
std::string private_key_;
};
diff --git a/net/quic/crypto/crypto_utils.cc b/net/quic/crypto/crypto_utils.cc
index e7a2376..bf1f4d2 100644
--- a/net/quic/crypto/crypto_utils.cc
+++ b/net/quic/crypto/crypto_utils.cc
@@ -18,21 +18,21 @@ using std::string;
namespace net {
// static
-bool CryptoUtils::FindMutualTag(const CryptoTagVector& our_tags_vector,
- const CryptoTag* their_tags,
+bool CryptoUtils::FindMutualTag(const QuicTagVector& our_tags_vector,
+ const QuicTag* their_tags,
size_t num_their_tags,
Priority priority,
- CryptoTag* out_result,
+ QuicTag* out_result,
size_t* out_index) {
if (our_tags_vector.empty()) {
return false;
}
const size_t num_our_tags = our_tags_vector.size();
- const CryptoTag* our_tags = &our_tags_vector[0];
+ const QuicTag* our_tags = &our_tags_vector[0];
size_t num_priority_tags, num_inferior_tags;
- const CryptoTag* priority_tags;
- const CryptoTag* inferior_tags;
+ const QuicTag* priority_tags;
+ const QuicTag* inferior_tags;
if (priority == LOCAL_PRIORITY) {
num_priority_tags = num_our_tags;
priority_tags = our_tags;
@@ -64,14 +64,14 @@ bool CryptoUtils::FindMutualTag(const CryptoTagVector& our_tags_vector,
return false;
}
-void CryptoUtils::GenerateNonce(QuicTime::Delta now,
+void CryptoUtils::GenerateNonce(QuicWallTime now,
QuicRandom* random_generator,
StringPiece orbit,
string* nonce) {
// a 4-byte timestamp + 28 random bytes.
nonce->reserve(kNonceSize);
nonce->resize(kNonceSize);
- uint32 gmt_unix_time = now.ToSeconds();
+ uint32 gmt_unix_time = now.ToUNIXSeconds();
// The time in the nonce must be encoded in big-endian because the
// strike-register depends on the nonces being ordered by time.
(*nonce)[0] = static_cast<char>(gmt_unix_time >> 24);
@@ -88,34 +88,37 @@ void CryptoUtils::GenerateNonce(QuicTime::Delta now,
kNonceSize - bytes_written);
}
-void CryptoUtils::DeriveKeys(QuicCryptoNegotiatedParameters* params,
+void CryptoUtils::DeriveKeys(StringPiece premaster_secret,
+ QuicTag aead,
StringPiece client_nonce,
+ StringPiece server_nonce,
const string& hkdf_input,
- Perspective perspective) {
- params->encrypter.reset(QuicEncrypter::Create(params->aead));
- params->decrypter.reset(QuicDecrypter::Create(params->aead));
- size_t key_bytes = params->encrypter->GetKeySize();
- size_t nonce_prefix_bytes = params->encrypter->GetNoncePrefixSize();
+ Perspective perspective,
+ CrypterPair* out) {
+ out->encrypter.reset(QuicEncrypter::Create(aead));
+ out->decrypter.reset(QuicDecrypter::Create(aead));
+ size_t key_bytes = out->encrypter->GetKeySize();
+ size_t nonce_prefix_bytes = out->encrypter->GetNoncePrefixSize();
StringPiece nonce = client_nonce;
string nonce_storage;
- if (!params->server_nonce.empty()) {
- nonce_storage = client_nonce.as_string() + params->server_nonce;
+ if (!server_nonce.empty()) {
+ nonce_storage = client_nonce.as_string() + server_nonce.as_string();
nonce = nonce_storage;
}
- crypto::HKDF hkdf(params->premaster_secret, nonce,
- hkdf_input, key_bytes, nonce_prefix_bytes);
+ crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes,
+ nonce_prefix_bytes);
if (perspective == SERVER) {
- params->encrypter->SetKey(hkdf.server_write_key());
- params->encrypter->SetNoncePrefix(hkdf.server_write_iv());
- params->decrypter->SetKey(hkdf.client_write_key());
- params->decrypter->SetNoncePrefix(hkdf.client_write_iv());
+ out->encrypter->SetKey(hkdf.server_write_key());
+ out->encrypter->SetNoncePrefix(hkdf.server_write_iv());
+ out->decrypter->SetKey(hkdf.client_write_key());
+ out->decrypter->SetNoncePrefix(hkdf.client_write_iv());
} else {
- params->encrypter->SetKey(hkdf.client_write_key());
- params->encrypter->SetNoncePrefix(hkdf.client_write_iv());
- params->decrypter->SetKey(hkdf.server_write_key());
- params->decrypter->SetNoncePrefix(hkdf.server_write_iv());
+ out->encrypter->SetKey(hkdf.client_write_key());
+ out->encrypter->SetNoncePrefix(hkdf.client_write_iv());
+ out->decrypter->SetKey(hkdf.server_write_key());
+ out->decrypter->SetNoncePrefix(hkdf.server_write_iv());
}
}
diff --git a/net/quic/crypto/crypto_utils.h b/net/quic/crypto/crypto_utils.h
index 4ad4149..6c607a5 100644
--- a/net/quic/crypto/crypto_utils.h
+++ b/net/quic/crypto/crypto_utils.h
@@ -13,6 +13,7 @@
#include "net/base/net_export.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/quic_time.h"
namespace net {
@@ -40,32 +41,35 @@ class NET_EXPORT_PRIVATE CryptoUtils {
//
// If |out_index| is non-NULL and a match is found then the index of that
// match in |their_tags| is written to |out_index|.
- static bool FindMutualTag(const CryptoTagVector& our_tags,
- const CryptoTag* their_tags,
+ static bool FindMutualTag(const QuicTagVector& our_tags,
+ const QuicTag* their_tags,
size_t num_their_tags,
Priority priority,
- CryptoTag* out_result,
+ QuicTag* out_result,
size_t* out_index);
// Generates the connection nonce. The nonce is formed as:
// <4 bytes> current time
// <8 bytes> |orbit| (or random if |orbit| is empty)
// <20 bytes> random
- static void GenerateNonce(QuicTime::Delta now,
+ static void GenerateNonce(QuicWallTime now,
QuicRandom* random_generator,
base::StringPiece orbit,
std::string* nonce);
- // DeriveKeys populates |params->encrypter| and |params->decrypter| given the
- // contents of |params->premaster_secret|, |client_nonce|,
- // |params->server_nonce| and |hkdf_input|. |perspective| controls whether
- // the server's keys are assigned to |encrypter| or |decrypter|.
- // |params->server_nonce| is optional and, if non-empty, is mixed into the
- // key derivation.
- static void DeriveKeys(QuicCryptoNegotiatedParameters* params,
+ // DeriveKeys populates |out->encrypter| and |out->decrypter| given the
+ // contents of |premaster_secret|, |client_nonce|, |server_nonce| and
+ // |hkdf_input|. |aead| determines which cipher will be used. |perspective|
+ // controls whether the server's keys are assigned to |encrypter| or
+ // |decrypter|. |server_nonce| is optional and, if non-empty, is mixed into
+ // the key derivation.
+ static void DeriveKeys(base::StringPiece premaster_secret,
+ QuicTag aead,
base::StringPiece client_nonce,
+ base::StringPiece server_nonce,
const std::string& hkdf_input,
- Perspective perspective);
+ Perspective perspective,
+ CrypterPair* out);
};
} // namespace net
diff --git a/net/quic/crypto/curve25519_key_exchange.cc b/net/quic/crypto/curve25519_key_exchange.cc
index a4c20fa..3b888045 100644
--- a/net/quic/crypto/curve25519_key_exchange.cc
+++ b/net/quic/crypto/curve25519_key_exchange.cc
@@ -13,11 +13,9 @@ using std::string;
namespace net {
-Curve25519KeyExchange::Curve25519KeyExchange() {
-}
+Curve25519KeyExchange::Curve25519KeyExchange() {}
-Curve25519KeyExchange::~Curve25519KeyExchange() {
-}
+Curve25519KeyExchange::~Curve25519KeyExchange() {}
// static
Curve25519KeyExchange* Curve25519KeyExchange::New(
@@ -29,9 +27,8 @@ Curve25519KeyExchange* Curve25519KeyExchange::New(
COMPILE_ASSERT(
sizeof(ka->private_key_) == crypto::curve25519::kScalarBytes,
header_out_of_sync);
- COMPILE_ASSERT(
- sizeof(ka->public_key_) == crypto::curve25519::kBytes,
- header_out_of_sync);
+ COMPILE_ASSERT(sizeof(ka->public_key_) == crypto::curve25519::kBytes,
+ header_out_of_sync);
if (private_key.size() != crypto::curve25519::kScalarBytes) {
return NULL;
@@ -57,6 +54,11 @@ string Curve25519KeyExchange::NewPrivateKey(QuicRandom* rand) {
return string(reinterpret_cast<char*>(private_key), sizeof(private_key));
}
+KeyExchange* Curve25519KeyExchange::NewKeyPair(QuicRandom* rand) const {
+ const string private_value = NewPrivateKey(rand);
+ return Curve25519KeyExchange::New(private_value);
+}
+
bool Curve25519KeyExchange::CalculateSharedKey(
const StringPiece& peer_public_value,
string* out_result) const {
@@ -79,8 +81,6 @@ StringPiece Curve25519KeyExchange::public_value() const {
sizeof(public_key_));
}
-CryptoTag Curve25519KeyExchange::tag() const {
- return kC255;
-}
+QuicTag Curve25519KeyExchange::tag() const { return kC255; }
} // namespace net
diff --git a/net/quic/crypto/curve25519_key_exchange.h b/net/quic/crypto/curve25519_key_exchange.h
index 73cf741..ecc0880 100644
--- a/net/quic/crypto/curve25519_key_exchange.h
+++ b/net/quic/crypto/curve25519_key_exchange.h
@@ -31,10 +31,11 @@ class NET_EXPORT_PRIVATE Curve25519KeyExchange : public KeyExchange {
static std::string NewPrivateKey(QuicRandom* rand);
// KeyExchange interface.
+ virtual KeyExchange* NewKeyPair(QuicRandom* rand) const OVERRIDE;
virtual bool CalculateSharedKey(const base::StringPiece& peer_public_value,
std::string* shared_key) const OVERRIDE;
virtual base::StringPiece public_value() const OVERRIDE;
- virtual CryptoTag tag() const OVERRIDE;
+ virtual QuicTag tag() const OVERRIDE;
private:
Curve25519KeyExchange();
diff --git a/net/quic/crypto/curve25519_key_exchange_test.cc b/net/quic/crypto/curve25519_key_exchange_test.cc
index 83ddcfb..93ef630 100644
--- a/net/quic/crypto/curve25519_key_exchange_test.cc
+++ b/net/quic/crypto/curve25519_key_exchange_test.cc
@@ -24,10 +24,9 @@ TEST(Curve25519KeyExchange, SharedKey) {
const string alice_key(Curve25519KeyExchange::NewPrivateKey(rand));
const string bob_key(Curve25519KeyExchange::NewPrivateKey(rand));
- scoped_ptr<Curve25519KeyExchange> alice(Curve25519KeyExchange::New(
- alice_key));
- scoped_ptr<Curve25519KeyExchange> bob(Curve25519KeyExchange::New(
- bob_key));
+ scoped_ptr<Curve25519KeyExchange> alice(
+ Curve25519KeyExchange::New(alice_key));
+ scoped_ptr<Curve25519KeyExchange> bob(Curve25519KeyExchange::New(bob_key));
const StringPiece alice_public(alice->public_value());
const StringPiece bob_public(bob->public_value());
diff --git a/net/quic/crypto/ephemeral_key_source.h b/net/quic/crypto/ephemeral_key_source.h
new file mode 100644
index 0000000..2700be0
--- /dev/null
+++ b/net/quic/crypto/ephemeral_key_source.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
+#define NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+class KeyExchange;
+class QuicRandom;
+
+// EphemeralKeySource manages and rotates ephemeral keys as they can be reused
+// for several connections in a short space of time. Since the implementation
+// of this may involve locking or thread-local data, this interface abstracts
+// that away.
+class NET_EXPORT_PRIVATE EphemeralKeySource {
+ public:
+ virtual ~EphemeralKeySource() {}
+
+ // CalculateForwardSecureKey generates an ephemeral public/private key pair
+ // using the algorithm |key_exchange|, sets |*public_value| to the public key
+ // and returns the shared key between |peer_public_value| and the private
+ // key. |*public_value| will be sent to the peer to be used with the peer's
+ // private key.
+ virtual std::string CalculateForwardSecureKey(
+ const KeyExchange* key_exchange,
+ QuicRandom* rand,
+ QuicTime now,
+ base::StringPiece peer_public_value,
+ std::string* public_value) = 0;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
diff --git a/net/quic/crypto/key_exchange.h b/net/quic/crypto/key_exchange.h
index 4f043bd..8690f0e 100644
--- a/net/quic/crypto/key_exchange.h
+++ b/net/quic/crypto/key_exchange.h
@@ -13,11 +13,18 @@
namespace net {
+class QuicRandom;
+
// KeyExchange is an abstract class that provides an interface to a
// key-exchange primitive.
class NET_EXPORT_PRIVATE KeyExchange {
public:
- virtual ~KeyExchange() { }
+ virtual ~KeyExchange() {}
+
+ // NewKeyPair generates a new public, private key pair. The caller takes
+ // ownership of the return value. (This is intended for servers that need to
+ // generate forward-secure keys.)
+ virtual KeyExchange* NewKeyPair(QuicRandom* rand) const = 0;
// CalculateSharedKey computes the shared key between the local private key
// (which is implicitly known by a KeyExchange object) and a public value
@@ -32,7 +39,7 @@ class NET_EXPORT_PRIVATE KeyExchange {
virtual base::StringPiece public_value() const = 0;
// tag returns the tag value that identifies this key exchange function.
- virtual CryptoTag tag() const = 0;
+ virtual QuicTag tag() const = 0;
};
} // namespace net
diff --git a/net/quic/crypto/null_decrypter.cc b/net/quic/crypto/null_decrypter.cc
index 0875558..7bda75f 100644
--- a/net/quic/crypto/null_decrypter.cc
+++ b/net/quic/crypto/null_decrypter.cc
@@ -11,9 +11,7 @@ using std::string;
namespace net {
-bool NullDecrypter::SetKey(StringPiece key) {
- return key.empty();
-}
+bool NullDecrypter::SetKey(StringPiece key) { return key.empty(); }
bool NullDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return nonce_prefix.empty();
@@ -69,12 +67,8 @@ QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
return new QuicData(plaintext.data(), plaintext.length());
}
-StringPiece NullDecrypter::GetKey() const {
- return StringPiece();
-}
+StringPiece NullDecrypter::GetKey() const { return StringPiece(); }
-StringPiece NullDecrypter::GetNoncePrefix() const {
- return StringPiece();
-}
+StringPiece NullDecrypter::GetNoncePrefix() const { return StringPiece(); }
} // namespace net
diff --git a/net/quic/crypto/null_decrypter_test.cc b/net/quic/crypto/null_decrypter_test.cc
index 7854b04..e9b9647 100644
--- a/net/quic/crypto/null_decrypter_test.cc
+++ b/net/quic/crypto/null_decrypter_test.cc
@@ -22,11 +22,9 @@ TEST(NullDecrypterTest, Decrypt) {
'b', 'y', 'e', '!',
};
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(
- 0, "hello world!",
- StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
+ 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
+ arraysize(expected))));
ASSERT_TRUE(decrypted.get());
EXPECT_EQ("goodbye!", decrypted->AsStringPiece());
}
@@ -43,11 +41,9 @@ TEST(NullDecrypterTest, BadHash) {
'b', 'y', 'e', '!',
};
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(
- 0, "hello world!",
- StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
+ 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
+ arraysize(expected))));
ASSERT_FALSE(decrypted.get());
}
@@ -60,11 +56,9 @@ TEST(NullDecrypterTest, ShortInput) {
0x88, 0x79, 0xca,
};
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(
- decrypter.DecryptPacket(
- 0, "hello world!",
- StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
+ 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
+ arraysize(expected))));
ASSERT_FALSE(decrypted.get());
}
diff --git a/net/quic/crypto/null_encrypter.cc b/net/quic/crypto/null_encrypter.cc
index d8bb6df..a0a680d 100644
--- a/net/quic/crypto/null_encrypter.cc
+++ b/net/quic/crypto/null_encrypter.cc
@@ -13,9 +13,7 @@ namespace net {
const size_t kHashSize = 16; // size of uint128 serialized
-bool NullEncrypter::SetKey(StringPiece key) {
- return key.empty();
-}
+bool NullEncrypter::SetKey(StringPiece key) { return key.empty(); }
bool NullEncrypter::SetNoncePrefix(StringPiece nonce_prefix) {
return nonce_prefix.empty();
@@ -44,13 +42,9 @@ QuicData* NullEncrypter::EncryptPacket(
return new QuicData(reinterpret_cast<char*>(buffer), len, true);
}
-size_t NullEncrypter::GetKeySize() const {
- return 0;
-}
+size_t NullEncrypter::GetKeySize() const { return 0; }
-size_t NullEncrypter::GetNoncePrefixSize() const {
- return 0;
-}
+size_t NullEncrypter::GetNoncePrefixSize() const { return 0; }
size_t NullEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const {
return ciphertext_size - kHashSize;
@@ -60,12 +54,8 @@ size_t NullEncrypter::GetCiphertextSize(size_t plaintext_size) const {
return plaintext_size + kHashSize;
}
-StringPiece NullEncrypter::GetKey() const {
- return StringPiece();
-}
+StringPiece NullEncrypter::GetKey() const { return StringPiece(); }
-StringPiece NullEncrypter::GetNoncePrefix() const {
- return StringPiece();
-}
+StringPiece NullEncrypter::GetNoncePrefix() const { return StringPiece(); }
} // namespace net
diff --git a/net/quic/crypto/null_encrypter_test.cc b/net/quic/crypto/null_encrypter_test.cc
index e1e6834..4c00f91 100644
--- a/net/quic/crypto/null_encrypter_test.cc
+++ b/net/quic/crypto/null_encrypter_test.cc
@@ -22,8 +22,8 @@ TEST(NullEncrypterTest, Encrypt) {
'b', 'y', 'e', '!',
};
NullEncrypter encrypter;
- scoped_ptr<QuicData> encrypted(encrypter.EncryptPacket(0, "hello world!",
- "goodbye!"));
+ scoped_ptr<QuicData> encrypted(
+ encrypter.EncryptPacket(0, "hello world!", "goodbye!"));
ASSERT_TRUE(encrypted.get());
test::CompareCharArraysWithHexError(
"encrypted data", encrypted->data(), encrypted->length(),
diff --git a/net/quic/crypto/p256_key_exchange.h b/net/quic/crypto/p256_key_exchange.h
index f30d292..8145cc0 100644
--- a/net/quic/crypto/p256_key_exchange.h
+++ b/net/quic/crypto/p256_key_exchange.h
@@ -40,10 +40,11 @@ class NET_EXPORT_PRIVATE P256KeyExchange : public KeyExchange {
static std::string NewPrivateKey();
// KeyExchange interface.
+ virtual KeyExchange* NewKeyPair(QuicRandom* rand) const OVERRIDE;
virtual bool CalculateSharedKey(const base::StringPiece& peer_public_value,
std::string* shared_key) const OVERRIDE;
virtual base::StringPiece public_value() const OVERRIDE;
- virtual CryptoTag tag() const OVERRIDE;
+ virtual QuicTag tag() const OVERRIDE;
private:
enum {
diff --git a/net/quic/crypto/p256_key_exchange_nss.cc b/net/quic/crypto/p256_key_exchange_nss.cc
index c1de42e..dede5ba 100644
--- a/net/quic/crypto/p256_key_exchange_nss.cc
+++ b/net/quic/crypto/p256_key_exchange_nss.cc
@@ -149,9 +149,14 @@ string P256KeyExchange::NewPrivateKey() {
return string(&result[0], result_size);
}
-bool P256KeyExchange::CalculateSharedKey(
- const StringPiece& peer_public_value,
- string* out_result) const {
+KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
+ // TODO(agl): avoid the serialisation/deserialisation in this function.
+ const string private_value = NewPrivateKey();
+ return P256KeyExchange::New(private_value);
+}
+
+bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
+ string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes ||
peer_public_value[0] != kUncompressedECPointForm) {
DLOG(INFO) << "Peer public value is invalid.";
@@ -222,9 +227,7 @@ StringPiece P256KeyExchange::public_value() const {
sizeof(public_key_));
}
-CryptoTag P256KeyExchange::tag() const {
- return kP256;
-}
+QuicTag P256KeyExchange::tag() const { return kP256; }
} // namespace net
diff --git a/net/quic/crypto/p256_key_exchange_openssl.cc b/net/quic/crypto/p256_key_exchange_openssl.cc
index 051adcf..6eaa981 100644
--- a/net/quic/crypto/p256_key_exchange_openssl.cc
+++ b/net/quic/crypto/p256_key_exchange_openssl.cc
@@ -20,8 +20,7 @@ P256KeyExchange::P256KeyExchange(EC_KEY* private_key, const uint8* public_key)
memcpy(public_key_, public_key, sizeof(public_key_));
}
-P256KeyExchange::~P256KeyExchange() {
-}
+P256KeyExchange::~P256KeyExchange() {}
// static
P256KeyExchange* P256KeyExchange::New(StringPiece key) {
@@ -39,13 +38,10 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
}
uint8 public_key[kUncompressedP256PointBytes];
- if (EC_POINT_point2oct(
- EC_KEY_get0_group(private_key.get()),
- EC_KEY_get0_public_key(private_key.get()),
- POINT_CONVERSION_UNCOMPRESSED,
- public_key,
- sizeof(public_key),
- NULL) != sizeof(public_key)) {
+ if (EC_POINT_point2oct(EC_KEY_get0_group(private_key.get()),
+ EC_KEY_get0_public_key(private_key.get()),
+ POINT_CONVERSION_UNCOMPRESSED, public_key,
+ sizeof(public_key), NULL) != sizeof(public_key)) {
DLOG(INFO) << "Can't get public key.";
return NULL;
}
@@ -76,34 +72,34 @@ string P256KeyExchange::NewPrivateKey() {
return string(reinterpret_cast<char*>(private_key.get()), key_len);
}
-bool P256KeyExchange::CalculateSharedKey(
- const StringPiece& peer_public_value,
- string* out_result) const {
+KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
+ // TODO(agl): avoid the serialisation/deserialisation in this function.
+ const string private_value = NewPrivateKey();
+ return P256KeyExchange::New(private_value);
+}
+
+bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
+ string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes) {
DLOG(INFO) << "Peer public value is invalid";
return false;
}
crypto::ScopedOpenSSL<EC_POINT, EC_POINT_free> point(
- EC_POINT_new(EC_KEY_get0_group(private_key_.get())));
+ EC_POINT_new(EC_KEY_get0_group(private_key_.get())));
if (!point.get() ||
!EC_POINT_oct2point( /* also test if point is on curve */
EC_KEY_get0_group(private_key_.get()),
point.get(),
reinterpret_cast<const uint8*>(peer_public_value.data()),
- peer_public_value.size(),
- NULL)) {
+ peer_public_value.size(), NULL)) {
DLOG(INFO) << "Can't convert peer public value to curve point.";
return false;
}
uint8 result[kP256FieldBytes];
- if (ECDH_compute_key(
- result,
- sizeof(result),
- point.get(),
- private_key_.get(),
- NULL) != sizeof(result)) {
+ if (ECDH_compute_key(result, sizeof(result), point.get(), private_key_.get(),
+ NULL) != sizeof(result)) {
DLOG(INFO) << "Can't compute ECDH shared key.";
return false;
}
@@ -117,9 +113,7 @@ StringPiece P256KeyExchange::public_value() const {
sizeof(public_key_));
}
-CryptoTag P256KeyExchange::tag() const {
- return kP256;
-}
+QuicTag P256KeyExchange::tag() const { return kP256; }
} // namespace net
diff --git a/net/quic/crypto/quic_decrypter.cc b/net/quic/crypto/quic_decrypter.cc
index 3c0e660..2eafdc3 100644
--- a/net/quic/crypto/quic_decrypter.cc
+++ b/net/quic/crypto/quic_decrypter.cc
@@ -10,7 +10,7 @@
namespace net {
// static
-QuicDecrypter* QuicDecrypter::Create(CryptoTag algorithm) {
+QuicDecrypter* QuicDecrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
return new Aes128GcmDecrypter();
diff --git a/net/quic/crypto/quic_decrypter.h b/net/quic/crypto/quic_decrypter.h
index 349425a..124d98f 100644
--- a/net/quic/crypto/quic_decrypter.h
+++ b/net/quic/crypto/quic_decrypter.h
@@ -15,7 +15,7 @@ class NET_EXPORT_PRIVATE QuicDecrypter {
public:
virtual ~QuicDecrypter() {}
- static QuicDecrypter* Create(CryptoTag algorithm);
+ static QuicDecrypter* Create(QuicTag algorithm);
// Sets the encryption key. Returns true on success, false on failure.
//
diff --git a/net/quic/crypto/quic_encrypter.cc b/net/quic/crypto/quic_encrypter.cc
index a84530f..2e2b83d 100644
--- a/net/quic/crypto/quic_encrypter.cc
+++ b/net/quic/crypto/quic_encrypter.cc
@@ -10,7 +10,7 @@
namespace net {
// static
-QuicEncrypter* QuicEncrypter::Create(CryptoTag algorithm) {
+QuicEncrypter* QuicEncrypter::Create(QuicTag algorithm) {
switch (algorithm) {
case kAESG:
return new Aes128GcmEncrypter();
diff --git a/net/quic/crypto/quic_encrypter.h b/net/quic/crypto/quic_encrypter.h
index 86d0e3a..edddf36 100644
--- a/net/quic/crypto/quic_encrypter.h
+++ b/net/quic/crypto/quic_encrypter.h
@@ -15,7 +15,7 @@ class NET_EXPORT_PRIVATE QuicEncrypter {
public:
virtual ~QuicEncrypter() {}
- static QuicEncrypter* Create(CryptoTag algorithm);
+ static QuicEncrypter* Create(QuicTag algorithm);
// Sets the encryption key. Returns true on success, false on failure.
//
diff --git a/net/quic/crypto/quic_random.cc b/net/quic/crypto/quic_random.cc
index be1f3c0..c96f01a 100644
--- a/net/quic/crypto/quic_random.cc
+++ b/net/quic/crypto/quic_random.cc
@@ -61,8 +61,6 @@ DefaultRandom::DefaultRandom() {
} // namespace
// static
-QuicRandom* QuicRandom::GetInstance() {
- return DefaultRandom::GetInstance();
-}
+QuicRandom* QuicRandom::GetInstance() { return DefaultRandom::GetInstance(); }
} // namespace net
diff --git a/net/quic/crypto/scoped_evp_cipher_ctx.h b/net/quic/crypto/scoped_evp_cipher_ctx.h
index a241eea..8741c3e 100644
--- a/net/quic/crypto/scoped_evp_cipher_ctx.h
+++ b/net/quic/crypto/scoped_evp_cipher_ctx.h
@@ -18,9 +18,7 @@ namespace net {
// functions.
class ScopedEVPCipherCtx {
public:
- ScopedEVPCipherCtx() {
- EVP_CIPHER_CTX_init(&ctx_);
- }
+ ScopedEVPCipherCtx() { EVP_CIPHER_CTX_init(&ctx_); }
~ScopedEVPCipherCtx() {
int rv = EVP_CIPHER_CTX_cleanup(&ctx_);
diff --git a/net/quic/crypto/strike_register.cc b/net/quic/crypto/strike_register.cc
index 565d5c8..95f358c 100644
--- a/net/quic/crypto/strike_register.cc
+++ b/net/quic/crypto/strike_register.cc
@@ -37,25 +37,15 @@ class StrikeRegister::InternalNode {
data_[1] |= otherbits;
}
- void SetNextPtr(uint32 next) {
- data_[0] = next;
- }
+ void SetNextPtr(uint32 next) { data_[0] = next; }
- uint32 next() const {
- return data_[0];
- }
+ uint32 next() const { return data_[0]; }
- uint32 child(unsigned n) const {
- return data_[n] >> 8;
- }
+ uint32 child(unsigned n) const { return data_[n] >> 8; }
- uint8 critbyte() const {
- return data_[0];
- }
+ uint8 critbyte() const { return data_[0]; }
- uint8 otherbits() const {
- return data_[1];
- }
+ uint8 otherbits() const { return data_[1]; }
// These bytes are organised thus:
// <24 bits> left child
@@ -88,9 +78,7 @@ StrikeRegister::StrikeRegister(unsigned max_entries,
Reset();
}
-StrikeRegister::~StrikeRegister() {
- delete[] internal_nodes_;
-}
+StrikeRegister::~StrikeRegister() { delete[] internal_nodes_; }
void StrikeRegister::Reset() {
// Thread a free list through all of the internal nodes.
@@ -242,7 +230,7 @@ bool StrikeRegister::Insert(const uint8 nonce[32],
uint8 c = value[node->critbyte()];
const int direction =
- (1 + static_cast<unsigned>(node->otherbits() | c)) >> 8;
+ (1 + static_cast<unsigned>(node->otherbits() | c)) >> 8;
where_index = &node->data_[direction];
}
@@ -299,7 +287,7 @@ uint32 StrikeRegister::BestMatch(const uint8 v[24]) const {
InternalNode* node = &internal_nodes_[next];
uint8 b = v[node->critbyte()];
unsigned direction =
- (1 + static_cast<unsigned>(node->otherbits() | b)) >> 8;
+ (1 + static_cast<unsigned>(node->otherbits() | b)) >> 8;
next = node->child(direction);
}
@@ -347,7 +335,7 @@ void StrikeRegister::DropNode() {
// (whereq) when walking down the tree.
uint32 p = internal_node_head_ >> 8, *wherep = &internal_node_head_,
- *whereq = NULL;
+ *whereq = NULL;
while ((p & kExternalFlag) == 0) {
whereq = wherep;
InternalNode* inode = &internal_nodes_[p];
@@ -440,8 +428,8 @@ void StrikeRegister::ValidateTree(
CHECK_EQ(used_external_nodes->count(ext), 0u);
used_external_nodes->insert(ext);
const uint8* bytes = external_node(ext);
- for (vector<pair<unsigned, bool> >::const_iterator
- i = bits.begin(); i != bits.end(); i++) {
+ for (vector<pair<unsigned, bool> >::const_iterator i = bits.begin();
+ i != bits.end(); i++) {
unsigned byte = i->first / 8;
DCHECK_LE(byte, 0xffu);
unsigned bit = i->first % 8;
diff --git a/net/quic/crypto/strike_register_test.cc b/net/quic/crypto/strike_register_test.cc
index 4dd479e..d805269 100644
--- a/net/quic/crypto/strike_register_test.cc
+++ b/net/quic/crypto/strike_register_test.cc
@@ -16,7 +16,7 @@ using net::StrikeRegister;
using std::set;
using std::string;
-const uint8 kOrbit[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+const uint8 kOrbit[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
void
NonceSetTimeAndOrbit(uint8 nonce[32], unsigned time, const uint8 orbit[8]) {
@@ -54,7 +54,7 @@ TEST(StrikeRegisterTest, BadOrbit) {
StrikeRegister set(10 /* max size */, 1000 /* current time */,
100 /* window secs */, kOrbit);
uint8 nonce[32];
- static const uint8 kBadOrbit[8] = {0, 0, 0, 0, 1, 1, 1, 1};
+ static const uint8 kBadOrbit[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
NonceSetTimeAndOrbit(nonce, 1101, kBadOrbit);
ASSERT_FALSE(set.Insert(nonce, 1100));
}
@@ -186,7 +186,7 @@ class SlowStrikeRegister {
void DropOldestEntry() {
set<string>::iterator oldest = nonces_.begin(), it;
uint32 oldest_time =
- TimeFromBytes(reinterpret_cast<const uint8*>(oldest->data()));
+ TimeFromBytes(reinterpret_cast<const uint8*>(oldest->data()));
for (it = oldest; it != nonces_.end(); it++) {
uint32 t = TimeFromBytes(reinterpret_cast<const uint8*>(it->data()));
@@ -214,10 +214,10 @@ TEST(StrikeRegisterStressTest, Stress) {
srand(42);
unsigned max_entries = 64;
uint32 current_time = 10000, window = 200;
- scoped_ptr<StrikeRegister> s1(new StrikeRegister(
- max_entries, current_time, window, kOrbit));
- scoped_ptr<SlowStrikeRegister> s2(new SlowStrikeRegister(
- max_entries, current_time, window, kOrbit));
+ scoped_ptr<StrikeRegister> s1(
+ new StrikeRegister(max_entries, current_time, window, kOrbit));
+ scoped_ptr<SlowStrikeRegister> s2(
+ new SlowStrikeRegister(max_entries, current_time, window, kOrbit));
uint64 i;
// When making changes it's worth removing the limit on this test and running
@@ -231,8 +231,8 @@ TEST(StrikeRegisterStressTest, Stress) {
current_time = rand() % 10000;
window = rand() % 500;
s1.reset(new StrikeRegister(max_entries, current_time, window, kOrbit));
- s2.reset(new SlowStrikeRegister(max_entries, current_time, window,
- kOrbit));
+ s2.reset(
+ new SlowStrikeRegister(max_entries, current_time, window, kOrbit));
}
int32 time_delta = rand() % (window * 4);
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 8b7bddb..b347dc3 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -99,7 +99,7 @@ TEST_F(QuicClientSessionTest, GoAwayReceived) {
EXPECT_EQ(NULL, session_.CreateOutgoingReliableStream());
}
-TEST_F(QuicClientSessionTest, Logging) {
+TEST_F(QuicClientSessionTest, DISABLED_Logging) {
if (!Aes128GcmEncrypter::IsSupported()) {
LOG(INFO) << "AES GCM not supported. Test skipped.";
return;
diff --git a/net/quic/quic_clock.cc b/net/quic/quic_clock.cc
index 26c1a65..6c8dd48 100644
--- a/net/quic/quic_clock.cc
+++ b/net/quic/quic_clock.cc
@@ -22,8 +22,9 @@ QuicTime QuicClock::Now() const {
return QuicTime(base::TimeTicks::Now());
}
-QuicTime::Delta QuicClock::NowAsDeltaSinceUnixEpoch() const {
- return QuicTime::Delta(base::Time::Now() - base::Time::UnixEpoch());
+QuicWallTime QuicClock::WallNow() const {
+ return QuicWallTime::FromUNIXSeconds(
+ base::Time::Now().ToInternalValue() / 1000000);
}
} // namespace net
diff --git a/net/quic/quic_clock.h b/net/quic/quic_clock.h
index 6b6cb31..0b3ef4a 100644
--- a/net/quic/quic_clock.h
+++ b/net/quic/quic_clock.h
@@ -27,10 +27,9 @@ class NET_EXPORT_PRIVATE QuicClock {
// Note: this use significant resources please use only if needed.
virtual QuicTime Now() const;
- // Returns the current time as an offset from the Unix epoch (1970-01-01
- // 00:00:00 GMT). This function may return a smaller Delta in subsequent
- // calls if the system clock is changed.
- virtual QuicTime::Delta NowAsDeltaSinceUnixEpoch() const;
+ // WallNow returns the current wall-time - a time is consistent across
+ // different clocks.
+ virtual QuicWallTime WallNow() const;
};
} // namespace net
diff --git a/net/quic/quic_clock_test.cc b/net/quic/quic_clock_test.cc
index 1f285942..7b106c1 100644
--- a/net/quic/quic_clock_test.cc
+++ b/net/quic/quic_clock_test.cc
@@ -20,15 +20,20 @@ TEST(QuicClockTest, Now) {
EXPECT_LE(now, end);
}
-TEST(QuicClockTest, NowAsDeltaSinceUnixEpoch) {
+TEST(QuicClockTest, WallNow) {
QuicClock clock;
- QuicTime::Delta start(base::Time::Now() - base::Time::UnixEpoch());
- QuicTime::Delta now = clock.NowAsDeltaSinceUnixEpoch();
- QuicTime::Delta end(base::Time::Now() - base::Time::UnixEpoch());
-
- EXPECT_LE(start, now);
- EXPECT_LE(now, end);
+ base::Time start = base::Time::Now();
+ QuicWallTime now = clock.WallNow();
+ base::Time end = base::Time::Now();
+
+ // If end > start, then we can check now is between start and end.
+ if (end > start) {
+ EXPECT_LE(static_cast<uint64>(start.ToInternalValue() / 1000000),
+ now.ToUNIXSeconds());
+ EXPECT_LE(now.ToUNIXSeconds(),
+ static_cast<uint64>(end.ToInternalValue() / 1000000));
+ }
}
} // namespace test
diff --git a/net/quic/quic_config.cc b/net/quic/quic_config.cc
index 70e0b45..867cb6d 100644
--- a/net/quic/quic_config.cc
+++ b/net/quic/quic_config.cc
@@ -29,7 +29,7 @@ void QuicConfig::SetDefaults() {
}
bool QuicConfig::SetFromHandshakeMessage(const CryptoHandshakeMessage& scfg) {
- const CryptoTag* cgst;
+ const QuicTag* cgst;
size_t num_cgst;
QuicErrorCode error;
@@ -73,7 +73,7 @@ QuicErrorCode QuicConfig::ProcessFinalPeerHandshake(
string* error_details) const {
DCHECK(error_details != NULL);
- const CryptoTag* their_congestion_controls;
+ const QuicTag* their_congestion_controls;
size_t num_their_congestion_controls;
QuicErrorCode error;
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h
index 17441d7..013a4f2 100644
--- a/net/quic/quic_config.h
+++ b/net/quic/quic_config.h
@@ -19,7 +19,7 @@ class NET_EXPORT_PRIVATE QuicNegotiatedParameters {
public:
QuicNegotiatedParameters();
- CryptoTag congestion_control;
+ QuicTag congestion_control;
QuicTime::Delta idle_connection_state_lifetime;
QuicTime::Delta keepalive_timeout;
};
@@ -31,6 +31,11 @@ class NET_EXPORT_PRIVATE QuicConfig {
QuicConfig();
~QuicConfig();
+ void set_idle_connection_state_lifetime(
+ QuicTime::Delta idle_connection_state_lifetime) {
+ idle_connection_state_lifetime_ = idle_connection_state_lifetime;
+ }
+
// SetDefaults sets the members to sensible, default values.
void SetDefaults();
@@ -54,7 +59,7 @@ class NET_EXPORT_PRIVATE QuicConfig {
private:
// Congestion control feedback type.
- CryptoTagVector congestion_control_;
+ QuicTagVector congestion_control_;
// Idle connection state lifetime
QuicTime::Delta idle_connection_state_lifetime_;
// Keepalive timeout, or 0 to turn off keepalive probes
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc
index 4851d47..481fca9 100644
--- a/net/quic/quic_connection.cc
+++ b/net/quic/quic_connection.cc
@@ -24,10 +24,6 @@ using std::set;
using std::string;
namespace net {
-
-// TODO(pwestin): kDefaultTimeoutUs is in int64.
-int32 kNegotiatedTimeoutUs = kDefaultTimeoutUs;
-
namespace {
// The largest gap in packets we'll accept without closing the connection.
@@ -77,10 +73,10 @@ QuicConnection::QuicConnection(QuicGuid guid,
IPEndPoint address,
QuicConnectionHelperInterface* helper,
bool is_server)
- : helper_(helper),
- framer_(kQuicVersion1,
+ : framer_(kQuicVersion1,
helper->GetClock()->ApproximateNow(),
is_server),
+ helper_(helper),
encryption_level_(ENCRYPTION_NONE),
clock_(helper->GetClock()),
random_generator_(helper->GetRandomGenerator()),
@@ -136,7 +132,7 @@ QuicConnection::~QuicConnection() {
}
bool QuicConnection::SelectMutualVersion(
- const QuicVersionTagList& available_versions) {
+ const QuicTagVector& available_versions) {
// TODO(satyamshekhar): Make this generic.
if (std::find(available_versions.begin(), available_versions.end(),
kQuicVersion1) == available_versions.end()) {
@@ -178,8 +174,7 @@ void QuicConnection::OnPublicResetPacket(
CloseConnection(QUIC_PUBLIC_RESET, true);
}
-bool QuicConnection::OnProtocolVersionMismatch(
- QuicVersionTag received_version) {
+bool QuicConnection::OnProtocolVersionMismatch(QuicTag received_version) {
// TODO(satyamshekhar): Implement no server state in this mode.
if (!is_server_) {
LOG(DFATAL) << "Framer called OnProtocolVersionMismatch for server. "
@@ -680,7 +675,7 @@ void QuicConnection::MaybeSendAckInResponseToPacket() {
}
void QuicConnection::SendVersionNegotiationPacket() {
- QuicVersionTagList supported_versions;
+ QuicTagVector supported_versions;
supported_versions.push_back(kQuicVersion1);
QuicEncryptedPacket* encrypted =
packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
@@ -1294,6 +1289,11 @@ bool QuicConnection::HasQueuedData() const {
return !queued_packets_.empty() || packet_generator_.HasQueuedData();
}
+void QuicConnection::SetConnectionTimeout(QuicTime::Delta timeout) {
+ timeout_ = timeout;
+ CheckForTimeout();
+}
+
bool QuicConnection::CheckForTimeout() {
QuicTime now = clock_->ApproximateNow();
QuicTime time_of_last_packet = std::max(time_of_last_received_packet_,
diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h
index 5e916f8..ce3a263 100644
--- a/net/quic/quic_connection.h
+++ b/net/quic/quic_connection.h
@@ -93,8 +93,7 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitorInterface {
// Called when the protocol version on the received packet doensn't match
// current protocol version of the connection.
- virtual void OnProtocolVersionMismatch(
- QuicVersionTag version) = 0;
+ virtual void OnProtocolVersionMismatch(QuicTag version) = 0;
// Called when the complete header of a packet has been parsed.
virtual void OnPacketHeader(const QuicPacketHeader& header) = 0;
@@ -258,14 +257,11 @@ class NET_EXPORT_PRIVATE QuicConnection
// queued writes to happen. Returns false if the socket has become blocked.
virtual bool OnCanWrite() OVERRIDE;
- QuicVersionTag version() const {
- return quic_version_;
- }
+ QuicTag version() const { return quic_version_; }
// From QuicFramerVisitorInterface
virtual void OnError(QuicFramer* framer) OVERRIDE;
- virtual bool OnProtocolVersionMismatch(
- QuicVersionTag received_version) OVERRIDE;
+ virtual bool OnProtocolVersionMismatch(QuicTag received_version) OVERRIDE;
virtual void OnPacket() OVERRIDE;
virtual void OnPublicResetPacket(
const QuicPublicResetPacket& packet) OVERRIDE;
@@ -330,6 +326,10 @@ class NET_EXPORT_PRIVATE QuicConnection
// Returns true if the connection has queued packets or frames.
bool HasQueuedData() const;
+ // Sets (or resets) the idle state connection timeout. Also, checks and times
+ // out the connection if network timer has expired for |timeout|.
+ void SetConnectionTimeout(QuicTime::Delta timeout);
+
// If the connection has timed out, this will close the connection and return
// true. Otherwise, it will return false and will reset the timeout alarm.
bool CheckForTimeout();
@@ -420,6 +420,9 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicConnectionHelperInterface* helper() { return helper_.get(); }
+ protected:
+ QuicFramer framer_;
+
private:
friend class test::QuicConnectionPeer;
@@ -480,8 +483,7 @@ class NET_EXPORT_PRIVATE QuicConnection
// Selects and updates the version of the protocol being used by selecting a
// version from |available_versions| which is also supported. Returns true if
// such a version exists, false otherwise.
- bool SelectMutualVersion(
- const QuicVersionTagList& available_versions);
+ bool SelectMutualVersion(const QuicTagVector& available_versions);
// Sends a version negotiation packet to the peer.
void SendVersionNegotiationPacket();
@@ -508,7 +510,6 @@ class NET_EXPORT_PRIVATE QuicConnection
void CloseFecGroupsBefore(QuicPacketSequenceNumber sequence_number);
scoped_ptr<QuicConnectionHelperInterface> helper_;
- QuicFramer framer_;
EncryptionLevel encryption_level_;
const QuicClock* clock_;
QuicRandom* random_generator_;
@@ -580,7 +581,7 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicPacketGenerator packet_generator_;
// Network idle time before we kill of this connection.
- const QuicTime::Delta timeout_;
+ QuicTime::Delta timeout_;
// Statistics for this session.
QuicConnectionStats stats_;
@@ -603,7 +604,7 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicVersionNegotiationState version_negotiation_state_;
// The version of the protocol this connection is using.
- QuicVersionTag quic_version_;
+ QuicTag quic_version_;
// Tracks if the connection was created by the server.
bool is_server_;
diff --git a/net/quic/quic_connection_helper_test.cc b/net/quic/quic_connection_helper_test.cc
index 3576981..0c81722 100644
--- a/net/quic/quic_connection_helper_test.cc
+++ b/net/quic/quic_connection_helper_test.cc
@@ -372,11 +372,11 @@ TEST_F(QuicConnectionHelperTest, TimeoutAfterSend) {
Initialize();
EXPECT_TRUE(connection_->connected());
- EXPECT_EQ(0u, clock_.NowAsDeltaSinceUnixEpoch().ToMicroseconds());
+ QuicTime start = clock_.ApproximateNow();
// When we send a packet, the timeout will change to 5000 + kDefaultTimeout.
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(5000));
- EXPECT_EQ(5000u, clock_.NowAsDeltaSinceUnixEpoch().ToMicroseconds());
+ EXPECT_EQ(5000u, clock_.ApproximateNow().Subtract(start).ToMicroseconds());
EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION));
// Send an ack so we don't set the retransmission alarm.
@@ -395,8 +395,8 @@ TEST_F(QuicConnectionHelperTest, TimeoutAfterSend) {
EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, NOT_RETRANSMISSION));
runner_->RunNextTask();
- EXPECT_EQ(kDefaultTimeoutUs + 5000,
- clock_.NowAsDeltaSinceUnixEpoch().ToMicroseconds());
+ EXPECT_EQ(kDefaultTimeoutUs + 5000, clock_.ApproximateNow().Subtract(
+ QuicTime::Zero()).ToMicroseconds());
EXPECT_FALSE(connection_->connected());
EXPECT_TRUE(AtEof());
}
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc
index 5b13c92..288d3dd 100644
--- a/net/quic/quic_connection_logger.cc
+++ b/net/quic/quic_connection_logger.cc
@@ -147,8 +147,7 @@ void QuicConnectionLogger::OnPacketReceived(const IPEndPoint& self_address,
packet.length()));
}
-void QuicConnectionLogger::OnProtocolVersionMismatch(
- QuicVersionTag received_version) {
+void QuicConnectionLogger::OnProtocolVersionMismatch(QuicTag received_version) {
// TODO(rtenneti): Add logging.
}
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index 4fe390b..9f38f22 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -24,8 +24,7 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
virtual void OnPacketReceived(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
const QuicEncryptedPacket& packet) OVERRIDE;
- virtual void OnProtocolVersionMismatch(
- QuicVersionTag version) OVERRIDE;
+ virtual void OnProtocolVersionMismatch(QuicTag version) OVERRIDE;
virtual void OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
virtual void OnAckFrame(const QuicAckFrame& frame) OVERRIDE;
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc
index e81e011..826681a 100644
--- a/net/quic/quic_connection_test.cc
+++ b/net/quic/quic_connection_test.cc
@@ -1889,7 +1889,7 @@ TEST_F(QuicConnectionTest, CheckSentEntropyHash) {
// TODO(satyamsehkhar): Add more test when we start supporting more versions.
TEST_F(QuicConnectionTest, SendVersionNegotiationPacket) {
- QuicVersionTag kRandomVersion = 143;
+ QuicTag kRandomVersion = 143;
QuicFramerPeer::SetVersion(&framer_, kRandomVersion);
QuicPacketHeader header;
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index e3ee834..75f5fd3 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -40,16 +40,6 @@ bool QuicCryptoClientStream::CryptoConnect() {
return true;
}
-const QuicNegotiatedParameters&
-QuicCryptoClientStream::negotiated_params() const {
- return negotiated_params_;
-}
-
-const QuicCryptoNegotiatedParameters&
-QuicCryptoClientStream::crypto_negotiated_params() const {
- return crypto_negotiated_params_;
-}
-
int QuicCryptoClientStream::num_sent_client_hellos() const {
return num_client_hellos_;
}
@@ -98,7 +88,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
server_hostname_,
session()->connection()->guid(),
cached,
- session()->connection()->clock(),
+ session()->connection()->clock()->WallNow(),
session()->connection()->random_generator(),
&crypto_negotiated_params_,
&out,
@@ -119,19 +109,25 @@ void QuicCryptoClientStream::DoHandshakeLoop(
SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key.
session()->connection()->SetAlternativeDecrypter(
- crypto_negotiated_params_.decrypter.release(),
+ crypto_negotiated_params_.initial_crypters.decrypter.release(),
true /* latch once used */);
// Send subsequent packets under encryption on the assumption that the
// server will accept the handshake.
session()->connection()->SetEncrypter(
ENCRYPTION_INITIAL,
- crypto_negotiated_params_.encrypter.release());
+ crypto_negotiated_params_.initial_crypters.encrypter.release());
session()->connection()->SetDefaultEncryptionLevel(
ENCRYPTION_INITIAL);
if (!encryption_established_) {
- session()->OnCryptoHandshakeEvent(
- QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
- encryption_established_ = true;
+ // TODO(agl): the following, commented code should live here and not
+ // down when the handshake is confirmed. However, it causes
+ // EndToEndTest.LargePost to be flaky (b/8074678), seemingly because
+ // the packets dropped when the client hello is dropped cause the
+ // congestion control to be too conservative and the server times
+ // out.
+ // session()->OnCryptoHandshakeEvent(
+ // QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
+ // encryption_established_ = true;
} else {
session()->OnCryptoHandshakeEvent(
QuicSession::ENCRYPTION_REESTABLISHED);
@@ -180,10 +176,19 @@ void QuicCryptoClientStream::DoHandshakeLoop(
ENCRYPTION_NONE);
next_state_ = STATE_SEND_CHLO;
break;
- case STATE_RECV_SHLO:
+ case STATE_RECV_SHLO: {
// We sent a CHLO that we expected to be accepted and now we're hoping
// for a SHLO from the server to confirm that.
if (in->tag() == kREJ) {
+ // alternative_decrypter will be NULL if the original alternative
+ // decrypter latched and became the primary decrypter. That happens
+ // if we received a message encrypted with the INITIAL key.
+ if (session()->connection()->alternative_decrypter() == NULL) {
+ // The rejection was sent encrypted!
+ CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+ "encrypted REJ message");
+ return;
+ }
next_state_ = STATE_RECV_REJ;
break;
}
@@ -192,11 +197,46 @@ void QuicCryptoClientStream::DoHandshakeLoop(
"Expected SHLO or REJ");
return;
}
- // TODO(agl): enable this once the tests are corrected to permit it.
- // DCHECK(session()->connection()->alternative_decrypter() == NULL);
+ // alternative_decrypter will be NULL if the original alternative
+ // decrypter latched and became the primary decrypter. That happens
+ // if we received a message encrypted with the INITIAL key.
+ if (session()->connection()->alternative_decrypter() != NULL) {
+ // The server hello was sent without encryption.
+ CloseConnectionWithDetails(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+ "unencrypted SHLO message");
+ return;
+ }
+ error = crypto_config_->ProcessServerHello(
+ *in, session()->connection()->guid(), &crypto_negotiated_params_,
+ &error_details);
+ if (error != QUIC_NO_ERROR) {
+ CloseConnectionWithDetails(
+ error, "Server hello invalid: " + error_details);
+ return;
+ }
+ CrypterPair* crypters =
+ &crypto_negotiated_params_.forward_secure_crypters;
+ // TODO(agl): we don't currently latch this decrypter because the idea
+ // has been floated that the server shouldn't send packets encrypted
+ // with the FORWARD_SECURE key until it receives a FORWARD_SECURE
+ // packet from the client.
+ session()->connection()->SetAlternativeDecrypter(
+ crypters->decrypter.release(), false /* don't latch */);
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE, crypters->encrypter.release());
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
+
+ // TODO(agl): this code shouldn't be here. See the TODO further up
+ // about it.
+ session()->OnCryptoHandshakeEvent(
+ QuicSession::ENCRYPTION_FIRST_ESTABLISHED);
+ encryption_established_ = true;
+
handshake_confirmed_ = true;
session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
return;
+ }
case STATE_IDLE:
// This means that the peer sent us a message that we weren't expecting.
CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
index 740c892..041d11c 100644
--- a/net/quic/quic_crypto_client_stream.h
+++ b/net/quic/quic_crypto_client_stream.h
@@ -37,9 +37,6 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
// TODO(agl): this should probably return void.
virtual bool CryptoConnect();
- const QuicNegotiatedParameters& negotiated_params() const;
- const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const;
-
// num_sent_client_hellos returns the number of client hello messages that
// have been sent. If the handshake has completed then this is one greater
// than the number of round-trips needed for the handshake.
@@ -67,9 +64,6 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
const QuicConfig& config_;
QuicCryptoClientConfig* const crypto_config_;
- QuicNegotiatedParameters negotiated_params_;
- QuicCryptoNegotiatedParameters crypto_negotiated_params_;
-
// Client's connection nonce (4-byte timestamp + 28 random bytes)
std::string nonce_;
// Server's hostname
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 96547e42..c913964 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -45,22 +45,6 @@ class TestQuicVisitor : public NoOpFramerVisitor {
DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor);
};
-// The same as MockSession, except that WriteData() is not mocked.
-class TestMockSession : public MockSession {
- public:
- TestMockSession(QuicConnection* connection, bool is_server)
- : MockSession(connection, is_server) {
- }
- virtual ~TestMockSession() {}
-
- virtual QuicConsumedData WriteData(QuicStreamId id,
- base::StringPiece data,
- QuicStreamOffset offset,
- bool fin) OVERRIDE {
- return QuicSession::WriteData(id, data, offset, fin);
- }
-};
-
class QuicCryptoClientStreamTest : public ::testing::Test {
public:
QuicCryptoClientStreamTest()
@@ -68,6 +52,7 @@ class QuicCryptoClientStreamTest : public ::testing::Test {
connection_(new PacketSavingConnection(1, addr_, true)),
session_(connection_, true),
stream_(kServerHostname, config_, &session_, &crypto_config_) {
+ session_.SetCryptoStream(&stream_);
config_.SetDefaults();
crypto_config_.SetDefaults();
}
@@ -84,7 +69,7 @@ class QuicCryptoClientStreamTest : public ::testing::Test {
IPEndPoint addr_;
PacketSavingConnection* connection_;
- TestMockSession session_;
+ TestSession session_;
QuicCryptoClientStream stream_;
CryptoHandshakeMessage message_;
scoped_ptr<QuicData> message_data_;
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
index 1dab72f..57c1076 100644
--- a/net/quic/quic_crypto_server_stream.cc
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -40,54 +40,60 @@ void QuicCryptoServerStream::OnHandshakeMessage(
string error_details;
CryptoHandshakeMessage reply;
- crypto_config_.ProcessClientHello(
+ QuicErrorCode error = crypto_config_.ProcessClientHello(
message, session()->connection()->guid(),
session()->connection()->peer_address(),
- session()->connection()->clock()->NowAsDeltaSinceUnixEpoch(),
+ session()->connection()->clock(),
session()->connection()->random_generator(),
&crypto_negotiated_params_, &reply, &error_details);
- if (reply.tag() == kSHLO) {
- // If we are returning a SHLO then we accepted the handshake.
- QuicErrorCode error = config_.ProcessFinalPeerHandshake(
- message, CryptoUtils::LOCAL_PRIORITY, &negotiated_params_,
- &error_details);
- if (error != QUIC_NO_ERROR) {
- CloseConnectionWithDetails(error, error_details);
- return;
- }
+ if (error != QUIC_NO_ERROR) {
+ CloseConnectionWithDetails(error, error_details);
+ return;
+ }
+
+ if (reply.tag() != kSHLO) {
+ SendHandshakeMessage(reply);
+ return;
+ }
- // Receiving a full CHLO implies the client is prepared to decrypt with
- // the new server write key. We can start to encrypt with the new server
- // write key.
- //
- // NOTE: the SHLO will be encrypted with the new server write key.
- session()->connection()->SetEncrypter(
- ENCRYPTION_INITIAL,
- crypto_negotiated_params_.encrypter.release());
- session()->connection()->SetDefaultEncryptionLevel(
- ENCRYPTION_INITIAL);
- // Set the decrypter immediately so that we no longer accept unencrypted
- // packets.
- session()->connection()->SetDecrypter(
- crypto_negotiated_params_.decrypter.release());
- encryption_established_ = true;
- handshake_confirmed_ = true;
- session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
+ // If we are returning a SHLO then we accepted the handshake.
+ error = config_.ProcessFinalPeerHandshake(
+ message, CryptoUtils::LOCAL_PRIORITY, &negotiated_params_,
+ &error_details);
+ if (error != QUIC_NO_ERROR) {
+ CloseConnectionWithDetails(error, error_details);
+ return;
}
+ // Receiving a full CHLO implies the client is prepared to decrypt with
+ // the new server write key. We can start to encrypt with the new server
+ // write key.
+ //
+ // NOTE: the SHLO will be encrypted with the new server write key.
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_INITIAL,
+ crypto_negotiated_params_.initial_crypters.encrypter.release());
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_INITIAL);
+ // Set the decrypter immediately so that we no longer accept unencrypted
+ // packets.
+ session()->connection()->SetDecrypter(
+ crypto_negotiated_params_.initial_crypters.decrypter.release());
SendHandshakeMessage(reply);
- return;
-}
-const QuicNegotiatedParameters&
-QuicCryptoServerStream::negotiated_params() const {
- return negotiated_params_;
-}
+ session()->connection()->SetEncrypter(
+ ENCRYPTION_FORWARD_SECURE,
+ crypto_negotiated_params_.forward_secure_crypters.encrypter.release());
+ session()->connection()->SetDefaultEncryptionLevel(
+ ENCRYPTION_FORWARD_SECURE);
+ session()->connection()->SetAlternativeDecrypter(
+ crypto_negotiated_params_.forward_secure_crypters.decrypter.release(),
+ false /* don't latch */);
-const QuicCryptoNegotiatedParameters&
-QuicCryptoServerStream::crypto_negotiated_params() const {
- return crypto_negotiated_params_;
+ encryption_established_ = true;
+ handshake_confirmed_ = true;
+ session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
}
} // namespace net
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
index 3e4264a..47c1478 100644
--- a/net/quic/quic_crypto_server_stream.h
+++ b/net/quic/quic_crypto_server_stream.h
@@ -34,9 +34,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream : public QuicCryptoStream {
virtual void OnHandshakeMessage(
const CryptoHandshakeMessage& message) OVERRIDE;
- const QuicNegotiatedParameters& negotiated_params() const;
- const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const;
-
private:
friend class test::CryptoTestUtils;
@@ -45,9 +42,6 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream : public QuicCryptoStream {
const QuicConfig& config_;
// crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig& crypto_config_;
-
- QuicNegotiatedParameters negotiated_params_;
- QuicCryptoNegotiatedParameters crypto_negotiated_params_;
};
} // namespace net
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index 2cc2746..d12597b 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -54,18 +54,6 @@ class TestQuicVisitor : public NoOpFramerVisitor {
DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor);
};
-class TestSession: public QuicSession {
- public:
- TestSession(QuicConnection* connection, bool is_server)
- : QuicSession(connection, is_server) {
- }
-
- MOCK_METHOD1(CreateIncomingReliableStream,
- ReliableQuicStream*(QuicStreamId id));
- MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
- MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
-};
-
class QuicCryptoServerStreamTest : public ::testing::Test {
public:
QuicCryptoServerStreamTest()
@@ -76,6 +64,7 @@ class QuicCryptoServerStreamTest : public ::testing::Test {
session_(connection_, true),
crypto_config_(QuicCryptoServerConfig::TESTING),
stream_(config_, crypto_config_, &session_) {
+ session_.SetCryptoStream(&stream_);
// We advance the clock initially because the default time is zero and the
// strike register worries that we've just overflowed a uint32 time.
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
@@ -152,8 +141,8 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
new PacketSavingConnection(guid, addr, false);
PacketSavingConnection* server_conn =
new PacketSavingConnection(guid, addr, false);
- client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
- server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
+ client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
+ server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
scoped_ptr<TestSession> client_session(new TestSession(client_conn, true));
scoped_ptr<TestSession> server_session(new TestSession(server_conn, true));
@@ -167,6 +156,7 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream(
"test.example.com", client_config, client_session.get(),
&client_crypto_config));
+ client_session->SetCryptoStream(client.get());
// Do a first handshake in order to prime the client config with the server's
// information.
@@ -176,6 +166,7 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
scoped_ptr<QuicCryptoServerStream> server(
new QuicCryptoServerStream(config_, crypto_config_,
server_session.get()));
+ server_session->SetCryptoStream(server.get());
CryptoTestUtils::CommunicateHandshakeMessages(
client_conn, client.get(), server_conn, server.get());
@@ -188,8 +179,8 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
server_conn = new PacketSavingConnection(guid, addr, false);
// We need to advance time past the strike-server window so that it's
// authoritative in this time span.
- client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000));
- server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1002000));
+ client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
+ server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
// This causes the client's nonce to be different and thus stops the
// strike-register from rejecting the repeated nonce.
@@ -199,8 +190,11 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
client.reset(new QuicCryptoClientStream(
"test.example.com", client_config, client_session.get(),
&client_crypto_config));
+ client_session->SetCryptoStream(client.get());
+
server.reset(new QuicCryptoServerStream(config_, crypto_config_,
server_session.get()));
+ server_session->SetCryptoStream(server.get());
CHECK(client->CryptoConnect());
diff --git a/net/quic/quic_crypto_stream.cc b/net/quic/quic_crypto_stream.cc
index df6c610..70bf4d3 100644
--- a/net/quic/quic_crypto_stream.cc
+++ b/net/quic/quic_crypto_stream.cc
@@ -57,4 +57,14 @@ void QuicCryptoStream::SendHandshakeMessage(
WriteData(string(data.data(), data.length()), false);
}
+const QuicNegotiatedParameters&
+QuicCryptoStream::negotiated_params() const {
+ return negotiated_params_;
+}
+
+const QuicCryptoNegotiatedParameters&
+QuicCryptoStream::crypto_negotiated_params() const {
+ return crypto_negotiated_params_;
+}
+
} // namespace net
diff --git a/net/quic/quic_crypto_stream.h b/net/quic/quic_crypto_stream.h
index db83503..1352f2e 100644
--- a/net/quic/quic_crypto_stream.h
+++ b/net/quic/quic_crypto_stream.h
@@ -7,6 +7,7 @@
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/quic_config.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/reliable_quic_stream.h"
@@ -45,6 +46,9 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
bool encryption_established() { return encryption_established_; }
bool handshake_confirmed() { return handshake_confirmed_; }
+ const QuicNegotiatedParameters& negotiated_params() const;
+ const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const;
+
protected:
// Closes the connection
void CloseConnection(QuicErrorCode error);
@@ -53,6 +57,9 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
bool encryption_established_;
bool handshake_confirmed_;
+ QuicNegotiatedParameters negotiated_params_;
+ QuicCryptoNegotiatedParameters crypto_negotiated_params_;
+
private:
CryptoFramer crypto_framer_;
diff --git a/net/quic/quic_crypto_stream_test.cc b/net/quic/quic_crypto_stream_test.cc
index 6e465ab..cc69304 100644
--- a/net/quic/quic_crypto_stream_test.cc
+++ b/net/quic/quic_crypto_stream_test.cc
@@ -98,7 +98,11 @@ TEST_F(QuicCryptoStreamTest, ProcessData) {
TEST_F(QuicCryptoStreamTest, ProcessBadData) {
string bad(message_data_->data(), message_data_->length());
- bad[8] = 0x7F; // out of order tag
+ const int kFirstTagIndex = sizeof(uint32) + // message tag
+ sizeof(uint16) + // number of tag-value pairs
+ sizeof(uint16); // padding
+ EXPECT_EQ(1, bad[kFirstTagIndex]);
+ bad[kFirstTagIndex] = 0x7F; // out of order tag
EXPECT_CALL(*connection_,
SendConnectionClose(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index 95c42b7..67a376e 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -45,7 +45,7 @@ QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target,
} // namespace
-QuicFramer::QuicFramer(QuicVersionTag version,
+QuicFramer::QuicFramer(QuicTag version,
QuicTime creation_time,
bool is_server)
: visitor_(NULL),
@@ -54,6 +54,7 @@ QuicFramer::QuicFramer(QuicVersionTag version,
last_sequence_number_(0),
quic_version_(version),
decrypter_(QuicDecrypter::Create(kNULL)),
+ alternative_decrypter_latch_(false),
is_server_(is_server),
creation_time_(creation_time) {
DCHECK(IsSupportedVersion(version));
@@ -101,7 +102,7 @@ size_t QuicFramer::GetMinGoAwayFrameSize() {
kQuicStreamIdSize;
}
-bool QuicFramer::IsSupportedVersion(QuicVersionTag version) {
+bool QuicFramer::IsSupportedVersion(QuicTag version) {
return version == kQuicVersion1;
}
@@ -288,7 +289,7 @@ QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket(
QuicEncryptedPacket* QuicFramer::ConstructVersionNegotiationPacket(
const QuicPacketPublicHeader& header,
- const QuicVersionTagList& supported_versions) {
+ const QuicTagVector& supported_versions) {
DCHECK(header.version_flag);
size_t len = GetVersionNegotiationPacketSize(supported_versions.size());
QuicDataWriter writer(len);
@@ -350,7 +351,7 @@ bool QuicFramer::ProcessVersionNegotiationPacket(
DCHECK(!is_server_);
// Try reading at least once to raise error if the packet is invalid.
do {
- QuicVersionTag version;
+ QuicTag version;
if (!reader_->ReadBytes(&version, kQuicVersionSize)) {
set_detailed_error("Unable to read supported version in negotiation.");
return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
@@ -553,7 +554,7 @@ bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) {
}
if (public_header->version_flag && is_server_) {
- QuicVersionTag version;
+ QuicTag version;
if (!reader_->ReadUInt32(&version)) {
// Read the version only if the packet is from the client.
// version flag from the server means version negotiation packet.
@@ -1068,6 +1069,18 @@ const QuicEncrypter* QuicFramer::encrypter(EncryptionLevel level) const {
return encrypter_[level].get();
}
+void QuicFramer::SwapCryptersForTest(QuicFramer* other) {
+ for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) {
+ encrypter_[i].swap(other->encrypter_[i]);
+ }
+ decrypter_.swap(other->decrypter_);
+ alternative_decrypter_.swap(other->alternative_decrypter_);
+
+ const bool other_latch = other->alternative_decrypter_latch_;
+ other->alternative_decrypter_latch_ = alternative_decrypter_latch_;
+ alternative_decrypter_latch_ = other_latch;
+}
+
QuicEncryptedPacket* QuicFramer::EncryptPacket(
EncryptionLevel level,
QuicPacketSequenceNumber packet_sequence_number,
@@ -1116,26 +1129,21 @@ bool QuicFramer::DecryptPayload(QuicPacketSequenceNumber sequence_number,
return false;
}
DCHECK(decrypter_.get() != NULL);
- LOG(INFO) << "Decrypting packet";
decrypted_.reset(decrypter_->DecryptPacket(
sequence_number,
GetAssociatedDataFromEncryptedPacket(packet, version_flag),
encrypted));
if (decrypted_.get() == NULL && alternative_decrypter_.get() != NULL) {
- LOG(INFO) << "Trying alternative";
decrypted_.reset(alternative_decrypter_->DecryptPacket(
sequence_number,
GetAssociatedDataFromEncryptedPacket(packet, version_flag),
encrypted));
if (decrypted_.get() != NULL) {
- LOG(INFO) << "alternative ok";
if (alternative_decrypter_latch_) {
- LOG(INFO) << " latching";
// Switch to the alternative decrypter and latch so that we cannot
// switch back.
decrypter_.reset(alternative_decrypter_.release());
} else {
- LOG(INFO) << " swapping";
// Switch the alternative decrypter so that we use it first next time.
decrypter_.swap(alternative_decrypter_);
}
diff --git a/net/quic/quic_framer.h b/net/quic/quic_framer.h
index 1802fed..8286844 100644
--- a/net/quic/quic_framer.h
+++ b/net/quic/quic_framer.h
@@ -64,7 +64,7 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
// |quic_version_|. The visitor should return true after it updates the
// version of the |framer_| to |received_version| or false to stop processing
// this packet.
- virtual bool OnProtocolVersionMismatch(QuicVersionTag received_version) = 0;
+ virtual bool OnProtocolVersionMismatch(QuicTag received_version) = 0;
// Called when a new packet has been received, before it
// has been validated or processed.
@@ -153,14 +153,14 @@ class NET_EXPORT_PRIVATE QuicFramer {
public:
// Constructs a new framer that installs a kNULL QuicEncrypter and
// QuicDecrypter for level ENCRYPTION_NONE.
- QuicFramer(QuicVersionTag quic_version,
+ QuicFramer(QuicTag quic_version,
QuicTime creation_time,
bool is_server);
virtual ~QuicFramer();
// Returns true if |version| is a supported protocol version.
- bool IsSupportedVersion(QuicVersionTag version);
+ bool IsSupportedVersion(QuicTag version);
// Calculates the largest observed packet to advertise in the case an Ack
// Frame was truncated. last_written in this case is the iterator for the
@@ -184,11 +184,11 @@ class NET_EXPORT_PRIVATE QuicFramer {
fec_builder_ = builder;
}
- QuicVersionTag version() const {
+ QuicTag version() const {
return quic_version_;
}
- void set_version(QuicVersionTag version) {
+ void set_version(QuicTag version) {
DCHECK(IsSupportedVersion(version));
quic_version_ = version;
}
@@ -271,7 +271,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicEncryptedPacket* ConstructVersionNegotiationPacket(
const QuicPacketPublicHeader& header,
- const QuicVersionTagList& supported_versions);
+ const QuicTagVector& supported_versions);
// SetDecrypter sets the primary decrypter, replacing any that already exists,
// and takes ownership. If an alternative decrypter is in place then the
@@ -296,6 +296,10 @@ class NET_EXPORT_PRIVATE QuicFramer {
void SetEncrypter(EncryptionLevel level, QuicEncrypter* encrypter);
const QuicEncrypter* encrypter(EncryptionLevel level) const;
+ // SwapCryptersForTest exchanges the state of the crypters with |other|. To
+ // be used in tests only.
+ void SwapCryptersForTest(QuicFramer* other);
+
// Returns a new encrypted packet, owned by the caller.
QuicEncryptedPacket* EncryptPacket(EncryptionLevel level,
QuicPacketSequenceNumber sequence_number,
@@ -396,7 +400,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Buffer containing decrypted payload data during parsing.
scoped_ptr<QuicData> decrypted_;
// Version of the protocol being used.
- QuicVersionTag quic_version_;
+ QuicTag quic_version_;
// Primary decrypter used to decrypt packets during parsing.
scoped_ptr<QuicDecrypter> decrypter_;
// Alternative decrypter that can also be used to decrypt packets.
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc
index 6e2556c..6986443 100644
--- a/net/quic/quic_framer_test.cc
+++ b/net/quic/quic_framer_test.cc
@@ -190,8 +190,7 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface {
revived_packets_++;
}
- virtual bool OnProtocolVersionMismatch(
- QuicVersionTag version) OVERRIDE {
+ virtual bool OnProtocolVersionMismatch(QuicTag version) OVERRIDE {
DCHECK(false);
return true;
}
@@ -573,7 +572,7 @@ TEST_F(QuicFramerTest, PacketHeaderWithVersionFlag) {
// public flags (version)
0x01,
// version tag
- 'Q', '1', '.', '0',
+ 'Q', '0', '0', '1',
// packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
@@ -818,7 +817,7 @@ TEST_F(QuicFramerTest, StreamFrameWithVersion) {
// public flags (version)
0x01,
// version tag
- 'Q', '1', '.', '0',
+ 'Q', '0', '0', '1',
// packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
@@ -1627,7 +1626,7 @@ TEST_F(QuicFramerTest, VersionNegotiationPacket) {
// public flags (version)
0x01,
// version tag
- 'Q', '1', '.', '0',
+ 'Q', '0', '0', '1',
'Q', '2', '.', '0',
};
@@ -1826,7 +1825,7 @@ TEST_F(QuicFramerTest, ConstructStreamFramePacketWithVersionFlag) {
// public flags (version)
0x01,
// version tag
- 'Q', '1', '.', '0',
+ 'Q', '0', '0', '1',
// packet sequence number
0xBC, 0x9A, 0x78, 0x56,
0x34, 0x12,
@@ -1874,12 +1873,12 @@ TEST_F(QuicFramerTest, ConstructVersionNegotiationPacket) {
// public flags (version)
0x01,
// version tag
- 'Q', '1', '.', '0',
+ 'Q', '0', '0', '1',
'Q', '2', '.', '0',
};
const int kQuicVersion2 = MakeQuicTag('Q', '2', '.', '0');
- QuicVersionTagList versions;
+ QuicTagVector versions;
versions.push_back(kQuicVersion1);
versions.push_back(kQuicVersion2);
scoped_ptr<QuicEncryptedPacket> data(
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
index 5339a7f..2cdfd69 100644
--- a/net/quic/quic_packet_creator.cc
+++ b/net/quic/quic_packet_creator.cc
@@ -177,7 +177,7 @@ SerializedPacket QuicPacketCreator::SerializeConnectionClose(
}
QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
- const QuicVersionTagList& supported_versions) {
+ const QuicTagVector& supported_versions) {
DCHECK(is_server_);
QuicPacketPublicHeader header;
header.guid = guid_;
diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h
index 2e5c596..6f557c0a 100644
--- a/net/quic/quic_packet_creator.h
+++ b/net/quic/quic_packet_creator.h
@@ -120,7 +120,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// serialized packet to a random bool and returns that value as a member of
// SerializedPacket.
QuicEncryptedPacket* SerializeVersionNegotiationPacket(
- const QuicVersionTagList& supported_versions);
+ const QuicTagVector& supported_versions);
QuicPacketSequenceNumber sequence_number() const {
return sequence_number_;
diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc
index 4fe4f18..bd4f332 100644
--- a/net/quic/quic_packet_creator_test.cc
+++ b/net/quic/quic_packet_creator_test.cc
@@ -179,7 +179,7 @@ TEST_F(QuicPacketCreatorTest, CreateStreamFrameFinOnly) {
TEST_F(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
QuicPacketCreatorPeer::SetIsServer(&creator_, true);
- QuicVersionTagList versions;
+ QuicTagVector versions;
versions.push_back(kQuicVersion1);
scoped_ptr<QuicEncryptedPacket> encrypted(
creator_.SerializeVersionNegotiationPacket(versions));
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h
index c3fd9a0..31fab86 100644
--- a/net/quic/quic_protocol.h
+++ b/net/quic/quic_protocol.h
@@ -36,9 +36,10 @@ typedef uint64 QuicPacketSequenceNumber;
typedef QuicPacketSequenceNumber QuicFecGroupNumber;
typedef uint64 QuicPublicResetNonceProof;
typedef uint8 QuicPacketEntropyHash;
-typedef uint32 QuicVersionTag;
-typedef std::vector<QuicVersionTag> QuicVersionTagList;
typedef uint32 QuicHeaderId;
+// QuicTag is the type of a tag in the wire protocol.
+typedef uint32 QuicTag;
+typedef std::vector<QuicTag> QuicTagVector;
// TODO(rch): Consider Quic specific names for these constants.
// Maximum size in bytes of a QUIC packet.
@@ -75,7 +76,7 @@ NET_EXPORT_PRIVATE size_t GetStartOfFecProtectedData(bool include_version);
// Index of the first byte in a QUIC packet of encrypted data.
NET_EXPORT_PRIVATE size_t GetStartOfEncryptedData(bool include_version);
// Returns true if |version| is a supported protocol version.
-NET_EXPORT_PRIVATE bool IsSupportedVersion(QuicVersionTag version);
+NET_EXPORT_PRIVATE bool IsSupportedVersion(QuicTag version);
// Index of the first byte in a QUIC packet which is used in hash calculation.
const size_t kStartOfHashData = 0;
@@ -95,13 +96,13 @@ const uint8 kNoFecOffset = 0xFF;
const int64 kDefaultTimeoutUs = 600000000; // 10 minutes.
enum Retransmission {
- NOT_RETRANSMISSION = 0,
- IS_RETRANSMISSION = 1,
+ NOT_RETRANSMISSION,
+ IS_RETRANSMISSION,
};
enum HasRetransmittableData {
- HAS_RETRANSMITTABLE_DATA = 0,
- NO_RETRANSMITTABLE_DATA = 1,
+ NO_RETRANSMITTABLE_DATA,
+ HAS_RETRANSMITTABLE_DATA,
};
enum QuicFrameType {
@@ -233,6 +234,11 @@ enum QuicErrorCode {
QUIC_PROOF_INVALID,
// A crypto message was received with a duplicate tag.
QUIC_CRYPTO_DUPLICATE_TAG,
+ // A crypto message was received with the wrong encryption level (i.e. it
+ // should have been encrypted but was not.)
+ QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT,
+ // The server config for a server has expired.
+ QUIC_CRYPTO_SERVER_CONFIG_EXPIRED,
// No error. Used as bound while iterating.
QUIC_LAST_ERROR,
@@ -248,8 +254,11 @@ enum QuicErrorCode {
// The TAG macro is used in header files to ensure that we don't create static
// initialisers. In normal code, the MakeQuicTag function should be used.
#define TAG(a, b, c, d) ((d << 24) + (c << 16) + (b << 8) + a)
-const QuicVersionTag kUnsupportedVersion = -1;
-const QuicVersionTag kQuicVersion1 = TAG('Q', '1', '.', '0');
+const QuicTag kUnsupportedVersion = -1;
+// Each time the wire format changes, this need needs to be incremented.
+// At some point, we will actually freeze the wire format and make an official
+// version number, but this works for now.
+const QuicTag kQuicVersion1 = TAG('Q', '0', '0', '1');
#undef TAG
// MakeQuicTag returns a value given the four bytes. For example:
@@ -267,7 +276,7 @@ struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
QuicGuid guid;
bool reset_flag;
bool version_flag;
- QuicVersionTagList versions;
+ QuicTagVector versions;
};
// Header for Data or FEC packets.
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc
index 80f6f6a..271cca6 100644
--- a/net/quic/quic_protocol_test.cc
+++ b/net/quic/quic_protocol_test.cc
@@ -11,6 +11,16 @@ namespace net {
namespace test {
namespace {
+TEST(QuicProtocolTest, MakeQuicTag) {
+ QuicTag tag = MakeQuicTag('A', 'B', 'C', 'D');
+ char bytes[4];
+ memcpy(bytes, &tag, 4);
+ EXPECT_EQ('A', bytes[0]);
+ EXPECT_EQ('B', bytes[1]);
+ EXPECT_EQ('C', bytes[2]);
+ EXPECT_EQ('D', bytes[3]);
+}
+
TEST(QuicProtocolTest, IsAawaitingPacket) {
ReceivedPacketInfo received_info;
received_info.largest_observed = 10u;
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 8cd605a..66879300 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -213,6 +213,10 @@ bool QuicSession::IsCryptoHandshakeConfirmed() {
}
void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
+ if (event == QuicSession::HANDSHAKE_CONFIRMED) {
+ connection_->SetConnectionTimeout(
+ GetCryptoStream()->negotiated_params().idle_connection_state_lifetime);
+ }
}
void QuicSession::ActivateStream(ReliableQuicStream* stream) {
diff --git a/net/quic/quic_time.cc b/net/quic/quic_time.cc
index c4c80b0..fa0d516 100644
--- a/net/quic/quic_time.cc
+++ b/net/quic/quic_time.cc
@@ -99,4 +99,56 @@ QuicTime::Delta QuicTime::Subtract(const QuicTime& other) const {
return QuicTime::Delta(ticks_ - other.ticks_);
}
+// static
+QuicWallTime QuicWallTime::FromUNIXSeconds(uint64 seconds) {
+ return QuicWallTime(seconds);
+}
+
+uint64 QuicWallTime::ToUNIXSeconds() const {
+ return seconds_;
+}
+
+bool QuicWallTime::IsAfter(QuicWallTime other) const {
+ return seconds_ > other.seconds_;
+}
+
+bool QuicWallTime::IsBefore(QuicWallTime other) const {
+ return seconds_ < other.seconds_;
+}
+
+QuicTime::Delta QuicWallTime::AbsoluteDifference(QuicWallTime other) const {
+ uint64 d;
+
+ if (seconds_ > other.seconds_) {
+ d = seconds_ - other.seconds_;
+ } else {
+ d = other.seconds_ - seconds_;
+ }
+
+ if (d > static_cast<uint64>(kint64max)) {
+ d = kint64max;
+ }
+ return QuicTime::Delta::FromSeconds(d);
+}
+
+QuicWallTime QuicWallTime::Add(QuicTime::Delta delta) const {
+ uint64 seconds = seconds_ + delta.ToSeconds();
+ if (seconds < seconds_) {
+ seconds = kuint64max;
+ }
+ return QuicWallTime(seconds);
+}
+
+QuicWallTime QuicWallTime::Subtract(QuicTime::Delta delta) const {
+ uint64 seconds = seconds_ - delta.ToSeconds();
+ if (seconds > seconds_) {
+ seconds = 0;
+ }
+ return QuicWallTime(seconds);
+}
+
+QuicWallTime::QuicWallTime(uint64 seconds)
+ : seconds_(seconds) {
+}
+
} // namespace net
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h
index dc919fc..067027b 100644
--- a/net/quic/quic_time.h
+++ b/net/quic/quic_time.h
@@ -19,6 +19,9 @@ namespace net {
static const uint64 kNumMicrosPerSecond = base::Time::kMicrosecondsPerSecond;
+// A QuicTime is a purely relative time. QuicTime values from different clocks
+// cannot be compared to each other. If you need an absolute time, see
+// QuicWallTime, below.
class NET_EXPORT_PRIVATE QuicTime {
public:
// A QuicTime::Delta represents the signed difference between two points in
@@ -96,6 +99,40 @@ class NET_EXPORT_PRIVATE QuicTime {
base::TimeTicks ticks_;
};
+// A QuicWallTime represents an absolute time that is globally consistent. It
+// provides, at most, one second granularity and, in practice, clock-skew means
+// that you shouldn't even depend on that.
+class NET_EXPORT_PRIVATE QuicWallTime {
+ public:
+ // FromUNIXSeconds constructs a QuicWallTime from a count of the seconds
+ // since the UNIX epoch.
+ static QuicWallTime FromUNIXSeconds(uint64 seconds);
+
+ // ToUNIXSeconds converts a QuicWallTime into a count of seconds since the
+ // UNIX epoch.
+ uint64 ToUNIXSeconds() const;
+
+ bool IsAfter(QuicWallTime other) const;
+ bool IsBefore(QuicWallTime other) const;
+
+ // AbsoluteDifference returns the absolute value of the time difference
+ // between |this| and |other|.
+ QuicTime::Delta AbsoluteDifference(QuicWallTime other) const;
+
+ // Add returns a new QuicWallTime that represents the time of |this| plus
+ // |delta|.
+ QuicWallTime Add(QuicTime::Delta delta) const;
+
+ // Subtract returns a new QuicWallTime that represents the time of |this|
+ // minus |delta|.
+ QuicWallTime Subtract(QuicTime::Delta delta) const;
+
+ private:
+ explicit QuicWallTime(uint64 seconds);
+
+ uint64 seconds_;
+};
+
// Non-member relational operators for QuicTime::Delta.
inline bool operator==(QuicTime::Delta lhs, QuicTime::Delta rhs) {
return lhs.ToMicroseconds() == rhs.ToMicroseconds();
diff --git a/net/quic/quic_utils.cc b/net/quic/quic_utils.cc
index 142f9cc..228b796 100644
--- a/net/quic/quic_utils.cc
+++ b/net/quic/quic_utils.cc
@@ -127,6 +127,8 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_CONNECTION_TIMED_OUT);
RETURN_STRING_LITERAL(QUIC_PROOF_INVALID);
RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED);
RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
// if we add errors and don't put them here.
diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc
index cdcec21..cadbe9a 100644
--- a/net/quic/reliable_quic_stream.cc
+++ b/net/quic/reliable_quic_stream.cc
@@ -20,7 +20,7 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
visitor_(NULL),
stream_bytes_read_(0),
stream_bytes_written_(0),
- headers_complete_(false),
+ headers_decompressed_(false),
headers_id_(0),
stream_error_(QUIC_STREAM_NO_ERROR),
connection_error_(QUIC_NO_ERROR),
@@ -99,7 +99,7 @@ void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
}
int ReliableQuicStream::Readv(const struct iovec* iov, int iov_len) {
- if (headers_complete_ && decompressed_headers_.empty()) {
+ if (headers_decompressed_ && decompressed_headers_.empty()) {
return sequencer_.Readv(iov, iov_len);
}
size_t bytes_consumed = 0;
@@ -119,7 +119,7 @@ int ReliableQuicStream::Readv(const struct iovec* iov, int iov_len) {
}
int ReliableQuicStream::GetReadableRegions(iovec* iov, int iov_len) {
- if (headers_complete_ && decompressed_headers_.empty()) {
+ if (headers_decompressed_ && decompressed_headers_.empty()) {
return sequencer_.GetReadableRegions(iov, iov_len);
}
if (iov_len == 0) {
@@ -132,7 +132,7 @@ int ReliableQuicStream::GetReadableRegions(iovec* iov, int iov_len) {
}
bool ReliableQuicStream::IsHalfClosed() const {
- if (!headers_complete_ || !decompressed_headers_.empty()) {
+ if (!headers_decompressed_ || !decompressed_headers_.empty()) {
return false;
}
return sequencer_.IsHalfClosed();
@@ -254,9 +254,16 @@ uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
DCHECK_NE(0u, headers_id_);
// Once the headers are finished, we simply pass the data through.
- if (headers_complete_ && decompressed_headers_.empty()) {
- DVLOG(1) << "Delegating procesing to ProcessData";
- return total_bytes_consumed + ProcessData(data, data_len);
+ if (headers_decompressed_) {
+ // Some buffered header data remains.
+ if (!decompressed_headers_.empty()) {
+ ProcessHeaderData();
+ }
+ if (decompressed_headers_.empty()) {
+ DVLOG(1) << "Delegating procesing to ProcessData";
+ total_bytes_consumed += ProcessData(data, data_len);
+ }
+ return total_bytes_consumed;
}
QuicHeaderId current_header_id =
@@ -264,9 +271,11 @@ uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
// Ensure that this header id looks sane.
if (headers_id_ < current_header_id ||
headers_id_ > kMaxHeaderIdDelta + current_header_id) {
- DVLOG(1) << "Invalud headers for stream: " << id()
- << " header_id: " << headers_id_;
+ DVLOG(1) << "Invalid headers for stream: " << id()
+ << " header_id: " << headers_id_
+ << " current_header_id: " << current_header_id;
session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
+ return total_bytes_consumed;
}
// If we are head-of-line blocked on decompression, then back up.
@@ -284,18 +293,10 @@ uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
// Headers are complete if the decompressor has moved on to the
// next stream.
- headers_complete_ =
+ headers_decompressed_ =
session_->decompressor()->current_header_id() != headers_id_;
- if (!decompressed_headers_.empty()) {
- size_t bytes_processed = ProcessData(decompressed_headers_.data(),
- decompressed_headers_.length());
- if (bytes_processed == decompressed_headers_.length()) {
- decompressed_headers_.clear();
- } else {
- decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
- }
- }
+ ProcessHeaderData();
// We have processed all of the decompressed data but we might
// have some more raw data to process.
@@ -327,24 +328,24 @@ uint32 ReliableQuicStream::ProcessHeaderData() {
void ReliableQuicStream::OnDecompressorAvailable() {
DCHECK_EQ(headers_id_,
session_->decompressor()->current_header_id());
- DCHECK(!headers_complete_);
+ DCHECK(!headers_decompressed_);
DCHECK_EQ(0u, decompressed_headers_.length());
size_t total_bytes_consumed = 0;
struct iovec iovecs[5];
- while (!headers_complete_) {
+ while (!headers_decompressed_) {
size_t num_iovecs =
sequencer_.GetReadableRegions(iovecs, arraysize(iovecs));
if (num_iovecs == 0) {
return;
}
- for (size_t i = 0; i < num_iovecs && !headers_complete_; i++) {
+ for (size_t i = 0; i < num_iovecs && !headers_decompressed_; i++) {
total_bytes_consumed += session_->decompressor()->DecompressData(
StringPiece(static_cast<char*>(iovecs[i].iov_base),
iovecs[i].iov_len), this);
- headers_complete_ =
+ headers_decompressed_ =
session_->decompressor()->current_header_id() != headers_id_;
}
}
@@ -354,7 +355,7 @@ void ReliableQuicStream::OnDecompressorAvailable() {
ProcessHeaderData(); // Unprocessed headers remain in decompressed_headers_.
- if (headers_complete_ && decompressed_headers_.empty()) {
+ if (headers_decompressed_ && decompressed_headers_.empty()) {
sequencer_.FlushBufferedFrames();
}
}
diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h
index 2aa66e6..726cc9c 100644
--- a/net/quic/reliable_quic_stream.h
+++ b/net/quic/reliable_quic_stream.h
@@ -126,6 +126,8 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
// Close the write side of the socket. Further writes will fail.
void CloseWriteSide();
+ bool fin_buffered() { return fin_buffered_; }
+
QuicSession* session() { return session_; }
// Sends as much of 'data' to the connection as the connection will consume,
@@ -154,7 +156,7 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
uint64 stream_bytes_read_;
uint64 stream_bytes_written_;
// True if the headers have been completely decompresssed.
- bool headers_complete_;
+ bool headers_decompressed_;
// ID of the header block sent by the peer, once parsed.
QuicHeaderId headers_id_;
// Buffer into which we write bytes from the headers_id_
diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc
index d86a0b6..ede58bd 100644
--- a/net/quic/reliable_quic_stream_test.cc
+++ b/net/quic/reliable_quic_stream_test.cc
@@ -43,7 +43,7 @@ class TestStream : public ReliableQuicStream {
}
virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE {
- LOG(INFO) << "data_len: " << data_len;
+ DVLOG(1) << "ProcessData data_len: " << data_len;
data_ += string(data, data_len);
return should_process_data_ ? data_len : 0;
}
@@ -68,8 +68,10 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
}
void Initialize(bool stream_should_process_data) {
- connection_ = new MockConnection(kGuid, IPEndPoint(), kIsServer);
- session_.reset(new MockSession(connection_, kIsServer));
+ connection_ = new testing::StrictMock<MockConnection>(
+ kGuid, IPEndPoint(), kIsServer);
+ session_.reset(new testing::StrictMock<MockSession>(
+ connection_, kIsServer));
stream_.reset(new TestStream(kStreamId, session_.get(),
stream_should_process_data));
stream2_.reset(new TestStream(kStreamId + 2, session_.get(),
@@ -307,6 +309,26 @@ TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
stream2_->OnDecompressorAvailable();
EXPECT_EQ(decompressed_headers2, stream2_->data());
}
+TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
+ Initialize(!kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeaders(headers_);
+ QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers);
+ string decompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ // Send the headers to the stream and verify they were decompressed.
+ stream_->OnStreamFrame(frame1);
+ EXPECT_EQ(2u, session_->decompressor()->current_header_id());
+
+ // Verify that we are now able to handle the body data,
+ // even though the stream has not processed the headers.
+ EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
+ .Times(0);
+ QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
+ "body data");
+ stream_->OnStreamFrame(frame2);
+}
} // namespace
} // namespace test
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 99af86f..058157e 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -14,6 +14,7 @@
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_crypto_server_stream.h"
#include "net/quic/quic_crypto_stream.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
@@ -26,18 +27,6 @@ namespace test {
namespace {
-class TestSession : public QuicSession {
- public:
- TestSession(QuicConnection* connection, bool is_server)
- : QuicSession(connection, is_server) {
- }
-
- MOCK_METHOD1(CreateIncomingReliableStream,
- ReliableQuicStream*(QuicStreamId id));
- MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
- MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
-};
-
// CryptoFramerVisitor is a framer visitor that records handshake messages.
class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
public:
@@ -73,16 +62,24 @@ class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
// than the last packet processed.
void MovePackets(PacketSavingConnection* source_conn,
size_t *inout_packet_index,
- QuicCryptoStream* dest_stream) {
+ QuicCryptoStream* dest_stream,
+ PacketSavingConnection* dest_conn) {
SimpleQuicFramer framer;
CryptoFramer crypto_framer;
CryptoFramerVisitor crypto_visitor;
+ // In order to properly test the code we need to perform encryption and
+ // decryption so that the crypters latch when expected. The crypters are in
+ // |dest_conn|, but we don't want to try and use them there. Instead we swap
+ // them into |framer|, perform the decryption with them, and then swap them
+ // back.
+ QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
+
crypto_framer.set_visitor(&crypto_visitor);
size_t index = *inout_packet_index;
- for (; index < source_conn->packets_.size(); index++) {
- ASSERT_TRUE(framer.ProcessPacket(*source_conn->packets_[index]));
+ for (; index < source_conn->encrypted_packets_.size(); index++) {
+ ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index]));
for (vector<QuicStreamFrame>::const_iterator
i = framer.stream_frames().begin();
i != framer.stream_frames().end(); ++i) {
@@ -92,6 +89,8 @@ void MovePackets(PacketSavingConnection* source_conn,
}
*inout_packet_index = index;
+ QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
+
ASSERT_EQ(0u, crypto_framer.InputBytesRemaining());
for (vector<CryptoHandshakeMessage>::const_iterator
@@ -114,7 +113,7 @@ void CryptoTestUtils::CommunicateHandshakeMessages(
ASSERT_GT(a_conn->packets_.size(), a_i);
LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
<< " packets a->b";
- MovePackets(a_conn, &a_i, b);
+ MovePackets(a_conn, &a_i, b, b_conn);
ASSERT_GT(b_conn->packets_.size(), b_i);
LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
@@ -122,7 +121,7 @@ void CryptoTestUtils::CommunicateHandshakeMessages(
if (b_conn->packets_.size() - b_i == 2) {
LOG(INFO) << "here";
}
- MovePackets(b_conn, &b_i, a);
+ MovePackets(b_conn, &b_i, a, a_conn);
}
}
@@ -146,6 +145,7 @@ int CryptoTestUtils::HandshakeWithFakeServer(
&config, &crypto_config);
QuicCryptoServerStream server(config, crypto_config, &server_session);
+ server_session.SetCryptoStream(&server);
// The client's handshake must have been started already.
CHECK_NE(0u, client_conn->packets_.size());
@@ -177,6 +177,7 @@ int CryptoTestUtils::HandshakeWithFakeClient(
// crypto_config.SetProofVerifier(ProofVerifierForTesting());
QuicCryptoClientStream client("test.example.com", config, &client_session,
&crypto_config);
+ client_session.SetCryptoStream(&client);
CHECK(client.CryptoConnect());
CHECK_EQ(1u, client_conn->packets_.size());
@@ -199,7 +200,8 @@ void CryptoTestUtils::SetupCryptoServerConfigForTest(
config->ToHandshakeMessage(&extra_tags);
scoped_ptr<CryptoHandshakeMessage> scfg(
- crypto_config->AddDefaultConfig(rand, clock, extra_tags));
+ crypto_config->AddDefaultConfig(
+ rand, clock, extra_tags, QuicCryptoServerConfig::kDefaultExpiry));
if (!config->SetFromHandshakeMessage(*scfg)) {
CHECK(false) << "Crypto config could not be parsed by QuicConfig.";
}
@@ -207,28 +209,28 @@ void CryptoTestUtils::SetupCryptoServerConfigForTest(
// static
string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
- CryptoTag tag) {
- CryptoTagValueMap::const_iterator it = message.tag_value_map().find(tag);
+ QuicTag tag) {
+ QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag);
if (it == message.tag_value_map().end()) {
return string();
}
return it->second;
}
-class MockCommonCertSet : public CommonCertSet {
+class MockCommonCertSets : public CommonCertSets {
public:
- MockCommonCertSet(StringPiece cert, uint64 hash, uint32 index)
+ MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index)
: cert_(cert.as_string()),
hash_(hash),
index_(index) {
}
- virtual StringPiece GetCommonHashes() OVERRIDE {
+ virtual StringPiece GetCommonHashes() const OVERRIDE {
CHECK(false) << "not implemented";
return StringPiece();
}
- virtual StringPiece GetCert(uint64 hash, uint32 index) OVERRIDE {
+ virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE {
if (hash == hash_ && index == index_) {
return cert_;
}
@@ -238,7 +240,7 @@ class MockCommonCertSet : public CommonCertSet {
virtual bool MatchCert(StringPiece cert,
StringPiece common_set_hashes,
uint64* out_hash,
- uint32* out_index) OVERRIDE {
+ uint32* out_index) const OVERRIDE {
if (cert != cert_) {
return false;
}
@@ -271,10 +273,10 @@ class MockCommonCertSet : public CommonCertSet {
const uint32 index_;
};
-CommonCertSet* CryptoTestUtils::MockCommonCertSet(StringPiece cert,
- uint64 hash,
- uint32 index) {
- return new class MockCommonCertSet(cert, hash, index);
+CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert,
+ uint64 hash,
+ uint32 index) {
+ return new class MockCommonCertSets(cert, hash, index);
}
void CryptoTestUtils::CompareClientAndServerKeys(
@@ -282,26 +284,45 @@ void CryptoTestUtils::CompareClientAndServerKeys(
QuicCryptoServerStream* server) {
const QuicEncrypter* client_encrypter(
client->session()->connection()->encrypter(ENCRYPTION_INITIAL));
- // Normally we would expect the client's INITIAL decrypter to have latched
- // from the receipt of the server hello. However, when using a
- // PacketSavingConnection (at the tests do) we don't actually encrypt with
- // the correct encrypter.
- // TODO(agl): make the tests more realistic.
const QuicDecrypter* client_decrypter(
+ client->session()->connection()->decrypter());
+ const QuicEncrypter* client_forward_secure_encrypter(
+ client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
+ const QuicDecrypter* client_forward_secure_decrypter(
client->session()->connection()->alternative_decrypter());
const QuicEncrypter* server_encrypter(
server->session()->connection()->encrypter(ENCRYPTION_INITIAL));
const QuicDecrypter* server_decrypter(
server->session()->connection()->decrypter());
+ const QuicEncrypter* server_forward_secure_encrypter(
+ server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE));
+ const QuicDecrypter* server_forward_secure_decrypter(
+ server->session()->connection()->alternative_decrypter());
StringPiece client_encrypter_key = client_encrypter->GetKey();
StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix();
StringPiece client_decrypter_key = client_decrypter->GetKey();
StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix();
+ StringPiece client_forward_secure_encrypter_key =
+ client_forward_secure_encrypter->GetKey();
+ StringPiece client_forward_secure_encrypter_iv =
+ client_forward_secure_encrypter->GetNoncePrefix();
+ StringPiece client_forward_secure_decrypter_key =
+ client_forward_secure_decrypter->GetKey();
+ StringPiece client_forward_secure_decrypter_iv =
+ client_forward_secure_decrypter->GetNoncePrefix();
StringPiece server_encrypter_key = server_encrypter->GetKey();
StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix();
StringPiece server_decrypter_key = server_decrypter->GetKey();
StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix();
+ StringPiece server_forward_secure_encrypter_key =
+ server_forward_secure_encrypter->GetKey();
+ StringPiece server_forward_secure_encrypter_iv =
+ server_forward_secure_encrypter->GetNoncePrefix();
+ StringPiece server_forward_secure_decrypter_key =
+ server_forward_secure_decrypter->GetKey();
+ StringPiece server_forward_secure_decrypter_iv =
+ server_forward_secure_decrypter->GetNoncePrefix();
CompareCharArraysWithHexError("client write key",
client_encrypter_key.data(),
@@ -323,6 +344,26 @@ void CryptoTestUtils::CompareClientAndServerKeys(
server_encrypter_iv.length(),
client_decrypter_iv.data(),
client_decrypter_iv.length());
+ CompareCharArraysWithHexError("client forward secure write key",
+ client_forward_secure_encrypter_key.data(),
+ client_forward_secure_encrypter_key.length(),
+ server_forward_secure_decrypter_key.data(),
+ server_forward_secure_decrypter_key.length());
+ CompareCharArraysWithHexError("client forward secure write IV",
+ client_forward_secure_encrypter_iv.data(),
+ client_forward_secure_encrypter_iv.length(),
+ server_forward_secure_decrypter_iv.data(),
+ server_forward_secure_decrypter_iv.length());
+ CompareCharArraysWithHexError("server forward secure write key",
+ server_forward_secure_encrypter_key.data(),
+ server_forward_secure_encrypter_key.length(),
+ client_forward_secure_decrypter_key.data(),
+ client_forward_secure_decrypter_key.length());
+ CompareCharArraysWithHexError("server forward secure write IV",
+ server_forward_secure_encrypter_iv.data(),
+ server_forward_secure_encrypter_iv.length(),
+ client_forward_secure_decrypter_iv.data(),
+ client_forward_secure_decrypter_iv.length());
}
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 62d813a..62748a3 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -15,7 +15,7 @@
namespace net {
-class CommonCertSet;
+class CommonCertSets;
class ProofSource;
class ProofVerifier;
class QuicClock;
@@ -57,7 +57,7 @@ class CryptoTestUtils {
// Returns the value for the tag |tag| in the tag value map of |message|.
static std::string GetValueForTag(const CryptoHandshakeMessage& message,
- CryptoTag tag);
+ QuicTag tag);
// Returns a |ProofSource| that serves up test certificates.
static ProofSource* ProofSourceForTesting();
@@ -65,11 +65,11 @@ class CryptoTestUtils {
// Returns a |ProofVerifier| that uses the QUIC testing root CA.
static ProofVerifier* ProofVerifierForTesting();
- // MockCommonCertSet returns a CommonCertSet that contains a single set with
+ // MockCommonCertSets returns a CommonCertSets that contains a single set with
// hash |hash|, consisting of the certificate |cert| at index |index|.
- static CommonCertSet* MockCommonCertSet(base::StringPiece cert,
- uint64 hash,
- uint32 index);
+ static CommonCertSets* MockCommonCertSets(base::StringPiece cert,
+ uint64 hash,
+ uint32 index);
private:
static void CompareClientAndServerKeys(QuicCryptoClientStream* client,
diff --git a/net/quic/test_tools/mock_clock.cc b/net/quic/test_tools/mock_clock.cc
index 4e5864d..47f2380 100644
--- a/net/quic/test_tools/mock_clock.cc
+++ b/net/quic/test_tools/mock_clock.cc
@@ -24,8 +24,9 @@ QuicTime MockClock::ApproximateNow() const {
return now_;
}
-QuicTime::Delta MockClock::NowAsDeltaSinceUnixEpoch() const {
- return now_.Subtract(QuicTime::Zero());
+QuicWallTime MockClock::WallNow() const {
+ return QuicWallTime::FromUNIXSeconds(
+ now_.Subtract(QuicTime::Zero()).ToSeconds());
}
base::TimeTicks MockClock::NowInTicks() const {
diff --git a/net/quic/test_tools/mock_clock.h b/net/quic/test_tools/mock_clock.h
index 7497aa2..33a93b4 100644
--- a/net/quic/test_tools/mock_clock.h
+++ b/net/quic/test_tools/mock_clock.h
@@ -25,7 +25,7 @@ class MockClock : public QuicClock {
virtual QuicTime ApproximateNow() const OVERRIDE;
- virtual QuicTime::Delta NowAsDeltaSinceUnixEpoch() const OVERRIDE;
+ virtual QuicWallTime WallNow() const OVERRIDE;
base::TimeTicks NowInTicks() const;
diff --git a/net/quic/test_tools/quic_connection_peer.cc b/net/quic/test_tools/quic_connection_peer.cc
index 102b2d7..6816e54 100644
--- a/net/quic/test_tools/quic_connection_peer.cc
+++ b/net/quic/test_tools/quic_connection_peer.cc
@@ -115,5 +115,11 @@ void QuicConnectionPeer::SetIsServer(QuicConnection* connection,
QuicFramerPeer::SetIsServer(&connection->framer_, is_server);
}
+// static
+void QuicConnectionPeer::SwapCrypters(QuicConnection* connection,
+ QuicFramer* framer) {
+ framer->SwapCryptersForTest(&connection->framer_);
+}
+
} // namespace test
} // namespace net
diff --git a/net/quic/test_tools/quic_connection_peer.h b/net/quic/test_tools/quic_connection_peer.h
index 97f7afa..89c6482 100644
--- a/net/quic/test_tools/quic_connection_peer.h
+++ b/net/quic/test_tools/quic_connection_peer.h
@@ -14,6 +14,7 @@ namespace net {
struct QuicAckFrame;
class QuicConnection;
class QuicConnectionVisitorInterface;
+class QuicFramer;
class QuicPacketCreator;
class ReceiveAlgorithmInterface;
class SendAlgorithmInterface;
@@ -67,6 +68,8 @@ class QuicConnectionPeer {
static void SetIsServer(QuicConnection* connection, bool is_server);
+ static void SwapCrypters(QuicConnection* connection, QuicFramer* framer);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
};
diff --git a/net/quic/test_tools/quic_framer_peer.cc b/net/quic/test_tools/quic_framer_peer.cc
index 15a8067..9a3b968 100644
--- a/net/quic/test_tools/quic_framer_peer.cc
+++ b/net/quic/test_tools/quic_framer_peer.cc
@@ -28,7 +28,7 @@ void QuicFramerPeer::SetIsServer(QuicFramer* framer, bool is_server) {
framer->is_server_ = is_server;
}
-void QuicFramerPeer::SetVersion(QuicFramer* framer, QuicVersionTag version) {
+void QuicFramerPeer::SetVersion(QuicFramer* framer, QuicTag version) {
framer->quic_version_ = version;
}
diff --git a/net/quic/test_tools/quic_framer_peer.h b/net/quic/test_tools/quic_framer_peer.h
index 3880412..0c59d2d 100644
--- a/net/quic/test_tools/quic_framer_peer.h
+++ b/net/quic/test_tools/quic_framer_peer.h
@@ -22,7 +22,7 @@ class QuicFramerPeer {
QuicFramer* framer,
QuicPacketSequenceNumber packet_sequence_number);
static void SetIsServer(QuicFramer* framer, bool is_server);
- static void SetVersion(QuicFramer* framer, QuicVersionTag version);
+ static void SetVersion(QuicFramer* framer, QuicTag version);
private:
DISALLOW_COPY_AND_ASSIGN(QuicFramerPeer);
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index cd83756..c987277 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -5,7 +5,6 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "base/stl_util.h"
-#include "base/strings/string_piece.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_utils.h"
@@ -56,7 +55,7 @@ MockFramerVisitor::MockFramerVisitor() {
MockFramerVisitor::~MockFramerVisitor() {
}
-bool NoOpFramerVisitor::OnProtocolVersionMismatch(QuicVersionTag version) {
+bool NoOpFramerVisitor::OnProtocolVersionMismatch(QuicTag version) {
return false;
}
@@ -189,7 +188,8 @@ void MockHelper::AdvanceTime(QuicTime::Delta delta) {
MockConnection::MockConnection(QuicGuid guid,
IPEndPoint address,
bool is_server)
- : QuicConnection(guid, address, new MockHelper(), is_server),
+ : QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
+ is_server),
has_mock_helper_(true) {
}
@@ -218,6 +218,7 @@ PacketSavingConnection::PacketSavingConnection(QuicGuid guid,
PacketSavingConnection::~PacketSavingConnection() {
STLDeleteElements(&packets_);
+ STLDeleteElements(&encrypted_packets_);
}
bool PacketSavingConnection::SendOrQueuePacket(
@@ -227,6 +228,9 @@ bool PacketSavingConnection::SendOrQueuePacket(
QuicPacketEntropyHash entropy_hash,
HasRetransmittableData retransmittable) {
packets_.push_back(packet);
+ QuicEncryptedPacket* encrypted =
+ framer_.EncryptPacket(level, sequence_number, *packet);
+ encrypted_packets_.push_back(encrypted);
return true;
}
@@ -239,6 +243,22 @@ MockSession::MockSession(QuicConnection* connection, bool is_server)
MockSession::~MockSession() {
}
+TestSession::TestSession(QuicConnection* connection, bool is_server)
+ : QuicSession(connection, is_server),
+ crypto_stream_(NULL) {
+}
+
+TestSession::~TestSession() {
+}
+
+void TestSession::SetCryptoStream(QuicCryptoStream* stream) {
+ crypto_stream_ = stream;
+}
+
+QuicCryptoStream* TestSession::GetCryptoStream() {
+ return crypto_stream_;
+}
+
MockSendAlgorithm::MockSendAlgorithm() {
}
@@ -355,7 +375,7 @@ static QuicPacket* ConstructPacketFromHandshakeMessage(
return quic_framer.ConstructFrameDataPacket(header, frames).packet;
}
-QuicPacket* ConstructHandshakePacket(QuicGuid guid, CryptoTag tag) {
+QuicPacket* ConstructHandshakePacket(QuicGuid guid, QuicTag tag) {
CryptoHandshakeMessage message;
message.set_tag(tag);
return ConstructPacketFromHandshakeMessage(guid, message, false);
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index 13e7a8d..5ea2a78 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -7,8 +7,10 @@
#ifndef NET_QUIC_TEST_TOOLS_QUIC_TEST_UTILS_H_
#define NET_QUIC_TEST_TOOLS_QUIC_TEST_UTILS_H_
+#include <string>
#include <vector>
+#include "base/strings/string_piece.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_framer.h"
@@ -46,7 +48,7 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
MOCK_METHOD1(OnError, void(QuicFramer* framer));
// The constructor sets this up to return false by default.
- MOCK_METHOD1(OnProtocolVersionMismatch, bool(QuicVersionTag version));
+ MOCK_METHOD1(OnProtocolVersionMismatch, bool(QuicTag version));
MOCK_METHOD0(OnPacket, void());
MOCK_METHOD1(OnPublicResetPacket, void(const QuicPublicResetPacket& header));
MOCK_METHOD1(OnVersionNegotiationPacket,
@@ -81,7 +83,7 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) OVERRIDE {}
virtual void OnRevivedPacket() OVERRIDE {}
- virtual bool OnProtocolVersionMismatch(QuicVersionTag version) OVERRIDE;
+ virtual bool OnProtocolVersionMismatch(QuicTag version) OVERRIDE;
virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnFecProtectedPayload(base::StringPiece payload) OVERRIDE {}
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
@@ -238,7 +240,7 @@ class MockConnection : public QuicConnection {
QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
- virtual bool OnProtocolVersionMismatch(QuicVersionTag version) OVERRIDE {
+ virtual bool OnProtocolVersionMismatch(QuicTag version) OVERRIDE {
return false;
}
@@ -261,6 +263,7 @@ class PacketSavingConnection : public MockConnection {
HasRetransmittableData has_retransmittable_data) OVERRIDE;
std::vector<QuicPacket*> packets_;
+ std::vector<QuicEncryptedPacket*> encrypted_packets_;
private:
DISALLOW_COPY_AND_ASSIGN(PacketSavingConnection);
@@ -290,6 +293,24 @@ class MockSession : public QuicSession {
DISALLOW_COPY_AND_ASSIGN(MockSession);
};
+class TestSession : public QuicSession {
+ public:
+ TestSession(QuicConnection* connection, bool is_server);
+ virtual ~TestSession();
+
+ MOCK_METHOD1(CreateIncomingReliableStream,
+ ReliableQuicStream*(QuicStreamId id));
+ MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
+
+ void SetCryptoStream(QuicCryptoStream* stream);
+
+ virtual QuicCryptoStream* GetCryptoStream();
+
+ private:
+ QuicCryptoStream* crypto_stream_;
+ DISALLOW_COPY_AND_ASSIGN(TestSession);
+};
+
class MockSendAlgorithm : public SendAlgorithmInterface {
public:
MockSendAlgorithm();
diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc
index c39a724..7e77b0f 100644
--- a/net/quic/test_tools/simple_quic_framer.cc
+++ b/net/quic/test_tools/simple_quic_framer.cc
@@ -25,7 +25,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
error_ = framer->error();
}
- virtual bool OnProtocolVersionMismatch(QuicVersionTag version) OVERRIDE {
+ virtual bool OnProtocolVersionMismatch(QuicTag version) OVERRIDE {
return false;
}
@@ -128,9 +128,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
};
SimpleQuicFramer::SimpleQuicFramer()
- : framer_(kQuicVersion1,
- QuicTime::Zero(),
- true) {
+ : framer_(kQuicVersion1, QuicTime::Zero(), true) {
}
SimpleQuicFramer::~SimpleQuicFramer() {
@@ -156,6 +154,10 @@ const QuicFecData& SimpleQuicFramer::fec_data() const {
return visitor_->fec_data();
}
+QuicFramer* SimpleQuicFramer::framer() {
+ return &framer_;
+}
+
size_t SimpleQuicFramer::num_frames() const {
return ack_frames().size() +
stream_frames().size() +
diff --git a/net/quic/test_tools/simple_quic_framer.h b/net/quic/test_tools/simple_quic_framer.h
index bda2b89..4416019 100644
--- a/net/quic/test_tools/simple_quic_framer.h
+++ b/net/quic/test_tools/simple_quic_framer.h
@@ -43,6 +43,7 @@ class SimpleQuicFramer {
const std::vector<QuicRstStreamFrame>& rst_stream_frames() const;
const std::vector<QuicStreamFrame>& stream_frames() const;
const QuicFecData& fec_data() const;
+ QuicFramer* framer();
private:
QuicFramer framer_;
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 12e2da9..c03f9d8 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -109,6 +109,7 @@ class EndToEndTest : public ::testing::Test {
net::IPAddressNumber ip;
CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
server_address_ = IPEndPoint(ip, 0);
+ config_.SetDefaults();
AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody);
AddToCache("GET", "https://www.google.com/foo",
@@ -123,7 +124,8 @@ class EndToEndTest : public ::testing::Test {
virtual QuicTestClient* CreateQuicClient() {
QuicTestClient* client = new QuicTestClient(server_address_,
- server_hostname_);
+ server_hostname_,
+ config_);
client->Connect();
return client;
}
@@ -152,8 +154,10 @@ class EndToEndTest : public ::testing::Test {
void StopServer() {
if (!server_started_)
return;
- server_thread_->quit()->Signal();
- server_thread_->Join();
+ if (server_thread_.get()) {
+ server_thread_->quit()->Signal();
+ server_thread_->Join();
+ }
}
void AddToCache(const StringPiece& method,
@@ -192,6 +196,7 @@ class EndToEndTest : public ::testing::Test {
scoped_ptr<ServerThread> server_thread_;
scoped_ptr<QuicTestClient> client_;
bool server_started_;
+ QuicConfig config_;
};
TEST_F(EndToEndTest, SimpleRequestResponse) {
@@ -499,11 +504,11 @@ TEST_F(EndToEndTest, MultipleTermination) {
}
/*TEST_F(EndToEndTest, Timeout) {
- FLAGS_negotiated_timeout_us = 500;
+ config_.set_idle_connection_state_lifetime(
+ QuicTime::Delta::FromMicroseconds(500));
// Note: we do NOT ASSERT_TRUE: we may time out during initial handshake:
// that's enough to validate timeout in this case.
Initialize();
-
while (client_->client()->connected()) {
client_->client()->WaitForEvents();
}
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc
index 5054eb9..0206c3f 100644
--- a/net/tools/quic/quic_client.cc
+++ b/net/tools/quic/quic_client.cc
@@ -39,9 +39,20 @@ QuicClient::QuicClient(IPEndPoint server_address,
initialized_(false),
packets_dropped_(0),
overflow_supported_(false) {
- epoll_server_.set_timeout_in_us(50 * 1000);
config_.SetDefaults();
- crypto_config_.SetDefaults();
+}
+
+QuicClient::QuicClient(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicConfig& config)
+ : server_address_(server_address),
+ server_hostname_(server_hostname),
+ config_(config),
+ local_port_(0),
+ fd_(-1),
+ initialized_(false),
+ packets_dropped_(0),
+ overflow_supported_(false) {
}
QuicClient::~QuicClient() {
@@ -52,7 +63,10 @@ QuicClient::~QuicClient() {
}
bool QuicClient::Initialize() {
+ epoll_server_.set_timeout_in_us(50 * 1000);
+ crypto_config_.SetDefaults();
int address_family = server_address_.GetSockAddrFamily();
+
fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
if (fd_ < 0) {
LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h
index 2d19e6c..9cfaa3e 100644
--- a/net/tools/quic/quic_client.h
+++ b/net/tools/quic/quic_client.h
@@ -27,6 +27,10 @@ namespace tools {
class QuicClient : public EpollCallbackInterface {
public:
QuicClient(IPEndPoint server_address, const std::string& server_hostname);
+ QuicClient(IPEndPoint server_address,
+ const std::string& server_hostname,
+ const QuicConfig& config);
+
virtual ~QuicClient();
// Initializes the client to create a connection. Should be called exactly
@@ -116,6 +120,11 @@ class QuicClient : public EpollCallbackInterface {
// Hostname of the server. This may be a DNS name or an IP address literal.
const std::string server_hostname_;
+ // config_ and crypto_config_ contain configuration and cached state about
+ // servers.
+ QuicConfig config_;
+ QuicCryptoClientConfig crypto_config_;
+
// Address of the client if the client is connected to the server.
IPEndPoint client_address_;
@@ -143,11 +152,6 @@ class QuicClient : public EpollCallbackInterface {
// because the socket would otherwise overflow.
bool overflow_supported_;
- // config_ and crypto_config_ contain configuration and cached state about
- // servers.
- QuicConfig config_;
- QuicCryptoClientConfig crypto_config_;
-
DISALLOW_COPY_AND_ASSIGN(QuicClient);
};
diff --git a/net/tools/quic/quic_epoll_clock.cc b/net/tools/quic/quic_epoll_clock.cc
index eb7eb65..e310256 100644
--- a/net/tools/quic/quic_epoll_clock.cc
+++ b/net/tools/quic/quic_epoll_clock.cc
@@ -25,8 +25,9 @@ QuicTime QuicEpollClock::Now() const {
QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec()));
}
-QuicTime::Delta QuicEpollClock::NowAsDeltaSinceUnixEpoch() const {
- return QuicTime::Delta::FromMicroseconds(epoll_server_->NowInUsec());
+QuicWallTime QuicEpollClock::WallNow() const {
+ return QuicWallTime::FromUNIXSeconds(
+ epoll_server_->ApproximateNowInUsec() / 1000000);
}
} // namespace tools
diff --git a/net/tools/quic/quic_epoll_clock.h b/net/tools/quic/quic_epoll_clock.h
index 291ab0a..95e6dc0 100644
--- a/net/tools/quic/quic_epoll_clock.h
+++ b/net/tools/quic/quic_epoll_clock.h
@@ -29,10 +29,9 @@ class QuicEpollClock : public QuicClock {
// Note: this use significant resources please use only if needed.
virtual QuicTime Now() const OVERRIDE;
- // Returns the current time as an offset from the Unix epoch (1970-01-01
- // 00:00:00 GMT). This function may return a smaller Delta in subsequent
- // calls if the system clock is changed.
- virtual QuicTime::Delta NowAsDeltaSinceUnixEpoch() const OVERRIDE;
+ // WallNow returns the current wall-time - a time is consistent across
+ // different clocks.
+ virtual QuicWallTime WallNow() const OVERRIDE;
protected:
EpollServer* epoll_server_;
diff --git a/net/tools/quic/quic_epoll_clock_test.cc b/net/tools/quic/quic_epoll_clock_test.cc
index 5d7c6b9..14276ca 100644
--- a/net/tools/quic/quic_epoll_clock_test.cc
+++ b/net/tools/quic/quic_epoll_clock_test.cc
@@ -18,14 +18,15 @@ TEST(QuicEpollClockTest, ApproximateNowInUsec) {
epoll_server.set_now_in_usec(1000000);
EXPECT_EQ(1000000,
clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds());
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000000),
- clock.NowAsDeltaSinceUnixEpoch());
+ EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds());
epoll_server.AdvanceBy(5);
EXPECT_EQ(1000005,
clock.ApproximateNow().Subtract(QuicTime::Zero()).ToMicroseconds());
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000005),
- clock.NowAsDeltaSinceUnixEpoch());
+ EXPECT_EQ(1u, clock.WallNow().ToUNIXSeconds());
+
+ epoll_server.AdvanceBy(10 * 1000000);
+ EXPECT_EQ(11u, clock.WallNow().ToUNIXSeconds());
}
TEST(QuicEpollClockTest, NowInUsec) {
@@ -35,14 +36,10 @@ TEST(QuicEpollClockTest, NowInUsec) {
epoll_server.set_now_in_usec(1000000);
EXPECT_EQ(1000000,
clock.Now().Subtract(QuicTime::Zero()).ToMicroseconds());
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000000),
- clock.NowAsDeltaSinceUnixEpoch());
epoll_server.AdvanceBy(5);
EXPECT_EQ(1000005,
clock.Now().Subtract(QuicTime::Zero()).ToMicroseconds());
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(1000005),
- clock.NowAsDeltaSinceUnixEpoch());
}
} // namespace test
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc
index 4e1743a..7319c67 100644
--- a/net/tools/quic/quic_server.cc
+++ b/net/tools/quic/quic_server.cc
@@ -51,8 +51,9 @@ QuicServer::QuicServer()
QuicEpollClock clock(&epoll_server_);
scoped_ptr<CryptoHandshakeMessage> scfg(
- crypto_config_.AddDefaultConfig(QuicRandom::GetInstance(), &clock,
- extra_tags));
+ crypto_config_.AddDefaultConfig(
+ QuicRandom::GetInstance(), &clock, extra_tags,
+ QuicCryptoServerConfig::kDefaultExpiry));
// If we were using the same config in many servers then we would have to
// parse a QuicConfig from config_tags here.
if (!config_.SetFromHandshakeMessage(*scfg)) {
diff --git a/net/tools/quic/quic_spdy_client_stream.cc b/net/tools/quic/quic_spdy_client_stream.cc
index 11d42a0..21c0d3c 100644
--- a/net/tools/quic/quic_spdy_client_stream.cc
+++ b/net/tools/quic/quic_spdy_client_stream.cc
@@ -67,7 +67,7 @@ ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers,
bool has_body = !body.empty();
- WriteData(headers_string, fin && !has_body);
+ WriteData(headers_string, fin && !has_body); // last_data
if (has_body) {
WriteData(body, fin);
diff --git a/net/tools/quic/quic_spdy_server_stream.cc b/net/tools/quic/quic_spdy_server_stream.cc
index 94afaa0..ac537a8 100644
--- a/net/tools/quic/quic_spdy_server_stream.cc
+++ b/net/tools/quic/quic_spdy_server_stream.cc
@@ -50,6 +50,10 @@ void QuicSpdyServerStream::TerminateFromPeer(bool half_close) {
if (!half_close) {
return;
}
+ if (write_side_closed() || fin_buffered()) {
+ return;
+ }
+
if (!request_headers_received_) {
SendErrorResponse(); // We're not done writing headers.
} else if ((headers().content_length_status() ==
diff --git a/net/tools/quic/quic_spdy_server_stream_test.cc b/net/tools/quic/quic_spdy_server_stream_test.cc
new file mode 100644
index 0000000..1f7a0fe
--- /dev/null
+++ b/net/tools/quic/quic_spdy_server_stream_test.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/quic_spdy_server_stream.h"
+
+#include "base/strings/string_piece.h"
+#include "net/quic/quic_connection.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/tools/quic/test_tools/quic_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using net::tools::test::MockConnection;
+using net::test::MockSession;
+
+namespace net {
+namespace tools {
+namespace test {
+namespace {
+
+class QuicSpdyServerStreamTest : public ::testing::Test {
+ public:
+ QuicSpdyServerStreamTest()
+ : connection_(new MockConnection(1, IPEndPoint(), false)),
+ session_(connection_, true),
+ stream_(1, &session_) {
+ }
+
+ MockConnection* connection_;
+ MockSession session_;
+ QuicSpdyServerStream stream_;
+};
+
+TEST_F(QuicSpdyServerStreamTest, InvalidHeadersWithFin) {
+ char arr[] = {
+ 0x00, 0x00, 0x00, 0x05, // ....
+ 0x00, 0x00, 0x00, 0x05, // ....
+ 0x3a, 0x68, 0x6f, 0x73, // :hos
+ 0x74, 0x00, 0x00, 0x00, // t...
+ 0x00, 0x00, 0x00, 0x00, // ....
+ 0x07, 0x3a, 0x6d, 0x65, // .:me
+ 0x74, 0x68, 0x6f, 0x64, // thod
+ 0x00, 0x00, 0x00, 0x03, // ....
+ 0x47, 0x45, 0x54, 0x00, // GET.
+ 0x00, 0x00, 0x05, 0x3a, // ...:
+ 0x70, 0x61, 0x74, 0x68, // path
+ 0x00, 0x00, 0x00, 0x04, // ....
+ 0x2f, 0x66, 0x6f, 0x6f, // /foo
+ 0x00, 0x00, 0x00, 0x07, // ....
+ 0x3a, 0x73, 0x63, 0x68, // :sch
+ 0x65, 0x6d, 0x65, 0x00, // eme.
+ 0x00, 0x00, 0x00, 0x00, // ....
+ 0x00, 0x00, 0x08, 0x3a, // ...:
+ 0x76, 0x65, 0x72, 0x73, // vers
+ 0x96, 0x6f, 0x6e, 0x00, // <i(69)>on.
+ 0x00, 0x00, 0x08, 0x48, // ...H
+ 0x54, 0x54, 0x50, 0x2f, // TTP/
+ 0x31, 0x2e, 0x31, // 1.1
+ };
+ QuicStreamFrame frame(1, true, 0, StringPiece(arr, arraysize(arr)));
+ // Verify that we don't crash when we get a invalid headers in stream frame.
+ stream_.OnStreamFrame(frame);
+}
+
+} // namespace
+} // namespace test
+} // namespace tools
+} // namespace net
diff --git a/net/tools/quic/quic_time_wait_list_manager.cc b/net/tools/quic/quic_time_wait_list_manager.cc
index dd792ea..0b538bd 100644
--- a/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/net/tools/quic/quic_time_wait_list_manager.cc
@@ -154,7 +154,7 @@ void QuicTimeWaitListManager::OnError(QuicFramer* framer) {
}
bool QuicTimeWaitListManager::OnProtocolVersionMismatch(
- QuicVersionTag received_version) {
+ QuicTag received_version) {
// Drop such packets whose version don't match.
return false;
}
diff --git a/net/tools/quic/quic_time_wait_list_manager.h b/net/tools/quic/quic_time_wait_list_manager.h
index 4cee3ea..cc4d671d 100644
--- a/net/tools/quic/quic_time_wait_list_manager.h
+++ b/net/tools/quic/quic_time_wait_list_manager.h
@@ -71,8 +71,7 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface,
// FramerVisitorInterface
virtual void OnError(QuicFramer* framer) OVERRIDE;
- virtual bool OnProtocolVersionMismatch(
- QuicVersionTag received_version) OVERRIDE;
+ virtual bool OnProtocolVersionMismatch(QuicTag received_version) OVERRIDE;
virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnPacket() OVERRIDE {}
virtual void OnPublicResetPacket(
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index 843af2f..c6c921e8 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -45,6 +45,19 @@ QuicTestClient::QuicTestClient(IPEndPoint address, const string& hostname)
never_connected_(true) {
}
+QuicTestClient::QuicTestClient(IPEndPoint address,
+ const string& hostname,
+ const QuicConfig& config)
+ : server_address_(address),
+ client_(address, hostname, config),
+ stream_(NULL),
+ stream_error_(QUIC_STREAM_NO_ERROR),
+ connection_error_(QUIC_NO_ERROR),
+ bytes_read_(0),
+ bytes_written_(0),
+ never_connected_(true) {
+}
+
QuicTestClient::~QuicTestClient() {
if (stream_) {
stream_->set_visitor(NULL);
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h
index 343c99c..e7cb976 100644
--- a/net/tools/quic/test_tools/quic_test_client.h
+++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -24,6 +24,10 @@ class HTTPMessage;
class QuicTestClient : public ReliableQuicStream::Visitor {
public:
QuicTestClient(IPEndPoint server_address, const string& server_hostname);
+ QuicTestClient(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicConfig& config);
+
virtual ~QuicTestClient();
// Clears any outstanding state and sends a simple GET of 'uri' to the
diff --git a/net/tools/quic/test_tools/quic_test_utils.cc b/net/tools/quic/test_tools/quic_test_utils.cc
index 9aed3af..a5c22ea6 100644
--- a/net/tools/quic/test_tools/quic_test_utils.cc
+++ b/net/tools/quic/test_tools/quic_test_utils.cc
@@ -27,7 +27,8 @@ MockConnection::MockConnection(QuicGuid guid,
MockConnection::MockConnection(QuicGuid guid,
IPEndPoint address,
bool is_server)
- : QuicConnection(guid, address, new MockHelper(), is_server),
+ : QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
+ is_server),
has_mock_helper_(true) {
}
@@ -53,6 +54,21 @@ bool TestDecompressorVisitor::OnDecompressedData(StringPiece data) {
return true;
}
+TestSession::TestSession(QuicConnection* connection, bool is_server)
+ : QuicSession(connection, is_server),
+ crypto_stream_(NULL) {
+}
+
+TestSession::~TestSession() {}
+
+void TestSession::SetCryptoStream(QuicCryptoStream* stream) {
+ crypto_stream_ = stream;
+}
+
+QuicCryptoStream* TestSession::GetCryptoStream() {
+ return crypto_stream_;
+}
+
} // namespace test
} // namespace tools
} // namespace net
diff --git a/net/tools/quic/test_tools/quic_test_utils.h b/net/tools/quic/test_tools/quic_test_utils.h
index e4069c5..fd69a1d 100644
--- a/net/tools/quic/test_tools/quic_test_utils.h
+++ b/net/tools/quic/test_tools/quic_test_utils.h
@@ -9,6 +9,7 @@
#include "base/strings/string_piece.h"
#include "net/quic/quic_connection.h"
+#include "net/quic/quic_session.h"
#include "net/quic/quic_spdy_decompressor.h"
#include "net/spdy/spdy_framer.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -62,9 +63,7 @@ class MockConnection : public QuicConnection {
return QuicConnection::ProcessUdpPacket(self_address, peer_address, packet);
}
- virtual bool OnProtocolVersionMismatch(QuicVersionTag version) {
- return false;
- }
+ virtual bool OnProtocolVersionMismatch(QuicTag version) { return false; }
private:
const bool has_mock_helper_;
@@ -83,6 +82,24 @@ class TestDecompressorVisitor : public QuicSpdyDecompressor::Visitor {
std::string data_;
};
+class TestSession : public QuicSession {
+ public:
+ TestSession(QuicConnection* connection, bool is_server);
+ virtual ~TestSession();
+
+ MOCK_METHOD1(CreateIncomingReliableStream,
+ ReliableQuicStream*(QuicStreamId id));
+ MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
+
+ void SetCryptoStream(QuicCryptoStream* stream);
+
+ virtual QuicCryptoStream* GetCryptoStream();
+
+ private:
+ QuicCryptoStream* crypto_stream_;
+ DISALLOW_COPY_AND_ASSIGN(TestSession);
+};
+
} // namespace test
} // namespace tools
} // namespace net