Skip to content

Force security request when watch reports a bond but link won't encrypt#289

Open
gmarull wants to merge 1 commit into
coredevices:masterfrom
teslabs:fix-stale-bond-encryption
Open

Force security request when watch reports a bond but link won't encrypt#289
gmarull wants to merge 1 commit into
coredevices:masterfrom
teslabs:fix-stale-bond-encryption

Conversation

@gmarull

@gmarull gmarull commented Jul 8, 2026

Copy link
Copy Markdown
Member

When the user forgets the pairing on the phone, the watch still holds its copy of the bond, so the connection address resolves and the watch reports paired=true in the Pebble Pairing Service connectivity status (since pebbleos 916fdbf17, which derives it from the persistent bond store). On iOS, isBonded() has no backing API and is hardcoded to true, so the needs-pairing check concludes "already paired" and never requests pairing. The link then sits unencrypted: the watch's kernel LE client (and thus PPoG) is gated on encryption, the phone's PPoG handshake times out after ~12s, and the app tears down and reconnects in an endless loop with nobody ever initiating SMP.

Detect the stalemate: when the watch says paired but the link hasn't encrypted shortly after connection setup, write the pairing trigger with forceSecurityRequest. The watch then sends an SM security request, and the phone either silently re-encrypts (keys present) or starts a fresh pairing (keys lost), which also makes the watch drop its stale bond via the repeat-pairing path. Falls back to reading the trigger characteristic for watches without a writeable trigger, and waits for the watch's encryption-change connectivity notification to confirm.

This doesn't touch createBond(), so it cannot reintroduce the Android bond-reject reconnect storm fixed by pebbleos 916fdbf17 (FIRM-2212).

Fixes MOB-9335

Note: NOT tested

When the user forgets the pairing on the phone, the watch still holds
its copy of the bond, so the connection address resolves and the watch
reports paired=true in the Pebble Pairing Service connectivity status
(since pebbleos 916fdbf17, which derives it from the persistent bond
store). On iOS, isBonded() has no backing API and is hardcoded to true,
so the needs-pairing check concludes "already paired" and never requests
pairing. The link then sits unencrypted: the watch's kernel LE client
(and thus PPoG) is gated on encryption, the phone's PPoG handshake times
out after ~12s, and the app tears down and reconnects in an endless loop
with nobody ever initiating SMP.

Detect the stalemate: when the watch says paired but the link hasn't
encrypted shortly after connection setup, write the pairing trigger with
forceSecurityRequest. The watch then sends an SM security request, and
the phone either silently re-encrypts (keys present) or starts a fresh
pairing (keys lost), which also makes the watch drop its stale bond via
the repeat-pairing path. Falls back to reading the trigger characteristic
for watches without a writeable trigger, and waits for the watch's
encryption-change connectivity notification to confirm.

This doesn't touch createBond(), so it cannot reintroduce the Android
bond-reject reconnect storm fixed by pebbleos 916fdbf17 (FIRM-2212).

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
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.

1 participant