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

pm_conn_secure does NOT timeout when Central does not initiate bonding

Hello:

I have been at this problem for days now and not getting anywhere to a solution. My app is using  a static passkey for encryption and does timeout after 30 seconds if no key is received from the central when using the nRFconnect app as it should. Our central app uses BlueGiga dongle and BlueGiga has their own GUI app that can be used for testing. when using Bluegiga app and not enabling bonding, my app still connects and still transmits data and does NOT timeout and therefore bypassing the whole security feature. I know that the passkey is passed through the boding process but how can I force my app to disconnect if the central does not wanna bond? I am using SDK 15 and softdevice 6.00. any help would be greatly appreciated. 

Here is my peer manger init function

#define SEC_PARAM_BOND                  1                                           /**< Perform bonding. */
#define SEC_PARAM_MITM                  1                                           /**< Man In The Middle protection required (applicable when display module is detected). */
#define SEC_PARAM_LESC                  0                                           /**< LE Secure Connections enabled. */
#define SEC_PARAM_KEYPRESS              0                                           /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_DISPLAY_ONLY                /**< Display 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. */

I did try with SEC_PARAM_LESC set to 1 and made no difference.

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;

		static uint8_t passkey[] = "000000";
		
    static ble_opt_t m_ble_opt;
    m_ble_opt.gap_opt.passkey.p_passkey = &passkey[0];   
		
		err_code = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY,&m_ble_opt);
    APP_ERROR_CHECK(err_code);
		
    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);
}

static uint32_t standard_acquisition_char_add(ble_acq_mode_service_t * p_acq_mode_service, ble_acq_mode_service_init_t const * p_acq_mode_service_init)
{
    /**@snippet [Adding proprietary characteristic to the SoftDevice] */
		uint32_t            err_code;
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_md_t cccd_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;
	
		
		memset(&cccd_md, 0, sizeof(cccd_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);

    cccd_md.vloc = BLE_GATTS_VLOC_STACK;
	
		memset(&char_md, 0, sizeof(char_md));
		
		char_md.char_props.read 	= 1;
		char_md.char_props.write 	= 1;
    char_md.char_props.notify = 1;
    char_md.p_char_user_desc  = NULL;
    char_md.p_char_pf         = NULL;
    char_md.p_user_desc_md    = NULL;
		char_md.p_cccd_md         = &cccd_md;
    char_md.p_sccd_md         = NULL;
	
		memset(&attr_md, 0, sizeof(attr_md));
		
//		attr_md.read_perm  = p_acq_mode_service_init->acq_mode_service_value_char_attr_md.read_perm; 
//    attr_md.write_perm = p_acq_mode_service_init->acq_mode_service_value_char_attr_md.write_perm;

//    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
//    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
    
    BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&attr_md.write_perm);

		attr_md.vloc    = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth = 0;
    attr_md.wr_auth = 0;
    attr_md.vlen    = 1;
		
		ble_uuid.type = p_acq_mode_service->uuid_type;
    ble_uuid.uuid = BLE_UUID_STANDARD_FUNCTION_CHARACTERISTIC_UUID;
		
		memset(&attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid    = &ble_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = sizeof(uint8_t);
    attr_char_value.init_offs = 0;
    attr_char_value.max_len   = 20;
		
		err_code =  sd_ble_gatts_characteristic_add(p_acq_mode_service->service_handle,
                                           &char_md,
                                           &attr_char_value,
                                           &p_acq_mode_service->standard_char_handle );
		
		if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    return NRF_SUCCESS;

    /**@snippet [Adding proprietary characteristic to the SoftDevice] */
}

static void services_init(void)
{
    uint32_t           							err_code;
    nrf_ble_qwr_init_t 							qwr_init = {0};
		
		ble_acq_mode_service_init_t     acq_mode_service_init;
		ble_dfu_init_t 									dfus_init = {0};
		
		ble_dis_init_t     							dis_init;
    
		// Initialize Queued Write Module.
    qwr_init.error_handler = nrf_qwr_error_handler;

    err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
    APP_ERROR_CHECK(err_code);
    
		memset(&acq_mode_service_init, 0, sizeof(acq_mode_service_init));

		acq_mode_service_init.evt_handler = on_acq_mode_service_evt;

//		BLE_GAP_CONN_SEC_MODE_SET_OPEN(&acq_mode_service_init.acq_mode_service_value_char_attr_md.read_perm);
//		BLE_GAP_CONN_SEC_MODE_SET_OPEN(&acq_mode_service_init.acq_mode_service_value_char_attr_md.write_perm);
    
    BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM (&acq_mode_service_init.acq_mode_service_value_char_attr_md.read_perm);
		BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM (&acq_mode_service_init.acq_mode_service_value_char_attr_md.write_perm);
		
		err_code = ble_acq_mode_service_init(&m_acq_mode_service, &acq_mode_service_init);
    APP_ERROR_CHECK(err_code);
		
#ifndef DEBUG
    // Initialize the async SVCI interface to bootloader.
    err_code = ble_dfu_async_svci_init();
    APP_ERROR_CHECK(err_code);
#endif

    dfus_init.evt_handler = ble_dfu_evt_handler;

    err_code = ble_dfu_init(&dfus_init);
    APP_ERROR_CHECK(err_code);
		
		// Initialize Device Information Service.
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);

    ble_srv_ascii_to_utf8(&dis_init.serial_num_str, MODEL_NUMBER);

    ble_dis_sys_id_t system_id;
    system_id.manufacturer_id            = MANUFACTURER_ID;
    system_id.organizationally_unique_id = ORG_UNIQUE_ID;
    dis_init.p_sys_id                    = &system_id;

//    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dis_init.dis_attr_md.read_perm);
//    BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&dis_init.dis_attr_md.write_perm);
    
    BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dis_init.dis_attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dis_init.dis_attr_md.write_perm);

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);

}

