This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Legacy Pairing/Bonding problem, pc-ble-driver, NRF52, central

I currently need to solve pairing/bonding to be able to implement DFU with the buttonless bonded bootloader. So I need to handle bonding/pairing from my central device, controlled using pc-ble-driver (and connectivity firmware SD 140, v6.1.1). The project is at a late stage. Scanning, connecting, discovering and using characteristics is already really stable and works as expected.

Just a side note: The peripheral firmware seems to be correct, as I'm able to do DFU from a mobile application running on Android!

What already works:
After a connection to an unbonded peripheral is established (just before discovering services), I call sd_ble_gap_authenticate() with:

const ble_gap_sec_params_t SecurityParams = {
1, // Bond
0,
0,
0,
BLE_GAP_IO_CAPS_NONE,
0,
7,
16,
{ 1, 1, 0, 0 },
{ 1, 1, 0, 0 }
};

which responds with BLE_GAP_EVT_SEC_PARAMS_REQUEST. I answer this by calling sd_ble_gap_sec_params_reply(sec_status=0, p_sec_params=NULL, keySet), where keySet is just an empty buffer. This call fills the own/p_id_key with key data, which I store in a file. I than got BLE_GAP_EVT_AUTH_STATUS with bonded=true and auth_status=0 (SUCCESS).

At this point, I'm able to subscribe to BLE_DFU_BUTTONLESS_BONDED_CHAR_UUID's indication, so I assume bonding was successful. I can repeat this by resetting the bonding information in the peripheral.

What does not work:
I'm not able to recreate this state if the peripheral holds the bonding information. After the connection has been established I directly got BLE_GAP_EVT_SEC_REQUEST. Upon receiving this event, I call sd_ble_gap_authenticate() using the parameters above (tested with bond=0 and bond=1). I've also tested calling sd_ble_gap_authenticate() a second time after handling BLE_GAP_EVT_SEC_REQUEST. Either case, I always receive BLE_GAP_EVT_AUTH_STATUS with bonded=false and auth_status=133 (BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP). So I neither got BLE_GAP_EVT_SEC_PARAMS_REQUEST to supply my stored keys to the central.

I've tried to understand how pc-nrfutil handles this, but looking into github.com/.../dfu_transport_ble.py , def bond(), seems to do it this way too. I've no idea what I do wrong.

What's the correct way to connect / pair / (reestablish-)bond to an already bonded peripheral?

A second question: Does the connectivity firmware store the bonding keys on device site too? This question is centered about the usability. If I connect my central device to a different host PC and try to connect to an already bonded peripheral, does the central know the bonding keys (e.g. stored in flash) or do I have to copy my host site keystore to the new host (and supply them when receiving BLE_GAP_EVT_SEC_REQUEST)?

Many thanks,
Thomas

Parents
  • Hello Thomas,

    The peer manager on the peripheral will by default reject bonding requests from a previously bonded peer, so this is likely why you get the BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP status in response to your request. I explained how you can configure the Peer manager to accept bond updates in my post here: https://devzone.nordicsemi.com/f/nordic-q-a/51965/pairing-and-bonding-after-deleting-synchronization/208927#208927. The other option is to delete the bond on the DFU target before you initiate DFU.

    A second question: Does the connectivity firmware store the bonding keys on device site too? This question is centered about the usability. If I connect my central device to a different host PC and try to connect to an already bonded peripheral, does the central know the bonding keys (e.g. stored in flash) or do I have to copy my host site keystore to the new host (and supply them when receiving BLE_GAP_EVT_SEC_REQUEST)?

    The host (pc-ble-driver app in this case) is responsible for the key storage. The connectivity FW does not store anything to flash.

    If anything is unclear, let me know.

    Best regards,

    Vidar

  • Thanks again Vidar. I'm now a little bit further. In case I found a stored key to the newly connected device, I call sd_ble_gap_encrypt() using the keyset: own/p_enc_key pair (received from BLE_GAP_EVT_AUTH_STATUS after bonding).

    But subscription to the DFU characteristic still fails in this case.

    Not sure if this is important. When receiving BLE_GAP_EVT_CONN_SEC_UPDATE I got two different security levels:

    Initial bond/sd_ble_gap_authenticate(): security_mode=1, level=2, key_size=16 -> DFU Char subscription success

    Reconnect/sd_ble_gap_encrypt(): security_mode=1, level=1, key_size=0 -> DFU Char subscription fails (BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION)

    Just in case this may be useful, here's the call to sd_ble_gap_encrypt() in the debugger. The key may be valid .. (it's a list not 0x00, 0x00, ..).

    PS: I took another look into how pc-nrfutil is able to subscribe to this characteristic (https://github.com/NordicSemiconductor/pc-nrfutil/blob/af139f1fa2e511c9bf378eff00049d8bb69b8a15/nordicsemi/dfu/dfu_transport_ble.py)

    After connecting and service discovery, and if the bonded DFU char is present, it jumps to  jump_from_buttonless_mode_to_bootloader() (from line 164), where it calls bond() (line 199) in any case. In there, a call to sd_ble_gap_authenticate() (line 325) seems to be called every time, independent if a previous bonding was successfully done or not .. and this must be responed with success (line 334). After that, the char is subscribed (line 206). sd_ble_encrypt() (line 168) is started after the device has rebooted into DFU mode.

    I'm still really confused :)

  • Level 1 means the link did not get encrypted or authenticated, which explains why you are unable to enable subscribe to the DFU characteristic. The question is why. I obviously can't tell if the encryption key is correct just by looking at it. The lesc and auth bits are set correctly at least.

    Here is what I get for comparison when testing on a dev kit :

    One way to troubleshoot this further is to capture a sniffer trace of the bonding exchange + the reconnect where you try to encrypt the link again. You can use our nRF Sniffer for Bluetooth LE if you have an extra devkit or nRF52840 Dongle laying around.

Reply
  • Level 1 means the link did not get encrypted or authenticated, which explains why you are unable to enable subscribe to the DFU characteristic. The question is why. I obviously can't tell if the encryption key is correct just by looking at it. The lesc and auth bits are set correctly at least.

    Here is what I get for comparison when testing on a dev kit :

    One way to troubleshoot this further is to capture a sniffer trace of the bonding exchange + the reconnect where you try to encrypt the link again. You can use our nRF Sniffer for Bluetooth LE if you have an extra devkit or nRF52840 Dongle laying around.

Children
No Data
Related