| // 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_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ | 
 | #define QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ | 
 |  | 
 | #include <cstdint> | 
 | #include <memory> | 
 | #include <string> | 
 |  | 
 | #include "quic/core/crypto/proof_verifier.h" | 
 | #include "quic/core/crypto/quic_crypto_client_config.h" | 
 | #include "quic/core/proto/cached_network_parameters_proto.h" | 
 | #include "quic/core/quic_config.h" | 
 | #include "quic/core/quic_crypto_handshaker.h" | 
 | #include "quic/core/quic_crypto_stream.h" | 
 | #include "quic/core/quic_server_id.h" | 
 | #include "quic/core/quic_session.h" | 
 | #include "quic/core/quic_versions.h" | 
 | #include "quic/platform/api/quic_export.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | namespace test { | 
 | class QuicCryptoClientStreamPeer; | 
 | }  // namespace test | 
 |  | 
 | class TlsClientHandshaker; | 
 |  | 
 | class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream { | 
 |  public: | 
 |   explicit QuicCryptoClientStreamBase(QuicSession* session); | 
 |  | 
 |   ~QuicCryptoClientStreamBase() override {} | 
 |  | 
 |   // Performs a crypto handshake with the server. Returns true if the connection | 
 |   // is still connected. | 
 |   virtual bool CryptoConnect() = 0; | 
 |  | 
 |   // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or | 
 |   // ReceivedInchoateReject instead. | 
 |   // | 
 |   // num_sent_client_hellos returns the number of client hello messages that | 
 |   // have been sent. If the handshake has completed then this is one greater | 
 |   // than the number of round-trips needed for the handshake. | 
 |   virtual int num_sent_client_hellos() const = 0; | 
 |  | 
 |   // Returns true if the handshake performed was a resumption instead of a full | 
 |   // handshake. Resumption only makes sense for TLS handshakes - there is no | 
 |   // concept of resumption for QUIC crypto even though it supports a 0-RTT | 
 |   // handshake. This function only returns valid results once the handshake is | 
 |   // complete. | 
 |   virtual bool IsResumption() const = 0; | 
 |  | 
 |   // Returns true if early data (0-RTT) was accepted in the connection. | 
 |   virtual bool EarlyDataAccepted() const = 0; | 
 |  | 
 |   // Returns true if the client received an inchoate REJ during the handshake, | 
 |   // extending the handshake by one round trip. This only applies for QUIC | 
 |   // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet, | 
 |   // but that is handled at the connection layer instead of the crypto layer. | 
 |   virtual bool ReceivedInchoateReject() const = 0; | 
 |  | 
 |   // The number of server config update messages received by the | 
 |   // client.  Does not count update messages that were received prior | 
 |   // to handshake confirmation. | 
 |   virtual int num_scup_messages_received() const = 0; | 
 |  | 
 |   bool ExportKeyingMaterial(absl::string_view /*label*/, | 
 |                             absl::string_view /*context*/, | 
 |                             size_t /*result_len*/, | 
 |                             std::string* /*result*/) override { | 
 |     QUICHE_NOTREACHED(); | 
 |     return false; | 
 |   } | 
 |  | 
 |   std::string GetAddressToken( | 
 |       const CachedNetworkParameters* /*cached_network_params*/) const override { | 
 |     QUICHE_DCHECK(false); | 
 |     return ""; | 
 |   } | 
 |  | 
 |   bool ValidateAddressToken(absl::string_view /*token*/) const override { | 
 |     QUICHE_DCHECK(false); | 
 |     return false; | 
 |   } | 
 |  | 
 |   const CachedNetworkParameters* PreviousCachedNetworkParams() const override { | 
 |     QUICHE_DCHECK(false); | 
 |     return nullptr; | 
 |   } | 
 |  | 
 |   void SetPreviousCachedNetworkParams( | 
 |       CachedNetworkParameters /*cached_network_params*/) override { | 
 |     QUICHE_DCHECK(false); | 
 |   } | 
 | }; | 
 |  | 
 | class QUIC_EXPORT_PRIVATE QuicCryptoClientStream | 
 |     : public QuicCryptoClientStreamBase { | 
 |  public: | 
 |   // kMaxClientHellos is the maximum number of times that we'll send a client | 
 |   // hello. The value 4 accounts for: | 
 |   //   * One failure due to an incorrect or missing source-address token. | 
 |   //   * One failure due the server's certificate chain being unavailible and | 
 |   //     the server being unwilling to send it without a valid source-address | 
 |   //     token. | 
 |   //   * One failure due to the ServerConfig private key being located on a | 
 |   //     remote oracle which has become unavailable, forcing the server to send | 
 |   //     the client a fallback ServerConfig. | 
 |   static const int kMaxClientHellos = 4; | 
 |  | 
 |   // QuicCryptoClientStream creates a HandshakerInterface at construction time | 
 |   // based on the QuicTransportVersion of the connection. Different | 
 |   // HandshakerInterfaces provide implementations of different crypto handshake | 
 |   // protocols. Currently QUIC crypto is the only protocol implemented; a future | 
 |   // HandshakerInterface will use TLS as the handshake protocol. | 
 |   // QuicCryptoClientStream delegates all of its public methods to its | 
 |   // HandshakerInterface. | 
 |   // | 
 |   // This setup of the crypto stream delegating its implementation to the | 
 |   // handshaker results in the handshaker reading and writing bytes on the | 
 |   // crypto stream, instead of the handshaker passing the stream bytes to send. | 
 |   class QUIC_EXPORT_PRIVATE HandshakerInterface { | 
 |    public: | 
 |     virtual ~HandshakerInterface() {} | 
 |  | 
 |     // Performs a crypto handshake with the server. Returns true if the | 
 |     // connection is still connected. | 
 |     virtual bool CryptoConnect() = 0; | 
 |  | 
 |     // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or | 
 |     // ReceivedInchoateReject instead. | 
 |     // | 
 |     // num_sent_client_hellos returns the number of client hello messages that | 
 |     // have been sent. If the handshake has completed then this is one greater | 
 |     // than the number of round-trips needed for the handshake. | 
 |     virtual int num_sent_client_hellos() const = 0; | 
 |  | 
 |     // Returns true if the handshake performed was a resumption instead of a | 
 |     // full handshake. Resumption only makes sense for TLS handshakes - there is | 
 |     // no concept of resumption for QUIC crypto even though it supports a 0-RTT | 
 |     // handshake. This function only returns valid results once the handshake is | 
 |     // complete. | 
 |     virtual bool IsResumption() const = 0; | 
 |  | 
 |     // Returns true if early data (0-RTT) was accepted in the connection. | 
 |     virtual bool EarlyDataAccepted() const = 0; | 
 |  | 
 |     // Returns the ssl_early_data_reason_t describing why 0-RTT was accepted or | 
 |     // rejected. | 
 |     virtual ssl_early_data_reason_t EarlyDataReason() const = 0; | 
 |  | 
 |     // Returns true if the client received an inchoate REJ during the handshake, | 
 |     // extending the handshake by one round trip. This only applies for QUIC | 
 |     // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet, | 
 |     // but that is handled at the connection layer instead of the crypto layer. | 
 |     virtual bool ReceivedInchoateReject() const = 0; | 
 |  | 
 |     // The number of server config update messages received by the | 
 |     // client.  Does not count update messages that were received prior | 
 |     // to handshake confirmation. | 
 |     virtual int num_scup_messages_received() const = 0; | 
 |  | 
 |     virtual std::string chlo_hash() const = 0; | 
 |  | 
 |     // Returns true once any encrypter (initial/0RTT or final/1RTT) has been set | 
 |     // for the connection. | 
 |     virtual bool encryption_established() const = 0; | 
 |  | 
 |     // Returns true once 1RTT keys are available. | 
 |     virtual bool one_rtt_keys_available() const = 0; | 
 |  | 
 |     // Returns the parameters negotiated in the crypto handshake. | 
 |     virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params() | 
 |         const = 0; | 
 |  | 
 |     // Used by QuicCryptoStream to parse data received on this stream. | 
 |     virtual CryptoMessageParser* crypto_message_parser() = 0; | 
 |  | 
 |     // Used by QuicCryptoStream to know how much unprocessed data can be | 
 |     // buffered at each encryption level. | 
 |     virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0; | 
 |  | 
 |     // Returns whether the implementation supports key update. | 
 |     virtual bool KeyUpdateSupportedLocally() const = 0; | 
 |  | 
 |     // Called to generate a decrypter for the next key phase. Each call should | 
 |     // generate the key for phase n+1. | 
 |     virtual std::unique_ptr<QuicDecrypter> | 
 |     AdvanceKeysAndCreateCurrentOneRttDecrypter() = 0; | 
 |  | 
 |     // Called to generate an encrypter for the same key phase of the last | 
 |     // decrypter returned by AdvanceKeysAndCreateCurrentOneRttDecrypter(). | 
 |     virtual std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() = 0; | 
 |  | 
 |     // Returns current handshake state. | 
 |     virtual HandshakeState GetHandshakeState() const = 0; | 
 |  | 
 |     // Called when a 1RTT packet has been acknowledged. | 
 |     virtual void OnOneRttPacketAcknowledged() = 0; | 
 |  | 
 |     // Called when a packet of ENCRYPTION_HANDSHAKE gets sent. | 
 |     virtual void OnHandshakePacketSent() = 0; | 
 |  | 
 |     // Called when connection gets closed. | 
 |     virtual void OnConnectionClosed(QuicErrorCode error, | 
 |                                     ConnectionCloseSource source) = 0; | 
 |  | 
 |     // Called when handshake done has been received. | 
 |     virtual void OnHandshakeDoneReceived() = 0; | 
 |  | 
 |     // Called when new token has been received. | 
 |     virtual void OnNewTokenReceived(absl::string_view token) = 0; | 
 |  | 
 |     // Called when application state is received. | 
 |     virtual void SetServerApplicationStateForResumption( | 
 |         std::unique_ptr<ApplicationState> application_state) = 0; | 
 |  | 
 |     // Called to obtain keying material export of length |result_len| with the | 
 |     // given |label| and |context|. Returns false on failure. | 
 |     virtual bool ExportKeyingMaterial(absl::string_view label, | 
 |                                       absl::string_view context, | 
 |                                       size_t result_len, | 
 |                                       std::string* result) = 0; | 
 |   }; | 
 |  | 
 |   // ProofHandler is an interface that handles callbacks from the crypto | 
 |   // stream when the client has proof verification details of the server. | 
 |   class QUIC_EXPORT_PRIVATE ProofHandler { | 
 |    public: | 
 |     virtual ~ProofHandler() {} | 
 |  | 
 |     // Called when the proof in |cached| is marked valid.  If this is a secure | 
 |     // QUIC session, then this will happen only after the proof verifier | 
 |     // completes. | 
 |     virtual void OnProofValid( | 
 |         const QuicCryptoClientConfig::CachedState& cached) = 0; | 
 |  | 
 |     // Called when proof verification details become available, either because | 
 |     // proof verification is complete, or when cached details are used. This | 
 |     // will only be called for secure QUIC connections. | 
 |     virtual void OnProofVerifyDetailsAvailable( | 
 |         const ProofVerifyDetails& verify_details) = 0; | 
 |   }; | 
 |  | 
 |   QuicCryptoClientStream(const QuicServerId& server_id, | 
 |                          QuicSession* session, | 
 |                          std::unique_ptr<ProofVerifyContext> verify_context, | 
 |                          QuicCryptoClientConfig* crypto_config, | 
 |                          ProofHandler* proof_handler, | 
 |                          bool has_application_state); | 
 |   QuicCryptoClientStream(const QuicCryptoClientStream&) = delete; | 
 |   QuicCryptoClientStream& operator=(const QuicCryptoClientStream&) = delete; | 
 |  | 
 |   ~QuicCryptoClientStream() override; | 
 |  | 
 |   // From QuicCryptoClientStreamBase | 
 |   bool CryptoConnect() override; | 
 |   int num_sent_client_hellos() const override; | 
 |   bool IsResumption() const override; | 
 |   bool EarlyDataAccepted() const override; | 
 |   ssl_early_data_reason_t EarlyDataReason() const override; | 
 |   bool ReceivedInchoateReject() const override; | 
 |  | 
 |   int num_scup_messages_received() const override; | 
 |  | 
 |   // From QuicCryptoStream | 
 |   bool encryption_established() const override; | 
 |   bool one_rtt_keys_available() const override; | 
 |   const QuicCryptoNegotiatedParameters& crypto_negotiated_params() | 
 |       const override; | 
 |   CryptoMessageParser* crypto_message_parser() override; | 
 |   void OnPacketDecrypted(EncryptionLevel /*level*/) override {} | 
 |   void OnOneRttPacketAcknowledged() override; | 
 |   void OnHandshakePacketSent() override; | 
 |   void OnConnectionClosed(QuicErrorCode error, | 
 |                           ConnectionCloseSource source) override; | 
 |   void OnHandshakeDoneReceived() override; | 
 |   void OnNewTokenReceived(absl::string_view token) override; | 
 |   HandshakeState GetHandshakeState() const override; | 
 |   void SetServerApplicationStateForResumption( | 
 |       std::unique_ptr<ApplicationState> application_state) override; | 
 |   size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; | 
 |   bool KeyUpdateSupportedLocally() const override; | 
 |   std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter() | 
 |       override; | 
 |   std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override; | 
 |   SSL* GetSsl() const override; | 
 |   bool ExportKeyingMaterial(absl::string_view label, absl::string_view context, | 
 |                             size_t result_len, std::string* result) override; | 
 |   std::string chlo_hash() const; | 
 |  | 
 |  protected: | 
 |   void set_handshaker(std::unique_ptr<HandshakerInterface> handshaker) { | 
 |     handshaker_ = std::move(handshaker); | 
 |   } | 
 |  | 
 |  private: | 
 |   friend class test::QuicCryptoClientStreamPeer; | 
 |   std::unique_ptr<HandshakerInterface> handshaker_; | 
 |   // Points to |handshaker_| if it uses TLS1.3. Otherwise, nullptr. | 
 |   // TODO(danzh) change the type of |handshaker_| to TlsClientHandshaker after | 
 |   // deprecating Google QUIC. | 
 |   TlsClientHandshaker* tls_handshaker_{nullptr}; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ |