// Copyright 2019 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 "src/connectivity/bluetooth/core/bt-host/gap/pairing_state.h"

#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/util.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/transport.h"

namespace bt::gap {

using hci_spec::AuthRequirements;
using hci_spec::IOCapability;
using sm::util::IOCapabilityForHci;

PairingState::PairingState(fxl::WeakPtr<Peer> peer, hci::BrEdrConnection* link, bool link_initiated,
                           fit::closure auth_cb, StatusCallback status_cb)
    : peer_id_(peer->identifier()),
      peer_(std::move(peer)),
      link_(link),
      outgoing_connection_(link_initiated),
      peer_missing_key_(false),
      state_(State::kIdle),
      send_auth_request_callback_(std::move(auth_cb)),
      status_callback_(std::move(status_cb)) {
  ZX_ASSERT(link_);
  ZX_ASSERT(send_auth_request_callback_);
  ZX_ASSERT(status_callback_);
  link_->set_encryption_change_callback(fit::bind_member<&PairingState::OnEncryptionChange>(this));
  cleanup_cb_ = [](PairingState* self) {
    self->link_->set_encryption_change_callback(nullptr);
    auto callbacks_to_signal =
        self->CompletePairingRequests(ToResult(HostError::kLinkDisconnected));

    bt_log(TRACE, "gap-bredr", "Signaling %zu unresolved pairing listeners for %#.4x",
           callbacks_to_signal.size(), self->handle());

    for (auto& cb : callbacks_to_signal) {
      cb();
    }
  };
}

PairingState::~PairingState() {
  if (cleanup_cb_) {
    cleanup_cb_(this);
  }
}

void PairingState::InitiatePairing(BrEdrSecurityRequirements security_requirements,
                                   StatusCallback status_cb) {
  if (state() == State::kIdle) {
    ZX_ASSERT(!is_pairing());

    // If the current link key already meets the security requirements, skip pairing and report
    // success.
    if (link_->ltk_type() &&
        SecurityPropertiesMeetRequirements(sm::SecurityProperties(*link_->ltk_type()),
                                           security_requirements)) {
      status_cb(handle(), fitx::ok());
      return;
    }
    // TODO(fxbug.dev/42403): If there is no pairing delegate set AND the current peer does not have
    // a bonded link key, there is no way to upgrade the link security, so we don't need to bother
    // calling `send_auth_request`.
    //
    // TODO(fxbug.dev/55770): If current IO capabilities would make meeting security requirements
    // impossible, skip pairing and report failure immediately.

    current_pairing_ = Pairing::MakeInitiator(security_requirements, outgoing_connection_);
    PairingRequest request{.security_requirements = security_requirements,
                           .status_callback = std::move(status_cb)};
    request_queue_.push_back(std::move(request));
    bt_log(DEBUG, "gap-bredr", "Initiating pairing on %#.4x (id %s)", handle(), bt_str(peer_id()));
    state_ = State::kInitiatorWaitLinkKeyRequest;
    send_auth_request_callback_();
    return;
  }

  // More than one consumer may wish to initiate pairing (e.g. concurrent outbound L2CAP channels),
  // but each should wait for the results of any ongoing pairing procedure instead of sending their
  // own Authentication Request.
  if (is_pairing()) {
    ZX_ASSERT(state() != State::kIdle);
    bt_log(INFO, "gap-bredr", "Already pairing %#.4x (id: %s); blocking callback on completion",
           handle(), bt_str(peer_id()));
    PairingRequest request{.security_requirements = security_requirements,
                           .status_callback = std::move(status_cb)};
    request_queue_.push_back(std::move(request));
  } else {
    // In the error state, we should expect no pairing to be created and cancel this particular
    // request immediately.
    ZX_ASSERT(state() == State::kFailed);
    status_cb(handle(), ToResult(HostError::kCanceled));
  }
}

void PairingState::InitiateNextPairingRequest() {
  ZX_ASSERT(state() == State::kIdle);
  ZX_ASSERT(!is_pairing());

  if (request_queue_.empty()) {
    return;
  }

  PairingRequest& request = request_queue_.front();

  current_pairing_ = Pairing::MakeInitiator(request.security_requirements, outgoing_connection_);
  bt_log(DEBUG, "gap-bredr", "Initiating queued pairing on %#.4x (id %s)", handle(),
         bt_str(peer_id()));
  state_ = State::kInitiatorWaitLinkKeyRequest;
  send_auth_request_callback_();
}

std::optional<IOCapability> PairingState::OnIoCapabilityRequest() {
  if (state() != State::kInitiatorWaitIoCapRequest &&
      state() != State::kResponderWaitIoCapRequest) {
    FailWithUnexpectedEvent(__func__);
    return std::nullopt;
  }

  // Log an error and return std::nullopt if we can't respond to a pairing request because there's
  // no pairing delegate. This corresponds to the non-bondable state as outlined in spec v5.2 Vol.
  // 3 Part C 4.3.1.
  if (!pairing_delegate()) {
    bt_log(WARN, "gap-bredr", "No pairing delegate set; not pairing link %#.4x (peer: %s)",
           handle(), bt_str(peer_id()));
    // We set the state_ to Idle instead of Failed because it is possible that a PairingDelegate
    // will be set before the next pairing attempt, allowing it to succeed.
    state_ = State::kIdle;
    SignalStatus(ToResult(HostError::kNotReady));
    return std::nullopt;
  }

  current_pairing_->local_iocap = sm::util::IOCapabilityForHci(pairing_delegate()->io_capability());
  if (state() == State::kInitiatorWaitIoCapRequest) {
    ZX_ASSERT(initiator());
    state_ = State::kInitiatorWaitIoCapResponse;
  } else {
    ZX_ASSERT(is_pairing());
    ZX_ASSERT(!initiator());
    current_pairing_->ComputePairingData();

    state_ = GetStateForPairingEvent(current_pairing_->expected_event);
  }

  return current_pairing_->local_iocap;
}

void PairingState::OnIoCapabilityResponse(IOCapability peer_iocap) {
  // If we preivously provided a key for peer to pair, but that didn't work, they may try to
  // re-pair.  Cancel the previous pairing if they try to restart.
  if (state() == State::kWaitEncryption) {
    ZX_ASSERT(is_pairing());
    current_pairing_ = nullptr;
    state_ = State::kIdle;
  }
  if (state() == State::kIdle) {
    ZX_ASSERT(!is_pairing());
    current_pairing_ = Pairing::MakeResponder(peer_iocap, outgoing_connection_);

    // Defer gathering local IO Capability until OnIoCapabilityRequest, where
    // the pairing can be rejected if there's no pairing delegate.
    state_ = State::kResponderWaitIoCapRequest;
  } else if (state() == State::kInitiatorWaitIoCapResponse) {
    ZX_ASSERT(initiator());

    current_pairing_->peer_iocap = peer_iocap;
    current_pairing_->ComputePairingData();

    state_ = GetStateForPairingEvent(current_pairing_->expected_event);
  } else {
    FailWithUnexpectedEvent(__func__);
  }
}

void PairingState::OnUserConfirmationRequest(uint32_t numeric_value, UserConfirmationCallback cb) {
  if (state() != State::kWaitUserConfirmationRequest) {
    FailWithUnexpectedEvent(__func__);
    cb(false);
    return;
  }
  ZX_ASSERT(is_pairing());

  // TODO(fxbug.dev/37447): Reject pairing if pairing delegate went away.
  ZX_ASSERT(pairing_delegate());
  state_ = State::kWaitPairingComplete;
  bt_log_scope("%#.4x, id: %s", handle(), bt_str(peer_id()));

  if (current_pairing_->action == PairingAction::kAutomatic) {
    if (!outgoing_connection_) {
      bt_log(ERROR, "gap-bredr", "automatically rejecting incoming link pairing");
    } else {
      bt_log(DEBUG, "gap-bredr", "automatically confirming outgoing link pairing");
    }
    cb(outgoing_connection_);
    return;
  }
  auto confirm_cb = [cb = std::move(cb), log_ctx = capture_log_context(),
                     pairing = current_pairing_->GetWeakPtr()](bool confirm) mutable {
    if (!pairing) {
      return;
    }
    add_parent_context(log_ctx);
    bt_log(DEBUG, "gap-bredr", "%sing User Confirmation Request", confirm ? "Confirm" : "Cancel");
    cb(confirm);
  };
  // PairingAction::kDisplayPasskey indicates that this device has a display and performs "Numeric
  // Comparison with automatic confirmation" but auto-confirmation is delegated to PairingDelegate.
  if (current_pairing_->action == PairingAction::kDisplayPasskey ||
      current_pairing_->action == PairingAction::kComparePasskey) {
    pairing_delegate()->DisplayPasskey(peer_id(), numeric_value,
                                       PairingDelegate::DisplayMethod::kComparison,
                                       std::move(confirm_cb));
  } else if (current_pairing_->action == PairingAction::kGetConsent) {
    pairing_delegate()->ConfirmPairing(peer_id(), std::move(confirm_cb));
  } else {
    ZX_PANIC("%#.4x (id: %s): unexpected action %d", handle(), bt_str(peer_id()),
             current_pairing_->action);
  }
}

void PairingState::OnUserPasskeyRequest(UserPasskeyCallback cb) {
  if (state() != State::kWaitUserPasskeyRequest) {
    FailWithUnexpectedEvent(__func__);
    cb(std::nullopt);
    return;
  }
  ZX_ASSERT(is_pairing());

  // TODO(fxbug.dev/37447): Reject pairing if pairing delegate went away.
  ZX_ASSERT(pairing_delegate());
  state_ = State::kWaitPairingComplete;

  ZX_ASSERT_MSG(current_pairing_->action == PairingAction::kRequestPasskey,
                "%#.4x (id: %s): unexpected action %d", handle(), bt_str(peer_id()),
                current_pairing_->action);
  auto pairing = current_pairing_->GetWeakPtr();
  auto passkey_cb = [this, cb = std::move(cb), pairing](int64_t passkey) mutable {
    if (!pairing) {
      return;
    }
    bt_log(DEBUG, "gap-bredr", "%#.4x (id: %s): Replying %" PRId64 " to User Passkey Request",
           handle(), bt_str(peer_id()), passkey);
    if (passkey >= 0) {
      cb(static_cast<uint32_t>(passkey));
    } else {
      cb(std::nullopt);
    }
  };
  pairing_delegate()->RequestPasskey(peer_id(), std::move(passkey_cb));
}

void PairingState::OnUserPasskeyNotification(uint32_t numeric_value) {
  if (state() != State::kWaitUserPasskeyNotification) {
    FailWithUnexpectedEvent(__func__);
    return;
  }
  ZX_ASSERT(is_pairing());

  // TODO(fxbug.dev/37447): Reject pairing if pairing delegate went away.
  ZX_ASSERT(pairing_delegate());
  state_ = State::kWaitPairingComplete;

  auto pairing = current_pairing_->GetWeakPtr();
  auto confirm_cb = [this, pairing](bool confirm) {
    if (!pairing) {
      return;
    }
    bt_log(DEBUG, "gap-bredr", "%#.4x (id: %s): Can't %s pairing from Passkey Notification side",
           handle(), bt_str(peer_id()), confirm ? "confirm" : "cancel");
  };
  pairing_delegate()->DisplayPasskey(
      peer_id(), numeric_value, PairingDelegate::DisplayMethod::kPeerEntry, std::move(confirm_cb));
}

void PairingState::OnSimplePairingComplete(hci_spec::StatusCode status_code) {
  // The pairing process may fail early, which the controller will deliver as an Simple Pairing
  // Complete with a non-success status. Log and proxy the error code.
  if (const fitx::result result = ToResult(status_code);
      is_pairing() &&
      bt_is_error(result, INFO, "gap-bredr", "Pairing failed on link %#.4x (id: %s)", handle(),
                  bt_str(peer_id()))) {
    // TODO(fxbug.dev/37447): Checking pairing_delegate() for reset like this isn't thread safe.
    if (pairing_delegate()) {
      pairing_delegate()->CompletePairing(peer_id(), ToResult(HostError::kFailed));
    }
    state_ = State::kFailed;
    SignalStatus(result);
    return;
  }

  // Handle successful Authentication Complete events that are not expected.
  if (state() != State::kWaitPairingComplete) {
    FailWithUnexpectedEvent(__func__);
    return;
  }
  ZX_ASSERT(is_pairing());

  pairing_delegate()->CompletePairing(peer_id(), fitx::ok());
  state_ = State::kWaitLinkKey;
}

std::optional<hci_spec::LinkKey> PairingState::OnLinkKeyRequest() {
  if (state() != State::kIdle && state() != State::kInitiatorWaitLinkKeyRequest) {
    FailWithUnexpectedEvent(__func__);
    return std::nullopt;
  }

  ZX_ASSERT(peer_);

  std::optional<sm::LTK> link_key;

  if (peer_missing_key_) {
    bt_log(INFO, "gap-bredr", "peer %s missing key, ignoring our key", bt_str(peer_->identifier()));
  } else if (peer_->bredr() && peer_->bredr()->bonded()) {
    bt_log(INFO, "gap-bredr", "recalling link key for bonded peer %s", bt_str(peer_->identifier()));

    ZX_ASSERT(peer_->bredr()->link_key().has_value());
    link_key = peer_->bredr()->link_key();
    ZX_ASSERT(link_key->security().enc_key_size() == hci_spec::kBrEdrLinkKeySize);

    const auto link_key_type = link_key->security().GetLinkKeyType();
    ZX_ASSERT(link_key_type.has_value());

    link_->set_link_key(link_key->key(), link_key_type.value());
  } else {
    bt_log(INFO, "gap-bredr", "peer %s not bonded", bt_str(peer_->identifier()));
  }

  // The link key request may be received outside of Simple Pairing (e.g. when the peer initiates
  // the authentication procedure).
  if (state() == State::kIdle) {
    if (link_key.has_value()) {
      ZX_ASSERT(!is_pairing());
      current_pairing_ = Pairing::MakeResponderForBonded();
      state_ = State::kWaitEncryption;
      return link_key->key();
    }
    return std::optional<hci_spec::LinkKey>();
  }

  ZX_ASSERT(is_pairing());

  if (link_key.has_value() && SecurityPropertiesMeetRequirements(
                                  link_key->security(), current_pairing_->preferred_security)) {
    // Skip Simple Pairing and just perform authentication with existing key.
    state_ = State::kInitiatorWaitAuthComplete;
    return link_key->key();
  }

  // Request that the controller perform Simple Pairing to generate a new key.
  state_ = State::kInitiatorWaitIoCapRequest;
  return std::nullopt;
}

void PairingState::OnLinkKeyNotification(const UInt128& link_key, hci_spec::LinkKeyType key_type) {
  // TODO(fxbug.dev/36360): We assume the controller is never in pairing debug mode because it's a
  // security hazard to pair and bond using Debug Combination link keys.
  ZX_ASSERT_MSG(key_type != hci_spec::LinkKeyType::kDebugCombination,
                "Pairing on link %#.4x (id: %s) resulted in insecure Debug Combination link key",
                handle(), bt_str(peer_id()));

  // When not pairing, only connection link key changes are allowed.
  if (state() == State::kIdle && key_type == hci_spec::LinkKeyType::kChangedCombination) {
    if (!link_->ltk()) {
      bt_log(WARN, "gap-bredr",
             "Got Changed Combination key but link %#.4x (id: %s) has no current key", handle(),
             bt_str(peer_id()));
      state_ = State::kFailed;
      SignalStatus(ToResult(HostError::kInsufficientSecurity));
      return;
    }

    bt_log(DEBUG, "gap-bredr", "Changing link key on %#.4x (id: %s)", handle(), bt_str(peer_id()));
    link_->set_link_key(hci_spec::LinkKey(link_key, 0, 0), key_type);
    return;
  }

  if (state() != State::kWaitLinkKey) {
    FailWithUnexpectedEvent(__func__);
    return;
  }

  // The association model and resulting link security properties are computed by both the Link
  // Manager (controller) and the host subsystem, so check that they agree.
  ZX_ASSERT(is_pairing());
  const sm::SecurityProperties sec_props = sm::SecurityProperties(key_type);
  current_pairing_->security_properties = sec_props;

  // Link keys resulting from legacy pairing are assigned lowest security level and we reject them.
  if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
    bt_log(WARN, "gap-bredr", "Link key (type %hhu) for %#.4x (id: %s) has insufficient security",
           key_type, handle(), bt_str(peer_id()));
    state_ = State::kFailed;
    SignalStatus(ToResult(HostError::kInsufficientSecurity));
    return;
  }

