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_SERVER_HANDSHAKER_H_ |
| 6 | #define QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ |
| 7 | |
vasilvv | 872e7a3 | 2019-03-12 16:42:44 -0700 | [diff] [blame] | 8 | #include <string> |
| 9 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 10 | #include "third_party/boringssl/src/include/openssl/pool.h" |
| 11 | #include "third_party/boringssl/src/include/openssl/ssl.h" |
| 12 | #include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h" |
| 13 | #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" |
| 14 | #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" |
| 15 | #include "net/third_party/quiche/src/quic/core/tls_handshaker.h" |
| 16 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 17 | |
| 18 | namespace quic { |
| 19 | |
| 20 | // An implementation of QuicCryptoServerStream::HandshakerDelegate which uses |
| 21 | // TLS 1.3 for the crypto handshake protocol. |
| 22 | class QUIC_EXPORT_PRIVATE TlsServerHandshaker |
| 23 | : public QuicCryptoServerStream::HandshakerDelegate, |
| 24 | public TlsHandshaker { |
| 25 | public: |
| 26 | TlsServerHandshaker(QuicCryptoStream* stream, |
| 27 | QuicSession* session, |
| 28 | SSL_CTX* ssl_ctx, |
| 29 | ProofSource* proof_source); |
| 30 | TlsServerHandshaker(const TlsServerHandshaker&) = delete; |
| 31 | TlsServerHandshaker& operator=(const TlsServerHandshaker&) = delete; |
| 32 | |
| 33 | ~TlsServerHandshaker() override; |
| 34 | |
| 35 | // Creates and configures an SSL_CTX to be used with a TlsServerHandshaker. |
| 36 | // The caller is responsible for ownership of the newly created struct. |
| 37 | static bssl::UniquePtr<SSL_CTX> CreateSslCtx(); |
| 38 | |
| 39 | // From QuicCryptoServerStream::HandshakerDelegate |
| 40 | void CancelOutstandingCallbacks() override; |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 41 | bool GetBase64SHA256ClientChannelID(std::string* output) const override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 42 | void SendServerConfigUpdate( |
| 43 | const CachedNetworkParameters* cached_network_params) override; |
| 44 | uint8_t NumHandshakeMessages() const override; |
| 45 | uint8_t NumHandshakeMessagesWithServerNonces() const override; |
| 46 | int NumServerConfigUpdateMessagesSent() const override; |
| 47 | const CachedNetworkParameters* PreviousCachedNetworkParams() const override; |
| 48 | bool ZeroRttAttempted() const override; |
| 49 | void SetPreviousCachedNetworkParams( |
| 50 | CachedNetworkParameters cached_network_params) override; |
| 51 | bool ShouldSendExpectCTHeader() const override; |
| 52 | |
| 53 | // From QuicCryptoServerStream::HandshakerDelegate and TlsHandshaker |
| 54 | bool encryption_established() const override; |
| 55 | bool handshake_confirmed() const override; |
| 56 | const QuicCryptoNegotiatedParameters& crypto_negotiated_params() |
| 57 | const override; |
| 58 | CryptoMessageParser* crypto_message_parser() override; |
| 59 | |
| 60 | // Calls SelectCertificate after looking up the TlsServerHandshaker from |
| 61 | // |ssl|. |
| 62 | static int SelectCertificateCallback(SSL* ssl, int* out_alert, void* arg); |
| 63 | |
| 64 | private: |
| 65 | class SignatureCallback : public ProofSource::SignatureCallback { |
| 66 | public: |
| 67 | explicit SignatureCallback(TlsServerHandshaker* handshaker); |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 68 | void Run(bool ok, std::string signature) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 69 | |
| 70 | // If called, Cancel causes the pending callback to be a no-op. |
| 71 | void Cancel(); |
| 72 | |
| 73 | private: |
| 74 | TlsServerHandshaker* handshaker_; |
| 75 | }; |
| 76 | |
| 77 | enum State { |
| 78 | STATE_LISTENING, |
| 79 | STATE_SIGNATURE_PENDING, |
| 80 | STATE_SIGNATURE_COMPLETE, |
| 81 | STATE_HANDSHAKE_COMPLETE, |
| 82 | STATE_CONNECTION_CLOSED, |
| 83 | }; |
| 84 | |
| 85 | // |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and |
| 86 | // PrivateKeyComplete used by the TLS stack to compute the signature for the |
| 87 | // CertificateVerify message (using the server's private key). |
| 88 | static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; |
| 89 | |
| 90 | // Called when a new message is received on the crypto stream and is available |
| 91 | // for the TLS stack to read. |
| 92 | void AdvanceHandshake() override; |
| 93 | void CloseConnection(QuicErrorCode error, |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 94 | const std::string& reason_phrase) override; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 95 | |
| 96 | // Called when the TLS handshake is complete. |
| 97 | void FinishHandshake(); |
| 98 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 99 | void CloseConnection(const std::string& reason_phrase); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 100 | |
| 101 | bool SetTransportParameters(); |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 102 | bool ProcessTransportParameters(std::string* error_details); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 103 | |
| 104 | // Calls the instance method PrivateKeySign after looking up the |
| 105 | // TlsServerHandshaker from |ssl|. |
| 106 | static ssl_private_key_result_t PrivateKeySign(SSL* ssl, |
| 107 | uint8_t* out, |
| 108 | size_t* out_len, |
| 109 | size_t max_out, |
| 110 | uint16_t sig_alg, |
| 111 | const uint8_t* in, |
| 112 | size_t in_len); |
| 113 | |
| 114 | // Signs |in| using the signature algorithm specified by |sig_alg| (an |
| 115 | // SSL_SIGN_* value). If the signing operation cannot be completed |
| 116 | // synchronously, ssl_private_key_retry is returned. If there is an error |
| 117 | // signing, or if the signature is longer than |max_out|, then |
| 118 | // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is |
| 119 | // returned with the signature put in |*out| and the length in |*out_len|. |
| 120 | ssl_private_key_result_t PrivateKeySign(uint8_t* out, |
| 121 | size_t* out_len, |
| 122 | size_t max_out, |
| 123 | uint16_t sig_alg, |
| 124 | QuicStringPiece in); |
| 125 | |
| 126 | // Calls the instance method PrivateKeyComplete after looking up the |
| 127 | // TlsServerHandshaker from |ssl|. |
| 128 | static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, |
| 129 | uint8_t* out, |
| 130 | size_t* out_len, |
| 131 | size_t max_out); |
| 132 | |
| 133 | // When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete will |
| 134 | // be called after the async sign operation has completed. PrivateKeyComplete |
| 135 | // puts the resulting signature in |*out| and length in |*out_len|. If the |
| 136 | // length is greater than |max_out| or if there was an error in signing, then |
| 137 | // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is |
| 138 | // returned. |
| 139 | ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, |
| 140 | size_t* out_len, |
| 141 | size_t max_out); |
| 142 | |
| 143 | // Configures the certificate to use on |ssl_| based on the SNI sent by the |
| 144 | // client. Returns an SSL_TLSEXT_ERR_* value (see |
| 145 | // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback). |
| 146 | // |
| 147 | // If SelectCertificate returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in |
| 148 | // |*out_alert| the TLS alert value that the server will send. |
| 149 | int SelectCertificate(int* out_alert); |
| 150 | |
| 151 | static TlsServerHandshaker* HandshakerFromSsl(SSL* ssl); |
| 152 | |
| 153 | State state_ = STATE_LISTENING; |
| 154 | |
| 155 | ProofSource* proof_source_; |
| 156 | SignatureCallback* signature_callback_ = nullptr; |
| 157 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 158 | std::string hostname_; |
| 159 | std::string cert_verify_sig_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 160 | |
| 161 | bool encryption_established_ = false; |
| 162 | bool handshake_confirmed_ = false; |
| 163 | QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> |
| 164 | crypto_negotiated_params_; |
| 165 | }; |
| 166 | |
| 167 | } // namespace quic |
| 168 | |
| 169 | #endif // QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ |