// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_bluetooth_sapphire/internal/host/sm/security_manager.h"

#include <chrono>
#include <cstdlib>

#include "pw_bluetooth_sapphire/internal/host/common/macros.h"
#include "pw_bluetooth_sapphire/internal/host/common/random.h"
#include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
#include "pw_bluetooth_sapphire/internal/host/hci-spec/link_key.h"
#include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
#include "pw_bluetooth_sapphire/internal/host/hci/fake_low_energy_connection.h"
#include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel_test.h"
#include "pw_bluetooth_sapphire/internal/host/sm/ecdh_key.h"
#include "pw_bluetooth_sapphire/internal/host/sm/error.h"
#include "pw_bluetooth_sapphire/internal/host/sm/packet.h"
#include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
#include "pw_bluetooth_sapphire/internal/host/sm/types.h"
#include "pw_bluetooth_sapphire/internal/host/sm/util.h"
#include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
#include "pw_bluetooth_sapphire/internal/host/testing/mock_controller.h"
#include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
#include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
#include "pw_bluetooth_sapphire/internal/host/transport/error.h"

// inclusive-language: disable
namespace bt::sm {
namespace {

const DeviceAddress kLocalAddr(DeviceAddress::Type::kLEPublic,
                               {0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1});
const DeviceAddress kPeerAddr(DeviceAddress::Type::kLERandom,
                              {0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1});

const PairingRandomValue kHardCodedPairingRandom = {0x0,
                                                    0x1,
                                                    0x2,
                                                    0x3,
                                                    0x4,
                                                    0x5,
                                                    0x6,
                                                    0x7,
                                                    0x8,
                                                    0x9,
                                                    0xA,
                                                    0xB,
                                                    0xC,
                                                    0xD,
                                                    0xE,
                                                    0xF};

constexpr hci_spec::ConnectionHandle kConnectionHandle(1);

class SecurityManagerTest : public l2cap::testing::FakeChannelTest,
                            public sm::Delegate {
 public:
  SecurityManagerTest() : weak_delegate_(this) {}
  ~SecurityManagerTest() override = default;

 protected:
  void SetUp() override {
    l2cap::testing::FakeChannelTest::SetUp();
    InitializeTransport();
  }
  void TearDown() override {
    RunUntilIdle();
    DestroySecurityManager();
    fake_link_.reset();
    transport_.reset();
    l2cap::testing::FakeChannelTest::TearDown();
  }

  void NewSecurityManager(Role role,
                          IOCapability ioc,
                          BondableMode bondable_mode) {
    // Setup fake SMP channel.
    ChannelOptions options(l2cap::kLESMPChannelId);
    fake_chan_ = CreateFakeChannel(options);
    fake_chan_->SetSendCallback(
        fit::bind_member<&SecurityManagerTest::OnDataReceived>(this),
        dispatcher());

    // Setup a fake logical link.
    auto link_role = role == Role::kInitiator
                         ? pw::bluetooth::emboss::ConnectionRole::CENTRAL
                         : pw::bluetooth::emboss::ConnectionRole::PERIPHERAL;

    if (fake_link_) {
      auto status_event = testing::CommandStatusPacket(
          hci_spec::kDisconnect, pw::bluetooth::emboss::StatusCode::SUCCESS);
      auto disconnect_complete =
          testing::DisconnectionCompletePacket(kConnectionHandle);
      EXPECT_CMD_PACKET_OUT(controller_,
                            testing::DisconnectPacket(kConnectionHandle),
                            &status_event,
                            &disconnect_complete);
      fake_link_.reset();
      RunUntilIdle();
    }
    fake_link_ = std::make_unique<hci::testing::FakeLowEnergyConnection>(
        kConnectionHandle,
        kLocalAddr,
        kPeerAddr,
        link_role,
        transport_->GetWeakPtr());

    pairing_ = SecurityManager::Create(fake_link_->GetWeakPtr(),
                                       fake_chan_->GetWeakPtr(),
                                       ioc,
                                       weak_delegate_.GetWeakPtr(),
                                       bondable_mode,
                                       gap::LESecurityMode::Mode1,
                                       dispatcher());
  }

  void DestroySecurityManager() { pairing_ = nullptr; }

  // sm::Delegate override:
  void ConfirmPairing(ConfirmCallback confirm) override {
    if (confirm_delegate_) {
      confirm_delegate_(std::move(confirm));
    } else {
      confirm(true);
    }
  }

  // sm::Delegate override:
  void DisplayPasskey(uint32_t passkey,
                      DisplayMethod method,
                      ConfirmCallback confirm) override {
    if (display_delegate_) {
      display_delegate_(passkey, method, std::move(confirm));
    } else {
      ADD_FAILURE() << "No passkey display delegate set for "
                    << util::DisplayMethodToString(method) << " pairing";
    }
  }

  // sm::Delegate override:
  void RequestPasskey(PasskeyResponseCallback respond) override {
    if (request_passkey_delegate_) {
      request_passkey_delegate_(std::move(respond));
    } else {
      ADD_FAILURE()
          << "No passkey entry delegate set for passkey entry pairing";
    }
  }

  std::optional<IdentityInfo> OnIdentityInformationRequest() override {
    local_id_info_callback_count_++;
    return local_id_info_;
  }

  // Called by |pairing_| when the pairing procedure ends.
  void OnPairingComplete(Result<> status) override {
    pairing_complete_count_++;
    pairing_complete_status_ = status;
  }

  // Called by |pairing_| when a new LTK is obtained.
  void OnNewPairingData(const PairingData& pairing_data) override {
    pairing_data_callback_count_++;
    pairing_data_ = pairing_data;
  }

  // Called by |pairing_| when any encryption procedure fails.
  void OnAuthenticationFailure(hci::Result<> status) override {
    auth_failure_callback_count_++;
    auth_failure_status_ = status;
  }

  // Called by |pairing_| when the link security properties change.
  void OnNewSecurityProperties(const SecurityProperties& sec) override {
    new_sec_props_count_++;
    new_sec_props_ = sec;
  }

  void UpgradeSecurity(SecurityLevel level) {
    BT_DEBUG_ASSERT(pairing_);
    pairing_->UpgradeSecurity(level, [this](auto status, const auto& props) {
      security_callback_count_++;
      security_status_ = status;
      sec_props_ = props;
    });
  }

  // Called when SMP sends a packet over the fake channel.
  void OnDataReceived(std::unique_ptr<const ByteBuffer> packet) {
    BT_DEBUG_ASSERT(packet);

    PacketReader reader(packet.get());
    switch (reader.code()) {
      case kPairingFailed:
        pairing_failed_count_++;
        received_error_code_ = reader.payload<PairingFailedParams>();
        break;
      case kSecurityRequest:
        security_request_count_++;
        security_auth_req_ = reader.payload<AuthReqField>();
        break;
      case kPairingRequest:
        pairing_request_count_++;
        packet->Copy(&local_pairing_cmd_);
        break;
      case kPairingResponse:
        pairing_response_count_++;
        packet->Copy(&local_pairing_cmd_);
        break;
      case kPairingPublicKey:
        pairing_public_key_count_++;
        public_ecdh_key_ = EcdhKey::ParseFromPublicKey(
            reader.payload<PairingPublicKeyParams>());
        break;
      case kPairingConfirm:
        pairing_confirm_count_++;
        pairing_confirm_ = reader.payload<PairingConfirmValue>();
        break;
      case kPairingRandom:
        pairing_random_count_++;
        pairing_random_ = reader.payload<PairingRandomValue>();
        break;
      case kPairingDHKeyCheck:
        pairing_dhkey_check_count_++;
        pairing_dhkey_check_ = reader.payload<PairingDHKeyCheckValueE>();
        break;
      case kEncryptionInformation:
        enc_info_count_++;
        enc_info_ = reader.payload<EncryptionInformationParams>();
        break;
      case kCentralIdentification: {
        const auto& params = reader.payload<CentralIdentificationParams>();
        central_ident_count_++;
        ediv_ = le16toh(params.ediv);
        rand_ = le64toh(params.rand);
        break;
      }
      case kIdentityInformation:
        id_info_count_++;
        id_info_ = reader.payload<UInt128>();
        break;
      case kIdentityAddressInformation: {
        const auto& params = reader.payload<IdentityAddressInformationParams>();
        id_addr_info_count_++;
        id_addr_info_ = DeviceAddress(params.type == AddressType::kStaticRandom
                                          ? DeviceAddress::Type::kLERandom
                                          : DeviceAddress::Type::kLEPublic,
                                      params.bd_addr);
        break;
      }
      default:
        FAIL() << "Sent unsupported SMP command";
    }
  }

  // Emulates the receipt of pairing features (both as initiator and responder).
  void ReceivePairingFeatures(const PairingRequestParams& params,
                              bool peer_initiator = false) {
    PacketWriter writer(peer_initiator ? kPairingRequest : kPairingResponse,
                        &peer_pairing_cmd_);
    *writer.mutable_payload<PairingRequestParams>() = params;
    fake_chan()->Receive(peer_pairing_cmd_);
  }

  void ReceivePairingFeatures(IOCapability ioc = IOCapability::kNoInputNoOutput,
                              AuthReqField auth_req = 0,
                              uint8_t max_enc_key_size = kMaxEncryptionKeySize,
                              bool peer_initiator = false) {
    PairingRequestParams pairing_params;
    std::memset(&pairing_params, 0, sizeof(pairing_params));
    pairing_params.io_capability = ioc;
    pairing_params.auth_req = auth_req;
    pairing_params.max_encryption_key_size = max_enc_key_size;

    ReceivePairingFeatures(pairing_params, peer_initiator);
  }

  void ReceivePairingFailed(ErrorCode error_code) {
    StaticByteBuffer<sizeof(Header) + sizeof(ErrorCode)> buffer;
    PacketWriter writer(kPairingFailed, &buffer);
    *writer.mutable_payload<PairingFailedParams>() = error_code;
    fake_chan()->Receive(buffer);
  }

  void ReceivePairingPublicKey(const PairingPublicKeyParams& key) {
    StaticByteBuffer<util::PacketSize<PairingPublicKeyParams>()> buffer;
    PacketWriter writer(kPairingPublicKey, &buffer);
    std::memcpy(
        writer.mutable_payload_bytes(), &key, sizeof(PairingPublicKeyParams));
    fake_chan()->Receive(buffer);
  }

  void ReceivePairingConfirm(const UInt128& confirm) {
    Receive128BitCmd(kPairingConfirm, confirm);
  }

  void ReceivePairingRandom(const UInt128& random) {
    Receive128BitCmd(kPairingRandom, random);
  }

  void ReceivePairingDHKeyCheck(const UInt128& check) {
    Receive128BitCmd(kPairingDHKeyCheck, check);
  }

  void ReceiveEncryptionInformation(const UInt128& ltk) {
    Receive128BitCmd(kEncryptionInformation, ltk);
  }

  void ReceiveCentralIdentification(uint64_t random, uint16_t ediv) {
    StaticByteBuffer<sizeof(Header) + sizeof(CentralIdentificationParams)>
        buffer;
    PacketWriter writer(kCentralIdentification, &buffer);
    auto* params = writer.mutable_payload<CentralIdentificationParams>();
    params->ediv = htole16(ediv);
    params->rand = htole64(random);
    fake_chan()->Receive(buffer);
  }

  void ReceiveIdentityResolvingKey(const UInt128& irk) {
    Receive128BitCmd(kIdentityInformation, irk);
  }

  void ReceiveNonBondablePairingResponse() {
    // clang-format off
    const StaticByteBuffer kResponse(
      0x02,  // code: Pairing Response
      0x00,  // IO cap.: DisplayOnly
      0x00,  // OOB: not present
      0x00,  // AuthReq: no bonding, MITM not required
      0x07,  // encr. key size: 7 (default min)
      0x00,  // initiator keys: none
      0x00   // responder keys: none - nonbondable mode
    );
    // clang-format on
    fake_chan()->Receive(kResponse);
  }

  void ReceiveIdentityAddress(const DeviceAddress& address) {
    StaticByteBuffer<sizeof(Header) + sizeof(IdentityAddressInformationParams)>
        buffer;
    PacketWriter writer(kIdentityAddressInformation, &buffer);
    auto* params = writer.mutable_payload<IdentityAddressInformationParams>();
    params->type = address.type() == DeviceAddress::Type::kLEPublic
                       ? AddressType::kPublic
                       : AddressType::kStaticRandom;
    params->bd_addr = address.value();
    fake_chan()->Receive(buffer);
  }

  void ReceiveSecurityRequest(AuthReqField auth_req = 0u) {
    StaticByteBuffer<sizeof(Header) + sizeof(AuthReqField)> buffer;
    buffer[0] = kSecurityRequest;
    buffer[1] = auth_req;
    fake_chan()->Receive(buffer);
    RunUntilIdle();
  }

  void GenerateLegacyConfirmValue(const UInt128& random,
                                  UInt128* out_value,
                                  bool peer_initiator = false,
                                  uint32_t tk = 0) {
    BT_DEBUG_ASSERT(out_value);

    tk = htole32(tk);
    UInt128 tk128;
    tk128.fill(0);
    std::memcpy(tk128.data(), &tk, sizeof(tk));

    const ByteBuffer *preq, *pres;
    const DeviceAddress *init_addr, *rsp_addr;
    if (peer_initiator) {
      preq = &peer_pairing_cmd();
      pres = &local_pairing_cmd();
      init_addr = &kPeerAddr;
      rsp_addr = &kLocalAddr;
    } else {
      preq = &local_pairing_cmd();
      pres = &peer_pairing_cmd();
      init_addr = &kLocalAddr;
      rsp_addr = &kPeerAddr;
    }

    util::C1(tk128, random, *preq, *pres, *init_addr, *rsp_addr, out_value);
  }

  UInt128 GenerateScConfirmValue(const LocalEcdhKey& peer_key,
                                 const UInt128& random,
                                 Role local_role,
                                 bool gen_initiator_confirm,
                                 uint8_t r = 0) {
    BT_ASSERT_MSG(public_ecdh_key_.has_value(),
                  "cannot compute confirm, missing key!");
    UInt256 pka = public_ecdh_key_->GetPublicKeyX(),
            pkb = peer_key.GetPublicKeyX();
    if (local_role == Role::kResponder) {
      std::swap(pka, pkb);
    }
    return gen_initiator_confirm ? util::F4(pka, pkb, random, r).value()
                                 : util::F4(pkb, pka, random, r).value();
  }

  SecurityManager* pairing() const { return pairing_.get(); }
  l2cap::testing::FakeChannel* fake_chan() const { return fake_chan_.get(); }
  hci::testing::FakeLowEnergyConnection* fake_link() const {
    return fake_link_.get();
  }

  int security_callback_count() const { return security_callback_count_; }
  const std::optional<ErrorCode>& received_error_code() const {
    return received_error_code_;
  }
  const Result<>& security_status() const { return security_status_; }
  const SecurityProperties& sec_props() const { return sec_props_; }

  int pairing_complete_count() const { return pairing_complete_count_; }
  const Result<>& pairing_complete_status() const {
    return pairing_complete_status_;
  }

  int pairing_data_callback_count() const {
    return pairing_data_callback_count_;
  }

  int auth_failure_callback_count() const {
    return auth_failure_callback_count_;
  }
  const hci::Result<>& auth_failure_status() const {
    return auth_failure_status_;
  }

  int local_id_info_callback_count() const {
    return local_id_info_callback_count_;
  }

  int new_sec_props_count() const { return new_sec_props_count_; }
  const SecurityProperties& new_sec_props() const { return new_sec_props_; }

  const std::optional<LTK>& peer_ltk() const { return pairing_data_.peer_ltk; }
  const std::optional<LTK>& local_ltk() const {
    return pairing_data_.local_ltk;
  }
  const std::optional<Key>& irk() const { return pairing_data_.irk; }
  const std::optional<DeviceAddress>& identity() const {
    return pairing_data_.identity_address;
  }
  const std::optional<Key>& csrk() const { return pairing_data_.csrk; }

  using ConfirmDelegate = fit::function<void(ConfirmCallback)>;
  void set_confirm_delegate(ConfirmDelegate delegate) {
    confirm_delegate_ = std::move(delegate);
  }

  using DisplayDelegate =
      fit::function<void(uint32_t, DisplayMethod, ConfirmCallback)>;
  void set_display_delegate(DisplayDelegate delegate) {
    display_delegate_ = std::move(delegate);
  }

  // sm::Delegate override:
  using RequestPasskeyDelegate = fit::function<void(PasskeyResponseCallback)>;
  void set_request_passkey_delegate(RequestPasskeyDelegate delegate) {
    request_passkey_delegate_ = std::move(delegate);
  }

  void set_local_id_info(std::optional<IdentityInfo> info) {
    local_id_info_ = info;
  }

  int security_request_count() const { return security_request_count_; }
  int pairing_failed_count() const { return pairing_failed_count_; }
  int pairing_request_count() const { return pairing_request_count_; }
  int pairing_response_count() const { return pairing_response_count_; }
  int pairing_public_key_count() const { return pairing_public_key_count_; }
  int pairing_confirm_count() const { return pairing_confirm_count_; }
  int pairing_random_count() const { return pairing_random_count_; }
  int pairing_dhkey_check_count() const { return pairing_dhkey_check_count_; }
  int enc_info_count() const { return enc_info_count_; }
  int id_info_count() const { return id_info_count_; }
  int id_addr_info_count() const { return id_addr_info_count_; }
  int central_ident_count() const { return central_ident_count_; }

  AuthReqField security_request_payload() const { return security_auth_req_; }
  const std::optional<EcdhKey>& public_ecdh_key() const {
    return public_ecdh_key_;
  }
  const UInt128& pairing_confirm() const { return pairing_confirm_; }
  const UInt128& pairing_random() const { return pairing_random_; }
  const UInt128& pairing_dhkey_check() const { return pairing_dhkey_check_; }
  const UInt128& enc_info() const { return enc_info_; }
  const UInt128& id_info() const { return id_info_; }
  const DeviceAddress& id_addr_info() const { return id_addr_info_; }
  uint16_t ediv() const { return ediv_; }
  uint64_t rand() const { return rand_; }
  const PairingData& pairing_data() const { return pairing_data_; }

  const ByteBuffer& local_pairing_cmd() const { return local_pairing_cmd_; }
  const ByteBuffer& peer_pairing_cmd() const { return peer_pairing_cmd_; }

 private:
  void Receive128BitCmd(Code cmd_code, const UInt128& value) {
    StaticByteBuffer<sizeof(Header) + sizeof(UInt128)> buffer;
    PacketWriter writer(cmd_code, &buffer);
    *writer.mutable_payload<UInt128>() = value;
    fake_chan()->Receive(buffer);
  }

  void InitializeTransport() {
    // Ensure any tasks posted by an existing transport are dispatched.
    RunUntilIdle();
    auto mock_controller =
        std::make_unique<bt::testing::MockController>(dispatcher());
    controller_ = mock_controller->GetWeakPtr();
    transport_ = std::make_unique<hci::Transport>(std::move(mock_controller),
                                                  dispatcher());
    std::optional<bool> init_success;
    transport_->Initialize([&](bool success) { init_success = success; });
    RunUntilIdle();
    ASSERT_TRUE(init_success.has_value());
    ASSERT_TRUE(init_success.value());
    transport_->InitializeACLDataChannel(hci::DataBufferInfo(1, 1),
                                         hci::DataBufferInfo(1, 1));
  }

  testing::MockController::WeakPtr controller_;
  std::unique_ptr<hci::Transport> transport_;

  // We store the preq/pres values here to generate a valid confirm value for
  // the fake side.
  StaticByteBuffer<sizeof(Header) + sizeof(PairingRequestParams)>
      local_pairing_cmd_, peer_pairing_cmd_;

  // Number of times the security callback given to UpgradeSecurity has been
  // called and the most recent parameters that it was called with.
  int security_callback_count_ = 0;
  Result<> security_status_ = fit::ok();
  SecurityProperties sec_props_;

  // Number of times the pairing data callback has been called and the most
  // recent value that it was called with.
  int pairing_data_callback_count_ = 0;
  PairingData pairing_data_;

  // Number of times the link security properties have been notified via
  // OnNewSecurityProperties().
  int new_sec_props_count_ = 0;
  SecurityProperties new_sec_props_;

  // State tracking the OnPairingComplete event.
  int pairing_complete_count_ = 0;
  Result<> pairing_complete_status_ = fit::ok();

  // State tracking the OnAuthenticationFailure event.
  int auth_failure_callback_count_ = 0;
  hci::Result<> auth_failure_status_ = fit::ok();

  // State tracking the OnIdentityInformationRequest event.
  int local_id_info_callback_count_ = 0;
  std::optional<IdentityInfo> local_id_info_;

  // Delegate functions used to respond to user input requests from the Security
  // Manager.
  ConfirmDelegate confirm_delegate_;
  DisplayDelegate display_delegate_;
  RequestPasskeyDelegate request_passkey_delegate_;

  // Counts of commands that we have sent out to the peer.
  int security_request_count_ = 0;
  int pairing_failed_count_ = 0;
  int pairing_request_count_ = 0;
  int pairing_response_count_ = 0;
  int pairing_public_key_count_ = 0;
  int pairing_confirm_count_ = 0;
  int pairing_random_count_ = 0;
  int pairing_dhkey_check_count_ = 0;
  int enc_info_count_ = 0;
  int id_info_count_ = 0;
  int id_addr_info_count_ = 0;
  int central_ident_count_ = 0;

  // Values that have we have sent to the peer.
  AuthReqField security_auth_req_ = 0;
  std::optional<EcdhKey> public_ecdh_key_;
  UInt128 pairing_confirm_ = {};
  UInt128 pairing_random_ = {};
  UInt128 pairing_dhkey_check_ = {};
  UInt128 enc_info_ = {};
  UInt128 id_info_ = {};
  DeviceAddress id_addr_info_;
  uint16_t ediv_ = 0;
  uint64_t rand_ = 0;

  std::optional<ErrorCode> received_error_code_;

  std::unique_ptr<l2cap::testing::FakeChannel> fake_chan_;
  std::unique_ptr<hci::testing::FakeLowEnergyConnection> fake_link_;
  std::unique_ptr<SecurityManager> pairing_;

  WeakSelf<Delegate> weak_delegate_;

  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(SecurityManagerTest);
};

class InitiatorPairingTest : public SecurityManagerTest {
 public:
  InitiatorPairingTest() = default;
  ~InitiatorPairingTest() override = default;

  void SetUp() override {
    SecurityManagerTest::SetUp();
    SetUpSecurityManager();
  }

  void SetUpSecurityManager(
      IOCapability ioc = IOCapability::kDisplayOnly,
      BondableMode bondable_mode = BondableMode::Bondable) {
    NewSecurityManager(Role::kInitiator, ioc, bondable_mode);
  }

  void GenerateMatchingLegacyConfirmAndRandom(UInt128* out_confirm,
                                              UInt128* out_random,
                                              uint32_t tk = 0) {
    BT_DEBUG_ASSERT(out_confirm);
    BT_DEBUG_ASSERT(out_random);
    *out_random = kHardCodedPairingRandom;
    GenerateLegacyConfirmValue(
        *out_random, out_confirm, /*peer_initiator=*/false, tk);
  }

  struct MatchingPair {
    UInt128 confirm;
    UInt128 random;
  };
  MatchingPair GenerateMatchingScConfirmAndRandom(const LocalEcdhKey& peer_key,
                                                  uint8_t r = 0) {
    MatchingPair pair;
    pair.random = kHardCodedPairingRandom;
    pair.confirm = GenerateScConfirmValue(peer_key,
                                          pair.random,
                                          Role::kInitiator,
                                          /*gen_initiator_confirm=*/false,
                                          r);
    return pair;
  }
  // Emulate legacy pairing up until before encryption with STK. Returns the STK
  // that the initiator is expected to encrypt the link with in |out_stk|.
  //
  // This will not resolve the encryption request that is made by using the STK
  // before this function returns (this is to unit test encryption failure). Use
  // FastForwardToPhase3() to also emulate successful encryption.
  void FastForwardToSTK(UInt128* out_stk,
                        SecurityLevel level = SecurityLevel::kEncrypted,
                        KeyDistGenField remote_keys = 0,
                        KeyDistGenField local_keys = 0,
                        uint8_t max_key_size = kMaxEncryptionKeySize,
                        BondableMode bondable_mode = BondableMode::Bondable) {
    UpgradeSecurity(level);

    PairingRequestParams pairing_params;
    pairing_params.io_capability = IOCapability::kNoInputNoOutput;
    AuthReqField bondable = (bondable_mode == BondableMode::Bondable)
                                ? AuthReq::kBondingFlag
                                : 0,
                 mitm_protected = (level >= SecurityLevel::kAuthenticated)
                                      ? AuthReq::kMITM
                                      : 0;
    pairing_params.auth_req = mitm_protected | bondable;
    pairing_params.max_encryption_key_size = max_key_size;
    pairing_params.initiator_key_dist_gen = local_keys;
    pairing_params.responder_key_dist_gen = remote_keys;
    ReceivePairingFeatures(pairing_params);

    // Run the loop until the harness caches the feature exchange PDUs (preq &
    // pres) so that we can generate a valid confirm value.
    RunUntilIdle();

    UInt128 sconfirm, srand;
    GenerateMatchingLegacyConfirmAndRandom(&sconfirm, &srand);
    ReceivePairingConfirm(sconfirm);
    ReceivePairingRandom(srand);
    RunUntilIdle();

    EXPECT_EQ(1, pairing_confirm_count());
    EXPECT_EQ(1, pairing_random_count());
    EXPECT_EQ(0, pairing_failed_count());
    EXPECT_EQ(0, security_callback_count());

    BT_DEBUG_ASSERT(out_stk);

    UInt128 tk;
    tk.fill(0);
    util::S1(tk, srand, pairing_random(), out_stk);
  }

  void FastForwardToPhase3(
      UInt128* out_encryption_key,
      bool secure_connections = false,
      SecurityLevel level = SecurityLevel::kEncrypted,
      KeyDistGenField remote_keys = 0,
      KeyDistGenField local_keys = 0,
      uint8_t max_key_size = kMaxEncryptionKeySize,
      BondableMode bondable_mode = BondableMode::Bondable) {
    if (secure_connections) {
      FastForwardToScLtk(
          out_encryption_key, level, remote_keys, local_keys, bondable_mode);
    } else {
      FastForwardToSTK(out_encryption_key,
                       level,
                       remote_keys,
                       local_keys,
                       max_key_size,
                       bondable_mode);
    }

    ASSERT_TRUE(fake_link()->ltk());
    EXPECT_EQ(1, fake_link()->start_encryption_count());

    // Resolve the encryption request.
    fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
    RunUntilIdle();
    EXPECT_EQ(1, new_sec_props_count());
    EXPECT_EQ(level, new_sec_props().level());
  }

  void FastForwardToScLtk(UInt128* out_ltk,
                          SecurityLevel level = SecurityLevel::kEncrypted,
                          KeyDistGenField peer_keys = 0,
                          KeyDistGenField local_keys = 0,
                          BondableMode bondable = BondableMode::Bondable) {
    UpgradeSecurity(level);
    RunUntilIdle();

    ASSERT_EQ(1, pairing_request_count());
    PairingRequestParams pres;
    pres.io_capability = IOCapability::kDisplayYesNo;
    pres.oob_data_flag = OOBDataFlag::kNotPresent;
    AuthReqField bondable_flag =
        (bondable == BondableMode::Bondable) ? AuthReq::kBondingFlag : 0;
    AuthReqField mitm_flag =
        (level >= SecurityLevel::kAuthenticated) ? AuthReq::kMITM : 0;
    pres.auth_req = AuthReq::kSC | mitm_flag | bondable_flag;
    pres.max_encryption_key_size = kMaxEncryptionKeySize;
    pres.initiator_key_dist_gen = local_keys;
    pres.responder_key_dist_gen = peer_keys;
    ReceivePairingFeatures(pres);
    RunUntilIdle();

    ASSERT_TRUE(public_ecdh_key().has_value());
    LocalEcdhKey peer_key = *LocalEcdhKey::Create();
    ReceivePairingPublicKey(peer_key.GetSerializedPublicKey());
    RunUntilIdle();
    // We're in SC Numeric Comparison/Just Works, so as initiator we should not
    // send a confirm.
    ASSERT_EQ(0, pairing_confirm_count());
    MatchingPair phase_2_vals = GenerateMatchingScConfirmAndRandom(peer_key);
    ReceivePairingConfirm(phase_2_vals.confirm);
    RunUntilIdle();
    ASSERT_EQ(1, pairing_random_count());
    // If using MITM, we expect to be in Numeric Comparison
    ConfirmCallback display_cb = nullptr;
    if (mitm_flag != 0) {
      uint32_t kExpectedDisplayVal =
          *util::G2(public_ecdh_key()->GetPublicKeyX(),
                    peer_key.GetPublicKeyX(),
                    pairing_random(),
                    phase_2_vals.random) %
          1000000;
      set_display_delegate(
          [kExpectedDisplayVal, &display_cb](uint32_t compare_value,
                                             Delegate::DisplayMethod method,
                                             ConfirmCallback cb) {
            ASSERT_TRUE(method == Delegate::DisplayMethod::kComparison);
            ASSERT_EQ(kExpectedDisplayVal, compare_value);
            display_cb = std::move(cb);
          });
    }
    ReceivePairingRandom(phase_2_vals.random);
    RunUntilIdle();
    if (mitm_flag != 0) {
      ASSERT_TRUE(display_cb);
      display_cb(true);
    }  // Else we are content to use the default confirm delegate behavior to
       // accept the pairing.

    util::F5Results f5 = *util::F5(peer_key.CalculateDhKey(*public_ecdh_key()),
                                   pairing_random(),
                                   phase_2_vals.random,
                                   kLocalAddr,
                                   kPeerAddr);

    UInt128 r_array{0};
    PacketReader reader(&local_pairing_cmd());
    PairingResponseParams preq = reader.payload<PairingRequestParams>();
    UInt128 dhkey_check_a = *util::F6(f5.mac_key,
                                      pairing_random(),
                                      phase_2_vals.random,
                                      r_array,
                                      preq.auth_req,
                                      preq.oob_data_flag,
                                      preq.io_capability,
                                      kLocalAddr,
                                      kPeerAddr);
    UInt128 dhkey_check_b = *util::F6(f5.mac_key,
                                      phase_2_vals.random,
                                      pairing_random(),
                                      r_array,
                                      pres.auth_req,
                                      pres.oob_data_flag,
                                      pres.io_capability,
                                      kPeerAddr,
                                      kLocalAddr);
    RunUntilIdle();
    EXPECT_EQ(1, pairing_dhkey_check_count());
    ASSERT_EQ(dhkey_check_a, pairing_dhkey_check());
    ReceivePairingDHKeyCheck(dhkey_check_b);
    RunUntilIdle();
    EXPECT_EQ(0, pairing_failed_count());
    EXPECT_EQ(0, security_callback_count());

    ASSERT_TRUE(out_ltk);
    *out_ltk = f5.ltk;
  }

 private:
  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(InitiatorPairingTest);
};

class ResponderPairingTest : public SecurityManagerTest {
 public:
  ResponderPairingTest() = default;
  ~ResponderPairingTest() override = default;

  void SetUp() override {
    SecurityManagerTest::SetUp();
    SetUpSecurityManager();
  }

  void SetUpSecurityManager(
      IOCapability ioc = IOCapability::kDisplayOnly,
      BondableMode bondable_mode = BondableMode::Bondable) {
    NewSecurityManager(Role::kResponder, ioc, bondable_mode);
  }

  void GenerateMatchingLegacyConfirmAndRandom(UInt128* out_confirm,
                                              UInt128* out_random,
                                              uint32_t tk = 0) {
    BT_DEBUG_ASSERT(out_confirm);
    BT_DEBUG_ASSERT(out_random);
    *out_random = kHardCodedPairingRandom;
    GenerateLegacyConfirmValue(
        *out_random, out_confirm, /*peer_initiator=*/true, tk);
  }
  struct MatchingPair {
    UInt128 confirm;
    UInt128 random;
  };
  MatchingPair GenerateMatchingScConfirmAndRandom(const LocalEcdhKey& peer_key,
                                                  uint8_t r = 0) {
    MatchingPair pair;
    pair.random = kHardCodedPairingRandom;
    pair.confirm = GenerateScConfirmValue(peer_key,
                                          pair.random,
                                          Role::kResponder,
                                          /*gen_initiator_confirm=*/true,
                                          r);
    return pair;
  }
  void ReceivePairingRequest(IOCapability ioc = IOCapability::kNoInputNoOutput,
                             AuthReqField auth_req = 0,
                             uint8_t max_enc_key_size = kMaxEncryptionKeySize) {
    ReceivePairingFeatures(
        ioc, auth_req, max_enc_key_size, /*peer_initiator=*/true);
  }

  void FastForwardToSTK(UInt128* out_stk,
                        SecurityLevel level = SecurityLevel::kEncrypted,
                        KeyDistGenField remote_keys = 0,
                        KeyDistGenField local_keys = 0,
                        uint8_t max_key_size = kMaxEncryptionKeySize,
                        BondableMode bondable_mode = BondableMode::Bondable) {
    PairingRequestParams pairing_params;
    pairing_params.io_capability = IOCapability::kNoInputNoOutput;
    AuthReqField bondable = (bondable_mode == BondableMode::Bondable)
                                ? AuthReq::kBondingFlag
                                : 0,
                 mitm_protected = (level >= SecurityLevel::kAuthenticated)
                                      ? AuthReq::kMITM
                                      : 0;
    pairing_params.auth_req = mitm_protected | bondable;
    pairing_params.max_encryption_key_size = max_key_size;
    pairing_params.initiator_key_dist_gen = remote_keys;
    pairing_params.responder_key_dist_gen = local_keys;
    ReceivePairingFeatures(pairing_params, /*peer_initiator=*/true);

    // Run the loop until the harness caches the feature exchange PDUs (preq &
    // pres) so that we can generate a valid confirm value.
    RunUntilIdle();
    EXPECT_EQ(0, pairing_request_count());
    EXPECT_EQ(1, pairing_response_count());

    // The initiator should start the confirm/random exchange to generate the
    // Phase 2 keys.
    EXPECT_EQ(0, pairing_confirm_count());
    EXPECT_EQ(0, pairing_random_count());

    UInt128 mconfirm, mrand;
    GenerateMatchingLegacyConfirmAndRandom(&mconfirm, &mrand);
    ReceivePairingConfirm(mconfirm);
    RunUntilIdle();
    EXPECT_EQ(1, pairing_confirm_count());
    EXPECT_EQ(0, pairing_random_count());

    ReceivePairingRandom(mrand);
    RunUntilIdle();
    EXPECT_EQ(1, pairing_confirm_count());
    EXPECT_EQ(1, pairing_random_count());
    EXPECT_EQ(0, pairing_failed_count());
    EXPECT_EQ(0, security_callback_count());

    BT_DEBUG_ASSERT(out_stk);

    UInt128 tk;
    tk.fill(0);
    util::S1(tk, pairing_random(), mrand, out_stk);
  }

  void FastForwardToPhase3(
      UInt128* out_encryption_key,
      bool secure_connections = false,
      SecurityLevel level = SecurityLevel::kEncrypted,
      KeyDistGenField remote_keys = 0,
      KeyDistGenField local_keys = 0,
      uint8_t max_key_size = kMaxEncryptionKeySize,
      BondableMode bondable_mode = BondableMode::Bondable) {
    if (secure_connections) {
      FastForwardToScLtk(
          out_encryption_key, level, remote_keys, local_keys, bondable_mode);
    } else {
      FastForwardToSTK(out_encryption_key,
                       level,
                       remote_keys,
                       local_keys,
                       max_key_size,
                       bondable_mode);
    }

    ASSERT_TRUE(fake_link()->ltk());

    // No local start encryption request should be made.
    EXPECT_EQ(0, fake_link()->start_encryption_count());

    // Pretend that the initiator succeeded in encrypting the connection.
    fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
    RunUntilIdle();
    EXPECT_EQ(1, new_sec_props_count());
    EXPECT_EQ(level, new_sec_props().level());
  }

  void FastForwardToScLtk(UInt128* out_ltk,
                          SecurityLevel level = SecurityLevel::kEncrypted,
                          KeyDistGenField peer_keys = 0,
                          KeyDistGenField local_keys = 0,
                          BondableMode bondable = BondableMode::Bondable) {
    PairingRequestParams preq;
    preq.io_capability = IOCapability::kDisplayYesNo;
    preq.oob_data_flag = OOBDataFlag::kNotPresent;
    AuthReqField bondable_flag =
        (bondable == BondableMode::Bondable) ? AuthReq::kBondingFlag : 0;
    AuthReqField mitm_flag =
        (level >= SecurityLevel::kAuthenticated) ? AuthReq::kMITM : 0;
    preq.auth_req = AuthReq::kSC | mitm_flag | bondable_flag;
    preq.max_encryption_key_size = kMaxEncryptionKeySize;
    preq.initiator_key_dist_gen = local_keys;
    preq.responder_key_dist_gen = peer_keys;
    ReceivePairingFeatures(preq, /*peer_initiator=*/true);
    RunUntilIdle();
    ASSERT_EQ(1, pairing_response_count());

    LocalEcdhKey peer_key = *LocalEcdhKey::Create();
    ReceivePairingPublicKey(peer_key.GetSerializedPublicKey());
    RunUntilIdle();
    ASSERT_TRUE(public_ecdh_key().has_value());
    ASSERT_EQ(1, pairing_public_key_count());

    // We are in Just Works or Numeric Comparison based on IOCapabilities/MITM
    // preferences, so we expect the confirm value immediately after the public
    // key.
    ASSERT_EQ(1, pairing_confirm_count());
    std::optional<uint32_t> display_val;
    if (mitm_flag != 0) {
      set_display_delegate([&](uint32_t compare_value,
                               Delegate::DisplayMethod method,
                               ConfirmCallback cb) {
        ASSERT_TRUE(method == Delegate::DisplayMethod::kComparison);
        display_val = compare_value;
        cb(true);
      });
    }  // Else we are content to use the default confirm delegate behavior to
       // accept the pairing.
    auto peer_rand = Random<PairingRandomValue>();
    ReceivePairingRandom(peer_rand);
    RunUntilIdle();
    ASSERT_EQ(1, pairing_random_count());
    ASSERT_EQ(GenerateScConfirmValue(
                  peer_key, pairing_random(), Role::kResponder, false),
              pairing_confirm());
    if (mitm_flag != 0) {
      ASSERT_TRUE(display_val.has_value());
      uint32_t kExpectedDisplayVal =
          *util::G2(peer_key.GetPublicKeyX(),
                    public_ecdh_key()->GetPublicKeyX(),
                    peer_rand,
                    pairing_random()) %
          1000000;

      EXPECT_EQ(kExpectedDisplayVal, display_val);
    }

    util::F5Results f5 = *util::F5(peer_key.CalculateDhKey(*public_ecdh_key()),
                                   peer_rand,
                                   pairing_random(),
                                   kPeerAddr,
                                   kLocalAddr);

    UInt128 r_array{0};
    PacketReader reader(&local_pairing_cmd());
    PairingResponseParams pres = reader.payload<PairingResponseParams>();
    UInt128 dhkey_check_a = *util::F6(f5.mac_key,
                                      peer_rand,
                                      pairing_random(),
                                      r_array,
                                      preq.auth_req,
                                      preq.oob_data_flag,
                                      preq.io_capability,
                                      kPeerAddr,
                                      kLocalAddr);
    UInt128 dhkey_check_b = *util::F6(f5.mac_key,
                                      pairing_random(),
                                      peer_rand,
                                      r_array,
                                      pres.auth_req,
                                      pres.oob_data_flag,
                                      pres.io_capability,
                                      kLocalAddr,
                                      kPeerAddr);
    ReceivePairingDHKeyCheck(dhkey_check_a);
    RunUntilIdle();
    EXPECT_EQ(1, pairing_dhkey_check_count());
    ASSERT_EQ(dhkey_check_b, pairing_dhkey_check());
    EXPECT_EQ(0, pairing_failed_count());
    EXPECT_EQ(0, pairing_complete_count());

    ASSERT_TRUE(out_ltk);
    *out_ltk = f5.ltk;
  }

 private:
  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ResponderPairingTest);
};

// Calling `Abort` with no in-progress security upgrade should not cause a
// PairingComplete event.
TEST_F(InitiatorPairingTest, AbortNoSecurityUpgradeInProgress) {
  pairing()->Abort();
  RunUntilIdle();
  EXPECT_EQ(0, pairing_complete_count());
}

// Disconnecting with no in-progress security upgrade should not cause a
// PairingComplete event.
TEST_F(InitiatorPairingTest, DisconnectNoSecurityUpgradeInProgress) {
  fake_chan()->Close();
  RunUntilIdle();
  EXPECT_EQ(0, pairing_complete_count());
}

// Requesting pairing at the current security level should succeed immediately.
TEST_F(InitiatorPairingTest, UpgradeSecurityCurrentLevel) {
  UpgradeSecurity(SecurityLevel::kNoSecurity);
  RunUntilIdle();

  // No pairing requests should have been made.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Pairing should succeed.
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(SecurityLevel::kNoSecurity, sec_props().level());
  EXPECT_EQ(0u, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());
}

// Peer aborts during Phase 1.
TEST_F(InitiatorPairingTest, PairingFailedInPhase1) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pairing not complete yet but we should be in Phase 1.
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());

  ReceivePairingFailed(ErrorCode::kPairingNotSupported);
  RunUntilIdle();

  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());
  EXPECT_EQ(ToResult(ErrorCode::kPairingNotSupported), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// Local aborts during Phase 1.
TEST_F(InitiatorPairingTest, PairingAbortedInPhase1) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pairing not complete yet but we should be in Phase 1.
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());

  pairing()->Abort();
  RunUntilIdle();

  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// Local resets I/O capabilities while pairing. This should abort any ongoing
// pairing and the new I/O capabilities should be used in following pairing
// requests.
TEST_F(InitiatorPairingTest, SecurityManagerResetDuringPairing) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pairing not complete yet but we should be in Phase 1.
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());

  pairing()->Reset(IOCapability::kNoInputNoOutput);
  RunUntilIdle();

  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_request_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());

  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Should have sent a new pairing request.
  EXPECT_EQ(2, pairing_request_count());

  // Make sure that the new request has the new I/O capabilities.
  const auto& params = local_pairing_cmd().view(1).To<PairingRequestParams>();
  EXPECT_EQ(IOCapability::kNoInputNoOutput, params.io_capability);
}

TEST_F(InitiatorPairingTest, ReceiveConfirmValueWhileNotPairing) {
  UInt128 confirm;
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Nothing should happen.
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
}

TEST_F(InitiatorPairingTest, ReceiveConfirmValueInPhase1) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  UInt128 confirm;
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest,
       RejectUnauthenticatedPairingInSecureConnectionsOnlyMode) {
  SetUpSecurityManager(IOCapability::kKeyboardDisplay);
  pairing()->set_security_mode(gap::LESecurityMode::SecureConnectionsOnly);
  // In SC Only mode, SM should translate this "encrypted" request into a MITM
  // requirement.
  UpgradeSecurity(SecurityLevel::kEncrypted);
  // The peer has NoInputNoOutput IOCapabilities, thus cannot perform
  // authenticated pairing.
  ReceivePairingFeatures(IOCapability::kNoInputNoOutput,
                         AuthReq::kBondingFlag | AuthReq::kSC);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kAuthenticationRequirements),
            security_status());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest,
       RejectUnauthenticatedEncryptionInSecureConnectionsOnlyMode) {
  pairing()->set_security_mode(gap::LESecurityMode::SecureConnectionsOnly);
  const LTK kUnauthenticatedLtk(SecurityProperties(/*encrypted=*/true,
                                                   /*authenticated=*/false,
                                                   /*secure_connections=*/true,
                                                   kMaxEncryptionKeySize),
                                hci_spec::LinkKey());
  pairing()->AssignLongTermKey(kUnauthenticatedLtk);
  RunUntilIdle();
  // After setting SC Only mode, assigning and encrypting with an
  // unauthenticated LTK should cause the channel to be disconnected with an
  // authentication failure.
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  EXPECT_EQ(1, auth_failure_callback_count());
  EXPECT_EQ(ToResult(HostError::kInsufficientSecurity), auth_failure_status());
  EXPECT_TRUE(fake_chan()->link_error());
}

TEST_F(InitiatorPairingTest,
       AllowSecureAuthenticatedPairingInSecureConnectionsOnlyMode) {
  SetUpSecurityManager(IOCapability::kDisplayYesNo);
  pairing()->set_security_mode(gap::LESecurityMode::SecureConnectionsOnly);
  UInt128 enc_key;
  FastForwardToPhase3(&enc_key,
                      /*secure_connections=*/true,
                      SecurityLevel::kSecureAuthenticated);
  RunUntilIdle();
  // After setting SC Only mode, secure authenticated pairing should still
  // complete successfully.
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_TRUE(peer_ltk().has_value());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(SecurityLevel::kSecureAuthenticated, sec_props().level());
}

// In Phase 2 but still waiting to receive TK.
TEST_F(InitiatorPairingTest, ReceiveConfirmValueWhileWaitingForUserInput) {
  bool tk_requested = false;
  set_confirm_delegate([&](ConfirmCallback) { tk_requested = true; });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_TRUE(tk_requested);

  UInt128 confirm;
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// SecurityManager destroyed when waiting for Just Works user confirmation.
TEST_F(InitiatorPairingTest,
       SecurityManagerDestroyedStateWhileWaitingForUserInput) {
  ConfirmCallback respond;
  set_confirm_delegate([&](ConfirmCallback rsp) { respond = std::move(rsp); });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_TRUE(respond);

  DestroySecurityManager();

  // This should proceed safely.
  respond(true);
  RunUntilIdle();
}

// Pairing no longer in progress when waiting for Just Works user confirmation.
TEST_F(InitiatorPairingTest, PairingAbortedWhileWaitingForUserInput) {
  ConfirmCallback respond;
  set_confirm_delegate([&](ConfirmCallback rsp) { respond = std::move(rsp); });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_TRUE(respond);

  ReceivePairingFailed(ErrorCode::kPairingNotSupported);
  RunUntilIdle();
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kPairingNotSupported), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // This should have no effect.
  respond(true);
  RunUntilIdle();
  EXPECT_EQ(1, pairing_request_count());
  EXPECT_EQ(0, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, pairing_data_callback_count());
}

// Pairing procedure stopped and restarted when TKResponse runs. The TKResponse
// does not belong to the current pairing.
TEST_F(InitiatorPairingTest, PairingRestartedWhileWaitingForTK) {
  ConfirmCallback respond;
  set_confirm_delegate([&](ConfirmCallback rsp) { respond = std::move(rsp); });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_TRUE(respond);

  // Stop pairing.
  ReceivePairingFailed(ErrorCode::kPairingNotSupported);
  RunUntilIdle();
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kPairingNotSupported), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // Reset the delegate so that |respond| doesn't get overwritten by the second
  // pairing.
  set_confirm_delegate(nullptr);

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_EQ(2, pairing_request_count());
  EXPECT_EQ(0, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  // This should have no effect.
  respond(true);
  RunUntilIdle();
  EXPECT_EQ(2, pairing_request_count());
  EXPECT_EQ(0, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, pairing_data_callback_count());
}

TEST_F(InitiatorPairingTest, ReceiveRandomValueWhileNotPairing) {
  UInt128 random;
  ReceivePairingRandom(random);
  RunUntilIdle();

  // Nothing should happen.
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
}

TEST_F(InitiatorPairingTest, ReceiveRandomValueInPhase1) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  UInt128 random;
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// In Phase 2 but still waiting to receive TK.
TEST_F(InitiatorPairingTest, ReceiveRandomValueWhileWaitingForTK) {
  bool confirmation_requested = false;
  set_confirm_delegate([&](ConfirmCallback) { confirmation_requested = true; });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();
  EXPECT_TRUE(confirmation_requested);

  UInt128 random;
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, LegacyPhase2SconfirmValueReceivedTwice) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  ReceivePairingFeatures();
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  UInt128 confirm;
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Should have received Mrand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Send Mconfirm again
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, LegacyPhase2ReceiveRandomValueInWrongOrder) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  ReceivePairingFeatures();
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  UInt128 random;
  ReceivePairingRandom(random);
  RunUntilIdle();

  // Should have aborted pairing if Srand arrives before Srand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, LegacyPhase2SconfirmValueInvalid) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pick I/O capabilities and MITM flags that will result in Just Works
  // pairing.
  ReceivePairingFeatures();
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Receive Sconfirm and Srand values that don't match.
  UInt128 confirm, random;
  confirm.fill(0);
  random.fill(1);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Should have received Mrand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Our Mconfirm/Mrand should be correct.
  UInt128 expected_confirm;
  GenerateLegacyConfirmValue(pairing_random(), &expected_confirm);
  EXPECT_EQ(expected_confirm, pairing_confirm());

  // Send the non-matching Srandom.
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kConfirmValueFailed), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, LegacyPhase2RandomValueReceivedTwice) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pick I/O capabilities and MITM flags that will result in Just Works
  // pairing.
  ReceivePairingFeatures();
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Receive Sconfirm and Srand values that match.
  UInt128 confirm, random;
  GenerateMatchingLegacyConfirmAndRandom(&confirm, &random);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Should have received Mrand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Our Mconfirm/Mrand should be correct.
  UInt128 expected_confirm;
  GenerateLegacyConfirmValue(pairing_random(), &expected_confirm);
  EXPECT_EQ(expected_confirm, pairing_confirm());

  // Send Srandom.
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  // Send Srandom again.
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());

  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, LegacyPhase2ConfirmValuesExchanged) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pick I/O capabilities and MITM flags that will result in Just Works
  // pairing.
  ReceivePairingFeatures();
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Receive Sconfirm and Srand values that match.
  UInt128 confirm, random;
  GenerateMatchingLegacyConfirmAndRandom(&confirm, &random);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Should have received Mrand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Our Mconfirm/Mrand should be correct.
  UInt128 expected_confirm;
  GenerateLegacyConfirmValue(pairing_random(), &expected_confirm);
  EXPECT_EQ(expected_confirm, pairing_confirm());

  // Send Srandom.
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
}

// TK delegate rejects pairing. When pairing method is "PasskeyEntryInput", this
// should result in a "Passkey Entry Failed" error.
TEST_F(InitiatorPairingTest, LegacyPhase2TKDelegateRejectsPasskeyInput) {
  SetUpSecurityManager(IOCapability::kKeyboardOnly);

  bool tk_requested = false;
  PasskeyResponseCallback respond;
  set_request_passkey_delegate([&](PasskeyResponseCallback cb_rsp) {
    tk_requested = true;
    respond = std::move(cb_rsp);
  });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pick I/O capabilities and MITM flags that will result in Passkey Entry
  // pairing.
  ReceivePairingFeatures(IOCapability::kDisplayOnly, AuthReq::kMITM);
  RunUntilIdle();
  ASSERT_TRUE(tk_requested);

  // Reject pairing.
  respond(-1);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kPasskeyEntryFailed), security_status());
}

// TK delegate rejects pairing.
TEST_F(InitiatorPairingTest, LegacyPhase2TKDelegateRejectsPairing) {
  bool tk_requested = false;
  ConfirmCallback respond;
  set_confirm_delegate([&](ConfirmCallback cb_rsp) {
    tk_requested = true;
    respond = std::move(cb_rsp);
  });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  ReceivePairingFeatures();
  RunUntilIdle();
  ASSERT_TRUE(tk_requested);

  // Reject pairing.
  respond(false);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
}

TEST_F(InitiatorPairingTest, IgnoresExpiredConfirmRequestCallback) {
  ConfirmCallback respond = nullptr;
  set_confirm_delegate([&](ConfirmCallback rsp) { respond = std::move(rsp); });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  ReceivePairingFeatures();
  RunUntilIdle();
  ASSERT_TRUE(respond);
  ConfirmCallback first_pairing_cb = std::move(respond);
  pairing()->Abort();
  RunUntilIdle();
  EXPECT_EQ(1, pairing_failed_count());

  // We reset the respond variable so we can "catch" the next PairingDelegate
  // request in the same variable (the `set_confirm_delegate` callback still has
  // the reference to `respond`)
  respond = nullptr;

  // Start a separate pairing from the one captured in `first_pairing_cb`, which
  // was `Abort`ed
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  ReceivePairingFeatures();
  RunUntilIdle();
  first_pairing_cb(true);
  RunUntilIdle();
  // The callback from the `Abort`ed pairing should be ignored, while calling
  // `respond`, which is associated with the active pairing, should cause the
  // expected Pairing Confirm to be sent.
  EXPECT_EQ(0, pairing_confirm_count());
  ASSERT_TRUE(respond);
  respond(true);
  RunUntilIdle();
  EXPECT_EQ(1, pairing_confirm_count());
}

TEST_F(InitiatorPairingTest, IgnoresExpiredDisplayRequestCallback) {
  SetUpSecurityManager(IOCapability::kDisplayOnly);
  ConfirmCallback respond = nullptr;
  set_display_delegate(
      [&](uint32_t /**/, Delegate::DisplayMethod method, ConfirmCallback rsp) {
        ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);
        respond = std::move(rsp);
      });

  // Must request MITM to test PasskeyEntryDisplay instead of JustWorks pairing
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();

  ReceivePairingFeatures(IOCapability::kKeyboardOnly);
  RunUntilIdle();
  ASSERT_TRUE(respond);
  ConfirmCallback first_pairing_cb = std::move(respond);
  pairing()->Abort();
  RunUntilIdle();
  EXPECT_EQ(1, pairing_failed_count());

  // We reset the respond variable so we can "catch" the next PairingDelegate
  // request in the same variable (the `set_display_delegate` callback still has
  // the reference to `respond`)
  respond = nullptr;

  // Start a separate pairing from the one captured in `first_pairing_cb`, which
  // was `Abort`ed
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();

  ReceivePairingFeatures(IOCapability::kKeyboardOnly);
  RunUntilIdle();
  first_pairing_cb(true);
  RunUntilIdle();
  // The callback from the `Abort`ed pairing should be ignored, while calling
  // `respond`, which is associated with the active pairing, should cause the
  // expected Pairing Confirm to be sent.
  EXPECT_EQ(0, pairing_confirm_count());
  ASSERT_TRUE(respond);
  respond(true);
  RunUntilIdle();
  EXPECT_EQ(1, pairing_confirm_count());
}

TEST_F(InitiatorPairingTest, IgnoresExpiredPasskeyEntryInputCallback) {
  SetUpSecurityManager(IOCapability::kKeyboardOnly);
  PasskeyResponseCallback passkey_cb = nullptr;
  set_request_passkey_delegate(
      [&](PasskeyResponseCallback cb) { passkey_cb = std::move(cb); });

  // Must request MITM to test PasskeyEntryInput instead of JustWorks pairing
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();

  ReceivePairingFeatures(IOCapability::kDisplayOnly);
  RunUntilIdle();
  ASSERT_TRUE(passkey_cb);
  PasskeyResponseCallback first_pairing_cb = std::move(passkey_cb);
  pairing()->Abort();
  RunUntilIdle();
  EXPECT_EQ(1, pairing_failed_count());

  // We reset the respond variable so we can "catch" the next PairingDelegate
  // request in the same variable (the `set_display_delegate` callback still has
  // the reference to `respond`)
  passkey_cb = nullptr;

  // Start a separate pairing from the one captured in `first_pairing_cb`, which
  // was `Abort`ed
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();

  ReceivePairingFeatures(IOCapability::kDisplayOnly);
  RunUntilIdle();
  const int32_t kGenericPositive6DigitNumber = 123456;
  first_pairing_cb(kGenericPositive6DigitNumber);
  RunUntilIdle();
  // The callback from the `Abort`ed pairing should be ignored, while calling
  // `respond`, which is associated with the active pairing, should cause the
  // expected Pairing Confirm to be sent.
  EXPECT_EQ(0, pairing_confirm_count());
  ASSERT_TRUE(passkey_cb);
  passkey_cb(kGenericPositive6DigitNumber);
  RunUntilIdle();
  EXPECT_EQ(1, pairing_confirm_count());
}

// The TK delegate is called with the correct pairing method and the TK is
// factored into the confirm value generation.
TEST_F(InitiatorPairingTest, LegacyPhase2ConfirmValuesExchangedWithUserTK) {
  std::optional<uint32_t> tk = std::nullopt;
  auto method = Delegate::DisplayMethod::kComparison;
  ConfirmCallback respond;
  set_display_delegate([&](uint32_t passkey,
                           Delegate::DisplayMethod cb_method,
                           ConfirmCallback cb_rsp) {
    tk = passkey;
    method = cb_method;
    respond = std::move(cb_rsp);
  });

  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();

  // Pick I/O capabilities and MITM flags that will result in Passkey Entry
  // pairing.
  ReceivePairingFeatures(IOCapability::kKeyboardOnly, AuthReq::kMITM);
  RunUntilIdle();
  ASSERT_TRUE(tk.has_value());

  // DisplayMethod should be kPeerEntry, as Comparison is only for Secure
  // Connections, not Legacy.
  ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);

  // Notify that TK was displayed.
  respond(true);
  RunUntilIdle();

  // Should have received Mconfirm.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Receive Sconfirm and Srand values that match.
  UInt128 confirm, random;
  GenerateMatchingLegacyConfirmAndRandom(&confirm, &random, *tk);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Should have received Mrand.
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, security_callback_count());

  // Our Mconfirm/Mrand should be correct.
  UInt128 expected_confirm;
  GenerateLegacyConfirmValue(
      pairing_random(), &expected_confirm, /*peer_initiator=*/false, *tk);
  EXPECT_EQ(expected_confirm, pairing_confirm());

  // Send Srandom.
  ReceivePairingRandom(random);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
}

