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.

Encryption in rfWSN example cc1310

Other Parts Discussed in Thread: CC1310


I'm building a wireless sensor application using the rfWSn example. I've managed to encrypt and decrypt my data portion of the packet. Now i want to extend the encryption and secure the whole packet (including header). Can anyone point me to where i have to insert my crypto function?

As of now, i encrypt the wohle package that is written to the txBuffer on the tx side, but on the rxSide there doesn't seem to be an rxBuffer, so i decrypt pDataEntry->data, but that doesn't work.

Maybe anybody has done some encryption on the rfWSN example and can help me out.

I'm using CC1310 and Ti RTOS

  • Hi, in addition to the link you referred to, I suggest that you read through the installed TI-RTOS documentation as well. There are some code user cases/code snippets which you can familiarize yourself with.

    On my PC its located here:
  • Hi FredG,

    i already checked the documentation you mentioned, which shows how to setup and use the hardware AES unit. This procedure is clear enough for me to en/decrypt blocks of data, which is working fine.

    My question is about where to perform this operations in the sequence of radio / packet related functions in the rfWSN example if i want to not only encrypt my data, but the whole package including header and ACK.

    Best regards,
  • Hi Sebastian,

    you usually encrypt only the payload and create an encrypted fingerprint of the header (message authentication code, MAC). I suggest to use CBC-MAC + AES. Here is an excerpt from the Crypto driver documentation that will be part of the next TI-RTOS release:

    CryptoCC26XX AES-CCM Transaction.
    The Counter with CBC-MAC (CCM) mode of operation is a generic authenticated
    encryption block cipher mode. It can be used with any 128-bit block cipher.
    AES-CCM combines CBC-MAC with an AES block cipher.
    AES-CCM encryption has the following inputs and outputs:
    Encryption                 | Decryption
    Shared AES key             | Shared AES key
    Nonce                      | Nonce
    Cleartext                  | Ciphertext (encrypted cleartext + MAC)
    AAD (optional)             | AAD (optional)
    Ciphertext                 | 
    (encrypted cleatext + MAC) | Cleatext
    The AES key is a shared secret between the two parties and has a length of 128
    Bit. The key is stored in a dedicated RAM of the AES hardware unit before the
    crypto operation.
    The nonce is generated by the party performing the authenticated encryption
    operation. Within the scope of any authenticated encryption key, the nonce
    value must be unique. That is, the set of nonce values used with any given key
    must not contain any duplicate values. Using the same nonce for two different
    messages encrypted with the same key destroys the security properties.
    The optional AAD is authenticated, but not encrypted. Thus, the AAD is not
    included in the AES-CCM output. It can be used to authenticate packet headers
    for transport layer security.
    After the encryption operation, the ciphertext contains the encrypted data and
    the message authentication code (MAC). The MAC can be seen as an encrypted
    fingerprint of the message header and content.
    AES-CCM works in both ways: encryption and decryption. When a message is
    decrypted, then ciphertext, AAD, nonce and MAC are used as inputs while the
    output comprises the cleatext only. The decryption operation is successful,
    when the received ciphertext, the nonce and the AAD can reproduce the
    containing MAC.
    The CryptoCC26XX_AESCCM_Transaction structure defines all necessary parameters
    for a AES-CCM transaction.

    #include <ti/drivers/crypto/CryptoCC26XX.h>
    #define macLength           (4)
    #define clearTextLength     (16)
    #define cipherTextLength    (macLength + clearTextLength)
    #define nonceLength         (12)
    #define hdrLength           (14)
    // Holds the AES-CCM setup for this example
    typedef struct
        uint8_t key[16];                                // A 128 Bit AES key
        CryptoCC26XX_KeyLocation keyLocation;           // One of 8 key locations in the hardware
        uint8_t clearAndCipherText[cipherTextLength];   // Holds the cleartext before, and the ciphertext
                                                        // after the encryption operation.
                                                        // Ciphertext = encrypted text + message authentication code (MAC).
        uint8_t nonce[nonceLength];                     // A value that is used only once (cryptographic term 'nonce')
        uint8_t header[hdrLength];                   // A header that is not encrypted but is authenticated in the operation.
    } AesCcmExample;
    AesCcmExample ccmSetup =
        .key = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
                 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
        .keyLocation = CRYPTOCC26XX_KEY_0,
        .clearAndCipherText = { 't','h','i','s','i','s','a','p','l','a','i','n','t','e','x','t','0','0','0','0' },
        .nonce  = { 't','h','i','s','i','s','a','n','o','n','c','e' },
        .header = { 't','h','i','s','i','s','a','h','e','a','d','e','r','1' }
    CryptoCC26XX_Handle             handle;
    int32_t                         keyIndex;
    CryptoCC26XX_AESCCM_Transaction trans;
    int32_t                         status;
    // Initialize Crypto driver structures
    // Open the crypto hardware with non-exclusive access and default parameters.
    handle = CryptoCC26XX_open(Board_CRYPTO, false, NULL);
    if (handle == NULL) {
        System_abort("CryptoCC26XX did not open");
    // Allocate a key storage location in the hardware
    keyIndex = CryptoCC26XX_allocateKey(handle, ccmSetup.keyLocation, (const uint32_t *) ccmSetup.key);
    if (keyIndex == CRYPTOCC26XX_STATUS_ERROR) {
        System_abort("Key Location was not allocated.");
    // Encrypt and authenticate the message
    CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCM);
    trans.keyIndex   = keyIndex;
    trans.authLength = macLength;
    trans.nonce  = (char *) ccmSetup.nonce;
    trans.header = (char *) ccmSetup.header;
    trans.fieldLength  = 3;
    trans.msgInLength  = clearTextLength;
    trans.headerLength = hdrLength;
    trans.msgIn  = (char *) &(ccmSetup.clearAndCipherText[0]);                // Message is encrypted in place
    trans.msgOut = (char *) &(ccmSetup.clearAndCipherText[clearTextLength]);  // MAC will be written to this position
    status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    if (status != CRYPTOCC26XX_STATUS_SUCCESS) {
        System_abort("Encryption and signing failed.");
    // Decrypt and authenticate message
    CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCMINV);
    trans.keyIndex   = keyIndex;
    trans.authLength = macLength;
    trans.nonce  = (char *) ccmSetup.nonce;
    trans.header = (char *) ccmSetup.header;
    trans.fieldLength  = 3;
    trans.msgInLength  = cipherTextLength;
    trans.headerLength = hdrLength;
    trans.msgIn  = (char *) &(ccmSetup.clearAndCipherText[0]);                // Message is decrypted in place
    trans.msgOut = (char *) &(ccmSetup.clearAndCipherText[clearTextLength]);  // Points to the MAC, is used as input here
    // Do AES-CCM decryption and authentication
    status = CryptoCC26XX_transact(handle, (CryptoCC26XX_Transaction *) &trans);
    if(status != CRYPTOCC26XX_STATUS_SUCCESS){
        System_abort("Decryption and authentication failed.");
    // Release the key location
    status = CryptoCC26XX_releaseKey(handle, &keyIndex);
    if (status != CRYPTOCC26XX_STATUS_SUCCESS) {
        System_abort("Key release was not successful.");

  • Hey Richard,

    if i got this right, i can leave the packet transmitting functions in easylink "as is" and implement transport layer security by adding mesage authentification code?

    I tried removing the dest.Address entry from the easylink rxPacket and txPacket structs and added the address in the header part of the payload. This is working, but i think this can cause problems when i get to implement more advanced features like association of clients to a router and key exchange.

    I will try this out and report back.

    Also i think i have not fully grasped the concept of the nounce which is added to the message. I'm sending very small amounts of data so i'm filling the remaining bits of the 128 bit encryption block with random numbers before encryption. Is this the same concept as the nounce in your example?

    Best ragards,


  • Hi Sebastian,

    in an ideal world, we would use the OSI model and distinguish between link layer, network layer, transport layer... However, in the real world, some layers are always mingled for practical reasons and sometimes some layers are dropped completely. The easylink API provides point-to-point communication of datagrams with a certain size and ensures integrity. This corresponds to the link layer (LL) in OSI. Network and transport layer are implemented on top of that.

    In our easylink examples, like the wireless sensor network (WSN), the easylink layer is also the network layer (NL), or in other words LL==NL, because we do not use packet routing and fragmentation. The WSN examples implement timeouts and different type of messages, which could be seen as a mixture of transport layer and application layer.

    I suggest to implement encryption and authentication on top of easylink. You can use the node address and packet size as a header/AAD and the ciphertext (encrypted data + MAC) would become the payload for the easylink layer. 

    In order to understand nonce values, please refer to literature about encryption and authentication. The purpose of the nonce is, that an attacker would not be able to detect, whether a packet contains the same payload and draw conclusions from that. So filling up the payload with random data provides the same security. At least some amount of random data must be included and you must be able to authenticate the message and check integrity after decryption. This is what the MAC is used for.

  • Hi Richard,

    your last reply helped me a lot, thank you. I know have a very similiar problem.

    I encrypt the payload (datapacket, destination address and length field are NOT encrypted) and can receive an decrypt that data.

    However, if i try to encrypt the acknowldge packet in the same manner, the rxDoneCallback is called with the Eventmask RF_EventCmdAborted. Where does this come from? I am unable to track this error further down, because it occurs during RF_postCmd(rfHandle, (RF_Op*)&EasyLink_cmdPropRxAdv, RF_PriorityNormal, rxDoneCallback, EASYLINK_RF_EVENT_MASK);

    Thanks for any help!

  • How is that possible? I guess that the problem is not related to easylink, but maybe an unintended memory overwrite during encryption. Could it be that some data structures are destroyed? Can you maybe change your setup a bit? Just send encrypted messages back and forth and check their content. Does that work?
  • Sebastian Wirth said:


    I encrypt the payload (datapacket, destination address and length field are NOT encrypted) and can receive an decrypt that data.



    how do you get the nonce over to the other side? Do you send that over plain or hashed? Or isn't it needed on the decrypt side?

  • Dear Richard,

                 I want to create nonce by using TRNG , so every time data is encrypted, it is encrypted using the different nonce and how does same nonce is shared at the decrytion side?



  • I would also like to know this, how do you share the nonce between sender and receiver?

  • Hello Tom,
    I have done the following to share the nonce between sender and receiver :
    1) Generate the nonce randomly before the encryption and use the same nonce in encryption
    2) Concatenate the generated nonce with the encrypted data to send together as a payload.
    3) At the receiver end, extract the nonce attached in payload and use the same nonce for decryption. (Here you know when the nonce starts in payload so it is easy to extract.

    It worked for me. Hope it helped you.

  • Thanks for your answer

    I do wonder if it is secure the send the nonce together with the payload, aren't you giving away valuable information?
  • Hello Tom,
    Only if you send it in unrecognizable pattern with payload ( Here using TRNG) , it will be more secure. You can check the encrypted data on RF studio, it will hardly make any sense to outsider.
    Hope this helps !

  • A nonce have to be unique for every message to ensure that the encryption is secure.

    I would advice reading up on the basics in cryptography before using it in the application to avoid security issues later.