  // If we performed an association procedure for MITM protection then expect the controller to
  // produce a corresponding "authenticated" link key. Inversely, do not accept a link key reported
  // as authenticated if we haven't performed the corresponding association procedure because it
  // may provide a false high expectation of security to the user or application.
  if (sec_props.authenticated() != current_pairing_->authenticated) {
    bt_log(WARN, "gap-bredr", "Expected %sauthenticated link key for %#.4x (id: %s), got %hhu",
           current_pairing_->authenticated ? "" : "un", handle(), bt_str(peer_id()), key_type);
    state_ = State::kFailed;
    SignalStatus(ToResult(HostError::kInsufficientSecurity));
    return;
  }

  link_->set_link_key(hci_spec::LinkKey(link_key, 0, 0), key_type);
  if (initiator()) {
    state_ = State::kInitiatorWaitAuthComplete;
  } else {
    EnableEncryption();
  }
}

void PairingState::OnAuthenticationComplete(hci_spec::StatusCode status_code) {
  if (is_pairing() && peer_->bredr() && peer_->bredr()->bonded() &&
      status_code == hci_spec::StatusCode::kPinOrKeyMissing) {
    // We have provided our link key, but the remote side says they don't have a key.
    // Pretend we don't have a link key, then start the pairing over.
    // We will get consent even if we are otherwise kAutomatic
    bt_log(INFO, "gap-bredr",
           "Re-initiating pairing on %#.4x (id %s) as remote side reports no key.", handle(),
           bt_str(peer_id()));
    peer_missing_key_ = true;
    current_pairing_->allow_automatic = false;
    state_ = State::kInitiatorWaitLinkKeyRequest;
    send_auth_request_callback_();
    return;
  }
  // The pairing process may fail early, which the controller will deliver as an Authentication
  // Complete with a non-success status. Log and proxy the error code.
  if (const fitx::result result = ToResult(status_code);
      bt_is_error(result, INFO, "gap-bredr", "Authentication failed on link %#.4x (id: %s)",
                  handle(), bt_str(peer_id()))) {
    state_ = State::kFailed;
    SignalStatus(result);
    return;
  }

  // Handle successful Authentication Complete events that are not expected.
  if (state() != State::kInitiatorWaitAuthComplete) {
    FailWithUnexpectedEvent(__func__);
    return;
  }
  ZX_ASSERT(initiator());
  EnableEncryption();
}

