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_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ |
| 6 | #define QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ |
| 7 | |
| 8 | #include <cstdint> |
| 9 | #include <memory> |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 10 | #include <string> |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 11 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 12 | #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h" |
| 13 | #include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h" |
| 14 | #include "net/third_party/quiche/src/quic/core/quic_config.h" |
| 15 | #include "net/third_party/quiche/src/quic/core/quic_crypto_handshaker.h" |
| 16 | #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" |
| 17 | #include "net/third_party/quiche/src/quic/core/quic_server_id.h" |
| 18 | #include "net/third_party/quiche/src/quic/core/quic_session.h" |
renjietang | f21e385 | 2020-04-13 15:45:39 -0700 | [diff] [blame] | 19 | #include "net/third_party/quiche/src/quic/core/quic_versions.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 20 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 21 | |
| 22 | namespace quic { |
| 23 | |
nharper | 1e32f4f | 2020-04-20 12:23:01 -0700 | [diff] [blame] | 24 | namespace test { |
| 25 | class QuicCryptoClientStreamPeer; |
| 26 | } // namespace test |
| 27 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 28 | class QUIC_EXPORT_PRIVATE QuicCryptoClientStreamBase : public QuicCryptoStream { |
| 29 | public: |
| 30 | explicit QuicCryptoClientStreamBase(QuicSession* session); |
| 31 | |
| 32 | ~QuicCryptoClientStreamBase() override {} |
| 33 | |
| 34 | // Performs a crypto handshake with the server. Returns true if the connection |
| 35 | // is still connected. |
| 36 | virtual bool CryptoConnect() = 0; |
| 37 | |
nharper | 4084fc9 | 2020-02-10 14:43:35 -0800 | [diff] [blame] | 38 | // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or |
| 39 | // ReceivedInchoateReject instead. |
| 40 | // |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 41 | // num_sent_client_hellos returns the number of client hello messages that |
| 42 | // have been sent. If the handshake has completed then this is one greater |
| 43 | // than the number of round-trips needed for the handshake. |
| 44 | virtual int num_sent_client_hellos() const = 0; |
| 45 | |
nharper | 0270396 | 2019-11-07 12:23:13 -0800 | [diff] [blame] | 46 | // Returns true if the handshake performed was a resumption instead of a full |
| 47 | // handshake. Resumption only makes sense for TLS handshakes - there is no |
| 48 | // concept of resumption for QUIC crypto even though it supports a 0-RTT |
| 49 | // handshake. This function only returns valid results once the handshake is |
| 50 | // complete. |
| 51 | virtual bool IsResumption() const = 0; |
| 52 | |
nharper | 4084fc9 | 2020-02-10 14:43:35 -0800 | [diff] [blame] | 53 | // Returns true if early data (0-RTT) was accepted in the connection. |
| 54 | virtual bool EarlyDataAccepted() const = 0; |
| 55 | |
| 56 | // Returns true if the client received an inchoate REJ during the handshake, |
| 57 | // extending the handshake by one round trip. This only applies for QUIC |
| 58 | // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet, |
| 59 | // but that is handled at the connection layer instead of the crypto layer. |
| 60 | virtual bool ReceivedInchoateReject() const = 0; |
| 61 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 62 | // The number of server config update messages received by the |
| 63 | // client. Does not count update messages that were received prior |
| 64 | // to handshake confirmation. |
| 65 | virtual int num_scup_messages_received() const = 0; |
| 66 | }; |
| 67 | |
| 68 | class QUIC_EXPORT_PRIVATE QuicCryptoClientStream |
| 69 | : public QuicCryptoClientStreamBase { |
| 70 | public: |
| 71 | // kMaxClientHellos is the maximum number of times that we'll send a client |
QUICHE team | 8b353f3 | 2019-04-09 13:49:10 -0700 | [diff] [blame] | 72 | // hello. The value 4 accounts for: |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 73 | // * One failure due to an incorrect or missing source-address token. |
| 74 | // * One failure due the server's certificate chain being unavailible and |
| 75 | // the server being unwilling to send it without a valid source-address |
| 76 | // token. |
QUICHE team | 8b353f3 | 2019-04-09 13:49:10 -0700 | [diff] [blame] | 77 | // * One failure due to the ServerConfig private key being located on a |
| 78 | // remote oracle which has become unavailable, forcing the server to send |
| 79 | // the client a fallback ServerConfig. |
| 80 | static const int kMaxClientHellos = 4; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 81 | |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 82 | // QuicCryptoClientStream creates a HandshakerInterface at construction time |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 83 | // based on the QuicTransportVersion of the connection. Different |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 84 | // HandshakerInterfaces provide implementations of different crypto handshake |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 85 | // protocols. Currently QUIC crypto is the only protocol implemented; a future |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 86 | // HandshakerInterface will use TLS as the handshake protocol. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 87 | // QuicCryptoClientStream delegates all of its public methods to its |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 88 | // HandshakerInterface. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 89 | // |
| 90 | // This setup of the crypto stream delegating its implementation to the |
| 91 | // handshaker results in the handshaker reading and writing bytes on the |
| 92 | // crypto stream, instead of the handshaker passing the stream bytes to send. |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 93 | class QUIC_EXPORT_PRIVATE HandshakerInterface { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 94 | public: |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 95 | virtual ~HandshakerInterface() {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 96 | |
| 97 | // Performs a crypto handshake with the server. Returns true if the |
| 98 | // connection is still connected. |
| 99 | virtual bool CryptoConnect() = 0; |
| 100 | |
nharper | 4084fc9 | 2020-02-10 14:43:35 -0800 | [diff] [blame] | 101 | // DEPRECATED: Use IsResumption, EarlyDataAccepted, and/or |
| 102 | // ReceivedInchoateReject instead. |
| 103 | // |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 104 | // num_sent_client_hellos returns the number of client hello messages that |
| 105 | // have been sent. If the handshake has completed then this is one greater |
| 106 | // than the number of round-trips needed for the handshake. |
| 107 | virtual int num_sent_client_hellos() const = 0; |
| 108 | |
nharper | 0270396 | 2019-11-07 12:23:13 -0800 | [diff] [blame] | 109 | // Returns true if the handshake performed was a resumption instead of a |
| 110 | // full handshake. Resumption only makes sense for TLS handshakes - there is |
| 111 | // no concept of resumption for QUIC crypto even though it supports a 0-RTT |
| 112 | // handshake. This function only returns valid results once the handshake is |
| 113 | // complete. |
| 114 | virtual bool IsResumption() const = 0; |
| 115 | |
nharper | 4084fc9 | 2020-02-10 14:43:35 -0800 | [diff] [blame] | 116 | // Returns true if early data (0-RTT) was accepted in the connection. |
| 117 | virtual bool EarlyDataAccepted() const = 0; |
| 118 | |
| 119 | // Returns true if the client received an inchoate REJ during the handshake, |
| 120 | // extending the handshake by one round trip. This only applies for QUIC |
| 121 | // crypto handshakes. The equivalent feature in IETF QUIC is a Retry packet, |
| 122 | // but that is handled at the connection layer instead of the crypto layer. |
| 123 | virtual bool ReceivedInchoateReject() const = 0; |
| 124 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 125 | // The number of server config update messages received by the |
| 126 | // client. Does not count update messages that were received prior |
| 127 | // to handshake confirmation. |
| 128 | virtual int num_scup_messages_received() const = 0; |
| 129 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 130 | virtual std::string chlo_hash() const = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 131 | |
| 132 | // Returns true once any encrypter (initial/0RTT or final/1RTT) has been set |
| 133 | // for the connection. |
| 134 | virtual bool encryption_established() const = 0; |
| 135 | |
fayang | 685367a | 2020-01-14 10:40:15 -0800 | [diff] [blame] | 136 | // Returns true once 1RTT keys are available. |
| 137 | virtual bool one_rtt_keys_available() const = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 138 | |
| 139 | // Returns the parameters negotiated in the crypto handshake. |
| 140 | virtual const QuicCryptoNegotiatedParameters& crypto_negotiated_params() |
| 141 | const = 0; |
| 142 | |
| 143 | // Used by QuicCryptoStream to parse data received on this stream. |
| 144 | virtual CryptoMessageParser* crypto_message_parser() = 0; |
nharper | 486a8a9 | 2019-08-28 16:25:10 -0700 | [diff] [blame] | 145 | |
| 146 | // Used by QuicCryptoStream to know how much unprocessed data can be |
| 147 | // buffered at each encryption level. |
| 148 | virtual size_t BufferSizeLimitForLevel(EncryptionLevel level) const = 0; |
fayang | 9a863cf | 2020-01-16 14:12:11 -0800 | [diff] [blame] | 149 | |
| 150 | // Returns current handshake state. |
| 151 | virtual HandshakeState GetHandshakeState() const = 0; |
fayang | 0106294 | 2020-01-22 07:23:23 -0800 | [diff] [blame] | 152 | |
fayang | 2f2915d | 2020-01-24 06:47:15 -0800 | [diff] [blame] | 153 | // Called when a 1RTT packet has been acknowledged. |
| 154 | virtual void OnOneRttPacketAcknowledged() = 0; |
| 155 | |
fayang | 44ae4e9 | 2020-04-28 13:09:42 -0700 | [diff] [blame] | 156 | // Called when a packet of ENCRYPTION_HANDSHAKE gets sent. |
| 157 | virtual void OnHandshakePacketSent() = 0; |
| 158 | |
fayang | a6a85a8 | 2020-05-04 08:58:53 -0700 | [diff] [blame] | 159 | // Called when connection gets closed. |
| 160 | virtual void OnConnectionClosed(QuicErrorCode error, |
| 161 | ConnectionCloseSource source) = 0; |
| 162 | |
fayang | 0106294 | 2020-01-22 07:23:23 -0800 | [diff] [blame] | 163 | // Called when handshake done has been received. |
| 164 | virtual void OnHandshakeDoneReceived() = 0; |
renjietang | f21e385 | 2020-04-13 15:45:39 -0700 | [diff] [blame] | 165 | |
| 166 | // Called when application state is received. |
nharper | ac52a86 | 2020-06-08 12:41:06 -0700 | [diff] [blame] | 167 | virtual void SetServerApplicationStateForResumption( |
renjietang | f21e385 | 2020-04-13 15:45:39 -0700 | [diff] [blame] | 168 | std::unique_ptr<ApplicationState> application_state) = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 169 | }; |
| 170 | |
| 171 | // ProofHandler is an interface that handles callbacks from the crypto |
| 172 | // stream when the client has proof verification details of the server. |
| 173 | class QUIC_EXPORT_PRIVATE ProofHandler { |
| 174 | public: |
| 175 | virtual ~ProofHandler() {} |
| 176 | |
| 177 | // Called when the proof in |cached| is marked valid. If this is a secure |
| 178 | // QUIC session, then this will happen only after the proof verifier |
| 179 | // completes. |
| 180 | virtual void OnProofValid( |
| 181 | const QuicCryptoClientConfig::CachedState& cached) = 0; |
| 182 | |
| 183 | // Called when proof verification details become available, either because |
| 184 | // proof verification is complete, or when cached details are used. This |
| 185 | // will only be called for secure QUIC connections. |
| 186 | virtual void OnProofVerifyDetailsAvailable( |
| 187 | const ProofVerifyDetails& verify_details) = 0; |
| 188 | }; |
| 189 | |
| 190 | QuicCryptoClientStream(const QuicServerId& server_id, |
| 191 | QuicSession* session, |
| 192 | std::unique_ptr<ProofVerifyContext> verify_context, |
| 193 | QuicCryptoClientConfig* crypto_config, |
renjietang | bcc066a | 2020-04-21 18:05:57 -0700 | [diff] [blame] | 194 | ProofHandler* proof_handler, |
| 195 | bool has_application_state); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 196 | QuicCryptoClientStream(const QuicCryptoClientStream&) = delete; |
| 197 | QuicCryptoClientStream& operator=(const QuicCryptoClientStream&) = delete; |
| 198 | |
| 199 | ~QuicCryptoClientStream() override; |
| 200 | |
| 201 | // From QuicCryptoClientStreamBase |
| 202 | bool CryptoConnect() override; |
| 203 | int num_sent_client_hellos() const override; |
nharper | 0270396 | 2019-11-07 12:23:13 -0800 | [diff] [blame] | 204 | bool IsResumption() const override; |
nharper | 4084fc9 | 2020-02-10 14:43:35 -0800 | [diff] [blame] | 205 | bool EarlyDataAccepted() const override; |
| 206 | bool ReceivedInchoateReject() const override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 207 | |
| 208 | int num_scup_messages_received() const override; |
| 209 | |
| 210 | // From QuicCryptoStream |
| 211 | bool encryption_established() const override; |
fayang | 685367a | 2020-01-14 10:40:15 -0800 | [diff] [blame] | 212 | bool one_rtt_keys_available() const override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 213 | const QuicCryptoNegotiatedParameters& crypto_negotiated_params() |
| 214 | const override; |
| 215 | CryptoMessageParser* crypto_message_parser() override; |
fayang | d58736d | 2019-11-27 13:35:31 -0800 | [diff] [blame] | 216 | void OnPacketDecrypted(EncryptionLevel /*level*/) override {} |
fayang | 2f2915d | 2020-01-24 06:47:15 -0800 | [diff] [blame] | 217 | void OnOneRttPacketAcknowledged() override; |
fayang | 44ae4e9 | 2020-04-28 13:09:42 -0700 | [diff] [blame] | 218 | void OnHandshakePacketSent() override; |
fayang | a6a85a8 | 2020-05-04 08:58:53 -0700 | [diff] [blame] | 219 | void OnConnectionClosed(QuicErrorCode error, |
| 220 | ConnectionCloseSource source) override; |
fayang | 0106294 | 2020-01-22 07:23:23 -0800 | [diff] [blame] | 221 | void OnHandshakeDoneReceived() override; |
fayang | 9a863cf | 2020-01-16 14:12:11 -0800 | [diff] [blame] | 222 | HandshakeState GetHandshakeState() const override; |
nharper | ac52a86 | 2020-06-08 12:41:06 -0700 | [diff] [blame] | 223 | void SetServerApplicationStateForResumption( |
renjietang | f21e385 | 2020-04-13 15:45:39 -0700 | [diff] [blame] | 224 | std::unique_ptr<ApplicationState> application_state) override; |
nharper | ac52a86 | 2020-06-08 12:41:06 -0700 | [diff] [blame] | 225 | size_t BufferSizeLimitForLevel(EncryptionLevel level) const override; |
renjietang | f21e385 | 2020-04-13 15:45:39 -0700 | [diff] [blame] | 226 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 227 | std::string chlo_hash() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 228 | |
| 229 | protected: |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 230 | void set_handshaker(std::unique_ptr<HandshakerInterface> handshaker) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 231 | handshaker_ = std::move(handshaker); |
| 232 | } |
| 233 | |
| 234 | private: |
nharper | 1e32f4f | 2020-04-20 12:23:01 -0700 | [diff] [blame] | 235 | friend class test::QuicCryptoClientStreamPeer; |
rch | 85240a1 | 2019-12-23 11:51:59 -0800 | [diff] [blame] | 236 | std::unique_ptr<HandshakerInterface> handshaker_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 237 | }; |
| 238 | |
| 239 | } // namespace quic |
| 240 | |
| 241 | #endif // QUICHE_QUIC_CORE_QUIC_CRYPTO_CLIENT_STREAM_H_ |