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

#include "phase_2_secure_connections.h"

#include <cstdint>
#include <memory>

#include <gtest/gtest.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/device_address.h"
#include "src/connectivity/bluetooth/core/bt-host/common/random.h"
#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/common/uint128.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel_test.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/ecdh_key.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/fake_phase_listener.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/util.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace bt::sm {
namespace {
using ConfirmCallback = FakeListener::ConfirmCallback;
using PasskeyResponseCallback = FakeListener::PasskeyResponseCallback;

// clang-format off
const PairingFeatures kDefaultFeatures(
    true,                                     // initiator
    true,                                     // secure_connections
    true,                                     // will_bond
    std::optional<CrossTransportKeyAlgo>{std::nullopt},
    PairingMethod::kJustWorks,
    kMaxEncryptionKeySize,                    // encryption_key_size
    KeyDistGen::kIdKey,                       // local_key_distribution
    KeyDistGen::kIdKey | KeyDistGen::kEncKey  // remote_key_distribution
);

const PairingRequestParams kDefaultPreq{
    .io_capability = IOCapability::kNoInputNoOutput,
    .oob_data_flag = OOBDataFlag::kNotPresent,
    .auth_req = AuthReq::kSC | AuthReq::kBondingFlag,
    .max_encryption_key_size = kMaxEncryptionKeySize,
    .initiator_key_dist_gen = KeyDistGen::kIdKey,
    .responder_key_dist_gen = KeyDistGen::kIdKey | KeyDistGen::kEncKey
};

const PairingResponseParams kDefaultPres{
    .io_capability = IOCapability::kNoInputNoOutput,
    .oob_data_flag = OOBDataFlag::kNotPresent,
    .auth_req = AuthReq::kSC | AuthReq::kBondingFlag,
    .max_encryption_key_size = kMaxEncryptionKeySize,
    .initiator_key_dist_gen = KeyDistGen::kIdKey,
    .responder_key_dist_gen = KeyDistGen::kIdKey | KeyDistGen::kEncKey
};
// clang-format on
const DeviceAddress kAddr1(DeviceAddress::Type::kLEPublic, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
const DeviceAddress kAddr2(DeviceAddress::Type::kLEPublic, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02});
const LocalEcdhKey kDefaultEcdhKey = LocalEcdhKey::Create().value();

using util::PacketSize;

class SMP_Phase2SecureConnectionsTest : public l2cap::testing::FakeChannelTest {
 public:
  SMP_Phase2SecureConnectionsTest() = default;
  ~SMP_Phase2SecureConnectionsTest() override = default;

 protected:
  void SetUp() override { NewPhase2SecureConnections(); }

  void TearDown() override { phase_2_sc_ = nullptr; }

  void NewPhase2SecureConnections(Role local_role = Role::kInitiator,
                                  PairingMethod method = PairingMethod::kJustWorks,
                                  uint16_t mtu = kLeSecureConnectionsMtu) {
    features_.initiator = (local_role == Role::kInitiator);
    features_.method = method;
    ChannelOptions options(l2cap::kLESMPChannelId, mtu);
    options.link_type = hci::Connection::LinkType::kLE;
    sm_chan_ = std::make_unique<PairingChannel>(CreateFakeChannel(options));

    listener_ = std::make_unique<FakeListener>();
    phase_2_sc_ = std::make_unique<Phase2SecureConnections>(
        sm_chan_->GetWeakPtr(), listener_->as_weak_ptr(), local_role, features_, preq_, pres_,
        initiator_addr_, responder_addr_, [this](const UInt128& ltk) {
          phase_2_complete_count_++;
          ltk_ = ltk;
        });
  }

  template <typename T>
  void ReceiveCmd(Code cmd_code, const T& value) {
    fake_chan()->Receive(MakeCmd(cmd_code, value));
  }

  template <typename T>
  StaticByteBuffer<PacketSize<T>()> MakeCmd(Code cmd_code, const T& value) {
    StaticByteBuffer<PacketSize<T>()> buffer;
    PacketWriter writer(cmd_code, &buffer);
    *writer.mutable_payload<T>() = value;
    return buffer;
  }

