This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Errors after unpairing devices and further attempts to bond them

I built and run Bluetooth: Peripheral HIDS keyboard example on nRF52840 DK using nRF Connect SDK 1.3.0. I connected and bonded with it from an Android phone. Then I deleted bond information from the Android phone. After it, I wanted to connect and bond again. And it worked properly. Great! It was BT_SECURITY_L4. You can see UART logs below.

*** Booting Zephyr OS build v2.3.0-rc1-ncs1  ***
Starting Bluetooth Peripheral HIDS keyboard example
I: 8 Sectors of 4096 bytes
I: alloc wra: 0, fa0
I: data wra: 0, f4
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 2.3 Build 0
I: No ID address. App must call settings_load()
Bluetooth initialized
E: set-value failure. key: bt/name error(-2)
I: Identity: d6:c4:f9:a2:02:ad (random)
I: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
I: LMP: version 5.2 (0x0b) subver 0xffff
NFC configuration start
NFC configuration done
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Passkey for 20:47:da:12:f4:e8 (public): 800540
Press Button 1 to confirm, Button 2 to reject.
Numeric Match, conn 0x2000177c
Key report send error: -13
Security changed: 20:47:da:12:f4:e8 (public) level 4
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Passkey for 20:47:da:12:f4:e8 (public): 379671
Press Button 1 to confirm, Button 2 to reject.
Numeric Match, conn 0x2000177c
Security changed: 20:47:da:12:f4:e8 (public) level 4
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)


Now I want to do the same with BT_SECURITY_L2 without any numeric comparison. What should I do? I set passkey_display and passkey_confirm callbacks to NULL:

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = NULL,
	.passkey_confirm = NULL,
	.cancel = auth_cancel,
	.pairing_confirm = pairing_confirm,
#if CONFIG_NFC_OOB_PAIRING
	.oob_data_request = auth_oob_data_request,
#endif
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};


Is it right?

And I built and run the program. And I did the same steps of connecting/disconnecting and bonding/deleting bond information twice. And you can see in below UART logs that I couldn't bond the second time:

Security failed: 20:47:da:12:f4:e8 (public) level 1 err 4
Pairing failed conn: 20:47:da:12:f4:e8 (public), reason 4

*** Booting Zephyr OS build v2.3.0-rc1-ncs1  ***
Starting Bluetooth Peripheral HIDS keyboard example
I: 8 Sectors of 4096 bytes
I: alloc wra: 0, ff0
I: data wra: 0, 0
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 2.3 Build 0
I: No ID address. App must call settings_load()
Bluetooth initialized
I: Identity: d6:c4:f9:a2:02:ad (random)
I: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
I: LMP: version 5.2 (0x0b) subver 0xffff
NFC configuration start
NFC configuration done
Advertising successfully started
Advertising continued
Connected 48:ef:30:6f:b3:db (random)
Pairing confirmed: 48:ef:30:6f:b3:db (random)
Security changed: 48:ef:30:6f:b3:db (random) level 2
Pairing completed: 20:47:da:12:f4:e8 (public), bonded: 1
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)
Advertising successfully started
Advertising continued
Connected 20:47:da:12:f4:e8 (public)
Security failed: 20:47:da:12:f4:e8 (public) level 1 err 4
Pairing failed conn: 20:47:da:12:f4:e8 (public), reason 4
Disconnected from 20:47:da:12:f4:e8 (public) (reason 19)

Logs from nRF Connect SDK:

nRF Connect, 2020-08-07
Nordic_HIDS_keyboard (D6:C4:F9:A2:02:AD)
V	02:32:15.042	Connecting to D6:C4:F9:A2:02:AD...
D	02:32:15.042	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D	02:32:15.922	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	02:32:15.922	Connected to D6:C4:F9:A2:02:AD
D	02:32:15.922	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
V	02:32:15.946	Discovering services...
D	02:32:15.946	gatt.discoverServices()
D	02:32:15.954	[Callback] Services discovered with status: 0
I	02:32:15.954	Services discovered
V	02:32:15.991	Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
- Client Supported Features [R W] (0x2B29)
- Database Hash [R] (0x2B2A)
Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Battery Service (0x180F)
- Battery Level [N R] (0x2A19)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Model Number String [R] (0x2A24)
- Manufacturer Name String [R] (0x2A29)
- PnP ID [R] (0x2A50)
Human Interface Device (0x1812)
- Protocol Mode [R WNR] (0x2A4E)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [R W WNR] (0x2A4D)
   Report Reference (0x2908)
- Report Map [R] (0x2A4B)
- Boot Keyboard Input Report [N R] (0x2A22)
   Client Characteristic Configuration (0x2902)
