// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "security_manager.h"

#include <zircon/assert.h>
#include <zircon/status.h>

#include <memory>
#include <optional>
#include <type_traits>
#include <utility>
#include <variant>

#include "lib/async/default.h"
#include "lib/fit/function.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/device_address.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/common/random.h"
#include "src/connectivity/bluetooth/core/bt-host/common/uint128.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/link_key.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/phase_2_secure_connections.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/security_request_phase.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "util.h"

namespace bt::sm {

namespace {

SecurityProperties FeaturesToProperties(const PairingFeatures& features) {
  return SecurityProperties(features.method == PairingMethod::kJustWorks
                                ? SecurityLevel::kEncrypted
                                : SecurityLevel::kAuthenticated,
                            features.encryption_key_size, features.secure_connections);
}
}  // namespace

class SecurityManagerImpl final : public SecurityManager,
                                  public PairingPhase::Listener,
                                  public PairingChannel::Handler {
 public:
  ~SecurityManagerImpl() override;
  SecurityManagerImpl(fxl::WeakPtr<hci::Connection> link, fbl::RefPtr<l2cap::Channel> smp,
                      IOCapability io_capability, fxl::WeakPtr<Delegate> delegate,
                      BondableMode bondable_mode, gap::LeSecurityMode security_mode);
  // SecurityManager overrides:
  bool AssignLongTermKey(const LTK& ltk) override;
  void UpgradeSecurity(SecurityLevel level, PairingCallback callback) override;
  void Reset(IOCapability io_capability) override;
  void Abort(ErrorCode ecode) override;

 private:
  // Represents a pending request to update the security level.
  struct PendingRequest {
    PendingRequest(SecurityLevel level, PairingCallback callback);
    PendingRequest(PendingRequest&&) = default;
    PendingRequest& operator=(PendingRequest&&) = default;

    SecurityLevel level;
    PairingCallback callback;
  };

  // Called when we receive a peer security request as initiator, will start Phase 1.
  void OnSecurityRequest(AuthReqField auth_req);

  // Called when we receive a peer pairing request as responder, will start Phase 1.
  void OnPairingRequest(const PairingRequestParams& req_params);

  // Pulls the next PendingRequest off |request_queue_| and starts a security upgrade to that
  // |level| by either sending a Pairing Request as initiator or a Security Request as responder.
  void UpgradeSecurityInternal();

  // Called when the feature exchange (Phase 1) completes and the relevant features of both sides
  // have been resolved into `features`. `preq` and `pres` need to be retained for cryptographic
  // calculations in Phase 2. Causes a state transition from Phase 1 to Phase 2
  void OnFeatureExchange(PairingFeatures features, PairingRequestParams preq,
                         PairingResponseParams pres);

  // Called when Phase 2 generates an encryption key, so the link can be encrypted with it.
  void OnPhase2EncryptionKey(const UInt128& new_key);

  // Check if encryption using `current_ltk` will satisfy the current security requirements.
  static bool CurrentLtkInsufficientlySecureForEncryption(
      std::optional<LTK> current_ltk, SecurityRequestPhase* security_request_phase,
      gap::LeSecurityMode mode);

  // Called when the encryption state of the LE link changes.
  void OnEncryptionChange(hci::Status status, bool enabled);

  // Called when the link is encrypted at the end of pairing Phase 2.
  void EndPhase2();

  // Cleans up pairing state, updates the current security level, and notifies parties that
  // requested security of the link's updated security properties.
  void OnPairingComplete(PairingData data);

  // After a call to UpgradeSecurity results in an increase of the link security level (through
  // pairing completion or SMP Security Requested encryption), this method notifies all the
  // callbacks associated with SecurityUpgrade requests.
  void NotifySecurityCallbacks();

  // Assign the current security properties and notify the delegate of the
  // change.
  void SetSecurityProperties(const SecurityProperties& sec);

  // Directly assigns the current |ltk_| and the underlying |le_link_|'s link key. This function
  // does not initiate link layer encryption and can be called during and outside of pairing.
  void OnNewLongTermKey(const LTK& ltk);

  // PairingPhase::Listener overrides:
  void OnPairingFailed(Status status) override;
  std::optional<IdentityInfo> OnIdentityRequest() override;
  void ConfirmPairing(ConfirmCallback confirm) override;
  void DisplayPasskey(uint32_t passkey, Delegate::DisplayMethod method,
                      ConfirmCallback cb) override;
  void RequestPasskey(PasskeyResponseCallback respond) override;

  // PairingChannel::Handler overrides. SecurityManagerImpl is only the fallback handler, meaning
  // these methods are only called by PairingChannel when no security upgrade is in progress:
  void OnRxBFrame(ByteBufferPtr sdu) override;
  void OnChannelClosed() override;

  // Starts the SMP timer. Stops and cancels any in-progress timers.
  void StartNewTimer();
  // Stops and resets the SMP Pairing Timer.
  void StopTimer();
  // Called when the pairing timer expires, forcing the pairing process to stop
  void OnPairingTimeout();

  // Returns a std::pair<InitiatorAddress, ResponderAddress>. Will assert if called outside active
  // pairing or before Phase 1 is complete.
  std::pair<DeviceAddress, DeviceAddress> LEPairingAddresses();

  // Puts the class into a non-pairing state.
  void ResetState();

  // Returns true if the pairing state machine is currently in Phase 2 of pairing.
  bool InPhase2() const {
    return std::holds_alternative<Phase2Legacy>(current_phase_) ||
           std::holds_alternative<Phase2SecureConnections>(current_phase_);
  }

  bool SecurityUpgradeInProgress() const {
    return !std::holds_alternative<std::monostate>(current_phase_);
  }

  // Validates that both SM and the link have stored LTKs, and that these values match. Disconnects
  // the link if it finds an issue. Should only be called when an LTK is expected to exist.
  Status ValidateExistingLocalLtk();

  // The ID that will be assigned to the next pairing operation.
  PairingProcedureId next_pairing_id_;

  // The higher-level class acting as a delegate for operations outside of SMP.
  fxl::WeakPtr<Delegate> delegate_;

  // Data for the currently registered LE-U link, if any.
  fxl::WeakPtr<hci::Connection> le_link_;

  // The IO capabilities of the device
  IOCapability io_cap_;

  // The current LTK assigned to this connection. This can be assigned directly
  // by calling AssignLongTermKey() or as a result of a pairing procedure.
  std::optional<LTK> ltk_;

  // If a pairing is in progress and Phase 1 (feature exchange) has completed, this will store the
  // result of that feature exchange. Otherwise, this will be std::nullopt.
  std::optional<PairingFeatures> features_;

  // The pending security requests added via UpgradeSecurity().
  std::queue<PendingRequest> request_queue_;

  // Fixed SMP Channel used to send/receive packets
  std::unique_ptr<PairingChannel> sm_chan_;

  // The role of the local device in pairing.
  Role role_;

  async::TaskClosureMethod<SecurityManagerImpl, &SecurityManagerImpl::OnPairingTimeout>
      timeout_task_{this};

  // The presence of a particular phase in this variant indicates that a security upgrade is in
  // progress at the stored phase. No security upgrade is in progress if std::monostate is present.
  std::variant<std::monostate, SecurityRequestPhase, std::unique_ptr<Phase1>, Phase2Legacy,
               Phase2SecureConnections, Phase3>
      current_phase_;

  fxl::WeakPtrFactory<SecurityManagerImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(SecurityManagerImpl);
};

SecurityManagerImpl::PendingRequest::PendingRequest(SecurityLevel level, PairingCallback callback)
    : level(level), callback(std::move(callback)) {}

SecurityManagerImpl::~SecurityManagerImpl() {
  if (le_link_) {
    le_link_->set_encryption_change_callback({});
  }
}

SecurityManagerImpl::SecurityManagerImpl(
    fxl::WeakPtr<hci::Connection> link, fbl::RefPtr<l2cap::Channel> smp, IOCapability io_capability,
    fxl::WeakPtr<Delegate> delegate, BondableMode bondable_mode, gap::LeSecurityMode security_mode)
    : SecurityManager(bondable_mode, security_mode),
      next_pairing_id_(0),
      delegate_(std::move(delegate)),
      le_link_(std::move(link)),
      io_cap_(io_capability),
      sm_chan_(std::make_unique<PairingChannel>(
          smp, fit::bind_member(this, &SecurityManagerImpl::StartNewTimer))),
      role_(le_link_->role() == hci::Connection::Role::kMaster ? Role::kInitiator
                                                               : Role::kResponder),
      weak_ptr_factory_(this) {
  ZX_ASSERT(delegate_);
  ZX_ASSERT(le_link_);
  ZX_ASSERT(smp);
  ZX_ASSERT(le_link_->handle() == smp->link_handle());
  ZX_ASSERT(le_link_->ll_type() == hci::Connection::LinkType::kLE);
  ZX_ASSERT(smp->id() == l2cap::kLESMPChannelId);
  // `current_phase_` is default constructed into std::monostate in the initializer list as no
  // security upgrade is in progress upon construction.

  // Set up HCI encryption event.
  le_link_->set_encryption_change_callback(
      fit::bind_member(this, &SecurityManagerImpl::OnEncryptionChange));
  sm_chan_->SetChannelHandler(weak_ptr_factory_.GetWeakPtr());
}

void SecurityManagerImpl::OnSecurityRequest(AuthReqField auth_req) {
  ZX_ASSERT(!SecurityUpgradeInProgress());

  if (role_ != Role::kInitiator) {
    bt_log(DEBUG, "sm", "Received spurious Security Request while not acting as SM initiator");
    return;
  }

  SecurityLevel requested_level;
  if (auth_req & AuthReq::kMITM) {
    requested_level = SecurityLevel::kAuthenticated;
  } else {
    requested_level = SecurityLevel::kEncrypted;
  }

  // If we already have a LTK and its security properties satisfy the request, then we start link
  // layer encryption (which will either encrypt the link or perform a key refresh). See Vol 3,
  // Part H, Figure 2.7 for the algorithm.
  if (ltk_ && (ltk_->security().level() >= requested_level) &&
      (!(auth_req & AuthReq::kSC) || ltk_->security().secure_connections())) {
    if (bt_is_error(ValidateExistingLocalLtk(), ERROR, "sm",
                    "disconnecting link as it cannot be encrypted with LTK status")) {
      return;
    }
    le_link_->StartEncryption();
    return;
  }
  // V5.1 Vol. 3 Part H Section 3.4: "Upon [...] reception of the Security Request command, the
  // Security Manager Timer shall be [...] restarted."
  StartNewTimer();
  // Initiate pairing.
  UpgradeSecurity(requested_level, [](Status status, const auto& security) {
    bt_log(DEBUG, "sm", "security request resolved - %s %s", bt_str(status), bt_str(security));
  });
}

void SecurityManagerImpl::UpgradeSecurity(SecurityLevel level, PairingCallback callback) {
  if (SecurityUpgradeInProgress()) {
    bt_log(TRACE, "sm", "LE security upgrade in progress; request for %s security queued",
           LevelToString(level));
    request_queue_.emplace(level, std::move(callback));
    return;
  }

  if (level <= security().level()) {
    callback(Status(), security());
    return;
  }

  // Secure Connections only mode only permits Secure Connections authenticated pairing with a 128-
  // bit encryption key, so we force all security upgrade requests to that level.
  if (security_mode() == gap::LeSecurityMode::SecureConnectionsOnly) {
    level = SecurityLevel::kSecureAuthenticated;
  }

  // |request_queue| must be empty if there is no active security upgrade request, which is
  // equivalent to being in idle phase with no pending security request.
  ZX_ASSERT(request_queue_.empty());
  request_queue_.emplace(level, std::move(callback));
  UpgradeSecurityInternal();
}

void SecurityManagerImpl::OnPairingRequest(const PairingRequestParams& req_params) {
  // Only the initiator may send the Pairing Request (V5.0 Vol. 3 Part H 3.5.1).
  if (role_ != Role::kResponder) {
    bt_log(DEBUG, "sm", "rejecting \"Pairing Request\" as initiator");
    sm_chan_->SendMessage(kPairingFailed, ErrorCode::kCommandNotSupported);
    return;
  }
  // V5.1 Vol. 3 Part H Section 3.4: "Upon [...] reception of the Pairing Request command, the
  // Security Manager Timer shall be reset and started."
  StartNewTimer();

  // We only require authentication as Responder if there is a pending Security Request for it.
  SecurityRequestPhase* security_req_phase = std::get_if<SecurityRequestPhase>(&current_phase_);
  auto required_level = security_req_phase ? security_req_phase->pending_security_request()
                                           : SecurityLevel::kEncrypted;

  // Secure Connections only mode only permits Secure Connections authenticated pairing with a 128-
  // bit encryption key, so we force all security upgrade requests to that level.
  if (security_mode() == gap::LeSecurityMode::SecureConnectionsOnly) {
    required_level = SecurityLevel::kSecureAuthenticated;
  }

  current_phase_ = Phase1::CreatePhase1Responder(
      sm_chan_->GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(), req_params, io_cap_, bondable_mode(),
      required_level, fit::bind_member(this, &SecurityManagerImpl::OnFeatureExchange));
  std::get<std::unique_ptr<Phase1>>(current_phase_)->Start();
}

void SecurityManagerImpl::UpgradeSecurityInternal() {
  ZX_ASSERT_MSG(!SecurityUpgradeInProgress(),
                "cannot upgrade security while security upgrade already in progress!");
  const PendingRequest& next_req = request_queue_.front();
  if (next_req.level >= SecurityLevel::kAuthenticated &&
      io_cap_ == IOCapability::kNoInputNoOutput) {
    bt_log(WARN, "sm",
           "cannot fulfill authenticated security request as IOCapabilities are NoInputNoOutput");
    next_req.callback(Status(ErrorCode::kAuthenticationRequirements), security());
    request_queue_.pop();
    if (!request_queue_.empty()) {
      UpgradeSecurityInternal();
    }
    return;
  }

  // V5.1 Vol. 3 Part H Section 3.4: "Upon transmission of the Pairing Request command [...] the
  // [SM] Timer shall be [..] started" and "Upon transmission of the Security Request command [...]
  // the [SM] Timer shall be reset and restarted".
  StartNewTimer();
  if (role_ == Role::kInitiator) {
    current_phase_ = Phase1::CreatePhase1Initiator(
        sm_chan_->GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(), io_cap_, bondable_mode(),
        next_req.level, fit::bind_member(this, &SecurityManagerImpl::OnFeatureExchange));
    std::get<std::unique_ptr<Phase1>>(current_phase_)->Start();
  } else {
    current_phase_.emplace<SecurityRequestPhase>(
        sm_chan_->GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(), next_req.level, bondable_mode(),
        fit::bind_member(this, &SecurityManagerImpl::OnPairingRequest));
    std::get<SecurityRequestPhase>(current_phase_).Start();
  }
}

void SecurityManagerImpl::OnFeatureExchange(PairingFeatures features, PairingRequestParams preq,
                                            PairingResponseParams pres) {
  ZX_ASSERT(std::holds_alternative<std::unique_ptr<Phase1>>(current_phase_));
  bt_log(TRACE, "sm", "obtained LE Pairing features");
  next_pairing_id_++;
  features_ = features;

  const auto [initiator_addr, responder_addr] = LEPairingAddresses();
  auto self = weak_ptr_factory_.GetWeakPtr();
  if (!features.secure_connections) {
    auto preq_pdu = util::NewPdu(sizeof(PairingRequestParams)),
         pres_pdu = util::NewPdu(sizeof(PairingResponseParams));
    PacketWriter preq_writer(kPairingRequest, preq_pdu.get()),
        pres_writer(kPairingResponse, pres_pdu.get());
    *preq_writer.mutable_payload<PairingRequestParams>() = preq;
    *pres_writer.mutable_payload<PairingRequestParams>() = pres;
    current_phase_.emplace<Phase2Legacy>(
        sm_chan_->GetWeakPtr(), self, role_, features, *preq_pdu, *pres_pdu, initiator_addr,
        responder_addr, fit::bind_member(this, &SecurityManagerImpl::OnPhase2EncryptionKey));
    std::get<Phase2Legacy>(current_phase_).Start();
  } else {
    current_phase_.emplace<Phase2SecureConnections>(
        sm_chan_->GetWeakPtr(), self, role_, features, preq, pres, initiator_addr, responder_addr,
        fit::bind_member(this, &SecurityManagerImpl::OnPhase2EncryptionKey));
    std::get<Phase2SecureConnections>(current_phase_).Start();
  }
}

void SecurityManagerImpl::OnPhase2EncryptionKey(const UInt128& new_key) {
  ZX_ASSERT(le_link_);
  ZX_ASSERT(features_);
  ZX_ASSERT(InPhase2());
  // EDiv and Rand values are 0 for Phase 2 keys generated by Legacy or Secure Connections (Vol 3,
  // Part H, 2.4.4 / 2.4.4.1). Secure Connections generates an LTK, while Legacy generates an STK.
  auto new_link_key = hci::LinkKey(new_key, 0, 0);

  if (features_->secure_connections) {
    OnNewLongTermKey(LTK(FeaturesToProperties(*features_), new_link_key));
  } else {
    // `set_le_ltk` sets the encryption key of the LE link (which is the STK for Legacy), not the
    // long-term key that results from pairing (which is generated in Phase 3 for Legacy).
    le_link_->set_le_ltk(new_link_key);
  }
  // If we're the initiator, we encrypt the link. If we're the responder, we wait for the initiator
  // to encrypt the link with the new key.|le_link_| will respond to the HCI "LTK request" event
  // with the `new_link_key` assigned above, which should trigger OnEncryptionChange.
  if (role_ == Role::kInitiator) {
    if (!le_link_->StartEncryption()) {
      bt_log(ERROR, "sm", "failed to start encryption");
      Abort(ErrorCode::kUnspecifiedReason);
    }
  }
}

bool SecurityManagerImpl::CurrentLtkInsufficientlySecureForEncryption(
    std::optional<LTK> current_ltk, SecurityRequestPhase* security_request_phase,
    gap::LeSecurityMode mode) {
  SecurityLevel current_ltk_sec =
      current_ltk ? current_ltk->security().level() : SecurityLevel::kNoSecurity;
  return (security_request_phase &&
          security_request_phase->pending_security_request() > current_ltk_sec) ||
         (mode == gap::LeSecurityMode::SecureConnectionsOnly &&
          current_ltk_sec != SecurityLevel::kSecureAuthenticated);
}

void SecurityManagerImpl::OnEncryptionChange(hci::Status status, bool enabled) {
  // First notify the delegate in case of failure.
  if (bt_is_error(status, ERROR, "sm", "link layer authentication failed")) {
    ZX_ASSERT(delegate_);
    delegate_->OnAuthenticationFailure(status);
  }

  if (!status || !enabled) {
    bt_log(WARN, "sm", "encryption of link (handle: %#.4x) %s%s!", le_link_->handle(),
           !status ? fxl::StringPrintf("failed with %s", bt_str(status)).c_str() : "disabled",
           SecurityUpgradeInProgress() ? "" : " during security upgrade");
    SetSecurityProperties(sm::SecurityProperties());
    if (SecurityUpgradeInProgress()) {
      Abort(ErrorCode::kUnspecifiedReason);
    }
    return;
  }

  SecurityRequestPhase* security_request_phase = std::get_if<SecurityRequestPhase>(&current_phase_);
  if (CurrentLtkInsufficientlySecureForEncryption(ltk_, security_request_phase, security_mode())) {
    bt_log(WARN, "sm", "peer encrypted link with insufficiently secure key, disconnecting");
    delegate_->OnAuthenticationFailure(hci::Status(HostError::kInsufficientSecurity));
    sm_chan_->SignalLinkError();
    return;
  }

  if (!SecurityUpgradeInProgress() || security_request_phase) {
    bt_log(DEBUG, "sm", "encryption enabled while not pairing");
    if (bt_is_error(ValidateExistingLocalLtk(), ERROR, "sm",
                    "disconnecting link as it cannot be encrypted with LTK status")) {
      return;
    }
    // If encryption is enabled while not pairing, we update the security properties to those of
    // `ltk_`. Otherwise, we let the EndPhase2 pairing function determine the security properties.
    SetSecurityProperties(ltk_->security());
    if (security_request_phase) {
      ZX_ASSERT(role_ == Role::kResponder);
      ZX_ASSERT(!request_queue_.empty());
      NotifySecurityCallbacks();
    }
    return;
  }

  if (InPhase2()) {
    bt_log(DEBUG, "sm", "link encrypted with phase 2 generated key");
    EndPhase2();
  }
}

void SecurityManagerImpl::EndPhase2() {
  ZX_ASSERT(features_.has_value());
  ZX_ASSERT(InPhase2());

  SetSecurityProperties(FeaturesToProperties(*features_));
  // If there are no keys to distribute, don't bother creating Phase 3
  if (!HasKeysToDistribute(*features_)) {
    OnPairingComplete(PairingData());
    return;
  }
  auto self = weak_ptr_factory_.GetWeakPtr();
  current_phase_.emplace<Phase3>(sm_chan_->GetWeakPtr(), self, role_, *features_, security(),
                                 fit::bind_member(this, &SecurityManagerImpl::OnPairingComplete));
  std::get<Phase3>(current_phase_).Start();
}

void SecurityManagerImpl::OnPairingComplete(PairingData pairing_data) {
  // We must either be in Phase3 or Phase 2 with no keys to distribute if pairing has completed.
  if (!std::holds_alternative<Phase3>(current_phase_)) {
    ZX_ASSERT(InPhase2());
    ZX_ASSERT(!HasKeysToDistribute(*features_));
  }
  ZX_ASSERT(delegate_);
  ZX_ASSERT(features_.has_value());
  bt_log(DEBUG, "sm", "LE pairing complete");
  delegate_->OnPairingComplete(Status());
  // In Secure Connections, the LTK will be generated in Phase 2, not exchanged in Phase 3, so
  // we want to ensure that it is still put in the pairing_data.
  if (features_->secure_connections) {
    ZX_ASSERT(ltk_.has_value());
    pairing_data.peer_ltk = pairing_data.local_ltk = ltk_;
  } else {
    // The SM-internal LTK is used to validate future encryption events on the existing link.
    // Encryption with LTKs generated by LE legacy pairing uses the key received by the link-layer
    // master - so as initiator, this is the peer key, and as responder, this is the local key.
    const std::optional<LTK>& new_ltk =
        role_ == Role::kInitiator ? pairing_data.peer_ltk : pairing_data.local_ltk;
    if (new_ltk.has_value()) {
      OnNewLongTermKey(*new_ltk);
    }
  }

  if (features_->generate_ct_key.has_value()) {
    // If we are generating the CT key, we must be using secure connections, and as such the peer
    // and local LTKs will be equivalent.
    ZX_ASSERT(features_->secure_connections);
    ZX_ASSERT(pairing_data.peer_ltk == pairing_data.local_ltk);
    std::optional<UInt128> ct_key_value =
        util::LeLtkToBrEdrLinkKey(ltk_->key().value(), features_->generate_ct_key.value());
    if (ct_key_value) {
      pairing_data.cross_transport_key =
          sm::LTK(ltk_->security(), hci::LinkKey(*ct_key_value, 0, 0));
    } else {
      bt_log(WARN, "sm", "failed to generate cross-transport key");
    }
  }

  if (features_->will_bond) {
    delegate_->OnNewPairingData(pairing_data);
  } else {
    bt_log(
        INFO, "gap-le", " %s pairing complete in non-bondable mode with [%s%s%s%s%s]",
        features_->secure_connections ? "secure connections" : "legacy",
        pairing_data.peer_ltk ? "peer_ltk " : "", pairing_data.local_ltk ? "local_ltk " : "",
        pairing_data.irk ? "irk " : "",
        pairing_data.identity_address
            ? fxl::StringPrintf("(identity: %s) ", bt_str(*pairing_data.identity_address)).c_str()
            : "",
        pairing_data.csrk ? "csrk " : "");
  }
  // So we can pair again if need be.
  ResetState();

  NotifySecurityCallbacks();
}

void SecurityManagerImpl::NotifySecurityCallbacks() {
  // Separate out the requests that are satisfied by the current security level from those that
  // require a higher level. We'll retry pairing for the latter.
  std::queue<PendingRequest> satisfied;
  std::queue<PendingRequest> unsatisfied;
  while (!request_queue_.empty()) {
    auto& request = request_queue_.front();
    if (request.level <= security().level()) {
      satisfied.push(std::move(request));
    } else {
      unsatisfied.push(std::move(request));
    }
    request_queue_.pop();
  }

  request_queue_ = std::move(unsatisfied);

  // Notify the satisfied requests with success.
  while (!satisfied.empty()) {
    satisfied.front().callback(Status(), security());
    satisfied.pop();
  }

  if (!request_queue_.empty()) {
    UpgradeSecurityInternal();
  }
}

void SecurityManagerImpl::Reset(IOCapability io_capability) {
  Abort(ErrorCode::kUnspecifiedReason);
  io_cap_ = io_capability;
  ResetState();
}

void SecurityManagerImpl::ResetState() {
  StopTimer();
  features_.reset();
  sm_chan_->SetChannelHandler(weak_ptr_factory_.GetWeakPtr());
  current_phase_ = std::monostate{};
}

bool SecurityManagerImpl::AssignLongTermKey(const LTK& ltk) {
  if (SecurityUpgradeInProgress()) {
    bt_log(DEBUG, "sm", "Cannot directly assign LTK while pairing is in progress");
    return false;
  }

  OnNewLongTermKey(ltk);

  // The initiatior starts encryption when it receives a new LTK from GAP.
  if (role_ == Role::kInitiator && !le_link_->StartEncryption()) {
    bt_log(ERROR, "sm", "Failed to initiate authentication procedure");
    return false;
  }

  return true;
}

void SecurityManagerImpl::SetSecurityProperties(const SecurityProperties& sec) {
  if (sec != security()) {
    bt_log(DEBUG, "sm", "security properties changed - handle: %#.4x, new: %s, old: %s",
           le_link_->handle(), bt_str(sec), bt_str(security()));
    set_security(sec);
    delegate_->OnNewSecurityProperties(security());
  }
}

void SecurityManagerImpl::Abort(ErrorCode ecode) {
  std::visit(
      [=](auto& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<std::unique_ptr<Phase1>, T>) {
          arg->Abort(ecode);
        } else if constexpr (std::is_base_of_v<PairingPhase, T>) {
          arg.Abort(ecode);
        } else {
          bt_log(DEBUG, "sm", "Attempted to abort security upgrade while not in progress");
        }
      },
      current_phase_);
  // "Abort" should trigger OnPairingFailed.
}

