security settings not working on custom descriptor or CCD

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I am unable to get the security settings working on any of the custom descriptors or CCD's. I have the security settings set to: Mode 1, Authenticated pairing with encription, No, Display, Bonding, 16. My project has the standard Generic Attribute-Service Changed-Configuration which cannot be read unless I enter the correct passkey when pairing. This does not apply to my custom service for which I have a CCD to transfer a value depending on which 1 of 4 buttons has been pressed. Notifications are set to disabled on both my custom and generic CCDs. In my custom descriptor I have set the write permissions to Encryption require and Authentication required (same as the generic CCD).

When I connect my device (Gap Peripheral, Gatt Server) to CySmart 1.2 I get the correct popup (Pairing request received from peer device) when clicking connect. If I click No then the device doesn't pair (all pairing info removed from CySmart), I can then discover all attributes. If I go to the generic CCD and try to write to it I get a message saying 'wrtie characteristic descriptor failed. Insufficient authentication'. If I do the same thing on my custom CCD it allows me to write to it.

The only things that I can see is different in ble component profile in PSoC Creator is that the permissions tick boxes in the generic CCD are greyed out whereas I can change them on my custom CCD. Also, the small round icons on my custom services, characteristics, and descriptors as light grey and the generic ones are dark grey.

I feel as though I must be missing something really simple here... If it helps I'm using a CY8C4127LQI-BL473 running through a CY8CKIT-042-BLE-A Pioneer baseboard

0 Likes
1 Solution
Anonymous
Not applicable

Peter,

You will have to implement the check for authentication in the application. The write to the CCCD is handled by the stack itself but a write to a custom characteristic should be handled by the application.

In the write request event, you will have to implement the check similar to what is shown below:

gattErr = CyBle_GattsWriteAttributeValue(&wrReqParam.handleValPair,0,&cyBle_connHandle,CYBLE_GATT_DB_PEER_INITIATED);

            if(gattErr == CYBLE_GATT_ERR_NONE)

            {

                                /* Send Write Response */

                CyBle_GattsWriteRsp(cyBle_connHandle);

            }

            else

            {

                err_param.opcode = (uint8) CYBLE_GATT_WRITE_REQ;

                err_param.attrHandle = wrReqParam.handleValPair.attrHandle;

                err_param.errorCode = gattErr;

                               /* Send Error Response */

                (void)CyBle_GattsErrorRsp(cyBle_connHandle, &err_param);

             }

Make sure that the last parameter of the Write Attribute API is CYBLE_GATT_DB_PEER_INITIATED, else the return value will always be ERR_NONE.

With the above implementation, if you try to write without pairing, then the client will receive an error response with 'Insufficient Authentication.

View solution in original post

6 Replies
Anonymous
Not applicable

Peter,

You will have to implement the check for authentication in the application. The write to the CCCD is handled by the stack itself but a write to a custom characteristic should be handled by the application.

In the write request event, you will have to implement the check similar to what is shown below:

gattErr = CyBle_GattsWriteAttributeValue(&wrReqParam.handleValPair,0,&cyBle_connHandle,CYBLE_GATT_DB_PEER_INITIATED);

            if(gattErr == CYBLE_GATT_ERR_NONE)

            {

                                /* Send Write Response */

                CyBle_GattsWriteRsp(cyBle_connHandle);

            }

            else

            {

                err_param.opcode = (uint8) CYBLE_GATT_WRITE_REQ;

                err_param.attrHandle = wrReqParam.handleValPair.attrHandle;

                err_param.errorCode = gattErr;

                               /* Send Error Response */

                (void)CyBle_GattsErrorRsp(cyBle_connHandle, &err_param);

             }

Make sure that the last parameter of the Write Attribute API is CYBLE_GATT_DB_PEER_INITIATED, else the return value will always be ERR_NONE.

With the above implementation, if you try to write without pairing, then the client will receive an error response with 'Insufficient Authentication.

