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 <memory> 12 #include <utility> 13 #include <vector> 14 15 #include "absl/strings/string_view.h" 16 #include "absl/types/span.h" 17 #include "openssl/evp.h" 18 #include "quiche/quic/core/crypto/crypto_framer.h" 19 #include "quiche/quic/core/crypto/quic_random.h" 20 #include "quiche/quic/core/quic_connection.h" 21 #include "quiche/quic/core/quic_framer.h" 22 #include "quiche/quic/core/quic_packets.h" 23 #include "quiche/quic/core/quic_types.h" 24 #include "quiche/quic/test_tools/quic_test_utils.h" 25 #include "quiche/common/quiche_callbacks.h" 26 27 namespace quic { 28 29 class ProofSource; 30 class ProofVerifier; 31 class ProofVerifyContext; 32 class QuicClock; 33 class QuicConfig; 34 class QuicCryptoClientStream; 35 class QuicCryptoServerConfig; 36 class QuicCryptoServerStreamBase; 37 class QuicCryptoStream; 38 class QuicServerId; 39 40 namespace test { 41 42 class PacketSaver; 43 class PacketSavingConnection; 44 45 namespace crypto_test_utils { 46 47 // An interface for a source of callbacks. This is used for invoking 48 // callbacks asynchronously. 49 // 50 // Call the RunPendingCallbacks method regularly to run the callbacks from 51 // this source. 52 class CallbackSource { 53 public: ~CallbackSource()54 virtual ~CallbackSource() {} 55 56 // Runs pending callbacks from this source. If there is no pending 57 // callback, does nothing. 58 virtual void RunPendingCallbacks() = 0; 59 }; 60 61 // FakeClientOptions bundles together a number of options for configuring 62 // HandshakeWithFakeClient. 63 struct FakeClientOptions { 64 FakeClientOptions(); 65 ~FakeClientOptions(); 66 67 // If only_tls_versions is set, then the client will only use TLS for the 68 // crypto handshake. 69 bool only_tls_versions = false; 70 71 // If only_quic_crypto_versions is set, then the client will only use 72 // PROTOCOL_QUIC_CRYPTO for the crypto handshake. 73 bool only_quic_crypto_versions = false; 74 }; 75 76 // Returns a QuicCryptoServerConfig that is in a reasonable configuration to 77 // pass into HandshakeWithFakeServer. 78 std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting(); 79 80 // returns: the number of client hellos that the client sent. 81 int HandshakeWithFakeServer(QuicConfig* server_quic_config, 82 QuicCryptoServerConfig* crypto_config, 83 MockQuicConnectionHelper* helper, 84 MockAlarmFactory* alarm_factory, 85 PacketSavingConnection* client_conn, 86 QuicCryptoClientStreamBase* client, 87 std::string alpn); 88 89 // returns: the number of client hellos that the client sent. 90 int HandshakeWithFakeClient(MockQuicConnectionHelper* helper, 91 MockAlarmFactory* alarm_factory, 92 PacketSavingConnection* server_conn, 93 QuicCryptoServerStreamBase* server, 94 const QuicServerId& server_id, 95 const FakeClientOptions& options, std::string alpn); 96 97 // SetupCryptoServerConfigForTest configures |crypto_config| 98 // with sensible defaults for testing. 99 void SetupCryptoServerConfigForTest(const QuicClock* clock, QuicRandom* rand, 100 QuicCryptoServerConfig* crypto_config); 101 102 // Sends the handshake message |message| to stream |stream| with the perspective 103 // that the message is coming from |perspective|. 104 void SendHandshakeMessageToStream(QuicCryptoStream* stream, 105 const CryptoHandshakeMessage& message, 106 Perspective perspective); 107 108 // CommunicateHandshakeMessages moves messages from `client` (or 109 // `packets_from_client`) to `server` from `server` (or `packets_from_server`) 110 // to `client` until `clients`'s handshake has completed. 111 void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, 112 QuicCryptoStream* client, 113 PacketSavingConnection* server_conn, 114 QuicCryptoStream* server); 115 void CommunicateHandshakeMessages(QuicConnection& client_conn, 116 QuicCryptoStream& client, 117 QuicConnection& server_conn, 118 QuicCryptoStream& server, 119 PacketProvider& packets_from_client, 120 PacketProvider& packets_from_server); 121 122 // CommunicateHandshakeMessagesUntil: 123 // 1) Moves messages from `client` (or `packets_from_client`) to `server` until 124 // `server_condition` is met. 125 // 2) Moves messages from `server` (or `packets_from_server`) to `client` until 126 // `client_condition` is met. 127 // 3) For IETF QUIC, if `process_stream_data` is true, STREAM_FRAME within the 128 // packet containing crypto messages is also processed. 129 // 4) Returns true if both conditions are met. 130 // 5) Returns false if either connection is closed or there is no more packet to 131 // deliver before both conditions are met. 132 // TODO(ericorth): If the callers are eventually converted and these overloads 133 // are merged, consider also converting `process_stream_data` to an enum. 134 bool CommunicateHandshakeMessagesUntil( 135 PacketSavingConnection* client_conn, QuicCryptoStream* client, 136 quiche::UnretainedCallback<bool()> client_condition, 137 PacketSavingConnection* server_conn, QuicCryptoStream* server, 138 quiche::UnretainedCallback<bool()> server_condition, 139 bool process_stream_data); 140 bool CommunicateHandshakeMessagesUntil( 141 QuicConnection& client_conn, QuicCryptoStream& client, 142 quiche::UnretainedCallback<bool()> client_condition, 143 QuicConnection& server_conn, QuicCryptoStream& server, 144 quiche::UnretainedCallback<bool()> server_condition, 145 bool process_stream_data, PacketProvider& packets_from_client, 146 PacketProvider& packets_from_server); 147 148 // AdvanceHandshake attempts to move all current messages: 149 // * Starting at `client_i`, from `client` to `server` 150 // * Starting at `server_i`, from `server` to `client` 151 // 152 // Returns the total number of messages attempted to be moved so far from each 153 // of `client` and `server` (number moved in this call plus `client_i` or 154 // `server_i`). 155 std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, 156 QuicCryptoStream* client, 157 size_t client_i, 158 PacketSavingConnection* server_conn, 159 QuicCryptoStream* server, 160 size_t server_i); 161 162 // AdvanceHandshake attempts to move all messages from `packets_from_client` to 163 // `server` and from `packets_from_server` to `client`. 164 void AdvanceHandshake( 165 absl::Span<const QuicEncryptedPacket* const> packets_from_client, 166 QuicConnection& client_conn, QuicCryptoStream& client, 167 absl::Span<const QuicEncryptedPacket* const> packets_from_server, 168 QuicConnection& server_conn, QuicCryptoStream& server); 169 170 // Returns the value for the tag |tag| in the tag value map of |message|. 171 std::string GetValueForTag(const CryptoHandshakeMessage& message, QuicTag tag); 172 173 // Returns a new |ProofSource| that serves up test certificates. 174 std::unique_ptr<ProofSource> ProofSourceForTesting(); 175 176 // Returns a new |ProofVerifier| that uses the QUIC testing root CA. 177 std::unique_ptr<ProofVerifier> ProofVerifierForTesting(); 178 179 // Returns the hostname used by the proof source and the proof verifier above. 180 std::string CertificateHostnameForTesting(); 181 182 // Returns a hash of the leaf test certificate. 183 uint64_t LeafCertHashForTesting(); 184 185 // Returns a |ProofVerifyContext| that must be used with the verifier 186 // returned by |ProofVerifierForTesting|. 187 std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting(); 188 189 // Creates a minimal dummy reject message that will pass the client-config 190 // validation tests. This will include a server config, but no certs, proof 191 // source address token, or server nonce. 192 void FillInDummyReject(CryptoHandshakeMessage* rej); 193 194 // ParseTag returns a QuicTag from parsing |tagstr|. |tagstr| may either be 195 // in the format "EXMP" (i.e. ASCII format), or "#11223344" (an explicit hex 196 // format). It QUICHE_CHECK fails if there's a parse error. 197 QuicTag ParseTag(const char* tagstr); 198 199 // Message constructs a CHLO message from a provided vector of tag/value pairs. 200 // The first of each pair is the tag of a tag/value and is given as an argument 201 // to |ParseTag|. The second is the value of the tag/value pair and is either a 202 // hex dump, preceeded by a '#', or a raw value. If minimum_size_bytes is 203 // provided then the message will be padded to this minimum size. 204 // 205 // CreateCHLO( 206 // {{"NOCE", "#11223344"}, 207 // {"SNI", "www.example.com"}}, 208 // optional_minimum_size_bytes); 209 CryptoHandshakeMessage CreateCHLO( 210 std::vector<std::pair<std::string, std::string>> tags_and_values); 211 CryptoHandshakeMessage CreateCHLO( 212 std::vector<std::pair<std::string, std::string>> tags_and_values, 213 int minimum_size_bytes); 214 215 // Return an inchoate CHLO with some basic tag value pairs. 216 CryptoHandshakeMessage GenerateDefaultInchoateCHLO( 217 const QuicClock* clock, QuicTransportVersion version, 218 QuicCryptoServerConfig* crypto_config); 219 220 // Takes a inchoate CHLO, returns a full CHLO in |out| which can pass 221 // |crypto_config|'s validation. 222 void GenerateFullCHLO( 223 const CryptoHandshakeMessage& inchoate_chlo, 224 QuicCryptoServerConfig* crypto_config, QuicSocketAddress server_addr, 225 QuicSocketAddress client_addr, QuicTransportVersion transport_version, 226 const QuicClock* clock, 227 quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config, 228 QuicCompressedCertsCache* compressed_certs_cache, 229 CryptoHandshakeMessage* out); 230 231 void CompareClientAndServerKeys(QuicCryptoClientStreamBase* client, 232 QuicCryptoServerStreamBase* server); 233 234 // Return a CHLO nonce in hexadecimal. 235 std::string GenerateClientNonceHex(const QuicClock* clock, 236 QuicCryptoServerConfig* crypto_config); 237 238 // Return a CHLO PUBS in hexadecimal. 239 std::string GenerateClientPublicValuesHex(); 240 241 } // namespace crypto_test_utils 242 243 } // namespace test 244 245 } // namespace quic 246 247 #endif // QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ 248