std::optional<IdentityInfo> SecurityManagerImpl::OnIdentityRequest() {
  // This is called by the bearer to determine if we have local identity
  // information to distribute.
  ZX_ASSERT(delegate_);
  return delegate_->OnIdentityInformationRequest();
}

void SecurityManagerImpl::ConfirmPairing(ConfirmCallback confirm) {
  ZX_ASSERT(delegate_);
  delegate_->ConfirmPairing([id = next_pairing_id_, self = weak_ptr_factory_.GetWeakPtr(),
                             cb = std::move(confirm)](bool confirm) {
    if (!self || self->next_pairing_id_ != id) {
      bt_log(TRACE, "sm", "ignoring user confirmation for expired pairing: id = %lu", id);
      return;
    }
    cb(confirm);
  });
}

void SecurityManagerImpl::DisplayPasskey(uint32_t passkey, Delegate::DisplayMethod method,
                                         ConfirmCallback confirm) {
  ZX_ASSERT(delegate_);
  delegate_->DisplayPasskey(passkey, method,
                            [id = next_pairing_id_, self = weak_ptr_factory_.GetWeakPtr(), method,
                             cb = std::move(confirm)](bool confirm) {
                              if (!self || self->next_pairing_id_ != id) {
                                bt_log(TRACE, "sm",
                                       "ignoring %s response for expired pairing: id = %lu",
                                       util::DisplayMethodToString(method).c_str(), id);
                                return;
                              }
                              cb(confirm);
                            });
}