// Peer aborts during Phase 2.
TEST_F(InitiatorPairingTest, PairingFailedInPhase2) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  ReceivePairingFeatures();
  RunUntilIdle();

  UInt128 confirm, random;
  GenerateMatchingLegacyConfirmAndRandom(&confirm, &random);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  ReceivePairingFailed(ErrorCode::kConfirmValueFailed);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kConfirmValueFailed), security_status());
}

// Encryption with STK fails.
TEST_F(InitiatorPairingTest, EncryptionWithSTKFails) {
  UInt128 stk;
  FastForwardToSTK(&stk);

  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(stk, fake_link()->ltk()->value());
  EXPECT_EQ(0u, fake_link()->ltk()->ediv());
  EXPECT_EQ(0u, fake_link()->ltk()->rand());

  // The host should have requested encryption.
  EXPECT_EQ(SecurityProperties(), pairing()->security());
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  fake_link()->TriggerEncryptionChangeCallback(
      ToResult(pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING)
          .take_error());
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, auth_failure_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING),
            auth_failure_status());

  // No security property update should have been sent since the security
  // properties have not changed.
  EXPECT_EQ(0, new_sec_props_count());
  EXPECT_EQ(SecurityProperties(), pairing()->security());
}

TEST_F(InitiatorPairingTest, EncryptionDisabledInPhase2) {
  UInt128 stk;
  FastForwardToSTK(&stk);

  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(stk, fake_link()->ltk()->value());
  EXPECT_EQ(0u, fake_link()->ltk()->ediv());
  EXPECT_EQ(0u, fake_link()->ltk()->rand());

  // The host should have requested encryption.
  EXPECT_EQ(1, fake_link()->start_encryption_count());
  EXPECT_EQ(SecurityProperties(), pairing()->security());

  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/false));
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(0, auth_failure_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());

  // No security property update should have been sent since the security
  // properties have not changed.
  EXPECT_EQ(0, new_sec_props_count());
  EXPECT_EQ(SecurityProperties(), pairing()->security());
}

// Tests that the STK is generated according to the max length provided
TEST_F(InitiatorPairingTest, StkLengthGeneration) {
  UInt128 stk;
  uint8_t max_key_size = 10;
  FastForwardToSTK(&stk, SecurityLevel::kEncrypted, 0, 0, max_key_size);

  // At this stage, the stk is stored here
  ASSERT_TRUE(fake_link()->ltk());

  // Ensure that most significant (16 - max_key_size) bytes are zero. The key
  // should be generated up to the max_key_size.
  for (auto i = max_key_size; i < fake_link()->ltk()->value().size(); i++) {
    EXPECT_TRUE(fake_link()->ltk()->value()[i] == 0);
  }
}

// Tests that the pairing procedure ends after encryption with the STK if there
// are no keys to distribute, and that no keys are notified for Legacy pairing
// in this case.
TEST_F(InitiatorPairingTest, LegacyPhase3CompleteWithoutKeyExchange) {
  UInt128 stk;
  FastForwardToSTK(&stk);

  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(stk, fake_link()->ltk()->value());
  EXPECT_EQ(0u, fake_link()->ltk()->ediv());
  EXPECT_EQ(0u, fake_link()->ltk()->rand());

  // The host should have requested encryption.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  // Pairing should succeed without any pairing data.
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_FALSE(peer_ltk());
  EXPECT_FALSE(irk());
  EXPECT_FALSE(identity());
  EXPECT_FALSE(csrk());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());

  // The security properties should have been updated to match the STK.
  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props(), pairing()->security());

  ASSERT_TRUE(fake_link()->ltk());
}

// Tests that for Secure Connections, the pairing procedure ends after
// encryption with the LTK if there are no keys to distribute, and that the LTK
// is notified.
TEST_F(InitiatorPairingTest, ScPhase3CompleteWithoutKeyExchange) {
  UInt128 ltk_bytes;
  const SecurityProperties kExpectedSecurity(SecurityLevel::kEncrypted,
                                             kMaxEncryptionKeySize,
                                             /*secure_connections=*/true);
  FastForwardToPhase3(&ltk_bytes,
                      /*secure_connections=*/true,
                      kExpectedSecurity.level(),
                      KeyDistGenField{0},
                      KeyDistGenField{0});

  const LTK kExpectedLtk(kExpectedSecurity, hci_spec::LinkKey(ltk_bytes, 0, 0));
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kExpectedLtk.key(), fake_link()->ltk());

  // Pairing should succeed with the LTK as the SC pairing is bondable, even
  // though no keys need to be distributed in Phase 3.
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_TRUE(peer_ltk().has_value());
  EXPECT_EQ(kExpectedLtk, peer_ltk());
  EXPECT_EQ(peer_ltk(), local_ltk());
  EXPECT_FALSE(irk());
  EXPECT_FALSE(identity());
  EXPECT_FALSE(csrk());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(kExpectedSecurity, sec_props());

  // The security properties should have been updated to match the LTK.
  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props(), pairing()->security());

  ASSERT_TRUE(fake_link()->ltk());
}

// Tests that Secure Connections ignores the EncKey bit in the key distribution
// field.
TEST_F(InitiatorPairingTest, ScPhase3EncKeyBitSetNotDistributed) {
  UInt128 ltk_bytes;
  const SecurityProperties kExpectedSecurity(SecurityLevel::kEncrypted,
                                             kMaxEncryptionKeySize,
                                             /*secure_connections=*/true);
  // We will request the EncKey from the peer and the peer will respond that it
  // is capable of sending it, but as this is SC pairing that should not occur.
  KeyDistGenField remote_keys{KeyDistGen::kEncKey}, local_keys{0};
  FastForwardToScLtk(&ltk_bytes,
                     kExpectedSecurity.level(),
                     remote_keys,
                     local_keys,
                     BondableMode::Bondable);

  const LTK kExpectedLtk(kExpectedSecurity, hci_spec::LinkKey(ltk_bytes, 0, 0));
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kExpectedLtk.key(), fake_link()->ltk());

  // The host should have requested encryption.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  // Pairing should succeed without any messages being sent in "Phase 3". The
  // LTK was generated in SC Phase 2, and as the pairing is bondable, it is
  // included in the callback.
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_TRUE(peer_ltk().has_value());
  EXPECT_EQ(kExpectedLtk, peer_ltk());
  EXPECT_FALSE(irk());
  EXPECT_FALSE(identity());
  EXPECT_FALSE(csrk());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(kExpectedSecurity, sec_props());

  // The security properties should have been updated to match the LTK.
  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props(), pairing()->security());

  ASSERT_TRUE(fake_link()->ltk());
}

// Tests that for Secure Connections non-bondable mode, the pairing procedure
// ends after encryption with the key generated in Phase 2, but the upper layers
// are not notified of that key as an LTK.
TEST_F(InitiatorPairingTest, ScPhase3NonBondableCompleteWithoutKeyExchange) {
  // Must have DisplayYesNo IOC to generate Authenticated security per
  // kExpectedSecurity
  SetUpSecurityManager(IOCapability::kDisplayYesNo);
  const SecurityProperties kExpectedSecurity(SecurityLevel::kAuthenticated,
                                             kMaxEncryptionKeySize,
                                             /*secure_connections=*/true);
  UInt128 ltk_bytes;
  FastForwardToScLtk(&ltk_bytes,
                     kExpectedSecurity.level(),
                     KeyDistGenField{0},
                     KeyDistGenField{0},
                     BondableMode::NonBondable);

  const hci_spec::LinkKey kExpectedLinkKey(ltk_bytes, 0, 0);
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kExpectedLinkKey, fake_link()->ltk());

  // The host should have requested encryption.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  // Pairing should succeed with the LTK as we are in SC, but as the pairing is
  // non-bondable, no LTK should be relayed up to the delegate.
  EXPECT_EQ(0, pairing_data_callback_count());

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(kExpectedSecurity, sec_props());

  // The security properties should have been updated to match the LTK.
  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props(), pairing()->security());

  ASSERT_TRUE(fake_link()->ltk());
}

TEST_F(InitiatorPairingTest, Phase3EncryptionInformationReceivedTwice) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  ReceiveEncryptionInformation(UInt128());
  RunUntilIdle();

  // Waiting for EDIV and Rand
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  // Send the LTK twice. This should cause pairing to fail.
  ReceiveEncryptionInformation(UInt128());
  RunUntilIdle();
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// The responder sends EDIV and Rand before LTK.
TEST_F(InitiatorPairingTest, Phase3CentralIdentificationReceivedInWrongOrder) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  // Send central identification before encryption information. This should
  // cause pairing to fail.
  ReceiveCentralIdentification(1, 2);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// The responder sends the sample LTK from the specification doc
TEST_F(InitiatorPairingTest, Phase3CentralIdentificationReceiveSampleLTK) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  const UInt128 kLtkSample{{0xBF,
                            0x01,
                            0xFB,
                            0x9D,
                            0x4E,
                            0xF3,
                            0xBC,
                            0x36,
                            0xD8,
                            0x74,
                            0xF5,
                            0x39,
                            0x41,
                            0x38,
                            0x68,
                            0x4C}};

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  // Send a bad LTK, this should cause pairing to fail.
  ReceiveEncryptionInformation(kLtkSample);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// The responder sends the sample Rand from the specification doc
TEST_F(InitiatorPairingTest, Phase3CentralIdentificationReceiveExampleRand) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  uint64_t kRandSample = 0xABCDEF1234567890;
  uint16_t kEDiv = 20;

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  // Send a bad Rand, this should cause pairing to fail.
  ReceiveEncryptionInformation(UInt128());
  ReceiveCentralIdentification(kRandSample, kEDiv);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// The responder sends an LTK that is longer than the max key size
TEST_F(InitiatorPairingTest, Phase3CentralIdentificationReceiveLongLTK) {
  UInt128 stk;
  auto max_key_size = 8;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey,
                      0,
                      max_key_size);

  const UInt128 kLtk{{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}};

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  // Send a long LTK, this should cause pairing to fail.
  ReceiveEncryptionInformation(kLtk);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kInvalidParameters), security_status());
  EXPECT_EQ(ErrorCode::kInvalidParameters, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, Phase3CentralIdentificationReceivedTwice) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  constexpr uint16_t kEdiv = 1;
  constexpr uint64_t kRand = 2;
  constexpr uint16_t kDupEdiv = 3;
  constexpr uint64_t kDupRand = 4;

  // Send duplicate central identification. Pairing should complete with the
  // first set of information. The second set should get ignored.
  ReceiveEncryptionInformation(UInt128());
  ReceiveCentralIdentification(kRand, kEdiv);
  ReceiveCentralIdentification(kDupRand, kDupEdiv);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());
  ASSERT_TRUE(pairing_data().peer_ltk.has_value());
  EXPECT_EQ(kEdiv, pairing_data().peer_ltk->key().ediv());
  EXPECT_EQ(kRand, pairing_data().peer_ltk->key().rand());
}

// Pairing completes after obtaining peer encryption information only.
TEST_F(InitiatorPairingTest, Phase3CompleteWithReceivingEncKey) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);

  const UInt128 kLTK{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  uint64_t kRand = 5;
  uint16_t kEDiv = 20;

  ReceiveEncryptionInformation(kLTK);
  ReceiveCentralIdentification(kRand, kEDiv);
  RunUntilIdle();

  // Pairing should have succeeded.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // LTK should have been assigned to the link.
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kLTK, fake_link()->ltk()->value());
  EXPECT_EQ(kRand, fake_link()->ltk()->rand());
  EXPECT_EQ(kEDiv, fake_link()->ltk()->ediv());

  // We don't re-encrypt with the LTK while the link is already authenticated
  // with the STK.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  // Local identity information should not have been distributed by us since it
  // isn't available.
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());

  // Should have notified the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(peer_ltk());
  ASSERT_FALSE(irk());
  ASSERT_FALSE(identity());
  ASSERT_FALSE(csrk());
  EXPECT_EQ(sec_props(), peer_ltk()->security());
  EXPECT_EQ(kLTK, peer_ltk()->key().value());
  EXPECT_EQ(kRand, peer_ltk()->key().rand());
  EXPECT_EQ(kEDiv, peer_ltk()->key().ediv());

  // No security property update should have been sent for the LTK. This is
  // because the LTK and the STK are expected to have the same properties.
  EXPECT_EQ(1, new_sec_props_count());
}

TEST_F(InitiatorPairingTest, Phase3CompleteWithSendingEncKey) {
  UInt128 stk;
  KeyDistGenField remote_keys{0u}, local_keys{KeyDistGen::kEncKey};
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      remote_keys,
                      local_keys);
  RunUntilIdle();

  // Pairing should have succeeded.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // Only the STK should be assigned to the link, as the distributed LTK was
  // initiator-generated. This means it can only be used to encrypt future
  // connections where the roles are reversed.
  EXPECT_EQ(stk, fake_link()->ltk()->value());
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  // Should have notified pairing data callback with the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(local_ltk());

  // LTK sent OTA should match what we notified the pairing data callback with.
  EXPECT_EQ(local_ltk()->key(), hci_spec::LinkKey(enc_info(), rand(), ediv()));
}