  static std::pair<Code, UInt128> ExtractCodeAnd128BitCmd(ByteBufferPtr sdu) {
    ZX_ASSERT_MSG(sdu, "Tried to ExtractCodeAnd128BitCmd from nullptr in test");
    auto maybe_reader = ValidPacketReader::ParseSdu(sdu);
    ZX_ASSERT_MSG(maybe_reader.is_ok(), "Tried to ExtractCodeAnd128BitCmd from invalid SMP packet");
    return {maybe_reader.value().code(), maybe_reader.value().payload<UInt128>()};
  }

  std::optional<PairingConfirmValue> FastForwardPublicKeyExchange() {
    std::optional<PairingConfirmValue> responder_jw_nc_confirm = std::nullopt;
    fake_chan()->SetSendCallback(
        [&responder_jw_nc_confirm, this](ByteBufferPtr sdu) {
          auto reader = ValidPacketReader::ParseSdu(sdu).value();
          if (reader.code() == kPairingPublicKey) {
            local_key_ = EcdhKey::ParseFromPublicKey(reader.payload<PairingPublicKeyParams>());
          } else if (reader.code() == kPairingConfirm) {
            // Confirm must come after ECDH Pub Key if it comes now
            ASSERT_TRUE(local_key_.has_value());
            responder_jw_nc_confirm = reader.payload<PairingConfirmValue>();
          } else {
            ADD_FAILURE() << "unexpected packet code " << reader.code();
          }
        },
        dispatcher());

    if (phase_2_sc_->role() == Role::kInitiator) {
      phase_2_sc_->Start();
      RunLoopUntilIdle();
      ZX_ASSERT_MSG(local_key_.has_value(), "initiator did not send ecdh key upon starting");
      ReceiveCmd(kPairingPublicKey, peer_key_.GetSerializedPublicKey());
      RunLoopUntilIdle();
    } else {
      phase_2_sc_->Start();
      ReceiveCmd(kPairingPublicKey, peer_key_.GetSerializedPublicKey());
      RunLoopUntilIdle();
      ZX_ASSERT_MSG(local_key_.has_value(), "responder did not send ecdh key upon peer key");
      if (features_.method == PairingMethod::kJustWorks ||
          features_.method == PairingMethod::kNumericComparison) {
        ZX_ASSERT(responder_jw_nc_confirm.has_value());
        return responder_jw_nc_confirm;
      }
    }
    // We should only send confirm value immediately after ECDH key as responder in Numeric
    // Comparison/Just Works pairing, in which case we would've already returned.
    ZX_ASSERT(!responder_jw_nc_confirm.has_value());
    return responder_jw_nc_confirm;
  }