void SecurityManagerImpl::RequestPasskey(PasskeyResponseCallback respond) {
  ZX_ASSERT(delegate_);
  delegate_->RequestPasskey([id = next_pairing_id_, self = weak_ptr_factory_.GetWeakPtr(),
                             cb = std::move(respond)](int64_t passkey) {
    if (!self || self->next_pairing_id_ != id) {
      bt_log(TRACE, "sm", "ignoring passkey input response for expired pairing: id = %lu", id);
      return;
    }
    cb(passkey);
  });
}

void SecurityManagerImpl::OnRxBFrame(ByteBufferPtr sdu) {
  fit::result<ValidPacketReader, ErrorCode> maybe_reader = ValidPacketReader::ParseSdu(sdu);
  if (maybe_reader.is_error()) {
    bt_log(INFO, "sm", "dropped SMP packet: %s", bt_str(Status(maybe_reader.error())));
    return;
  }
  ValidPacketReader reader = maybe_reader.value();
  Code smp_code = reader.code();

  if (smp_code == kPairingRequest) {
    OnPairingRequest(reader.payload<PairingRequestParams>());
  } else if (smp_code == kSecurityRequest) {
    OnSecurityRequest(reader.payload<AuthReqField>());
  } else {
    bt_log(INFO, "sm", "dropped unexpected SMP code %#.2X when not pairing", smp_code);
  }
}

