Skip to content

Commit

Permalink
pw_bluetooth_sapphire: Register PairingToken during LE pairing
Browse files Browse the repository at this point in the history
Bug: 388607971
Change-Id: Ic1c2c74f6d68dd4641b9c327d18cfadd4c08c7f2
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/259454
Reviewed-by: Jason Graffius <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
Pigweed-Auto-Submit: Ben Lawson <[email protected]>
Docs-Not-Needed: Ben Lawson <[email protected]>
Lint: Lint 🤖 <[email protected]>
  • Loading branch information
BenjaminLawson authored and CQ Bot Account committed Jan 10, 2025
1 parent 3c65121 commit dfc7184
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
14 changes: 14 additions & 0 deletions pw_bluetooth_sapphire/host/sm/security_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace bt::sm {

namespace {

using PairingToken = gap::Peer::PairingToken;

SecurityProperties FeaturesToProperties(const PairingFeatures& features) {
return SecurityProperties(features.method == PairingMethod::kJustWorks
? SecurityLevel::kEncrypted
Expand Down Expand Up @@ -231,6 +233,9 @@ class SecurityManagerImpl final : public SecurityManager,

SmartTask timeout_task_{pw_dispatcher_};

// Set to a PairingToken when the current phase is not monostate (always null
// in monostate).
std::optional<PairingToken> pairing_token_;
bt::gap::Peer::WeakPtr peer_;

// The presence of a particular phase in this variant indicates that a
Expand Down Expand Up @@ -415,6 +420,10 @@ void SecurityManagerImpl::OnPairingRequest(
required_level = SecurityLevel::kSecureAuthenticated;
}

if (!pairing_token_) {
pairing_token_ = peer_->MutLe().RegisterPairing();
}

current_phase_ = Phase1::CreatePhase1Responder(
sm_chan_->GetWeakPtr(),
weak_listener_.GetWeakPtr(),
Expand Down Expand Up @@ -452,6 +461,10 @@ fit::result<ErrorCode> SecurityManagerImpl::RequestSecurityUpgrade(
return fit::error(ErrorCode::kAuthenticationRequirements);
}

if (!pairing_token_) {
pairing_token_ = peer_->MutLe().RegisterPairing();
}

if (role_ == Role::kInitiator) {
current_phase_ = Phase1::CreatePhase1Initiator(
sm_chan_->GetWeakPtr(),
Expand Down Expand Up @@ -751,6 +764,7 @@ void SecurityManagerImpl::ResetState() {
StopTimer();
features_.reset();
sm_chan_->SetChannelHandler(weak_handler_.GetWeakPtr());
pairing_token_.reset();
current_phase_ = std::monostate{};
}

Expand Down
20 changes: 20 additions & 0 deletions pw_bluetooth_sapphire/host/sm/security_manager_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ class SecurityManagerTest : public l2cap::testing::FakeChannelTest,
const ByteBuffer& local_pairing_cmd() const { return local_pairing_cmd_; }
const ByteBuffer& peer_pairing_cmd() const { return peer_pairing_cmd_; }

gap::Peer& peer() { return peer_.value(); }

private:
void Receive128BitCmd(Code cmd_code, const UInt128& value) {
StaticByteBuffer<sizeof(Header) + sizeof(UInt128)> buffer;
Expand Down Expand Up @@ -696,6 +698,7 @@ class InitiatorPairingTest : public SecurityManagerTest {
uint8_t max_key_size = kMaxEncryptionKeySize,
BondableMode bondable_mode = BondableMode::Bondable) {
UpgradeSecurity(level);
EXPECT_TRUE(peer().MutLe().is_pairing());

PairingRequestParams pairing_params;
pairing_params.io_capability = IOCapability::kNoInputNoOutput;
Expand Down Expand Up @@ -725,6 +728,7 @@ class InitiatorPairingTest : public SecurityManagerTest {
EXPECT_EQ(1, pairing_random_count());
EXPECT_EQ(0, pairing_failed_count());
EXPECT_EQ(0, security_callback_count());
EXPECT_TRUE(peer().MutLe().is_pairing());

PW_DCHECK(out_stk);

Expand All @@ -741,6 +745,7 @@ class InitiatorPairingTest : public SecurityManagerTest {
KeyDistGenField local_keys = 0,
uint8_t max_key_size = kMaxEncryptionKeySize,
BondableMode bondable_mode = BondableMode::Bondable) {
EXPECT_FALSE(peer().MutLe().is_pairing());
if (secure_connections) {
FastForwardToScLtk(
out_encryption_key, level, remote_keys, local_keys, bondable_mode);
Expand Down Expand Up @@ -769,6 +774,7 @@ class InitiatorPairingTest : public SecurityManagerTest {
KeyDistGenField local_keys = 0,
BondableMode bondable = BondableMode::Bondable) {
UpgradeSecurity(level);
EXPECT_TRUE(peer().MutLe().is_pairing());
RunUntilIdle();

ASSERT_EQ(1, pairing_request_count());
Expand Down Expand Up @@ -857,6 +863,7 @@ class InitiatorPairingTest : public SecurityManagerTest {
RunUntilIdle();
EXPECT_EQ(0, pairing_failed_count());
EXPECT_EQ(0, security_callback_count());
EXPECT_TRUE(peer().MutLe().is_pairing());

ASSERT_TRUE(out_ltk);
*out_ltk = f5.ltk;
Expand Down Expand Up @@ -932,6 +939,7 @@ class ResponderPairingTest : public SecurityManagerTest {
pairing_params.initiator_key_dist_gen = remote_keys;
pairing_params.responder_key_dist_gen = local_keys;
ReceivePairingFeatures(pairing_params, /*peer_initiator=*/true);
EXPECT_TRUE(peer().MutLe().is_pairing());

// Run the loop until the harness caches the feature exchange PDUs (preq &
// pres) so that we can generate a valid confirm value.
Expand Down Expand Up @@ -1014,6 +1022,7 @@ class ResponderPairingTest : public SecurityManagerTest {
preq.initiator_key_dist_gen = local_keys;
preq.responder_key_dist_gen = peer_keys;
ReceivePairingFeatures(preq, /*peer_initiator=*/true);
EXPECT_TRUE(peer().MutLe().is_pairing());
RunUntilIdle();
ASSERT_EQ(1, pairing_response_count());

Expand Down Expand Up @@ -1090,6 +1099,7 @@ class ResponderPairingTest : public SecurityManagerTest {
ASSERT_EQ(dhkey_check_b, pairing_dhkey_check());
EXPECT_EQ(0, pairing_failed_count());
EXPECT_EQ(0, pairing_complete_count());
EXPECT_TRUE(peer().MutLe().is_pairing());

ASSERT_TRUE(out_ltk);
*out_ltk = f5.ltk;
Expand Down Expand Up @@ -1123,6 +1133,7 @@ TEST_F(InitiatorPairingTest, UpgradeSecurityCurrentLevel) {
// No pairing requests should have been made.
EXPECT_EQ(0, pairing_request_count());
EXPECT_EQ(0, pairing_complete_count());
EXPECT_FALSE(peer().MutLe().is_pairing());

// Pairing should succeed.
EXPECT_EQ(1, security_callback_count());
Expand All @@ -1135,6 +1146,7 @@ TEST_F(InitiatorPairingTest, UpgradeSecurityCurrentLevel) {
// Peer aborts during Phase 1.
TEST_F(InitiatorPairingTest, PairingFailedInPhase1) {
UpgradeSecurity(SecurityLevel::kEncrypted);
EXPECT_TRUE(peer().MutLe().is_pairing());
RunUntilIdle();

// Pairing not complete yet but we should be in Phase 1.
Expand All @@ -1150,11 +1162,13 @@ TEST_F(InitiatorPairingTest, PairingFailedInPhase1) {

EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(security_status(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());
}

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

// Pairing not complete yet but we should be in Phase 1.
Expand All @@ -1170,6 +1184,7 @@ TEST_F(InitiatorPairingTest, PairingAbortedInPhase1) {

EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(security_status(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());
}

// Local resets I/O capabilities while pairing. This should abort any ongoing
Expand All @@ -1192,6 +1207,7 @@ TEST_F(InitiatorPairingTest, SecurityManagerResetDuringPairing) {

EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(security_status(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());

UpgradeSecurity(SecurityLevel::kEncrypted);
RunUntilIdle();
Expand Down Expand Up @@ -1294,6 +1310,7 @@ TEST_F(InitiatorPairingTest,
EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(fit::ok(), security_status());
EXPECT_EQ(security_status(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());

EXPECT_EQ(SecurityLevel::kSecureAuthenticated, sec_props().level());
}
Expand Down Expand Up @@ -3688,6 +3705,7 @@ TEST_F(ResponderPairingTest, LegacyPhase3LocalIdKeyDistributionWithRemoteKeys) {
// 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());
EXPECT_FALSE(peer().MutLe().is_pairing());

// The peer should have sent us its identity information.
ASSERT_TRUE(pairing_data().irk);
Expand Down Expand Up @@ -3879,6 +3897,7 @@ TEST_F(ResponderPairingTest,
security_status());
EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(security_status(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());
}

TEST_F(ResponderPairingTest,
Expand Down Expand Up @@ -3930,6 +3949,7 @@ TEST_F(ResponderPairingTest, SecureConnectionsWorks) {
EXPECT_EQ(1, pairing_complete_count());
EXPECT_EQ(0, pairing_failed_count());
EXPECT_EQ(fit::ok(), pairing_complete_status());
EXPECT_FALSE(peer().MutLe().is_pairing());

// No callbacks are notified as the peer started this pairing, not a call to
// UpgradeSecurity.
Expand Down

0 comments on commit dfc7184

Please sign in to comment.