This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Get NRF_ERROR_INVALID_PARAM for function sd_ble_gatts_characteristic_add() after setting BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM for notify type Characteristic

I'm using mbed+nRF51822+BLE_API+softdevice 7.1.0 for BLE peripheral side. I add uart service with the setting BLE_GAP_CONN_SEC_MODE_SET_OPEN which is open link, and set the permission for uart tx Characteristic as BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE and BLE_GATT_CHAR_PROPERTIES_WRITE, for uart rx Characteristic as BLE_GATT_CHAR_PROPERTIES_NOTIFY. They uuid is showed as below:

const LongUUIDBytes_t long_uuid = {0x6E, 0x40, 0x00, 0x01, 0xB5, 0xA3, 0xF3, 0x93,
								0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E};

const LongUUIDBytes_t long_uuid_tx = {0x6E, 0x40, 0x00, 0x02, 0xB5, 0xA3, 0xF3, 0x93,
								 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E};

const LongUUIDBytes_t long_uuid_rx = {0x6E, 0x40, 0x00, 0x03, 0xB5, 0xA3, 0xF3, 0x93,
								 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC, 0xCA, 0x9E};

With these settings, everything is fine. I can add uart service, tx and rx Characteristics successfully.

Then I want to use encryption, I change each BLE_GAP_CONN_SEC_MODE_SET_OPEN to BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM. Then I can add uart tx Characteristics successfully, but failed to add uart rx Characteristics !!! After debugging, I found the problem happens in the function custom_add_in_characteristic() in source file custom_helper.cpp. After change BLE_GAP_CONN_SEC_MODE_SET_OPEN to BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM in this function, the return value of calling function sd_ble_gatts_characteristic_add() in function custom_add_in_characteristic() is NRF_ERROR_INVALID_PARAM when adding uart rx characteristic. Then failed to add uart rx Characteristic. If I change BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM back to BLE_GAP_CONN_SEC_MODE_SET_OPEN, or change the permission for uart rx from BLE_GATT_CHAR_PROPERTIES_NOTIFY to BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE and BLE_GATT_CHAR_PROPERTIES_WRITE, then I can add uart rx Characteristics successfully.

Here is the code for function custom_add_in_characteristic():

error_t custom_add_in_characteristic (uint16_t    service_handle,
                                     ble_uuid_t *p_uuid,
                                     uint8_t     properties,
                                     uint8_t    *p_data,
                                     uint16_t    min_length,
                                     uint16_t    max_length,
                                     bool        readAuthorization,
                                     bool        writeAuthorization,
                                     ble_gatts_char_handles_t *p_char_handle)
{
    ble_gatts_attr_md_t   cccd_md;
    ble_gatt_char_props_t char_props;

    memcpy(&char_props, &properties, 1);

    if (char_props.notify || char_props.indicate) {
        /* Notification requires cccd */
        memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t));
        cccd_md.vloc = BLE_GATTS_VLOC_STACK;
        BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);
    }

    ble_gatts_char_md_t char_md = {0};

    char_md.char_props = char_props;
    char_md.p_cccd_md  =
        (char_props.notify || char_props.indicate) ? &cccd_md : NULL;

    /* Attribute declaration */
    ble_gatts_attr_md_t attr_md = {0};

    attr_md.rd_auth = readAuthorization;
    attr_md.wr_auth = writeAuthorization;

    attr_md.vloc = BLE_GATTS_VLOC_STACK;
    attr_md.vlen = (min_length == max_length) ? 0 : 1;

    if (char_props.read || char_props.notify || char_props.indicate) {
        BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm);
    }

    if (char_props.write || char_props.write_wo_resp) {
        BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm);
    }

    ble_gatts_attr_t attr_char_value = {0};

    attr_char_value.p_uuid    = p_uuid;
    attr_char_value.p_attr_md = &attr_md;
    attr_char_value.init_len  = min_length;
    attr_char_value.max_len   = max_length;
    attr_char_value.p_value   = p_data;

    ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle,
                                                    &char_md,
                                                    &attr_char_value,
                                                    p_char_handle));

    return ERROR_NONE;
}

So in summary looks like if using BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM for the Characteristics with permission BLE_GATT_CHAR_PROPERTIES_NOTIFY, adding Characteristics will be failed and get the return value NRF_ERROR_INVALID_PARAM for sd_ble_gatts_characteristic_add(). Anyone can help me on this problem?

  • Looks like for cccd I have to set cccd_md.read_perm to BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MIT, then it works. So I have to change the code as below: BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&cccd_md.write_perm);

    And also from the SDK document, I see the following description: Several restrictions apply to the parameters, such as matching permissions between the user description descriptor and the writeable auxiliaries bits, readable (no security) and writeable (selectable) CCCDs and SCCDs and valid presentation format values.

    Looks like read permission for CCCDs should not have security. But what's the reason for it?

  • The spec demands it. See Volume 3, Part G, Chapter 3.3.3.3 about CCCDs:

    "Authentication and authorization may be required by the server to write the configuration descriptor. The Client Characteristic Configuration declaration shall be readable and writable."

Related