This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PeerManager [1°pairing->1°NoPairing->2°Pairing without"delete_bonds()"]

I modified the "ble_app_uart" project on "nRF5_SDK_15.2.0_9412b96".
I added the "peer manager" function.
The first pairing works perfectly.
After performing the NoPairing function, it is no longer possible to perform a second pairing.
The message "peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Bonding, error: 133" appears on the terminal.
To be able to perform a pairing again, the startup must press an EVAL button to execute the "delete_bonds()" function.

How can I solve this problem ?
See the terminal report below.

Thanks.
BR

Demetrio Magrin

-------------------------------------------------------------------------------------------

static void advertising_start(bool erase_bonds)
{
    if (erase_bonds == true)
    {
        delete_bonds();
        // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event.
    }
    else
    {
        ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);

        APP_ERROR_CHECK(err_code);
    }
}

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

int main(void)
{
    bool erase_bonds;

    // Initialize.
    uart_init();
    log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();

    // Start execution.
    //printf("\r\nUART started.\r\n");
    NRF_LOG_INFO("Debug logging for UART over RTT started.");
    advertising_start(erase_bonds);

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

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

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

        default:
            break;
    }
}

-------------------------------------------------------------------------------------------

From JLINK-RTT Viewer:

00> <info> app: Debug logging for UART over RTT started.
00> <info> app: Debug logging for UART over RTT started.
00> <info> app: Connected
00> <info> app: Data len is set to 0xF4(244)
00> <info> peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Bonding, error: 133
00> <info> app: Disconnected
00>


  • Bonding, error: 133" appears on the terminal.

    Have you looked up what that error code means?

    To be able to perform a pairing again, the startup must press an EVAL button to execute the "delete_bonds()" function

    So do that, then!

    How can I solve this problem ?

    See above.

    How to properly post source code:

  • Hi,

    The peer manager will by default reject pairing requests from an already paired device (bond refresh). You need to delete the bond on the nRF52 to establish a new bond with the phone (e.g. with the button press at startup), or set the ".allow_repairing" flag to accept bond refresh, as shown in this post. As mentioned in that post, allow_repairing will enable a potential attacker to update an existing bond. So there is a trade-off between security and user-friendliness. 

  • Hello Mr. Sigurd,

    thanks for your advice
    I modified the code as follows:

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

        switch (p_evt->evt_id)
        {
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
            {
                advertising_start(false);
            }
            break;
            case PM_EVT_CONN_SEC_CONFIG_REQ:
            {
                //
                // Allow pairing request from an already bonded peer.
                // Note that this will enable a potential attacker to update an existing bond.
                // So there is a trade-off between security and user-friendliness.
                //
                pm_conn_sec_config_t conn_sec_config = { .allow_repairing = true };
                pm_conn_sec_config_reply(m_conn_handle, &conn_sec_config);
            }
            break;
            default:
            break;
        }
    }

    Now the error has disappeared.
    Is there another safer way to not have this problem ?

    ------------------------------------------

    ------------------------------------------

    Another question about pairing:
    My initialization is this:

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

    Is it possible to make pairing only if, for example, an EVAL key is pressed at the startup ?
    Is it possible to do this ?
    Where can I find an example ?

    Thank you.

    BR

    Demetrio Magrin

  • HI, 

    you can refer to the example (https://github.com/jimmywong2003/nrf5-bond-with-2nd-central-example).  I enable the 2 peripheral role on the device.  if the device needs to bond with another host, need to press the button to trigger advertising without whitelist. If success, it would replace the existing host bonding record.

  • Hi,

    Thank you for your suggestion.
    I need to be able to perform the pairing with the same device (central) without having to perform the "delete_bonds()" function that is activated by pressing the "BSP_EVENT_CLEAR_BONDING_DATA" button at the startup.

    I saw that the only way is to change the function as follows:

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

        switch (p_evt->evt_id)
        {
            case PM_EVT_PEERS_DELETE_SUCCEEDED:
            {
                advertising_start(false);
            }
            break;
            case PM_EVT_CONN_SEC_CONFIG_REQ:
            {
                //
                // Allow pairing request from an already bonded peer.
                // Note that this will enable a potential attacker to update an existing bond.
                // So there is a trade-off between security and user-friendliness.
                //
                pm_conn_sec_config_t conn_sec_config = { .allow_repairing = true };
                pm_conn_sec_config_reply(m_conn_handle, &conn_sec_config);
            }
            break;
            default:
            break;
        }
    }

    As written in the function:
    // Notes that this will enable a potential attacker to update an existing bond.
    // So there is a trade-off between security and user-friendliness.

    I was wondering if there was another safer way to solve this problem.

    Thank you.

    BR
    Demetrio Magrin

Related