This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2640: Successful pairing using LE Secure Connections Just Works but cannot read data

Part Number: CC2640

Hello,

We are testing the LE Secure Connections Just Works pairing. We have our BLE device CC2640 configured in peripheral role and connecting with a Pixel Smartphone running Android 9.0 and nRF Connect app.

Our configuration is as follows:

  • CCS 7.4.0
  • BLE Stack ble_sdk_2_02_02_25 (Version 2.2.2)
  • Compiler TI ARM Compiler v16.9.4 LTS
  • LE SC set to GAPBOND_SECURE_CONNECTION_ONLY
  • MITM set to false
  • IO Capabilities set to No Display No Keyboard

We have all our characteristics set with read and write authentication required setting, this means the moment we attempt a read using nRF Connect using the Smartphone, the pairing process begins. It seems the pairing process is successful and we even receive the corresponding callback from gapbondmgr passing a pairing success code for a pairing complete event.



However, the issue we are observing is that we cannot get any data at all from any characteristic after the pairing process is completed and the link encryption is started. We observe our peripheral device is sending a "Start Encryption Request" every time as a result for a reading request coming from the master.

In the following trace, the Bluetooth sniffer shows that the initial encryption process sequence is apparently incomplete. However, we know that this part of the pairing is handled entirely by the stack.We have also verified there are no heap memory allocation issues when this happens. Here is a screenshot of the trace right after the one shown above after sharing the keys and the checks were successful:



The warning sign for the "LLCP Encryption Start" row says "Incomplete Sequence". After the pairing process is over, we can see the "Encrypted Link Layer Traffic" packets. Then, every time a read attempt is executed using the nRF Connect app on the Smartphone, we observe the event shown in this picture at the bottom "LLCP Start Encryption Request". One per reading attempt. The Bluetooth sniffer shows a "No Request From Master" warning when this happens.

Is it possible that the stack actually missed something during the initial encryption start process and that's why the Bluetooth sniffer is giving an "Incomplete Sequence" warning and hence we cannot read any characteristics data at all?