void PairingState::OnEncryptionChange(hci::Result<bool> result) {
  if (state() != State::kWaitEncryption) {
    // Ignore encryption changes when not expecting them because they may be triggered by the peer
    // at any time (v5.0 Vol 2, Part F, Sec 4.4).
    bt_log(TRACE, "gap-bredr", "%#.4x (id: %s): %s(%s, %s) in state \"%s\"; taking no action",
           handle(), bt_str(peer_id()), __func__, bt_str(result),
           result.is_ok() ? (result.value() ? "true" : "false") : "?", ToString(state()));
    return;
  }

  if (result.is_ok() && !result.value()) {
    // With Secure Connections, encryption should never be disabled (v5.0 Vol 2,
    // Part E, Sec 7.1.16) at all.
    bt_log(WARN, "gap-bredr", "Pairing failed due to encryption disable on link %#.4x (id: %s)",
           handle(), bt_str(peer_id()));
    result = fitx::error(Error(HostError::kFailed));
  }

  // Perform state transition.
  if (result.is_ok()) {
    // Reset state for another pairing.
    state_ = State::kIdle;
  } else {
    state_ = State::kFailed;
  }

  SignalStatus(result.is_ok() ? hci::Result<>(fitx::ok()) : result.take_error());
}

std::unique_ptr<PairingState::Pairing> PairingState::Pairing::MakeInitiator(
    BrEdrSecurityRequirements security_requirements, bool link_initiated) {
  // Private ctor is inaccessible to std::make_unique.
  std::unique_ptr<Pairing> pairing(new Pairing(link_initiated));
  pairing->initiator = true;
  pairing->preferred_security = security_requirements;
  return pairing;
}

