summaryrefslogtreecommitdiffstats
path: root/net/quic
diff options
context:
space:
mode:
Diffstat (limited to 'net/quic')
-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
97 files changed, 1438 insertions, 1006 deletions
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_;