// Pairing completes after obtaining short encryption information only.
TEST_F(InitiatorPairingTest, Phase3CompleteWithShortEncKey) {
  UInt128 stk;
  uint8_t max_key_size = 12;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey,
                      0u,
                      max_key_size);

  // This LTK is within the max_key_size specified above.
  const UInt128 kLTK{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 0, 0, 0, 0}};
  uint64_t kRand = 5;
  uint16_t kEDiv = 20;

  ReceiveEncryptionInformation(kLTK);
  ReceiveCentralIdentification(kRand, kEDiv);
  RunUntilIdle();

  // Pairing should have succeeded.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // LTK should have been assigned to the link.
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kLTK, fake_link()->ltk()->value());
  EXPECT_EQ(kRand, fake_link()->ltk()->rand());
  EXPECT_EQ(kEDiv, fake_link()->ltk()->ediv());

  // We don't re-encrypt with the LTK while the link is already authenticated
  // with the STK.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(max_key_size, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  // Local identity information should not have been distributed by us since it
  // isn't available.
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());

  // Should have notified the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(peer_ltk());
  ASSERT_FALSE(irk());
  ASSERT_FALSE(identity());
  ASSERT_FALSE(csrk());
  EXPECT_EQ(sec_props(), peer_ltk()->security());
  EXPECT_EQ(kLTK, peer_ltk()->key().value());
  EXPECT_EQ(kRand, peer_ltk()->key().rand());
  EXPECT_EQ(kEDiv, peer_ltk()->key().ediv());

  // No security property update should have been sent for the LTK. This is
  // because the LTK and the STK are expected to have the same properties.
  EXPECT_EQ(1, new_sec_props_count());
}

TEST_F(InitiatorPairingTest, Phase3WithLocalIdKey) {
  IdentityInfo local_id_info;
  local_id_info.irk = UInt128{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  local_id_info.address = kLocalAddr;
  set_local_id_info(local_id_info);

  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0,                    // remote keys
                      KeyDistGen::kIdKey);  // local keys

  // Local identity information should have been sent.
  EXPECT_EQ(1, id_info_count());
  EXPECT_EQ(local_id_info.irk, id_info());
  EXPECT_EQ(1, id_addr_info_count());
  EXPECT_EQ(local_id_info.address, id_addr_info());

  // Pairing should succeed without notifying any keys.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// Tests that pairing results in an error if a local ID key was initially
// negotiated but gets removed before the distribution phase.
TEST_F(InitiatorPairingTest, Phase3IsAbortedIfLocalIdKeyIsRemoved) {
  IdentityInfo local_id_info;
  local_id_info.irk = UInt128{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  local_id_info.address = kLocalAddr;
  set_local_id_info(local_id_info);

  UInt128 stk;
  FastForwardToSTK(&stk,
                   SecurityLevel::kEncrypted,
                   0,                    // remote keys
                   KeyDistGen::kIdKey);  // local keys

  // Local identity information should not have been sent yet.
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());

  // Pairing still in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Remove the local identity information.
  set_local_id_info(std::nullopt);

  // Encrypt with the STK to finish phase 2.
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  // Pairing should have been aborted.
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
}

TEST_F(InitiatorPairingTest, Phase3IRKReceivedTwice) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kIdKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());

  ReceiveIdentityResolvingKey(UInt128());
  RunUntilIdle();

  // Waiting for identity address.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Send an IRK again. This should cause pairing to fail.
  ReceiveIdentityResolvingKey(UInt128());
  RunUntilIdle();
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// The responder sends its identity address before sending its IRK.
TEST_F(InitiatorPairingTest, Phase3IdentityAddressReceivedInWrongOrder) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kIdKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Send identity address before the IRK. This should cause pairing to fail.
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, Phase3IdentityAddressReceivedTwice) {
  UInt128 stk;
  // Request enc key to prevent pairing from completing after sending the first
  // identity address.
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey | KeyDistGen::kIdKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  ReceiveIdentityResolvingKey(UInt128());
  ReceiveIdentityAddress(kPeerAddr);
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), security_status());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

// Pairing completes after obtaining identity information only.
TEST_F(InitiatorPairingTest, Phase3CompleteWithIdKey) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kIdKey);

  // Pairing should still be in progress.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_data_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  const UInt128 kIRK{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};

  ReceiveIdentityResolvingKey(kIRK);
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // The link remains encrypted with the STK.
  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());

  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_FALSE(peer_ltk());
  ASSERT_TRUE(irk());
  ASSERT_TRUE(identity());
  ASSERT_FALSE(csrk());

  EXPECT_EQ(sec_props(), irk()->security());
  EXPECT_EQ(kIRK, irk()->value());
  EXPECT_EQ(kPeerAddr, *identity());
}

TEST_F(InitiatorPairingTest, Phase3CompleteWithAllKeys) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey | KeyDistGen::kIdKey);

  const UInt128 kLTK{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  const UInt128 kIRK{{8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8}};
  uint64_t kRand = 5;
  uint16_t kEDiv = 20;

  // The link should be assigned the STK as its link key.
  EXPECT_EQ(stk, fake_link()->ltk()->value());

  // Receive EncKey
  ReceiveEncryptionInformation(kLTK);
  ReceiveCentralIdentification(kRand, kEDiv);
  RunUntilIdle();

  // Pairing still pending. SMP does not assign the LTK to the link until
  // pairing completes.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Receive IdKey
  ReceiveIdentityResolvingKey(kIRK);
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  // Pairing should have succeeded
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // LTK should have been assigned to the link.
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kLTK, fake_link()->ltk()->value());
  EXPECT_EQ(kRand, fake_link()->ltk()->rand());
  EXPECT_EQ(kEDiv, fake_link()->ltk()->ediv());

  // We don't re-encrypt with the LTK while the link is already authenticated
  // with the STK.
  EXPECT_EQ(1, fake_link()->start_encryption_count());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_FALSE(sec_props().secure_connections());

  // Should have notified the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(peer_ltk());
  ASSERT_TRUE(irk());
  ASSERT_TRUE(identity());
  ASSERT_FALSE(csrk());
  EXPECT_EQ(sec_props(), peer_ltk()->security());
  EXPECT_EQ(kLTK, peer_ltk()->key().value());
  EXPECT_EQ(kRand, peer_ltk()->key().rand());
  EXPECT_EQ(kEDiv, peer_ltk()->key().ediv());
  EXPECT_EQ(sec_props(), irk()->security());
  EXPECT_EQ(kIRK, irk()->value());
  EXPECT_EQ(kPeerAddr, *identity());
}

TEST_F(InitiatorPairingTest, GenerateCrossTransportLinkKey) {
  UInt128 stk;
  // Indicate support for SC and for link keys in both directions to enable
  // CTKG.
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/true,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kLinkKey,
                      KeyDistGen::kLinkKey);
  RunUntilIdle();

  // Pairing should have succeeded
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // The PairingData should contain the CTKGenerated BR/EDR link key.
  EXPECT_TRUE(pairing_data().cross_transport_key.has_value());
}

TEST_F(InitiatorPairingTest, AssignLongTermKeyFailsDuringPairing) {
  UpgradeSecurity(SecurityLevel::kEncrypted);  // Initiate pairing.
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  EXPECT_FALSE(
      pairing()->AssignLongTermKey(LTK(sec_props, hci_spec::LinkKey())));
  EXPECT_EQ(0, fake_link()->start_encryption_count());
  EXPECT_EQ(SecurityLevel::kNoSecurity, pairing()->security().level());
}

TEST_F(InitiatorPairingTest, AssignLongTermKey) {
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  LTK ltk(sec_props, hci_spec::LinkKey());

  EXPECT_TRUE(pairing()->AssignLongTermKey(ltk));
  EXPECT_EQ(1, fake_link()->start_encryption_count());
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(ltk.key(), *fake_link()->ltk());

  // The link security level is not assigned until successful encryption.
  EXPECT_EQ(SecurityProperties(), pairing()->security());
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props, new_sec_props());
  EXPECT_EQ(sec_props, pairing()->security());
}

TEST_F(InitiatorPairingTest, ReceiveSecurityRequest) {
  ReceiveSecurityRequest(AuthReq::kMITM);
  RunUntilIdle();

  // Should have requested pairing with MITM protection.
  EXPECT_EQ(1, pairing_request_count());
  const auto& params = local_pairing_cmd().view(1).To<PairingRequestParams>();
  EXPECT_TRUE(params.auth_req & AuthReq::kMITM);
}

TEST_F(InitiatorPairingTest, ReceiveSecurityRequestWhenPaired) {
  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kEncKey);
  EXPECT_EQ(stk, fake_link()->ltk()->value());
  EXPECT_EQ(1, pairing_request_count());

  // Receive EncKey and wait until the link is encrypted with the LTK.
  UInt128 kLTK{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  uint64_t kRand = 5;
  uint16_t kEDiv = 20;
  ReceiveEncryptionInformation(kLTK);
  ReceiveCentralIdentification(kRand, kEDiv);
  RunUntilIdle();
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(fit::ok(), security_status());
  ASSERT_TRUE(peer_ltk());
  ASSERT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  ASSERT_EQ(1, fake_link()->start_encryption_count());  // Once for the STK
  ASSERT_EQ(1, pairing_request_count());

  // Receive a security request with the no MITM requirement. This should
  // trigger an encryption key refresh and no pairing request.
  ReceiveSecurityRequest();
  EXPECT_EQ(1, pairing_request_count());

  // Once for the STK and once again due to the locally initiated key refresh.
  ASSERT_EQ(2, fake_link()->start_encryption_count());

  // Receive a security request with a higher security requirement. This should
  // trigger a pairing request.
  ReceiveSecurityRequest(AuthReq::kMITM);
  EXPECT_EQ(2, pairing_request_count());
  const auto& params = local_pairing_cmd().view(1).To<PairingRequestParams>();
  EXPECT_TRUE(params.auth_req & AuthReq::kMITM);
}

TEST_F(InitiatorPairingTest,
       ReceiveMITMSecurityRequestLocalIoCapNoInputNoOutput) {
  SetUpSecurityManager(IOCapability::kNoInputNoOutput);
  ReceiveSecurityRequest(AuthReq::kMITM);
  // We should notify the peer that we cannot complete the security request due
  // to authentication requirements.
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(ErrorCode::kAuthenticationRequirements, received_error_code());

  // When we receive a Security Request, we start a timer. Run the loop to
  // ensure that when we can't fulfill the Security Request, we stop the timer
  // before it expires as we never started pairing.
  RunFor(kPairingTimeout + std::chrono::seconds(1));
  // Double check we haven't sent any more Pairing Failed messages
  EXPECT_EQ(1, pairing_failed_count());
  // We should not notify local clients of any pairing completion, because no
  // pairing ever started.
  EXPECT_EQ(0, pairing_complete_count());
}

TEST_F(InitiatorPairingTest, RejectPairingRequest) {
  // Although we are the initiator, set the peer_initiator=true for this test so
  // that we emulate reception of the Pairing Request command, not the Pairing
  // Response command.
  ReceivePairingFeatures(IOCapability::kDisplayYesNo,
                         AuthReqField{0},
                         kMaxEncryptionKeySize,
                         /*peer_initiator=*/true);
  RunUntilIdle();
  // We should reject the security request with CommandNotSupported as
  // initiator.
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(ErrorCode::kCommandNotSupported, received_error_code());

  // Run for the full pairing timeout to ensure we do not timeout due to sending
  // a message.
  RunFor(kPairingTimeout + std::chrono::seconds(1));
  // No pairing occurred, as we rejected the security request command.
  EXPECT_EQ(0, pairing_complete_count());
  EXPECT_EQ(1, pairing_failed_count());
}

TEST_F(InitiatorPairingTest, PairingTimeoutWorks) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  ASSERT_EQ(1, pairing_request_count());
  // Expiration of the pairing timeout should trigger the link error callback
  // per v5.2 Vol. 3 Part H 3.4. Link disconnection will generally cause channel
  // closure, so this simulates that behavior to validate that SM handles this
  // safely.
  fake_chan()->SetLinkErrorCallback([chan = fake_chan()]() { chan->Close(); });
  RunFor(kPairingTimeout);
  EXPECT_TRUE(fake_chan()->link_error());
  ASSERT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(HostError::kTimedOut), security_status());
  ASSERT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(HostError::kTimedOut), pairing_complete_status());
}

TEST_F(InitiatorPairingTest, NoTimeoutAfterSuccessfulPairing) {
  UInt128 out_stk;
  FastForwardToPhase3(&out_stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGenField{0},
                      KeyDistGenField{0});
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  ASSERT_EQ(fit::ok(), security_status());
  ASSERT_EQ(fit::ok(), pairing_complete_status());
  // Verify that no timeout occurs after a successful pairing followed by a long
  // interval.
  RunFor(kPairingTimeout * 2);
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  EXPECT_NE(ToResult(HostError::kTimedOut), pairing_complete_status());
  EXPECT_NE(ToResult(HostError::kTimedOut), security_status());
}

TEST_F(InitiatorPairingTest, AbortStopsPairingTimer) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  ASSERT_EQ(1, pairing_request_count());
  pairing()->Abort();
  // Calling Abort should stop the pairing procedure and the timer.
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  // Run the loop for a time that would cause a timeout if a timer were active.
  RunFor(kPairingTimeout * 2);
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  EXPECT_NE(ToResult(HostError::kTimedOut), pairing_complete_status());
  EXPECT_NE(ToResult(HostError::kTimedOut), security_status());
}

TEST_F(InitiatorPairingTest, ResetStopsPairingTimer) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  ASSERT_EQ(1, pairing_request_count());
  pairing()->Reset(IOCapability::kDisplayYesNo);
  // Resetting the pairing aborts the current procedure.
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  // Run the loop for a time that would cause a timeout if a timer were active.
  RunFor(kPairingTimeout * 2);
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  EXPECT_NE(ToResult(HostError::kTimedOut), pairing_complete_status());
  EXPECT_NE(ToResult(HostError::kTimedOut), security_status());
}

TEST_F(InitiatorPairingTest, SendingMessageRestartsTimer) {
  // SM will send the Pairing Request, which is special-cased to "reset and
  // start" the pairing timer (v5.2 Vol. 3 Part H 3.4), and thus not under test
  // here.
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  ASSERT_EQ(1, pairing_request_count());
  // Run the loop until the pairing timeout has almost expired.
  RunFor(kPairingTimeout - pw::chrono::SystemClock::duration(1));
  // Receive the not special-cased Pairing Response, which should trigger SM to
  // send the also not special-cased Pairing Confirm.
  ReceivePairingFeatures();
  // Run the loop for 1 more second, which would timeout if the timer had not
  // been reset.
  RunFor(pw::chrono::SystemClock::duration(1));
  // The timeout should not have triggered, so there should be no notification
  // of pairing failure.
  ASSERT_EQ(0, pairing_complete_count());
  ASSERT_EQ(0, security_callback_count());
  // Verify that the timer is in fact still active; without receiving further
  // messages, the timeout should trigger.
  RunFor(kPairingTimeout);
  ASSERT_EQ(1, pairing_complete_count());
  ASSERT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(HostError::kTimedOut), pairing_complete_status());
  EXPECT_EQ(ToResult(HostError::kTimedOut), security_status());
}

