Pairing is asked again and again to an already bonded device nRF52832

Hello, 

We have a custom board with nRF52832 in production, nRF5 SDK, s132, using BLE. We recently have faced some issues regarding connection from some of our clients.

The problem they have described to us is: They connect to the device with a mobile phone or a tablet (Android) and perform bonding with a static key. At first it looks like it is completed successfully but after trying to have access to the characteristics with our app, the pop-up window of pairing appears again and they see at Bluetooth settings that the device was removed from bonded devices. This happens again and again and they cannot eventually connect to the device. 

About our application: 

/**@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();
    hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 0, NULL);

    memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures. These are common parameters for bonding.
    sec_param.bond           = 1;
    sec_param.mitm           = 0;
    sec_param.lesc           = 0;
    sec_param.keypress       = 0;
    sec_param.io_caps        = BLE_GAP_IO_CAPS_DISPLAY_ONLY;
    sec_param.oob            = 0;
    sec_param.min_key_size   = 7;
    sec_param.max_key_size   = 16;
    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);   // sets security parameters for pairing and bonding
    hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 1, NULL);

    err_code = pm_register(pm_evt_handler);   // register an event handler for the module
    hardfault = app_error_check_logger(err_code, true, log_str[PEER_MANAGER_INIT], 2, NULL);
}

peer manager initialization

static void pm_evt_handler(pm_evt_t const * p_evt)
{
    pm_handler_on_pm_evt(p_evt);    // Logging peer events. Starts encryption if connected to a bonded device.
    pm_handler_disconnect_on_sec_failure(p_evt);    // Disconnects if the connection was not secured.
    pm_handler_flash_clean(p_evt);

    switch (p_evt->evt_id)
    {
        case PM_EVT_CONN_SEC_SUCCEEDED:   //a link has been encrypted, result of a call of pm_conn_secure or of an action by the peer.
            m_peer_id = p_evt->peer_id;
            pm_local_database_has_changed();
            break;

        case PM_EVT_PEERS_DELETE_SUCCEEDED:   // a peer was cleared from flash storage (result of pm_peer_delete)
            NRF_LOG_INFO("PM_EVT_PEERS_DELETE_SUCCEEDED");
            hardfault = app_error_check_logger(1, false, "peersdel", 1, NULL);
            advertising_start(false);
            break;

        case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: // a piece of peer data was tored, updated or cleared in flash storage.
            if (     p_evt->params.peer_data_update_succeeded.flash_changed
                 && (p_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_BONDING))
            {
                NRF_LOG_INFO("New Bond. Peer data update succeeded.");
            }
            break;
        case PM_EVT_CONN_SEC_FAILED:    // a pairing or encryption procedure has failed. in some cases, this means that security is not possible on this link.
        {
            NRF_LOG_INFO("Pairing or Encryption procedure failed. Peer id=%d, Error=%x, Procedure=%d, Source=%d", p_evt->peer_id, p_evt->params.conn_sec_failed.error,
                                                                                        p_evt->params.conn_sec_failed.procedure,p_evt->params.conn_sec_failed.error_src);
            uint8_t proc=0;
            if(p_evt->params.conn_sec_failed.error_src == 1)
            {
                  proc = p_evt->params.conn_sec_failed.procedure + 10;
            }
            else
            {
                  proc = p_evt->params.conn_sec_failed.procedure;
            }
            hardfault = app_error_check_logger(p_evt->params.conn_sec_failed.error, false, "secfail", proc, NULL);
            m_scoliosense.err_code = p_evt->params.conn_sec_failed.error;
            ble_error_sec_update(m_conn_handle, &m_scoliosense);
         }
            break;
         case PM_EVT_CONN_SEC_CONFIG_REQ:
         {
            // Allow or reject pairing request from an already bonded peer.
            NRF_LOG_INFO("Repairing Process was initiated.");
            pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
            pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
         } 
         break;

        default:
            break;
    }
}

peer manager handler

static void conn_params_init(void)
{
  ret_code_t             err_code;
  ble_conn_params_init_t cp_init;

  memset(&cp_init, 0, sizeof(cp_init));

  cp_init.p_conn_params                  = NULL;
  cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
  cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
  cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
  cp_init.disconnect_on_fail             = false;
  cp_init.evt_handler                    = on_conn_params_evt;
  cp_init.error_handler                  = conn_params_error_handler;

  err_code = ble_conn_params_init(&cp_init);
  hardfault = app_error_check_logger(err_code, true, log_str[CONN_PARAMS_INIT], 0, 1);
}

conn params init, where
#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) 
#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) 
#define MAX_CONN_PARAMS_UPDATE_COUNT 3

Connection parameters:

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) 
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) 
#define SLAVE_LATENCY 0 
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(10000, UNIT_10_MS) 

Also, we see in our analytics that these errors are caused:
BLE_GAP_SEC_STATUS_UNSPECIFIED

BLE_GAP_SEC_STATUS_TIMEOUT
at PM_EVT_CONN_SEC_FAILED event. 
and sometimes at connection parameter handler error 0x8 Invalid state is triggered which is " Disconnection in progress or link has not been established"

Finally, at sdk_config, we have
PM_HANDLER_SEC_DELAY_MS 400 
PM_RA_PROTECTION_ENABLED 0


1. What could cause this issue ? 
2. Could it be the allowed repairing ? Could it be the delay of 400 ms before starting security? 
3. Could it be that we haven't enabled PM_RA_PROTECTION_ENABLED ?
4. Could it be something about connection parameters update? because at this part of code, we haven't included any logs to track any errors there apart from conn_params_handler. 
5. Could it be something caused by the specific phones? because in developing and testing we have never encountered such issues. 

Maybe we have set something wrong about pairing bonding and peer manager, something is not set as it supposed to, or something is missing? 

Any help is very much appreciated. 

Kind  regards,
Dimitra

  • Hello, 

    I found a device which has the issue but I don't really see the problem in sniffer.. 

    Also, from nRF connect mobile app I can see the logs:

    Please let me know if you can find any information from sniffer screenshots.. 

    Also, I noticed that bonding is performed successfully the first time, but afterwards, if we disconnect it will ask to bond again, and repairing process will start. Also, sometimes GATT error 133 appeared. So, since I know that the peripheral device (nRF52832) did not erase the bonds, something happens and the phone deletes it. I dont know why but I had an idea that maybe PM_HANDLER_SEC_DELAY_MS is related to it..

    Therefore, I tried to change this 

    // <o> PM_HANDLER_SEC_DELAY_MS - Delay before starting security. 
    // <i>  This might be necessary for interoperability reasons, especially as peripheral.
    
    #ifndef PM_HANDLER_SEC_DELAY_MS
    #define PM_HANDLER_SEC_DELAY_MS 400
    #endif

    from 400 ms to 4000 ms. And it looks like it works. Also, if I set it to default value, 0, it also works. 

    1) Could it be that the peer manager handler security delay is the cause of the issue? How could it be related to it? 
    2) If so, is it better to set it at 0, so that my device, as a peripheral, will never initiate security procedure and will always wait the central device to do so?
    3) Or is it recommended to set a delay, but high enough so that there is no collision.. and if this is the case, is 4000ms a good value? is there another one recommended?
    4) Also, if I set a delay, does this mean that there will be a delay before my peripheral device starts security if for some reason mobile has not started it ? and if the device starts the security, I guess the preipheral will not also start it. 

    Best regards, 
    Dimitra

Related