Anonymous
Not applicable

Really appreciate the quick response. I did wonder if it was something that I would have to do manually. I had CYBLE_GATT_DB_LOCALLY_INITIATED set in the write attribute value API and wasn't checking for an error code.

0 Likes
Anonymous
Not applicable

I may have jumped the gun in saying this is answered...

checking the error message on the write attribute value api certainly works to stop write commands on my custom CCCD. However, what do you do for notifications? I have been currently using the following code to send a notification whenever 1 of the 4 buttons I mentioned earlier is pressed:

void ParseBLE_ServerMessage(uint8 ButtonValue)

{

    CYBLE_GATTS_HANDLE_VALUE_NTF_T buttonHandle;  

    buttonHandle.attrHandle = CYBLE_BUTTON_PRESS_BUTTON_NUMBER_CHAR_HANDLE;

    buttonHandle.value.val = (uint8 *) &ButtonValue;

    buttonHandle.value.len = 1; //length of value

        

    CyBle_GattsWriteAttributeValue(&buttonHandle, 0, &cyBle_connHandle,CYBLE_GATT_DB_LOCALLY_INITIATED);

    CyBle_GattsNotification(cyBle_connHandle, &buttonHandle);              

}

If I take the same approach as you have mentioned and switch to this code:

void ParseBLE_ServerMessage(uint8 ButtonValue)

{

    CYBLE_GATTS_HANDLE_VALUE_NTF_T buttonHandle;  

    CYBLE_GATT_ERR_CODE_T gattNotifErr;

    buttonHandle.attrHandle = CYBLE_BUTTON_PRESS_BUTTON_NUMBER_CHAR_HANDLE;

    buttonHandle.value.val = (uint8 *) &ButtonValue;

    buttonHandle.value.len = 1; //length of value

    

    gattNotifErr = CyBle_GattsWriteAttributeValue(&buttonHandle, 0, &cyBle_connHandle, CYBLE_GATT_DB_PEER_INITIATED);

    if (gattNotifErr == CYBLE_GATT_ERR_NONE)

        CyBle_GattsNotification(cyBle_connHandle, &buttonHandle);

                

}

When I check the gattNotifErr response I keep getting CYBLE_GATT_ERR_WRITE_NOT_PERMITTED irrespective of the whether the device is paired or not. Any ideas?

0 Likes
Anonymous
Not applicable

Notifications is a server-initiated procedure unlike the write which is a client-initiated. Notifications are completely under the control of the server. So you can send notification before pairing, after pairing since there are no restrictions on this.

With regard to your Write not permitted issue, why do you want to set the flag to PEER_INITIATED if you are pressing the button on the server? You should be setting it to LOCALLY_INITIATED.

Also, are you sure you have enabled 'write' property for the characteristic? If you have not enabled, you might be getting the CYBLE_GATT_ERR_WRITE_NOT_PERMITTED error.

0 Likes
Anonymous
Not applicable

Is there a standardized procedure for making sure notifications are not sent if pairing is not complete? I see that one way would be to block any notifications until CYBLE_EVT_GAP_AUTH_COMPLETE has been confirmed in the stack handler.

My initial intention was to get the client to enable notifications on the custom CCCD. However, I may as well set the custom CCCD to notifications enabled on the server if using pairing. Thanks for clearing up the write permissions flag, that was a lack of understanding on my behalf - the error I mentioned goes away with this set correctly.

0 Likes
Anonymous
Not applicable

You read/check the notification enabled flag of the corresponding CCCD before sending the notification. (That's the only standard I've seen so far). But, this is more of a "I want data" rather than a "security verified" flag. For checking that the pairing is complete, checking the CYBLE_EVT_GAP_AUTH_COMPLETE event is close enough I think. Possibly there is a flag somewhere (in the cypress code) to indicate if the unit has paired with the remote device or not?

Regards,

Epratt

0 Likes