* * Copyright (c) 2015-2016, 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 #include #include #include #include #include #include /* Drivers */ #include #include #include "driverlib/rf_prop_mailbox.h" /* Board Header files */ #include "Board.h" #include "RFQueue.h" #include #include "smartrf_settings/smartrf_settings.h" #include /* Pin driver handle */ static PIN_Handle ledPinHandle; static PIN_State ledPinState; /* * Application LED pin configuration table: * - All LEDs board LEDs are off. */ PIN_Config pinTable[] = { Board_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, Board_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, PIN_TERMINATE }; /***** Defines *****/ #define RX_TASK_STACK_SIZE 1024 #define RX_TASK_PRIORITY 2 /* Packet RX Configuration */ #define DATA_ENTRY_HEADER_SIZE 8 /* Constant header size of a Generic Data Entry */ #define MAX_LENGTH 100 /* Max length byte the radio will accept */ #define NUM_DATA_ENTRIES 2 /* NOTE: Only two data entries supported at the moment */ #define NUM_APPENDED_BYTES 2 /* The Data Entries data field will contain: * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1) * Max 30 payload bytes * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */ /* Packet TX Configuration */ #define PAYLOAD_LENGTH 24 #define PACKET_INTERVAL (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */ #define macLength (4) #define clearTextLength (16) #define cipherTextLength (macLength + clearTextLength) #define nonceLength (12) #define aadLength (14) /***** Prototypes *****/ static void rxTaskFunction(UArg arg0, UArg arg1); static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e); static void decryptPacketCCM(uint8_t *key); /***** Variable declarations *****/ static Task_Params rxTaskParams; Task_Struct rxTask; /* not static so you can see in ROV */ static uint8_t rxTaskStack[RX_TASK_STACK_SIZE]; static RF_Object rfObject; static RF_Handle rfHandle; /* Buffer which contains all Data Entries for receiving data. * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN (rxDataEntryBuffer, 4); static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES, MAX_LENGTH, NUM_APPENDED_BYTES)]; #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment = 4 static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES, MAX_LENGTH, NUM_APPENDED_BYTES)]; #elif defined(__GNUC__) static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES, MAX_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4))); #else #error This compiler is not supported. #endif /* Receive dataQueue for RF Core to fill in data */ static dataQueue_t dataQueue; static rfc_dataEntryGeneral_t* currentDataEntry; static uint8_t packetLength; static uint8_t* packetDataPointer; static PIN_Handle pinHandle; static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */ static uint8_t decryptPacket[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; // Key variables //static CryptoCC26XX_KeyLocation keyLocation = CRYPTOCC26XX_KEY_0; //static uint8_t cryptoKey[16] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, // 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }; // uint8_t header[14]; uint8_t macBuffer[40]; // 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[aadLength]; // A header that is not encrypted but is authenticated in the operation (AAD). uint8_t verificationMAC[macLength]; // Location that the recalculated and encrypted MAC is stored during decryption. } 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 = { 'l','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','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' } }; //semaphore object definitions Semaphore_Struct semStruct; Semaphore_Handle semHandle; void decryptPacketCCM(uint8_t * key) { memcpy(header,packet,aadLength); uint8_t clearTextBuffer[AES_ECB_LENGTH]; CryptoCC26XX_Handle handle; int32_t keyIndex; int32_t status; CryptoCC26XX_AESCCM_Transaction trans; // // // Initialize Crypto driver CryptoCC26XX_init(); // Open the crypto hardware with non-exclusive access and default parameters // Attempt to open CryptoCC26XX. handle = CryptoCC26XX_open(Board_CRYPTO, false, NULL); if (!handle) { System_abort("Crypto module could not be opened."); } // Allocate a key storage location in the hardware keyIndex = CryptoCC26XX_allocateKey(handle, ccmSetup.keyLocation, (const uint32_t *) ccmSetup.key); //keyIndex = CryptoCC26XX_allocateKey(handle, ecbExample.keyLocation, //(const uint32_t *) ecbExample.key); // keyIndex = CryptoCC26XX_allocateKey(handle, keyLocation, (const uint32_t *) key); if (keyIndex == CRYPTOCC26XX_STATUS_ERROR) { System_abort("Key Location was not allocated."); } // Decrypt the cipher text and authenticate the message // Initialize transaction CryptoCC26XX_Transac_init((CryptoCC26XX_Transaction *) &trans, CRYPTOCC26XX_OP_AES_CCM_DECRYPT); /// only change is CRYPTOCC26XX_OP_AES_CCMINV // Setup transaction trans.keyIndex = keyIndex; trans.authLength = macLength; trans.nonce = (char *) ccmSetup.nonce; trans.header = (char *) ccmSetup.header; trans.fieldLength = 3; trans.msgInLength = cipherTextLength; trans.headerLength = aadLength; trans.msgIn = (char *) &(packet[aadLength+nonceLength]); // Message is decrypted in place trans.msgOut = (char *) macBuffer; // Points to the MAC, is used as input here // trans.msgOut = (char *) ccmSetup.verificationMAC; // memset(&(ccmSetup.clearAndCipherText[clearTextLength]), 0x0, clearTextLength); // added this part from ecb example // 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."); } CryptoCC26XX_close(handle); } /***** Function definitions *****/ void RxTask_init(PIN_Handle ledPinHandle) { pinHandle = ledPinHandle; Task_Params_init(&rxTaskParams); rxTaskParams.stackSize = RX_TASK_STACK_SIZE; rxTaskParams.priority = RX_TASK_PRIORITY; rxTaskParams.stack = &rxTaskStack; rxTaskParams.arg0 = (UInt)1000000; Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL); } static void rxTaskFunction(UArg arg0, UArg arg1) { // Radio defs RF_Params rfParams; RF_Params_init(&rfParams); if( RFQueue_defineQueue(&dataQueue, rxDataEntryBuffer, sizeof(rxDataEntryBuffer), NUM_DATA_ENTRIES, MAX_LENGTH + NUM_APPENDED_BYTES)) { /* Failed to allocate space for all data entries */ while(1); } /* Modify CMD_PROP_RX command for application needs */ RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */ RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1; /* Discard ignored packets from Rx queue */ RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */ RF_cmdPropRx.maxPktLen = MAX_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */ RF_cmdPropRx.pktConf.bRepeatOk = 1; RF_cmdPropRx.pktConf.bRepeatNok = 1; /* Request access to the radio */ rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams); /* Set the frequency */ RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0); /* Enter RX mode and stay forever in RX */ RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE); while(1) { Semaphore_pend(semHandle, BIOS_WAIT_FOREVER); //decryptPacketECB(cryptoKey); decryptPacketCCM(ccmSetup.key); PIN_setOutputValue(pinHandle, Board_RLED ,!PIN_getOutputValue(Board_RLED)); } } void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) { if (e & RF_EventRxEntryDone) { /* Toggle pin to indicate RX */ PIN_setOutputValue(pinHandle, Board_GLED,!PIN_getOutputValue(Board_GLED)); /* Get current unhandled data entry */ currentDataEntry = RFQueue_getDataEntry(); /* Handle the packet data, located at ¤tDataEntry->data: * - Length is the first byte with the current configuration * - Data starts from the second byte */ packetLength = *(uint8_t*)(¤tDataEntry->data); packetDataPointer = (uint8_t*)(¤tDataEntry->data + 1); /* Copy the payload + the status byte to the packet variable */ memcpy(packet, packetDataPointer, (packetLength + 1)); RFQueue_nextEntry(); Semaphore_post(semHandle); } } /* * ======== main ======== */ int main(void) { Semaphore_Params semParams; /* Construct a Semaphore object to be use as a resource lock, inital count 1 */ Semaphore_Params_init(&semParams); Semaphore_construct(&semStruct, 0, &semParams); /* Obtain instance handle */ semHandle = Semaphore_handle(&semStruct); /* Call driver init functions. */ Board_initGeneral(); /* Open LED pins */ ledPinHandle = PIN_open(&ledPinState, pinTable); if(!ledPinHandle) { System_abort("Error initializing board LED pins\n"); } /* Initialize task */ RxTask_init(ledPinHandle); /* Start BIOS */ BIOS_start(); return (0); }