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_;