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

Peer Manager fails to save bond

I am working on a BLE peripheral (nRF52832 & SDK 15) which uses the Peer Manager to handle encryption and bonding to a previously existing central device.  Sometimes bonding works, but often I am seeing a failure mode where the encryption and bonding process succeeds (the connection completes and data flows from central to peripheral and vice versa) but the Peer Manager doesn't save the bond.  I discover this when I disconnect and reconnect, and I get PM_EVT_CONN_SEC_FAILED with PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING.  

So far I have attempted to verify that the bond data isn't being stored by looking at what happens after I get PM_EVT_CONN_SEC_SUCCEEDED during bonding.  I went into peer_database.c and added some NRF_LOG()s in write_buf_store().  I see the write happen and no error is reported.  However I never get either PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or PM_EVT_PEER_DATA_UPDATE_FAILED.  I put log msgs into pdb_pds_evt_handler() in peer_database.c, and in my own pm_evt_handler.  It appears that the bond save is failing silently.  This is very frustrating.

Sometimes the bond *is* successfully saved, and I'm able to reconnect to the central indefinitely.  I can't yet figure out why it sometimes succeeds.

I discovered this issue when starting to write code to handle a possible failure which could be caused by the central losing its bond data... the idea being that if the connection fails, both sides will the delete their bonds automatically and can then be manually rebonded by the user.  I test this scenario by manually deleting the bond in the central... on the next connection attempt, reestablishing the link fails and the peripheral deletes its bonds.  This all seems to be working as expected.  But when I manually rebond, I'm stuck... the nRF52 usually isn't saving the new bond.

This current project is to replace a remote control based on another vendor's BLE chip.  Encryption and bonding have worked for years with the central so I have no reason to distrust it.

Any advice on how to debug this further would be much appreciated.

Darren

Parents
  • Hi, 

     

    We would need to know what you set in your conn_sec_config when calling pm_conn_sec_config_reply(). 

    If you have a look at our example, ble_app_proximity for example you can see we set allow_repairing = false inside pm_evt_handler(): 

    case PM_EVT_CONN_SEC_CONFIG_REQ:
    {
    // Reject pairing request from an already bonded peer.
    pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
    pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
    } break;

     

    This mean, if the central lose bond information, the device would reject re-bonding. The reason for this is to avoid attacker force a device to delete original bond information and force a new bond where they can be sniff the bonding process or to be MITM. 

    If you set allow_repairing = true, the device supposed to replace old bond information with new one. I would need you to reproduce the issue with our example so we can try here. 

     

Reply
  • Hi, 

     

    We would need to know what you set in your conn_sec_config when calling pm_conn_sec_config_reply(). 

    If you have a look at our example, ble_app_proximity for example you can see we set allow_repairing = false inside pm_evt_handler(): 

    case PM_EVT_CONN_SEC_CONFIG_REQ:
    {
    // Reject pairing request from an already bonded peer.
    pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
    pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
    } break;

     

    This mean, if the central lose bond information, the device would reject re-bonding. The reason for this is to avoid attacker force a device to delete original bond information and force a new bond where they can be sniff the bonding process or to be MITM. 

    If you set allow_repairing = true, the device supposed to replace old bond information with new one. I would need you to reproduce the issue with our example so we can try here. 

     

Children
  • Hello and thanks for the quick response.

    I have set allow_repairing to true during my testing and it doesn't make any difference.  In any case it shouldn't matter because the problem is not that the pairing fails, it's that the key data isn't being saved.  In other words, I can delete all bonds on the nRF device (so it should not recognize any previously paired devices) and still when creating a new bond the key data isn't saved.

    My steps are:

    1. Delete all bonds on both central and peripheral 

    2. Pairing initiated and succeeds, get a correct and working connection.

    3. power cycle the peripheral; on reconnect peripheral won't connect with error PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING.

    4. back to step 1 above.

    So my issue is not that pairing fails, it's that re-connecting after pairing fails because the peripheral didn't save the bond even though write_buf_store() is being called after pairing.

    As I mentioned, my app is also using fds.  Is there anything I need to be sure to do or not do when using fds in order to not interfere the with Peer Manager's use of fds?

  • Hi Darrenji

    Sorry that I misunderstood your issue.

    I assume you have set SEC_PARAM_BOND = 1 to enable bonding, not just pairing. 

    I would suggest you to use the same phone to test with one of our example, the ble_app_proximity for example to make sure the central handle bonding properly. 

    I don't think it would be a problem storage your own data with fds and have the peer manager working at the same time. 

    Please enable debugging to get more log from the peer manager unit. You need to add DEBUG in the preprocessor symbols and enable logging either by RTT or UART. 

     

  • Hello,

    Yes I do have SEC_PARAM_BOND = 1.  I'm not pairing to a phone, but to our own device.  Our Central device has been working for 3 years bonding successfully to another peripheral.

    What I'm seeing with the nRF is that fds fails silently.  The high level call to write returns SUCCESS, but the actual asynchronous write to flash never happens and no event or error is reported. I've seen this both with the peer manager's internal write to save the bond data, and with my own call to fds to write config data.

    It seems like no matter what I'm doing, fds shouldn't fail silently.

  • I have one more specific question... I based my app on the proximity app so the code is basically identical with respect to pairing/bonding.  One question I have is why when the BLE_GAP_EVT_CONNECTED event happens, nrf_ble_qwr_conn_handle_assign() is called.  There are no comments in the example that explain why it would need queued writes.  There are no other references to qwr in the app.  Is it necessary for something else in the sd?  If I remove the calls and take queued write manager out of the makefile, no symbols are missing.  I've searched the sdk and online but can't find any obvious explanations.  I'm not using long writes in any characteristics.

  • I have spent many hours tracing the execution of fds and can now see what is failing, but not why.  When I write my config data, the write request is passed down into nrf_fstorage_sd.c.  The queue_process() function tries to write the header (FDS_OP_WRITE_HEADER_BEGIN) and calls write_execute().  The write_execute() function calls sd_flash_write() which returns NRF_SUCCESS, but the soft device doesn't generate an event, so the fstorage state machine cannot continue to process the write. There is a comment in nrf_fstorage_sd.c in the switch() case that handles the return value from write_execute():

                /* The operation was accepted by the SoftDevice.
                 * If the SoftDevice is enabled, wait for a system event. Otherwise,
                 * the SoftDevice call is synchronous and will not send an event so we simulate it. */
    

    Because the soft device is enabled, the code is waiting for a system event, and never gets one.

    I did the same trace exercise when pairing, and the store of the bond fails for the same reason, no event is generated.

    Do you have any advice about how to figure out why the soft device is not posting file system events but seems to otherwise work?

Related