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

Pairing & Bonding happens even when the client's iocap is no_io_caps

I have a ble server with display developed for passkey security.  It works fine when the Master (i.e. client) is set to have Keyboard input capability, which is good.

The problem is that when the client is set to have no_io_caps, the pairing and bonding still happens successfully.  That means the client may bypass the security without needing to enter the passkey.  I am wondering where in code would I need to change in order for the server to stop pairing with client devices without entering the correct passkey.

Note that the following are the security settings I used:

#define SEC_PARAM_BOND                  1                                       /**< Perform bonding. */
#define SEC_PARAM_MITM                  1                                       /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC                  0                                       /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS              0                                       /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_DISPLAY_ONLY            /**< No I/O capabilities. */
#define SEC_PARAM_OOB                   0                                       /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE          7                                       /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE          16                                      /**< Maximum encryption key size. */

Also, I had made sure that the bonds on both the client and the server are removed before all my tests.

Your help will be greatly appreciated.

  • Both sides must state that they support LESC, otherwise the paring will be performed with the common denominator in terms of supported features. So we need to verify if the ESP32 sets LESC as a suppported feature during the connection preocedure. 

    Could you use the nRF Sniffer v2 to capture a on-air-trace of the communication between the ESP32 and the nRF52? 

  • Regarding LESC connection, thanks for the useful suggestion of using nRF Sniffer to capture the connection.  It looks like towards the end, after Key Exchange, the MASTER (i.e. ESP32 as client) sends a LL_CONNECTION_UPDATE_REQ.  But, the nrf device (Server) doesn't respond with anything. Until 28 seconds later, the nrf sends a LL_TERMINATE_IND.

    Is the nRF device supposed to respond to a LL_CONNECTION_UPDATE_REQ command, or not?  Can you tell what the problem may be?

    I have attached the capture from nRF Sniffer.  You may use this as filter to see the essential packets:

             btle.length!=0 && !btle.advertising_header

    LeSecureConnectFail.pcapng

  • I took a look at the trace and in terms of LESC support its all good, both sides states that they support LESC in the pairing request/response. 

    Which SDK version are you using ?

    At least in SDK v15.2.0 you will need to respond to the BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST event by adding the following snippet to ble_evt_handler

     case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
    {
        NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST");
    
        err_code = sd_ble_gap_conn_param_update(m_conn_handle,
            &p_gap->params.conn_param_update_request.conn_params);
    
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failure to update connection parameter request: 0x%x", err_code);
        }
    
        APP_ERROR_CHECK(err_code);
    } break;

    You can also add handling of the BLE_GAP_EVT_CONN_PARAM_UPDATE event, which is generated when the update is finished. 

     case BLE_GAP_EVT_CONN_PARAM_UPDATE:
    {
        NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE");
    
        ble_gap_conn_params_t const * p_conn =
            &p_gap->params.conn_param_update.conn_params;
    
        NRF_LOG_DEBUG("max_conn_interval: %d", p_conn->max_conn_interval);
        NRF_LOG_DEBUG("min_conn_interval: %d", p_conn->min_conn_interval);
        NRF_LOG_DEBUG("slave_latency: %d",     p_conn->slave_latency);
        NRF_LOG_DEBUG("conn_sup_timeout: %d",  p_conn->conn_sup_timeout);
    } break;

    Best regards

    Bjørn

  • Thanks for the additional info.  Added what you suggested, but it didn't help.

    After further investigation, I now believe the problem is caused by ESP32 (i.e. BLE client)'s request for "DH Key Check", which translates to BLE_GAP_EVT_LESC_DHKEY_REQUEST in nRF.  The process dies because nRF side didn't respond to this DH Key request.

    A few questions:

    1. Am I supposed to handle the request explicitly myself?

    2. For comparison, I traced connection to the NRF using nRF connect from my iPhone.  It worked fine.  But strangely, I did not see any DHKEY Request during the handshake.  Why is it different?

    Based on the client about BLE_GAP_EVT_LESC_DHKEY_REQUEST, I found some code from one of the NFC examples that generates a reply to the DH Key request that look something like this:

            case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
            {
                // Buffer peer Public Key because ECC module arguments must be word aligned.
                memcpy(&m_lesc_peer_pk.pk[0],
                       &p_ble_evt->evt.gap_evt.params.lesc_dhkey_request.p_pk_peer->pk[0],
                       BLE_GAP_LESC_P256_PK_LEN);
    
                // Compute D-H key.
                err_code = ecc_p256_shared_secret_compute(&m_lesc_sk.pk[0],
                                                          &m_lesc_peer_pk.pk[0],
                                                          &m_lesc_dhkey.key[0]);
                APP_ERROR_CHECK(err_code);
    
                // Reply with obtained result.
                err_code = sd_ble_gap_lesc_dhkey_reply(m_conn_handle, &m_lesc_dhkey);
                APP_ERROR_CHECK(err_code);
            } break;

    However, I have yet to be able to try it yet, as it requires me to build the external micro-ecc library, which seems really complicated. It's getting late, I will probably try it more tomorrow.  But, before I sink more time into this, I want to make sure I am on the right track.

    Thanks,

    Joseph

  • Hi Joseph, 

    Q1:there is a LESC module in the nRF5x SDK v15.2.0 that handles the LESC events for you and is integrated in the PM manager. I recommend taking a look at at the Experimental: LE Secure Connections Multirole Example in the SDK. 

    Add nRF5_SDK_15.2.0_9412b96\components\ble\peer_manager\nrf_ble_lesc.c to your project and include #include "nrf_ble_lesc.h" in main.c

    You also need to set PM_LESC_ENABLED to 1 in sdk_config.h. If this isnt present in you sdk_config file, then simply add the following snippet to the Peer Manager section

    // <q> PM_LESC_ENABLED  - Enable/disable LESC support in Peer Manager.
     
    
    // <i> If set to true, you need to call nrf_ble_lesc_request_handler() in the main loop to respond to LESC-related BLE events. If LESC support is not required, set this to false to save code space.
    
    #ifndef PM_LESC_ENABLED
    #define PM_LESC_ENABLED 1
    #endif

    You also need to add nrf_ble_lesc_request_handler to the idle_state_handler() function in main.c

    static void idle_state_handle(void)
    {
        ret_code_t err_code;
        
        err_code = nrf_ble_lesc_request_handler();
        APP_ERROR_CHECK(err_code);
        
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    

    Q2: Could you attach the trace of the communication between your iPhone and the NRF52832? I would like to see if the pairing request sent from the iPhone sets the Secure Connection Flag. As stated previously both sides must state that they support LESC, otherwise the paring will be performed with the common denominator in terms of supported features. 

Related