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.

CC2642R: Link layer encryption

Part Number: CC2642R
Other Parts Discussed in Thread: CC2652R

Dear All

I'm trying to encrypt the link layer using a CC2642R, based on a multi role project, without success so far.

As mentioned in my previous post https://e2e.ti.com/support/wireless-connectivity/bluetooth/f/bluetooth-forum/982882/cc2642r-how-to-check-the-link-layer-is-encrypted?tisearch=e2e-sitesearch&keymatch=%252520user%25253A16043#, 

I modified the services and characteristics declarations, by replacing GATT_PERMIT_READ | GATT_PERMIT_WRITE with GATT_PERMIT_ENCRYPT_READ | GATT_PERMIT_ENCRYPT_WRITE.
But this does not seem to encrypt the link layer.

To check if the link is encrypted, I proceeded as follow :

- Use Btool to connect to my device
- Once connected, I read all chars description to find characteristics handles
- I then enabled notifications on my device by writing 01:00 to the characteristics handle
- When sending data (MIDI over BLE) from my device (Note ON: 90:58:40, then Note OFF: 80:58:00), I can see them in btool, but they are NOT encrypted: 

------------------------------------------------------------------------------------------------------------------------
[51] : <Rx> - 10:08:37.255
-Type : 0x04 (Event)
-EventCode : 0xFF (HCI_LE_ExtEvent)
-Data Length : 0x10 (16) bytes(s)
 Event : 0x051B (ATT_HandleValueNotification)
 Status : 0x00 (Success)
 ConnHandle : 0x0000 (0)
 PduLen : 0x0A (10)
 Handle : 0x0017 (23)
 Value : 00:00:FF:FF:09:90:58:40
Dump(Rx):
04 FF 10 1B 05 00 00 00 0A 17 00 00 00 FF FF 09 
90 58 40 
------------------------------------------------------------------------------------------------------------------------
[52] : <Rx> - 10:08:37.348
-Type : 0x04 (Event)
-EventCode : 0xFF (HCI_LE_ExtEvent)
-Data Length : 0x10 (16) bytes(s)
 Event : 0x051B (ATT_HandleValueNotification)
 Status : 0x00 (Success)
 ConnHandle : 0x0000 (0)
 PduLen : 0x0A (10)
 Handle : 0x0017 (23)
 Value : 01:00:FF:FF:08:80:58:00
Dump(Rx):
04 FF 10 1B 05 00 00 00 0A 17 00 01 00 FF FF 08 
80 58 00 

Please note I previously erased all bounds in the device, and I did not pair nor bound to the device, I only connected btool central to my peripheral.
I also tried to send notifications with the third parameter as 0x02 (Secure Connections authenticated) instead of 0x00 

GATT_Notification(handle, &noti, 0x02)

This does not result in an encrypted layer.

