How to get pairing/bonding to work in e.g. ble_app_uart

   Hello List,

First some context: I am working with SDK 17.1.0 on a nrf52840 (arduino nano ble).

Created a variant of the ble_app_uart example and want to add pairing/bonding with it. Started looking at ble_app_hrs to start.

Basically I added functions "peer_manager_init" and "pm_evt_handler" and some changes to "sdk_config.h", but now am stuck. Please see below for that code.

With this code it just works, but without pairing/bonding.

If I remove the "pm_conn_sec_params_reply" call from "pm_evt_handler" the smartphone pops up a window and asks whether there should be a pairing, which then fails as can be seen using the RTT-log:

<error> peer_manager_sm: Could not perform security procedure. smd_params_reply() or smd_link_secure() returned NRF_ERROR_INVALID_ADDR. conn_handle: 0
<error> peer_manager_handler: Unexpected fatal error occurred: error: NRF_ERROR_INVALID_ADDR
<error> peer_manager_handler: Asserting.
<error> app: Fatal error

One thing that is missing is setting the pin code in the program, how is that to be done?

Hopefully someone can help me in the right direction.

Thanks in advance, Sietse

Here the code snipped.

// peer_manager stuff in main.c
      
#include "peer_manager.h"
#include "peer_manager_handler.h"
#include "fds.h"

#define SEC_PARAM_BOND                      1                                       /**< Perform bonding. */
#define SEC_PARAM_MITM                      0                                       /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC                      1                                       /**< LE Secure Connections enabled. */
#define SEC_PARAM_KEYPRESS                  0                                       /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_NONE                    /**< No I/O capabilities. */
#define SEC_PARAM_OOB                       0                                       /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE              7                                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE              16                                      /**< Maximum encryption key size. */


static void pm_evt_handler(pm_evt_t const * p_evt)
{
    pm_handler_on_pm_evt(p_evt);
    pm_handler_disconnect_on_sec_failure(p_evt);
    pm_handler_flash_clean(p_evt);

    switch (p_evt->evt_id)
      {
      case PM_EVT_PEERS_DELETE_SUCCEEDED:
	advertising_start();
	break;

      case  PM_EVT_CONN_SEC_SUCCEEDED:
	NRF_LOG_INFO("--> PM_EVT_CONN_SEC_SUCCEEDED");
	break;
      case  PM_EVT_CONN_SEC_PARAMS_REQ:
	NRF_LOG_INFO("--> PM_EVT_CONN_SEC_PARAMS_REQ");
	pm_conn_sec_params_reply(p_evt->conn_handle,
				 p_evt->params.conn_sec_params_req.p_peer_params,
				 p_evt->params.conn_sec_params_req.p_context);
	break;
      default:
	NRF_LOG_INFO("--> pm_evt_handler %d", p_evt->evt_id);
	break;
    }
}



/**@brief Function for the Peer Manager initialization.
 */

static void peer_manager_init(void)
{
    ble_gap_sec_params_t sec_param;
    ret_code_t           err_code;

    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    sec_param.bond           = SEC_PARAM_BOND;
    sec_param.mitm           = SEC_PARAM_MITM;
    sec_param.lesc           = SEC_PARAM_LESC;
    sec_param.keypress       = SEC_PARAM_KEYPRESS;
    sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
    sec_param.oob            = SEC_PARAM_OOB;
    sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
    sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
    sec_param.kdist_own.enc  = 1;
    sec_param.kdist_own.id   = 1;
    sec_param.kdist_peer.enc = 1;
    sec_param.kdist_peer.id  = 1;

    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);
}


Parents
  • Hi

    Yes, the peer_manager_init() is there, but I didn't see where the peer manager library (.c and .h files) was referenced. 

    1. I think this is because the service is not set up to require bonding before using it. For that you need to do something like the ble_app_gls application does for the glucose service, where the security level is set when initializing the service. If you want to trig bonding on connection, you should start a security request timer like this application does in the BLE_GAP_EVT_CONNECTED event.

            case BLE_GAP_EVT_CONNECTED:
            {
                NRF_LOG_INFO("Connected");
                m_peer_to_be_deleted = PM_PEER_ID_INVALID;
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                // Start Security Request timer.
            } break;

    2. When you remove bonding on your smartphone, the bonding info is likely left stored on the nRF52 side, which will cause the bonding to fail when you try again. You will need to erase bonds on the nRF as well, either with the pm_peers_delete() function.

    Best regards,

    Simon

  • Hi,

    Almost there! Pairing works.

    In pm_evt_handler I had:

          case  PM_EVT_CONN_SEC_PARAMS_REQ:                                                                                                                                                                        
            NRF_LOG_INFO("--> PM_EVT_CONN_SEC_PARAMS_REQ");                                                                                                                                                        
            pm_conn_sec_params_reply(p_evt->conn_handle,                                                                                                                                                           
                                     p_evt->params.conn_sec_params_req.p_peer_params,                                                                                                                              
                                     p_evt->params.conn_sec_params_req.p_context);                                                                                                                                 
            break;                                                                   

    and in ble_evt_handler for case BLE_GAP_EVT_CONNECTED I had:

            err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);   

    This in an attempt to get pm_conn_secure to work. After removing this pairing/bonding works as advertised!

    For the second point I understood that pm_peer_delete should be called when NOT connected.

    My final problem is, where to do that. I read it can best done in event BLE_GAP_EVT_DISCONNECTED. But there is NO such event in this case. Here an annotated snippet of the RTT-log of the situation when trying to connect when the bond has been deleted on central.

    <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
    <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
    <info> app: --> pm_evt_handler 1  PM_EVT_CONN_CONFIG_REQ
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 1, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9  PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <info> app: --> pm_evt_handler 0  PM_EVT_BONDED_PEER_CONNECTED
    <info> app: --> pm_evt_handler 15 PM_EVT_LOCAL_DB_CACHE_APPLIED
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Connected
    <info> app: --> pm_evt_handler 2  PM_EVT_CONN_SEC_START
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: --> pm_evt_handler 5  PM_EVT_CONN_SEC_CONFIG_REQ
    <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
    <info> app: Data len is set to 0xF4(244)
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Bonding, error: 133
    <warning> peer_manager_handler: Disconnecting conn_handle 0.
    <debug> nrf_ble_lesc: Generating ECC key pair
    <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x85 bond=0x0 lv4: 0 kdist_own:0x0 kdist_peer:0x0
    <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 517 bytes.
    <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
    

    I see that in the code for BL_GAP_EVT_DISCONNECTED there is a call to pm_peer_delete for an other case.

    Could I use the same mechanism? Maybe set a flag in one of the occurring events above?

    Thanks for the help so far!  Sietse

Reply
  • Hi,

    Almost there! Pairing works.

    In pm_evt_handler I had:

          case  PM_EVT_CONN_SEC_PARAMS_REQ:                                                                                                                                                                        
            NRF_LOG_INFO("--> PM_EVT_CONN_SEC_PARAMS_REQ");                                                                                                                                                        
            pm_conn_sec_params_reply(p_evt->conn_handle,                                                                                                                                                           
                                     p_evt->params.conn_sec_params_req.p_peer_params,                                                                                                                              
                                     p_evt->params.conn_sec_params_req.p_context);                                                                                                                                 
            break;                                                                   

    and in ble_evt_handler for case BLE_GAP_EVT_CONNECTED I had:

            err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);   

    This in an attempt to get pm_conn_secure to work. After removing this pairing/bonding works as advertised!

    For the second point I understood that pm_peer_delete should be called when NOT connected.

    My final problem is, where to do that. I read it can best done in event BLE_GAP_EVT_DISCONNECTED. But there is NO such event in this case. Here an annotated snippet of the RTT-log of the situation when trying to connect when the bond has been deleted on central.

    <debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
    <debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
    <info> app: --> pm_evt_handler 1  PM_EVT_CONN_CONFIG_REQ
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 1, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9  PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <info> app: --> pm_evt_handler 0  PM_EVT_BONDED_PEER_CONNECTED
    <info> app: --> pm_evt_handler 15 PM_EVT_LOCAL_DB_CACHE_APPLIED
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Connected
    <info> app: --> pm_evt_handler 2  PM_EVT_CONN_SEC_START
    <info> app: --> pm_evt_handler 6  PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: --> pm_evt_handler 5  PM_EVT_CONN_SEC_CONFIG_REQ
    <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
    <info> app: Data len is set to 0xF4(244)
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Bonding, error: 133
    <warning> peer_manager_handler: Disconnecting conn_handle 0.
    <debug> nrf_ble_lesc: Generating ECC key pair
    <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x85 bond=0x0 lv4: 0 kdist_own:0x0 kdist_peer:0x0
    <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 517 bytes.
    <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
    

    I see that in the code for BL_GAP_EVT_DISCONNECTED there is a call to pm_peer_delete for an other case.

    Could I use the same mechanism? Maybe set a flag in one of the occurring events above?

    Thanks for the help so far!  Sietse

Children
No Data
Related