Internal change

PiperOrigin-RevId: 385054011
diff --git a/quic/core/crypto/proof_source.h b/quic/core/crypto/proof_source.h
index 80d337a..830ce2b 100644
--- a/quic/core/crypto/proof_source.h
+++ b/quic/core/crypto/proof_source.h
@@ -197,7 +197,12 @@
     // returns the encrypted ticket. The resulting value must not be larger than
     // MaxOverhead bytes larger than |in|. If encryption fails, this method
     // returns an empty vector.
-    virtual std::vector<uint8_t> Encrypt(absl::string_view in) = 0;
+    //
+    // If |encryption_key| is nonempty, this method should use it for minting
+    // TLS resumption tickets.  If it is empty, this method may use an
+    // internally cached encryption key, if available.
+    virtual std::vector<uint8_t> Encrypt(absl::string_view in,
+                                         absl::string_view encryption_key) = 0;
 
     // Decrypt takes an encrypted ticket |in|, decrypts it, and calls
     // |callback->Run| with the decrypted ticket, which must not be larger than
@@ -231,13 +236,15 @@
   // |chain| the certificate chain in leaf-first order.
   // |handshake_hints| (optional) handshake hints that can be used by
   //      SSL_set_handshake_hints.
+  // |ticket_encryption_key| (optional) encryption key to be used for minting
+  //      TLS resumption tickets.
   //
   // When called asynchronously(is_sync=false), this method will be responsible
   // to continue the handshake from where it left off.
