QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2017 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_TLS_HANDSHAKER_H_ |
| 6 | #define QUICHE_QUIC_CORE_TLS_HANDSHAKER_H_ |
| 7 | |
vasilvv | c872ee4 | 2020-10-07 19:50:22 -0700 | [diff] [blame] | 8 | #include "absl/strings/string_view.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 9 | #include "third_party/boringssl/src/include/openssl/base.h" |
| 10 | #include "third_party/boringssl/src/include/openssl/ssl.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 11 | #include "quic/core/crypto/crypto_handshake.h" |
| 12 | #include "quic/core/crypto/crypto_message_parser.h" |
| 13 | #include "quic/core/crypto/proof_verifier.h" |
| 14 | #include "quic/core/crypto/quic_decrypter.h" |
| 15 | #include "quic/core/crypto/quic_encrypter.h" |
| 16 | #include "quic/core/crypto/tls_connection.h" |
| 17 | #include "quic/core/quic_session.h" |
| 18 | #include "quic/platform/api/quic_export.h" |
wub | fa47a6d | 2021-04-16 08:56:26 -0700 | [diff] [blame] | 19 | #include "quic/platform/api/quic_flags.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 20 | |
| 21 | namespace quic { |
| 22 | |
| 23 | class QuicCryptoStream; |
| 24 | |
| 25 | // Base class for TlsClientHandshaker and TlsServerHandshaker. TlsHandshaker |
| 26 | // provides functionality common to both the client and server, such as moving |
| 27 | // messages between the TLS stack and the QUIC crypto stream, and handling |
| 28 | // derivation of secrets. |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 29 | class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate, |
| 30 | public CryptoMessageParser { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 31 | public: |
| 32 | // TlsHandshaker does not take ownership of any of its arguments; they must |
| 33 | // outlive the TlsHandshaker. |
nharper | 80d3b17 | 2020-01-17 11:43:39 -0800 | [diff] [blame] | 34 | TlsHandshaker(QuicCryptoStream* stream, QuicSession* session); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 35 | TlsHandshaker(const TlsHandshaker&) = delete; |
| 36 | TlsHandshaker& operator=(const TlsHandshaker&) = delete; |
| 37 | |
| 38 | ~TlsHandshaker() override; |
| 39 | |
| 40 | // From CryptoMessageParser |
vasilvv | c872ee4 | 2020-10-07 19:50:22 -0700 | [diff] [blame] | 41 | bool ProcessInput(absl::string_view input, EncryptionLevel level) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 42 | size_t InputBytesRemaining() const override { return 0; } |
| 43 | QuicErrorCode error() const override { return parser_error_; } |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 44 | const std::string& error_detail() const override { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 45 | return parser_error_detail_; |
| 46 | } |
| 47 | |
nharper | 82bea25 | 2020-09-16 16:18:49 -0700 | [diff] [blame] | 48 | // The following methods provide implementations to subclasses of |
| 49 | // TlsHandshaker which use them to implement methods of QuicCryptoStream. |
| 50 | CryptoMessageParser* crypto_message_parser() { return this; } |
nharper | 486a8a9 | 2019-08-28 16:25:10 -0700 | [diff] [blame] | 51 | size_t BufferSizeLimitForLevel(EncryptionLevel level) const; |
nharper | 6a6bd31 | 2020-09-17 13:20:53 -0700 | [diff] [blame] | 52 | ssl_early_data_reason_t EarlyDataReason() const; |
mattm | 072a7e3 | 2020-10-09 16:16:56 -0700 | [diff] [blame] | 53 | std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter(); |
| 54 | std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter(); |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 55 | virtual HandshakeState GetHandshakeState() const = 0; |
haoyuewang | f88c4a5 | 2021-10-04 15:21:37 -0700 | [diff] [blame] | 56 | bool ExportKeyingMaterialForLabel(absl::string_view label, |
| 57 | absl::string_view context, |
| 58 | size_t result_len, std::string* result); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 59 | |
| 60 | protected: |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 61 | // Called when a new message is received on the crypto stream and is available |
| 62 | // for the TLS stack to read. |
QUICHE team | 4f1e2f9 | 2021-06-14 15:18:50 -0700 | [diff] [blame] | 63 | virtual void AdvanceHandshake(); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 64 | |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 65 | void CloseConnection(QuicErrorCode error, const std::string& reason_phrase); |
mattm | 55006b0 | 2021-01-14 15:09:54 -0800 | [diff] [blame] | 66 | // Closes the connection, specifying the wire error code |ietf_error| |
| 67 | // explicitly. |
| 68 | void CloseConnection(QuicErrorCode error, |
| 69 | QuicIetfTransportErrorCodes ietf_error, |
| 70 | const std::string& reason_phrase); |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 71 | |
| 72 | void OnConnectionClosed(QuicErrorCode error, ConnectionCloseSource source); |
| 73 | |
| 74 | bool is_connection_closed() const { return is_connection_closed_; } |
| 75 | |
| 76 | // Called when |SSL_do_handshake| returns 1, indicating that the handshake has |
wub | bebae4a | 2021-06-28 09:41:11 -0700 | [diff] [blame] | 77 | // finished. Note that a handshake only finishes once, entering early data |
| 78 | // does not count. |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 79 | virtual void FinishHandshake() = 0; |
| 80 | |
wub | 48b1681 | 2021-04-30 10:22:22 -0700 | [diff] [blame] | 81 | // Called when |SSL_do_handshake| returns 1 and the connection is in early |
| 82 | // data. In that case, |AdvanceHandshake| will call |OnEnterEarlyData| and |
| 83 | // retry |SSL_do_handshake| once. |
| 84 | virtual void OnEnterEarlyData() { |
| 85 | // By default, do nothing but check the preconditions. |
wub | 48b1681 | 2021-04-30 10:22:22 -0700 | [diff] [blame] | 86 | QUICHE_DCHECK(SSL_in_early_data(ssl())); |
| 87 | } |
| 88 | |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 89 | // Called when a handshake message is received after the handshake is |
| 90 | // complete. |
| 91 | virtual void ProcessPostHandshakeMessage() = 0; |
| 92 | |
| 93 | // Called when an unexpected error code is received from |SSL_get_error|. If a |
| 94 | // subclass can expect more than just a single error (as provided by |
| 95 | // |set_expected_ssl_error|), it can override this method to handle that case. |
| 96 | virtual bool ShouldCloseConnectionOnUnexpectedError(int ssl_error); |
| 97 | |
| 98 | void set_expected_ssl_error(int ssl_error) { |
| 99 | expected_ssl_error_ = ssl_error; |
| 100 | } |
| 101 | int expected_ssl_error() const { return expected_ssl_error_; } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 102 | |
wub | 5b786df | 2021-12-01 15:11:38 -0800 | [diff] [blame] | 103 | // Called to verify a cert chain. This can be implemented as a simple wrapper |
| 104 | // around ProofVerifier, which optionally gathers additional arguments to pass |
| 105 | // into their VerifyCertChain method. This class retains a non-owning pointer |
| 106 | // to |callback|; the callback must live until this function returns |
| 107 | // QUIC_SUCCESS or QUIC_FAILURE, or until the callback is run. |
nharper | 54fc9ab | 2020-11-12 11:07:39 -0800 | [diff] [blame] | 108 | // |
| 109 | // If certificate verification fails, |*out_alert| may be set to a TLS alert |
| 110 | // that will be sent when closing the connection; it defaults to |
| 111 | // certificate_unknown. Implementations of VerifyCertChain may retain the |
| 112 | // |out_alert| pointer while performing an async operation. |
nharper | e62aab7 | 2020-11-04 16:32:09 -0800 | [diff] [blame] | 113 | virtual QuicAsyncStatus VerifyCertChain( |
| 114 | const std::vector<std::string>& certs, |
| 115 | std::string* error_details, |
| 116 | std::unique_ptr<ProofVerifyDetails>* details, |
nharper | 54fc9ab | 2020-11-12 11:07:39 -0800 | [diff] [blame] | 117 | uint8_t* out_alert, |
nharper | e62aab7 | 2020-11-04 16:32:09 -0800 | [diff] [blame] | 118 | std::unique_ptr<ProofVerifierCallback> callback) = 0; |
| 119 | // Called when certificate verification is completed. |
| 120 | virtual void OnProofVerifyDetailsAvailable( |
| 121 | const ProofVerifyDetails& verify_details) = 0; |
| 122 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 123 | // Returns the PRF used by the cipher suite negotiated in the TLS handshake. |
nharper | 8d4ff5c | 2020-02-27 11:43:44 -0800 | [diff] [blame] | 124 | const EVP_MD* Prf(const SSL_CIPHER* cipher); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 125 | |
nharper | 486a8a9 | 2019-08-28 16:25:10 -0700 | [diff] [blame] | 126 | virtual const TlsConnection* tls_connection() const = 0; |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 127 | |
nharper | 486a8a9 | 2019-08-28 16:25:10 -0700 | [diff] [blame] | 128 | SSL* ssl() const { return tls_connection()->ssl(); } |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 129 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 130 | QuicCryptoStream* stream() { return stream_; } |
renjietang | bd33b62 | 2020-02-12 16:52:30 -0800 | [diff] [blame] | 131 | HandshakerDelegateInterface* handshaker_delegate() { |
| 132 | return handshaker_delegate_; |
| 133 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 134 | |
nharper | e62aab7 | 2020-11-04 16:32:09 -0800 | [diff] [blame] | 135 | enum ssl_verify_result_t VerifyCert(uint8_t* out_alert) override; |
| 136 | |
nharper | d08b82c | 2020-02-26 12:10:25 -0800 | [diff] [blame] | 137 | // SetWriteSecret provides the encryption secret used to encrypt messages at |
| 138 | // encryption level |level|. The secret provided here is the one from the TLS |
| 139 | // 1.3 key schedule (RFC 8446 section 7.1), in particular the handshake |
| 140 | // traffic secrets and application traffic secrets. The provided write secret |
| 141 | // must be used with the provided cipher suite |cipher|. |
| 142 | void SetWriteSecret(EncryptionLevel level, |
| 143 | const SSL_CIPHER* cipher, |
| 144 | const std::vector<uint8_t>& write_secret) override; |
| 145 | |
| 146 | // SetReadSecret is similar to SetWriteSecret, except that it is used for |
| 147 | // decrypting messages. SetReadSecret at a particular level is always called |
| 148 | // after SetWriteSecret for that level, except for ENCRYPTION_ZERO_RTT, where |
| 149 | // the EncryptionLevel for SetWriteSecret is ENCRYPTION_FORWARD_SECURE. |
| 150 | bool SetReadSecret(EncryptionLevel level, |
| 151 | const SSL_CIPHER* cipher, |
| 152 | const std::vector<uint8_t>& read_secret) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 153 | |
| 154 | // WriteMessage is called when there is |data| from the TLS stack ready for |
| 155 | // the QUIC stack to write in a crypto frame. The data must be transmitted at |
| 156 | // encryption level |level|. |
vasilvv | c872ee4 | 2020-10-07 19:50:22 -0700 | [diff] [blame] | 157 | void WriteMessage(EncryptionLevel level, absl::string_view data) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 158 | |
| 159 | // FlushFlight is called to signal that the current flight of |
| 160 | // messages have all been written (via calls to WriteMessage) and can be |
| 161 | // flushed to the underlying transport. |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 162 | void FlushFlight() override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 163 | |
| 164 | // SendAlert causes this TlsHandshaker to close the QUIC connection with an |
| 165 | // error code corresponding to the TLS alert description |desc|. |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 166 | void SendAlert(EncryptionLevel level, uint8_t desc) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 167 | |
wub | d9036e4 | 2021-08-02 20:59:15 -0700 | [diff] [blame] | 168 | // Informational callback from BoringSSL. Subclasses can override it to do |
| 169 | // logging, tracing, etc. |
| 170 | // See |SSL_CTX_set_info_callback| for the meaning of |type| and |value|. |
| 171 | void InfoCallback(int /*type*/, int /*value*/) override {} |
| 172 | |
nharper | 6ebe83b | 2019-06-13 17:43:52 -0700 | [diff] [blame] | 173 | private: |
nharper | e62aab7 | 2020-11-04 16:32:09 -0800 | [diff] [blame] | 174 | // ProofVerifierCallbackImpl handles the result of an asynchronous certificate |
| 175 | // verification operation. |
| 176 | class QUIC_EXPORT_PRIVATE ProofVerifierCallbackImpl |
| 177 | : public ProofVerifierCallback { |
| 178 | public: |
| 179 | explicit ProofVerifierCallbackImpl(TlsHandshaker* parent); |
| 180 | ~ProofVerifierCallbackImpl() override; |
| 181 | |
| 182 | // ProofVerifierCallback interface. |
| 183 | void Run(bool ok, |
| 184 | const std::string& error_details, |
| 185 | std::unique_ptr<ProofVerifyDetails>* details) override; |
| 186 | |
| 187 | // If called, Cancel causes the pending callback to be a no-op. |
| 188 | void Cancel(); |
| 189 | |
| 190 | private: |
| 191 | // Non-owning pointer to the TlsHandshaker responsible for this callback. |
| 192 | // |parent_| must be valid for the life of this callback or until |Cancel| |
| 193 | // is called. |
| 194 | TlsHandshaker* parent_; |
| 195 | }; |
| 196 | |
| 197 | // ProofVerifierCallback used for async certificate verification. Ownership of |
| 198 | // this object is transferred to |VerifyCertChain|; |
| 199 | ProofVerifierCallbackImpl* proof_verify_callback_ = nullptr; |
| 200 | std::unique_ptr<ProofVerifyDetails> verify_details_; |
| 201 | enum ssl_verify_result_t verify_result_ = ssl_verify_retry; |
nharper | 54fc9ab | 2020-11-12 11:07:39 -0800 | [diff] [blame] | 202 | uint8_t cert_verify_tls_alert_ = SSL_AD_CERTIFICATE_UNKNOWN; |
nharper | e62aab7 | 2020-11-04 16:32:09 -0800 | [diff] [blame] | 203 | std::string cert_verify_error_details_; |
| 204 | |
nharper | 0ab1c66 | 2020-11-02 17:05:32 -0800 | [diff] [blame] | 205 | int expected_ssl_error_ = SSL_ERROR_WANT_READ; |
| 206 | bool is_connection_closed_ = false; |
| 207 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 208 | QuicCryptoStream* stream_; |
renjietang | bd33b62 | 2020-02-12 16:52:30 -0800 | [diff] [blame] | 209 | HandshakerDelegateInterface* handshaker_delegate_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 210 | |
| 211 | QuicErrorCode parser_error_ = QUIC_NO_ERROR; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 212 | std::string parser_error_detail_; |
mattm | 072a7e3 | 2020-10-09 16:16:56 -0700 | [diff] [blame] | 213 | |
| 214 | // The most recently derived 1-RTT read and write secrets, which are updated |
| 215 | // on each key update. |
| 216 | std::vector<uint8_t> latest_read_secret_; |
| 217 | std::vector<uint8_t> latest_write_secret_; |
| 218 | // 1-RTT header protection keys, which are not changed during key update. |
| 219 | std::vector<uint8_t> one_rtt_read_header_protection_key_; |
| 220 | std::vector<uint8_t> one_rtt_write_header_protection_key_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 221 | }; |
| 222 | |
| 223 | } // namespace quic |
| 224 | |
| 225 | #endif // QUICHE_QUIC_CORE_TLS_HANDSHAKER_H_ |