[PATCH 2/2] Bluetooth: SMP: distribute the identity address when bonding
From: Brandon Williams
Date: Sat Oct 24 2026 - 07:25:28 EST
build_pairing_cmd() only offers our Identity Information and Identity
Address Information when privacy is enabled. Without privacy the peer
never learns our identity address, and bonds without it.
Some peripherals need it. The Microsoft Surface Slim Pen 2 only
advertises to reconnect, after a button press, if the host it bonded
with distributed its identity, as Windows does. Paired by Linux, the pen
stays silent. Enabling privacy is no workaround: the host then scans and
connects from a resolvable private address, while the pen directs its
advertisements at the host's public address.
Offer the identity key whenever we bond over LE. Without privacy,
hdev->irk is all zeros, which "indicates that a device does not have a
valid resolvable private address" (Core Specification, Vol 3, Part H,
3.6.4), so the peer receives our public or static identity address and
no usable IRK; the previous patch makes Linux ignore such an IRK. The
peer still decides: the Pairing Response masks the distribution down to
what it accepts. Cross-transport key derivation over BR/EDR is
unchanged.
Tested on a Microsoft Surface Pro 11 (X1E80100, WCN7850): the Slim Pen 2
now accepts our identity key, and reconnects on a single click, double
click and press-and-hold after it has dropped the link. The Surface Pro
Flex Keyboard also accepts our identity key over its out-of-band pairing
and still reconnects.
Assisted-by: LLM
Signed-off-by: Brandon Williams <turbine.bmw@xxxxxxxxx>
---
net/bluetooth/smp.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index fc75cf568471..8ce5f92d7ee5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -636,7 +636,13 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
if (hci_dev_test_flag(hdev, HCI_BONDABLE)) {
- local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
+ /* Always distribute our identity address when bonding, so the
+ * peer can tell who it is bonded with. Without privacy the IRK
+ * sent along with it is all zeros, which the specification
+ * defines as having no resolvable private address. Some
+ * peripherals only reconnect to hosts that did this.
+ */
+ local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN | SMP_DIST_ID_KEY;
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
authreq |= SMP_AUTH_BONDING;
} else {
--
2.56.0