Use TicketCrypter to enable TLS session resumption in QUIC.

gfe-relnote: Adds support for session resumption in TLS-based versions of QUIC. Protected by quic_enable_tls_resumption.
PiperOrigin-RevId: 308357681
Change-Id: I3889a8eec65d3903967d6ab1ca7c1b997da79606
diff --git a/quic/test_tools/fake_proof_source.cc b/quic/test_tools/fake_proof_source.cc
index 032560e..3763bcc 100644
--- a/quic/test_tools/fake_proof_source.cc
+++ b/quic/test_tools/fake_proof_source.cc
@@ -114,9 +114,17 @@
 }
 
 ProofSource::TicketCrypter* FakeProofSource::SessionTicketCrypter() {
+  if (ticket_crypter_) {
+    return ticket_crypter_.get();
+  }
   return delegate_->SessionTicketCrypter();
 }
 
+void FakeProofSource::SetTicketCrypter(
+    std::unique_ptr<TicketCrypter> ticket_crypter) {
+  ticket_crypter_ = std::move(ticket_crypter);
+}
+
 int FakeProofSource::NumPendingCallbacks() const {
   return pending_ops_.size();
 }
diff --git a/quic/test_tools/fake_proof_source.h b/quic/test_tools/fake_proof_source.h
index ef7669d..c179f59 100644
--- a/quic/test_tools/fake_proof_source.h
+++ b/quic/test_tools/fake_proof_source.h
@@ -15,10 +15,13 @@
 namespace quic {
 namespace test {
 
-// Implementation of ProofSource which delegates to a ProofSourceForTesting,
-// except that when the async GetProof is called, it captures the call and
-// allows tests to see that a call is pending, which they can then cause to
-// complete at a time of their choosing.
+// Implementation of ProofSource which delegates to a ProofSourceForTesting, but
+// allows for overriding certain functionality. FakeProofSource allows
+// intercepting calls to GetProof and ComputeTlsSignature to force them to run
+// asynchronously, and allow the caller to see that the call is pending and
+// resume the operation at the caller's choosing. FakeProofSource also allows
+// the caller to replace the TicketCrypter provided by
+// FakeProofSource::SessionTicketCrypter.
 class FakeProofSource : public ProofSource {
  public:
   FakeProofSource();
@@ -46,9 +49,12 @@
       uint16_t signature_algorithm,
       quiche::QuicheStringPiece in,
       std::unique_ptr<ProofSource::SignatureCallback> callback) override;
-
   TicketCrypter* SessionTicketCrypter() override;
 
+  // Sets the TicketCrypter to use. If nullptr, the TicketCrypter from
+  // ProofSourceForTesting will be returned instead.
+  void SetTicketCrypter(std::unique_ptr<TicketCrypter> ticket_crypter);
+
   // Get the number of callbacks which are pending
   int NumPendingCallbacks() const;
 
@@ -58,6 +64,7 @@
 
  private:
   std::unique_ptr<ProofSource> delegate_;
+  std::unique_ptr<TicketCrypter> ticket_crypter_;
   bool active_ = false;
 
   class PendingOp {
diff --git a/quic/test_tools/test_ticket_crypter.cc b/quic/test_tools/test_ticket_crypter.cc
new file mode 100644
index 0000000..4d0d93e
--- /dev/null
+++ b/quic/test_tools/test_ticket_crypter.cc
@@ -0,0 +1,74 @@
+// Copyright (c) 2020 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.
+
+#include "net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h"
+
+#include <cstring>
+
+#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
+
+namespace quic {
+namespace test {
+
+namespace {
+
+// A TicketCrypter implementation is supposed to encrypt and decrypt session
+// tickets. However, the only requirement that is needed of a test
+// implementation is that calling Decrypt(Encrypt(input), callback) results in
+// callback being called with input. (The output of Encrypt must also not exceed
+// the overhead specified by MaxOverhead.) This test implementation encrypts
+// tickets by prepending kTicketPrefix to generate the ciphertext. The decrypt
+// function checks that the prefix is present and strips it; otherwise it
+// returns an empty vector to signal failure.
+constexpr char kTicketPrefix[] = "TEST TICKET";
+
+}  // namespace
+
+size_t TestTicketCrypter::MaxOverhead() {
+  return QUICHE_ARRAYSIZE(kTicketPrefix);
+}
+
+std::vector<uint8_t> TestTicketCrypter::Encrypt(quiche::QuicheStringPiece in) {
+  size_t prefix_len = QUICHE_ARRAYSIZE(kTicketPrefix);
+  std::vector<uint8_t> out(prefix_len + in.size());
+  memcpy(out.data(), kTicketPrefix, prefix_len);
+  memcpy(out.data() + prefix_len, in.data(), in.size());
+  return out;
+}
+
+std::vector<uint8_t> TestTicketCrypter::Decrypt(quiche::QuicheStringPiece in) {
+  size_t prefix_len = QUICHE_ARRAYSIZE(kTicketPrefix);
+  if (fail_decrypt_ || in.size() < prefix_len ||
+      memcmp(kTicketPrefix, in.data(), prefix_len) != 0) {
+    return std::vector<uint8_t>();
+  }
+  return std::vector<uint8_t>(in.begin() + prefix_len, in.end());
+}
+
+void TestTicketCrypter::Decrypt(
+    quiche::QuicheStringPiece in,
+    std::unique_ptr<ProofSource::DecryptCallback> callback) {
+  auto decrypted_ticket = Decrypt(in);
+  if (run_async_) {
+    pending_callbacks_.push_back({std::move(callback), decrypted_ticket});
+  } else {
+    callback->Run(decrypted_ticket);
+  }
+}
+
+void TestTicketCrypter::SetRunCallbacksAsync(bool run_async) {
+  run_async_ = run_async;
+}
+
+size_t TestTicketCrypter::NumPendingCallbacks() {
+  return pending_callbacks_.size();
+}
+
+void TestTicketCrypter::RunPendingCallback(size_t n) {
+  const PendingCallback& callback = pending_callbacks_[n];
+  callback.callback->Run(callback.decrypted_ticket);
+}
+
+}  // namespace test
+}  // namespace quic
diff --git a/quic/test_tools/test_ticket_crypter.h b/quic/test_tools/test_ticket_crypter.h
new file mode 100644
index 0000000..b596348
--- /dev/null
+++ b/quic/test_tools/test_ticket_crypter.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2020 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 QUICHE_QUIC_TEST_TOOLS_TEST_TICKET_CRYPTER_H_
+#define QUICHE_QUIC_TEST_TOOLS_TEST_TICKET_CRYPTER_H_
+
+#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
+
+namespace quic {
+namespace test {
+
+// Provides a simple implementation of ProofSource::TicketCrypter for testing.
+// THIS IMPLEMENTATION IS NOT SECURE. It is only intended for testing purposes.
+class TestTicketCrypter : public ProofSource::TicketCrypter {
+ public:
+  ~TestTicketCrypter() override = default;
+
+  // TicketCrypter interface
+  size_t MaxOverhead() override;
+  std::vector<uint8_t> Encrypt(quiche::QuicheStringPiece in) override;
+  void Decrypt(quiche::QuicheStringPiece in,
+               std::unique_ptr<ProofSource::DecryptCallback> callback) override;
+
+  void SetRunCallbacksAsync(bool run_async);
+  size_t NumPendingCallbacks();
+  void RunPendingCallback(size_t n);
+
+  // Allows configuring this TestTicketCrypter to fail decryption.
+  void set_fail_decrypt(bool fail_decrypt) { fail_decrypt_ = fail_decrypt; }
+
+ private:
+  // Performs the Decrypt operation synchronously.
+  std::vector<uint8_t> Decrypt(quiche::QuicheStringPiece in);
+
+  struct PendingCallback {
+    std::unique_ptr<ProofSource::DecryptCallback> callback;
+    std::vector<uint8_t> decrypted_ticket;
+  };
+
+  bool fail_decrypt_ = false;
+  bool run_async_ = false;
+  std::vector<PendingCallback> pending_callbacks_;
+};
+
+}  // namespace test
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_TEST_TOOLS_TEST_TICKET_CRYPTER_H_