[nRF52833] Peripheral changing IRK while connected, on bonding attempt

Hi,

I'm working on a legacy program (Peripheral) using nRF52833 and nRF5 SDK using SoftDevice S113.

One of the requirements of my peripheral application is that it should automatically reconnect (whenever in range) to only one Central device (the latest Central that it Bonded with). The reconnection should be automatic (on major OSs, like iOS/Android/ChromeOS).

While connected, the Peripheral should also allow incoming connections from other Centrals that may then Bond to it (if they pass an encrypted data exchange at the App layer), in which case the Peripheral will now become associated with this latest device and only allow automatic reconnection (on power cycles, reboots, etc...) from this Central. The peripheral also needs to use Resolvable Private Addresses for privacy.

The approach I was thinking of following to achieve this was the following:

  • 1. Peripheral boots, fetches curr_IRK from persistent storage and applies it with pm_privacy_set()
  • 2. Starts connectable advertising and rotates address every 30s (BLE stack will generate addresses resolvable by Centrals using curr_IRK) 
  • 3. CentralA (bonded) resolves the address and connects. App data is now exchanged while user is interacting with the Peripheral/CentralA
  • 4. Peripheral immediately re-enables connectable advertising to allow other Centrals to connect/bond
  • 5. CentralB connects and starts bonding/auth
  • 6. On Auth start App generates a new IRK, (new_IRK) and sets it via pm_privacy_set() with the goal of completing Bonding with CentralB with new_IRK
  • 7a. On Auth success, new_IRK is stored in persistent storage, curr_IRK = new_IRK, then Peripheral disconnects from CentralA and deletes its bonding peer data from persistent storage (CentralA will now fail to scan/connect to Peripheral due to IRK change)
  • 7b. On Auth failure, new_IRK is discarded and (previous) curr_IRK is set with pm_privacy_set()

My two questions are:

1. Is the above approach feasible to meet my requirement (would changing the IRK when attempting bonding with CentralB while CentralA is connected cause any problems with either

  • a) CentralA (whose connection is still using the previous IRK)
  • b) CentralB connected to Peripheral which at the time of connection was advertising an RPA resolvable with curr_IRK, but the IRK changes during the connection, right before Auth (before keys exchanged)?

2. If the above approach sounds possible, what's the latest valid AUTH/BLE event that I can use to change the IRK via pm_security_set() before the change is rejected by the SoftDevice? Should it be PM_EVT_CONN_SEC_START, SD_BLE_GAP_AUTHENTICATE, BLE_GAP_EVT_SEC_PARAMS_REQUEST (or other)?

Thanks,

Marco