TEST_F(InitiatorPairingTest,
       ModifyAssignedLinkLtkBeforeSecurityRequestCausesDisconnect) {
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  const LTK kOriginalLtk(sec_props, hci_spec::LinkKey({1}, 2, 3));
  const hci_spec::LinkKey kModifiedLtk(hci_spec::LinkKey({4}, 5, 6));

  EXPECT_TRUE(pairing()->AssignLongTermKey(kOriginalLtk));
  fake_link()->set_ltk(kModifiedLtk);
  // When we receive the Security Request on a bonded (i.e. AssignLongTermKey
  // has been called) connection, we will refresh the encryption key. This
  // checks that the link LTK = the SMP LTK which is not the case.
  ReceiveSecurityRequest(AuthReqField{0});
  RunUntilIdle();
  ASSERT_TRUE(fake_chan()->link_error());
  ASSERT_EQ(1, auth_failure_callback_count());
  ASSERT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING),
            auth_failure_status());
}

TEST_F(ResponderPairingTest, SuccessfulPairAfterResetInProgressPairing) {
  ReceivePairingRequest();
  RunUntilIdle();
  // At this point, we expect to have completed Phase 1, and pairing should
  // still be in progress.
  EXPECT_EQ(1, pairing_response_count());

  pairing()->Abort();
  RunUntilIdle();
  // Pairing should have failed and ended.
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, pairing_complete_count());

  // Verify that the next pairing request is properly handled
  ReceivePairingRequest();
  RunUntilIdle();
  // At this point, we expect to have completed Phase 1, and pairing should
  // still be in progress.
  EXPECT_EQ(2, pairing_response_count());
}

TEST_F(ResponderPairingTest, SecurityRequestCausesPairing) {
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  AuthReqField expected_auth_req = AuthReq::kBondingFlag;
  EXPECT_EQ(1, security_request_count());
  EXPECT_EQ(expected_auth_req, security_request_payload());
  UInt128 ltk_bytes;
  FastForwardToPhase3(&ltk_bytes, /*secure_connections=*/true);
  // Pairing should have succeeded
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // LTK should have been assigned to the link.
  hci_spec::LinkKey kExpectedLinkKey(ltk_bytes, 0, 0);
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kExpectedLinkKey, fake_link()->ltk());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_TRUE(sec_props().secure_connections());

  // Should have notified the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(local_ltk());
  EXPECT_EQ(sec_props(), local_ltk()->security());
  EXPECT_EQ(kExpectedLinkKey, local_ltk()->key());
}

TEST_F(ResponderPairingTest, SecurityRequestWithExistingLtk) {
  const SecurityProperties kProps(SecurityLevel::kAuthenticated,
                                  kMaxEncryptionKeySize,
                                  /*secure_connections=*/true);
  const LTK kLtk(kProps, hci_spec::LinkKey({1, 2, 3}, 0, 0));
  // This pretends that we have an already-bonded LTK.
  pairing()->AssignLongTermKey(kLtk);
  // LTK should have been assigned to the link.
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kLtk.key(), fake_link()->ltk());

  // Make the Security Upgrade request
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();
  AuthReqField expected_auth_req = AuthReq::kBondingFlag | AuthReq::kMITM;
  EXPECT_EQ(1, security_request_count());
  EXPECT_EQ(expected_auth_req, security_request_payload());
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));

  // Security should be upgraded.
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(kProps.level(), sec_props().level());
  EXPECT_EQ(16u, sec_props().enc_key_size());
  EXPECT_TRUE(sec_props().secure_connections());

  // No pairing should have taken place - we had an already-bonded LTK.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, pairing_complete_count());
  EXPECT_EQ(0, pairing_data_callback_count());
}

TEST_F(ResponderPairingTest,
       SecurityRequestInitiatorEncryptsWithInsufficientSecurityLtk) {
  const SecurityProperties kProps(SecurityLevel::kEncrypted,
                                  kMaxEncryptionKeySize,
                                  /*secure_connections=*/true);
  const LTK kLtk(kProps, hci_spec::LinkKey({1, 2, 3}, 0, 0));
  // This pretends that we have an already-bonded LTK with kEncrypted security
  // level.
  pairing()->AssignLongTermKey(kLtk);
  // LTK should have been assigned to the link.
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kLtk.key(), fake_link()->ltk());

  // Make a security request for authenticated security
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();
  AuthReqField expected_auth_req = AuthReq::kBondingFlag | AuthReq::kMITM;
  EXPECT_EQ(1, security_request_count());
  EXPECT_EQ(expected_auth_req, security_request_payload());

  // Pretend the SMP initiator started encryption with the bonded LTK of
  // SecurityLevel::kEncrypted.
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));

  // If the peer responds to our MITM security request by encrypting with an
  // unauthenticated key, they stored the LTK/handle security request
  // incorrectly - either way, disconnect the link.
  ASSERT_TRUE(fake_chan()->link_error());
}

TEST_F(ResponderPairingTest,
       AuthenticatedSecurityRequestWithInsufficientIoCapRejected) {
  SetUpSecurityManager(IOCapability::kNoInputNoOutput);
  // Make a security request for authenticated security
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();
  // The security callback should have been rejected w/o sending any messages,
  // as our IOCap cannot perform authenticated pairing.
  EXPECT_EQ(0, security_request_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kAuthenticationRequirements),
            security_status());
  EXPECT_EQ(SecurityLevel::kNoSecurity, sec_props().level());
}

TEST_F(ResponderPairingTest, HandlesMultipleSecurityRequestsCorrectly) {
  // Make a security request for encrypted security
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  AuthReqField expected_auth_req = AuthReq::kBondingFlag;
  EXPECT_EQ(1, security_request_count());
  EXPECT_EQ(expected_auth_req, security_request_payload());

  // Making another security request, this time for authenticated security,
  // while the first is still pending should not cause another Security Request
  // message to be sent.
  UpgradeSecurity(SecurityLevel::kAuthenticated);
  RunUntilIdle();
  EXPECT_EQ(1, security_request_count());

  // Handle the first Security Request
  UInt128 ltk_bytes;
  FastForwardToPhase3(
      &ltk_bytes, /*secure_connections=*/true, SecurityLevel::kEncrypted);
  // Pairing should have succeeded
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  EXPECT_EQ(SecurityLevel::kEncrypted, sec_props().level());

  // Should have notified the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(local_ltk());
  EXPECT_EQ(sec_props(), local_ltk()->security());
  EXPECT_EQ(ltk_bytes, local_ltk()->key().value());

  // After the first pairing satisfied the kEncrypted Security Request, the
  // pending kAuthenticated Security Request should have been sent immediately.
  EXPECT_EQ(2, security_request_count());
}

TEST_F(ResponderPairingTest, ReceiveSecondPairingRequestWhilePairing) {
  ReceivePairingRequest();
  RunUntilIdle();

  // We should have sent a pairing response and should now be in Phase 2,
  // waiting for the peer to send us Mconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // This should cause pairing to be aborted.
  ReceivePairingRequest();
  RunUntilIdle();
  EXPECT_EQ(0, pairing_request_count());
  // We will abort the second pairing request without responding if we're
  // already in progress
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  ASSERT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(ToResult(received_error_code().value()), pairing_complete_status());
}

TEST_F(ResponderPairingTest, ReceiveConfirmValueWhileWaitingForTK) {
  bool tk_requested = false;
  ConfirmCallback respond;
  set_confirm_delegate([&](ConfirmCallback cb) {
    tk_requested = true;
    respond = std::move(cb);
  });

  ReceivePairingRequest();
  RunUntilIdle();
  ASSERT_TRUE(tk_requested);

  UInt128 confirm;
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // Pairing should still be in progress without sending out any packets.
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Respond with the TK. This should cause us to send Sconfirm.
  respond(true);
  RunUntilIdle();
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());
}

TEST_F(ResponderPairingTest, LegacyPhase2ReceivePairingRandomInWrongOrder) {
  ReceivePairingRequest();
  RunUntilIdle();

  // We should have sent a pairing response and should now be in Phase 2,
  // waiting for the peer to send us Mconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Peer sends Mrand before Mconfirm.
  UInt128 random;
  ReceivePairingRandom(random);
  RunUntilIdle();
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ErrorCode::kUnspecifiedReason, received_error_code());
  EXPECT_EQ(ToResult(ErrorCode::kUnspecifiedReason), pairing_complete_status());
}

TEST_F(ResponderPairingTest, LegacyPhase2MconfirmValueInvalid) {
  ReceivePairingRequest();
  RunUntilIdle();

  // We should have sent a pairing response and should now be in Phase 2,
  // waiting for the peer to send us Mconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Set up values that don't match.
  UInt128 confirm, random;
  confirm.fill(0);
  random.fill(1);

  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // We should have sent Sconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Peer sends Mrand that doesn't match. We should reject the pairing
  // without sending Srand.
  ReceivePairingRandom(random);
  RunUntilIdle();
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ErrorCode::kConfirmValueFailed, received_error_code());
  EXPECT_EQ(ToResult(ErrorCode::kConfirmValueFailed),
            pairing_complete_status());
}

TEST_F(ResponderPairingTest, LegacyPhase2ConfirmValuesExchanged) {
  ReceivePairingRequest();
  RunUntilIdle();

  // We should have sent a pairing response and should now be in Phase 2,
  // waiting for the peer to send us Mconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(0, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Set up Sconfirm and Srand values that match.
  UInt128 confirm, random;
  GenerateMatchingLegacyConfirmAndRandom(&confirm, &random);

  // Peer sends Mconfirm.
  ReceivePairingConfirm(confirm);
  RunUntilIdle();

  // We should have sent Sconfirm.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(0, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Peer sends Mrand.
  ReceivePairingRandom(random);
  RunUntilIdle();

  // We should have sent Srand.
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(1, pairing_response_count());
  EXPECT_EQ(1, pairing_confirm_count());
  EXPECT_EQ(1, pairing_random_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, pairing_complete_count());

  // Sconfirm/Srand values we sent should be correct.
  UInt128 expected_confirm;
  GenerateLegacyConfirmValue(
      pairing_random(), &expected_confirm, /*peer_initiator=*/true);
  EXPECT_EQ(expected_confirm, pairing_confirm());
}

TEST_F(ResponderPairingTest, LegacyPhase3LocalLTKDistributionNoRemoteKeys) {
  EXPECT_EQ(0, enc_info_count());
  EXPECT_EQ(0, central_ident_count());

  UInt128 stk;
  KeyDistGenField remote_keys{0}, local_keys{KeyDistGen::kEncKey};
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      remote_keys,
                      local_keys);

  // Local LTK, EDiv, and Rand should be sent to the peer.
  EXPECT_EQ(1, enc_info_count());
  EXPECT_EQ(1, central_ident_count());
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(enc_info(), fake_link()->ltk()->value());
  EXPECT_EQ(ediv(), fake_link()->ltk()->ediv());
  EXPECT_EQ(rand(), fake_link()->ltk()->rand());

  // This LTK should be stored with the pairing data but the pairing callback
  // shouldn't be called because pairing wasn't initiated by UpgradeSecurity().
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  // Pairing is considered complete when all keys have been distributed even if
  // we're still encrypted with the STK. This is because the initiator may not
  // always re-encrypt the link with the LTK until a reconnection.
  EXPECT_EQ(1, pairing_data_callback_count());

  // Nonetheless the link should have been assigned the LTK.
  ASSERT_TRUE(pairing_data().local_ltk.has_value());
  EXPECT_EQ(fake_link()->ltk(), pairing_data().local_ltk->key());

  // Make sure that an encryption change has no effect.
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();
  EXPECT_EQ(1, pairing_data_callback_count());

  // No additional security property update should have been sent since the STK
  // and LTK have the same properties.
  EXPECT_EQ(1, new_sec_props_count());
}

TEST_F(ResponderPairingTest, LegacyPhase3LocalLTKDistributionWithRemoteKeys) {
  EXPECT_EQ(0, enc_info_count());
  EXPECT_EQ(0, central_ident_count());

  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kIdKey,    // remote keys
                      KeyDistGen::kEncKey);  // local keys

  // Local LTK, EDiv, and Rand should be sent to the peer - we don't assign the
  // new LTK to the link until pairing is complete.
  EXPECT_EQ(1, enc_info_count());
  EXPECT_EQ(1, central_ident_count());

  // No local identity information should have been sent.
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());

  // This LTK should be stored with the pairing data but the pairing callback
  // shouldn't be called because pairing wasn't initiated by UpgradeSecurity().
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  // Still waiting for initiator's keys.
  EXPECT_EQ(0, pairing_data_callback_count());

  const auto kIrk = Random<UInt128>();
  ReceiveIdentityResolvingKey(kIrk);
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  // Pairing is considered complete when all keys have been distributed even if
  // we're still encrypted with the STK. This is because the initiator may not
  // always re-encrypt the link with the LTK until a reconnection.
  EXPECT_EQ(1, pairing_data_callback_count());

  // The peer should have sent us its identity information.
  ASSERT_TRUE(pairing_data().irk);
  EXPECT_EQ(kIrk, pairing_data().irk->value());
  ASSERT_TRUE(pairing_data().identity_address);
  EXPECT_EQ(kPeerAddr, *pairing_data().identity_address);

  // Nonetheless the link should have been assigned the LTK.
  ASSERT_TRUE(pairing_data().local_ltk.has_value());
  EXPECT_EQ(fake_link()->ltk(), pairing_data().local_ltk->key());
}

