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