std::unique_ptr<PairingState::Pairing> PairingState::Pairing::MakeResponder(
    hci_spec::IOCapability peer_iocap, bool link_initiated) {
  // Private ctor is inaccessible to std::make_unique.
  std::unique_ptr<Pairing> pairing(new Pairing(link_initiated));
  pairing->initiator = false;
  pairing->peer_iocap = peer_iocap;
  // Don't try to upgrade security as responder.
  pairing->preferred_security = {.authentication = false, .secure_connections = false};
  return pairing;
}

std::unique_ptr<PairingState::Pairing> PairingState::Pairing::MakeResponderForBonded() {
  std::unique_ptr<Pairing> pairing(new Pairing(/* link initiated */ false));
  pairing->initiator = false;
  // Don't try to upgrade security as responder.
  pairing->preferred_security = {.authentication = false, .secure_connections = false};
  return pairing;
}

void PairingState::Pairing::ComputePairingData() {
  if (initiator) {
    action = GetInitiatorPairingAction(local_iocap, peer_iocap);
  } else {
    action = GetResponderPairingAction(peer_iocap, local_iocap);
  }
  if (!allow_automatic && action == PairingAction::kAutomatic) {
    action = PairingAction::kGetConsent;
  }
  expected_event = GetExpectedEvent(local_iocap, peer_iocap);
  ZX_DEBUG_ASSERT(GetStateForPairingEvent(expected_event) != State::kFailed);
  authenticated = IsPairingAuthenticated(local_iocap, peer_iocap);
  bt_log(DEBUG, "gap-bredr",
         "As %s with local %hhu/peer %hhu capabilities, expecting an %sauthenticated %u pairing "
         "using %#x%s",
         initiator ? "initiator" : "responder", local_iocap, peer_iocap, authenticated ? "" : "un",
         action, expected_event, allow_automatic ? "" : " (auto not allowed)");
}