void SecurityManagerImpl::OnChannelClosed() {
  bt_log(DEBUG, "sm", "SMP channel closed while not pairing");
}

void SecurityManagerImpl::OnPairingFailed(Status status) {
  std::string phase_status = std::visit(
      [=](auto& arg) {
        using T = std::decay_t<decltype(arg)>;
        std::string s;
        if constexpr (std::is_same_v<std::unique_ptr<Phase1>, T>) {
          s = arg->ToString();
        } else if constexpr (std::is_base_of_v<PairingPhase, T>) {
          s = arg.ToString();
        } else {
          ZX_PANIC("security upgrade cannot fail when current_phase_ is std::monostate!");
        }
        return s;
      },
      current_phase_);
  bt_log(ERROR, "sm", "LE pairing failed: %s. Current pairing phase: %s", status.ToString().c_str(),
         phase_status.c_str());
  StopTimer();
  // TODO(fxbug.dev/910): implement "waiting interval" to prevent repeated attempts
  // as described in Vol 3, Part H, 2.3.6.

  ZX_ASSERT(delegate_);
  delegate_->OnPairingComplete(status);

  auto requests = std::move(request_queue_);
  while (!requests.empty()) {
    requests.front().callback(status, security());
    requests.pop();
  }

  if (SecurityUpgradeInProgress()) {
    ZX_ASSERT(le_link_);
    le_link_->set_le_ltk(hci::LinkKey());
  }
  ResetState();
  // Reset state before potentially disconnecting link to avoid causing pairing phase to fail twice.
  if (!status && status.error() == HostError::kTimedOut) {
    // Per v5.2 Vol. 3 Part H 3.4, after a pairing timeout "No further SMP commands shall be sent
    // over the L2CAP Security Manager Channel. A new Pairing process shall only be performed when a
    // new physical link has been established."
    bt_log(WARN, "sm", "pairing timed out! disconnecting link");
    sm_chan_->SignalLinkError();
  }
}

