Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

BLE Pairing/Bonding issue betweennRF52840 as server and PC as a client

Hi all,

I use nRF52840 custom device in peripheral role and I am testing the pairing and bonding process with passkey, first with a tablet and then with PC in client role.

when I connect from the client/central device, a dynamic passkey is sent to the peripheral, I read it in the debugger window and finally I type it in the tablet or PC.

When I pair and bond my tablet through nRF Connect app  to the peripheral the procedure works fine and the central (tablet) is paired and bonded without issues.

When I try the same thing from my PC through Bluetooth Devices > Add a bluetooth device, I get error BLE_GATTS_EVT_SYS_ATTR_MISSING after it has been paired and bonded to the peripheral. I have tested this with two PCs and it happens the same thing.

In my peer_manager_init() I set MITM with BLE_GAP_IO_CAPS_DISPLAY_ONLY

Any ideas?

Thank you for your time

 

#define LESC_DEBUG_MODE                     0                                       /**< Set to 1 to use LESC debug keys, allows you to use a sniffer to inspect traffic. */
#define SEC_PARAM_BOND                      1                                     
#define SEC_PARAM_MITM                      1                                      
#define SEC_PARAM_LESC                      0                                      
#define SEC_PARAM_KEYPRESS                  0                                      
#define SEC_PARAM_IO_CAPABILITIES           BLE_GAP_IO_CAPS_DISPLAY_ONLY //BLE_GAP_IO_CAPS_NONE     
#define SEC_PARAM_OOB                       0                                       
#define SEC_PARAM_MIN_KEY_SIZE              7                                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE              16        

this is the peer_manager_init() definition

static void peer_manager_init(void)  // Initializes the Peer Manager
{
    ret_code_t err_code;

    // Initialize the Peer Manager
    err_code = pm_init();
    APP_ERROR_CHECK(err_code);

    // Register the event handler
    err_code = pm_register(pm_evt_handler);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO("Clearing all data from peers");
    // Delete all existing bonds
    err_code = pm_peers_delete();
    APP_ERROR_CHECK(err_code);

    // Initialize security parameters
    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Set 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;

    // Set the security parameters
    err_code = pm_sec_params_set(&sec_param);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO("Security parameters set.");
    NRF_LOG_INFO("sec_param: bond=%d, mitm=%d, lesc=%d, io_caps=%d",
        sec_param.bond, sec_param.mitm, sec_param.lesc, sec_param.io_caps);
}

This is the pm_handler()

static void pm_evt_handler(pm_evt_t const * p_evt)  //TODO THIS IS FOR SECURITY
{
    pm_handler_on_pm_evt(p_evt);
    pm_handler_flash_clean(p_evt);

    NRF_LOG_INFO("PM_EVENT_HANDLER: %d", p_evt->evt_id);

    switch (p_evt->evt_id)
    {
        case PM_EVT_PEERS_DELETE_SUCCEEDED:
            NRF_LOG_INFO("PM_EVT_PEERS_DELETE_SUCCEEDED");
            //advertising_start(false);
            break;
        case PM_EVT_PEERS_DELETE_FAILED:
            NRF_LOG_INFO("PM_EVT_PEERS_DELETE_FAILED");
            break;
        case PM_EVT_CONN_SEC_CONFIG_REQ:
        {
            // Provide security configuration
            NRF_LOG_INFO("PM_EVT_CONN_SEC_CONFIG_REQ");
            pm_conn_sec_config_t conn_sec_config = { .allow_repairing = true };
            pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
        }
        break;
        case PM_EVT_CONN_SEC_PARAMS_REQ:    
        {
            NRF_LOG_INFO("PM_EVT_CONN_SEC_PARAMS_REQ");
            NRF_LOG_INFO("Security parameters request received.");
            NRF_LOG_INFO("sec_param: bond=%d, mitm=%d, lesc=%d, io_caps=%d",
            sec_param.bond, sec_param.mitm, sec_param.lesc, sec_param.io_caps);

            // Respond to the security parameters request
            err_code = pm_conn_sec_params_reply(p_evt->conn_handle, &sec_param, p_evt->params.conn_sec_params_req.p_context); 
            APP_ERROR_CHECK(err_code);
            NRF_LOG_INFO("REPLIED WITH SEC_PARAMS %d", p_evt->params.conn_sec_params_req.p_context);
        }
        break;
        case PM_EVT_LOCAL_DB_CACHE_APPLIED:
            NRF_LOG_INFO("PM_EVT_LOCAL_DB_CACHE_APPLIED event received.");
        break;

        default:
            break;
    }
}

And this is the corresponding security code parts ble_evt_handler()

case BLE_GAP_EVT_CONNECTED:
              err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, p_ble_evt->evt.gap_evt.conn_handle);
          APP_ERROR_CHECK(err_code);
    
          // Start the security procedure for the new connection
          err_code = pm_conn_secure(p_ble_evt->evt.gap_evt.conn_handle, false);
          if (err_code != NRF_SUCCESS)
          {
             NRF_LOG_ERROR("pm_conn_secure failed with error: %d", err_code);
             APP_ERROR_CHECK(err_code);
             
break;

case BLE_GAP_EVT_AUTH_KEY_REQUEST:  // THIS IS USED ONLY when: MITM = 1 and I/O Capabilities = Display
            NRF_LOG_DEBUG("BLE_GAP_EVT_AUTH_KEY_REQUEST");
        
            err_code = sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_AUTH_KEY_TYPE_NONE, passkey);
            if (err_code != NRF_SUCCESS) {NRF_LOG_ERROR("Failed to reply with passkey. Error code: 0x%04x", err_code);}
            else                         {NRF_LOG_INFO("Passkey reply sent successfully.");}
            break;

case BLE_GAP_EVT_PASSKEY_DISPLAY:  // THIS IS USED ONLY when: MITM = 1 and I/O Capabilities = Display
          
        memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, 6);
        NRF_LOG_INFO("PASSKEY DISPLAY: %s", passkey);
        // Display the passkey to the user (e.g., on a screen or log)
break;

case BLE_GAP_EVT_AUTH_STATUS:
        NRF_LOG_INFO("Authentication status: %d", p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
        if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS)
        {
            NRF_LOG_ERROR("Bonding failed with status: 0x%x", p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
        } 
        else 
        {
            NRF_LOG_INFO("Bonding succeeded.");
        }
break;

case BLE_GATTS_EVT_SYS_ATTR_MISSING:
        // No system attributes have been stored.
        err_code = sd_ble_gatts_sys_attr_set(*m_conn_handle_gen, NULL, 0, 0);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed to set system attributes, error code: %d", err_code);
        }
        else
        {
            NRF_LOG_INFO("System attributes set successfully.");
        }
        APP_ERROR_CHECK(err_code);
break;

  • Number 8 of the  pm_evt_id_t enum
    is the PM_EVT_PEER_DATA_UPDATE_SUCCEEDED in peer_manager_types.h

    I changed the pm log to level 4

  • But then I don't really see any problem here, what is really failing? 

    What is the disconnect reason? Have you checked if it's possible that the peripheral is disconnecting here? Maybe check all instances of sd_ble_gap_disconnect()?

    Kenneth

  • The error occurs in the BLE_GATTS_EVT_SYS_ATTR_MISSING  event when the err_code = sd_ble_gatts_sys_attr_set(*m_conn_handle_gen, NULL, 0, 0); is executed

  • But as mentioned, this should not be executed by the application. It's handled by the peer manager module (when / if neccessary).

    Kenneth

  • Yes sorry I un-commented it for a test and then I forgot to re-comment it Stuck out tongue

    When I remove it the device is disconnected. I suppose that the attributes of the PC are not the same with those of the nRF BLE stack and the PC stops the connection. But on the other hand the device seems to be paired on the PC. What is going on...

    <info> app: IMU Default attached at Power-On
    <info> app: TX_POWER_ROLE_ADV : OK
    <info> app: Clearing all data from peers
    <debug> peer_manager_handler: Event PM_EVT_PEERS_DELETE_SUCCEEDED
    <info> peer_manager_handler: All peers deleted.
    <info> app: PM_EVENT_HANDLER: 12
    <info> app: PM_EVT_PEERS_DELETE_SUCCEEDED
    <info> app: Security parameters set.
    <info> app: sec_param: bond=1, mitm=1, lesc=0, io_caps=0
    <info> app: NACK AFTER SENDING DATA
    <info> app: NACK AFTER SENDING DATA
    <info> app: NACK AFTER SENDING DATA
    <info> app: NACK AFTER SENDING DATA
    <info> app: Gauge Initialized
    <info> app: USB power detected
    <info> app: USB ready
    <info> app: Device  event started
    <info> app: Device suspend event
    <info> app: Device resume event
    <info> app: Device reset event
    <info> app: Device reset event
    <info> app: Device reset event
    <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: BLE GAP Connected
    <info> app: TX_POWER_ROLE_CONN: OK
    <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
    <debug> peer_manager_handler: Security parameter request
    <info> app: PM_EVENT_HANDLER: 5
    <info> app: PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Security parameters request received.
    <debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 527 bytes.
    <debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
    <debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_START
    <debug> peer_manager_handler: Connection security procedure started: role: Peripheral, conn_handle: 0, procedure: Bonding
    <info> app: PM_EVENT_HANDLER: 1
    <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_PARAMS_REQ
    <debug> peer_manager_handler: Security parameter request
    <info> app: PM_EVENT_HANDLER: 5
    <info> app: PM_EVT_CONN_SEC_PARAMS_REQ
    <info> app: Security parameters request received.
    <info> app: sec_param: bond=1, mitm=1, lesc=0, io_caps=0
    <info> app: REPLIED WITH SEC_PARAMS 537132156
    0.
    <debug> nrf_ble_gatt: max_rx_octets: 27
    <debug> nrf_ble_gatt: max_tx_octets: 27
    <debug> nrf_ble_gatt: max_rx_time: 328
    <debug> nrf_ble_gatt: max_tx_time: 328
    <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
    <info> app: PASSKEY DISPLAY: 832577
    <info> app: NACK AFTER SENDING DATA
    <debug> peer_manager_handler: Event PM_EVT_CONN_SEC_SUCCEEDED
    <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding
    <info> app: PM_EVENT_HANDLER: 2
    <info> app: Authentication status: 0
    <info> app: Bonding succeeded.
    <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <debug> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update
    <info> app: PM_EVENT_HANDLER: 8
    <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <debug> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update
    <info> app: PM_EVENT_HANDLER: 8
    <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <debug> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update
    <info> app: PM_EVENT_HANDLER: 8
    <debug> peer_manager_handler: Event PM_EVT_PEER_DATA_UPDATE_SUCCEEDED
    <debug> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update
    <info> app: PM_EVENT_HANDLER: 8
    <debug> peer_manager_handler: Event PM_EVT_LOCAL_DB_CACHE_APPLIED
    <debug> peer_manager_handler: Previously stored local DB applied: conn_handle: 0, peer_id: 0
    <info> app: PM_EVENT_HANDLER: 14
    <info> app: PM_EVT_LOCAL_DB_CACHE_APPLIED event received.
    <info> app: NACK AFTER SENDING DATA
    <info> app: BLE GAP Disconnected
    <info> app: BLE Disconnected
    

Related