const char* PairingState::ToString(PairingState::State state) {
  switch (state) {
    case State::kIdle:
      return "Idle";
    case State::kInitiatorWaitLinkKeyRequest:
      return "InitiatorWaitLinkKeyRequest";
    case State::kInitiatorWaitIoCapRequest:
      return "InitiatorWaitIoCapRequest";
    case State::kInitiatorWaitIoCapResponse:
      return "InitiatorWaitIoCapResponse";
    case State::kResponderWaitIoCapRequest:
      return "ResponderWaitIoCapRequest";
    case State::kWaitUserConfirmationRequest:
      return "WaitUserConfirmationRequest";
    case State::kWaitUserPasskeyRequest:
      return "WaitUserPasskeyRequest";
    case State::kWaitUserPasskeyNotification:
      return "WaitUserPasskeyNotification";
    case State::kWaitPairingComplete:
      return "WaitPairingComplete";
    case State::kWaitLinkKey:
      return "WaitLinkKey";
    case State::kInitiatorWaitAuthComplete:
      return "InitiatorWaitAuthComplete";
    case State::kWaitEncryption:
      return "WaitEncryption";
    case State::kFailed:
      return "Failed";
    default:
      break;
  }
  return "";
}

PairingState::State PairingState::GetStateForPairingEvent(hci_spec::EventCode event_code) {
  switch (event_code) {
    case hci_spec::kUserConfirmationRequestEventCode:
      return State::kWaitUserConfirmationRequest;
    case hci_spec::kUserPasskeyRequestEventCode:
      return State::kWaitUserPasskeyRequest;
    case hci_spec::kUserPasskeyNotificationEventCode:
      return State::kWaitUserPasskeyNotification;
    default:
      break;
  }
  return State::kFailed;
}