void SecurityManagerImpl::StartNewTimer() {
  if (timeout_task_.is_pending()) {
    ZX_ASSERT(timeout_task_.Cancel() == ZX_OK);
  }
  timeout_task_.PostDelayed(async_get_default_dispatcher(), kPairingTimeout);
}

void SecurityManagerImpl::StopTimer() {
  if (timeout_task_.is_pending()) {
    zx_status_t status = timeout_task_.Cancel();
    if (status != ZX_OK) {
      bt_log(TRACE, "sm", "smp: failed to stop timer: %s", zx_status_get_string(status));
    }
  }
}

void SecurityManagerImpl::OnPairingTimeout() {
  std::visit(
      [=](auto& arg) {
        using T = std::decay_t<decltype(arg)>;
        if constexpr (std::is_same_v<std::unique_ptr<Phase1>, T>) {
          arg->OnFailure(Status(HostError::kTimedOut));
        } else if constexpr (std::is_base_of_v<PairingPhase, T>) {
          arg.OnFailure(Status(HostError::kTimedOut));
        } else {
          ZX_PANIC("cannot timeout when current_phase_ is std::monostate!");
        }
      },
      current_phase_);
}

std::pair<DeviceAddress, DeviceAddress> SecurityManagerImpl::LEPairingAddresses() {
  ZX_ASSERT(SecurityUpgradeInProgress());
  const DeviceAddress *initiator = &le_link_->local_address(),
                      *responder = &le_link_->peer_address();
  if (role_ == Role::kResponder) {
    std::swap(initiator, responder);
  }
  return std::make_pair(*initiator, *responder);
}