// Locally generated ltk length should match max key length specified
TEST_F(ResponderPairingTest, LegacyPhase3LocalLTKMaxLength) {
  EXPECT_EQ(0, enc_info_count());
  EXPECT_EQ(0, central_ident_count());

  UInt128 stk;
  uint16_t max_key_size = 7;

  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0u,                   // remote keys
                      KeyDistGen::kEncKey,  // local keys
                      max_key_size);

  // Local LTK, EDiv, and Rand should be sent to the peer.
  EXPECT_EQ(1, enc_info_count());
  EXPECT_EQ(1, central_ident_count());
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(enc_info(), fake_link()->ltk()->value());
  EXPECT_EQ(ediv(), fake_link()->ltk()->ediv());
  EXPECT_EQ(rand(), fake_link()->ltk()->rand());

  // This LTK should be stored with the pairing data but the pairing callback
  // shouldn't be called because pairing wasn't initiated by UpgradeSecurity().
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(0, security_callback_count());

  // Pairing is considered complete when all keys have been distributed even if
  // we're still encrypted with the STK. This is because the initiator may not
  // always re-encrypt the link with the LTK until a reconnection.
  EXPECT_EQ(1, pairing_data_callback_count());

  // The link should have been assigned the LTK.
  ASSERT_TRUE(pairing_data().local_ltk.has_value());
  EXPECT_EQ(fake_link()->ltk(), pairing_data().local_ltk->key());

  // Ensure that most significant (16 - max_key_size) bytes are zero. The key
  // should be generated up to the max_key_size.
  auto ltk = pairing_data().local_ltk->key().value();
  for (auto i = max_key_size; i < ltk.size(); i++) {
    EXPECT_TRUE(ltk[i] == 0);
  }
}

TEST_F(ResponderPairingTest, LegacyPhase3ReceiveInitiatorEncKey) {
  UInt128 stk;
  KeyDistGenField remote_keys{KeyDistGen::kEncKey}, local_keys{0u};
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      remote_keys,
                      local_keys);

  const uint64_t kRand = 5;
  const uint16_t kEDiv = 20;
  const hci_spec::LinkKey kLTK(
      {1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}, kRand, kEDiv);

  ReceiveEncryptionInformation(kLTK.value());
  ReceiveCentralIdentification(kRand, kEDiv);
  RunUntilIdle();

  // Pairing should have succeeded.
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(fit::ok(), security_status());
  EXPECT_EQ(security_status(), pairing_complete_status());

  // No pairing callbacks needed as this is a peer-initiated pairing.
  EXPECT_EQ(0, security_callback_count());

  // Only the STK should be assigned to the link, as the distributed LTK was
  // initiator-generated. This means it can only be used to encrypt future
  // connections where the roles are reversed.
  EXPECT_EQ(stk, fake_link()->ltk()->value());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());

  // Should have notified pairing data callback with the LTK.
  EXPECT_EQ(1, pairing_data_callback_count());
  ASSERT_TRUE(peer_ltk());

  // LTK received OTA should match what we notified the pairing data callback
  // with.
  EXPECT_EQ(kLTK, peer_ltk()->key());
}

TEST_F(ResponderPairingTest, LegacyPhase3LocalIdKeyDistributionWithRemoteKeys) {
  IdentityInfo local_id_info;
  local_id_info.irk = UInt128{{1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
  local_id_info.address = kLocalAddr;
  set_local_id_info(local_id_info);

  EXPECT_EQ(0, enc_info_count());
  EXPECT_EQ(0, central_ident_count());

  UInt128 stk;
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      KeyDistGen::kIdKey,   // remote keys
                      KeyDistGen::kIdKey);  // local keys

  // No local LTK, EDiv, and Rand should be sent to the peer.
  EXPECT_EQ(0, enc_info_count());
  EXPECT_EQ(0, central_ident_count());

  // Local identity information should have been sent.
  EXPECT_EQ(1, id_info_count());
  EXPECT_EQ(local_id_info.irk, id_info());
  EXPECT_EQ(1, id_addr_info_count());
  EXPECT_EQ(local_id_info.address, id_addr_info());

  // Still waiting for initiator's keys.
  EXPECT_EQ(0, pairing_data_callback_count());

  const auto kIrk = Random<UInt128>();
  ReceiveIdentityResolvingKey(kIrk);
  ReceiveIdentityAddress(kPeerAddr);
  RunUntilIdle();

  // Pairing is considered complete when all keys have been distributed even if
  // we're still encrypted with the STK. This is because the initiator may not
  // always re-encrypt the link with the LTK until a reconnection.
  EXPECT_EQ(1, pairing_data_callback_count());

  // The peer should have sent us its identity information.
  ASSERT_TRUE(pairing_data().irk);
  EXPECT_EQ(kIrk, pairing_data().irk->value());
  ASSERT_TRUE(pairing_data().identity_address);
  EXPECT_EQ(kPeerAddr, *pairing_data().identity_address);
}

TEST_F(ResponderPairingTest, AssignLongTermKeyFailsDuringPairing) {
  ReceivePairingRequest();
  RunUntilIdle();
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  EXPECT_FALSE(
      pairing()->AssignLongTermKey(LTK(sec_props, hci_spec::LinkKey())));
  EXPECT_EQ(0, fake_link()->start_encryption_count());
  EXPECT_EQ(SecurityLevel::kNoSecurity, pairing()->security().level());
}

TEST_F(ResponderPairingTest, AssignLongTermKey) {
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  LTK ltk(sec_props, hci_spec::LinkKey());

  EXPECT_TRUE(pairing()->AssignLongTermKey(ltk));
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(ltk.key(), *fake_link()->ltk());

  // No encryption request should have been made as the initiator is expected to
  // do it.
  EXPECT_EQ(0, fake_link()->start_encryption_count());

  // The link security level is not assigned until successful encryption.
  EXPECT_EQ(SecurityProperties(), pairing()->security());
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();

  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(sec_props, new_sec_props());
  EXPECT_EQ(sec_props, pairing()->security());
}

TEST_F(ResponderPairingTest, EncryptWithLinkKeyModifiedOutsideSmDisconnects) {
  SecurityProperties sec_props(
      SecurityLevel::kAuthenticated, 16, /*secure_connections=*/false);
  const LTK kOriginalLtk(sec_props, hci_spec::LinkKey({1}, 2, 3));
  const hci_spec::LinkKey kModifiedLtk(hci_spec::LinkKey({4}, 5, 6));

  EXPECT_TRUE(pairing()->AssignLongTermKey(kOriginalLtk));
  fake_link()->set_ltk(kModifiedLtk);
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();
  ASSERT_TRUE(fake_chan()->link_error());
  ASSERT_EQ(1, auth_failure_callback_count());
  ASSERT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING),
            auth_failure_status());
}

TEST_F(ResponderPairingTest, EncryptWithLinkKeyButNoSmLtkDisconnects) {
  // The LE link LTK should always be assigned through SM, so while encryption
  // could succeed with a link LTK but no SM LTK, this is a violation of bt-host
  // assumptions and we will disconnect.
  fake_link()->set_ltk(hci_spec::LinkKey({1}, 2, 3));
  fake_link()->TriggerEncryptionChangeCallback(fit::ok(/*enabled=*/true));
  RunUntilIdle();
  ASSERT_TRUE(fake_chan()->link_error());
  ASSERT_EQ(1, auth_failure_callback_count());
  ASSERT_EQ(ToResult(pw::bluetooth::emboss::StatusCode::PIN_OR_KEY_MISSING),
            auth_failure_status());
}

// As responder, we reject security requests, as the initiator should never send
// them.
TEST_F(ResponderPairingTest, RejectSecurityRequest) {
  ReceiveSecurityRequest();
  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(ErrorCode::kCommandNotSupported, received_error_code());

  // Run for the full pairing timeout to ensure we do not timeout due to sending
  // a message.
  RunFor(kPairingTimeout + std::chrono::seconds(1));
  EXPECT_EQ(0, pairing_request_count());
  EXPECT_EQ(0, fake_link()->start_encryption_count());
  EXPECT_EQ(1, pairing_failed_count());
}

// Test that LTK is generated and passed up to SecurityManager when both sides
// request bonding
TEST_F(ResponderPairingTest, BothSidesRequestBondingLTKCreated) {
  UInt128 stk;
  SetUpSecurityManager(IOCapability::kDisplayOnly);
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0u,                   // remote keys
                      KeyDistGen::kEncKey,  // local keys
                      kMaxEncryptionKeySize,
                      BondableMode::Bondable);

  // The link should have been assigned the LTK.
  EXPECT_TRUE(pairing_data().local_ltk.has_value());
}

// Test that LTK is not passed up to SecurityManager when local side requests
// non-bondable mode and peer requests bondable mode.
TEST_F(ResponderPairingTest, LocalRequestsNonBondableNoLTKCreated) {
  UInt128 stk;
  SetUpSecurityManager(IOCapability::kDisplayOnly, BondableMode::NonBondable);
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0u,                   // remote keys
                      KeyDistGen::kEncKey,  // local keys
                      kMaxEncryptionKeySize,
                      BondableMode::Bondable);

  // The link should not have been assigned the LTK.
  EXPECT_FALSE(pairing_data().local_ltk.has_value() ||
               pairing_data().peer_ltk.has_value());
}

// Test that LTK is not passed up to SecurityManager when local side requests
// bondable mode and peer requests non-bondable mode.
TEST_F(ResponderPairingTest, PeerRequestsNonBondableNoLTKCreated) {
  UInt128 stk;
  SetUpSecurityManager(IOCapability::kDisplayOnly, BondableMode::Bondable);
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0u,  // remote keys
                      0u,  // local keys
                      kMaxEncryptionKeySize,
                      BondableMode::NonBondable);

  // The link should not have been assigned the LTK.
  EXPECT_FALSE(pairing_data().local_ltk.has_value() ||
               pairing_data().peer_ltk.has_value());
}

// Test that LTK is not generated and passed up to SecurityManager when both
// sides request non-bondable mode.
TEST_F(ResponderPairingTest, BothSidesRequestNonBondableNoLTKCreated) {
  UInt128 stk;
  SetUpSecurityManager(IOCapability::kDisplayOnly, BondableMode::NonBondable);
  FastForwardToPhase3(&stk,
                      /*secure_connections=*/false,
                      SecurityLevel::kEncrypted,
                      0u,  // remote keys
                      0u,  // local keys
                      kMaxEncryptionKeySize,
                      BondableMode::NonBondable);

  // The link should not have been assigned the LTK.
  EXPECT_FALSE(pairing_data().local_ltk.has_value() ||
               pairing_data().peer_ltk.has_value());
}

TEST_F(ResponderPairingTest, PairingRequestStartsPairingTimer) {
  ReceivePairingRequest();
  RunFor(kPairingTimeout);
  EXPECT_TRUE(fake_chan()->link_error());
  // Pairing should fail, but no callbacks should be notified because the
  // pairing was initiated remotely, not through UpgradeSecurity locally
  ASSERT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(HostError::kTimedOut), pairing_complete_status());
  EXPECT_EQ(0, security_callback_count());
}

TEST_F(ResponderPairingTest,
       RejectUnauthenticatedPairingInSecureConnectionsOnlyMode) {
  SetUpSecurityManager(IOCapability::kKeyboardDisplay);
  pairing()->set_security_mode(gap::LESecurityMode::SecureConnectionsOnly);
  // In SC Only mode, SM should translate this "encrypted" request into a MITM
  // requirement.
  UpgradeSecurity(SecurityLevel::kEncrypted);
  RunUntilIdle();
  EXPECT_EQ(1, security_request_count());
  EXPECT_EQ(AuthReq::kBondingFlag | AuthReq::kMITM | AuthReq::kSC,
            security_request_payload());
  // The peer has NoInputNoOutput IOCapabilities, thus cannot perform
  // authenticated pairing.
  ReceivePairingRequest(IOCapability::kNoInputNoOutput,
                        AuthReq::kBondingFlag | AuthReq::kSC);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, security_callback_count());
  EXPECT_EQ(ToResult(ErrorCode::kAuthenticationRequirements),
            security_status());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(security_status(), pairing_complete_status());
}

TEST_F(ResponderPairingTest,
       RejectInsufficientKeySizeRequestInSecureConnectionsOnlyMode) {
  SetUpSecurityManager(IOCapability::kKeyboardDisplay);
  pairing()->set_security_mode(gap::LESecurityMode::SecureConnectionsOnly);
  // The peer encryption key size is not kMaxEncryptionKeySize, thus does not
  // meet the Secure Connections Only requirements.
  ReceivePairingRequest(IOCapability::kDisplayYesNo,
                        AuthReq::kBondingFlag | AuthReq::kSC,
                        kMaxEncryptionKeySize - 1);
  RunUntilIdle();

  EXPECT_EQ(1, pairing_failed_count());
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(ToResult(ErrorCode::kEncryptionKeySize), pairing_complete_status());
}

// Tests that Secure Connections works as responder
TEST_F(ResponderPairingTest, SecureConnectionsWorks) {
  // Must have DisplayYesNo IOC to generate Authenticated security per
  // kExpectedSecurity
  SetUpSecurityManager(IOCapability::kDisplayYesNo);
  UInt128 ltk_bytes;
  const SecurityProperties kExpectedSecurity(SecurityLevel::kAuthenticated,
                                             kMaxEncryptionKeySize,
                                             /*secure_connections=*/true);
  FastForwardToPhase3(
      &ltk_bytes, /*secure_connections=*/true, kExpectedSecurity.level());

  const LTK kExpectedLtk(kExpectedSecurity, hci_spec::LinkKey(ltk_bytes, 0, 0));
  ASSERT_TRUE(fake_link()->ltk());
  EXPECT_EQ(kExpectedLtk.key(), fake_link()->ltk());

  // Pairing should succeed with the LTK as the SC pairing is bondable, even
  // though no keys need to be distributed in Phase 3.
  EXPECT_EQ(1, pairing_data_callback_count());
  EXPECT_TRUE(local_ltk().has_value());
  EXPECT_EQ(kExpectedLtk, local_ltk());
  EXPECT_EQ(local_ltk(), peer_ltk());
  EXPECT_FALSE(irk());
  EXPECT_FALSE(identity());
  EXPECT_FALSE(csrk());

  // Should have been called at least once to determine local identity
  // availability.
  EXPECT_NE(0, local_id_info_callback_count());
  // Pairing should complete successfully
  EXPECT_EQ(1, pairing_complete_count());
  EXPECT_EQ(0, pairing_failed_count());
  EXPECT_EQ(fit::ok(), pairing_complete_status());

  // No callbacks are notified as the peer started this pairing, not a call to
  // UpgradeSecurity.
  EXPECT_EQ(0, security_callback_count());
  EXPECT_EQ(0, id_info_count());
  EXPECT_EQ(0, id_addr_info_count());

  EXPECT_EQ(kExpectedSecurity, pairing()->security());

  // The security properties should have been updated to match the LTK.
  EXPECT_EQ(1, new_sec_props_count());
  EXPECT_EQ(pairing()->security(), new_sec_props());

  ASSERT_TRUE(fake_link()->ltk());
}
}  // namespace
}  // namespace bt::sm
// inclusive-language: enable
