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;

Parents Reply Children
No Data
Related