  UInt128 GenerateConfirmValue(const UInt128& random, bool gen_initiator_confirm,
                               uint8_t r = 0) const {
    ZX_ASSERT_MSG(local_key_.has_value(), "cannot compute confirm, missing key!");
    UInt256 pka = local_key_->GetPublicKeyX(), pkb = peer_key_.GetPublicKeyX();
    if (phase_2_sc_->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();
  }

  struct MatchingPair {
    UInt128 confirm;
    UInt128 random;
  };
  MatchingPair GenerateMatchingConfirmAndRandom(uint8_t r = 0) const {
    MatchingPair pair{.random = {1, 2, 3, 4}};
    pair.confirm = GenerateConfirmValue(pair.random, phase_2_sc_->role() == Role::kResponder, r);
    return pair;
  }

  struct LtkAndChecks {
    UInt128 ltk;
    UInt128 dhkey_check_a;
    UInt128 dhkey_check_b;
  };
  LtkAndChecks GenerateLtkAndChecks(const UInt128& initiator_rand, const UInt128& responder_rand,
                                    uint64_t r = 0) {
    LtkAndChecks vals;
    util::F5Results f5 = *util::F5(peer_key_.CalculateDhKey(*local_key_), initiator_rand,
                                   responder_rand, initiator_addr_, responder_addr_);
    vals.ltk = f5.ltk;

    UInt128 r_array{0};
    // Copy little-endian uint64 r to the UInt128 array needed for Stage 2
    std::memcpy(r_array.data(), &r, sizeof(uint64_t));
    vals.dhkey_check_a =
        *util::F6(f5.mac_key, initiator_rand, responder_rand, r_array, preq_.auth_req,
                  preq_.oob_data_flag, preq_.io_capability, initiator_addr_, responder_addr_);
    vals.dhkey_check_b =
        *util::F6(f5.mac_key, responder_rand, initiator_rand, r_array, pres_.auth_req,
                  pres_.oob_data_flag, pres_.io_capability, responder_addr_, initiator_addr_);
    return vals;
  }

  LtkAndChecks FastForwardToDhKeyCheck() {
    ZX_ASSERT_MSG(features_.method == PairingMethod::kJustWorks,
                  "Fast forward to DHKey check only implemented for JustWorks method");
    return phase_2_sc_->role() == Role::kInitiator ? FastForwardToDhKeyCheckInitiatorJustWorks()
                                                   : FastForwardToDhKeyCheckResponderJustWorks();
  }

  void DestroyPhase2() { phase_2_sc_.reset(nullptr); }
  Phase2SecureConnections* phase_2_sc() { return phase_2_sc_.get(); }
  FakeListener* listener() { return listener_.get(); }
  const LocalEcdhKey& peer_key() { return peer_key_; }
  const std::optional<EcdhKey>& local_key() { return local_key_; }
  std::optional<EcdhKey>& mut_local_key() { return local_key_; }
  int phase_2_complete_count() const { return phase_2_complete_count_; }
  UInt128 ltk() const { return ltk_; }

 private:
  LtkAndChecks FastForwardToDhKeyCheckInitiatorJustWorks() {
    FastForwardPublicKeyExchange();
    Code sent_code = kPairingFailed;
    PairingRandomValue initiator_rand;
    fake_chan()->SetSendCallback(
        [&](ByteBufferPtr sdu) {
          std::tie(sent_code, initiator_rand) = ExtractCodeAnd128BitCmd(std::move(sdu));
        },
        dispatcher());
    MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
    ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
    RunLoopUntilIdle();
    ZX_ASSERT_MSG(kPairingRandom == sent_code, "did not send pairing random when expected!");

    ReceiveCmd(kPairingRandom, stage1_vals.random);
    RunLoopUntilIdle();
    return GenerateLtkAndChecks(initiator_rand, stage1_vals.random);
  }

  LtkAndChecks FastForwardToDhKeyCheckResponderJustWorks() {
    UInt128 rsp_confirm = *FastForwardPublicKeyExchange();
    Code sent_code = kPairingFailed;
    UInt128 rsp_rand;
    fake_chan()->SetSendCallback(
        [&](ByteBufferPtr sdu) {
          std::tie(sent_code, rsp_rand) = ExtractCodeAnd128BitCmd(std::move(sdu));
        },
        dispatcher());
    PairingRandomValue initiator_rand{1};
    ReceiveCmd(kPairingRandom, initiator_rand);
    RunLoopUntilIdle();

    ZX_ASSERT_MSG(kPairingRandom == sent_code, "did not send pairing random when expected!");
    ZX_ASSERT_MSG(GenerateConfirmValue(rsp_rand, false /*gen_init_confirm*/) == rsp_confirm,
                  "send invalid confirm value as JustWorks responder");
    return GenerateLtkAndChecks(initiator_rand, rsp_rand);
  }

  std::unique_ptr<FakeListener> listener_;
  std::unique_ptr<PairingChannel> sm_chan_;
  std::unique_ptr<Phase2SecureConnections> phase_2_sc_;
  // Key of the internal bt-host SMP stack
  std::optional<EcdhKey> local_key_;
  // Key of the unit test peer we're mocking
  const LocalEcdhKey& peer_key_ = kDefaultEcdhKey;

  PairingFeatures features_ = kDefaultFeatures;
  PairingRequestParams preq_ = kDefaultPreq;
  PairingResponseParams pres_ = kDefaultPres;
  DeviceAddress initiator_addr_ = kAddr1;
  DeviceAddress responder_addr_ = kAddr2;
  int phase_2_complete_count_ = 0;
  UInt128 ltk_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(SMP_Phase2SecureConnectionsTest);
};

using SMP_Phase2SecureConnectionsDeathTest = SMP_Phase2SecureConnectionsTest;

TEST_F(SMP_Phase2SecureConnectionsDeathTest, MtuTooSmallDies) {
  ASSERT_DEATH_IF_SUPPORTED(NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kJustWorks,
                                                       kNoSecureConnectionsMtu),
                            ".*SecureConnections.*");
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceivePairingFailed) {
  phase_2_sc()->Start();
  fake_chan()->Receive(
      StaticByteBuffer<PacketSize<ErrorCode>()>{kPairingFailed, ErrorCode::kPairingNotSupported});
  RunLoopUntilIdle();

  ASSERT_TRUE(listener()->last_error().is_protocol_error());
  EXPECT_EQ(ErrorCode::kPairingNotSupported, listener()->last_error().protocol_error());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveMalformedPacket) {
  phase_2_sc()->Start();
  // PairingPublicKeyParams is expected to have both an X and Y value, not just an X.
  const UInt256 kX = peer_key().GetPublicKeyX();
  const auto kPairingPublicKeyCmd = MakeCmd(kPairingPublicKey, kX);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kInvalidParameters};

