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

nRF52832 BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM failed

Hi,

I got a problem that when I try to use BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM for characteristic.

As I follow the tutorial to create the custom service, when I changed "BLE_GAP_CONN_SEC_MODE_SET_OPEN" to "BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM" then the application run failed and show fatal error.

Is there any point that I miss it ? Or how to create the characteristic with encryption correctly ?

I used SDK v15 BTY.

Thanks.

Parents
  • Hi,

    Can you be more specific to what error you get? The simplest way to see where it fails and with what error code is to enable/define DEBUG and logging. Then you should see which file and line number the error is caught, and what the error code was.

  • Hi

    Sorry, the error code is 7.

    I follow the custom service to build my own service, but in this tutorial using the OPEN characteristic.

    But I want to use the encryption character, so follow the final step in Step6 in tutorial to set "BLE_GAP_CONN_SEC_MODE_SET_OPEN", and change it to "BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM"  in main.c, then I got the error.

  • I see. 7 is NRF_ERROR_INVALID_PARAM. From which function do you get that returned?

  • Hi 

    Sorry for the late reply, I was deal with another task.

    I got it when I called service init from main.c file.

    here's my code

    // In main.c
    static void btp_info_initiate(void) {
        ret_code_t     err_code;
        btp_info_init_t info_init;
    
        memset(&info_init, 0, sizeof(info_init));
    
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&info_init.btp_info_value_char_attr_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&info_init.btp_info_value_char_attr_md.write_perm);
    
        //BLE_GAP_CONN_SEC_MODE_SET_OPEN(&info_init.btp_info_value_char_attr_md.read_perm);
        //BLE_GAP_CONN_SEC_MODE_SET_OPEN(&info_init.btp_info_value_char_attr_md.write_perm);
    
        info_init.evt_handler = btp_info_evt;
    
        err_code = btp_info_init(&btp_info, &info_init);  // err_code return 7 on this line
        APP_ERROR_CHECK(err_code);
    }

    P.S This function will be call in service_init in main.c

    Then I trace with error, see the error code will return 7 when called btp_info_init function.

    // In cus_srv.c
    ret_code_t btp_info_init(btp_info_t * p_info, const btp_info_init_t * p_info_init) {
    
        if (p_info == NULL || p_info_init == NULL)
            return NRF_ERROR_NULL;
    
        ret_code_t err_code;
        ble_uuid_t ble_uuid;
    
        p_info->evt_handler = p_info_init->evt_handler;
        p_info->conn_handle = BLE_CONN_HANDLE_INVALID;
    
        // Add BTP Info Service UUID
        ble_uuid128_t base_uuid = {BTP_INFO_SERVICE_BASE};
        err_code = sd_ble_uuid_vs_add(&base_uuid, &p_info->uuid_type);
        VERIFY_SUCCESS(err_code);
    
        // Add BTP Info Service
        ble_uuid.type = p_info->uuid_type;
        ble_uuid.uuid = BTP_UUID_INFO_SERVICE;
    
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_info->service_handle);
        if(err_code != NRF_SUCCESS)
            return err_code;
        
        err_code = btp_info_trek_stat_char_add(p_info, p_info_init);
        VERIFY_SUCCESS(err_code);
    }

    And I keep trace into it, I see the error comes from btp_info_trek_stat_char_add function

    static uint32_t btp_info_trek_stat_char_add(btp_info_t * p_info, const btp_info_init_t * p_info_init) {
        ble_uuid_t          ble_uuid;
        ble_gatts_char_md_t char_md;
        ble_gatts_attr_md_t attr_md;
        ble_gatts_attr_t    attr_char_value;
    
        // The ble_gatts_char_md_t structure uses bit fields. So we reset the memory to zero.
        memset(&char_md, 0, sizeof(char_md));
    
        char_md.char_props.write = 0;
        char_md.char_props.read  = 1;
        char_md.char_props.notify = 1;
        char_md.p_char_pf = NULL;
        char_md.p_cccd_md = &attr_md;
        char_md.p_sccd_md = NULL;
        char_md.p_user_desc_md = NULL;
    
        memset(&attr_md, 0, sizeof(attr_md));
    
        attr_md.read_perm  = p_info_init->btp_info_value_char_attr_md.read_perm;
        attr_md.write_perm = p_info_init->btp_info_value_char_attr_md.write_perm;
        attr_md.vloc       = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth    = 0;
        attr_md.wr_auth    = 0;
        attr_md.vlen       = 0;
    
        uint32_t err_code;
        ble_uuid128_t base_uuid = BTP_INFO_TRACKING_STAT_BASE;
        ble_uuid.uuid = BTP_UUID_INFO_TRACKING_STAT;
        err_code = sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type);
        LOG_INFO("err_code: %d", err_code);
        APP_ERROR_CHECK(err_code);  
    
        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   = sizeof(uint8_t);
        //attr_char_value.p_value   = p_char_value;
    
        return sd_ble_gatts_characteristic_add(p_info->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_info->btp_info_trek_stat_handles);
    }

    And in final the error comes from the sd_ble_gatts_characteristic_add function.

    So is there something that I miss?

  • I see,

    So you get the NRF_ERROR_INVALID_PARAM return code from the call to sd_ble_gatts_characteristic_add(). From the API documentation, this indicate that

    Invalid parameter(s) supplied, service handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints.

    I do not immediately see the exact problem, though.

  • Dear

    I found that if my service have a Notify properties then this trouble will happen.

    Is the setting of Notify is not correct?

    Another question, when I used the BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM it should pop the requesting window to request the pairing / bonding on cell phone right?

    Right now I can't send / read the data without encryption, this is correct. But their won't pop up the requesting window.

    I used the nRF connect APP on cell phone with version 4.19.2, and test with OPPO R9s.

  • Hi,

    I do not see any reference to the CCCD in your code snippets. It is used for the client to enable or disable notification on the characteristic, so you must add it when you enable notification (set char_md.char_props.notify = 1;). This is covered in the Custom Service Tutorial.

    Regarding the second question regarding encryption, this depend on the behavior of the phone. For example, iOS will only automatically increase security (perform bonding) after it has attempted to read or write to a characteristic that required a higher security level. In this case, you should be able to trigger a pairing from nRF Connect manually. Also, the nRF can send a security request to the phone to initiate pairing at an earlier stage.

