• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
6 #define QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
7 
8 #include <cstdint>
9 #include <memory>
10 #include <string>
11 
12 #include "quiche/quic/core/crypto/proof_verifier.h"
13 #include "quiche/quic/core/crypto/quic_crypto_client_config.h"
14 #include "quiche/quic/core/proto/cached_network_parameters_proto.h"
15 #include "quiche/quic/core/quic_config.h"
16 #include "quiche/quic/core/quic_crypto_handshaker.h"
17 #include "quiche/quic/core/quic_crypto_stream.h"
18 #include "quiche/quic/core/quic_server_id.h"
19 #include "quiche/quic/core/quic_session.h"
20 #include "quiche/quic/core/quic_types.h"
21 #include "quiche/quic/core/quic_versions.h"
22 #include "quiche/quic/platform/api/quic_export.h"
23 
24 namespace quic {
25 
26 namespace test {
27 class QuicCryptoClientStreamPeer;
28 }  // namespace test
29 
30 class TlsClientHandshaker;
31 
32 class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream {
33  public:
34   explicit QuicCryptoClientStreamBase(QuicSession* session);
35 
~QuicCryptoClientStreamBase()36   ~QuicCryptoClientStreamBase() override {}
37 
38   // Performs a crypto handshake with the server. Returns true if the connection
39   // is still connected.
40   virtual bool CryptoConnect() = 0;
41 
42   // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or
43   // ReceivedInchoateReject instead.
44   //
45   // num_sent_client_hellos returns the number of client hello messages that
46   // have been sent. If the handshake has completed then this is one greater
47   // than the number of round-trips needed for the handshake.
48   virtual int num_sent_client_hellos() const = 0;
49 
50   // Returns true if the handshake performed was a resumption instead of a full
51   // handshake. Resumption only makes sense for TLS handshakes - there is no
52   // concept of resumption for QUIC crypto even though it supports a 0-RTT
53   // handshake. This function only returns valid results once the handshake is
54   // complete.
55   virtual bool IsResumption() const = 0;
56 
57   // Returns true if early data (0-RTT) was accepted in the connection.
58   virtual bool EarlyDataAccepted() const = 0;
59 
60   // Returns true if the client received an inchoate REJ during the handshake,
61   // extending the handshake by one round trip. This only applies for QUIC
62   // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet,
63   // but that is handled at the connection layer instead of the crypto layer.
64   virtual bool ReceivedInchoateReject() const = 0;
65 
66   // The number of server config update messages received by the
67   // client.  Does not count update messages that were received prior
68   // to handshake confirmation.
69   virtual int num_scup_messages_received() const = 0;
70 
ExportKeyingMaterial(absl::string_view,absl::string_view,size_t,std::string *)71   bool ExportKeyingMaterial(absl::string_view /*label*/,
72                             absl::string_view /*context*/,
73                             size_t /*result_len*/,
74                             std::string* /*result*/) override {
75     QUICHE_NOTREACHED();
76     return false;
77   }
78 
GetAddressToken(const CachedNetworkParameters *)79   std::string GetAddressToken(
80       const CachedNetworkParameters* /*cached_network_params*/) const override {
81     QUICHE_DCHECK(false);
82     return "";
83   }
84 
ValidateAddressToken(absl::string_view)85   bool ValidateAddressToken(absl::string_view /*token*/) const override {
86     QUICHE_DCHECK(false);
87     return false;
88   }
89 
PreviousCachedNetworkParams()90   const CachedNetworkParameters* PreviousCachedNetworkParams() const override {
91     QUICHE_DCHECK(false);
92     return nullptr;
93   }
94 
SetPreviousCachedNetworkParams(CachedNetworkParameters)95   void SetPreviousCachedNetworkParams(
96       CachedNetworkParameters /*cached_network_params*/) override {
97     QUICHE_DCHECK(false);
98   }
99 };
100 
101 class QUIC_EXPORT_PRIVATE QuicCryptoClientStream
102     : public QuicCryptoClientStreamBase {
103  public:
104   // kMaxClientHellos is the maximum number of times that we'll send a client
105   // hello. The value 4 accounts for:
106   //   * One failure due to an incorrect or missing source-address token.
107   //   * One failure due the server's certificate chain being unavailible and
108   //     the server being unwilling to send it without a valid source-address
109   //     token.
110   //   * One failure due to the ServerConfig private key being located on a
111   //     remote oracle which has become unavailable, forcing the server to send
112   //     the client a fallback ServerConfig.
113   static const int kMaxClientHellos = 4;
114 
115   // QuicCryptoClientStream creates a HandshakerInterface at construction time
116   // based on the QuicTransportVersion of the connection. Different
117   // HandshakerInterfaces provide implementations of different crypto handshake
118   // protocols. Currently QUIC crypto is the only protocol implemented; a future
119   // HandshakerInterface will use TLS as the handshake protocol.
120   // QuicCryptoClientStream delegates all of its public methods to its
121   // HandshakerInterface.
122   //
123   // This setup of the crypto stream delegating its implementation to the
124   // handshaker results in the handshaker reading and writing bytes on the
125   // crypto stream, instead of the handshaker passing the stream bytes to send.
126   class QUIC_EXPORT_PRIVATE HandshakerInterface {
127    public:
~HandshakerInterface()128     virtual ~HandshakerInterface() {}
129 
130     // Performs a crypto handshake with the server. Returns true if the
131     // connection is still connected.
132     virtual bool CryptoConnect() = 0;
133 
134     // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or
135     // ReceivedInchoateReject instead.
136     //
137     // num_sent_client_hellos returns the number of client hello messages that
138     // have been sent. If the handshake has completed then this is one greater
139     // than the number of round-trips needed for the handshake.
140     virtual int num_sent_client_hellos() const = 0;
141 
142     // Returns true if the handshake performed was a resumption instead of a
143     // full handshake. Resumption only makes sense for TLS handshakes - there is
144     // no concept of resumption for QUIC crypto even though it supports a 0-RTT
145     // handshake. This function only returns valid results once the handshake is
146     // complete.
147     virtual bool IsResumption() const = 0;
148 
149     // Returns true if early data (0-RTT) was accepted in the connection.
150     virtual bool EarlyDataAccepted() const = 0;
151 
152     // Returns the ssl_early_data_reason_t describing why 0-RTT was accepted or
153     // rejected.
154     virtual ssl_early_data_reason_t EarlyDataReason() const = 0;
155 
156     // Returns true if the client received an inchoate REJ during the handshake,
157     // extending the handshake by one round trip. This only applies for QUIC
158     // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet,
159     // but that is handled at the connection layer instead of the crypto layer.
160     virtual bool ReceivedInchoateReject() const = 0;
161 
162     // The number of server config update messages received by the
163     // client.  Does not count update messages that were received prior
164     // to handshake confirmation.
165     virtual int num_scup_messages_received() const = 0;
166 
167     virtual std::string chlo_hash() const = 0;
168 
169     // Returns true once any encrypter (initial/0RTT or final/1RTT) has been set
170     // for the connection.
171     virtual bool encryption_established() const = 0;
172 
173     // Returns true if receiving CRYPTO_FRAME at encryption `level` is expected.
174     virtual bool IsCryptoFrameExpectedForEncryptionLevel(
175         EncryptionLevel level) const = 0;
176 
177     // Returns the encryption level to send CRYPTO_FRAME for `space`.
178     virtual EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace(
179         PacketNumberSpace space) const = 0;
180 
181     // Returns true once 1RTT keys are available.
182     virtual bool one_rtt_keys_available() const = 0;
183 
184     // Returns the parameters negotiated in the crypto handshake.
185     virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
186         const = 0;
187 
188     // Used by QuicCryptoStream to parse data received on this stream.
189     virtual CryptoMessageParser* crypto_message_parser() = 0;
190 
191     // Used by QuicCryptoStream to know how much unprocessed data can be
192     // buffered at each encryption level.
193     virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0;
194 
195     // Called to generate a decrypter for the next key phase. Each call should
196     // generate the key for phase n+1.
197     virtual std::unique_ptr<QuicDecrypter>
198     AdvanceKeysAndCreateCurrentOneRttDecrypter() = 0;
199 
200     // Called to generate an encrypter for the same key phase of the last
201     // decrypter returned by AdvanceKeysAndCreateCurrentOneRttDecrypter().
202     virtual std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() = 0;
203 
204     // Returns current handshake state.
205     virtual HandshakeState GetHandshakeState() const = 0;
206 
207     // Called when a 1RTT packet has been acknowledged.
208     virtual void OnOneRttPacketAcknowledged() = 0;
209 
210     // Called when a packet of ENCRYPTION_HANDSHAKE gets sent.
211     virtual void OnHandshakePacketSent() = 0;
212 
213     // Called when connection gets closed.
214     virtual void OnConnectionClosed(QuicErrorCode error,
215                                     ConnectionCloseSource source) = 0;
216 
217     // Called when handshake done has been received.
218     virtual void OnHandshakeDoneReceived() = 0;
219 
220     // Called when new token has been received.
221     virtual void OnNewTokenReceived(absl::string_view token) = 0;
222 
223     // Called when application state is received.
224     virtual void SetServerApplicationStateForResumption(
225         std::unique_ptr<ApplicationState> application_state) = 0;
226 
227     // Called to obtain keying material export of length |result_len| with the
228     // given |label| and |context|. Returns false on failure.
229     virtual bool ExportKeyingMaterial(absl::string_view label,
230                                       absl::string_view context,
231                                       size_t result_len,
232                                       std::string* result) = 0;
233   };
234 
235   // ProofHandler is an interface that handles callbacks from the crypto
236   // stream when the client has proof verification details of the server.
237   class QUIC_EXPORT_PRIVATE ProofHandler {
238    public:
~ProofHandler()239     virtual ~ProofHandler() {}
240 
241     // Called when the proof in |cached| is marked valid.  If this is a secure
242     // QUIC session, then this will happen only after the proof verifier
243     // completes.
244     virtual void OnProofValid(
245         const QuicCryptoClientConfig::CachedState& cached) = 0;
246 
247     // Called when proof verification details become available, either because
248     // proof verification is complete, or when cached details are used. This
249     // will only be called for secure QUIC connections.
250     virtual void OnProofVerifyDetailsAvailable(
251         const ProofVerifyDetails& verify_details) = 0;
252   };
253 
254   QuicCryptoClientStream(const QuicServerId& server_id, QuicSession* session,
255                          std::unique_ptr<ProofVerifyContext> verify_context,
256                          QuicCryptoClientConfig* crypto_config,
257                          ProofHandler* proof_handler,
258                          bool has_application_state);
259   QuicCryptoClientStream(const QuicCryptoClientStream&) = delete;
260   QuicCryptoClientStream& operator=(const QuicCryptoClientStream&) = delete;
261 
262   ~QuicCryptoClientStream() override;
263 
264   // From QuicCryptoClientStreamBase
265   bool CryptoConnect() override;
266   int num_sent_client_hellos() const override;
267   bool IsResumption() const override;
268   bool EarlyDataAccepted() const override;
269   ssl_early_data_reason_t EarlyDataReason() const override;
270   bool ReceivedInchoateReject() const override;
271 
272   int num_scup_messages_received() const override;
273 
274   // From QuicCryptoStream
275   bool encryption_established() const override;
276   bool one_rtt_keys_available() const override;
277   const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
278       const override;
279   CryptoMessageParser* crypto_message_parser() override;
OnPacketDecrypted(EncryptionLevel)280   void OnPacketDecrypted(EncryptionLevel /*level*/) override {}
281   void OnOneRttPacketAcknowledged() override;
282   void OnHandshakePacketSent() override;
283   void OnConnectionClosed(QuicErrorCode error,
284                           ConnectionCloseSource source) override;
285   void OnHandshakeDoneReceived() override;
286   void OnNewTokenReceived(absl::string_view token) override;
287   HandshakeState GetHandshakeState() const override;
288   void SetServerApplicationStateForResumption(
289       std::unique_ptr<ApplicationState> application_state) override;
290   size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
291   std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
292       override;
293   std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
294   SSL* GetSsl() const override;
295   bool IsCryptoFrameExpectedForEncryptionLevel(
296       EncryptionLevel level) const override;
297   EncryptionLevel GetEncryptionLevelToSendCryptoDataOfSpace(
298       PacketNumberSpace space) const override;
299 
300   bool ExportKeyingMaterial(absl::string_view label, absl::string_view context,
301                             size_t result_len, std::string* result) override;
302   std::string chlo_hash() const;
303 
304  protected:
set_handshaker(std::unique_ptr<HandshakerInterface> handshaker)305   void set_handshaker(std::unique_ptr<HandshakerInterface> handshaker) {
306     handshaker_ = std::move(handshaker);
307   }
308 
309  private:
310   friend class test::QuicCryptoClientStreamPeer;
311   std::unique_ptr<HandshakerInterface> handshaker_;
312   // Points to |handshaker_| if it uses TLS1.3. Otherwise, nullptr.
313   // TODO(danzh) change the type of |handshaker_| to TlsClientHandshaker after
314   // deprecating Google QUIC.
315   TlsClientHandshaker* tls_handshaker_{nullptr};
316 };
317 
318 }  // namespace quic
319 
320 #endif  // QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_
321