|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ | 
|  | #define QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ | 
|  |  | 
|  | #include <cstdarg> | 
|  | #include <cstddef> | 
|  | #include <cstdint> | 
|  | #include <memory> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "absl/types/span.h" | 
|  | #include "openssl/evp.h" | 
|  | #include "quiche/quic/core/crypto/crypto_framer.h" | 
|  | #include "quiche/quic/core/crypto/quic_random.h" | 
|  | #include "quiche/quic/core/quic_connection.h" | 
|  | #include "quiche/quic/core/quic_framer.h" | 
|  | #include "quiche/quic/core/quic_packets.h" | 
|  | #include "quiche/quic/core/quic_types.h" | 
|  | #include "quiche/quic/test_tools/quic_test_utils.h" | 
|  | #include "quiche/common/quiche_callbacks.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | class ProofSource; | 
|  | class ProofVerifier; | 
|  | class ProofVerifyContext; | 
|  | class QuicClock; | 
|  | class QuicConfig; | 
|  | class QuicCryptoClientStream; | 
|  | class QuicCryptoServerConfig; | 
|  | class QuicCryptoServerStreamBase; | 
|  | class QuicCryptoStream; | 
|  | class QuicServerId; | 
|  |  | 
|  | namespace test { | 
|  |  | 
|  | class PacketSaver; | 
|  | class PacketSavingConnection; | 
|  |  | 
|  | namespace crypto_test_utils { | 
|  |  | 
|  | // An interface for a source of callbacks. This is used for invoking | 
|  | // callbacks asynchronously. | 
|  | // | 
|  | // Call the RunPendingCallbacks method regularly to run the callbacks from | 
|  | // this source. | 
|  | class CallbackSource { | 
|  | public: | 
|  | virtual ~CallbackSource() {} | 
|  |  | 
|  | // Runs pending callbacks from this source. If there is no pending | 
|  | // callback, does nothing. | 
|  | virtual void RunPendingCallbacks() = 0; | 
|  | }; | 
|  |  | 
|  | // FakeClientOptions bundles together a number of options for configuring | 
|  | // HandshakeWithFakeClient. | 
|  | struct FakeClientOptions { | 
|  | FakeClientOptions(); | 
|  | ~FakeClientOptions(); | 
|  |  | 
|  | // If only_tls_versions is set, then the client will only use TLS for the | 
|  | // crypto handshake. | 
|  | bool only_tls_versions = false; | 
|  |  | 
|  | // If only_quic_crypto_versions is set, then the client will only use | 
|  | // PROTOCOL_QUIC_CRYPTO for the crypto handshake. | 
|  | bool only_quic_crypto_versions = false; | 
|  | }; | 
|  |  | 
|  | // Returns a QuicCryptoServerConfig that is in a reasonable configuration to | 
|  | // pass into HandshakeWithFakeServer. | 
|  | std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting( | 
|  | const std::string& trust_anchor_id = ""); | 
|  |  | 
|  | // returns: the number of client hellos that the client sent. | 
|  | int HandshakeWithFakeServer(QuicConfig* server_quic_config, | 
|  | QuicCryptoServerConfig* crypto_config, | 
|  | MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | PacketSavingConnection* client_conn, | 
|  | QuicCryptoClientStreamBase* client, | 
|  | std::string alpn); | 
|  |  | 
|  | // returns: the number of client hellos that the client sent. | 
|  | int HandshakeWithFakeClient(MockQuicConnectionHelper* helper, | 
|  | MockAlarmFactory* alarm_factory, | 
|  | PacketSavingConnection* server_conn, | 
|  | QuicCryptoServerStreamBase* server, | 
|  | const QuicServerId& server_id, | 
|  | const FakeClientOptions& options, std::string alpn); | 
|  |  | 
|  | // SetupCryptoServerConfigForTest configures |crypto_config| | 
|  | // with sensible defaults for testing. | 
|  | void SetupCryptoServerConfigForTest(const QuicClock* clock, QuicRandom* rand, | 
|  | QuicCryptoServerConfig* crypto_config); | 
|  |  | 
|  | // Sends the handshake message |message| to stream |stream| with the perspective | 
|  | // that the message is coming from |perspective|. | 
|  | void SendHandshakeMessageToStream(QuicCryptoStream* stream, | 
|  | const CryptoHandshakeMessage& message, | 
|  | Perspective perspective); | 
|  |  | 
|  | // CommunicateHandshakeMessages moves messages from `client` (or | 
|  | // `packets_from_client`) to `server` from `server` (or `packets_from_server`) | 
|  | // to `client` until `clients`'s handshake has completed. | 
|  | void CommunicateHandshakeMessages(PacketSavingConnection* client_conn, | 
|  | QuicCryptoStream* client, | 
|  | PacketSavingConnection* server_conn, | 
|  | QuicCryptoStream* server); | 
|  | void CommunicateHandshakeMessages(QuicConnection& client_conn, | 
|  | QuicCryptoStream& client, | 
|  | QuicConnection& server_conn, | 
|  | QuicCryptoStream& server, | 
|  | PacketProvider& packets_from_client, | 
|  | PacketProvider& packets_from_server); | 
|  |  | 
|  | // CommunicateHandshakeMessagesUntil: | 
|  | // 1) Moves messages from `client` (or `packets_from_client`) to `server` until | 
|  | //    `server_condition` is met. | 
|  | // 2) Moves messages from `server` (or `packets_from_server`) to `client` until | 
|  | //    `client_condition` is met. | 
|  | // 3)  For IETF QUIC, if `process_stream_data` is true, STREAM_FRAME within the | 
|  | // packet containing crypto messages is also processed. | 
|  | // 4) Returns true if both conditions are met. | 
|  | // 5) Returns false if either connection is closed or there is no more packet to | 
|  | // deliver before both conditions are met. | 
|  | // TODO(ericorth): If the callers are eventually converted and these overloads | 
|  | // are merged, consider also converting `process_stream_data` to an enum. | 
|  | bool CommunicateHandshakeMessagesUntil( | 
|  | PacketSavingConnection* client_conn, QuicCryptoStream* client, | 
|  | quiche::UnretainedCallback<bool()> client_condition, | 
|  | PacketSavingConnection* server_conn, QuicCryptoStream* server, | 
|  | quiche::UnretainedCallback<bool()> server_condition, | 
|  | bool process_stream_data); | 
|  | bool CommunicateHandshakeMessagesUntil( | 
|  | QuicConnection& client_conn, QuicCryptoStream& client, | 
|  | quiche::UnretainedCallback<bool()> client_condition, | 
|  | QuicConnection& server_conn, QuicCryptoStream& server, | 
|  | quiche::UnretainedCallback<bool()> server_condition, | 
|  | bool process_stream_data, PacketProvider& packets_from_client, | 
|  | PacketProvider& packets_from_server); | 
|  |  | 
|  | // AdvanceHandshake attempts to move all current messages: | 
|  | // * Starting at `client_i`, from `client` to `server` | 
|  | // * Starting at `server_i`, from `server` to `client` | 
|  | // | 
|  | // Returns the total number of messages attempted to be moved so far from each | 
|  | // of `client` and `server` (number moved in this call plus `client_i` or | 
|  | // `server_i`). | 
|  | std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn, | 
|  | QuicCryptoStream* client, | 
|  | size_t client_i, | 
|  | PacketSavingConnection* server_conn, | 
|  | QuicCryptoStream* server, | 
|  | size_t server_i); | 
|  |  | 
|  | // AdvanceHandshake attempts to move all messages from `packets_from_client` to | 
|  | // `server` and from `packets_from_server` to `client`. | 
|  | void AdvanceHandshake( | 
|  | absl::Span<const QuicEncryptedPacket* const> packets_from_client, | 
|  | QuicConnection& client_conn, QuicCryptoStream& client, | 
|  | absl::Span<const QuicEncryptedPacket* const> packets_from_server, | 
|  | QuicConnection& server_conn, QuicCryptoStream& server); | 
|  |  | 
|  | // Returns the value for the tag |tag| in the tag value map of |message|. | 
|  | std::string GetValueForTag(const CryptoHandshakeMessage& message, QuicTag tag); | 
|  |  | 
|  | // Returns a new |ProofSource| that serves up test certificates. If | 
|  | // |trust_anchor_id| is provided, test certificates will be associated | 
|  | // with it as described at | 
|  | // https://tlswg.org/tls-trust-anchor-ids/draft-ietf-tls-trust-anchor-ids.html#section-4.1. | 
|  | std::unique_ptr<ProofSource> ProofSourceForTesting( | 
|  | const std::string& trust_anchor_id = ""); | 
|  |  | 
|  | // Returns a new |ProofVerifier| that uses the QUIC testing root CA. | 
|  | std::unique_ptr<ProofVerifier> ProofVerifierForTesting(); | 
|  |  | 
|  | // Returns the hostname used by the proof source and the proof verifier above. | 
|  | std::string CertificateHostnameForTesting(); | 
|  |  | 
|  | // Returns a hash of the leaf test certificate. | 
|  | uint64_t LeafCertHashForTesting(); | 
|  |  | 
|  | // Returns a |ProofVerifyContext| that must be used with the verifier | 
|  | // returned by |ProofVerifierForTesting|. | 
|  | std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting(); | 
|  |  | 
|  | // Creates a minimal dummy reject message that will pass the client-config | 
|  | // validation tests. This will include a server config, but no certs, proof | 
|  | // source address token, or server nonce. | 
|  | void FillInDummyReject(CryptoHandshakeMessage* rej); | 
|  |  | 
|  | // ParseTag returns a QuicTag from parsing |tagstr|. |tagstr| may either be | 
|  | // in the format "EXMP" (i.e. ASCII format), or "#11223344" (an explicit hex | 
|  | // format). It QUICHE_CHECK fails if there's a parse error. | 
|  | QuicTag ParseTag(const char* tagstr); | 
|  |  | 
|  | // Message constructs a CHLO message from a provided vector of tag/value pairs. | 
|  | // The first of each pair is the tag of a tag/value and is given as an argument | 
|  | // to |ParseTag|. The second is the value of the tag/value pair and is either a | 
|  | // hex dump, preceeded by a '#', or a raw value. If minimum_size_bytes is | 
|  | // provided then the message will be padded to this minimum size. | 
|  | // | 
|  | //   CreateCHLO( | 
|  | //       {{"NOCE", "#11223344"}, | 
|  | //        {"SNI", "www.example.com"}}, | 
|  | //       optional_minimum_size_bytes); | 
|  | CryptoHandshakeMessage CreateCHLO( | 
|  | std::vector<std::pair<std::string, std::string>> tags_and_values); | 
|  | CryptoHandshakeMessage CreateCHLO( | 
|  | std::vector<std::pair<std::string, std::string>> tags_and_values, | 
|  | int minimum_size_bytes); | 
|  |  | 
|  | // Return an inchoate CHLO with some basic tag value pairs. | 
|  | CryptoHandshakeMessage GenerateDefaultInchoateCHLO( | 
|  | const QuicClock* clock, QuicTransportVersion version, | 
|  | QuicCryptoServerConfig* crypto_config); | 
|  |  | 
|  | // Takes a inchoate CHLO, returns a full CHLO in |out| which can pass | 
|  | // |crypto_config|'s validation. | 
|  | void GenerateFullCHLO( | 
|  | const CryptoHandshakeMessage& inchoate_chlo, | 
|  | QuicCryptoServerConfig* crypto_config, QuicSocketAddress server_addr, | 
|  | QuicSocketAddress client_addr, QuicTransportVersion transport_version, | 
|  | const QuicClock* clock, | 
|  | quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config, | 
|  | QuicCompressedCertsCache* compressed_certs_cache, | 
|  | CryptoHandshakeMessage* out); | 
|  |  | 
|  | void CompareClientAndServerKeys(QuicCryptoClientStreamBase* client, | 
|  | QuicCryptoServerStreamBase* server); | 
|  |  | 
|  | // Return a CHLO nonce in hexadecimal. | 
|  | std::string GenerateClientNonceHex(const QuicClock* clock, | 
|  | QuicCryptoServerConfig* crypto_config); | 
|  |  | 
|  | // Return a CHLO PUBS in hexadecimal. | 
|  | std::string GenerateClientPublicValuesHex(); | 
|  |  | 
|  | }  // namespace crypto_test_utils | 
|  |  | 
|  | }  // namespace test | 
|  |  | 
|  | }  // namespace quic | 
|  |  | 
|  | #endif  // QUICHE_QUIC_TEST_TOOLS_CRYPTO_TEST_UTILS_H_ |