What am I missing here ?
Thanks
Jerome





  • Hi Jerome,

    I have assigned an expert to help you with your query. In the meantime, you may find the the SLA BLE Security Fundamentals course helpful. It covers how to add an encrypted characteristic. Can you provide us with which SDK version you are using?

    Sincerely,

    Jan

  • I already read this chapter.
    I'm using latest SDK simplelink_cc13x2_26x2_sdk_4_40_00_44, latest CCS.
    Thanks

  • Jerome,

    Quite interesting development. From the previous thread we worked, you could see the error message on the Btool app whenever I had an encrypted characteristic on an unbonded host.

    In this case, please check attached project I used, which includes the <simple_gatt_profile.c> I modified to add the encryption to the specific characteristics. You can try an example code by simply dropping the file in the subdirectory "Profiles" of a simple_peripheral project.

    I will try to check if there are any additional aspects I may be missing and report back in case I find anything relevant.

    Hope this helps,

    Rafael

    (sorry about the wall of text; I couldn't attach the .c file)

    /******************************************************************************
    
     @file  simple_gatt_profile.c
    
     @brief This file contains the Simple GATT profile sample GATT service profile
            for use with the BLE sample application.
    
     Group: WCS, BTS
     Target Device: cc13x2_26x2
    
     ******************************************************************************
     
     Copyright (c) 2010-2021, Texas Instruments Incorporated
     All rights reserved.
    
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions
     are met:
    
     *  Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
    
     *  Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
    
     *  Neither the name of Texas Instruments Incorporated nor the names of
        its contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
     ******************************************************************************
     
     
     *****************************************************************************/
    
    /*********************************************************************
     * INCLUDES
     */
    #include <string.h>
    #include <icall.h>
    #include "util.h"
    /* This Header file contains all BLE API and icall structure definition */
    #include "icall_ble_api.h"
    
    #include "simple_gatt_profile.h"
    
    #ifdef SYSCFG
    #include "ti_ble_config.h"
    
    #ifdef USE_GATT_BUILDER
    #include "ble_gatt_service.h"
    #endif
    
    #endif
    
    /*********************************************************************
     * MACROS
     */
    
    /*********************************************************************
     * CONSTANTS
     */
    #ifndef USE_GATT_BUILDER
    
    #define SERVAPP_NUM_ATTR_SUPPORTED        17
    
    /*********************************************************************
     * TYPEDEFS
     */
    
    /*********************************************************************
     * GLOBAL VARIABLES
     */
    // Simple GATT Profile Service UUID: 0xFFF0
    CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
    };
    
    // Characteristic 1 UUID: 0xFFF1
    CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)
    };
    
    // Characteristic 2 UUID: 0xFFF2
    CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)
    };
    
    // Characteristic 3 UUID: 0xFFF3
    CONST uint8 simpleProfilechar3UUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID)
    };
    
    // Characteristic 4 UUID: 0xFFF4
    CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)
    };
    
    // Characteristic 5 UUID: 0xFFF5
    CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] =
    {
      LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)
    };
    
    /*********************************************************************
     * EXTERNAL VARIABLES
     */
    
    /*********************************************************************
     * EXTERNAL FUNCTIONS
     */
    
    /*********************************************************************
     * LOCAL VARIABLES
     */
    
    static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;
    
    /*********************************************************************
     * Profile Attributes - variables
     */
    
    // Simple Profile Service attribute
    static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };
    
    
    // Simple Profile Characteristic 1 Properties
    static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE;
    
    // Characteristic 1 Value
    static uint8 simpleProfileChar1 = 0;
    
    // Simple Profile Characteristic 1 User Description
    static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";
    
    
    // Simple Profile Characteristic 2 Properties
    static uint8 simpleProfileChar2Props = GATT_PROP_READ;
    
    // Characteristic 2 Value
    static uint8 simpleProfileChar2 = 0;
    
    // Simple Profile Characteristic 2 User Description
    static uint8 simpleProfileChar2UserDesp[17] = "Characteristic 2";
    
    
    // Simple Profile Characteristic 3 Properties
    static uint8 simpleProfileChar3Props = GATT_PROP_WRITE;
    
    // Characteristic 3 Value
    static uint8 simpleProfileChar3 = 0;
    
    // Simple Profile Characteristic 3 User Description
    static uint8 simpleProfileChar3UserDesp[17] = "Characteristic 3";
    
    
    // Simple Profile Characteristic 4 Properties
    static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY;
    
    // Characteristic 4 Value
    static uint8 simpleProfileChar4 = 0;
    
    // Simple Profile Characteristic 4 Configuration Each client has its own
    // instantiation of the Client Characteristic Configuration. Reads of the
    // Client Characteristic Configuration only shows the configuration for
    // that client and writes only affect the configuration of that client.
    static gattCharCfg_t *simpleProfileChar4Config;
    
    // Simple Profile Characteristic 4 User Description
    static uint8 simpleProfileChar4UserDesp[17] = "Characteristic 4";
    
    
    // Simple Profile Characteristic 5 Properties
    static uint8 simpleProfileChar5Props = GATT_PROP_READ;
    
    // Characteristic 5 Value
    static uint8 simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = { 0, 0, 0, 0, 0 };
    
    // Simple Profile Characteristic 5 User Description
    static uint8 simpleProfileChar5UserDesp[17] = "Characteristic 5";
    
    /*********************************************************************
     * Profile Attributes - Table
     */
    
    static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
    {
      // Simple Profile Service
      {
        { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
        GATT_PERMIT_ENCRYPT_READ,                         /* permissions */
        0,                                        /* handle */
        (uint8 *)&simpleProfileService            /* pValue */
      },
    
        // Characteristic 1 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar1Props
        },
    
          // Characteristic Value 1
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            &simpleProfileChar1
          },
    
          // Characteristic 1 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar1UserDesp
          },
    
        // Characteristic 2 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar2Props
        },
    
          // Characteristic Value 2
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar2UUID },
            GATT_PERMIT_ENCRYPT_READ,
            0,
            &simpleProfileChar2
          },
    
          // Characteristic 2 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_ENCRYPT_READ,
            0,
            simpleProfileChar2UserDesp
          },
    
        // Characteristic 3 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar3Props
        },
    
          // Characteristic Value 3
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar3UUID },
            GATT_PERMIT_WRITE,
            0,
            &simpleProfileChar3
          },
    
          // Characteristic 3 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar3UserDesp
          },
    
        // Characteristic 4 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar4Props
        },
    
          // Characteristic Value 4
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
            0,
            0,
            &simpleProfileChar4
          },
    
          // Characteristic 4 configuration
          {
            { ATT_BT_UUID_SIZE, clientCharCfgUUID },
            GATT_PERMIT_READ | GATT_PERMIT_WRITE,
            0,
            (uint8 *)&simpleProfileChar4Config
          },
    
          // Characteristic 4 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar4UserDesp
          },
    
        // Characteristic 5 Declaration
        {
          { ATT_BT_UUID_SIZE, characterUUID },
          GATT_PERMIT_READ,
          0,
          &simpleProfileChar5Props
        },
    
          // Characteristic Value 5
          {
            { ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
            GATT_PERMIT_AUTHEN_READ,
            0,
            simpleProfileChar5
          },
    
          // Characteristic 5 User Description
          {
            { ATT_BT_UUID_SIZE, charUserDescUUID },
            GATT_PERMIT_READ,
            0,
            simpleProfileChar5UserDesp
          },
    };
    #endif // USE_GATT_BUILDER
    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                              gattAttribute_t *pAttr,
                                              uint8_t *pValue, uint16_t *pLen,
                                              uint16_t offset, uint16_t maxLen,
                                              uint8_t method);
    bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                               gattAttribute_t *pAttr,
                                               uint8_t *pValue, uint16_t len,
                                               uint16_t offset, uint8_t method);
    #ifndef USE_GATT_BUILDER
    /*********************************************************************
     * PROFILE CALLBACKS
     */
    
    // Simple Profile Service Callbacks
    // Note: When an operation on a characteristic requires authorization and
    // pfnAuthorizeAttrCB is not defined for that characteristic's service, the
    // Stack will report a status of ATT_ERR_UNLIKELY to the client.  When an
    // operation on a characteristic requires authorization the Stack will call
    // pfnAuthorizeAttrCB to check a client's authorization prior to calling
    // pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
    // made within these functions.
    CONST gattServiceCBs_t simpleProfileCBs =
    {
      simpleProfile_ReadAttrCB,  // Read callback function pointer
      simpleProfile_WriteAttrCB, // Write callback function pointer
      NULL                       // Authorization callback function pointer
    };
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SimpleProfile_AddService
     *
     * @brief   Initializes the Simple Profile service by registering
     *          GATT attributes with the GATT server.
     *
     * @param   services - services to add. This is a bit map and can
     *                     contain more than one service.
     *
     * @return  Success or Failure
     */
    bStatus_t SimpleProfile_AddService( uint32 services )
    {
      uint8 status;
    
      // Allocate Client Characteristic Configuration table
      simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
                                                                MAX_NUM_BLE_CONNS );
      if ( simpleProfileChar4Config == NULL )
      {
        return ( bleMemAllocError );
      }
    
      // Initialize Client Characteristic Configuration attributes
      GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar4Config );
    
      if ( services & SIMPLEPROFILE_SERVICE )
      {
        // Register GATT attribute list and CBs with GATT Server App
        status = GATTServApp_RegisterService( simpleProfileAttrTbl,
                                              GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                              GATT_MAX_ENCRYPT_KEY_SIZE,
                                              &simpleProfileCBs );
      }
      else
      {
        status = SUCCESS;
      }
    
      return ( status );
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_RegisterAppCBs
     *
     * @brief   Registers the application callback function. Only call
     *          this function once.
     *
     * @param   callbacks - pointer to application callbacks.
     *
     * @return  SUCCESS or bleAlreadyInRequestedMode
     */
    bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
    {
      if ( appCallbacks )
      {
        simpleProfile_AppCBs = appCallbacks;
    
        return ( SUCCESS );
      }
      else
      {
        return ( bleAlreadyInRequestedMode );
      }
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_SetParameter
     *
     * @brief   Set a Simple Profile parameter.
     *
     * @param   param - Profile parameter ID
     * @param   len - length of data to write
     * @param   value - pointer to data to write.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     *
     * @return  bStatus_t
     */
    bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case SIMPLEPROFILE_CHAR1:
          if ( len == sizeof ( uint8 ) )
          {
            simpleProfileChar1 = *((uint8*)value);
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        case SIMPLEPROFILE_CHAR2:
          if ( len == sizeof ( uint8 ) )
          {
            simpleProfileChar2 = *((uint8*)value);
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        case SIMPLEPROFILE_CHAR3:
          if ( len == sizeof ( uint8 ) )
          {
            simpleProfileChar3 = *((uint8*)value);
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        case SIMPLEPROFILE_CHAR4:
          if ( len == sizeof ( uint8 ) )
          {
            simpleProfileChar4 = *((uint8*)value);
    
            // See if Notification has been enabled
            GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE,
                                        simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                        INVALID_TASK_ID, simpleProfile_ReadAttrCB );
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        case SIMPLEPROFILE_CHAR5:
          if ( len == SIMPLEPROFILE_CHAR5_LEN )
          {
            VOID memcpy( simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN );
          }
          else
          {
            ret = bleInvalidRange;
          }
          break;
    
        default:
          ret = INVALIDPARAMETER;
          break;
      }
    
      return ( ret );
    }
    
    /*********************************************************************
     * @fn      SimpleProfile_GetParameter
     *
     * @brief   Get a Simple Profile parameter.
     *
     * @param   param - Profile parameter ID
     * @param   value - pointer to data to put.  This is dependent on
     *          the parameter ID and WILL be cast to the appropriate
     *          data type (example: data type of uint16 will be cast to
     *          uint16 pointer).
     *
     * @return  bStatus_t
     */
    bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
    {
      bStatus_t ret = SUCCESS;
      switch ( param )
      {
        case SIMPLEPROFILE_CHAR1:
          *((uint8*)value) = simpleProfileChar1;
          break;
    
        case SIMPLEPROFILE_CHAR2:
          *((uint8*)value) = simpleProfileChar2;
          break;
    
        case SIMPLEPROFILE_CHAR3:
          *((uint8*)value) = simpleProfileChar3;
          break;
    
        case SIMPLEPROFILE_CHAR4:
          *((uint8*)value) = simpleProfileChar4;
          break;
    
        case SIMPLEPROFILE_CHAR5:
          VOID memcpy( value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN );
          break;
    
        default:
          ret = INVALIDPARAMETER;
          break;
      }
    
      return ( ret );
    }
    #endif // USE_GATT_BUILDER
    /*********************************************************************
     * @fn          simpleProfile_ReadAttrCB
     *
     * @brief       Read an attribute.
     *
     * @param       connHandle - connection message was received on
     * @param       pAttr - pointer to attribute
     * @param       pValue - pointer to data to be read
     * @param       pLen - length of data to be read
     * @param       offset - offset of the first octet to be read
     * @param       maxLen - maximum length of data to be read
     * @param       method - type of read message
     *
     * @return      SUCCESS, blePending or Failure
     */
    bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                        gattAttribute_t *pAttr,
                                        uint8_t *pValue, uint16_t *pLen,
                                        uint16_t offset, uint16_t maxLen,
                                        uint8_t method)
    {
      bStatus_t status = SUCCESS;
    
      // Make sure it's not a blob operation (no attributes in the profile are long)
      if ( offset > 0 )
      {
        return ( ATT_ERR_ATTR_NOT_LONG );
      }
    
      if ( pAttr->type.len == ATT_BT_UUID_SIZE )
      {
        // 16-bit UUID
        uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
        switch ( uuid )
        {
          // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
          // gattserverapp handles those reads
    
          // characteristics 1 and 2 have read permissions
          // characteritisc 3 does not have read permissions; therefore it is not
          //   included here
          // characteristic 4 does not have read permissions, but because it
          //   can be sent as a notification, it is included here
          case SIMPLEPROFILE_CHAR1_UUID:
          case SIMPLEPROFILE_CHAR2_UUID:
          case SIMPLEPROFILE_CHAR4_UUID:
            *pLen = 1;
            pValue[0] = *pAttr->pValue;
            break;
    
          case SIMPLEPROFILE_CHAR5_UUID:
            *pLen = SIMPLEPROFILE_CHAR5_LEN;
            VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN );
            break;
    
          default:
            // Should never get here! (characteristics 3 and 4 do not have read permissions)
            *pLen = 0;
            status = ATT_ERR_ATTR_NOT_FOUND;
            break;
        }
      }
      else
      {
        // 128-bit UUID
        *pLen = 0;
        status = ATT_ERR_INVALID_HANDLE;
      }
    
      return ( status );
    }
    
    /*********************************************************************
     * @fn      simpleProfile_WriteAttrCB
     *
     * @brief   Validate attribute data prior to a write operation
     *
     * @param   connHandle - connection message was received on
     * @param   pAttr - pointer to attribute
     * @param   pValue - pointer to data to be written
     * @param   len - length of data
     * @param   offset - offset of the first octet to be written
     * @param   method - type of write message
     *
     * @return  SUCCESS, blePending or Failure
     */
    bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                         gattAttribute_t *pAttr,
                                         uint8_t *pValue, uint16_t len,
                                         uint16_t offset, uint8_t method)
      {
      bStatus_t status = SUCCESS;
      uint8 notifyApp = 0xFF;
    
      if ( pAttr->type.len == ATT_BT_UUID_SIZE )
      {
        // 16-bit UUID
        uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
        switch ( uuid )
        {
          case SIMPLEPROFILE_CHAR1_UUID:
          case SIMPLEPROFILE_CHAR3_UUID:
    
            //Validate the value
            // Make sure it's not a blob oper
            if ( offset == 0 )
            {
              if ( len != 1 )
              {
                status = ATT_ERR_INVALID_VALUE_SIZE;
              }
            }
            else
            {
              status = ATT_ERR_ATTR_NOT_LONG;
            }
    
            //Write the value
            if ( status == SUCCESS )
            {
              uint8 *pCurValue = (uint8 *)pAttr->pValue;
              *pCurValue = pValue[0];
    
              if( pAttr->pValue == &simpleProfileChar1 )
              {
                notifyApp = SIMPLEPROFILE_CHAR1;
              }
              else
              {
                notifyApp = SIMPLEPROFILE_CHAR3;
              }
            }
    
            break;
    
          case GATT_CLIENT_CHAR_CFG_UUID:
            status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                     offset, GATT_CLIENT_CFG_NOTIFY );
            break;
    
          default:
            // Should never get here! (characteristics 2 and 4 do not have write permissions)
            status = ATT_ERR_ATTR_NOT_FOUND;
            break;
        }
      }
      else
      {
        // 128-bit UUID
        status = ATT_ERR_INVALID_HANDLE;
      }
    
      // If a characteristic value changed then callback function to notify application of change
      if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
      {
        simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
      }
    
      return ( status );
    }
    
    /*********************************************************************
    *********************************************************************/
    

  • Rafael


    Thanks for your answer, anyway, modifying the characteristics properties with GATT_PERMIT_ENCRYPT_READ and GATT_PERMIT_ENCRYPT_WRITE does not result in encrypted data when sending notifications from the peripheral.

    Again, using Btool, connecting without pairing/bounding, just enabling notifications from Btool, we can observe clear data from notifications sent by the peripheral. Nothing is encrypted, I can clearly see Notes on/off sent through MIDI over BLE.

    I think there is something else to do to send encrypted notifications, but what ?
    Thanks again for your time

    Jerome

  • Jerome,

    I retried with a standard simple_peripheral for the CC2652R launchpad and furnished with the encrypted characteristics. I got the same results as in the other thread - i.e., Btool correctly reports the insufficient authentication error for Characteristics 2 and 5.

    In this case, please check the attached project which contains my setup here - hopefully you can spot something that may be out of sync with your project.

    Hope this helps,

    Rafael

    simple_peripheral_CC26XR1_LAUNCHXL_tirtos_ccs_secure_char.zip