- Boot Keyboard Output Report [R W WNR] (0x2A32)
- HID Information [R] (0x2A4A)
- HID Control Point [WNR] (0x2A4C)
D	02:32:15.991	gatt.setCharacteristicNotification(00002a05-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.993	gatt.setCharacteristicNotification(00002a19-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.994	gatt.setCharacteristicNotification(00002a4d-0000-1000-8000-00805f9b34fb, true)
D	02:32:15.995	gatt.setCharacteristicNotification(00002a22-0000-1000-8000-00805f9b34fb, true)
V	02:32:17.786	Starting pairing...
D	02:32:17.786	device.createBond()
D	02:32:17.809	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
I	02:32:18.619	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D	02:32:19.158	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I	02:32:19.158	Device bonded
I	02:32:19.696	Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
I	02:32:21.226	Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 420ms)
V	02:32:28.559	Removing bond information...
D	02:32:28.559	device.removeBond() (hidden)
D	02:32:28.608	[Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
E	02:32:28.609	Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
I	02:32:28.609	Disconnected
D	02:32:28.628	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
D	02:32:29.218	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	02:32:29.218	Bond information deleted
D	02:32:36.404	gatt.close()
D	02:32:36.406	wait(200)
V	02:32:36.608	Connecting to D6:C4:F9:A2:02:AD...
D	02:32:36.608	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
D	02:32:37.564	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
D	02:32:37.569	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
I	02:32:37.569	Connected to D6:C4:F9:A2:02:AD
V	02:32:37.594	Discovering services...
D	02:32:37.594	gatt.discoverServices()
D	02:32:37.601	[Callback] Services discovered with status: 0
I	02:32:37.601	Services discovered
V	02:32:37.617	Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
- Client Supported Features [R W] (0x2B29)
- Database Hash [R] (0x2B2A)
Generic Access (0x1800)
- Device Name [R] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Battery Service (0x180F)
- Battery Level [N R] (0x2A19)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Model Number String [R] (0x2A24)
- Manufacturer Name String [R] (0x2A29)
- PnP ID [R] (0x2A50)
Human Interface Device (0x1812)
- Protocol Mode [R WNR] (0x2A4E)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [R W WNR] (0x2A4D)
   Report Reference (0x2908)
- Report Map [R] (0x2A4B)
- Boot Keyboard Input Report [N R] (0x2A22)
   Client Characteristic Configuration (0x2902)
- Boot Keyboard Output Report [R W WNR] (0x2A32)
- HID Information [R] (0x2A4A)
- HID Control Point [WNR] (0x2A4C)
D	02:32:37.617	gatt.setCharacteristicNotification(00002a05-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.619	gatt.setCharacteristicNotification(00002a19-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.621	gatt.setCharacteristicNotification(00002a4d-0000-1000-8000-00805f9b34fb, true)
D	02:32:37.624	gatt.setCharacteristicNotification(00002a22-0000-1000-8000-00805f9b34fb, true)
V	02:32:40.512	Starting pairing...
D	02:32:40.512	device.createBond()
D	02:32:40.541	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D	02:32:40.589	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
I	02:32:40.589	Bonding failed
I	02:32:41.072	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D	02:32:43.644	[Callback] Connection state changed with status: 22 and new state: DISCONNECTED (0)
E	02:32:43.644	Error 22 (0x16): GATT CONN TERMINATE LOCAL HOST
I	02:32:43.644	Disconnected
D	02:32:43.708	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED

As I understood, I had to add unpairing on the side of peripherals. And I added bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY) call in a disconnected callback. Then I built and run the program again and I tried the same steps of connecting/disconnecting and bonding/deleting bond information twice. And everything worked fine!

So, I want to ask you about the unpairing stage. In which callback should I call bt_unpair function?

Is there a way to distinguish ordinary disconnection from deleting bond information on a remote device? I think that no. So, I want to ask how to properly avoid the error with the second attempt to bond, when there's not a numeric comparison. It's an ordinary case when the bond information was deleted on the remote device and it tries to connect the second time. So I have to handle such bonding properly. Please, explain to me, how to cope with it.

Why don't provided examples have such unpairing functions?

And why did a security level changed to 1 during the second bonding without calling bt_unpair function, although it was 2 after the first attempt?

Thank you in advance for any assistance!

  • Simon, many thanks for your answer! But could you explain more about re-pair if the existing bond information is authenticated? As I understood, if a Bluetooth security level is BT_SECURITY_L3 or BT_SECURITY_L4, which include authentication, then it's possible to re-pair devices. But it's not implemented yet, isn't it? Or should it work already with the current nRF Connect SDK without allow_repair function? Because currently, re-pair doesn't work automatically even in the case of BT_SECURITY_L4 security level. So whether should I implement something myself? And if the answer is yes, then I still don't know a stage of pairing flow, where I should do something and what exactly. Can you specify some details about how to re-pair devices using nRF Connect SDK in the case if the existing bond information is authenticated?

  • Hi Roman

    What authentication callbacks are you using now, in order to authenticate the connection? You said initially that you have set the passkey display and confirm callbacks to NULL, are you using some other authentication process or did you set the PASSKEY parameters back to their default values? If you could upload a sniffer log so we can see what is happening on the air during your pairing and re-pairing, that would be helpful. Setting CONFIG_BT_DEBUG_SMP=y would also be helpful to find out what exactly is causing this.

    Best regards,

    Simon

  • Because currently, re-pair doesn't work automatically even in the case of BT_SECURITY_L4 security level.

    It seems that I confused when I wrote it. I am sorry. When passkey_display and passkey_confirm are defined as in an example, then re-pair works properly without any code modifications.

    And in the case, when these callbacks are equal to NULL, then setting up BT_SMP_ALLOW_UNAUTH_OVERWRITE option allows to re-pair also, as you said.

    Many thanks to you, Simon!

  • You shouldn't though, as this option leaves you upon to the bond being hijacked.

    From the help text for the option:

    This option allows all unauthenticated pairing attempts made by the
    peer where an unauthenticated bond already exists.
    This would enable cases where an attacker could copy the peer device
    address to connect and start an unauthenticated pairing procedure
    to replace the existing bond. When this option is disabled in order
    to create a new bond the old bond has to be explicitly deleted with
    bt_unpair.

  • Yes, yes, yes, thank you, Joakim! Now I understood that it's better to completely avoid CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE option to reduce security risks. Thank you for emphasizing.

Related