  EXPECT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveUnexpectedPacket) {
  phase_2_sc()->Start();
  // Pairing Responses should only be sent during Phase 1 of pairing.
  const auto kPairingResponseCmd = MakeCmd(kPairingResponse, PairingResponseParams());
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};

  EXPECT_TRUE(ReceiveAndExpect(kPairingResponseCmd, kExpectedFailure));
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorPubKeyOutOfOrder) {
  NewPhase2SecureConnections(Role::kInitiator);

  const auto kPairingPublicKeyCmd = MakeCmd(kPairingPublicKey, peer_key().GetSerializedPublicKey());
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, RejectsPublicKeyOffCurve) {
  phase_2_sc()->Start();
  const auto kPairingPublicKeyCmd =
      MakeCmd(kPairingPublicKey, PairingPublicKeyParams{.x = {0x01}, .y = {0x02}});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kInvalidParameters};
  ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceivePeerPublicKeyTwice) {
  phase_2_sc()->Start();
  const auto kPairingPublicKeyCmd = MakeCmd(kPairingPublicKey, peer_key().GetSerializedPublicKey());
  fake_chan()->Receive(kPairingPublicKeyCmd);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingPublicKeyCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveConfirmValueBeforeStage1Fails) {
  phase_2_sc()->Start();
  const auto kPairingConfirmCmd = MakeCmd(kPairingConfirm, PairingConfirmValue{1});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingConfirmCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveRandomValueBeforeStage1Fails) {
  phase_2_sc()->Start();
  const auto kPairingRandomCmd = MakeCmd(kPairingRandom, PairingRandomValue{1});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingRandomCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveDhKeyCheckValueBeforeStage1Fails) {
  phase_2_sc()->Start();
  const auto kPairingDHKeyCheckCmd = MakeCmd(kPairingDHKeyCheck, PairingDHKeyCheckValueE{1});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveConfirmValueAfterStage1Fails) {
  FastForwardToDhKeyCheck();
  const auto kPairingConfirmCmd = MakeCmd(kPairingConfirm, PairingConfirmValue{1});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingConfirmCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ReceiveRandomValueAfterStage1Fails) {
  FastForwardToDhKeyCheck();
  const auto kPairingRandomCmd = MakeCmd(kPairingRandom, PairingRandomValue{1});
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingRandomCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorReceiveDhKeyCheckWhileWaitingForConfirmFails) {
  NewPhase2SecureConnections(Role::kInitiator);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
  ASSERT_TRUE(confirm_cb);
  // Receiving the peer DHKey check before user confirmation should fail as initiator.
  const auto kPairingDHKeyCheckCmd =
      MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kUnspecifiedReason};
  ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, Stage1JustWorksErrorPropagates) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kJustWorks);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  FastForwardPublicKeyExchange();

  Code sent_code = kPairingFailed;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, std::ignore) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
  ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
  RunLoopUntilIdle();
  ASSERT_EQ(kPairingRandom, sent_code);
  UInt128 mismatched_random = stage1_vals.random;
  mismatched_random[0] += 1;
  const auto kMismatchedPairingRandomCmd = MakeCmd(kPairingRandom, mismatched_random);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kConfirmValueFailed};
  ASSERT_TRUE(ReceiveAndExpect(kMismatchedPairingRandomCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, Stage1PasskeyErrorPropagates) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kPasskeyEntryDisplay);
  uint32_t passkey;
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_display_delegate(
      [&](uint32_t disp_passkey, Delegate::DisplayMethod method, ConfirmCallback cb) {
        ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);
        confirm_cb = std::move(cb);
        passkey = disp_passkey;
      });
  FastForwardPublicKeyExchange();

  ASSERT_TRUE(confirm_cb);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kPasskeyEntryFailed};
  bool failure_sent = false;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        ASSERT_TRUE(ContainersEqual(kExpectedFailure, *sdu));
        failure_sent = true;
      },
      dispatcher());
  confirm_cb(false);
  RunLoopUntilIdle();
  ASSERT_EQ(1, listener()->pairing_error_count());
  ASSERT_TRUE(failure_sent);
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorReceiveWrongDhKeyCheckFails) {
  NewPhase2SecureConnections(Role::kInitiator);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
  ASSERT_TRUE(confirm_cb);
  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  confirm_cb(true);
  RunLoopUntilIdle();
  ASSERT_EQ(kPairingDHKeyCheck, sent_code);
  // As initiator, we expect the dhkey_check_b value, not the a.
  const auto kPairingDHKeyCheckCmd =
      MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kDHKeyCheckFailed};
  ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmd, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
  ASSERT_EQ(0, phase_2_complete_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorFlowSuccessJustWorks) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kJustWorks);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  FastForwardPublicKeyExchange();

  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
  ReceiveCmd<PairingConfirmValue>(kPairingConfirm, stage1_vals.confirm);
  RunLoopUntilIdle();
  ASSERT_EQ(kPairingRandom, sent_code);
  UInt128 local_rand = sent_payload;
  ASSERT_FALSE(confirm_cb);
  ReceiveCmd(kPairingRandom, stage1_vals.random);
  RunLoopUntilIdle();
  ASSERT_TRUE(confirm_cb);

  LtkAndChecks expected_stage2_vals = GenerateLtkAndChecks(local_rand, stage1_vals.random);
  confirm_cb(true);
  RunLoopUntilIdle();
  // After receiving user confirmation, we should send (the correct) DHKey Check Ea
  ASSERT_EQ(kPairingDHKeyCheck, sent_code);
  ASSERT_EQ(expected_stage2_vals.dhkey_check_a, sent_payload);
  ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
  RunLoopUntilIdle();
  ASSERT_EQ(1, phase_2_complete_count());
  // We should generate the same LTK on "both sides"
  ASSERT_EQ(expected_stage2_vals.ltk, ltk());
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorFlowSuccessNumericComparison) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kNumericComparison);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_display_delegate(
      [&](uint32_t, Delegate::DisplayMethod method, ConfirmCallback cb) {
        ASSERT_EQ(Delegate::DisplayMethod::kComparison, method);
        confirm_cb = std::move(cb);
      });
  FastForwardPublicKeyExchange();

  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  MatchingPair stage1_vals = GenerateMatchingConfirmAndRandom();
  ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
  RunLoopUntilIdle();
  EXPECT_EQ(kPairingRandom, sent_code);
  UInt128 initiator_random = sent_payload;
  ASSERT_FALSE(confirm_cb);

  ReceiveCmd(kPairingRandom, stage1_vals.random);
  RunLoopUntilIdle();
  ASSERT_TRUE(confirm_cb);
  confirm_cb(true);
  RunLoopUntilIdle();
  LtkAndChecks vals = GenerateLtkAndChecks(initiator_random, stage1_vals.random);
  EXPECT_EQ(kPairingDHKeyCheck, sent_code);
  EXPECT_EQ(vals.dhkey_check_a, sent_payload);
  ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
  RunLoopUntilIdle();
  ASSERT_EQ(vals.ltk, ltk());
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorFlowSuccessPasskeyEntryDisplay) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kPasskeyEntryDisplay);
  uint32_t passkey;
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_display_delegate(
      [&](uint32_t disp_passkey, Delegate::DisplayMethod method, ConfirmCallback cb) {
        ASSERT_EQ(Delegate::DisplayMethod::kPeerEntry, method);
        confirm_cb = std::move(cb);
        passkey = disp_passkey;
      });
  FastForwardPublicKeyExchange();
  ASSERT_TRUE(confirm_cb);
  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  confirm_cb(true);
  MatchingPair stage1_vals;
  UInt128 last_sent_rand;
  for (size_t i = 0; i < 20; ++i) {
    const uint8_t r = (passkey & (1 << i)) ? 0x81 : 0x80;
    stage1_vals = GenerateMatchingConfirmAndRandom(r);
    RunLoopUntilIdle();

    ASSERT_EQ(kPairingConfirm, sent_code);
    PairingConfirmValue init_confirm = sent_payload;
    ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
    RunLoopUntilIdle();

    ASSERT_EQ(kPairingRandom, sent_code);
    last_sent_rand = sent_payload;
    EXPECT_EQ(GenerateConfirmValue(sent_payload, true /*gen_initiator_confirm*/, r), init_confirm);
    ReceiveCmd(kPairingRandom, stage1_vals.random);
  }
  LtkAndChecks vals = GenerateLtkAndChecks(last_sent_rand, stage1_vals.random, uint64_t{passkey});
  RunLoopUntilIdle();
  EXPECT_EQ(kPairingDHKeyCheck, sent_code);
  EXPECT_EQ(vals.dhkey_check_a, sent_payload);
  ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
  RunLoopUntilIdle();
  ASSERT_EQ(vals.ltk, ltk());
}

TEST_F(SMP_Phase2SecureConnectionsTest, InitiatorFlowSuccessPasskeyEntryInput) {
  NewPhase2SecureConnections(Role::kInitiator, PairingMethod::kPasskeyEntryInput);
  PasskeyResponseCallback passkey_cb = nullptr;
  listener()->set_request_passkey_delegate(
      [&](PasskeyResponseCallback cb) { passkey_cb = std::move(cb); });
  FastForwardPublicKeyExchange();
  ASSERT_TRUE(passkey_cb);
  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  const int64_t passkey = 123456;
  passkey_cb(passkey);
  MatchingPair stage1_vals;
  UInt128 last_sent_rand;
  for (size_t i = 0; i < 20; ++i) {
    const uint8_t r = (passkey & (1 << i)) ? 0x81 : 0x80;
    stage1_vals = GenerateMatchingConfirmAndRandom(r);
    RunLoopUntilIdle();

    ASSERT_EQ(kPairingConfirm, sent_code);
    PairingConfirmValue init_confirm = sent_payload;
    ReceiveCmd(kPairingConfirm, stage1_vals.confirm);
    RunLoopUntilIdle();

    ASSERT_EQ(kPairingRandom, sent_code);
    last_sent_rand = sent_payload;
    EXPECT_EQ(GenerateConfirmValue(sent_payload, true /*gen_initiator_confirm*/, r), init_confirm);
    ReceiveCmd(kPairingRandom, stage1_vals.random);
  }
  LtkAndChecks vals = GenerateLtkAndChecks(last_sent_rand, stage1_vals.random, uint64_t{passkey});
  RunLoopUntilIdle();
  EXPECT_EQ(kPairingDHKeyCheck, sent_code);
  EXPECT_EQ(vals.dhkey_check_a, sent_payload);
  ReceiveCmd(kPairingDHKeyCheck, vals.dhkey_check_b);
  RunLoopUntilIdle();
  ASSERT_EQ(vals.ltk, ltk());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ResponderReceiveWrongDhKeyCheckFails) {
  NewPhase2SecureConnections(Role::kResponder);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();
  ASSERT_TRUE(confirm_cb);
  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  confirm_cb(true);
  RunLoopUntilIdle();
  // As responder, we expect the dhkey_check_a value, not the b.
  const auto kPairingDHKeyCheckCmdWithBValue =
      MakeCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_b);
  const StaticByteBuffer<PacketSize<ErrorCode>()> kExpectedFailure{kPairingFailed,
                                                                   ErrorCode::kDHKeyCheckFailed};
  ASSERT_TRUE(ReceiveAndExpect(kPairingDHKeyCheckCmdWithBValue, kExpectedFailure));
  ASSERT_EQ(1, listener()->pairing_error_count());
  ASSERT_EQ(0, phase_2_complete_count());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ResponderFlowSuccessJustWorks) {
  NewPhase2SecureConnections(Role::kResponder, PairingMethod::kJustWorks);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  PairingConfirmValue responder_confirm = *FastForwardPublicKeyExchange();

  Code sent_code = kPairingFailed;
  UInt128 sent_payload;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_payload) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  ASSERT_FALSE(confirm_cb);
  const PairingRandomValue kInitiatorRand{1};
  ReceiveCmd(kPairingRandom, kInitiatorRand);
  RunLoopUntilIdle();

  ASSERT_EQ(kPairingRandom, sent_code);
  UInt128 responder_rand = sent_payload;
  ASSERT_EQ(GenerateConfirmValue(responder_rand, false /*gen_init_confirm*/), responder_confirm);
  ASSERT_TRUE(confirm_cb);
  LtkAndChecks expected_stage2_vals = GenerateLtkAndChecks(kInitiatorRand, responder_rand);
  // After receiving user confirmation & the peer dhkey check, we should send the DHKey Check Eb.
  confirm_cb(true);
  ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
  RunLoopUntilIdle();
  ASSERT_EQ(kPairingDHKeyCheck, sent_code);
  ASSERT_EQ(expected_stage2_vals.dhkey_check_b, sent_payload);
  ASSERT_EQ(1, phase_2_complete_count());
  // We should generate the same LTK on "both sides"
  ASSERT_EQ(expected_stage2_vals.ltk, ltk());
}

