Internal change
PiperOrigin-RevId: 498244260
diff --git a/quiche/quic/core/quic_flags_list.h b/quiche/quic/core/quic_flags_list.h
index 2b404a7..5b1fa1f 100644
--- a/quiche/quic/core/quic_flags_list.h
+++ b/quiche/quic/core/quic_flags_list.h
@@ -87,6 +87,8 @@
QUIC_FLAG(quic_reloadable_flag_quic_priority_update_structured_headers_parser, true)
// If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.
QUIC_FLAG(quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
+// If true, when TicketCrypter fails to encrypt a session ticket, quic::TlsServerHandshaker will send a placeholder ticket, instead of an empty one, to the client.
+QUIC_FLAG(quic_reloadable_flag_quic_send_placeholder_ticket_when_encrypt_ticket_fails, true)
// When true, defaults to BBR congestion control instead of Cubic.
QUIC_FLAG(quic_reloadable_flag_quic_default_to_bbr, false)
// When true, support draft-ietf-quic-v2-08
diff --git a/quiche/quic/core/tls_server_handshaker.cc b/quiche/quic/core/tls_server_handshaker.cc
index b035c60..f31489a 100644
--- a/quiche/quic/core/tls_server_handshaker.cc
+++ b/quiche/quic/core/tls_server_handshaker.cc
@@ -735,6 +735,15 @@
QUICHE_DCHECK(proof_source_->GetTicketCrypter());
std::vector<uint8_t> ticket =
proof_source_->GetTicketCrypter()->Encrypt(in, ticket_encryption_key_);
+ if (GetQuicReloadableFlag(
+ quic_send_placeholder_ticket_when_encrypt_ticket_fails) &&
+ ticket.empty()) {
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_send_placeholder_ticket);
+ const absl::string_view kTicketFailurePlaceholder = "TICKET FAILURE";
+ const absl::string_view kTicketWithSizeLimit =
+ kTicketFailurePlaceholder.substr(0, max_out_len);
+ ticket.assign(kTicketWithSizeLimit.begin(), kTicketWithSizeLimit.end());
+ }
if (max_out_len < ticket.size()) {
QUIC_BUG(quic_bug_12423_2)
<< "TicketCrypter returned " << ticket.size()
diff --git a/quiche/quic/core/tls_server_handshaker_test.cc b/quiche/quic/core/tls_server_handshaker_test.cc
index fe3f982..e68ea65 100644
--- a/quiche/quic/core/tls_server_handshaker_test.cc
+++ b/quiche/quic/core/tls_server_handshaker_test.cc
@@ -786,6 +786,29 @@
EXPECT_TRUE(server_stream()->ResumptionAttempted());
}
+TEST_P(TlsServerHandshakerTest, ResumptionWithPlaceholderTicket) {
+ // Do the first handshake
+ InitializeFakeClient();
+
+ ticket_crypter_->set_fail_encrypt(true);
+ CompleteCryptoHandshake();
+ ExpectHandshakeSuccessful();
+ EXPECT_FALSE(client_stream()->IsResumption());
+ EXPECT_FALSE(server_stream()->IsResumption());
+ EXPECT_FALSE(server_stream()->ResumptionAttempted());
+
+ // Now do another handshake. It should end up with a full handshake because
+ // the placeholder ticket is undecryptable.
+ InitializeServer();
+ InitializeFakeClient();
+ CompleteCryptoHandshake();
+ ExpectHandshakeSuccessful();
+ EXPECT_FALSE(client_stream()->IsResumption());
+ EXPECT_FALSE(server_stream()->IsResumption());
+ EXPECT_NE(server_stream()->ResumptionAttempted(),
+ GetParam().disable_resumption);
+}
+
TEST_P(TlsServerHandshakerTest, AdvanceHandshakeDuringAsyncDecryptCallback) {
if (GetParam().disable_resumption) {
return;
diff --git a/quiche/quic/test_tools/test_ticket_crypter.cc b/quiche/quic/test_tools/test_ticket_crypter.cc
index dbdb2a9..0a5ec49 100644
--- a/quiche/quic/test_tools/test_ticket_crypter.cc
+++ b/quiche/quic/test_tools/test_ticket_crypter.cc
@@ -37,6 +37,9 @@
std::vector<uint8_t> TestTicketCrypter::Encrypt(
absl::string_view in, absl::string_view /* encryption_key */) {
+ if (fail_encrypt_) {
+ return {};
+ }
size_t prefix_len = ticket_prefix_.size();
std::vector<uint8_t> out(prefix_len + in.size());
memcpy(out.data(), ticket_prefix_.data(), prefix_len);
diff --git a/quiche/quic/test_tools/test_ticket_crypter.h b/quiche/quic/test_tools/test_ticket_crypter.h
index 888bdef..0efd0f9 100644
--- a/quiche/quic/test_tools/test_ticket_crypter.h
+++ b/quiche/quic/test_tools/test_ticket_crypter.h
@@ -30,6 +30,7 @@
// Allows configuring this TestTicketCrypter to fail decryption.
void set_fail_decrypt(bool fail_decrypt) { fail_decrypt_ = fail_decrypt; }
+ void set_fail_encrypt(bool fail_encrypt) { fail_encrypt_ = fail_encrypt; }
private:
// Performs the Decrypt operation synchronously.
@@ -41,6 +42,7 @@
};
bool fail_decrypt_ = false;
+ bool fail_encrypt_ = false;
bool run_async_ = false;
std::vector<PendingCallback> pending_callbacks_;
std::vector<uint8_t> ticket_prefix_;