Skip to content

Commit

Permalink
pw_bluetooth_sapphire: Reland "Integrate LegacyPairingState with ..."
Browse files Browse the repository at this point in the history
Reland "Integrate LegacyPairingState with ..." PairingStateManager"

This is a reland of commit 31a9d97a99e1571ad674961a0647b3de85d9265e

Relanding this with no changes. Originally reverted because there was no
configuration to disable/enable legacy pairing (added in fxr/1102453).

Original change's description:
> [bt][gap] Integrate LegacyPairingState with PairingStateManager
>
> This CL wires up the legacy pairing process code to the rest of the
> system via the PairingStateManager.
>
> Depending on the pairing events we encounter before/after the ACL
> connection is complete, or depending on the result of interrogation with
> the peer, we will tell the PSM whether to use SSP or legacy pairing.
>
> Bug: b/42173830
> Test: fx test //src/connectivity/bluetooth
> Manual Test:
> - Paired and streamed audio to/from Nelson DUT with iOS and veho devices
>   supporting SSP to ensure SSP still functions
> - Paired and streamed audio to/from Nelson DUT with iOS and veho
>   devices. Cherry-picked fxr/1078858 to simulate legacy pairing
>
> Change-Id: Ibf745d6452b5f8fc53dbd16101f2cc3d6a20c114
> Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1062293
> Reviewed-by: Ben Lawson <[email protected]>
> Reviewed-by: Marie Janssen <[email protected]>
> Commit-Queue: Lulu Wang <[email protected]>

Bug: b/42173830
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1102393
GitOrigin-RevId: 52ee3d21a3b09f3139ec8b30681ca92e760350d4
Change-Id: I5cf5c5f5d2bfbfcff62de6ca76bb07f9d62047f3
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/232771
Lint: Lint 🤖 <[email protected]>
Commit-Queue: Jason Graffius <[email protected]>
Reviewed-by: Ben Lawson <[email protected]>
  • Loading branch information
