bluekitchen / btstack

Dual-mode Bluetooth stack, with small memory footprint.
http://bluekitchen-gmbh.com
Other
1.74k stars 618 forks source link

Failing to bonding iOS without deleting device from iOS #567

Closed amorniroli closed 8 months ago

amorniroli commented 9 months ago

Describe the bug

I'm trying gap_dedicated_bonding.c example trying to bond to iphone se, ios 17.3.1.

Pair is succesfull just the first time: after that, every time I try to re-bond it fails with status '5'.

I have to delete bonding info from ios to let bonding succeed again.

To Reproduce

Just run example gap_dedicated_bonding.c, trying to connect ios device

Expected behavior

I'd expect that bonding would succeed every time. Android is working as expected.

HCI Packet Logs See fail_ios.txt attachment (rename to .pcap). fail_ios.txt

Environment: (please complete the followi ng information):

Additional context /

mringwal commented 9 months ago

What do you do in the iPhone UI during this pairing? As far as I know, you can only pair when you're in the Bluetooth Settings.

In the log, you delete the local link key, then trigger authentication, which asks for our link key, which isn't there and triggers pairing. The pairing then fails. It looks like iOS just rejects it outright.

If you are in the Bluetooth Settings, could you also upload the iOS packet log? It requires to install a debugging certificate: https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/

I can imagine that iOS might just reject the pairing as the peripheral (your device) is not supposed to loose its link key. A device that looses it's link key can be seen as untrustworthy :)

amorniroli commented 9 months ago

Hi @mringwal ,

see my comments.

What do you do in the iPhone UI during this pairing? As far as I know, you can only pair when you're in the Bluetooth Settings. I stay in the bluetooth settings, without doing anything else

In the log, you delete the local link key, then trigger authentication, which asks for our link key, which isn't there and triggers pairing. The pairing then fails. It looks like iOS just rejects it outright.

If you are in the Bluetooth Settings, could you also upload the iOS packet log? It requires to install a debugging certificate: https://www.bluetooth.com/blog/a-new-way-to-debug-iosbluetooth-applications/ I will try in the next dats.

I can imagine that iOS might just reject the pairing as the peripheral (your device) is not supposed to loose its link key. A device that looses it's link key can be seen as untrustworthy :)

Using other chipset/stack (CC2564/Bluetopia) it seems to work as expected. Actually, I remember with previous btstack versions that everything was working as expected. I'll give a try with old btstack version to see if something has changed.

Meanwhile, I've recorded traces with android and ios. Both traces start in a "cleaned" scenario (no bonded devices on btstack / phones).

I just start inquiry -> waiting for devices I want to bond -> start bonding -> wait for bonding to finish -> restart bonding (3 bond in a row). Android always succeed, iOS (I've updated to 17.4) only the first time. android.pcap.txt ios.pcap.txt

I think it's something related to new iOS versions, because on the my friend ios it's working as expected (I was not able to record trace when I've tried).

mringwal commented 9 months ago

What was the state of the iPhone?

As far as I remember, pairing is rejected by OS without bothering the user unless you're in Bluetooth settings.

amorniroli commented 8 months ago

Hi @mringwal ,

I've just found out what is the issue.

iOS is refusing to overwrite the bonding if spp io capability is set to 'SSP_IO_CAPABILITY_NO_INPUT_NO_OUTPUT'.

I've tried to set SSP_IO_CAPABILITY_DISPLAY_ONLY and it's working as expected (iOS is overwriting the previous bonding, without the need to explicitly delete the old one).

On bluetopia stack it was working because I was using DISPLAY_ONLY: using NO_INPUT/NO_OUTPUT is failing also on bluetopia.

FYI, I guess this is something introduced with iOS 17, since with older iOS versions the issue is not present.

Thanks for the support.

Alessandro

mringwal commented 8 months ago

Hi Alessandro. Interesting find.

What irritates me, is that you have been able to pair the first time with SSP_IO_CAPABILITY_NO_INPUT_NO_OUTPUT, but it then fails in subsequent tries.

On the other hand, with DISPLAY (or most likely Passkey entry) and the iPhone iOS capabilities, this results in a pairing with MITM Protection, which involves the user. So I can image the internal rule "if the user is involved, accept the re-pairing, otherwise abort"

Does this make sense?

amorniroli commented 8 months ago

Hi Alessandro. Interesting find.

What irritates me, is that you have been able to pair the first time with SSP_IO_CAPABILITY_NO_INPUT_NO_OUTPUT, but it then fails in subsequent tries.

On the other hand, with DISPLAY (or most likely Passkey entry) and the iPhone iOS capabilities, this results in a pairing with MITM Protection, which involves the user. So I can image the internal rule "if the user is involved, accept the re-pairing, otherwise abort"

Does this make sense?

Hi, that's make sense. At least, that's the behavior we are seen.

What irritates me, is that apple makes changes without providing a detailed changelog :) (at least, I've tried to search for this behavior, but couldn't find anything).

mringwal commented 8 months ago

What irritates me, is that apple makes changes without providing a detailed changelog :) Haha! Feel free to submit a bug report to Apple :)