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);
}


  • Hi

    The gls_init. function is not relevant. It's only for the Glucose service specifically. I can't see that you've added the peer manager library in your main file, but I guess it might be added somewhere else since you're able to build and run the application. It seems like there just doesn't come a bonding request from the central device. What is the central in this case, and does it initiate a bonding procedure upon connection or not?

    Best regards,

    Simon

  • Thanks again!

    peer_manager_init() is on line 898.

    I tried both a python program on Linux, using the bleak library and the nRF Toolbox on Android using the Utils service UART.

    But i found something! I just tried the "nRF Connect" app and found that after connecting there is a "Bond" item in the menu! I didn't see that before.

    When trying that the bonding with my smartphone took place!  So progress,  but ...

    First: I don't understand it!  I can fully connect to and use the device without this bonding, so there is NO security at all here. I assumed that it should only be possible to get access to the functionality of the ble-device  after giving a correct passkey.

    Secondly: I removed the bonding on my smartphone. Now I still can connect but bonding is refused. Why isn't the bonding renewed? The only thing that I now can think of is re-flashing the device...

    Below there are two pieces of logging:

       1. a piece of the RTT logging. In the first part, the passkey 121224  is given, and bonding is done. At the end there is the bonding error 133.

       2. A saved log from nRF Connect from the same situation, after the initial bonding was removed from the smartphone. You see connecting and trying to bond.

    So a little step ahead. Hopefully this helps, Sietse

    <info> app_timer: RTC: initialized.
    <debug> nrf_ble_lesc: Initialized nrf_crypto.
    <debug> nrf_ble_lesc: Initialized nrf_ble_lesc.
    <debug> nrf_ble_lesc: Generating ECC key pair
    <info> app: Debug logging for UART over RTT started.
    <info> app: Fast advertising
    <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
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Connected
    <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
    <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 251
    <debug> nrf_ble_gatt: max_tx_octets: 251
    <debug> nrf_ble_gatt: max_rx_time: 2120
    <debug> nrf_ble_gatt: max_tx_time: 2120
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: --> pm_evt_handler 2
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Passkey: 121224
    <debug> nrf_ble_lesc: BLE_GAP_EVT_LESC_DHKEY_REQUEST
    <info> app: BLE_GAP_EVT_LESC_DHKEY_REQUEST
    <info> nrf_ble_lesc: Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: 0
    <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding
    <info> app: --> PM_EVT_CONN_SEC_SUCCEEDED
    <info> app: Link secured. Role: 1. conn_handle: 0, Procedure: 1
    <debug> nrf_ble_lesc: Generating ECC key pair
    <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 1 kdist_own:0x3 kdist_peer:0x2
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
    <info> app: --> pm_evt_handler 9
    
        (9 is PM_EVT_PEER_DELETE_SUCCEEDED)
    
    
    <info> app: Fast advertising
    <info> app: Disconnected
    <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
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9
    <info> app: --> pm_evt_handler 0
    <info> app: --> pm_evt_handler 15
    
      (15 is PM_EVT_SERVICE_CHANGED_IND_SENT
        documentation states that a PM_EVT_SERVICE_CHANGED_IND_CONFIRMED (16) should occur. It doesn't)
    
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_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
    <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 251
    <debug> nrf_ble_gatt: max_tx_octets: 251
    <debug> nrf_ble_gatt: max_rx_time: 2120
    <debug> nrf_ble_gatt: max_tx_time: 2120
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: --> pm_evt_handler 2
    <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Encryption
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9
    <info> app: --> PM_EVT_CONN_SEC_SUCCEEDED
    <info> app: Link secured. Role: 1. conn_handle: 0, Procedure: 0
    <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.
    <info> app: Data len is set to 0xF4(244)
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    <info> app: --> pm_evt_handler 9
    <debug> app: Received data from BLE NUS. Writing data on UART.
    <debug> app:  64 64 67 68 20 66 67 67|ddgh fgg
    <debug> app:  67                     |g       
    
    <info> app: Fast advertising
    <info> app: Disconnected
    <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
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9
    <info> app: --> pm_evt_handler 0
    <info> app: --> pm_evt_handler 15
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_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
    <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 251
    <debug> nrf_ble_gatt: max_tx_octets: 251
    <debug> nrf_ble_gatt: max_rx_time: 2120
    <debug> nrf_ble_gatt: max_tx_time: 2120
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: --> pm_evt_handler 2
    <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Encryption
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9
    <info> app: --> PM_EVT_CONN_SEC_SUCCEEDED
    <info> app: Link secured. Role: 1. conn_handle: 0, Procedure: 0
    <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.
    <info> app: Data len is set to 0xF4(244)
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: Fast advertising
    <info> app: Disconnected
    <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
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change
    <info> app: --> pm_evt_handler 9
    <info> app: --> pm_evt_handler 0
    <info> app: --> pm_evt_handler 15
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_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
    <debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
    <debug> nrf_ble_gatt: max_rx_octets: 251
    <debug> nrf_ble_gatt: max_tx_octets: 251
    <debug> nrf_ble_gatt: max_rx_time: 2120
    <debug> nrf_ble_gatt: max_tx_time: 2120
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: --> pm_evt_handler 2
    <info> app: --> PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: --> pm_evt_handler 5
    <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
    <info> app: Fast advertising
    <info> app: Disconnected
    

    Here the log from nRF Connect:

    nRF Connect, 2022-09-05
    Nordic_UART (FC:8D:82:18:DD:32)
    D	16:02:43.277	gatt.close()
    D	16:02:43.284	wait(200)
    V	16:02:43.487	Connecting to FC:8D:82:18:DD:32...
    D	16:02:43.488	gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, preferred PHY = LE 1M)
    D	16:02:44.517	[Broadcast] Action received: android.bluetooth.device.action.ACL_CONNECTED
    D	16:02:44.560	[Callback] Connection state changed with status: 0 and new state: CONNECTED (2)
    I	16:02:44.560	Connected to FC:8D:82:18:DD:32
    V	16:02:44.639	Discovering services...
    D	16:02:44.639	gatt.discoverServices()
    I	16:02:45.083	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
    D	16:02:45.208	[Callback] Services discovered with status: 0
    I	16:02:45.208	Services discovered
    V	16:02:45.240	Generic Access (0x1800)
    - Device Name [R W] (0x2A00)
    - Appearance [R] (0x2A01)
    - Peripheral Preferred Connection Parameters [R] (0x2A04)
    - Central Address Resolution [R] (0x2AA6)
    Generic Attribute (0x1801)
    Nordic UART Service (6e400001-b5a3-f393-e0a9-e50e24dcca9e)
    - RX Characteristic [W WNR] (6e400002-b5a3-f393-e0a9-e50e24dcca9e)
    - TX Characteristic [N] (6e400003-b5a3-f393-e0a9-e50e24dcca9e)
       Client Characteristic Configuration (0x2902)
    D	16:02:45.240	gatt.setCharacteristicNotification(6e400003-b5a3-f393-e0a9-e50e24dcca9e, true)
    I	16:02:45.294	Connection parameters updated (interval: 48.75ms, latency: 0, timeout: 5000ms)
    I	16:02:50.412	Connection parameters updated (interval: 75.0ms, latency: 0, timeout: 4000ms)
    V	16:03:03.611	Starting pairing...
    D	16:03:03.611	device.createBond()
    D	16:03:03.758	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
    D	16:03:04.162	[Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_NONE (10)
    I	16:03:04.162	Bonding failed
    I	16:03:04.233	Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
    D	16:03:04.254	[Callback] Connection state changed with status: 19 and new state: DISCONNECTED (0)
    W	16:03:04.254	Connection terminated by peer (status 19)
    I	16:03:04.254	Disconnected
    D	16:03:04.393	[Broadcast] Action received: android.bluetooth.device.action.ACL_DISCONNECTED
    

  • Forgot to mention. With the ble_app_gls the bonding was directly initiated when trying to connect.

    So that is different.

    But the problem after removing the bound on the smartphone occurs here too.

  • 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

Related