Lulu Wang authored and CQ Bot Account committed Aug 29, 2024
1 parent 7dabba5 commit fe17588
Show file tree
Hide file tree
Showing 13 changed files with 878 additions and 149 deletions.
11 changes: 10 additions & 1 deletion pw_bluetooth_sapphire/host/gap/bredr_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace bt::gap {
namespace {

const char* const kInspectPeerIdPropertyName = "peer_id";
const char* const kInspectPairingStateNodeName = "secure_simple_pairing_state";
const char* const kInspectPairingStateNodeName = "pairing_state_manager";

} // namespace

Expand Down Expand Up @@ -115,6 +115,15 @@ void BrEdrConnection::AddRequestCallback(
request_->AddCallback(std::move(cb));
}

void BrEdrConnection::CreateOrUpdatePairingState(
PairingStateManager::PairingStateType type,
const PairingDelegate::WeakPtr& pairing_delegate,
BrEdrSecurityMode security_mode) {
BT_ASSERT(pairing_state_manager_);
pairing_state_manager_->CreateOrUpdatePairingState(type, pairing_delegate);
set_security_mode(security_mode);
}

void BrEdrConnection::OpenL2capChannel(l2cap::Psm psm,
l2cap::ChannelParameters params,
l2cap::ChannelCallback cb) {
Expand Down
96 changes: 77 additions & 19 deletions pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,8 @@ void BrEdrConnectionManager::InitializeConnection(
auto on_peer_disconnect_cb = [this, link = link.get()] {
OnPeerDisconnect(link);
};

// Create the BrEdrConnection object and place into |connections_| map
auto [conn_iter, success] =
connections_.try_emplace(handle,
peer->GetWeakPtr(),
Expand All @@ -825,8 +827,6 @@ void BrEdrConnectionManager::InitializeConnection(
BT_ASSERT(success);

BrEdrConnection& connection = conn_iter->second;
connection.pairing_state_manager().SetPairingDelegate(pairing_delegate_);
connection.set_security_mode(security_mode());
connection.AttachInspect(inspect_properties_.connections_node_,
inspect_properties_.connections_node_.UniqueName(
kInspectConnectionNodeNamePrefix));
Expand Down Expand Up @@ -890,6 +890,17 @@ void BrEdrConnectionManager::CompleteConnectionSetup(
return;
}

// Now that interrogation has successfully completed, check if the peer's
// feature bits indicate SSP support. If yes, use SecurePairingState to
// perform pairing otherwise, use LegacyPairingState.
PairingStateManager::PairingStateType pairing_type =
PairingStateManager::PairingStateType::kLegacyPairing;
if (peer->IsSecureSimplePairingSupported()) {
pairing_type = PairingStateManager::PairingStateType::kSecureSimplePairing;
}
conn_state.CreateOrUpdatePairingState(
pairing_type, pairing_delegate_, security_mode());

WeakPtr<hci::BrEdrConnection> const connection =
conn_state.link().GetWeakPtr();

Expand Down Expand Up @@ -1295,6 +1306,14 @@ BrEdrConnectionManager::OnIoCapabilityRequest(
return hci::CommandChannel::EventCallbackResult::kContinue;
}
auto [handle, conn_ptr] = *conn_pair;

// If we receive an HCI_IO_Capability_Request event before interrogation is
// complete, there will be no pairing state object so we need to create it now
conn_ptr->CreateOrUpdatePairingState(
PairingStateManager::PairingStateType::kSecureSimplePairing,
pairing_delegate_,
security_mode());

auto reply = conn_ptr->pairing_state_manager().OnIoCapabilityRequest();

if (!reply) {
Expand Down Expand Up @@ -1337,6 +1356,16 @@ BrEdrConnectionManager::OnIoCapabilityResponse(
bt_str(addr));
return hci::CommandChannel::EventCallbackResult::kContinue;
}

// If we receive an HCI_IO_Capability_Response event before interrogation is
// complete, there will be no pairing state object so we need to create it
// now. If we previously created a pairing state object because there was
// already an HCI_IO_Capability_Request event, then this method will no-op.
conn_pair->second->CreateOrUpdatePairingState(
PairingStateManager::PairingStateType::kSecureSimplePairing,
pairing_delegate_,
security_mode());

conn_pair->second->pairing_state_manager().OnIoCapabilityResponse(
params.io_capability().Read());
return hci::CommandChannel::EventCallbackResult::kContinue;
Expand Down Expand Up @@ -1368,13 +1397,23 @@ BrEdrConnectionManager::OnLinkKeyRequest(const hci::EmbossEventPacket& event) {
if (!conn_pair) {
bt_log(WARN,
"gap-bredr",
"can't find connection for ltk (id: %s)",
"Can't find current connection or connection request for peer %s",
bt_str(peer_id));
SendLinkKeyRequestNegativeReply(addr.value());
return hci::CommandChannel::EventCallbackResult::kContinue;
}
auto& [handle, conn] = *conn_pair;

// TODO(fxbug.dev/355466957): Pairing state type is unknown if a
// link key request is received after ACL connection is complete but before
// interrogation is complete. Default to using SSP for now.
if (!conn->interrogation_complete()) {
conn->CreateOrUpdatePairingState(
PairingStateManager::PairingStateType::kSecureSimplePairing,
pairing_delegate_,
security_mode());
}

link_key = conn->pairing_state_manager().OnLinkKeyRequest();
} else {
// Legacy Pairing may occur before the ACL connection between two devices is
Expand Down Expand Up @@ -1461,15 +1500,6 @@ BrEdrConnectionManager::OnLinkKeyNotification(

auto peer_id = peer->identifier();

if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
bt_log(WARN,
"gap-bredr",
"link key for peer %s has insufficient security; not stored",
bt_str(peer_id));
cache_->LogBrEdrBondingEvent(false);
return hci::CommandChannel::EventCallbackResult::kContinue;
}

UInt128 key_value;
::emboss::support::ReadWriteContiguousBuffer(&key_value)
.CopyFrom(params.link_key().value().BackingStorage(), key_value.size());
Expand All @@ -1479,10 +1509,20 @@ BrEdrConnectionManager::OnLinkKeyNotification(

auto handle = FindConnectionById(peer_id);
if (!handle) {
bt_log(WARN,
"gap-bredr",
"can't find current connection for ltk (peer: %s)",
bt_str(peer_id));
std::optional<BrEdrConnectionRequest*> request =
FindConnectionRequestById(peer_id);
if (!request) {
bt_log(WARN,
"gap-bredr",
"Can't find current connection or connection request for peer %s",
bt_str(peer_id));
} else {
// The connection request's legacy pairing state object must exist at this
// point since we created it in the request's constructor.
BT_ASSERT(request.value()->legacy_pairing_state());
request.value()->legacy_pairing_state()->OnLinkKeyNotification(
key_value, static_cast<hci_spec::LinkKeyType>(key_type));
}
} else {
handle->second->link().set_link_key(
hci_key, static_cast<hci_spec::LinkKeyType>(key_type));
Expand Down Expand Up @@ -1711,16 +1751,34 @@ BrEdrConnectionManager::OnPinCodeRequest(const hci::EmbossEventPacket& event) {
// The ACL connection is complete so get the PIN code
auto conn_pair = FindConnectionByAddress(addr.value());
if (!conn_pair.has_value()) {
bt_log(ERROR,
bt_log(WARN,
"gap-bredr",
"Got %s for unconnected addr: %s",
__func__,
"Can't find current connection or connection request for peer %s",
bt_str(addr));
SendPinCodeRequestNegativeReply(addr.value());
return hci::CommandChannel::EventCallbackResult::kContinue;
}
auto [handle, conn_ptr] = *conn_pair;

if (conn_ptr->pairing_state_manager().secure_simple_pairing_state()) {
// TODO(fxbug.dev/355466957): If a SecureSimplePairingState object
// already exists for this connection, we have the following edge case: we
// received an HCI_Link_Key_Request event after ACL connection was
// complete but before interrogation was complete. We temporarily default
// to SSP which causes this error when it is actually legacy pairing.

SendPinCodeRequestNegativeReply(addr.value());
return hci::CommandChannel::EventCallbackResult::kContinue;
}

// If we receive an HCI_PIN_Code_Request event before interrogation is
// complete, there will be no pairing state object so we need to create it
// now
conn_ptr->CreateOrUpdatePairingState(
PairingStateManager::PairingStateType::kLegacyPairing,
pairing_delegate_,
security_mode());

conn_ptr->pairing_state_manager().OnPinCodeRequest(std::move(pin_code_cb));
} else {
// Legacy Pairing may occur before the ACL connection between two devices is
Expand Down
Loading

0 comments on commit fe17588

Please sign in to comment.