nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 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 | |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 5 | #include "quic/test_tools/test_ticket_crypter.h" |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 6 | |
| 7 | #include <cstring> |
| 8 | |
vasilvv | 035fe3d | 2020-10-20 08:38:37 -0700 | [diff] [blame] | 9 | #include "absl/base/macros.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 10 | #include "quic/core/crypto/quic_random.h" |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 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 | |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 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 | |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 36 | size_t TestTicketCrypter::MaxOverhead() { |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 37 | return ticket_prefix_.size(); |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 38 | } |
| 39 | |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 40 | std::vector<uint8_t> TestTicketCrypter::Encrypt(absl::string_view in) { |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 41 | size_t prefix_len = ticket_prefix_.size(); |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 42 | std::vector<uint8_t> out(prefix_len + in.size()); |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 43 | memcpy(out.data(), ticket_prefix_.data(), prefix_len); |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 44 | memcpy(out.data() + prefix_len, in.data(), in.size()); |
| 45 | return out; |
| 46 | } |
| 47 | |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 48 | std::vector<uint8_t> TestTicketCrypter::Decrypt(absl::string_view in) { |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 49 | size_t prefix_len = ticket_prefix_.size(); |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 50 | if (fail_decrypt_ || in.size() < prefix_len || |
nharper | 732883c | 2020-10-27 11:41:41 -0700 | [diff] [blame] | 51 | memcmp(ticket_prefix_.data(), in.data(), prefix_len) != 0) { |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 52 | return std::vector<uint8_t>(); |
| 53 | } |
| 54 | return std::vector<uint8_t>(in.begin() + prefix_len, in.end()); |
| 55 | } |
| 56 | |
| 57 | void TestTicketCrypter::Decrypt( |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 58 | absl::string_view in, |
nharper | fbaacc0 | 2020-04-24 17:30:22 -0700 | [diff] [blame] | 59 | std::unique_ptr<ProofSource::DecryptCallback> callback) { |
| 60 | auto decrypted_ticket = Decrypt(in); |
| 61 | if (run_async_) { |
| 62 | pending_callbacks_.push_back({std::move(callback), decrypted_ticket}); |
| 63 | } else { |
| 64 | callback->Run(decrypted_ticket); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | void TestTicketCrypter::SetRunCallbacksAsync(bool run_async) { |
| 69 | run_async_ = run_async; |
| 70 | } |
| 71 | |
| 72 | size_t TestTicketCrypter::NumPendingCallbacks() { |
| 73 | return pending_callbacks_.size(); |
| 74 | } |
| 75 | |
| 76 | void TestTicketCrypter::RunPendingCallback(size_t n) { |
| 77 | const PendingCallback& callback = pending_callbacks_[n]; |
| 78 | callback.callback->Run(callback.decrypted_ticket); |
| 79 | } |
| 80 | |
| 81 | } // namespace test |
| 82 | } // namespace quic |