Parents
  • Hi Marco,

    1. Is the above approach feasible to meet my requirement (would changing the IRK when attempting bonding with CentralB while CentralA is connected cause any problems with either

    Yes and no. The general approach is valid, but I would make a small adjustment. First though, pm_privacy_set() essentially just calls sd_ble_gap_privacy_set(), and unfortunately the API documentation of pm_privacy_set() is not entirely correct. The documentation for sd_ble_gap_privacy_set() is though, and states the following (for S132 version 7.2.0):

    /**@brief Set privacy settings.
     *
     * @note  Privacy settings cannot be changed while advertising, scanning or creating a connection.
     *
     * @param[in] p_privacy_params Privacy settings.
     *
     * @mscs
     * @mmsc{@ref BLE_GAP_PRIVACY_ADV_MSC}
     * @mmsc{@ref BLE_GAP_PRIVACY_SCAN_MSC}
     * @mmsc{@ref BLE_GAP_PRIVACY_ADV_DIR_PRIV_MSC}
     * @endmscs
     *
     * @retval ::NRF_SUCCESS Set successfully.
     * @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry.
     * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid address type is supplied.
     * @retval ::NRF_ERROR_INVALID_ADDR The pointer to privacy settings is NULL or invalid.
     *                                  Otherwise, the p_device_irk pointer in privacy parameter is an invalid pointer.
     * @retval ::NRF_ERROR_INVALID_PARAM Out of range parameters are provided.
     * @retval ::NRF_ERROR_NOT_SUPPORTED The SoftDevice does not support privacy if the Central Address Resolution
                                         characteristic is not configured to be included and the SoftDevice is configured
                                         to support central roles.
                                         See @ref ble_gap_cfg_car_incl_cfg_t and @ref ble_gap_cfg_role_count_t.
     * @retval ::NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while advertising, scanning
     *                                   or creating a connection.
     */

    As you can see, you cannot call sd_ble_gap_privacy_set() (and thus not pm_privacy_set()) while advertising, scanning or initiating a connection. Another important point is that the Bluetooth address is not used during a connection. Therefore, instead of the approach you described I would suggest that you change the IRK earlier, before you start advertising in your step 4.

    2. If the above approach sounds possible, what's the latest valid AUTH/BLE event that I can use to change the IRK via pm_security_set() before the change is rejected by the SoftDevice? Should it be PM_EVT_CONN_SEC_START, SD_BLE_GAP_AUTHENTICATE, BLE_GAP_EVT_SEC_PARAMS_REQUEST (or other)?

    As mentioned above I would consider doing it a bit differently so that this would not be relevant, but if not, you should update the IRK before calling sd_ble_gap_sec_params_reply() as you can see from this note in the API doc of ble_gap_privacy_params_t:

     * @note  If the device IRK is updated, the new IRK becomes the one to be distributed in all
     *        bonding procedures performed after @ref sd_ble_gap_privacy_set returns.
     *        The IRK distributed during bonding procedure is the device IRK that is active when @ref sd_ble_gap_sec_params_reply is called.

    The last event you will get before that when using the peer manager library is PM_EVT_CONN_SEC_PARAMS_REQ.

    Einar

  • Thanks for the clarification Einar.

    A couple of follow up questions:


    1. Another important point is that the Bluetooth address is not used during a connection
      You mean that the Bluetooth address is not used (for the purpose of scanning for devices or initiating a connection), after the Peripheral gets BLE_GAP_EVT_CONNECTED, so I could call sd_ble_gap_privacy_set() while handling the Connected BLE GAP event? In other words once the app gets BLE_GAP_EVT_CONNECTED, the state of the connection is now "during" (not "initiating")
      • instead of the approach you described I would suggest that you change the IRK earlier, before you start advertising in your step 4.
      The problem that I see with that is that if I change IRK when starting advertising after connected to CentralA (last bonded device), then what IRK should be used in step 2 (advertising after boot). If the previous IRK (curr_IRK) is used, CentralA can connect when in range, but if using a newly generated on (new_IRK) then CentralA won't be able to connect. So advertising with curr_IRK would allow bonded CentralA to connect (and also other Centrals), but changing it on PM_EVT_CONN_SEC_PARAMS_REQ would cause bonds to new Centrals to use the new IRK
  • Hi,

    so I could call sd_ble_gap_privacy_set() while handling the Connected BLE GAP event? In other words once the app gets BLE_GAP_EVT_CONNECTED, the state of the connection is now "during" (not "initiating")

    Yes, that is what I mean. I must admit I have not tested it, but I see not reason why it should not work. (Both because it should according to the SoftDevice spec, and in Bluetooth the device addresses are not use during a connection. In a connection, the randomly generated access address is used instead.)

Reply
  • Hi,

    so I could call sd_ble_gap_privacy_set() while handling the Connected BLE GAP event? In other words once the app gets BLE_GAP_EVT_CONNECTED, the state of the connection is now "during" (not "initiating")

    Yes, that is what I mean. I must admit I have not tested it, but I see not reason why it should not work. (Both because it should according to the SoftDevice spec, and in Bluetooth the device addresses are not use during a connection. In a connection, the randomly generated access address is used instead.)

Children
No Data
Related