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.

LAUNCHXL-CC1310: rfWSN eaxmple encryption problems

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310

HI

I have some questions.

Examples code: rfwsnNode and rfwsnconcentrator
sdk: simplelink_cc13x0_sdk_1_50_00_08
Used board: cc1310 LP

I would like to apply Encryption to the example code above. And I also found that there is CryptoCC26XX.h.

1.Do you have any examples for encryption / decryption?
   (I would like to exclude things like ECB, because it is not recommanded.)

2.If there is an encryption / decryption example, can the following packet also apply?

     (The packet frame structure is based on easylink.)

Thanks.

  • Here is an example for encrypt and decrypt using CCM:

    static int32_t encryptMessage(char *messageBuffer, char *nonce, uint8_t msgLength, int32_t keyIndex, CryptoCC26XX_Handle cryptoHandle)
    {
        uint8_t plainTextLength     = msgLength;
        uint8_t cipherTextLength    = MAC_LENGTH + plainTextLength;
        uint8_t header[AAD_LENGTH]  = {plainTextLength, cipherTextLength, MAC_LENGTH, NONCE_LENGTH};
        CryptoCC26XX_AESCCM_Transaction trans;
    
        /* Load key to the key register */
        CryptoCC26XX_loadKey(cryptoHandle, keyIndex, (const uint32_t *)key);
    
        /* Initialize encryption transaction */
        CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *)&trans, CRYPTOCC26XX_OP_AES_CCM_ENCRYPT);
    
        trans.keyIndex      = keyIndex;
        trans.authLength    = MAC_LENGTH;
        trans.nonce         = (char *) nonce;
        trans.header        = (char *) header;
        trans.fieldLength   = 15 - NONCE_LENGTH;
        trans.msgInLength   = plainTextLength;
        trans.headerLength  = AAD_LENGTH;
        trans.msgIn         = messageBuffer; /* Points to the plaintext */
        trans.msgOut        = (char *)&(messageBuffer[plainTextLength]); /* position of MAC field */
    
        /* Start the encryption transaction */
        return CryptoCC26XX_transact(cryptoHandle, (CryptoCC26XX_Transaction *)&trans);
    }
    
    /*
    *   ======== messageEncrypter ========
    *   Running function that will wait for input from the user and then encrypt the input message
    */
    void messageEncrypter(CryptoCC26XX_Handle cryptoHandle, PIN_Handle ledPinHandle, UART_Handle uart )
    {
        int32_t             keyIndex;
        int32_t             status;
        uint8_t             nonce[NONCE_LENGTH];
        uint8_t             msgLen = 0;
        EasyLink_TxPacket   txPacket = {0};
        char                messageBuffer[MAX_MSG_LENGTH] = {0};
        char                tempInputBuffer;
    
        /* Store key and receive key index for the first avilable keylocation */
        keyIndex = CryptoCC26XX_allocateKey(cryptoHandle, CRYPTOCC26XX_KEY_ANY, (const uint32_t*)key);
        if(keyIndex == CRYPTOCC26XX_STATUS_ERROR) {
            /* key allocation failed */
            while(1);
        }
    
        UART_write(uart, initialMsg, sizeof(initialMsg));
    
        while(1) {
            UART_read(uart, &tempInputBuffer, 1);
            /* Read characters until enter key has been pressed */
            if(tempInputBuffer == '\r') {
                UART_write(uart, crlf, sizeof(crlf));
                if(msgLen == 0) {
                    /* If message is empty, send a warning to the user */
                    UART_write(uart, msgEmptyError, sizeof(msgEmptyError));
                }
                else if(msgLen < MAX_MSG_LENGTH) {
                    messageBuffer[msgLen] = '\0';
                    /* generate new even nonce for every packet */
                    generateNonce(nonce, NONCE_LENGTH, false);
                    /* encrypt the user input with the newly generated nonce */
                    status = encryptMessage(messageBuffer, (char *)nonce, msgLen, keyIndex, cryptoHandle);
                    if(status == CRYPTOCC26XX_STATUS_SUCCESS){
                        /* toggle led to indicate that the message has been successfully encrypted */
                        PIN_setOutputValue(ledPinHandle, Board_PIN_LED0, !PIN_getOutputValue(Board_PIN_LED0));
                    }
                    /* Fill packet with encrypted data */
                    fillPacket(&txPacket, messageBuffer, (char *)nonce, msgLen);
    
                    status = EasyLink_transmit(&txPacket);
                    if(status == EasyLink_Status_Success){
                        /* Toggle led to indicate a packet has been successfully transmitted, otherwise ignore */
                        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, !PIN_getOutputValue(Board_PIN_LED1));
                    }
                }
                else {
                    /* If message exceeds char, ignore the message and send a warning to the user */
                    memset(messageBuffer,0,MAX_MSG_LENGTH);
                    UART_write(uart, msgExceedError, sizeof(msgExceedError));
                }
                msgLen = 0;
            }
            else {
                messageBuffer[msgLen++] = tempInputBuffer;
                /* Show the characters typed by the user on the terminal */
                UART_write(uart, &tempInputBuffer, 1);
            }
        }
    }
    
    /* Unloads packet then decrypts and verifies it. Content of message is stored on msgBuffer */
    int8_t decryptPacket(EasyLink_RxPacket *rxPacket, uint8_t *msgBuffer , uint8_t *msgLen,
                         CryptoCC26XX_Handle cryptoHandle, int32_t keyIndex)
    {
        int32_t status ;
        CryptoCC26XX_AESCCM_Transaction trans;
        uint8_t macBuffer[MAX_MAC_LENGTH];
        uint8_t header[AAD_LENGTH];
        uint8_t plainTextLength;
        uint8_t cipherTextLength;
        uint8_t nonceLength;
        uint8_t authLength;
    
        /* unload package in correct format */
        memcpy(header, rxPacket->payload, AAD_LENGTH);
        plainTextLength  = header[0];
        cipherTextLength = header[1];
        authLength       = header[2];
        nonceLength      = header[3];
        *msgLen          = plainTextLength;
    
        /* Load key to the key register */
        CryptoCC26XX_loadKey(cryptoHandle, keyIndex, (const uint32_t*)key);
        /* initialize transaction */
        CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction*)&trans, CRYPTOCC26XX_OP_AES_CCM_DECRYPT);
    
        trans.keyIndex      = keyIndex;
        trans.authLength    = authLength;
        trans.nonce         = (char *)&rxPacket->payload[AAD_LENGTH]; /* Points to the nonce */
        trans.header        = (char *) header;
        trans.fieldLength   = 15 - nonceLength; /* 15 = fieldlength + nonceLength condition must be true */
        trans.msgInLength   = cipherTextLength;
        trans.headerLength  = AAD_LENGTH;
        trans.msgIn         = (char *)&rxPacket->payload[AAD_LENGTH + nonceLength]; /* Points to the cipherText */
        trans.msgOut        = (char *)macBuffer;  /* Points to the MAC field */
    
        /* Start the decryption transaction */
        status = CryptoCC26XX_transact(cryptoHandle, (CryptoCC26XX_Transaction *)&trans);
        if(status != CRYPTOCC26XX_STATUS_SUCCESS) {
            /* Transaction did not succeed */
            return CRYPTOCC26XX_STATUS_ERROR;
        }
    
        /* Store the decrypted message in msgBuffer */
        memcpy(msgBuffer, &rxPacket->payload[AAD_LENGTH + nonceLength], plainTextLength);
        return CRYPTOCC26XX_STATUS_SUCCESS;
    }
    
    /*
    *   ======== messageDecrypter ========
    *   Open a crypto instance, decrypt and authenticate the message. Use uart to write the content on terminal
    */
    static void messageDecrypter(CryptoCC26XX_Handle cryptoHandle, PIN_Handle ledPinHandle, UART_Handle uartHandle)
    {
        EasyLink_RxPacket rxPacket = {0};
        int32_t keyIndex;
        EasyLink_init(EasyLink_Phy_50kbps2gfsk);
        uint8_t status;
        char    msgBuffer[MAX_MSG_BUFFER_LENGTH] = {0};
        uint8_t msgLen;
        uint8_t addressFilter = 0xaa; /* filter all adresses except 0xaa */
    
    
        /* Store key and receive key index for the first avilable keylocation */
        keyIndex = CryptoCC26XX_allocateKey(cryptoHandle, CRYPTOCC26XX_KEY_ANY, (const uint32_t *)key);
    
        /* Add Address filter for the incoming packets */
        EasyLink_enableRxAddrFilter(&addressFilter, 1, 1);
    
        EasyLink_setFrequency(868000000);
        UART_write(uartHandle, initialMsg, sizeof(initialMsg));
    
        while(1) {
            rxPacket.absTime = 0;
            EasyLink_Status result = EasyLink_receive(&rxPacket);
            if (result == EasyLink_Status_Success) {
                /* Toggle LED0 to indicate RX */
                PIN_setOutputValue(ledPinHandle, Board_PIN_LED0,!PIN_getOutputValue(Board_PIN_LED0));
    
                status = decryptPacket(&rxPacket, (uint8_t *)msgBuffer, &msgLen, cryptoHandle, keyIndex);
                if(status == CRYPTOCC26XX_STATUS_SUCCESS) {
                    UART_write(uartHandle, successfullDecryption, sizeof(successfullDecryption));
                    UART_write(uartHandle, msgBuffer, msgLen);
                    UART_write(uartHandle, crlf, sizeof(crlf));
                    PIN_setOutputValue(ledPinHandle, Board_PIN_LED1, !PIN_getOutputValue(Board_PIN_LED1));
                }
                else {
                    /* write error message to user if decryption failed */
                    UART_write(uartHandle, unsuccessfullDecryption, sizeof(unsuccessfullDecryption));
                }
            }
            else {
                /* Indicate error in receiving packet */
                UART_write(uartHandle, errorPacketRecv, sizeof(errorPacketRecv));
            }
        }
    }

    The packet format doesn't matter. 

  • Thanks. Have a nice day.
  •  refer to other code to understand the code you uploaded.


     

    The CCM I understand is:

    I do not know the meaning of the following code.

    trans.header = (char *) ccmSetup.header;

    trans.fieldLength  = 3;

    trans.headerLength = hdrLength;

    1. What does field and header mean?

     

    I think same key is also on the decryption side.I have also seen the theory that nonce (IV) must also be composed of random values.

    2. If the nonce(IV) is a randomly generated number, how Do you decode cipher text on the decrypting side?

     

    3.Does the size of the packet increase by the size of mac when encrypting? Can I reduce the size of my mac to 1 byte?

     

     

    thanks

  • 1) Go to C:\ti\simplelink_cc13x0_sdk_1_50_00_08\source\ti\drivers\crypto\CryptoCC26XX.c and see the definition of the  struct CryptoCC26XX_AESCCM_Transaction. In the comments the fields are covered in detail.

    2) The nonce does not have to be random, it just need to be only be used once. In the code the nonce is generated as follows:

    /* generate 128 bit nonce number based on an offset being incremented each time a new nonce is generated
     * generated numbers will always be either odd or even, depending on the isOddNumber argument.
     * This setup avoids the problem of having same nonce generated between two units.
     * Key should be changed after a certain amount of transactions because of overflow, which will cause same
     * nonce to be generated
     */
    static void generateNonce(uint8_t *nonceDestination, uint8_t nonceLength, bool isOddNumber)
    {
        uint8_t i;
        static union nonceNumber generatedNumber = {0};
    
        generatedNumber.doubleWord[0]+= 2;
    
        if(isOddNumber) {
            /* add one to make the number odd */
            generatedNumber.doubleWord[0]++;
        }
    
        /* check for overflow */
        if(generatedNumber.doubleWord[0] < 2){
            generatedNumber.doubleWord[1]++;
        }
    
        for(i = 0; i < nonceLength; i++) {
            nonceDestination[i] = generatedNumber.byte[i];
        }
        if(isOddNumber){
            /* remove the one to make it even again */
            generatedNumber.doubleWord[0]--;
        }
    }

    3) I believe so:

    static void fillPacket(EasyLink_TxPacket *txPacket, char *messageBuffer, char *nonce, uint8_t msgLength)
    {
        uint8_t plainTextLength     = msgLength;
        uint8_t cipherTextLength    = plainTextLength + MAC_LENGTH;
    
        /* Add destination adress 0xaa so that the receiver ignores other packets */
        txPacket->dstAddr[0] = 0xaa;
    
        /* Fill header with length parameters */
        uint8_t header[AAD_LENGTH]   = {plainTextLength, cipherTextLength, MAC_LENGTH, NONCE_LENGTH};
    
        memcpy(txPacket->payload, header, AAD_LENGTH);
        memcpy(&txPacket->payload[AAD_LENGTH], nonce , NONCE_LENGTH);
        memcpy(&txPacket->payload[AAD_LENGTH+NONCE_LENGTH], messageBuffer, cipherTextLength);
        txPacket->len = AAD_LENGTH + NONCE_LENGTH + cipherTextLength;
    }

    since the cipher text length is dependent on the MAC length. See the definition of CryptoCC26XX_AESCCM_Transaction, looks like the field has to be a even number. 

  • I want to use CBC only.(Using cbc-mac increases the payload size.)
    So I saw the following structure.


    <trans setting>
    typedef struct CryptoCC26XX_AESCBC_Transaction {
    CryptoCC26XX_Operation opType; /*!< The type of the crypto operation */
    CryptoCC26XX_Mode mode; /*!< The mode of current transaction. Set by transact function. */
    uint8_t keyIndex; /*!< The key store index to be used */
    void *nonce; /*!< A pointer to 16 byte Nonce. */
    void *msgIn; /*!< A pointer to the octet string input message */
    void *msgOut; /*!< A pointer to the output message location */
    uint16_t msgInLength; /*!< The length of the message */
    } CryptoCC26XX_AESCBC_Transaction;


    1. I know that nonce is used to create a mac, why do I use it in CBC?
    2. If I use nonce,Should I put it in payload?
    3. Is msgin the location of the plaintext, and msgout the location where the encrypted text will be stored?


    thanks