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

Loss of bonding key

I am working on a BLE peripheral (nRF52840 & SDK 15.3), which uses the Peer Manager to handle encryption and bonding to an iOS central device. 

Requirements call for the device to advertise its presence every 180 seconds such that the central device can connect and query for any available data.  Once all data has been transferred, the BLE peripheral closes the connection to conserve power.  When establishing the connection, central negotiates for notifications on three data channels (custom Characteristics) to expedite data transfer.  This action changes the CCCD definitions for these Characteristics and triggers an update to the data that Peer Manager saves in flash storage.

After approximately 18 hours of operation, pairing fails between the peripheral and the iOS central device.  I have traced the issue to an encryption failure in security_dispatcher, line 388 where the function sec_info_request_process() detects a null ble_gap_enc_info_t object for the valid device handle 0, indicating the security key is missing locally.  I have confirmed that the security descriptor is being saved to flash; valid connections can still be created following a power cycle on an nRF52840-DK with no battery.

Does garbage collection in the Peer Manager properly preserve security descriptors when there is only one peer device?  I am currently only ever bonding with a single iOS central device but have found that in pm_handler_flash_clean() the PM_EVT_STORAGE_FULL event is calling pm_peer_delete(); even when there is only one peer bonded with the peripheral.

The PM_PEER_RANKS_ENABLED is enabled to support connections to a second central device at some point, does disabling this functionality also disable deletion of the lowest ranked peer during garbage collection?  Is there documentation that explains Peer Ranking functionality?  I have disabled this and enabled re-bonding functionality in the pm call back in hopes that iOS honors the request.  I do not consider re-bonding to be a solution because of its security risks.

These two changes were just implemented and their results will be known in about 18 hours.   In the interim, I am asking for assistance in better understanding the garbage collection process and the peer ranking process in your Peer Manager implementation.

Parents
  • Nordic engineer to be assigned ... applying both of the above changes did correct the encryption failure issue that was being created.  The change to allow re-pairing is a security risk and therefore not considered an acceptable solution.  Is this condition being created because of the PM_PEER_RANKS_ENABLED option and, where is there documentation that describes the behavior of this option?  I would expect this option to delete the lowest ranked peer only when the number of bonded peers approaches the value assigned to PM_RA_PROTECTION_TRACKED_PEERS_NUM which is eight in my case.  Does this option also delete the only peer that is bonded when peer manager executes garbage collection anyway?

    While awaiting my answers I will back out the change to allow re-pairing and see if the condition returns after another 18 hour test.

  • You may disable the rank system, especially if you only have 1 bond at any time. The intention of the rank system is for the application to be able to have some kind of knowledge of which peer have been used last or least. The rank will be updated each time you connect to a peer, and that is really it. There is no automatic deletion of the peer based on it's rank, this must be handled by the application in some way based on application criteria (e.g. need to delete a bond to make room for a new). I am not sure what a good idea it is to frequently update CCCD's, since they will trigger flash write (and possible erase) operation frequently. A better idea would be to simply have CCCD's enabled all the time, but instead the peer can write a command on demand that the application will use to decide if it should send notifications or not.

  • You say in your response that there is no automatic deletion of the peer based on it's rank.  When this event occurs it is because peer_manager_handler.c line 350 is executed in the function pm_handler_flash_clean() with state PM_EVT_STORAGE_FULL.  How do I configure the app to allow this state to occur without the call to pm_peer_delete() on line 350?  This line deletes the lowest ranked peer even when it is the only peer.

Reply
  • You say in your response that there is no automatic deletion of the peer based on it's rank.  When this event occurs it is because peer_manager_handler.c line 350 is executed in the function pm_handler_flash_clean() with state PM_EVT_STORAGE_FULL.  How do I configure the app to allow this state to occur without the call to pm_peer_delete() on line 350?  This line deletes the lowest ranked peer even when it is the only peer.

Children
  • I see your point, this shouldn't occur no. There should at least be some check that if it's only one bond (e.g. call pm_peer_count()), then the pm_peer_delete() is not executed. Considering you only have one bond you may just set flash_write_after_gc to true always. You are free to change this as you see fit. 

    An alternative may be that you on each disconnection call fds_stat(), and then run fds_gc() before PM_EVT_STORAGE_FULL may occur.

Related