TEST_F(SMP_Phase2SecureConnectionsTest, ResponderReceiveDhKeyCheckWhileWaitingForConfirmSuccess) {
  NewPhase2SecureConnections(Role::kResponder, PairingMethod::kJustWorks);
  ConfirmCallback confirm_cb = nullptr;
  listener()->set_confirm_delegate([&](ConfirmCallback cb) { confirm_cb = std::move(cb); });
  LtkAndChecks expected_stage2_vals = FastForwardToDhKeyCheck();

  Code sent_code;
  PairingDHKeyCheckValueE sent_dhkey_check;
  fake_chan()->SetSendCallback(
      [&](ByteBufferPtr sdu) {
        std::tie(sent_code, sent_dhkey_check) = ExtractCodeAnd128BitCmd(std::move(sdu));
      },
      dispatcher());
  ASSERT_TRUE(confirm_cb);
  // Receiving the peer DHKey check before user confirmation should work as responder.
  ReceiveCmd(kPairingDHKeyCheck, expected_stage2_vals.dhkey_check_a);
  RunLoopUntilIdle();
  confirm_cb(true);
  RunLoopUntilIdle();

  ASSERT_EQ(kPairingDHKeyCheck, sent_code);
  ASSERT_EQ(expected_stage2_vals.dhkey_check_b, sent_dhkey_check);
  ASSERT_EQ(1, phase_2_complete_count());
}

}  // namespace
}  // namespace bt::sm
