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

How to force bonding?

-SDK: 15.0

-S132

-nRF52832

-Segger studio

I'm trying to implement bonding/whitelisting to my project, which is a connectable beacon with a custom service. What I want to create is that when the first device connects to my device it can be whitelisted with a single button press. After that, the device should ignore all other connection requests from other devices, unless the whitelisting is reset with another button press.

I've found this previous thread, which is not to old:

https://devzone.nordicsemi.com/f/nordic-q-a/36308/peer-manager-event-dispacthing---nrf52832-sdk-15-0-0/141375#141375

This describes the same issue I've got: the peermanager is never called and thus whitelisting is never done. In the previous thread the solution is to set a characteristic to require bonding. But how can this be done? How do I set the characteristic or attributes to require bonding?

I've used the ble_peripheral\ble_app_hids_keyboard example to implement whitelisting in my project, but without the peermanager being called whitelisting does not work.I've tried to run the ble_app_hids_keyboard example, but when I connect with nRF Connect on my smartphone (Samsung S5) the peermanager isn't called either.

Should I use a different client application instead of nRF Connect, is there a different method for whitelisting available or is there something else that I need to change?

Parents
  • I've found out that by setting the permission level of my custom characteristic with BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM to require encryption, the client is required to be bonded with my device in order to write to that specific characteristic. When I use nRF Connect this requires a write operation to an attribute in the characteristic for bonding to be initiated. Writing to the attributes works when bonded.

    However, the whitelisting I've implemented according to the ble_peripheral\ble_app_hids_keyboard example does not prevent another client (smartphone) from connecting with the device (I've increased the linkcount peripheral to 3 and restart advertising after connecting or disconnecting while the linkcount peripheral isn't reached). I could live with that, but the peermanager does not prevent the second client from bonding and accessing the "protected" characteristic while the BLE_GAP_WHITELIST_ADDR_MAX_COUNT is set to (1).

    So my main question remains:

    How do I prevent a second client from connecting or at least from bonding with the device when a previous device has been whitelisted?

  • Hello,

    Just to sum up:

    You want your beacon to be connectable, and have a characteristic that only bonded devices can use, right?

    I don't think you can "demand" bonding for a characteristic, but you can say that you need MITM protection, as you figured out.

    Just to keep things straight:

    Pairing is the exhange of encryption keys, which can be done both with and without MITM protection.

    Bonding is the storing of encryption keys (long term keys / ltk), to re-use for the next time they connect.

    If you demand MITM protection, then the device that wants to connect would need to know some shared secret, like a passkey that is either shown on a screen, or printed on a sticker on the device that it wants to pair with. Hence, it is not possible to access characteristics that are protected with MITM if you don't know this key.

    So you want only one device to be able to bond with the device, is that right?

    If that is correct, you can change from advertising with a connectable advertisement to advertising *just* as a beacon while you are in a connection. Do you still need other devices to be able to connect to it at this point in time? 

    When you disconnect, you can use the whitelist, which now consists of only one peer, in your advertisement settings, and it will only accept connection requests from this device. At least until it receives a button press to "open up" for new devices to bond with it as well.

    The ble_app_gls example is a good reference for BLE bonding with MITM. Check it out and see if you can re-use anything from there.

    Best regards,

    Edvin

Reply
  • Hello,

    Just to sum up:

    You want your beacon to be connectable, and have a characteristic that only bonded devices can use, right?

    I don't think you can "demand" bonding for a characteristic, but you can say that you need MITM protection, as you figured out.

    Just to keep things straight:

    Pairing is the exhange of encryption keys, which can be done both with and without MITM protection.

    Bonding is the storing of encryption keys (long term keys / ltk), to re-use for the next time they connect.

    If you demand MITM protection, then the device that wants to connect would need to know some shared secret, like a passkey that is either shown on a screen, or printed on a sticker on the device that it wants to pair with. Hence, it is not possible to access characteristics that are protected with MITM if you don't know this key.

    So you want only one device to be able to bond with the device, is that right?

    If that is correct, you can change from advertising with a connectable advertisement to advertising *just* as a beacon while you are in a connection. Do you still need other devices to be able to connect to it at this point in time? 

    When you disconnect, you can use the whitelist, which now consists of only one peer, in your advertisement settings, and it will only accept connection requests from this device. At least until it receives a button press to "open up" for new devices to bond with it as well.

    The ble_app_gls example is a good reference for BLE bonding with MITM. Check it out and see if you can re-use anything from there.

    Best regards,

    Edvin