void PairingState::SignalStatus(hci::Result<> status) {
  bt_log(INFO, "gap-bredr", "Signaling pairing listeners for %#.4x (id: %s) with %s", handle(),
         bt_str(peer_id()), bt_str(status));

  // Collect the callbacks before invoking them so that CompletePairingRequests() can safely access
  // members.
  auto callbacks_to_signal = CompletePairingRequests(status);

  // This PairingState may be destroyed by these callbacks (e.g. if signaling an error causes a
  // disconnection), so care must be taken not to access any members.
  status_callback_(handle(), status);
  for (auto& cb : callbacks_to_signal) {
    cb();
  }
}

std::vector<fit::closure> PairingState::CompletePairingRequests(hci::Result<> status) {
  std::vector<fit::closure> callbacks_to_signal;

  if (!is_pairing()) {
    ZX_ASSERT(request_queue_.empty());
    return callbacks_to_signal;
  }

  if (status.is_error()) {
    // On pairing failure, signal all requests.
    for (auto& request : request_queue_) {
      callbacks_to_signal.push_back(
          [handle = handle(), status, cb = std::move(request.status_callback)]() {
            cb(handle, status);
          });
    }
    request_queue_.clear();
    current_pairing_ = nullptr;
    return callbacks_to_signal;
  }

  ZX_ASSERT(state_ == State::kIdle);
  ZX_ASSERT(link_->ltk_type().has_value());

  auto security_properties = sm::SecurityProperties(link_->ltk_type().value());

  // If a new link key was received, notify all callbacks because we always negotiate the best
  // security possible. Even though pairing succeeded, send an error status if the individual
  // request security requirements are not satisfied.
  // TODO(fxbug.dev/1249): Only notify failure to callbacks of requests that have the same (or
  // none) MITM requirements as the current pairing.
  bool link_key_received = current_pairing_->security_properties.has_value();
  if (link_key_received) {
    for (auto& request : request_queue_) {
      auto sec_props_satisfied =
          SecurityPropertiesMeetRequirements(security_properties, request.security_requirements);
      auto request_status =
          sec_props_satisfied ? status : ToResult(HostError::kInsufficientSecurity);

      callbacks_to_signal.push_back(
          [handle = handle(), request_status, cb = std::move(request.status_callback)]() {
            cb(handle, request_status);
          });
    }
    request_queue_.clear();
  } else {
    // If no new link key was received, then only authentication with an old key was performed
    // (Simple Pairing was not required), and unsatisfied requests should initiate a new pairing
    // rather than failing. If any pairing requests are satisfied by the existing key, notify them.
    auto it = request_queue_.begin();
    while (it != request_queue_.end()) {
      if (!SecurityPropertiesMeetRequirements(security_properties, it->security_requirements)) {
        it++;
        continue;
      }

      callbacks_to_signal.push_back(
          [handle = handle(), status, cb = std::move(it->status_callback)]() {
            cb(handle, status);
          });
      it = request_queue_.erase(it);
    }
  }
  current_pairing_ = nullptr;
  InitiateNextPairingRequest();

  return callbacks_to_signal;
}

