| // Copyright 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/tools/simple_ticket_crypter.h" | 
 |  | 
 | #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" | 
 | #include "net/third_party/quiche/src/quic/test_tools/mock_clock.h" | 
 |  | 
 | namespace quic { | 
 | namespace test { | 
 |  | 
 | namespace { | 
 |  | 
 | constexpr QuicTime::Delta kOneDay = QuicTime::Delta::FromSeconds(60 * 60 * 24); | 
 |  | 
 | }  // namespace | 
 |  | 
 | class DecryptCallback : public quic::ProofSource::DecryptCallback { | 
 |  public: | 
 |   explicit DecryptCallback(std::vector<uint8_t>* out) : out_(out) {} | 
 |  | 
 |   void Run(std::vector<uint8_t> plaintext) override { *out_ = plaintext; } | 
 |  | 
 |  private: | 
 |   std::vector<uint8_t>* out_; | 
 | }; | 
 |  | 
 | absl::string_view StringPiece(const std::vector<uint8_t>& in) { | 
 |   return absl::string_view(reinterpret_cast<const char*>(in.data()), in.size()); | 
 | } | 
 |  | 
 | class SimpleTicketCrypterTest : public QuicTest { | 
 |  public: | 
 |   SimpleTicketCrypterTest() : ticket_crypter_(&mock_clock_) {} | 
 |  | 
 |  protected: | 
 |   MockClock mock_clock_; | 
 |   SimpleTicketCrypter ticket_crypter_; | 
 | }; | 
 |  | 
 | TEST_F(SimpleTicketCrypterTest, EncryptDecrypt) { | 
 |   std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5}; | 
 |   std::vector<uint8_t> ciphertext = | 
 |       ticket_crypter_.Encrypt(StringPiece(plaintext)); | 
 |   EXPECT_NE(plaintext, ciphertext); | 
 |  | 
 |   std::vector<uint8_t> out_plaintext; | 
 |   ticket_crypter_.Decrypt(StringPiece(ciphertext), | 
 |                           std::make_unique<DecryptCallback>(&out_plaintext)); | 
 |   EXPECT_EQ(out_plaintext, plaintext); | 
 | } | 
 |  | 
 | TEST_F(SimpleTicketCrypterTest, CiphertextsDiffer) { | 
 |   std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5}; | 
 |   std::vector<uint8_t> ciphertext1 = | 
 |       ticket_crypter_.Encrypt(StringPiece(plaintext)); | 
 |   std::vector<uint8_t> ciphertext2 = | 
 |       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)); | 
 |   EXPECT_NE(plaintext, ciphertext); | 
 |  | 
 |   // Check that a bit flip in any byte will cause a decryption failure. | 
 |   for (size_t i = 0; i < ciphertext.size(); i++) { | 
 |     SCOPED_TRACE(i); | 
 |     std::vector<uint8_t> munged_ciphertext = ciphertext; | 
 |     munged_ciphertext[i] ^= 1; | 
 |     std::vector<uint8_t> out_plaintext; | 
 |     ticket_crypter_.Decrypt(StringPiece(munged_ciphertext), | 
 |                             std::make_unique<DecryptCallback>(&out_plaintext)); | 
 |     EXPECT_TRUE(out_plaintext.empty()); | 
 |   } | 
 | } | 
 |  | 
 | TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithEmptyCiphertext) { | 
 |   std::vector<uint8_t> out_plaintext; | 
 |   ticket_crypter_.Decrypt(absl::string_view(), | 
 |                           std::make_unique<DecryptCallback>(&out_plaintext)); | 
 |   EXPECT_TRUE(out_plaintext.empty()); | 
 | } | 
 |  | 
 | TEST_F(SimpleTicketCrypterTest, KeyRotation) { | 
 |   std::vector<uint8_t> plaintext = {1, 2, 3}; | 
 |   std::vector<uint8_t> ciphertext = | 
 |       ticket_crypter_.Encrypt(StringPiece(plaintext)); | 
 |   EXPECT_FALSE(ciphertext.empty()); | 
 |  | 
 |   // Advance the clock 8 days, so the key used for |ciphertext| is now the | 
 |   // previous key. Check that decryption still works. | 
 |   mock_clock_.AdvanceTime(kOneDay * 8); | 
 |   std::vector<uint8_t> out_plaintext; | 
 |   ticket_crypter_.Decrypt(StringPiece(ciphertext), | 
 |                           std::make_unique<DecryptCallback>(&out_plaintext)); | 
 |   EXPECT_EQ(out_plaintext, plaintext); | 
 |  | 
 |   // Advance the clock 8 more days. Now the original key should be expired and | 
 |   // decryption should fail. | 
 |   mock_clock_.AdvanceTime(kOneDay * 8); | 
 |   ticket_crypter_.Decrypt(StringPiece(ciphertext), | 
 |                           std::make_unique<DecryptCallback>(&out_plaintext)); | 
 |   EXPECT_TRUE(out_plaintext.empty()); | 
 | } | 
 |  | 
 | }  // namespace test | 
 | }  // namespace quic |