Skip to content

Accept re-pairing from a bonded peer (espressif) - #11237

Merged
tannewt merged 1 commit into
adafruit:mainfrom
dhalbert:espressif-repeat-pairing
Aug 24, 2026
Merged

Accept re-pairing from a bonded peer (espressif)#11237
tannewt merged 1 commit into
adafruit:mainfrom
dhalbert:espressif-repeat-pairing

Conversation

@dhalbert

@dhalbert dhalbert commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Claude found this deficiency (not an outright bug) and wrote the fix.

(Part of the series of small PRs replacing #11178. Independent of the others.)

The problem

A central will ask to pair again when it no longer has its own copy of the bond. This happens whenever the user forgets the device in their OS Bluetooth settings, or the bonding info has otherwise gone away.

In this situation, before this fix, when the central asked to pair again, NimBLE reported BLE_GAP_EVENT_REPEAT_PAIRING to _bleio. But we did not handle that event, and nothing was sent back to the central. The board therefore could not be paired with again at all, and had to have its bonds erased with a blue-flash reset.

The fix

Handle the BLE_GAP_EVENT_REPEAT_PAIRING event by deleting the stale bond with ble_store_util_delete_peer() and returning BLE_GAP_REPEAT_PAIRING_RETRY. This idiom is used in NimBLE's own bleprph example. The nordic port already behaves this way: it clears the stored keys on BLE_GAP_EVT_SEC_PARAMS_REQUEST and lets the new pairing replace them.

ESP-IDF also offers CONFIG_BT_NIMBLE_HANDLE_REPEAT_PAIRING_DELETION, which makes the stack delete the bond itself. But we didn't use that because Claude's analysis showed the code enabled by that config option is not resilient to the connection going away.

Testing

Tested on a Metro ESP32-S3 with the web editor on Linux. Paired and transferred files, then removed the bond on the host only, leaving the board's bond in place, and reconnected: before this change nothing happened and no pairing prompt appeared, and now the central pairs and the session works.

Note that the reverse case cannot be fixed here. If the board's bonds are erased while the host keeps its key, the host offers a key the board no longer knows, encryption fails with PIN or Key Missing, and the host has to forget the device.

Other ports

As noted, this is not needed on nordic. I'll file separate issues for the other ports.

NimBLE reports BLE_GAP_EVENT_REPEAT_PAIRING when a peer we still hold a bond
for asks to pair again. Unless the application deletes the old bond and
returns BLE_GAP_REPEAT_PAIRING_RETRY, the stack silently ignores the pairing
request. The event was unhandled, so a central that had forgotten its side of
the bond could not pair again: the board's bonds had to be erased first.

Delete the stale bond with ble_store_util_delete_peer() and retry, matching
the nordic port, which clears the stored keys when a peer re-pairs.
@dhalbert
dhalbert requested a review from tannewt August 24, 2026 01:20
@tannewt

tannewt commented Aug 24, 2026

Copy link
Copy Markdown
Member

Note that the reverse case cannot be fixed here. If the board's bonds are erased while the host keeps its key, the host offers a key the board no longer knows, encryption fails with PIN or Key Missing, and the host has to forget the device.

FWIW my Android phone just shows the pairing prompt again. I don't need to explicitly "forget" the device.

@tannewt tannewt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@tannewt
tannewt merged commit 8d0527c into adafruit:main Aug 24, 2026
208 checks passed
@dhalbert
dhalbert deleted the espressif-repeat-pairing branch August 24, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants