QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2012 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 | #ifndef QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ |
| 6 | #define QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ |
| 7 | |
| 8 | #include <cstdarg> |
| 9 | #include <cstddef> |
| 10 | #include <cstdint> |
| 11 | #include <utility> |
| 12 | #include <vector> |
| 13 | |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 14 | #include "absl/strings/string_view.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 15 | #include "third_party/boringssl/src/include/openssl/evp.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 16 | #include "quic/core/crypto/crypto_framer.h" |
| 17 | #include "quic/core/quic_framer.h" |
| 18 | #include "quic/core/quic_packets.h" |
| 19 | #include "quic/test_tools/quic_test_utils.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 20 | |
| 21 | namespace quic { |
| 22 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 23 | class CommonCertSets; |
| 24 | class ProofSource; |
| 25 | class ProofVerifier; |
| 26 | class ProofVerifyContext; |
| 27 | class QuicClock; |
| 28 | class QuicConfig; |
| 29 | class QuicCryptoClientStream; |
| 30 | class QuicCryptoServerConfig; |
nharper | f579b5e | 2020-01-21 14:11:18 -0800 | [diff] [blame] | 31 | class QuicCryptoServerStreamBase; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 32 | class QuicCryptoStream; |
| 33 | class QuicRandom; |
| 34 | class QuicServerId; |
| 35 | |
| 36 | namespace test { |
| 37 | |
| 38 | class PacketSavingConnection; |
| 39 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 40 | namespace crypto_test_utils { |
| 41 | |
| 42 | // An interface for a source of callbacks. This is used for invoking |
| 43 | // callbacks asynchronously. |
| 44 | // |
| 45 | // Call the RunPendingCallbacks method regularly to run the callbacks from |
| 46 | // this source. |
| 47 | class CallbackSource { |
| 48 | public: |
| 49 | virtual ~CallbackSource() {} |
| 50 | |
| 51 | // Runs pending callbacks from this source. If there is no pending |
| 52 | // callback, does nothing. |
| 53 | virtual void RunPendingCallbacks() = 0; |
| 54 | }; |
| 55 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 56 | // FakeClientOptions bundles together a number of options for configuring |
| 57 | // HandshakeWithFakeClient. |
| 58 | struct FakeClientOptions { |
| 59 | FakeClientOptions(); |
| 60 | ~FakeClientOptions(); |
| 61 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 62 | // If only_tls_versions is set, then the client will only use TLS for the |
| 63 | // crypto handshake. |
| 64 | bool only_tls_versions = false; |
dschinazi | dffd298 | 2020-03-02 10:25:11 -0800 | [diff] [blame] | 65 | |
| 66 | // If only_quic_crypto_versions is set, then the client will only use |
| 67 | // PROTOCOL_QUIC_CRYPTO for the crypto handshake. |
| 68 | bool only_quic_crypto_versions = false; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 69 | }; |
| 70 | |
nharper | df7a77b | 2019-11-11 13:12:45 -0800 | [diff] [blame] | 71 | // Returns a QuicCryptoServerConfig that is in a reasonable configuration to |
| 72 | // pass into HandshakeWithFakeServer. |
rch | 83f29bd | 2019-11-13 11:47:34 -0800 | [diff] [blame] | 73 | std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting(); |
nharper | df7a77b | 2019-11-11 13:12:45 -0800 | [diff] [blame] | 74 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 75 | // returns: the number of client hellos that the client sent. |
| 76 | int HandshakeWithFakeServer(QuicConfig* server_quic_config, |
nharper | df7a77b | 2019-11-11 13:12:45 -0800 | [diff] [blame] | 77 | QuicCryptoServerConfig* crypto_config, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 78 | MockQuicConnectionHelper* helper, |
| 79 | MockAlarmFactory* alarm_factory, |
| 80 | PacketSavingConnection* client_conn, |
vasilvv | e6472f6 | 2019-10-02 06:50:56 -0700 | [diff] [blame] | 81 | QuicCryptoClientStream* client, |
| 82 | std::string alpn); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 83 | |
| 84 | // returns: the number of client hellos that the client sent. |
| 85 | int HandshakeWithFakeClient(MockQuicConnectionHelper* helper, |
| 86 | MockAlarmFactory* alarm_factory, |
| 87 | PacketSavingConnection* server_conn, |
nharper | f579b5e | 2020-01-21 14:11:18 -0800 | [diff] [blame] | 88 | QuicCryptoServerStreamBase* server, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 89 | const QuicServerId& server_id, |
vasilvv | efc6af8 | 2019-10-11 12:46:56 -0700 | [diff] [blame] | 90 | const FakeClientOptions& options, |
| 91 | std::string alpn); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 92 | |
| 93 | // SetupCryptoServerConfigForTest configures |crypto_config| |
| 94 | // with sensible defaults for testing. |
| 95 | void SetupCryptoServerConfigForTest(const QuicClock* clock, |
| 96 | QuicRandom* rand, |
nharper | ba5f32c | 2019-05-13 12:21:31 -0700 | [diff] [blame] | 97 | QuicCryptoServerConfig* crypto_config); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 98 | |
| 99 | // Sends the handshake message |message| to stream |stream| with the perspective |
| 100 | // that the message is coming from |perspective|. |
| 101 | void SendHandshakeMessageToStream(QuicCryptoStream* stream, |
| 102 | const CryptoHandshakeMessage& message, |
| 103 | Perspective perspective); |
| 104 | |
| 105 | // CommunicateHandshakeMessages moves messages from |client| to |server| and |
| 106 | // back until |clients|'s handshake has completed. |
| 107 | void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, |
| 108 | QuicCryptoStream* client, |
| 109 | PacketSavingConnection* server_conn, |
| 110 | QuicCryptoStream* server); |
| 111 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 112 | // AdvanceHandshake attempts to moves messages from |client| to |server| and |
| 113 | // |server| to |client|. Returns the number of messages moved. |
| 114 | std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, |
| 115 | QuicCryptoStream* client, |
| 116 | size_t client_i, |
| 117 | PacketSavingConnection* server_conn, |
| 118 | QuicCryptoStream* server, |
| 119 | size_t server_i); |
| 120 | |
| 121 | // Returns the value for the tag |tag| in the tag value map of |message|. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 122 | std::string GetValueForTag(const CryptoHandshakeMessage& message, QuicTag tag); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 123 | |
| 124 | // Returns a new |ProofSource| that serves up test certificates. |
| 125 | std::unique_ptr<ProofSource> ProofSourceForTesting(); |
| 126 | |
| 127 | // Returns a new |ProofVerifier| that uses the QUIC testing root CA. |
| 128 | std::unique_ptr<ProofVerifier> ProofVerifierForTesting(); |
| 129 | |
| 130 | // Returns a hash of the leaf test certificate. |
| 131 | uint64_t LeafCertHashForTesting(); |
| 132 | |
| 133 | // Returns a |ProofVerifyContext| that must be used with the verifier |
| 134 | // returned by |ProofVerifierForTesting|. |
| 135 | std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting(); |
| 136 | |
| 137 | // MockCommonCertSets returns a CommonCertSets that contains a single set with |
| 138 | // hash |hash|, consisting of the certificate |cert| at index |index|. |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 139 | CommonCertSets* MockCommonCertSets(absl::string_view cert, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 140 | uint64_t hash, |
| 141 | uint32_t index); |
| 142 | |
| 143 | // Creates a minimal dummy reject message that will pass the client-config |
| 144 | // validation tests. This will include a server config, but no certs, proof |
| 145 | // source address token, or server nonce. |
wub | 9b9cc81 | 2019-05-20 09:01:52 -0700 | [diff] [blame] | 146 | void FillInDummyReject(CryptoHandshakeMessage* rej); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 147 | |
| 148 | // ParseTag returns a QuicTag from parsing |tagstr|. |tagstr| may either be |
| 149 | // in the format "EXMP" (i.e. ASCII format), or "#11223344" (an explicit hex |
vasilvv | 5cef78e | 2021-01-30 11:11:14 -0800 | [diff] [blame] | 150 | // format). It QUICHE_CHECK fails if there's a parse error. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 151 | QuicTag ParseTag(const char* tagstr); |
| 152 | |
| 153 | // Message constructs a CHLO message from a provided vector of tag/value pairs. |
| 154 | // The first of each pair is the tag of a tag/value and is given as an argument |
| 155 | // to |ParseTag|. The second is the value of the tag/value pair and is either a |
| 156 | // hex dump, preceeded by a '#', or a raw value. If minimum_size_bytes is |
| 157 | // provided then the message will be padded to this minimum size. |
| 158 | // |
| 159 | // CreateCHLO( |
| 160 | // {{"NOCE", "#11223344"}, |
| 161 | // {"SNI", "www.example.com"}}, |
| 162 | // optional_minimum_size_bytes); |
| 163 | CryptoHandshakeMessage CreateCHLO( |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 164 | std::vector<std::pair<std::string, std::string>> tags_and_values); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 165 | CryptoHandshakeMessage CreateCHLO( |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 166 | std::vector<std::pair<std::string, std::string>> tags_and_values, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 167 | int minimum_size_bytes); |
| 168 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 169 | // MovePackets parses crypto handshake messages from packet number |
| 170 | // |*inout_packet_index| through to the last packet (or until a packet fails |
| 171 | // to decrypt) and has |dest_stream| process them. |*inout_packet_index| is |
| 172 | // updated with an index one greater than the last packet processed. |
| 173 | void MovePackets(PacketSavingConnection* source_conn, |
| 174 | size_t* inout_packet_index, |
| 175 | QuicCryptoStream* dest_stream, |
| 176 | PacketSavingConnection* dest_conn, |
| 177 | Perspective dest_perspective); |
| 178 | |
| 179 | // Return an inchoate CHLO with some basic tag value pairs. |
| 180 | CryptoHandshakeMessage GenerateDefaultInchoateCHLO( |
| 181 | const QuicClock* clock, |
| 182 | QuicTransportVersion version, |
| 183 | QuicCryptoServerConfig* crypto_config); |
| 184 | |
| 185 | // Takes a inchoate CHLO, returns a full CHLO in |out| which can pass |
| 186 | // |crypto_config|'s validation. |
| 187 | void GenerateFullCHLO( |
| 188 | const CryptoHandshakeMessage& inchoate_chlo, |
| 189 | QuicCryptoServerConfig* crypto_config, |
| 190 | QuicSocketAddress server_addr, |
| 191 | QuicSocketAddress client_addr, |
dschinazi | 8d1c9d4 | 2020-02-18 13:12:20 -0800 | [diff] [blame] | 192 | QuicTransportVersion transport_version, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 193 | const QuicClock* clock, |
| 194 | QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config, |
| 195 | QuicCompressedCertsCache* compressed_certs_cache, |
| 196 | CryptoHandshakeMessage* out); |
| 197 | |
| 198 | void CompareClientAndServerKeys(QuicCryptoClientStream* client, |
nharper | f579b5e | 2020-01-21 14:11:18 -0800 | [diff] [blame] | 199 | QuicCryptoServerStreamBase* server); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 200 | |
| 201 | // Return a CHLO nonce in hexadecimal. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 202 | std::string GenerateClientNonceHex(const QuicClock* clock, |
| 203 | QuicCryptoServerConfig* crypto_config); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 204 | |
| 205 | // Return a CHLO PUBS in hexadecimal. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 206 | std::string GenerateClientPublicValuesHex(); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 207 | |
| 208 | } // namespace crypto_test_utils |
| 209 | |
| 210 | } // namespace test |
| 211 | |
| 212 | } // namespace quic |
| 213 | |
| 214 | #endif // QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ |