1 // Copyright (c) 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/test_tools/test_ticket_crypter.h"
6
7 #include <cstring>
8
9 #include "absl/base/macros.h"
10 #include "quiche/quic/core/crypto/quic_random.h"
11
12 namespace quic {
13 namespace test {
14
15 namespace {
16
17 // A TicketCrypter implementation is supposed to encrypt and decrypt session
18 // tickets. However, the only requirement that is needed of a test
19 // implementation is that calling Decrypt(Encrypt(input), callback) results in
20 // callback being called with input. (The output of Encrypt must also not exceed
21 // the overhead specified by MaxOverhead.) This test implementation encrypts
22 // tickets by prepending kTicketPrefix to generate the ciphertext. The decrypt
23 // function checks that the prefix is present and strips it; otherwise it
24 // returns an empty vector to signal failure.
25 constexpr char kTicketPrefix[] = "TEST TICKET";
26
27 } // namespace
28
TestTicketCrypter()29 TestTicketCrypter::TestTicketCrypter()
30 : ticket_prefix_(ABSL_ARRAYSIZE(kTicketPrefix) + 16) {
31 memcpy(ticket_prefix_.data(), kTicketPrefix, ABSL_ARRAYSIZE(kTicketPrefix));
32 QuicRandom::GetInstance()->RandBytes(
33 ticket_prefix_.data() + ABSL_ARRAYSIZE(kTicketPrefix), 16);
34 }
35
MaxOverhead()36 size_t TestTicketCrypter::MaxOverhead() { return ticket_prefix_.size(); }
37
Encrypt(absl::string_view in,absl::string_view)38 std::vector<uint8_t> TestTicketCrypter::Encrypt(
39 absl::string_view in, absl::string_view /* encryption_key */) {
40 if (fail_encrypt_) {
41 return {};
42 }
43 size_t prefix_len = ticket_prefix_.size();
44 std::vector<uint8_t> out(prefix_len + in.size());
45 memcpy(out.data(), ticket_prefix_.data(), prefix_len);
46 memcpy(out.data() + prefix_len, in.data(), in.size());
47 return out;
48 }
49
Decrypt(absl::string_view in)50 std::vector<uint8_t> TestTicketCrypter::Decrypt(absl::string_view in) {
51 size_t prefix_len = ticket_prefix_.size();
52 if (fail_decrypt_ || in.size() < prefix_len ||
53 memcmp(ticket_prefix_.data(), in.data(), prefix_len) != 0) {
54 return std::vector<uint8_t>();
55 }
56 return std::vector<uint8_t>(in.begin() + prefix_len, in.end());
57 }
58
Decrypt(absl::string_view in,std::shared_ptr<ProofSource::DecryptCallback> callback)59 void TestTicketCrypter::Decrypt(
60 absl::string_view in,
61 std::shared_ptr<ProofSource::DecryptCallback> callback) {
62 auto decrypted_ticket = Decrypt(in);
63 if (run_async_) {
64 pending_callbacks_.push_back({std::move(callback), decrypted_ticket});
65 } else {
66 callback->Run(decrypted_ticket);
67 }
68 }
69
SetRunCallbacksAsync(bool run_async)70 void TestTicketCrypter::SetRunCallbacksAsync(bool run_async) {
71 run_async_ = run_async;
72 }
73
NumPendingCallbacks()74 size_t TestTicketCrypter::NumPendingCallbacks() {
75 return pending_callbacks_.size();
76 }
77
RunPendingCallback(size_t n)78 void TestTicketCrypter::RunPendingCallback(size_t n) {
79 const PendingCallback& callback = pending_callbacks_[n];
80 callback.callback->Run(callback.decrypted_ticket);
81 }
82
83 } // namespace test
84 } // namespace quic
85