void SecurityManagerImpl::OnNewLongTermKey(const LTK& ltk) {
  ltk_ = ltk;
  le_link_->set_le_ltk(ltk.key());
}

Status SecurityManagerImpl::ValidateExistingLocalLtk() {
  auto err = HostError::kNoError;
  if (!ltk_.has_value() || !le_link_->ltk().has_value()) {
    // The LTKs should always be present when this method is called.
    err = HostError::kNotFound;
  } else if (!(*le_link_->ltk() == ltk_->key())) {
    // As only SM should ever change the LE Link encryption key, these two values should always be
    // in sync, i.e. something in the system is acting unreliably if they get out of sync.
    err = HostError::kNotReliable;
  }
  Status status(err);
  if (!status) {
    // SM does not own the link, so although the checks above should never fail, disconnecting the
    // link (vs. ASSERTing these checks) is safer against non-SM code potentially touching the key.
    delegate_->OnAuthenticationFailure(hci::Status(hci::StatusCode::kPinOrKeyMissing));
    sm_chan_->SignalLinkError();
  }
  return status;
}

std::unique_ptr<SecurityManager> SecurityManager::Create(fxl::WeakPtr<hci::Connection> link,
                                                         fbl::RefPtr<l2cap::Channel> smp,
                                                         IOCapability io_capability,
                                                         fxl::WeakPtr<Delegate> delegate,
                                                         BondableMode bondable_mode,
                                                         gap::LeSecurityMode security_mode) {
  return std::unique_ptr<SecurityManagerImpl>(
      new SecurityManagerImpl(std::move(link), std::move(smp), io_capability, std::move(delegate),
                              bondable_mode, security_mode));
}

SecurityManager::SecurityManager(BondableMode bondable_mode, gap::LeSecurityMode security_mode)
    : bondable_mode_(bondable_mode), security_mode_(security_mode) {}

}  // namespace bt::sm
