Add support for retry integrity tag
This CL adds support for the retry integrity tag which was added in draft-25. It increases resilience to network errors and makes retry injection by attackers harder. This changes the wire-format of T050 and T099/draft-25 which are both disabled.
gfe-relnote: support retry integrity tag, client-only, not flag-protected
PiperOrigin-RevId: 292044658
Change-Id: Ib62a4d58cb761dce284c36b450816ad9151e4062
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 7c20394..7809cc5 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_error_code_wrappers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -39,6 +40,7 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_quic_framer.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h"
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
@@ -9795,6 +9797,75 @@
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
}
+TEST_P(QuicConnectionTest, ClientParsesRetry) {
+ if (!version().HasRetryIntegrityTag()) {
+ return;
+ }
+ if (version() != ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_99)) {
+ // TODO(dschinazi) generate retry packets for all versions once we have
+ // server-side support for generating these programmatically.
+ return;
+ }
+
+ // These values come from draft-ietf-quic-tls Appendix A.4.
+ char retry_packet[] = {0xff, 0xff, 0x00, 0x00, 0x19, 0x00, 0x08, 0xf0, 0x67,
+ 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x1e, 0x5e, 0xc5, 0xb0, 0x14, 0xcb, 0xb1,
+ 0xf0, 0xfd, 0x93, 0xdf, 0x40, 0x48, 0xc4, 0x46, 0xa6};
+ char original_connection_id_bytes[] = {0x83, 0x94, 0xc8, 0xf0,
+ 0x3e, 0x51, 0x57, 0x08};
+ char new_connection_id_bytes[] = {0xf0, 0x67, 0xa5, 0x50,
+ 0x2a, 0x42, 0x62, 0xb5};
+ char retry_token_bytes[] = {0x74, 0x6f, 0x6b, 0x65, 0x6e};
+
+ QuicConnectionId original_connection_id(
+ original_connection_id_bytes,
+ QUICHE_ARRAYSIZE(original_connection_id_bytes));
+ QuicConnectionId new_connection_id(new_connection_id_bytes,
+ QUICHE_ARRAYSIZE(new_connection_id_bytes));
+
+ std::string retry_token(retry_token_bytes,
+ QUICHE_ARRAYSIZE(retry_token_bytes));
+
+ {
+ TestConnection connection1(
+ original_connection_id, kPeerAddress, helper_.get(),
+ alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version());
+ connection1.set_visitor(&visitor_);
+
+ connection1.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(retry_packet, QUICHE_ARRAYSIZE(retry_packet),
+ clock_.Now()));
+ EXPECT_TRUE(connection1.GetStats().retry_packet_processed);
+ EXPECT_EQ(connection1.connection_id(), new_connection_id);
+ EXPECT_EQ(QuicPacketCreatorPeer::GetRetryToken(
+ QuicConnectionPeer::GetPacketCreator(&connection1)),
+ retry_token);
+ }
+
+ // Now flip the last bit of the retry packet to prevent the integrity tag
+ // from validating correctly.
+ retry_packet[QUICHE_ARRAYSIZE(retry_packet) - 1] ^= 1;
+
+ {
+ TestConnection connection2(
+ original_connection_id, kPeerAddress, helper_.get(),
+ alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version());
+ connection2.set_visitor(&visitor_);
+
+ connection2.ProcessUdpPacket(
+ kSelfAddress, kPeerAddress,
+ QuicReceivedPacket(retry_packet, QUICHE_ARRAYSIZE(retry_packet),
+ clock_.Now()));
+ EXPECT_FALSE(connection2.GetStats().retry_packet_processed);
+ EXPECT_EQ(connection2.connection_id(), original_connection_id);
+ EXPECT_TRUE(QuicPacketCreatorPeer::GetRetryToken(
+ QuicConnectionPeer::GetPacketCreator(&connection2))
+ .empty());
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic