// 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 "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "quic/core/crypto/quic_crypto_server_config.h"
#include "quic/core/crypto/tls_server_connection.h"
#include "quic/core/proto/cached_network_parameters_proto.h"
#include "quic/core/quic_crypto_server_stream_base.h"
#include "quic/core/quic_crypto_stream.h"
#include "quic/core/quic_time_accumulator.h"
#include "quic/core/quic_types.h"
#include "quic/core/tls_handshaker.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"

namespace quic {

// An implementation of QuicCryptoServerStreamBase which uses
// TLS 1.3 for the crypto handshake protocol.
class QUIC_EXPORT_PRIVATE TlsServerHandshaker
    : public TlsHandshaker,
      public TlsServerConnection::Delegate,
      public ProofSourceHandleCallback,
      public QuicCryptoServerStreamBase {
 public:
  // |crypto_config| must outlive TlsServerHandshaker.
  TlsServerHandshaker(QuicSession* session,
                      const QuicCryptoServerConfig* crypto_config);
  TlsServerHandshaker(const TlsServerHandshaker&) = delete;
  TlsServerHandshaker& operator=(const TlsServerHandshaker&) = delete;

  ~TlsServerHandshaker() override;

  // From QuicCryptoServerStreamBase
  void CancelOutstandingCallbacks() override;
  bool GetBase64SHA256ClientChannelID(std::string* output) const override;
  void SendServerConfigUpdate(
      const CachedNetworkParameters* cached_network_params) override;
  bool IsZeroRtt() const override;
  bool IsResumption() const override;
  bool ResumptionAttempted() const override;
  int NumServerConfigUpdateMessagesSent() const override;
  const CachedNetworkParameters* PreviousCachedNetworkParams() const override;
  void SetPreviousCachedNetworkParams(
      CachedNetworkParameters cached_network_params) override;
  void OnPacketDecrypted(EncryptionLevel level) override;
  void OnOneRttPacketAcknowledged() override {}
  void OnHandshakePacketSent() override {}
  void OnConnectionClosed(QuicErrorCode error,
                          ConnectionCloseSource source) override;
  void OnHandshakeDoneReceived() override;
  std::string GetAddressToken() const override;
  bool ValidateAddressToken(absl::string_view token) const override;
  void OnNewTokenReceived(absl::string_view token) override;
  bool ShouldSendExpectCTHeader() const override;
  bool DidCertMatchSni() const override;
  const ProofSource::Details* ProofSourceDetails() const override;

  // From QuicCryptoServerStreamBase and TlsHandshaker
  ssl_early_data_reason_t EarlyDataReason() const override;
  bool encryption_established() const override;
  bool one_rtt_keys_available() const override;
  const QuicCryptoNegotiatedParameters& crypto_negotiated_params()
      const override;
  CryptoMessageParser* crypto_message_parser() override;
  HandshakeState GetHandshakeState() const override;
  void SetServerApplicationStateForResumption(
      std::unique_ptr<ApplicationState> state) override;
  size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
  bool KeyUpdateSupportedLocally() const override;
  std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
      override;
  std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
  void SetWriteSecret(EncryptionLevel level,
                      const SSL_CIPHER* cipher,
                      const std::vector<uint8_t>& write_secret) override;

  // Called with normalized SNI hostname as |hostname|.  Return value will be
  // sent in an ACCEPT_CH frame in the TLS ALPS extension, unless empty.
  virtual std::string GetAcceptChValueForHostname(
      const std::string& hostname) const;

 protected:
  // Override for tracing.
  void InfoCallback(int type, int value) override;

  // Creates a proof source handle for selecting cert and computing signature.
  virtual std::unique_ptr<ProofSourceHandle> MaybeCreateProofSourceHandle();

  // Hook to allow the server to override parts of the QuicConfig based on SNI
  // before we generate transport parameters.
  virtual void OverrideQuicConfigDefaults(QuicConfig* config);

  virtual bool ValidateHostname(const std::string& hostname) const;

  const TlsConnection* tls_connection() const override {
    return &tls_connection_;
  }

  virtual void ProcessAdditionalTransportParameters(
      const TransportParameters& /*params*/) {}

  // Called when a potentially async operation is done and the done callback
  // needs to advance the handshake.
  void AdvanceHandshakeFromCallback();

  // TlsHandshaker implementation:
  void FinishHandshake() override;
  void ProcessPostHandshakeMessage() override {}
  QuicAsyncStatus VerifyCertChain(
      const std::vector<std::string>& certs,
      std::string* error_details,
      std::unique_ptr<ProofVerifyDetails>* details,
      uint8_t* out_alert,
      std::unique_ptr<ProofVerifierCallback> callback) override;
  void OnProofVerifyDetailsAvailable(
      const ProofVerifyDetails& verify_details) override;

  // TlsServerConnection::Delegate implementation:
  // Used to select certificates and process transport parameters.
  ssl_select_cert_result_t EarlySelectCertCallback(
      const SSL_CLIENT_HELLO* client_hello) override;
  int TlsExtServernameCallback(int* out_alert) override;
  int SelectAlpn(const uint8_t** out,
                 uint8_t* out_len,
                 const uint8_t* in,
                 unsigned in_len) override;
  ssl_private_key_result_t PrivateKeySign(uint8_t* out,
                                          size_t* out_len,
                                          size_t max_out,
                                          uint16_t sig_alg,
                                          absl::string_view in) override;
  ssl_private_key_result_t PrivateKeyComplete(uint8_t* out,
                                              size_t* out_len,
                                              size_t max_out) override;
  size_t SessionTicketMaxOverhead() override;
  int SessionTicketSeal(uint8_t* out,
                        size_t* out_len,
                        size_t max_out_len,
                        absl::string_view in) override;
  ssl_ticket_aead_result_t SessionTicketOpen(uint8_t* out,
                                             size_t* out_len,
                                             size_t max_out_len,
                                             absl::string_view in) override;
  // Called when ticket_decryption_callback_ is done to determine a final
  // decryption result.
  ssl_ticket_aead_result_t FinalizeSessionTicketOpen(uint8_t* out,
                                                     size_t* out_len,
                                                     size_t max_out_len);
  TlsConnection::Delegate* ConnectionDelegate() override { return this; }

  // The status of cert selection. nullopt means it hasn't started.
  const absl::optional<QuicAsyncStatus>& select_cert_status() const {
    return select_cert_status_;
  }
  // Whether |cert_verify_sig_| contains a valid signature.
  // NOTE: BoringSSL queries the result of a async signature operation using
  // PrivateKeyComplete(), a successful PrivateKeyComplete() will clear the
  // content of |cert_verify_sig_|, this function should not be called after
  // that.
  bool HasValidSignature(size_t max_signature_size) const;

  // ProofSourceHandleCallback implementation:
  void OnSelectCertificateDone(bool ok, bool is_sync,
                               const ProofSource::Chain* chain,
                               absl::string_view handshake_hints,
                               absl::string_view ticket_encryption_key,
                               bool cert_matched_sni) override;

  void OnComputeSignatureDone(
      bool ok,
      bool is_sync,
      std::string signature,
      std::unique_ptr<ProofSource::Details> details) override;

  void set_encryption_established(bool encryption_established) {
    encryption_established_ = encryption_established;
  }

  bool WillNotCallComputeSignature() const override;

  void SetIgnoreTicketOpen(bool value) { ignore_ticket_open_ = value; }

 private:
  class QUIC_EXPORT_PRIVATE DecryptCallback
      : public ProofSource::DecryptCallback {
   public:
    explicit DecryptCallback(TlsServerHandshaker* handshaker);
    void Run(std::vector<uint8_t> plaintext) override;

    // If called, Cancel causes the pending callback to be a no-op.
    void Cancel();

    // Return true if either
    // - Cancel() has been called.
    // - Run() has been called, or is in the middle of it.
    bool IsDone() const { return handshaker_ == nullptr; }

   private:
    TlsServerHandshaker* handshaker_;
  };

  // DefaultProofSourceHandle delegates all operations to the shared proof
  // source.
  class QUIC_EXPORT_PRIVATE DefaultProofSourceHandle
      : public ProofSourceHandle {
   public:
    DefaultProofSourceHandle(TlsServerHandshaker* handshaker,
                             ProofSource* proof_source);

    ~DefaultProofSourceHandle() override;

    // Close the handle. Cancel the pending signature operation, if any.
    void CloseHandle() override;

    // Delegates to proof_source_->GetCertChain.
    // Returns QUIC_SUCCESS or QUIC_FAILURE. Never returns QUIC_PENDING.
    QuicAsyncStatus SelectCertificate(
        const QuicSocketAddress& server_address,
        const QuicSocketAddress& client_address,
        absl::string_view ssl_capabilities,
        const std::string& hostname,
        absl::string_view client_hello,
        const std::string& alpn,
        absl::optional<std::string> alps,
        const std::vector<uint8_t>& quic_transport_params,
        const absl::optional<std::vector<uint8_t>>& early_data_context,
        const QuicSSLConfig& ssl_config) override;

    // Delegates to proof_source_->ComputeTlsSignature.
    // Returns QUIC_SUCCESS, QUIC_FAILURE or QUIC_PENDING.
    QuicAsyncStatus ComputeSignature(const QuicSocketAddress& server_address,
                                     const QuicSocketAddress& client_address,
                                     const std::string& hostname,
                                     uint16_t signature_algorithm,
                                     absl::string_view in,
                                     size_t max_signature_size) override;

   protected:
    ProofSourceHandleCallback* callback() override { return handshaker_; }

   private:
    class QUIC_EXPORT_PRIVATE DefaultSignatureCallback
        : public ProofSource::SignatureCallback {
     public:
      explicit DefaultSignatureCallback(DefaultProofSourceHandle* handle)
          : handle_(handle) {}

      void Run(bool ok,
               std::string signature,
               std::unique_ptr<ProofSource::Details> details) override {
        if (handle_ == nullptr) {
          // Operation has been canceled, or Run has been called.
          return;
        }

        DefaultProofSourceHandle* handle = handle_;
        handle_ = nullptr;

        handle->signature_callback_ = nullptr;
        if (handle->handshaker_ != nullptr) {
          handle->handshaker_->OnComputeSignatureDone(
              ok, is_sync_, std::move(signature), std::move(details));
        }
      }

      // If called, Cancel causes the pending callback to be a no-op.
      void Cancel() { handle_ = nullptr; }

      void set_is_sync(bool is_sync) { is_sync_ = is_sync; }

     private:
      DefaultProofSourceHandle* handle_;
      // Set to false if handle_->ComputeSignature returns QUIC_PENDING.
      bool is_sync_ = true;
    };

    // Not nullptr on construction. Set to nullptr when cancelled.
    TlsServerHandshaker* handshaker_;  // Not owned.
    ProofSource* proof_source_;        // Not owned.
    DefaultSignatureCallback* signature_callback_ = nullptr;
  };

  struct QUIC_NO_EXPORT SetTransportParametersResult {
    bool success = false;
    // Empty vector if QUIC transport params are not set successfully.
    std::vector<uint8_t> quic_transport_params;
    // absl::nullopt if there is no application state to begin with.
    // Empty vector if application state is not set successfully.
    absl::optional<std::vector<uint8_t>> early_data_context;
  };

  SetTransportParametersResult SetTransportParameters();
  bool ProcessTransportParameters(const SSL_CLIENT_HELLO* client_hello,
                                  std::string* error_details);

  struct QUIC_NO_EXPORT SetApplicationSettingsResult {
    bool success = false;
    std::unique_ptr<char[]> alps_buffer;
    size_t alps_length = 0;
  };
  SetApplicationSettingsResult SetApplicationSettings(absl::string_view alpn);

  QuicConnectionStats& connection_stats() {
    return session()->connection()->mutable_stats();
  }
  QuicTime now() const { return session()->GetClock()->Now(); }

  QuicConnectionContext* connection_context() {
    QUICHE_DCHECK(restore_connection_context_in_callbacks_);
    return session()->connection()->context();
  }

  std::unique_ptr<ProofSourceHandle> proof_source_handle_;
  ProofSource* proof_source_;

  // State to handle potentially asynchronous session ticket decryption.
  // |ticket_decryption_callback_| points to the non-owned callback that was
  // passed to ProofSource::TicketCrypter::Decrypt but hasn't finished running
  // yet.
  DecryptCallback* ticket_decryption_callback_ = nullptr;
  // |decrypted_session_ticket_| contains the decrypted session ticket after the
  // callback has run but before it is passed to BoringSSL.
  std::vector<uint8_t> decrypted_session_ticket_;
  // |ticket_received_| tracks whether we received a resumption ticket from the
  // client. It does not matter whether we were able to decrypt said ticket or
  // if we actually resumed a session with it - the presence of this ticket
  // indicates that the client attempted a resumption.
  bool ticket_received_ = false;

  // Force SessionTicketOpen to return ssl_ticket_aead_ignore_ticket if called.
  bool ignore_ticket_open_ = false;

  // nullopt means select cert hasn't started.
  absl::optional<QuicAsyncStatus> select_cert_status_;

  std::string cert_verify_sig_;
  std::unique_ptr<ProofSource::Details> proof_source_details_;

  // Count the duration of the current async operation, if any.
  absl::optional<QuicTimeAccumulator> async_op_timer_;

  std::unique_ptr<ApplicationState> application_state_;

  // Pre-shared key used during the handshake.
  std::string pre_shared_key_;

  // (optional) Key to use for encrypting TLS resumption tickets.
  std::string ticket_encryption_key_;

  HandshakeState state_ = HANDSHAKE_START;
  bool encryption_established_ = false;
  bool valid_alpn_received_ = false;
  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
      crypto_negotiated_params_;
  TlsServerConnection tls_connection_;
  const QuicCryptoServerConfig* crypto_config_;  // Unowned.
  const bool restore_connection_context_in_callbacks_ =
      GetQuicReloadableFlag(quic_tls_restore_connection_context_in_callbacks);

  bool cert_matched_sni_ = false;
};

}  // namespace quic

#endif  // QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_