Ricardo Bello

  • Hi Ricardo,

    Per the spec, during an LLCP Encryption start control procedure, the LLCP Start Encryption Response, which follows the Start Encryption Request will be encrypted. In order to decrypt this traffic, you can use the SC_HOST_DEBUG define described in the software users guide. This will enable code in the gapbondmgr to use link keys that are defined by the spec to be debug link keys. Ellisys traces will automatically see that the link keys are used and then proceed to decrypt all encrypted traffic.

    I would be interested to look at the rest of your ellisys trace though. You can attach the full file in the insert code attach files section below the comment box when typing a reply.
  • Hi Evan,

    I will check what you mention regarding the debug keys. In the meantime, here is the full Ellisys trace file assuming you can open it in its native format.

    CC2640 LE Secure Connections Just Works - Cannot Read Data.zip

    Regards,

    Ricardo Bello

  • Hi Ricardo,

    It's certainily got some strange behavior in your log. I presume that the CC2640 is the slave in the system? What is the master? Please let me know if you have more questions about using SC_HOST_DEBUG. I'm happy to help.

    To give you some context on where in the spec I was referencing earlier in my post, you can study BLE Spec 4.2 Vol 6, Part B Section 5.1.3 for more info in the Encryption Procedure. The good news is it looks like you have a successful session, but start encryption request is strange. I'd like to see what it looks like with the SC_HOST_DEBUG enabled so we can see what's going on in the encrypted traffic. I wonder if you have a characteristic that is only readable with authentication (which is not performed when using a just works pairing method). Do you have any protections around your characteristics?
  • Evan,

    Our CC2640 is configured in peripheral role and acting as the slave in this scenario. The master device is a Pixel Smartphone running Android Pie 9.0 with latest patches acting as the master.

    We have 14 characteristics in our custom profile. Some are read only, some are read/write and some support notifications in addition to be readable and/or writable. The values of all of them are protected with GATT_PERMIT_AUTHEN_READ, GATT_PERMIT_AUTHEN_WRITE or both accordingly.

    Enabling the macro SC_HOST_DEBUG was not enough to use the debug keys.  When I tried again the connection after defining the SC_HOST_DEBUG macro I did not see the debug keys in the Bluetooth link. After checking the code, I observed that I had to edit gapbongmgr.c in order to actually pass the debug keys to the stack:

    Macro added to gapbondmgr.c (original code as is from Stack 2.2.2 on the left and modification on the right)

    Debug key observed in sniffer only after the change:

    As you mentioned, the Ellisys sniffer is now showing more information about the encryption process and when a reading request is executed from nRF connect app using the Android smartphone. 

    Attached please find the trace log under this scenario.CC2640 LE Secure Connections Just Works - Cannot Read Data - Debug Keys.zip

    Ricardo Bello

  • Hi Ricardo,

    I think that i know your problem. You have all your characteristics protected by GATT_PERMIT_AUTHEN_READ/WRITE but a just works pairing is not enough security to provide Authentication. Please view BLE Spec 4.2 Vol 3 Part H Section 2.3.5.1 Selecting Key Generation Method to look at what various levels of IO Cap between the initiator and the responder give an Authenticated session. That or change your characteristics to use GATT_PERMIT_ENCRYPT_READ/WRITE.

    When you try to read the characteristics that only allow authenticated read/writes, the device will respond with insufficient authentication and will request the other device have a higher level encryption hence why you always see LLCP Encryption Start control procedures being sent. This will all be resolved by either using GATT_PERMIT_ENCRYPT_READ/WRITE or making sure you set your IO Cap and MITM appropriately to permit an authenticated session.
  • Hi Evan,

    I also thought of this, so I went ahead and changed all GATT_PERMIT_AUTHEN_READ and GATT_PERMIT_AUTHEN_WRITE to GATT_PERMIT_ENCRYPT_READ and GATT_PERMIT_ENCRYPT_WRITE accordingly.

    However, even after this change, we are observing the same behavior. Data readings are still not possible and for every reading attempt an LLCP Start Encryption Request is observed just as before.

    Here is the trace log in this case:

    CC2640 LE Secure Connections Just Works - Cannot Read Data - Permit_Encrypt.zip

    Was this behavior expected? "Just Works" is suppose to encrypt the link though in this case there is no authentication, correct? 

    Regards

    Ricardo Bello

    PS. We just tested with GATT_PERMIT_AUTHOR_READ and GATT_PERMIT_AUTHOR_WRITE with the same failed result.

  • Hi Ricardo,

    GATT_PERMIT_AUTHOR_READ or WRITE are not going to work because that requires Authorization which is an additional level of application security that is defined by the application. Authorization is done on top of Authentication.

    In the log you've provided that ends with Cannot Read Data - Permit_Encrypt.zip" you have the following.

    The initiating device supports Keyboard Display, Bonding, MITM = true, and LESC is enabled.

    The responder supports No input no output, No bonding, MITM = false, and LESC is enabled.

    Therefore, a just works pairing session will occur.

    The devices successfully encrypt a session and begin service discovery.

    At some point, when an ATT read request packet is sent by the Samsung phone, an ATT error response packet is generated with insufficient authentication set.

    Because this is sent to the phone, the phone responds by trying to restart encryption.

    This leads me to suspect something is still wrong in your setup for your characteristics. Can you attach your code for one of the characteristics?

  • Hi Evan,

    We have 14 characteristics in our service table. Just to let you know, without any link encryption, we have no issues and we can read and write data to our characteristics and notifications are sent as expected.

    The following is a snippet of the first 2 characteristics:

    /*----------- Characteristic 1: -----------*/
    /* UUID */
    static const uint8 g_char_ble_char_01_uuid[ UUID_SIZE ] =
    {
    SERVICE_BLE_CHAR_01_UUID ,
    };

    /* Properties */
    static uint8 g_char_ble_char_01_properties = (uint8)GATT_PROP_READ | (uint8)GATT_PROP_WRITE;

    /* Value */
    static uint8 g_char_ble_char_01_value[ SERVICE_BLE_DATA_CHAR_01_LEN ] =
    {
    0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu
    };

    /*----------- Characteristic 2: -----------*/
    /* UUID */
    static const uint8 g_char_ble_char_02_uuid[ UUID_SIZE ] =
    {
    SERVICE_BLE_CHAR_02_UUID ,
    };

    /* Properties */
    static uint8 g_char_ble_char_02_properties = (uint8)GATT_PROP_READ | (uint8)GATT_PROP_NOTIFY;

    /* Value */
    static uint8 g_char_ble_char_02_value[SERVICE_BLE_DATA_RSP_CHAR_LEN ] =
    {
    0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu, 0xFFu
    };

    /* Configuration */
    static gattCharCfg_t *p_char_ble_char_02_config;

    /* ... more characteristics ... */

    /*********************************************************************
    * Profile Attributes - Table
    */
    static gattAttribute_t service_table[] =
    {
    /* Profile Primary Service 0x2800 */
    {
    { (uint8)ATT_BT_UUID_SIZE, &primaryServiceUUID[0] }, /* type */
    (uint8)GATT_PERMIT_READ, /* permissions */
    0u, /* handle */
    (uint8 *)&g_profile_primary_service /* pValue */
    },

    /* Characteristic 1: Declaration 0x2803 */
    {
    { (uint8)ATT_BT_UUID_SIZE, &characterUUID[0] },
    (uint8)((uint8)GATT_PERMIT_READ | (uint8)GATT_PERMIT_WRITE),
    0u,
    &g_char_ble_char_01_properties
    },

    /* Characteristic 1: Value */
    {
    { (uint8)UUID_SIZE, &g_char_ble_char_01_uuid[0] },
    (uint8)((uint8)GATT_PERMIT_ENCRYPT_READ | (uint8)GATT_PERMIT_ENCRYPT_WRITE),
    0u,
    g_char_ble_char_01_value
    },

    /* Characteristic 2: Declaration (0x2803) */
    {
    { (uint8)ATT_BT_UUID_SIZE, &characterUUID[0] },
    (uint8)((uint8)GATT_PERMIT_READ | (uint8)GATT_PERMIT_WRITE),
    0u,
    &g_char_ble_char_02_properties
    },

    /* Characteristic 2: Value */
    {
    { (uint8)UUID_SIZE, &g_char_ble_char_02_uuid[0] },
    (uint8)GATT_PERMIT_ENCRYPT_READ,
    0u,
    g_char_ble_char_02_value
    },

    /* Characteristic 2: Client Characteristic Configuration (0x2902) */
    {
    { ATT_BT_UUID_SIZE, &clientCharCfgUUID[0] },
    (uint8)((uint8)GATT_PERMIT_READ | (uint8)GATT_PERMIT_WRITE),
    0,
    (uint8 *)&p_char_ble_char_02_config
    },

    /* ... more characteristics ... */

    };

    The UUID macros expand to 16 bytes values. Please let me know if more details are needed.

    Ricardo Bello
  • Hi Evan,

    Do you have any comment on this?

    Ricardo Bello

  • Ricardo,

    I have not had a chance to review this. My apologies. I will provide a response by Monday next week.
  • Hi Ricardo,

    In your gapbondmgr.c file, what have you set the GAPBOND_SECURE_CONNECTION to? i.e. GAPBOND_SECURE_CONNECTION_ONLY, GAPBOND_SECURE_CONNECTION etc?
  • My guess is that you have GAPBOND_SECURE_CONNECTION_ONLY set. According to the BLE Spec 5.0 Vol 3 Part C Section 10.2.4 when using Secure Connections Only Mode only security mode 1 level 4 (Authenticated LE Secure Connections pairing with encryption using a 128-
    bit strength encryption key) shall be used except for services that only require security mode 1 level 1 (No security (No authentication and no encryption).

    Since you are using just works and LE Secure Connection Only, you will not have an authenticated connection and therefore the stack will reject your request.

    If you change it to GAPBOND_SECURE_CONNECTIONS I believe you will be able to read it properly. 

  • I will check and let you know if this solves the issue. Thanks for the reply.