-  virtual void OnSelectCertificateDone(bool ok,
-                                       bool is_sync,
-                                       const ProofSource::Chain* chain,
-                                       absl::string_view handshake_hints) = 0;
+  virtual void OnSelectCertificateDone(
+      bool ok, bool is_sync, const ProofSource::Chain* chain,
+      absl::string_view handshake_hints,
+      absl::string_view ticket_encryption_key) = 0;
 
   // Called when a ProofSourceHandle::ComputeSignature operation completes.
   virtual void OnComputeSignatureDone(
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index b90f91f..01e1db2 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -82,7 +82,8 @@
 
   handshaker_->OnSelectCertificateDone(
       /*ok=*/true, /*is_sync=*/true, chain.get(),
-      /*handshake_hints=*/absl::string_view());
+      /*handshake_hints=*/absl::string_view(),
+      /*ticket_encryption_key=*/absl::string_view());
   if (!handshaker_->select_cert_status().has_value()) {
     QUIC_BUG(quic_bug_12423_1)
         << "select_cert_status() has no value after a synchronous select cert";
@@ -652,7 +653,8 @@
                                            size_t max_out_len,
                                            absl::string_view in) {
   QUICHE_DCHECK(proof_source_->GetTicketCrypter());
-  std::vector<uint8_t> ticket = proof_source_->GetTicketCrypter()->Encrypt(in);
+  std::vector<uint8_t> ticket =
+      proof_source_->GetTicketCrypter()->Encrypt(in, ticket_encryption_key_);
   if (max_out_len < ticket.size()) {
     QUIC_BUG(quic_bug_12423_2)
         << "TicketCrypter returned " << ticket.size()
@@ -878,13 +880,15 @@
 }
 
 void TlsServerHandshaker::OnSelectCertificateDone(
-    bool ok,
-    bool is_sync,
-    const ProofSource::Chain* chain,
-    absl::string_view handshake_hints) {
+    bool ok, bool is_sync, const ProofSource::Chain* chain,
+    absl::string_view handshake_hints,
+    absl::string_view ticket_encryption_key) {
   QUIC_DVLOG(1) << "OnSelectCertificateDone. ok:" << ok
                 << ", is_sync:" << is_sync
-                << ", len(handshake_hints):" << handshake_hints.size();
+                << ", len(handshake_hints):" << handshake_hints.size()
+                << ", len(ticket_encryption_key):"
+                << ticket_encryption_key.size();
+  ticket_encryption_key_ = std::string(ticket_encryption_key);
   select_cert_status_ = QUIC_FAILURE;
   if (ok) {
     if (chain && !chain->certs.empty()) {
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h
index 9567706..e9fc172 100644
--- a/quic/core/tls_server_handshaker.h
+++ b/quic/core/tls_server_handshaker.h
@@ -165,10 +165,10 @@
   bool HasValidSignature(size_t max_signature_size) const;
 
   // ProofSourceHandleCallback implementation:
-  void OnSelectCertificateDone(bool ok,
-                               bool is_sync,
-                               const ProofSource::Chain* chain,
-                               absl::string_view handshake_hints) override;
+  void OnSelectCertificateDone(
+      bool ok, bool is_sync, const ProofSource::Chain* chain,
+      absl::string_view handshake_hints,
+      absl::string_view ticket_encryption_key) override;
 
   void OnComputeSignatureDone(
       bool ok,
@@ -337,6 +337,9 @@
   // Pre-shared key used during the handshake.
   std::string pre_shared_key_;
 
+  // (optional) Key to use for encrypting TLS resumption tickets.
+  std::string ticket_encryption_key_;
+
   HandshakeState state_ = HANDSHAKE_START;
   bool encryption_established_ = false;
   bool valid_alpn_received_ = false;
diff --git a/quic/test_tools/fake_proof_source_handle.cc b/quic/test_tools/fake_proof_source_handle.cc
index a70ce40..f34247e 100644
--- a/quic/test_tools/fake_proof_source_handle.cc
+++ b/quic/test_tools/fake_proof_source_handle.cc
@@ -93,7 +93,8 @@
   } else if (select_cert_action_ == Action::FAIL_SYNC) {
     callback()->OnSelectCertificateDone(
         /*ok=*/false,
-        /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view());
+        /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view(),
+        /*ticket_encryption_key=*/absl::string_view());
     return QUIC_FAILURE;
   }
 
@@ -102,8 +103,10 @@
       delegate_->GetCertChain(server_address, client_address, hostname);
 
   bool ok = chain && !chain->certs.empty();
-  callback_->OnSelectCertificateDone(ok, /*is_sync=*/true, chain.get(),
-                                     /*handshake_hints=*/absl::string_view());
+  callback_->OnSelectCertificateDone(
+      ok, /*is_sync=*/true, chain.get(),
+      /*handshake_hints=*/absl::string_view(),
+      /*ticket_encryption_key=*/absl::string_view());
   return ok ? QUIC_SUCCESS : QUIC_FAILURE;
 }
 
@@ -175,16 +178,20 @@
 
 void FakeProofSourceHandle::SelectCertOperation::Run() {
   if (action_ == Action::FAIL_ASYNC) {
-    callback_->OnSelectCertificateDone(/*ok=*/false,
-                                       /*is_sync=*/false, nullptr,
-                                       /*handshake_hints=*/absl::string_view());
+    callback_->OnSelectCertificateDone(
+        /*ok=*/false,
+        /*is_sync=*/false, nullptr,
+        /*handshake_hints=*/absl::string_view(),
+        /*ticket_encryption_key=*/absl::string_view());
   } else if (action_ == Action::DELEGATE_ASYNC) {
     QuicReferenceCountedPointer<ProofSource::Chain> chain =
         delegate_->GetCertChain(args_.server_address, args_.client_address,
                                 args_.hostname);
     bool ok = chain && !chain->certs.empty();
-    callback_->OnSelectCertificateDone(ok, /*is_sync=*/false, chain.get(),
-                                       /*handshake_hints=*/absl::string_view());
+    callback_->OnSelectCertificateDone(
+        ok, /*is_sync=*/false, chain.get(),
+        /*handshake_hints=*/absl::string_view(),
+        /*ticket_encryption_key=*/absl::string_view());
   } else {
     QUIC_BUG(quic_bug_10139_1)
         << "Unexpected action: " << static_cast<int>(action_);
diff --git a/quic/test_tools/test_ticket_crypter.cc b/quic/test_tools/test_ticket_crypter.cc
index 4c4cfbb..be9021a 100644
--- a/quic/test_tools/test_ticket_crypter.cc
+++ b/quic/test_tools/test_ticket_crypter.cc
@@ -37,7 +37,8 @@
   return ticket_prefix_.size();
 }
 
-std::vector<uint8_t> TestTicketCrypter::Encrypt(absl::string_view in) {
+std::vector<uint8_t> TestTicketCrypter::Encrypt(
+    absl::string_view in, absl::string_view /* encryption_key */) {
   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/quic/test_tools/test_ticket_crypter.h b/quic/test_tools/test_ticket_crypter.h
index 63919c6..0300998 100644
--- a/quic/test_tools/test_ticket_crypter.h
+++ b/quic/test_tools/test_ticket_crypter.h
@@ -19,7 +19,8 @@
 
   // TicketCrypter interface
   size_t MaxOverhead() override;
-  std::vector<uint8_t> Encrypt(absl::string_view in) override;
+  std::vector<uint8_t> Encrypt(absl::string_view in,
+                               absl::string_view encryption_key) override;
   void Decrypt(absl::string_view in,
                std::unique_ptr<ProofSource::DecryptCallback> callback) override;
 
diff --git a/quic/tools/simple_ticket_crypter.cc b/quic/tools/simple_ticket_crypter.cc
index 0130352..149adda 100644
--- a/quic/tools/simple_ticket_crypter.cc
+++ b/quic/tools/simple_ticket_crypter.cc
@@ -38,7 +38,12 @@
   return kEpochSize + kIVSize + kAuthTagSize;
 }
 
-std::vector<uint8_t> SimpleTicketCrypter::Encrypt(absl::string_view in) {
+std::vector<uint8_t> SimpleTicketCrypter::Encrypt(
+    absl::string_view in, absl::string_view encryption_key) {
+  // This class is only used in Chromium, in which the |encryption_key| argument
+  // will never be populated and an internally-cached key should be used for
+  // encrypting tickets.
+  QUICHE_DCHECK(encryption_key.empty());
   MaybeRotateKeys();
   std::vector<uint8_t> out(in.size() + MaxOverhead());
   out[0] = key_epoch_;
diff --git a/quic/tools/simple_ticket_crypter.h b/quic/tools/simple_ticket_crypter.h
index d547a25..052bc58 100644
--- a/quic/tools/simple_ticket_crypter.h
+++ b/quic/tools/simple_ticket_crypter.h
@@ -24,7 +24,8 @@
   ~SimpleTicketCrypter() override;
 
   size_t MaxOverhead() override;
-  std::vector<uint8_t> Encrypt(absl::string_view in) override;
+  std::vector<uint8_t> Encrypt(absl::string_view in,
+                               absl::string_view encryption_key) override;
   void Decrypt(
       absl::string_view in,
       std::unique_ptr<quic::ProofSource::DecryptCallback> callback) override;
diff --git a/quic/tools/simple_ticket_crypter_test.cc b/quic/tools/simple_ticket_crypter_test.cc
index ad041c1..be71018 100644
--- a/quic/tools/simple_ticket_crypter_test.cc
+++ b/quic/tools/simple_ticket_crypter_test.cc
@@ -42,7 +42,7 @@
 TEST_F(SimpleTicketCrypterTest, EncryptDecrypt) {
   std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
   std::vector<uint8_t> ciphertext =
-      ticket_crypter_.Encrypt(StringPiece(plaintext));
+      ticket_crypter_.Encrypt(StringPiece(plaintext), {});
   EXPECT_NE(plaintext, ciphertext);
 
   std::vector<uint8_t> out_plaintext;
@@ -54,16 +54,16 @@
 TEST_F(SimpleTicketCrypterTest, CiphertextsDiffer) {
   std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
   std::vector<uint8_t> ciphertext1 =
-      ticket_crypter_.Encrypt(StringPiece(plaintext));
+      ticket_crypter_.Encrypt(StringPiece(plaintext), {});
   std::vector<uint8_t> ciphertext2 =
-      ticket_crypter_.Encrypt(StringPiece(plaintext));
+      ticket_crypter_.Encrypt(StringPiece(plaintext), {});
   EXPECT_NE(ciphertext1, ciphertext2);
 }
 
 TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithModifiedCiphertext) {
   std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
   std::vector<uint8_t> ciphertext =
-      ticket_crypter_.Encrypt(StringPiece(plaintext));
+      ticket_crypter_.Encrypt(StringPiece(plaintext), {});
   EXPECT_NE(plaintext, ciphertext);
 
   // Check that a bit flip in any byte will cause a decryption failure.
@@ -88,7 +88,7 @@
 TEST_F(SimpleTicketCrypterTest, KeyRotation) {
   std::vector<uint8_t> plaintext = {1, 2, 3};
   std::vector<uint8_t> ciphertext =
-      ticket_crypter_.Encrypt(StringPiece(plaintext));
+      ticket_crypter_.Encrypt(StringPiece(plaintext), {});
   EXPECT_FALSE(ciphertext.empty());
 
   // Advance the clock 8 days, so the key used for |ciphertext| is now the