void PairingState::EnableEncryption() {
  if (!link_->StartEncryption()) {
    bt_log(ERROR, "gap-bredr", "%#.4x (id: %s): Failed to enable encryption (state \"%s\")",
           handle(), bt_str(peer_id()), ToString(state()));
    status_callback_(link_->handle(), ToResult(HostError::kFailed));
    state_ = State::kFailed;
    return;
  }
  state_ = State::kWaitEncryption;
}

void PairingState::FailWithUnexpectedEvent(const char* handler_name) {
  bt_log(ERROR, "gap-bredr", "%#.4x (id: %s): Unexpected event %s while in state \"%s\"", handle(),
         bt_str(peer_id()), handler_name, ToString(state()));
  state_ = State::kFailed;
  SignalStatus(ToResult(HostError::kNotSupported));
}

PairingAction GetInitiatorPairingAction(IOCapability initiator_cap, IOCapability responder_cap) {
  if (initiator_cap == IOCapability::kNoInputNoOutput) {
    return PairingAction::kAutomatic;
  }
  if (responder_cap == IOCapability::kNoInputNoOutput) {
    if (initiator_cap == IOCapability::kDisplayYesNo) {
      return PairingAction::kGetConsent;
    }
    return PairingAction::kAutomatic;
  }
  if (initiator_cap == IOCapability::kKeyboardOnly) {
    return PairingAction::kRequestPasskey;
  }
  if (responder_cap == IOCapability::kDisplayOnly) {
    if (initiator_cap == IOCapability::kDisplayYesNo) {
      return PairingAction::kComparePasskey;
    }
    return PairingAction::kAutomatic;
  }
  return PairingAction::kDisplayPasskey;
}

