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