| // Copyright (c) 2017 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_TLS_SERVER_HANDSHAKER_H_ |
| #define QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ |
| |
| #include <string> |
| |
| #include "third_party/boringssl/src/include/openssl/pool.h" |
| #include "third_party/boringssl/src/include/openssl/ssl.h" |
| #include "net/third_party/quiche/src/quic/core/proto/cached_network_parameters.pb.h" |
| #include "net/third_party/quiche/src/quic/core/quic_crypto_server_stream.h" |
| #include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h" |
| #include "net/third_party/quiche/src/quic/core/tls_handshaker.h" |
| #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
| |
| namespace quic { |
| |
| // An implementation of QuicCryptoServerStream::HandshakerDelegate which uses |
| // TLS 1.3 for the crypto handshake protocol. |
| class QUIC_EXPORT_PRIVATE TlsServerHandshaker |
| : public QuicCryptoServerStream::HandshakerDelegate, |
| public TlsHandshaker { |
| public: |
| TlsServerHandshaker(QuicCryptoStream* stream, |
| QuicSession* session, |
| SSL_CTX* ssl_ctx, |
| ProofSource* proof_source); |
| TlsServerHandshaker(const TlsServerHandshaker&) = delete; |
| TlsServerHandshaker& operator=(const TlsServerHandshaker&) = delete; |
| |
| ~TlsServerHandshaker() override; |
| |
| // Creates and configures an SSL_CTX to be used with a TlsServerHandshaker. |
| // The caller is responsible for ownership of the newly created struct. |
| static bssl::UniquePtr<SSL_CTX> CreateSslCtx(); |
| |
| // From QuicCryptoServerStream::HandshakerDelegate |
| void CancelOutstandingCallbacks() override; |
| bool GetBase64SHA256ClientChannelID(std::string* output) const override; |
| void SendServerConfigUpdate( |
| const CachedNetworkParameters* cached_network_params) override; |
| uint8_t NumHandshakeMessages() const override; |
| uint8_t NumHandshakeMessagesWithServerNonces() const override; |
| int NumServerConfigUpdateMessagesSent() const override; |
| const CachedNetworkParameters* PreviousCachedNetworkParams() const override; |
| bool ZeroRttAttempted() const override; |
| void SetPreviousCachedNetworkParams( |
| CachedNetworkParameters cached_network_params) override; |
| bool ShouldSendExpectCTHeader() const override; |
| |
| // From QuicCryptoServerStream::HandshakerDelegate and TlsHandshaker |
| bool encryption_established() const override; |
| bool handshake_confirmed() const override; |
| const QuicCryptoNegotiatedParameters& crypto_negotiated_params() |
| const override; |
| CryptoMessageParser* crypto_message_parser() override; |
| |
| // Calls SelectCertificate after looking up the TlsServerHandshaker from |
| // |ssl|. |
| static int SelectCertificateCallback(SSL* ssl, int* out_alert, void* arg); |
| |
| // Calls SelectAlpn after looking up the TlsServerHandshaker from |ssl|. |
| static int SelectAlpnCallback(SSL* ssl, |
| const uint8_t** out, |
| uint8_t* out_len, |
| const uint8_t* in, |
| unsigned in_len, |
| void* arg); |
| |
| private: |
| class SignatureCallback : public ProofSource::SignatureCallback { |
| public: |
| explicit SignatureCallback(TlsServerHandshaker* handshaker); |
| void Run(bool ok, std::string signature) override; |
| |
| // If called, Cancel causes the pending callback to be a no-op. |
| void Cancel(); |
| |
| private: |
| TlsServerHandshaker* handshaker_; |
| }; |
| |
| enum State { |
| STATE_LISTENING, |
| STATE_SIGNATURE_PENDING, |
| STATE_SIGNATURE_COMPLETE, |
| STATE_HANDSHAKE_COMPLETE, |
| STATE_CONNECTION_CLOSED, |
| }; |
| |
| // |kPrivateKeyMethod| is a vtable pointing to PrivateKeySign and |
| // PrivateKeyComplete used by the TLS stack to compute the signature for the |
| // CertificateVerify message (using the server's private key). |
| static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; |
| |
| // Called when a new message is received on the crypto stream and is available |
| // for the TLS stack to read. |
| void AdvanceHandshake() override; |
| void CloseConnection(QuicErrorCode error, |
| const std::string& reason_phrase) override; |
| |
| // Called when the TLS handshake is complete. |
| void FinishHandshake(); |
| |
| void CloseConnection(const std::string& reason_phrase); |
| |
| bool SetTransportParameters(); |
| bool ProcessTransportParameters(std::string* error_details); |
| |
| // Calls the instance method PrivateKeySign after looking up the |
| // TlsServerHandshaker from |ssl|. |
| static ssl_private_key_result_t PrivateKeySign(SSL* ssl, |
| uint8_t* out, |
| size_t* out_len, |
| size_t max_out, |
| uint16_t sig_alg, |
| const uint8_t* in, |
| size_t in_len); |
| |
| // Signs |in| using the signature algorithm specified by |sig_alg| (an |
| // SSL_SIGN_* value). If the signing operation cannot be completed |
| // synchronously, ssl_private_key_retry is returned. If there is an error |
| // signing, or if the signature is longer than |max_out|, then |
| // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is |
| // returned with the signature put in |*out| and the length in |*out_len|. |
| ssl_private_key_result_t PrivateKeySign(uint8_t* out, |
| size_t* out_len, |
| size_t max_out, |
| uint16_t sig_alg, |
| QuicStringPiece in); |
| |
| // Calls the instance method PrivateKeyComplete after looking up the |
| // TlsServerHandshaker from |ssl|. |
| static ssl_private_key_result_t PrivateKeyComplete(SSL* ssl, |
| uint8_t* out, |
| size_t* out_len, |
| size_t max_out); |
| |
| // When PrivateKeySign returns ssl_private_key_retry, PrivateKeyComplete will |
| // be called after the async sign operation has completed. PrivateKeyComplete |
| // puts the resulting signature in |*out| and length in |*out_len|. If the |
| // length is greater than |max_out| or if there was an error in signing, then |
| // ssl_private_key_failure is returned. Otherwise, ssl_private_key_success is |
| // returned. |
| ssl_private_key_result_t PrivateKeyComplete(uint8_t* out, |
| size_t* out_len, |
| size_t max_out); |
| |
| // Configures the certificate to use on |ssl_| based on the SNI sent by the |
| // client. Returns an SSL_TLSEXT_ERR_* value (see |
| // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html#SSL_CTX_set_tlsext_servername_callback). |
| // |
| // If SelectCertificate returns SSL_TLSEXT_ERR_ALERT_FATAL, then it puts in |
| // |*out_alert| the TLS alert value that the server will send. |
| int SelectCertificate(int* out_alert); |
| |
| // Selects which ALPN to use based on the list sent by the client. |
| int SelectAlpn(const uint8_t** out, |
| uint8_t* out_len, |
| const uint8_t* in, |
| unsigned in_len); |
| |
| static TlsServerHandshaker* HandshakerFromSsl(SSL* ssl); |
| |
| State state_ = STATE_LISTENING; |
| |
| ProofSource* proof_source_; |
| SignatureCallback* signature_callback_ = nullptr; |
| |
| std::string hostname_; |
| std::string cert_verify_sig_; |
| |
| bool encryption_established_ = false; |
| bool handshake_confirmed_ = false; |
| QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> |
| crypto_negotiated_params_; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ |