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>


Parents
  • 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

Reply
  • 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

Children
No Data
Related