Children
  • Hello Edvin,

    So you want only one device to be able to bond with the device, is that right?

    That is correct. Preferably it should whitelist on a button press and the whitelisting can be cleared on another button press.

    I've implemented the whitelisting according to the ble_peripheral\ble_app_hids_keyboard, but that doesn't work in my application, as the peer list is rejected by the peer manager in the function pm_device_identities_list_set with error code 12804/0x3204.

            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            {
                // Note: You should check on what kind of white list policy your application should use.
                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, add the peer to the whitelist if possible");
                    NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d",
                                   m_whitelist_peer_cnt,
                                   BLE_GAP_WHITELIST_ADDR_MAX_COUNT);
    
                    if (m_whitelist_peer_cnt < BLE_GAP_WHITELIST_ADDR_MAX_COUNT)
                    {
                        // Bonded to a new peer, add it to the whitelist.
                        m_whitelist_peers[m_whitelist_peer_cnt++] = m_peer_id;
    
                        // The whitelist has been modified, update it in the Peer Manager.
                        err_code = pm_device_identities_list_set(m_whitelist_peers, m_whitelist_peer_cnt);
    		            NRF_LOG_INFO("Peer list set err_code: %u/0x%04X", (uint32_t)err_code, (uint32_t)err_code);
                        if (err_code != NRF_ERROR_NOT_SUPPORTED)
                        {
                            APP_ERROR_CHECK(err_code);
                        }
    
                        err_code = pm_whitelist_set(m_whitelist_peers, m_whitelist_peer_cnt);
                        APP_ERROR_CHECK(err_code);
                    }
    		else
    		{
    		    NRF_LOG_INFO("Adding the peer was not possible, maximum peers reached");
    		}
                }
            } break;

    I do not require MITM protection, just whitelisting a single client as you describe in the following:

    When you disconnect, you can use the whitelist, which now consists of only one peer, in your advertisement settings, and it will only accept connection requests from this device. At least until it receives a button press to "open up" for new devices to bond with it as well.

    If it would be faster and easier for you, I could provide you my project's code if you set this ticket to private.

  • A small update

    I've found this thread regarding the error code BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE returned by pm_device_identities_list_set.

    https://devzone.nordicsemi.com/f/nordic-q-a/32674/simultaneous-central-peripheral-with-whitelist-only-used-in-one-role

    Where the OP had to disable scanning while doing peer operations to write the peer_list.

    In my code upon connect or disconnect I restart advertising to keep the beacon functionality for other unconnected devices (even if they can't connect due to whitelisting).

    After disabeling restarting the advertising on connect disconnect, the pm_device_identities_list_set returned 0. So the given m_whitelist_peers should now be rejecting other connections, but after connecting with my smartphone and bonding it doesn't reject my nRF52 sniffer which still can bond.

  • Error 0x3204 means BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE. See peer_manager.h line 304.

    You add the device to the whitelist while you are using the whitelist. Try to add this device to the whitelist before you start to advertise again. Alternatively, stop the advertisement before you add it, and restart advertising again after that.

    It should look something like:

            case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
            {
                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, add the peer to the whitelist if possible");
                    NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d",
                                   m_whitelist_peer_cnt + 1,
                                   BLE_GAP_WHITELIST_ADDR_MAX_COUNT);
                    // Note: You should check on what kind of white list policy your application should use.
    
                    if (m_whitelist_peer_cnt < BLE_GAP_WHITELIST_ADDR_MAX_COUNT)
                    {
                        sd_ble_gap_adv_stop(m_advertising.adv_handle); 
                        // m_advertising might have a different name. Look for the name in BLE_ADVERTISING_DEF(m_advertising) near the top of your main.c
                        
                        // Bonded to a new peer, add it to the whitelist.
                        m_whitelist_peers[m_whitelist_peer_cnt++] = m_peer_id;
    
                        // The whitelist has been modified, update it in the Peer Manager.
                        err_code = pm_device_identities_list_set(m_whitelist_peers, m_whitelist_peer_cnt);
                        if (err_code != NRF_ERROR_NOT_SUPPORTED)
                        {
                            APP_ERROR_CHECK(err_code);
                        }
                        NRF_LOG_INFO("whitelist set succeed");
                        advertising_start(false); //erase_bonds = false
                        
    
                        err_code = pm_whitelist_set(m_whitelist_peers, m_whitelist_peer_cnt);
                        APP_ERROR_CHECK(err_code);
                    }
                }
            } break;

    Best regards,

    Edvin

  • Thank you for your response,

    Finaly found the error after concluding that the PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event was working as intended. I had two advertising_init functions: advertising_init and advertising_beacon_init. I was using the latter.  advertising_init  was from when this application wasn't an iBeacon. After adding init.config.ble_adv_whitelist_enabled = true; to advertising_beacon_init, whitelisting worked.

    Your sugesstion of changing the beacon to unconnectable upon connecting is appealing, but I can't find the parameter I need to change from connectable to unconnectable and vice versa.

    From what I found and understood, I must change the connection configuration tag with the ble_advertising_conn_cfg_tag_set()  function (currently ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); ), but I can't find the sd_ble_cfg_set in the online documentation. Would you mind pointing me to the correct file for the right value?

    Thank you kindly in advance and for the previous support messages!

  • Hello,

    Depending on how the advertising is set up, this is done in different places in different examples.

    in the examples\ble_peripheral\ble_app_beacon, on line 190 (if not modified), it says:

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;

    meaning that it is not possible to connect to this device. In this example it is in advertising_init.

    I see that this option is handled in ble_advertising.c in most other examples.

    BR,

    Edvin

Related