A very easy to understand LoRaWAN-node code.
Dependencies: LoRaWAN-lib SX1272Lib X_NUCLEO_IKS01A1 mbed
Important parameters:
• In comissioning.h: DevEUI, AppEUI, AppKEY, DevADR, NwksKEY, AppsKEY, OTAA and public network. Frequency and channel block to use, confirmed or unconfirmed messages, app port, app data size and OTAA and Tx duty cycles.
• In LoRaMac.h: Maximum payload and MAC commands length, receive delays, max FCNT, adr ack limit, timeout and delay, max ack retries, rssi threshold and sync words.
• In LoRaMac.cpp: Maximum payload, MAC commands and FRMpayload length.
• In LoRaMac-board.h: Tx power, data rates and band settings.
NOTE: Please refer to LoRaWAN regional parameters (page 12 for US band) to know which parameters you can modify.
Revision 0:60ff878b27b8, committed 2018-04-03
- Comitter:
- dgabino
- Date:
- Tue Apr 03 17:09:34 2018 +0000
- Commit message:
- A simpler way to customize your LoRaWAN payload
Changed in this revision
diff -r 000000000000 -r 60ff878b27b8 Code/Comissioning.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/Comissioning.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,163 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: End device comissioning and comunication parameters + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "board.h" + +//********************************************************************* COMISSIONING PARAMETERS ************************************************************************ + +#ifndef __LORA_COMISSIONING_H__ +#define __LORA_COMISSIONING_H__ + +/*! + * When set to 1 the application uses the Over-the-Air activation procedure + * When set to 0 the application uses the Personalization activation procedure + */ +#define OVER_THE_AIR_ACTIVATION 1 + +/*! + * Indicates if the end-device is to be connected to a private or public network + */ +#define LORAWAN_PUBLIC_NETWORK true + +#if( OVER_THE_AIR_ACTIVATION != 0 ) + +/*! + * Mote device IEEE OUI (big endian) + * \remark This is unique to a company or organization + */ +#define IEEE_OUI 0x4f, 0x72, 0x62 + +/*! + * Mote device IEEE EUI (big endian) + * + * \remark In this application, if the last 4 bytes are all 0, then the 32 bit address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value + * If provided by user, e.g. {IEEE_OUI, 0x00, 0x00, 0x00, 0xFF, 0x01}, then this value is used by the application. *0x69, 0x00, 0xab, 0xcd, 0xaa + */ +#define LORAWAN_DEVICE_EUI { IEEE_OUI, 0x69, 0x00, 0xab, 0xcd, 0xff } + +/*! + * Application IEEE EUI (big endian) + */ +#define LORAWAN_APPLICATION_EUI { 0x70, 0xb3, 0xd5, 0x7e, 0xd0, 0x00, 0x96, 0x4b} //0x70, 0xb3, 0xd5, 0x7e, 0xd0, 0x00, 0x96, 0x4b for TTN server + //0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 for semtech NA server +/*! + * AES encryption/decryption cipher application key + */ +#define LORAWAN_APPLICATION_KEY { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } + +#else + +/*! + * Device address on the network (big endian) + * + * \remark In this application, if the value is 0, then the address is automatically generated using a pseudo random generator seeded with a value derived from BoardUniqueId value + * If provided by user, e.g. 0x78563412, then this value is used by the application + */ +#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x0 + +/*! + * AES encryption/decryption cipher network session key + */ +#define LORAWAN_NWKSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + +/*! + * AES encryption/decryption cipher application session key + */ +#define LORAWAN_APPSKEY { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + +#endif + +#endif // __LORA_COMISSIONING_H__ + + +//********************************************************************* COMUNICATION PARAMETERS ************************************************************************ + +#ifndef __LORA_CONFIG_H__ +#define __LORA_CONFIG_H__ + +/*! + * Configure End-Device to use 8-channels corresponding to Block A + * Comment/Uncomment to disable/enable Hybrid mode + */ +#define USE_BAND_915_HYBRID + +#ifndef USE_BAND_915_HYBRID +/*! + * Configure End-Device to use 64-channels across to Block A thru Block H + */ +#define USE_BAND_915 + +#else + +// define channel block: e.g. USE_BAND_915_HYBRID_BLOCK_A, USE_BAND_915_HYBRID_BLOCK_B ... USE_BAND_915_HYBRID_BLOCK_H etc. +#define USE_BAND_915_HYBRID_BLOCK_A + +#endif + +/*! + * Join requests trials periodicity(+12s). It is the time between RX1/RX2 and next TX + */ +#define OVER_THE_AIR_ACTIVATION_DUTYCYCLE 5000000 // value in us + +/*! + * Defines the application data transmission periodicity. It is the time between RX1/RX2 and next TX + */ +#define APP_TX_DUTYCYCLE 25000000 // value in us + +/*! + * Defines the randomness in the dutycycle. + */ +#define APP_TX_DUTYCYCLE_RND 3000000 + +/*! + * LoRaWAN confirmed messages + * \remark 1 : Confirmed messages enabled. Must receive ACK from network server + 0 : Confirmed messages disabled. + */ +#define LORAWAN_CONFIRMED_MSG_ON 0 + +/*! + * LoRaWAN Adaptive Data Rate + * + * \remark Please note that when ADR is enabled the end-device uses default datarate of DR_0 + */ +#define LORAWAN_ADR_ON 0 + +/*! + * Default mote datarate + * \remark DR_0 : 980 bps; DR_1 : 1760 bps; DR_2 : 3125 bps; DR_3 : 5470 bps; DR_4 : 12500 bps + */ +#define LORAWAN_DEFAULT_DATARATE DR_0 + +/*! + * LoRaWAN application port + */ +#define LORAWAN_APP_PORT 5 + +/*! + * LoRaWAN User defined Tx Power + * + * \remark The Tx power level is set as TX_POWER_P_DBM, where 10 <= P <= 30 and P is even value { i.e. P = 10, 12, 14 ... 28 or 30 } + */ +#define LORAWAN_TX_POWER TX_POWER_10_DBM + + +#define LORAWAN_APP_DATA_SIZE 11 + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + +#define USE_IKS01A1_SENSOR + +#endif // __LORA_CONFIG_H__ +
diff -r 000000000000 -r 60ff878b27b8 Code/Common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/Common.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,74 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Extern declaration of parameters defined in main.cpp + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include "Comissioning.h" +#include "board.h" + + +/*! + * User application data buffer size + */ +#define LORAWAN_APP_DATA_MAX_SIZE 64 + +/*! + * Current network ID + */ +#define LORAWAN_NETWORK_ID ( uint32_t )0 + + +#if( OVER_THE_AIR_ACTIVATION != 0 ) +/*! + * Over the Air Activation + */ + +extern uint8_t DevEui[]; +extern uint8_t AppEui[]; +extern uint8_t AppKey[]; + +#else +/*! + * Activation by Personalization + */ + +extern uint8_t NwkSKey[]; +extern uint8_t AppSKey[]; +extern uint32_t DevAddr; + +#endif + + +extern uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; // User application data size + +extern uint8_t AppPort; // Application port + +extern uint8_t AppDataSize; // Application size + +extern uint8_t IsTxConfirmed; // Indicates if the node is sending confirmed or unconfirmed messages + +extern bool IsTxIntUpdate; // Indicates if a new transmit interrupt can be set + +extern bool NextTx; // Indicates if a new packet can be sent + +extern bool IsNetworkJoinedStatusUpdate; // Indicates if the MAC layer network join status has changed. + +extern bool IsTxUpdate; // Indicates if the message sent + +extern bool IsRxUpdate; // Indicates if the message received in the RX window. + +extern TimerEvent_t TxNextPacketTimer; // Timer to handle the application data transmission duty cycle + +#endif // __COMMON_H__ \ No newline at end of file
diff -r 000000000000 -r 60ff878b27b8 Code/LoRaDeviceFunctions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/LoRaDeviceFunctions.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,105 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Process function calls from various Device states + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __LORA_DEVICE_STATE_H__ +#define __LORA_DEVICE_STATE_H__ + +#include "Common.h" +#include "board.h" +#include "LoRaMac.h" + +#include "SerialDisplay.h" +#include "mbed.h" +#include "LoRaMacLayerService.h" + +/*! + * Strucure containing the Uplink status + */ +struct sLoRaMacUplinkStatus +{ + /*! + * MCPS-Request type + */ + Mcps_t Type; + uint8_t Acked; + int8_t Datarate; + uint16_t UplinkCounter; + uint8_t Port; + uint8_t *Buffer; + uint8_t BufferSize; + int8_t TxPower; +}; + +/*! + * Strucure containing the Downlink status + */ +struct sLoRaMacDownlinkStatus +{ + int16_t Rssi; + int8_t Snr; + uint16_t DownlinkCounter; + bool RxData; + uint8_t Port; + uint8_t *Buffer; + uint8_t BufferSize; + uint8_t RxSlot; +}; + +/*! + * Device states + */ +enum eDevicState +{ + DEVICE_STATE_INIT, + DEVICE_STATE_JOIN, + DEVICE_STATE_SEND, + DEVICE_STATE_SLEEP +}; + +extern sLoRaMacUplinkStatus LoRaMacUplinkStatus; + +extern sLoRaMacDownlinkStatus LoRaMacDownlinkStatus; + +extern eDevicState DeviceState; + +/*! + * \brief Initialize Device: Timer, MAC Services, MAC + */ +void DeviceInit( void ); + +/*! + * \brief Device Join update + */ +void DeviceJoinUpdate( void ); + +/*! + * \brief OTA: if device not joined, send JOIN REQUEST to network + * ABP: Request DevAddr if not already set + */ +void DeviceJoin( void ); + +/*! + * \brief Prepares the payload of the frame to be transmitted + * + * \param [IN] port application port corresponding to which payload is generated + */ +void PrepareTxFrame( uint8_t port ); + +/*! + * \brief Send the frame + * + */ +bool SendFrame( void ); + +#endif // __LORA_DEVICE_STATE_H__ \ No newline at end of file
diff -r 000000000000 -r 60ff878b27b8 Code/SerialDisplay.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/SerialDisplay.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,137 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: VT100 serial display management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ + +#include "SerialDisplay.h" + +VT100 vt( USBTX, USBRX ); + +void SerialDisplayJoinUpdate( void ) +{ + printf( "###### ===== JOINING ==== ######\r\n" ); + + DisplayNetworkParam( ); + + printf( "\r\n" ); +} + +void SerialDisplayTxUpdate(void) +{ + printf( "###### ===== UPLINK FRAME %d ==== ######\r\n", LoRaMacUplinkStatus.UplinkCounter ); + + DisplayNetworkParam( ); + + printf( "TX PORT: %d\r\n", LoRaMacUplinkStatus.Port ); + + if( LoRaMacUplinkStatus.BufferSize != 0 ) + { + printf( "TX DATA: " ); + if( LoRaMacUplinkStatus.Type == MCPS_CONFIRMED ) + { + printf( "CONFIRMED\r\n" ); + } + else + { + printf( "UNCONFIRMED\r\n" ); + } + SerialDisplayHex( LoRaMacUplinkStatus.Buffer, LoRaMacUplinkStatus.BufferSize ); + } + + printf( "DATA RATE: DR%d\r\n", LoRaMacUplinkStatus.Datarate ); + + printf( "TX POWER: %d dBm\r\n", 30 - ( LoRaMacUplinkStatus.TxPower << 1 ) ); + + printf( "BATTERY: %2.2fV\r\n", BoardGetBatteryLevel( ) ); + + printf( "\r\n"); +} + +void SerialDisplayRxUpdate( void ) +{ + printf( "###### ===== DOWNLINK FRAME %d ==== ######\r\n", LoRaMacDownlinkStatus.DownlinkCounter ); + + printf( "RX WINDOW: %d\r\n", LoRaMacDownlinkStatus.RxSlot + 1 ); + + printf( "RX PORT: %d\r\n", LoRaMacDownlinkStatus.Port ); + + if( LoRaMacDownlinkStatus.BufferSize != 0 ) + { + printf( "RX DATA: \r\n" ); + SerialDisplayHex( LoRaMacDownlinkStatus.Buffer, LoRaMacDownlinkStatus.BufferSize ); + } + + printf( "RX RSSI: %d\r\n", LoRaMacDownlinkStatus.Rssi ); + + printf( "RX SNR: %d\r\n", LoRaMacDownlinkStatus.Snr ); + + printf( "\r\n" ); +} + +void SerialDisplayHex( uint8_t *pData, uint8_t len ) +{ + int i; + bool newline = 0; + + for( i = 0; i < len; i++ ) + { + if( newline != 0 ) + { + printf( "\r\n" ); + newline = 0; + } + + printf( "%02X", pData[i] ); + + if( ( ( i + 1 ) % 16 ) == 0 ) + { + newline = 1; + } + } + printf( "\r\n" ); +} + + + +void DisplayNetworkParam( void ) +{ +#if( OVER_THE_AIR_ACTIVATION != 0 ) + + printf( "DEVEUI: " ); + SerialDisplayHex( DevEui, 8 ); + + printf( "APPEUI: " ); + SerialDisplayHex( AppEui, 8 ); + + printf( "APPKEY: " ); + SerialDisplayHex( AppKey, 16 ); + +#else + + printf( "DEVADDR: " ); + + uint8_t *pData = ( uint8_t* )&DevAddr; + for( int32_t i = 3; i >= 0; i-- ) + { + printf( "%02X", pData[i] ); + } + printf( "\r\n" ); + + printf( "NWKSKEY: " ); + SerialDisplayHex( NwkSKey, 16 ); + + printf( "APPSKEY: " ); + SerialDisplayHex( AppSKey, 16 ); + +#endif +} \ No newline at end of file
diff -r 000000000000 -r 60ff878b27b8 Code/SerialDisplay.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/SerialDisplay.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,31 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Serial display management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Uttam Bhat +*/ +#ifndef __SERIAL_DISPLAY_H__ +#define __SERIAL_DISPLAY_H__ + +#include "board.h" +#include "vt100.h" +#include "Comissioning.h" +#include "LoRaMac.h" +#include "Common.h" +#include "LoRaDeviceFunctions.h" + +void SerialDisplayJoinUpdate( void ); +void SerialDisplayTxUpdate( void ); +void SerialDisplayRxUpdate( void ); +void SerialDisplayHex( uint8_t *pData, uint8_t len ); +void DisplayNetworkParam( void ); + +#endif // __SERIAL_DISPLAY_H__
diff -r 000000000000 -r 60ff878b27b8 Code/board.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/board.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,81 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: Target board general functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __BOARD_H__ +#define __BOARD_H__ + +#include "Comissioning.h" +#include "mbed.h" +#include "system/timer.h" +#include "debug.h" +#include "system/utilities.h" +#include "sx1272-hal.h" + +#ifdef USE_IKS01A1_SENSOR +#include "x_nucleo_iks01a1.h" +#endif +/*! + * Unique Devices IDs register set ( STM32L1xxx ) + */ +#define ID1 ( 0x1FF800D0 ) +#define ID2 ( 0x1FF800D4 ) +#define ID3 ( 0x1FF800E4 ) + +#define LOW_BAT_THRESHOLD 3.45 +#define AIN_VREF 3.3 // STM32 internal refernce +#define AIN_VBAT_DIV 2 // Resistor divider + +extern SX1272MB2xAS Radio; + +extern DigitalIn UsrButton; + +extern DigitalOut Led; + +#ifdef USE_IKS01A1_SENSOR +extern X_NUCLEO_IKS01A1 *mems_expansion_board; +extern MotionSensor *accelerometer; +extern HumiditySensor *humidity_sensor; +extern PressureSensor *pressure_sensor; +extern TempSensor *temp_sensor1; +extern TempSensor *temp_sensor2; +#endif + +/*! + * \brief Initializes the target board peripherals. + */ +void BoardInit( void ); + +/*! + * \brief Measure the Battery level + * + * \retval value battery level ( 0: very low, 254: fully charged ) + */ +uint8_t BoardGetBatteryLevel( void ); + +/*! + * Returns a pseudo random seed generated using the MCU Unique ID + * + * \retval seed Generated pseudo random seed + */ +uint32_t BoardGetRandomSeed( void ); + +/*! + * \brief Generates Lower 32 bits of DEVEUI using 96 bits unique device ID + * + * \param [IN] id Pointer to an array that will contain the Unique ID + */ +void BoardGetDevEUI( uint8_t *id ); + + +#endif // __BOARD_H__
diff -r 000000000000 -r 60ff878b27b8 Code/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/main.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,411 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: LoRaMac classA device implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "mbed.h" +#include "board.h" +#include "radio.h" + +#include "LoRaMac.h" +#include "Comissioning.h" +#include "SerialDisplay.h" +#include "LoRaDeviceFunctions.h" +#include "LoRaMacLayerService.h" + + +#if( OVER_THE_AIR_ACTIVATION != 0 ) + +uint8_t DevEui[] = LORAWAN_DEVICE_EUI; +uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; +uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; + +#else + +uint8_t NwkSKey[] = LORAWAN_NWKSKEY; +uint8_t AppSKey[] = LORAWAN_APPSKEY; +uint32_t DevAddr = LORAWAN_DEVICE_ADDRESS; + +#endif + + +uint8_t AppPort = LORAWAN_APP_PORT; //application port + +uint8_t AppDataSize = LORAWAN_APP_DATA_SIZE; //data size + +uint8_t AppData[LORAWAN_APP_DATA_MAX_SIZE]; //payload array + +uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; //Indicates if the node is sending confirmed or unconfirmed messages + +TimerEvent_t TxNextPacketTimer; //Timer to handle the application data transmission duty cycle + +bool IsTxIntUpdate = false; //Indicates if a new transmit interrupt can be set + +bool NextTx = true; //Indicates if a new packet can be sent + +bool IsNetworkJoinedStatusUpdate = false; //Indicates if the MAC layer network join status has changed. + +bool IsTxUpdate = false; //Indicates if the message sent. + +bool IsRxUpdate = false; //Indicates if the message received in the RX window. + +float sensor_data; //Used to store the sensor data + +uint32_t TxDutyCycleTime = APP_TX_DUTYCYCLE; + +eDevicState DeviceState; + +sLoRaMacUplinkStatus LoRaMacUplinkStatus; + +sLoRaMacDownlinkStatus LoRaMacDownlinkStatus; + +LoRaMacPrimitives_t LoRaPrimitives; + +LoRaMacCallback_t LoRaCallbacks; + +MibRequestConfirm_t LoRaMibReq; + +MlmeReq_t mlmeReq; + +uint16_t ChannelMaskTemp[6] = {0}; + +uint8_t BoardGetBatteryLevel( void ) +{ + return 0xFE; +} +DigitalIn I2cInterrupt( D5 ); +I2C I2c(I2C_SDA, I2C_SCL); + +DigitalOut Pc7( D9 ); +DigitalIn Pc1( A4 ); + +//DigitalIn UsrButton( PC_13 ); +DigitalIn UsrButton( D10 ); + +DigitalOut Led( D6 ); + +#ifdef USE_IKS01A1_SENSOR +X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(); +MotionSensor *accelerometer = mems_expansion_board->GetAccelerometer(); +HumiditySensor *humidity_sensor = mems_expansion_board->ht_sensor;; +PressureSensor *pressure_sensor = mems_expansion_board->pt_sensor; +TempSensor *temp_sensor1 = mems_expansion_board->ht_sensor; +TempSensor *temp_sensor2 = mems_expansion_board->pt_sensor; +#endif + +SX1272MB2xAS Radio( NULL ); + + +uint32_t BoardGetRandomSeed( void ) +{ + return ( ( *( uint32_t* )ID1 ) ^ ( *( uint32_t* )ID2 ) ^ ( *( uint32_t* )ID3 ) ); +} + +void BoardGetDevEUI( uint8_t *id ) +{ + uint32_t *pDevEuiHWord = ( uint32_t* )&id[4]; + + if( *pDevEuiHWord == 0 ) + { + *pDevEuiHWord = BoardGetRandomSeed( ); + } + +} + +static void OnTxNextPacketTimerEvent( void ) +{ + MibRequestConfirm_t mibReq; + LoRaMacStatus_t status; + + TimerStop( &TxNextPacketTimer ); + + mibReq.Type = MIB_NETWORK_JOINED; + status = LoRaMacMibGetRequestConfirm( &mibReq ); + + if( status == LORAMAC_STATUS_OK ) + { + if( mibReq.Param.IsNetworkJoined == true ) + { + DeviceState = DEVICE_STATE_SEND; + } + else + { + DeviceState = DEVICE_STATE_JOIN; + } + NextTx = true; + } +} + +bool SendFrame( void ) +{ + McpsReq_t mcpsReq; + LoRaMacTxInfo_t txInfo; + + if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK ) + { + // Send empty frame in order to flush MAC commands + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fBuffer = NULL; + mcpsReq.Req.Unconfirmed.fBufferSize = 0; + mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; + + LoRaMacUplinkStatus.Acked = false; + LoRaMacUplinkStatus.Port = 0; + LoRaMacUplinkStatus.Buffer = NULL; + LoRaMacUplinkStatus.BufferSize = 0; + } + else + { + LoRaMacUplinkStatus.Acked = false; + LoRaMacUplinkStatus.Port = AppPort; + LoRaMacUplinkStatus.Buffer = AppData; + LoRaMacUplinkStatus.BufferSize = AppDataSize; + + if( ( IsTxConfirmed == false ) || ( LoRaMacUplinkStatus.UplinkCounter == 0 ) ) + { + mcpsReq.Type = MCPS_UNCONFIRMED; + mcpsReq.Req.Unconfirmed.fPort = AppPort; + mcpsReq.Req.Unconfirmed.fBuffer = AppData; + mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize; + mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; + } + else + { + mcpsReq.Type = MCPS_CONFIRMED; + mcpsReq.Req.Confirmed.fPort = AppPort; + mcpsReq.Req.Confirmed.fBuffer = AppData; + mcpsReq.Req.Confirmed.fBufferSize = AppDataSize; + mcpsReq.Req.Confirmed.NbTrials = 8; + mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE; + } + } + + LoRaMacUplinkStatus.Type = mcpsReq.Type; + + if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) + { + return false; + } + return true; +} + +int main( void ) +{ + + TimerTimeCounterInit( ); //initialize timer + + DeviceState = DEVICE_STATE_INIT; // Indicate Device state + + while( 1 ) + { + if( IsNetworkJoinedStatusUpdate == true ) + { + //Checks if the device has joined the server and updates the joined status + IsNetworkJoinedStatusUpdate = false; + LoRaMibReq.Type = MIB_NETWORK_JOINED; + LoRaMacMibGetRequestConfirm( &LoRaMibReq ); + } + + if( IsTxIntUpdate == true ) + { + // Initialize next Tx Interrupt + IsTxIntUpdate = false; + TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); + TimerStart( &TxNextPacketTimer ); + + } + + if( IsRxUpdate == true ) + { + // If downlink received then update Serial Terminal Rx parameters + IsRxUpdate = false; + SerialDisplayRxUpdate( ); + } + + switch( DeviceState ) //realizes different tasks depending on device state + { + case DEVICE_STATE_INIT: + { + + LoRaPrimitives.MacMcpsConfirm = McpsConfirm; //Update uplink and event info status + LoRaPrimitives.MacMcpsIndication = McpsIndication; // + LoRaPrimitives.MacMlmeConfirm = MlmeConfirm; + LoRaCallbacks.GetBatteryLevel = BoardGetBatteryLevel; //0: external power source, 1-254: battery level, 255: couldnt measure battery level + LoRaMacInitialization( &LoRaPrimitives, &LoRaCallbacks ); //Sets radio parameters (channels, frequency, timers, windows) + + TimerInit( &TxNextPacketTimer, OnTxNextPacketTimerEvent ); + + LoRaMibReq.Type = MIB_ADR; + LoRaMibReq.Param.AdrEnable = LORAWAN_ADR_ON; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_PUBLIC_NETWORK; + LoRaMibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_CHANNELS_TX_POWER; + LoRaMibReq.Param.ChannelsTxPower = LORAWAN_TX_POWER; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_CHANNELS_MASK; + LoRaMibReq.Param.ChannelsMask = ChannelMaskTemp; + //channel mask for USE_BAND_915_HYBRID + ChannelMaskTemp[0] = 0x00FF; + ChannelMaskTemp[1] = 0x0000; + ChannelMaskTemp[2] = 0x0000; + ChannelMaskTemp[3] = 0x0000; + ChannelMaskTemp[4] = 0x0001; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMacDownlinkStatus.DownlinkCounter = 0; + + DeviceState = DEVICE_STATE_JOIN; // Change Device state + break; + } + case DEVICE_STATE_JOIN: + { +#if( OVER_THE_AIR_ACTIVATION != 0 ) // OTAA + + BoardGetDevEUI( DevEui ); // Generate DevEUI if not defined by User + + mlmeReq.Type = MLME_JOIN; //Changes Mlmereq content to send in join request + mlmeReq.Req.Join.DevEui = DevEui; + mlmeReq.Req.Join.AppEui = AppEui; + mlmeReq.Req.Join.AppKey = AppKey; + + if( NextTx == true ) + { + LoRaMacMlmeRequest( &mlmeReq ); + } + + SerialDisplayJoinUpdate( ); // Show on serial terminal + + DeviceState = DEVICE_STATE_SLEEP; + +#else // ABP + + // Choose a random device address if not already defined in Config.h + if( DevAddr == 0 ) + { + // Random seed initialization + srand1( BoardGetRandomSeed( ) ); + DevAddr = randr( 0, 0x01FFFFFF ); + } + + LoRaMibReq.Type = MIB_NET_ID; + LoRaMibReq.Param.NetID = LORAWAN_NETWORK_ID; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_DEV_ADDR; + LoRaMibReq.Param.DevAddr = DevAddr; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_NWK_SKEY; + LoRaMibReq.Param.NwkSKey = NwkSKey; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_APP_SKEY; + LoRaMibReq.Param.AppSKey = AppSKey; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + LoRaMibReq.Type = MIB_NETWORK_JOINED; + LoRaMibReq.Param.IsNetworkJoined = true; + LoRaMacMibSetRequestConfirm( &LoRaMibReq ); + + DeviceState = DEVICE_STATE_SEND; +#endif + IsNetworkJoinedStatusUpdate = true; + break; + } + case DEVICE_STATE_SEND: + { + + if( NextTx == true ) + { + //===============Functions to get X_NUCLEO_IKS01A1 sensor data=============== + + temp_sensor2->GetTemperature(&sensor_data); + int16_t tmp_data = (int16_t) (sensor_data*10 + 0.5); + AppData[2] = (int8_t) ( ( tmp_data >> 8 ) & 0xFF ); + AppData[3] = (int8_t) tmp_data & 0xFF; + + pressure_sensor->GetPressure(&sensor_data); + int16_t tmp = (int16_t) ( sensor_data * 10 ); + AppData[6] = ( tmp >> 8 ) & 0xFF; + AppData[7] = ( tmp ) & 0xFF; + + humidity_sensor->GetHumidity(&sensor_data); + AppData[10] = (uint8_t) ( sensor_data * 2 ); + + //accelerometer->Get_X_Axes(Accl_Value); + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[0] >> 8 ) & 0xFF; + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[0] ) & 0xFF; + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[1] >> 8 ) & 0xFF; + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[1] ) & 0xFF; + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[2] >> 8 ) & 0xFF; + //AppData[BuffPtr++] = ( (int16_t) Accl_Value[2] ) & 0xFF; + //===========================Custom payload============================ + + //In this case the custom payload is the cayene LPP structure for the sensors data + AppData[0]=0x01; + AppData[1]=0x67; + + AppData[4]=0x02; + AppData[5]=0x73; + + AppData[8]=0x03; + AppData[9]=0x68; + + + //=========================Cayenne LPP format======================= + /* + STRUCTURE: + + 1 Byte 1 Byte N Bytes 1 Byte 1 Byte M Bytes ... + + Data1 Ch. Data1 Type Data1 Data2 Ch. Data2 Type Data2 ... + + COMMON TYP IDENTIFIERS AND RESOLUTIONS: + + TYPE LPP HEX DATA SIZE RESOLUTION PER BIT + + Temperature 103 67 2 0.1 °C Signed MSB + Humidity 104 68 1 0.5 % Unsigned + Accelerometer 113 71 6 0.001 G Signed MSB per axis + Barometer 115 73 2 0.1 hPa Unsigned MSB + + */ + // Send payload over the air + NextTx = SendFrame( ); + } + + if( NextTx == false ) + { + + SerialDisplayTxUpdate( ); + } + + DeviceState = DEVICE_STATE_SLEEP; + break; + } + case DEVICE_STATE_SLEEP: + { + break; + } + default: + { + DeviceState = DEVICE_STATE_INIT; + break; + } + } + } +}
diff -r 000000000000 -r 60ff878b27b8 Code/vt100.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/vt100.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,213 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2015 Semtech + +Description: VT100 terminal support class + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __VT100_H__ +#define __VT100_H__ + +#ifndef STRING_STACK_LIMIT +#define STRING_STACK_LIMIT 120 +#endif + +/** + * Implements VT100 terminal commands support. + * Implments also the same behaviour has RawSerial class. The only difference + * is located in putc fucntion where writeable check is made befor sending the character. + */ +class VT100 : public SerialBase +{ +public: + enum TextAttributes + { + ATTR_OFF = 0, + BOLD = 1, + USCORE = 4, + BLINK = 5, + REVERSE = 7, + BOLD_OFF = 21, + USCORE_OFF = 24, + BLINK_OFF = 25, + REVERSE_OFF = 27, + }; + + enum Colors + { + BLACK = 0, + RED = 1, + GREEN = 2, + BROWN = 3, + BLUE = 4, + MAGENTA = 5, + CYAN = 6, + WHITE = 7, + }; + + VT100( PinName tx, PinName rx ): SerialBase( tx, rx ) + { + this->baud( 115200 ); + // initializes terminal to "power-on" settings + // ESC c + this->printf( "\x1B\x63" ); + } + + void ClearScreen( uint8_t param ) + { + // ESC [ Ps J + // 0 Clear screen from cursor down + // 1 Clear screen from cursor up + // 2 Clear entire screen + this->printf( "\x1B[%dJ", param ); + } + + void ClearLine( uint8_t param ) + { + // ESC [ Ps K + // 0 Erase from the active position to the end of the line, inclusive (default) + // 1 Erase from the start of the screen to the active position, inclusive + // 2 Erase all of the line, inclusive + this->printf( "\x1B[%dK", param ); + } + + void SetAttribute( uint8_t attr ) + { + // ESC [ Ps;...;Ps m + this->printf( "\x1B[%dm", attr ); + } + + void SetAttribute( uint8_t attr, uint8_t fgcolor, uint8_t bgcolor ) + { + // ESC [ Ps;...;Ps m + this->printf( "\x1B[%d;%d;%dm", attr, fgcolor + 30, bgcolor + 40 ); + } + + void SetCursorMode( uint8_t visible ) + { + if( visible == true ) + { + // ESC [ ? 25 h + this->printf( "\x1B[?25h" ); + } + else + { + // ESC [ ? 25 l + this->printf( "\x1B[?25l" ); + } + } + + void SetCursorPos( uint8_t line, uint8_t col ) + { + // ESC [ Pl ; Pc H + this->printf( "\x1B[%d;%dH", line, col ); + } + + void PutStringAt( uint8_t line, uint8_t col, const char *s ) + { + this->SetCursorPos( line, col ); + this->printf( "%s", s ); + } + + void PutCharAt( uint8_t line, uint8_t col, uint8_t c ) + { + this->SetCursorPos( line, col ); + this->printf( "%c", c ); + } + + void PutHexAt( uint8_t line, uint8_t col, uint16_t n ) + { + this->SetCursorPos( line, col ); + this->printf( "%X", n ); + } + + void PutBoxDrawingChar( uint8_t c ) + { + this->printf( "\x1B(0%c\x1b(B", c ); + } + + bool Readable( void ) + { + return this->readable( ); + } + + uint8_t GetChar( void ) + { + return this->getc( ); + } + + /* + * RawSerial class implmentation copy. + */ + /** Read a char from the serial port + * + * @returns The char read from the serial port + */ + int getc( ) + { + return _base_getc(); + } + + /** Write a char to the serial port + * + * @param c The char to write + * + * @returns The written char or -1 if an error occured + */ + int putc( int c ) + { + while( this->writeable( ) != 1 ); + return _base_putc( c ); + } + + /** Write a string to the serial port + * + * @param str The string to write + * + * @returns 0 if the write succeeds, EOF for error + */ + int puts( const char *str ) + { + while( *str ) + putc( *str++ ); + return 0; + } + + // Experimental support for printf in RawSerial. No Stream inheritance + // means we can't call printf() directly, so we use sprintf() instead. + // We only call malloc() for the sprintf() buffer if the buffer + // length is above a certain threshold, otherwise we use just the stack. + int printf( const char *format, ... ) + { + std::va_list arg; + va_start( arg, format ); + int len = vsnprintf( NULL, 0, format, arg ); + if( len < STRING_STACK_LIMIT ) + { + char temp[STRING_STACK_LIMIT]; + vsprintf( temp, format, arg ); + puts( temp ); + } + else + { + char *temp = new char[len + 1]; + vsprintf( temp, format, arg ); + puts( temp ); + delete[] temp; + } + va_end( arg ); + return len; + } + +private: + +}; + +#endif // __VT100_H__
diff -r 000000000000 -r 60ff878b27b8 LoRaWAN-lib-v1_0_1.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoRaWAN-lib-v1_0_1.lib Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/dgabino/code/LoRaWAN-lib/#54937781831b
diff -r 000000000000 -r 60ff878b27b8 SX1272Lib.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib.lib Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/Semtech/code/SX1272Lib/#69d5976b504d
diff -r 000000000000 -r 60ff878b27b8 X_NUCLEO_IKS01A1.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/X_NUCLEO_IKS01A1.lib Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/teams/ST/code/X_NUCLEO_IKS01A1/#f4fa3dad9ec4
diff -r 000000000000 -r 60ff878b27b8 system/crypto/aes.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/aes.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,936 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state (there are options to use 32-bit types if available). + + The combination of mix columns and byte substitution used here is based on + that developed by Karl Malbrain. His contribution is acknowledged. + */ + +/* define if you have a fast memcpy function on your system */ +#if 0 +# define HAVE_MEMCPY +# include <string.h> +# if defined( _MSC_VER ) +# include <intrin.h> +# pragma intrinsic( memcpy ) +# endif +#endif + + +#include <stdlib.h> +#include <stdint.h> + +/* define if you have fast 32-bit types on your system */ +#if ( __CORTEX_M != 0 ) // if Cortex is different from M0/M0+ +# define HAVE_UINT_32T +#endif + +/* define if you don't want any tables */ +#if 1 +# define USE_TABLES +#endif + +/* On Intel Core 2 duo VERSION_1 is faster */ + +/* alternative versions (test for performance on your system) */ +#if 1 +# define VERSION_1 +#endif + +#include "aes.h" + +//#if defined( HAVE_UINT_32T ) +// typedef unsigned long uint32_t; +//#endif + +/* functions for finite field multiplication in the AES Galois field */ + +#define WPOLY 0x011b +#define BPOLY 0x1b +#define DPOLY 0x008d + +#define f1(x) (x) +#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) +#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) +#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \ + ^ (((x >> 5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#if defined( USE_TABLES ) + +#define sb_data(w) { /* S Box data values */ \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) { /* inverse S Box data values */ \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) { /* basic data for forming finite field tables */ \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +static const uint8_t sbox[256] = sb_data(f1); + +#if defined( AES_DEC_PREKEYED ) +static const uint8_t isbox[256] = isb_data(f1); +#endif + +static const uint8_t gfm2_sbox[256] = sb_data(f2); +static const uint8_t gfm3_sbox[256] = sb_data(f3); + +#if defined( AES_DEC_PREKEYED ) +static const uint8_t gfmul_9[256] = mm_data(f9); +static const uint8_t gfmul_b[256] = mm_data(fb); +static const uint8_t gfmul_d[256] = mm_data(fd); +static const uint8_t gfmul_e[256] = mm_data(fe); +#endif + +#define s_box(x) sbox[(x)] +#if defined( AES_DEC_PREKEYED ) +#define is_box(x) isbox[(x)] +#endif +#define gfm2_sb(x) gfm2_sbox[(x)] +#define gfm3_sb(x) gfm3_sbox[(x)] +#if defined( AES_DEC_PREKEYED ) +#define gfm_9(x) gfmul_9[(x)] +#define gfm_b(x) gfmul_b[(x)] +#define gfm_d(x) gfmul_d[(x)] +#define gfm_e(x) gfmul_e[(x)] +#endif +#else + +/* this is the high bit of x right shifted by 1 */ +/* position. Since the starting polynomial has */ +/* 9 bits (0x11b), this right shift keeps the */ +/* values of all top bits within a byte */ + +static uint8_t hibit(const uint8_t x) +{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint8_t gf_inv(const uint8_t x) +{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) + return x; + + for( ; ; ) + { + if(n1) + while(n2 >= n1) /* divide polynomial p2 by p1 */ + { + n2 /= n1; /* shift smaller polynomial left */ + p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ + v2 ^= (v1 * n2); /* shift accumulated value and */ + n2 = hibit(p2); /* add into result */ + } + else + return v1; + + if(n2) /* repeat with values swapped */ + while(n1 >= n2) + { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + else + return v2; + } +} + +/* The forward and inverse affine transformations used in the S-box */ +uint8_t fwd_affine(const uint8_t x) +{ +#if defined( HAVE_UINT_32T ) + uint32_t w = x; + w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); + return 0x63 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4) + ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4); +#endif +} + +uint8_t inv_affine(const uint8_t x) +{ +#if defined( HAVE_UINT_32T ) + uint32_t w = x; + w = (w << 1) ^ (w << 3) ^ (w << 6); + return 0x05 ^ ((w ^ (w >> 8)) & 0xff); +#else + return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6) + ^ (x >> 7) ^ (x >> 5) ^ (x >> 2); +#endif +} + +#define s_box(x) fwd_affine(gf_inv(x)) +#define is_box(x) gf_inv(inv_affine(x)) +#define gfm2_sb(x) f2(s_box(x)) +#define gfm3_sb(x) f3(s_box(x)) +#define gfm_9(x) f9(x) +#define gfm_b(x) fb(x) +#define gfm_d(x) fd(x) +#define gfm_e(x) fe(x) + +#endif + +#if defined( HAVE_MEMCPY ) +# define block_copy_nn(d, s, l) memcpy(d, s, l) +# define block_copy(d, s) memcpy(d, s, N_BLOCK) +#else +# define block_copy_nn(d, s, l) copy_block_nn(d, s, l) +# define block_copy(d, s) copy_block(d, s) +#endif + +static void copy_block( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0]; + ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1]; + ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2]; + ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3]; +#else + ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0]; + ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1]; + ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2]; + ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3]; + ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4]; + ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5]; + ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6]; + ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7]; + ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8]; + ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9]; + ((uint8_t*)d)[10] = ((uint8_t*)s)[10]; + ((uint8_t*)d)[11] = ((uint8_t*)s)[11]; + ((uint8_t*)d)[12] = ((uint8_t*)s)[12]; + ((uint8_t*)d)[13] = ((uint8_t*)s)[13]; + ((uint8_t*)d)[14] = ((uint8_t*)s)[14]; + ((uint8_t*)d)[15] = ((uint8_t*)s)[15]; +#endif +} + +static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn ) +{ + while( nn-- ) + //*((uint8_t*)d)++ = *((uint8_t*)s)++; + *d++ = *s++; +} + +static void xor_block( void *d, const void *s ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0]; + ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1]; + ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2]; + ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3]; +#else + ((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0]; + ((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1]; + ((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2]; + ((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3]; + ((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4]; + ((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5]; + ((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6]; + ((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7]; + ((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8]; + ((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9]; + ((uint8_t*)d)[10] ^= ((uint8_t*)s)[10]; + ((uint8_t*)d)[11] ^= ((uint8_t*)s)[11]; + ((uint8_t*)d)[12] ^= ((uint8_t*)s)[12]; + ((uint8_t*)d)[13] ^= ((uint8_t*)s)[13]; + ((uint8_t*)d)[14] ^= ((uint8_t*)s)[14]; + ((uint8_t*)d)[15] ^= ((uint8_t*)s)[15]; +#endif +} + +static void copy_and_key( void *d, const void *s, const void *k ) +{ +#if defined( HAVE_UINT_32T ) + ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0]; + ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1]; + ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2]; + ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3]; +#elif 1 + ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0]; + ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1]; + ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2]; + ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3]; + ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4]; + ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5]; + ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6]; + ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7]; + ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8]; + ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9]; + ((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10]; + ((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11]; + ((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12]; + ((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13]; + ((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14]; + ((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15]; +#else + block_copy(d, s); + xor_block(d, k); +#endif +} + +static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ) +{ + xor_block(d, k); +} + +static void shift_sub_rows( uint8_t st[N_BLOCK] ) +{ uint8_t tt; + + st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]); + st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]); + + tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]); + st[ 9] = s_box(st[13]); st[13] = s_box( tt ); + + tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt ); + tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt ); + + tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]); + st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt ); +} + +#if defined( AES_DEC_PREKEYED ) + +static void inv_shift_sub_rows( uint8_t st[N_BLOCK] ) +{ uint8_t tt; + + st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]); + st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]); + + tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]); + st[ 5] = is_box(st[1]); st[ 1] = is_box( tt ); + + tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt ); + tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt ); + + tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]); + st[11] = is_box(st[15]); st[15] = is_box( tt ); +} + +#endif + +#if defined( VERSION_1 ) + static void mix_sub_columns( uint8_t dt[N_BLOCK] ) + { uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else + static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) + { +#endif + dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]); + dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]); + dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]); + dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]); + + dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]); + dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]); + dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]); + dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]); + + dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]); + dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]); + dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]); + dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]); + + dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]); + dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]); + dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]); + dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]); + } + +#if defined( AES_DEC_PREKEYED ) + +#if defined( VERSION_1 ) + static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] ) + { uint8_t st[N_BLOCK]; + block_copy(st, dt); +#else + static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) + { +#endif + dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3])); + dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3])); + dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3])); + dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3])); + + dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7])); + dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7])); + dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7])); + dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7])); + + dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11])); + dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11])); + dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11])); + dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11])); + + dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15])); + dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15])); + dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15])); + dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15])); + } + +#endif + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +/* Set the cipher key for the pre-keyed version */ + +return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] ) +{ + uint8_t cc, rc, hi; + + switch( keylen ) + { + case 16: + case 24: + case 32: + break; + default: + ctx->rnd = 0; + return ( uint8_t )-1; + } + block_copy_nn(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + { uint8_t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if( cc % keylen == 0 ) + { + tt = t0; + t0 = s_box(t1) ^ rc; + t1 = s_box(t2); + t2 = s_box(t3); + t3 = s_box(tt); + rc = f2(rc); + } + else if( keylen > 24 && cc % keylen == 16 ) + { + t0 = s_box(t0); + t1 = s_box(t1); + t2 = s_box(t2); + t3 = s_box(t3); + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } + return 0; +} + +#endif + +#if defined( AES_ENC_PREKEYED ) + +/* Encrypt a single block of 16 bytes */ + +return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch ); + + for( r = 1 ; r < ctx->rnd ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + add_round_key( s1, ctx->ksch + r * N_BLOCK); + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); + } +#endif + shift_sub_rows( s1 ); + copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); + } + else + return ( uint8_t )-1; + return 0; +} + +/* CBC encrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) +{ + + while(n_block--) + { + xor_block(iv, in); + if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + //memcpy(out, iv, N_BLOCK); + block_copy(out, iv); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_DEC_PREKEYED ) + +/* Decrypt a single block of 16 bytes */ + +return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); + inv_shift_sub_rows( s1 ); + + for( r = ctx->rnd ; --r ; ) +#if defined( VERSION_1 ) + { + add_round_key( s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, ctx->ksch ); + } + else + return -1; + return 0; +} + +/* CBC decrypt a number of blocks (input and return an IV) */ + +return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out, + int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) +{ + while(n_block--) + { uint8_t tmp[N_BLOCK]; + + //memcpy(tmp, in, N_BLOCK); + block_copy(tmp, in); + if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + xor_block(out, iv); + //memcpy(iv, tmp, N_BLOCK); + block_copy(iv, tmp); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} + +#endif + +#if defined( AES_ENC_128_OTFK ) + +/* The 'on the fly' encryption key update for for 128 bit keys */ + +static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) +{ uint8_t s1[N_BLOCK], r, rc = 1; + + if(o_key != key) + block_copy( o_key, key ); + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 10 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns( s1 ); + update_encrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_128_OTFK ) + +/* The 'on the fly' decryption key update for for 128 bit keys */ + +static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + for( cc = 12; cc > 0; cc -= 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + *rc = d2(*rc); + k[0] ^= s_box(k[13]) ^ *rc; + k[1] ^= s_box(k[14]); + k[2] ^= s_box(k[15]); + k[3] ^= s_box(k[12]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ + +void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 0x6c; + if(o_key != key) + block_copy( o_key, key ); + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 10 ; --r ; ) +#if defined( VERSION_1 ) + { + update_decrypt_key_128( o_key, &rc ); + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + update_decrypt_key_128( o_key, &rc ); + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + update_decrypt_key_128( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_ENC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); + *rc = f2( *rc ); + + for(cc = 4; cc < 16; cc += 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for( cc = 20; cc < 32; cc += 4 ) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } +} + +/* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ + +void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 1; + if(o_key != key) + { + block_copy( o_key, key ); + block_copy( o_key + 16, key + 16 ); + } + copy_and_key( s1, in, o_key ); + + for( r = 1 ; r < 14 ; ++r ) +#if defined( VERSION_1 ) + { + mix_sub_columns(s1); + if( r & 1 ) + add_round_key( s1, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key ); + } + } +#else + { uint8_t s2[N_BLOCK]; + mix_sub_columns( s2, s1 ); + if( r & 1 ) + copy_and_key( s1, s2, o_key + 16 ); + else + { + update_encrypt_key_256( o_key, &rc ); + copy_and_key( s1, s2, o_key ); + } + } +#endif + + shift_sub_rows( s1 ); + update_encrypt_key_256( o_key, &rc ); + copy_and_key( out, s1, o_key ); +} + +#endif + +#if defined( AES_DEC_256_OTFK ) + +/* The 'on the fly' encryption key update for for 256 bit keys */ + +static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) +{ uint8_t cc; + + for(cc = 28; cc > 16; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + k[16] ^= s_box(k[12]); + k[17] ^= s_box(k[13]); + k[18] ^= s_box(k[14]); + k[19] ^= s_box(k[15]); + + for(cc = 12; cc > 0; cc -= 4) + { + k[cc + 0] ^= k[cc - 4]; + k[cc + 1] ^= k[cc - 3]; + k[cc + 2] ^= k[cc - 2]; + k[cc + 3] ^= k[cc - 1]; + } + + *rc = d2(*rc); + k[0] ^= s_box(k[29]) ^ *rc; + k[1] ^= s_box(k[30]); + k[2] ^= s_box(k[31]); + k[3] ^= s_box(k[28]); +} + +/* Decrypt a single block of 16 bytes with 'on the fly' + 256 bit keying +*/ +void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) +{ + uint8_t s1[N_BLOCK], r, rc = 0x80; + + if(o_key != key) + { + block_copy( o_key, key ); + block_copy( o_key + 16, key + 16 ); + } + + copy_and_key( s1, in, o_key ); + inv_shift_sub_rows( s1 ); + + for( r = 14 ; --r ; ) +#if defined( VERSION_1 ) + { + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + add_round_key( s1, o_key + 16 ); + } + else + add_round_key( s1, o_key ); + inv_mix_sub_columns( s1 ); + } +#else + { uint8_t s2[N_BLOCK]; + if( ( r & 1 ) ) + { + update_decrypt_key_256( o_key, &rc ); + copy_and_key( s2, s1, o_key + 16 ); + } + else + copy_and_key( s2, s1, o_key ); + inv_mix_sub_columns( s1, s2 ); + } +#endif + copy_and_key( out, s1, o_key ); +} + +#endif
diff -r 000000000000 -r 60ff878b27b8 system/crypto/aes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/aes.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,160 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue 09/09/2006 + + This is an AES implementation that uses only 8-bit byte operations on the + cipher state. + */ + +#ifndef AES_H +#define AES_H + +#if 1 +# define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ +#endif +#if 0 +# define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ +#endif +#if 0 +# define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ +#endif +#if 0 +# define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ +#endif + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +typedef uint8_t return_type; + +/* Warning: The key length for 256 bit keys overflows a byte + (see comment below) +*/ + +typedef uint8_t length_type; + +typedef struct +{ uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint8_t rnd; +} aes_context; + +/* The following calls are for a precomputed key schedule + + NOTE: If the length_type used for the key length is an + unsigned 8-bit character, a key length of 256 bits must + be entered as a length in bytes (valid inputs are hence + 128, 192, 16, 24 and 32). +*/ + +#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) + +return_type aes_set_key( const uint8_t key[], + length_type keylen, + aes_context ctx[1] ); +#endif + +#if defined( AES_ENC_PREKEYED ) + +return_type aes_encrypt( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1] ); + +return_type aes_cbc_encrypt( const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1] ); +#endif + +#if defined( AES_DEC_PREKEYED ) + +return_type aes_decrypt( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const aes_context ctx[1] ); + +return_type aes_cbc_decrypt( const uint8_t *in, + uint8_t *out, + int32_t n_block, + uint8_t iv[N_BLOCK], + const aes_context ctx[1] ); +#endif + +/* The following calls are for 'on the fly' keying. In this case the + encryption and decryption keys are different. + + The encryption subroutines take a key in an array of bytes in + key[L] where L is 16, 24 or 32 bytes for key lengths of 128, + 192, and 256 bits respectively. They then encrypts the input + data, in[] with this key and put the reult in the output array + out[]. In addition, the second key array, o_key[L], is used + to output the key that is needed by the decryption subroutine + to reverse the encryption operation. The two key arrays can + be the same array but in this case the original key will be + overwritten. + + In the same way, the decryption subroutines output keys that + can be used to reverse their effect when used for encryption. + + Only 128 and 256 bit keys are supported in these 'on the fly' + modes. +*/ + +#if defined( AES_ENC_128_OTFK ) +void aes_encrypt_128( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK] ); +#endif + +#if defined( AES_DEC_128_OTFK ) +void aes_decrypt_128( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[N_BLOCK], + uint8_t o_key[N_BLOCK] ); +#endif + +#if defined( AES_ENC_256_OTFK ) +void aes_encrypt_256( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK] ); +#endif + +#if defined( AES_DEC_256_OTFK ) +void aes_decrypt_256( const uint8_t in[N_BLOCK], + uint8_t out[N_BLOCK], + const uint8_t key[2 * N_BLOCK], + uint8_t o_key[2 * N_BLOCK] ); +#endif + +#endif
diff -r 000000000000 -r 60ff878b27b8 system/crypto/cmac.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/cmac.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,153 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ +//#include <sys/param.h> +//#include <sys/systm.h> +#include <stdint.h> +#include "aes.h" +#include "cmac.h" +#include "utilities.h" + +#define LSHIFT(v, r) do { \ + int32_t i; \ + for (i = 0; i < 15; i++) \ + (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \ + (r)[15] = (v)[15] << 1; \ + } while (0) + +#define XOR(v, r) do { \ + int32_t i; \ + for (i = 0; i < 16; i++) \ + { \ + (r)[i] = (r)[i] ^ (v)[i]; \ + } \ + } while (0) \ + + +void AES_CMAC_Init(AES_CMAC_CTX *ctx) +{ + memset1(ctx->X, 0, sizeof ctx->X); + ctx->M_n = 0; + memset1(ctx->rijndael.ksch, '\0', 240); +} + +void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]) +{ + //rijndael_set_key_enc_only(&ctx->rijndael, key, 128); + aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael); +} + +void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len) +{ + uint32_t mlen; + uint8_t in[16]; + + if (ctx->M_n > 0) { + mlen = MIN(16 - ctx->M_n, len); + memcpy1(ctx->M_last + ctx->M_n, data, mlen); + ctx->M_n += mlen; + if (ctx->M_n < 16 || len == mlen) + return; + XOR(ctx->M_last, ctx->X); + //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + aes_encrypt( ctx->X, ctx->X, &ctx->rijndael); + data += mlen; + len -= mlen; + } + while (len > 16) { /* not last block */ + + XOR(data, ctx->X); + //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); + + memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten + aes_encrypt( in, in, &ctx->rijndael); + memcpy1(&ctx->X[0], in, 16); + + data += 16; + len -= 16; + } + /* potential last block, save it */ + memcpy1(ctx->M_last, data, len); + ctx->M_n = len; +} + +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx) +{ + uint8_t K[16]; + uint8_t in[16]; + /* generate subkey K1 */ + memset1(K, '\0', 16); + + //rijndael_encrypt(&ctx->rijndael, K, K); + + aes_encrypt( K, K, &ctx->rijndael); + + if (K[0] & 0x80) { + LSHIFT(K, K); + K[15] ^= 0x87; + } else + LSHIFT(K, K); + + + if (ctx->M_n == 16) { + /* last block was a complete block */ + XOR(K, ctx->M_last); + + } else { + /* generate subkey K2 */ + if (K[0] & 0x80) { + LSHIFT(K, K); + K[15] ^= 0x87; + } else + LSHIFT(K, K); + + /* padding(M_last) */ + ctx->M_last[ctx->M_n] = 0x80; + while (++ctx->M_n < 16) + ctx->M_last[ctx->M_n] = 0; + + XOR(K, ctx->M_last); + + + } + XOR(ctx->M_last, ctx->X); + + //rijndael_encrypt(&ctx->rijndael, ctx->X, digest); + + memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten + aes_encrypt(in, digest, &ctx->rijndael); + memset1(K, 0, sizeof K); + +} +
diff -r 000000000000 -r 60ff878b27b8 system/crypto/cmac.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/crypto/cmac.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,63 @@ +/************************************************************************** +Copyright (C) 2009 Lander Casado, Philippas Tsigas + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal with the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimers. Redistributions in +binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimers in the documentation and/or +other materials provided with the distribution. + +In no event shall the authors or copyright holders be liable for any special, +incidental, indirect or consequential damages of any kind, or any damages +whatsoever resulting from loss of use, data or profits, whether or not +advised of the possibility of damage, and on any theory of liability, +arising out of or in connection with the use or performance of this software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS WITH THE SOFTWARE + +*****************************************************************************/ + +#ifndef _CMAC_H_ +#define _CMAC_H_ + +#include "aes.h" + +#define AES_CMAC_KEY_LENGTH 16 +#define AES_CMAC_DIGEST_LENGTH 16 + +typedef struct _AES_CMAC_CTX { + aes_context rijndael; + uint8_t X[16]; + uint8_t M_last[16]; + uint32_t M_n; + } AES_CMAC_CTX; + +//#include <sys/cdefs.h> + +//__BEGIN_DECLS +void AES_CMAC_Init(AES_CMAC_CTX * ctx); +void AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]); +void AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len); + // __attribute__((__bounded__(__string__,2,3))); +void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx); + // __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH))); +//__END_DECLS + +#endif /* _CMAC_H_ */ +
diff -r 000000000000 -r 60ff878b27b8 system/mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/mbed.bld Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/7c328cabac7e \ No newline at end of file
diff -r 000000000000 -r 60ff878b27b8 system/timer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/timer.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,78 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "board.h" + +Timer TimeCounter; +Ticker LoadTimeCounter; + +volatile uint32_t CurrentTime = 0; + +void TimerResetTimeCounter( void ) +{ + CurrentTime = CurrentTime + TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); +} + +void TimerTimeCounterInit( void ) +{ + TimeCounter.start( ); + LoadTimeCounter.attach( &TimerResetTimeCounter, 10 ); +} + +TimerTime_t TimerGetCurrentTime( void ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( ( TimerTime_t )CurrentTime ); +} + +TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( TimerTime_t )( CurrentTime - savedTime ); +} + +TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture ) +{ + CurrentTime += TimeCounter.read_us( ); + TimeCounter.reset( ); + TimeCounter.start( ); + return ( TimerTime_t )( CurrentTime + eventInFuture ); +} + +void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ) +{ + obj->value = 0; + obj->Callback = callback; +} + +void TimerStart( TimerEvent_t *obj ) +{ + obj->Timer.attach_us( obj->Callback, obj->value ); +} + +void TimerStop( TimerEvent_t *obj ) +{ + obj->Timer.detach( ); +} + +void TimerSetValue( TimerEvent_t *obj, uint32_t value ) +{ + obj->value = value; +}
diff -r 000000000000 -r 60ff878b27b8 system/timer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/timer.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,107 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include "mbed.h" + +/*! + * \brief Timer object description + */ +typedef struct TimerEvent_s +{ + uint32_t value; + void ( *Callback )( void ); + Ticker Timer; +}TimerEvent_t; + +/*! + * \brief Timer time variable definition + */ +#ifndef TimerTime_t +typedef uint32_t TimerTime_t; +#endif + +/*! + * \brief Inializes the timer used to get current time. + * + * \remark Current time corresponds to the time since system startup + */ +void TimerTimeCounterInit( void ); + +/*! + * \brief Initializes the timer object + * + * \remark TimerSetValue function must be called before starting the timer. + * this function initializes timestamp and reload value at 0. + * + * \param [IN] obj Structure containing the timer object parameters + * \param [IN] callback Function callback called at the end of the timeout + */ +void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ); + +/*! + * \brief Starts and adds the timer object to the list of timer events + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerStart( TimerEvent_t *obj ); + +/*! + * \brief Stops and removes the timer object from the list of timer events + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerStop( TimerEvent_t *obj ); + +/*! + * \brief Resets the timer object + * + * \param [IN] obj Structure containing the timer object parameters + */ +void TimerReset( TimerEvent_t *obj ); + +/*! + * \brief Set timer new timeout value + * + * \param [IN] obj Structure containing the timer object parameters + * \param [IN] value New timer timeout value + */ +void TimerSetValue( TimerEvent_t *obj, uint32_t value ); + +/*! + * \brief Read the current time + * + * \retval time returns current time + */ +TimerTime_t TimerGetCurrentTime( void ); + +/*! + * \brief Return the Time elapsed since a fix moment in Time + * + * \param [IN] savedTime fix moment in Time + * \retval time returns elapsed time + */ +TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); + +/*! + * \brief Return the Time elapsed since a fix moment in Time + * + * \param [IN] eventInFuture fix moment in the future + * \retval time returns difference between now and future event + */ +TimerTime_t TimerGetFutureTime( TimerTime_t eventInFuture ); + +#endif // __TIMER_H__
diff -r 000000000000 -r 60ff878b27b8 system/utilities.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/utilities.cpp Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,85 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Helper functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include <stdlib.h> +#include <stdio.h> +#include "board.h" +#include "utilities.h" + +/*! + * Redefinition of rand() and srand() standard C functions. + * These functions are redefined in order to get the same behavior across + * different compiler toolchains implementations. + */ +// Standard random functions redefinition start +#define RAND_LOCAL_MAX 2147483647L + +static uint32_t next = 1; + +int32_t rand1( void ) +{ + return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX ); +} + +void srand1( uint32_t seed ) +{ + next = seed; +} +// Standard random functions redefinition end + +int32_t randr( int32_t min, int32_t max ) +{ + return ( int32_t )rand1( ) % ( max - min + 1 ) + min; +} + +void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) +{ + while( size-- ) + { + *dst++ = *src++; + } +} + +void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) +{ + dst = dst + ( size - 1 ); + while( size-- ) + { + *dst-- = *src++; + } +} + +void memset1( uint8_t *dst, uint8_t value, uint16_t size ) +{ + while( size-- ) + { + *dst++ = value; + } +} + +int8_t Nibble2HexChar( uint8_t a ) +{ + if( a < 10 ) + { + return '0' + a; + } + else if( a < 16 ) + { + return 'A' + ( a - 10 ); + } + else + { + return '?'; + } +}
diff -r 000000000000 -r 60ff878b27b8 system/utilities.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/system/utilities.h Tue Apr 03 17:09:34 2018 +0000 @@ -0,0 +1,99 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Helper functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __UTILITIES_H__ +#define __UTILITIES_H__ + +/*! + * \brief Returns the minimum value betwen a and b + * + * \param [IN] a 1st value + * \param [IN] b 2nd value + * \retval minValue Minimum value + */ +#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) + +/*! + * \brief Returns the maximum value betwen a and b + * + * \param [IN] a 1st value + * \param [IN] b 2nd value + * \retval maxValue Maximum value + */ +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) + +/*! + * \brief Returns 2 raised to the power of n + * + * \param [IN] n power value + * \retval result of raising 2 to the power n + */ +#define POW2( n ) ( 1 << n ) + +/*! + * \brief Initializes the pseudo ramdom generator initial value + * + * \param [IN] seed Pseudo ramdom generator initial value + */ +void srand1( uint32_t seed ); + +/*! + * \brief Computes a random number between min and max + * + * \param [IN] min range minimum value + * \param [IN] max range maximum value + * \retval random random value in range min..max + */ +int32_t randr( int32_t min, int32_t max ); + +/*! + * \brief Copies size elements of src array to dst array + * + * \remark STM32 Standard memcpy function only works on pointers that are aligned + * + * \param [OUT] dst Destination array + * \param [IN] src Source array + * \param [IN] size Number of bytes to be copied + */ +void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ); + +/*! + * \brief Copies size elements of src array to dst array reversing the byte order + * + * \param [OUT] dst Destination array + * \param [IN] src Source array + * \param [IN] size Number of bytes to be copied + */ +void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ); + +/*! + * \brief Set size elements of dst array with value + * + * \remark STM32 Standard memset function only works on pointers that are aligned + * + * \param [OUT] dst Destination array + * \param [IN] value Default value + * \param [IN] size Number of bytes to be copied + */ +void memset1( uint8_t *dst, uint8_t value, uint16_t size ); + +/*! + * \brief Converts a nibble to an hexadecimal character + * + * \param [IN] a Nibble to be converted + * \retval hexChar Converted hexadecimal character + */ +int8_t Nibble2HexChar( uint8_t a ); + +#endif // __UTILITIES_H__