PairingAction GetResponderPairingAction(IOCapability initiator_cap, IOCapability responder_cap) {
  if (initiator_cap == IOCapability::kNoInputNoOutput &&
      responder_cap == IOCapability::kKeyboardOnly) {
    return PairingAction::kGetConsent;
  }
  if (initiator_cap == IOCapability::kDisplayYesNo &&
      responder_cap == IOCapability::kDisplayYesNo) {
    return PairingAction::kComparePasskey;
  }
  return GetInitiatorPairingAction(responder_cap, initiator_cap);
}

hci_spec::EventCode GetExpectedEvent(IOCapability local_cap, IOCapability peer_cap) {
  if (local_cap == IOCapability::kNoInputNoOutput || peer_cap == IOCapability::kNoInputNoOutput) {
    return hci_spec::kUserConfirmationRequestEventCode;
  }
  if (local_cap == IOCapability::kKeyboardOnly) {
    return hci_spec::kUserPasskeyRequestEventCode;
  }
  if (peer_cap == IOCapability::kKeyboardOnly) {
    return hci_spec::kUserPasskeyNotificationEventCode;
  }
  return hci_spec::kUserConfirmationRequestEventCode;
}

bool IsPairingAuthenticated(IOCapability local_cap, IOCapability peer_cap) {
  if (local_cap == IOCapability::kNoInputNoOutput || peer_cap == IOCapability::kNoInputNoOutput) {
    return false;
  }
  if (local_cap == IOCapability::kDisplayYesNo && peer_cap == IOCapability::kDisplayYesNo) {
    return true;
  }
  if (local_cap == IOCapability::kKeyboardOnly || peer_cap == IOCapability::kKeyboardOnly) {
    return true;
  }
  return false;
}

AuthRequirements GetInitiatorAuthRequirements(IOCapability local_cap) {
  if (local_cap == IOCapability::kNoInputNoOutput) {
    return AuthRequirements::kGeneralBonding;
  }
  return AuthRequirements::kMITMGeneralBonding;
}

AuthRequirements GetResponderAuthRequirements(IOCapability local_cap, IOCapability peer_cap) {
  if (IsPairingAuthenticated(local_cap, peer_cap)) {
    return AuthRequirements::kMITMGeneralBonding;
  }
  return AuthRequirements::kGeneralBonding;
}

}  // namespace bt::gap