Parents
  • Hi Wael, 

    In Bluetooth spec, there isn't a requirement of the link have to be encrypted after certain amount of time. What defined in the spec is that certain characteristics/services would requires the link to be encrypted at certain level so that the value of the attributes can be read/write. 

    In your case I assume you do have characteristics that require encryption ? And what you want to do is that on top of that requirement you also want to disconnect the central if the central doesn't do bonding at a certain time ? 

    If you want to do that, you would need to start a timer after the Connected event. And if after a certain time (30s for example) there isn't an event telling that the link is encrypted (BLE_GAP_EVT_CONN_SEC_UPDATE) the timer will timeout and disconnect the link. This should be done in the application. 

Reply
  • Hi Wael, 

    In Bluetooth spec, there isn't a requirement of the link have to be encrypted after certain amount of time. What defined in the spec is that certain characteristics/services would requires the link to be encrypted at certain level so that the value of the attributes can be read/write. 

    In your case I assume you do have characteristics that require encryption ? And what you want to do is that on top of that requirement you also want to disconnect the central if the central doesn't do bonding at a certain time ? 

    If you want to do that, you would need to start a timer after the Connected event. And if after a certain time (30s for example) there isn't an event telling that the link is encrypted (BLE_GAP_EVT_CONN_SEC_UPDATE) the timer will timeout and disconnect the link. This should be done in the application. 

Children
  • Hi Hung:

    I have implemented the timer and it seems to work as expected. But how do i prevent the central from reading my service characteristics during the 30 sec timer?  I am using BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM macro and it isn't working as expected. Again, Thanks for all your help!!

  • What do you mean by it isn't working as expected ? Please explain clearly if you give a statement. Also please give the code you used with that macro. 

     

  • Hi Hung:

    first off, thank you for your help!

    worked as expected means - I created a 20 second timer to check if I received the event BLE_GAP_EVT_CONN_SEC_UPDATE, if not; I disconnect the connection. 

    code I loaded show the use of the macro in the services_init and standard_acquisition_char_add functions. 

    since I'm setting the security on the service and characteristic, I would assume on the central side I would not be able to read the characteristic but yet I can prior to the timer expiring. if you need to see any other code, please let me know

    Thanks

  • Please post the code you used to declare the characteristics. 

    If you configure it correctly, the central shouldn't be able to read the content of the characteristics if the link is not encrypted with correct level. But the central can always read the attribute table meaning the structure of your attribute table, knowing if you have the characteristic or not. 

    If you don't want the central to know if you have the characteristics, you have to think of only declare the characteristic after you receive BLE_GAP_EVT_CONN_SEC_UPDATE. But this requires you to tell the central about service changed (send an indicator)  and the central have to do a service discovery again to get the new characteristic. 

  • I'm sorry Hung, what exactly are you looking for? the standard_acquisition_char_add function shows where I define the characteristic attribute and add it to the service. are you looking for the UUID defines?

    #define BLE_UUID_ACQ_MODE_SERVICE 											0x1400 /**< The UUID of the Acq. Mode Service. */
    
    #define BLE_UUID_IMU_CHARACTERISTIC_UUID								0x1401
    #define BLE_UUID_RAW_CDC_CHARACTERISTIC_UUID						0x1402
    #define BLE_UUID_STANDARD_FUNCTION_CHARACTERISTIC_UUID	0x1403 //0x1404
    #define BLE_UUID_ALL_MEASUREMENTS_CHARACTERISTIC_UUID		0x1404
    #define BLE_UUID_COMMAND_CHARACTERISTIC_UUID						0x1405

Related