http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/src/mac/LoRaMacCrypto.c ---------------------------------------------------------------------- diff --git a/net/lora/node/src/mac/LoRaMacCrypto.c b/net/lora/node/src/mac/LoRaMacCrypto.c new file mode 100644 index 0000000..81f93ed --- /dev/null +++ b/net/lora/node/src/mac/LoRaMacCrypto.c @@ -0,0 +1,203 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + ___ _____ _ ___ _ _____ ___ ___ ___ ___ +/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| +\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| +|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| +embedded.connectivity.solutions=============== + +Description: LoRa MAC layer implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE ) +*/ +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include "node/utilities.h" + +#include "aes.h" +#include "cmac.h" + +#include "node/mac/LoRaMacCrypto.h" + +/*! + * CMAC/AES Message Integrity Code (MIC) Block B0 size + */ +#define LORAMAC_MIC_BLOCK_B0_SIZE 16 + +/*! + * MIC field computation initial data + */ +static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +/*! + * Contains the computed MIC field. + * + * \remark Only the 4 first bytes are used + */ +static uint8_t Mic[16]; + +/*! + * Encryption aBlock and sBlock + */ +static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +/*! + * AES computation context variable + */ +static aes_context AesContext; + +/*! + * CMAC computation context variable + */ +//static AES_CMAC_CTX AesCmacCtx[1]; + +/*! + * \brief Computes the LoRaMAC frame MIC field + * + * \param [IN] buffer Data buffer + * \param [IN] size Data buffer size + * \param [IN] key AES key to be used + * \param [IN] address Frame address + * \param [IN] dir Frame direction [0: uplink, 1: downlink] + * \param [IN] sequenceCounter Frame sequence counter + * \param [OUT] mic Computed MIC field + */ +void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ) +{ + MicBlockB0[5] = dir; + + MicBlockB0[6] = ( address ) & 0xFF; + MicBlockB0[7] = ( address >> 8 ) & 0xFF; + MicBlockB0[8] = ( address >> 16 ) & 0xFF; + MicBlockB0[9] = ( address >> 24 ) & 0xFF; + + MicBlockB0[10] = ( sequenceCounter ) & 0xFF; + MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF; + MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF; + MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF; + + MicBlockB0[15] = size & 0xFF; + + //AES_CMAC_Init( AesCmacCtx ); + + //AES_CMAC_SetKey( AesCmacCtx, key ); + + //AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE ); + + //AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); + + //AES_CMAC_Final( Mic, AesCmacCtx ); + + *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); +} + +void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ) +{ + uint16_t i; + uint8_t bufferIndex = 0; + uint16_t ctr = 1; + + memset( AesContext.ksch, '\0', 240 ); + //aes_set_key( key, 16, &AesContext ); + + aBlock[5] = dir; + + aBlock[6] = ( address ) & 0xFF; + aBlock[7] = ( address >> 8 ) & 0xFF; + aBlock[8] = ( address >> 16 ) & 0xFF; + aBlock[9] = ( address >> 24 ) & 0xFF; + + aBlock[10] = ( sequenceCounter ) & 0xFF; + aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF; + aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF; + aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF; + + while( size >= 16 ) + { + aBlock[15] = ( ( ctr ) & 0xFF ); + ctr++; + //aes_encrypt( aBlock, sBlock, &AesContext ); + for( i = 0; i < 16; i++ ) + { + encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; + } + size -= 16; + bufferIndex += 16; + } + + if( size > 0 ) + { + aBlock[15] = ( ( ctr ) & 0xFF ); + //aes_encrypt( aBlock, sBlock, &AesContext ); + for( i = 0; i < size; i++ ) + { + encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; + } + } +} + +void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ) +{ + LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer ); +} + +void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ) +{ + //AES_CMAC_Init( AesCmacCtx ); + + //AES_CMAC_SetKey( AesCmacCtx, key ); + + //AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); + + //AES_CMAC_Final( Mic, AesCmacCtx ); + + *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); +} + +void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ) +{ + memset( AesContext.ksch, '\0', 240 ); + //aes_set_key( key, 16, &AesContext ); + //aes_encrypt( buffer, decBuffer, &AesContext ); + // Check if optional CFList is included + if( size >= 16 ) + { + //aes_encrypt( buffer + 16, decBuffer + 16, &AesContext ); + } +} + +void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ) +{ + uint8_t nonce[16]; + uint8_t *pDevNonce = ( uint8_t * )&devNonce; + + memset( AesContext.ksch, '\0', 240 ); + //aes_set_key( key, 16, &AesContext ); + + memset( nonce, 0, sizeof( nonce ) ); + nonce[0] = 0x01; + memcpy( nonce + 1, appNonce, 6 ); + memcpy( nonce + 7, pDevNonce, 2 ); + //aes_encrypt( nonce, nwkSKey, &AesContext ); + + memset( nonce, 0, sizeof( nonce ) ); + nonce[0] = 0x02; + memcpy( nonce + 1, appNonce, 6 ); + memcpy( nonce + 7, pDevNonce, 2 ); + //aes_encrypt( nonce, appSKey, &AesContext ); +}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/src/mac/aes.h ---------------------------------------------------------------------- diff --git a/net/lora/node/src/mac/aes.h b/net/lora/node/src/mac/aes.h new file mode 100644 index 0000000..5fdc143 --- /dev/null +++ b/net/lora/node/src/mac/aes.h @@ -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 http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/src/mac/cmac.h ---------------------------------------------------------------------- diff --git a/net/lora/node/src/mac/cmac.h b/net/lora/node/src/mac/cmac.h new file mode 100644 index 0000000..c12e970 --- /dev/null +++ b/net/lora/node/src/mac/cmac.h @@ -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_ */ + http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/src/misc.c ---------------------------------------------------------------------- diff --git a/net/lora/node/src/misc.c b/net/lora/node/src/misc.c new file mode 100644 index 0000000..3d4576a --- /dev/null +++ b/net/lora/node/src/misc.c @@ -0,0 +1,45 @@ +#include <stdlib.h> + +#include "syscfg/syscfg.h" +#include "node/utilities.h" +#include "lora_priv.h" + +int32_t +randr(int32_t min, int32_t max) +{ + return rand() % (max - min + 1) + min; +} + +void +memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) +{ + dst = dst + ( size - 1 ); + while( size-- ) + { + *dst-- = *src++; + } +} + +double +ceil(double d) +{ + int64_t i; + + i = d; + if (d == i) { + return i; + } + return i + 1; +} + +double +floor(double d) +{ + return (int64_t)d; +} + +double +round(double d) +{ + return (int64_t)(d + 0.5); +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/src/timer.c ---------------------------------------------------------------------- diff --git a/net/lora/node/src/timer.c b/net/lora/node/src/timer.c new file mode 100644 index 0000000..d445b01 --- /dev/null +++ b/net/lora/node/src/timer.c @@ -0,0 +1,15 @@ +#include "os/os.h" +#include "node/timer.h" +#include "node/utilities.h" + +uint32_t +TimerGetElapsedTime(uint32_t savedTime) +{ + return savedTime - os_cputime_get32(); +} + +uint32_t +TimerGetFutureTime(uint32_t eventInFuture) +{ + return os_cputime_get32() + eventInFuture; +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9986f68c/net/lora/node/syscfg.yml ---------------------------------------------------------------------- diff --git a/net/lora/node/syscfg.yml b/net/lora/node/syscfg.yml new file mode 100644 index 0000000..43fd05b --- /dev/null +++ b/net/lora/node/syscfg.yml @@ -0,0 +1,39 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + LORA_NODE: + description: > + Used by package management system to include lora/node hardware + drivers. + value: 1 + + LORA_NODE_FREQ_BAND: + description: > + Which frequency band to use. Valid values are: + o 433 + o 470 + o 780 + o 868 + o 915 + value: 868 + + LORA_NODE_CLI: + description: "Include shell commands for LoRa operations" + value: 0