Reply
  • Hi,

    I do not see any reference to the CCCD in your code snippets. It is used for the client to enable or disable notification on the characteristic, so you must add it when you enable notification (set char_md.char_props.notify = 1;). This is covered in the Custom Service Tutorial.

    Regarding the second question regarding encryption, this depend on the behavior of the phone. For example, iOS will only automatically increase security (perform bonding) after it has attempted to read or write to a characteristic that required a higher security level. In this case, you should be able to trigger a pairing from nRF Connect manually. Also, the nRF can send a security request to the phone to initiate pairing at an earlier stage.

Children
  • Dear

    I do enable the notify to char_md struct (in line 22 in below code), I found some thing wrong with previous code, but after I modified it still have error.

    static uint32_t btp_info_trek_stat_char_add(btp_info_t * p_info, const btp_info_init_t * p_info_init) {
        ble_uuid_t          ble_uuid;
        ble_gatts_char_md_t char_md;
        ble_gatts_attr_md_t attr_md;
        ble_gatts_attr_md_t cccd_md;
        ble_gatts_attr_t    attr_char_value;
    
        // The ble_gatts_char_md_t structure uses bit fields. So we reset the memory to zero.
        memset(&char_md, 0, sizeof(char_md));
        memset(&attr_md, 0, sizeof(attr_md));
        memset(&cccd_md, 0, sizeof(cccd_md));
    
        // Read operation on Cccd should be possible without authentication
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
        cccd_md.read_perm  = p_info_init->btp_info_value_char_attr_md.read_perm;
        cccd_md.write_perm = p_info_init->btp_info_value_char_attr_md.write_perm;
        cccd_md.vloc       = BLE_GATTS_VLOC_STACK;
    
        char_md.char_props.write = 0;
        char_md.char_props.read  = 1;
        char_md.char_props.notify = 1;
        char_md.p_char_pf = NULL;
        char_md.p_cccd_md = &cccd_md;
        char_md.p_sccd_md = NULL;
        char_md.p_user_desc_md = NULL;
        
        // Characteristic Description
        static char desc[] = "Tracking State";
        char_md.p_char_user_desc = (uint8_t *)desc;
        char_md.char_user_desc_size = strlen(desc);
        char_md.char_user_desc_max_size = strlen(desc);
    
        attr_md.read_perm  = p_info_init->btp_info_value_char_attr_md.read_perm; //dis_attr_md->read_perm;
        attr_md.write_perm = p_info_init->btp_info_value_char_attr_md.write_perm; //dis_attr_md->write_perm;
        attr_md.vloc       = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth    = 0;
        attr_md.wr_auth    = 0;
        attr_md.vlen       = 0;
    
        uint32_t            err_code;
        ble_uuid128_t       base_uuid = BTP_INFO_TRACKING_STAT_BASE;
        ble_uuid.uuid      = BTP_UUID_INFO_TRACKING_STAT;
        err_code = sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type);
        APP_ERROR_CHECK(err_code);  
    
        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   = sizeof(uint8_t);
        //attr_char_value.p_value   = p_char_value;
    
        return sd_ble_gatts_characteristic_add(p_info->service_handle, &char_md,
                                               &attr_char_value,
                                               &p_info->btp_info_trek_stat_handles);
    }

    Got it with second answer, thanks.

  • Hi,

    I found the problem is because the cccd_md.read_perm level is not 1 (open).

    In my code I set it as 1 (open level) first (line 14 in my previous reply), but then I set it as level 2 (encryption level) on line 16 that pass from main->service_init function.

    So the final cccd_md.read_perm level is 2, then the application will crash.

    Now the problem seems been fixed, but I'm not sure is the cccd read permission only can set as OPEN level? please help to answer it.

    Thanks.

  • Hi,

    You are correct. The read permissions must be open for notifications/indications. This makes sense, as you can require an encrypted link in order to write to the CCCD to enable notifications, as described in this post.

Related