1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/tools/simple_ticket_crypter.h"
6
7 #include "quiche/quic/platform/api/quic_test.h"
8 #include "quiche/quic/test_tools/mock_clock.h"
9
10 namespace quic {
11 namespace test {
12
13 namespace {
14
15 constexpr QuicTime::Delta kOneDay = QuicTime::Delta::FromSeconds(60 * 60 * 24);
16
17 } // namespace
18
19 class DecryptCallback : public quic::ProofSource::DecryptCallback {
20 public:
DecryptCallback(std::vector<uint8_t> * out)21 explicit DecryptCallback(std::vector<uint8_t>* out) : out_(out) {}
22
Run(std::vector<uint8_t> plaintext)23 void Run(std::vector<uint8_t> plaintext) override { *out_ = plaintext; }
24
25 private:
26 std::vector<uint8_t>* out_;
27 };
28
StringPiece(const std::vector<uint8_t> & in)29 absl::string_view StringPiece(const std::vector<uint8_t>& in) {
30 return absl::string_view(reinterpret_cast<const char*>(in.data()), in.size());
31 }
32
33 class SimpleTicketCrypterTest : public QuicTest {
34 public:
SimpleTicketCrypterTest()35 SimpleTicketCrypterTest() : ticket_crypter_(&mock_clock_) {}
36
37 protected:
38 MockClock mock_clock_;
39 SimpleTicketCrypter ticket_crypter_;
40 };
41
TEST_F(SimpleTicketCrypterTest,EncryptDecrypt)42 TEST_F(SimpleTicketCrypterTest, EncryptDecrypt) {
43 std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
44 std::vector<uint8_t> ciphertext =
45 ticket_crypter_.Encrypt(StringPiece(plaintext), {});
46 EXPECT_NE(plaintext, ciphertext);
47
48 std::vector<uint8_t> out_plaintext;
49 ticket_crypter_.Decrypt(StringPiece(ciphertext),
50 std::make_unique<DecryptCallback>(&out_plaintext));
51 EXPECT_EQ(out_plaintext, plaintext);
52 }
53
TEST_F(SimpleTicketCrypterTest,CiphertextsDiffer)54 TEST_F(SimpleTicketCrypterTest, CiphertextsDiffer) {
55 std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
56 std::vector<uint8_t> ciphertext1 =
57 ticket_crypter_.Encrypt(StringPiece(plaintext), {});
58 std::vector<uint8_t> ciphertext2 =
59 ticket_crypter_.Encrypt(StringPiece(plaintext), {});
60 EXPECT_NE(ciphertext1, ciphertext2);
61 }
62
TEST_F(SimpleTicketCrypterTest,DecryptionFailureWithModifiedCiphertext)63 TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithModifiedCiphertext) {
64 std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
65 std::vector<uint8_t> ciphertext =
66 ticket_crypter_.Encrypt(StringPiece(plaintext), {});
67 EXPECT_NE(plaintext, ciphertext);
68
69 // Check that a bit flip in any byte will cause a decryption failure.
70 for (size_t i = 0; i < ciphertext.size(); i++) {
71 SCOPED_TRACE(i);
72 std::vector<uint8_t> munged_ciphertext = ciphertext;
73 munged_ciphertext[i] ^= 1;
74 std::vector<uint8_t> out_plaintext;
75 ticket_crypter_.Decrypt(StringPiece(munged_ciphertext),
76 std::make_unique<DecryptCallback>(&out_plaintext));
77 EXPECT_TRUE(out_plaintext.empty());
78 }
79 }
80
TEST_F(SimpleTicketCrypterTest,DecryptionFailureWithEmptyCiphertext)81 TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithEmptyCiphertext) {
82 std::vector<uint8_t> out_plaintext;
83 ticket_crypter_.Decrypt(absl::string_view(),
84 std::make_unique<DecryptCallback>(&out_plaintext));
85 EXPECT_TRUE(out_plaintext.empty());
86 }
87
TEST_F(SimpleTicketCrypterTest,KeyRotation)88 TEST_F(SimpleTicketCrypterTest, KeyRotation) {
89 std::vector<uint8_t> plaintext = {1, 2, 3};
90 std::vector<uint8_t> ciphertext =
91 ticket_crypter_.Encrypt(StringPiece(plaintext), {});
92 EXPECT_FALSE(ciphertext.empty());
93
94 // Advance the clock 8 days, so the key used for |ciphertext| is now the
95 // previous key. Check that decryption still works.
96 mock_clock_.AdvanceTime(kOneDay * 8);
97 std::vector<uint8_t> out_plaintext;
98 ticket_crypter_.Decrypt(StringPiece(ciphertext),
99 std::make_unique<DecryptCallback>(&out_plaintext));
100 EXPECT_EQ(out_plaintext, plaintext);
101
102 // Advance the clock 8 more days. Now the original key should be expired and
103 // decryption should fail.
104 mock_clock_.AdvanceTime(kOneDay * 8);
105 ticket_crypter_.Decrypt(StringPiece(ciphertext),
106 std::make_unique<DecryptCallback>(&out_plaintext));
107 EXPECT_TRUE(out_plaintext.empty());
108 }
109
110 } // namespace test
111 } // namespace quic
112