From ba7c9c017aea090c292992cd4a1e9e959bdc0d9b Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Mon, 7 Nov 2022 17:05:12 -0400 Subject: [PATCH 01/11] moved in MIC files handling AES-128, AES128-CMAC, and MIC generation & verification --- model/lorawan-mic-trailer.cc | 648 +++++++++++++++++++++++++++++++++++ model/lorawan-mic-trailer.h | 61 ++++ 2 files changed, 709 insertions(+) create mode 100644 model/lorawan-mic-trailer.cc create mode 100644 model/lorawan-mic-trailer.h diff --git a/model/lorawan-mic-trailer.cc b/model/lorawan-mic-trailer.cc new file mode 100644 index 0000000000..cf97b5a519 --- /dev/null +++ b/model/lorawan-mic-trailer.cc @@ -0,0 +1,648 @@ +#include "lorawan-mic-trailer.h" +#include "ns3/log.h" + +namespace ns3{ +namespace lorawan{ + +NS_LOG_COMPONENT_DEFINE ("LorawanMICTrailer"); + +LorawanMICTrailer::LorawanMICTrailer () +{ +} + +LorawanMICTrailer::~LorawanMICTrailer () +{ +} + +TypeId +LorawanMICTrailer::GetTypeId (void) +{ + static TypeId tid = TypeId ("LorawanMICTrailer") + .SetParent () + .AddConstructor () + ; + + return tid; +} + +TypeId +LorawanMICTrailer::GetInstanceTypeId (void) +{ + return GetTypeId (); +} + +uint32_t +LorawanMICTrailer::GetSerializedSize (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + + return 4; +} + +void +LorawanMICTrailer::Serialize (Buffer::Iterator start) const +{ + NS_LOG_FUNCTION_NOARGS (); + + start.WriteU32 (m_mic); + + return; +} + +uint32_t +LorawanMICTrailer::Deserialize (Buffer::Iterator end) +{ + uint32_t trailer_data; + + NS_LOG_FUNCTION_NOARGS (); + + /* move iterator to start of trailer before reading */ + end.Prev(this->GetSerializedSize ()); + + trailer_data = end.ReadU32 (); + + m_mic = trailer_data; + + return this->GetSerializedSize (); +} + +void +LorawanMICTrailer::Print (std::ostream &os) const +{ + NS_LOG_FUNCTION_NOARGS (); + + os << "MIC=" << m_mic << std::endl; + + return; +} + +void +LorawanMICTrailer::SetMIC (uint32_t newMIC) +{ + NS_LOG_FUNCTION_NOARGS (); + + m_mic = newMIC; + + return; +} + +uint32_t +LorawanMICTrailer::GetMIC (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + return m_mic; +} + +void +LorawanMICTrailer::leftshift_1bit (uint8_t in[16], uint8_t out[16]) +{ + int i; + uint8_t overflow; /* from byte to the right */ + + for (i = 15, overflow = 0;i >= 0;i--) + { + out[i] = in[i] << 1; + out[i] |= overflow; + overflow = (in[i] & 0x80)?1:0; + } + + return; +} + +void +LorawanMICTrailer::xor_128 (uint8_t in1[16], uint8_t in2[16], uint8_t out[16]) +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + out[i] = in1[i] ^ in2[i]; + } + + return; +} + +void +LorawanMICTrailer::aes128_cmac_generate_subkeys (uint8_t K[16], uint8_t K1[16], uint8_t K2[16]) +{ + uint8_t tmp[16]; + uint8_t L[16]; + uint8_t Rb[16]; + unsigned int i; + + for (i = 0;i < 16;i++) + { + tmp[i] = 0; + Rb[i] = 0; + } + + Rb[15] = 0x87; + + aes128 (K, tmp, L); + + if ((L[0] & 0x80) == 0) /* MSB of L */ + { + leftshift_1bit (L, K1); + } + else + { + leftshift_1bit (L, tmp); + xor_128 (tmp, Rb, K1); + } + + if ((K1[0] & 0x80) == 0) + { + leftshift_1bit (K1, K2); + } + else + { + leftshift_1bit(K1, tmp); + xor_128 (tmp, Rb, K2); + } + + return; +} + +void +LorawanMICTrailer::padding_128 (uint8_t *in, uint8_t out[16], unsigned int length) +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + if (i < length) + { + out[i] = in[i]; + } + else if (i == length) + { + /* first byte to pad */ + out[i] = 0x80; + } + else + { + out[i] = 0x00; + } + } + + return; +} + +void +LorawanMICTrailer::aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]) +{ + const uint8_t Nr = 10; /* number of rounds 10 for 128bit key */ + const uint8_t Nb = 4; + uint8_t state[4][4]; + uint8_t w[44][4]; + unsigned int i, j; + + /* taken from NIST publication for AES: https://www.nist.gov/publications/advanced-encryption-standard-aes*/ + const uint8_t sbox[16][16] = { + {0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76}, + {0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0}, + {0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15}, + {0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75}, + {0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84}, + {0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf}, + {0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8}, + {0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2}, + {0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73}, + {0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb}, + {0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79}, + {0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08}, + {0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a}, + {0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e}, + {0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf}, + {0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16} + }; + + /* move input into state matrix */ + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + state[j][i] = M[(4 * i) + j]; + } + } + + /* cipher algorithm */ + aes128_addroundkeys(state, w, 0); + + for (i = 1;i < Nr;i++) + { + aes128_subbytes(state, sbox); + aes128_shiftrows(state); + aes128_mixcolumns(state); + aes128_addroundkeys(state, w, i); + } + + aes128_subbytes(state, sbox); + aes128_shiftrows(state); + aes128_addroundkeys(state, w, Nr); + + /* move state matrix to output */ + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + O[(4 * i) + j] = state[j][i]; + } + } + + return; +} + +void +LorawanMICTrailer::aes128_subbytes (uint8_t state[4][4], const uint8_t sbox[16][16]) +{ + unsigned int i, j, row, col; + + + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + col = state[i][j] & 0x0f; /* lower 4 bits */ + row = state[i][j] >> 4; /* upper 4 bits */ + + /* update state val */ + state[i][j] = sbox[row][col]; + } + } + + return; +} + +void +LorawanMICTrailer::aes128_shiftrows (uint8_t state[4][4]) +{ + unsigned int i; + uint8_t temp; + + /* first row doesn't shift */ + + /* second row: shift bytes left once*/ + temp = state[1][0]; + + for (i = 0;i < 3;i++) + { + state[1][i] = state[1][i + 1]; + } + + state[1][3] = temp; + + /* third row: shift bytes left twice -> swap bytes two spaces apart */ + + for (i = 0;i < 2;i++) + { + temp = state[2][i]; + state[2][i] = state[2][i + 2]; + state[2][i + 2] = temp; + } + + /* fourth row: shift bytes left thrice -> shift left once */ + temp = state[3][3]; + + for (i = 3;i > 0;i--) + { + state[3][i] = state[3][i - 1]; + } + + state[3][0] = temp; + + return; +} + +void +LorawanMICTrailer::aes128_mixcolumns (uint8_t state[4][4]) +{ + unsigned int i, j; + uint8_t temp[4]; + + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + temp[j] = gfmul (state[j][i], 0x02) ^ gfmul (state[(j + 1) % 4][i], 0x03) ^ state[(j + 2) % 4][i] ^ state[(j + 3) % 4][i]; + } + + /* update col */ + for (j = 0;j < 4;j++) + { + state[j][i] = temp[j]; + } + } + + return; +} + +uint8_t +LorawanMICTrailer::gfmul (uint8_t x, uint8_t y) +{ + uint16_t mulres, x16; + unsigned int i; + + /* cycle through bits and xor */ + for (i = 0, mulres = 0, x16 = x;i < 8;i++) + { + if (y & 0x01) /* check rightmost bit */ + { + mulres ^= (x16 << i); + } + + y >>= 1; + } + + /* modulo result with x^8 + x^4 + x^3 + x + 1 */ + for (i = 0;i < 8;i++) + { + if (mulres & (0x8000 >> i)) + { + mulres ^= (((mulres & (0x8000 >> i)) >> 8) * 0x001b); + } + } + + return (uint8_t)(mulres & 0x00ff); /* return rightmost byte */ +} + +void +LorawanMICTrailer::aes128_keyexpansion (uint8_t K[16], uint8_t w[44][4], const uint8_t sbox[16][16]) +{ + unsigned int i, j; + uint8_t temp[4]; + + const uint8_t rcon[11][4] = { + {0x8d, 0x00, 0x00, 0x00}, + {0x01, 0x00, 0x00, 0x00}, + {0x02, 0x00, 0x00, 0x00}, + {0x04, 0x00, 0x00, 0x00}, + {0x08, 0x00, 0x00, 0x00}, + {0x10, 0x00, 0x00, 0x00}, + {0x20, 0x00, 0x00, 0x00}, + {0x40, 0x00, 0x00, 0x00}, + {0x80, 0x00, 0x00, 0x00}, + {0x1b, 0x00, 0x00, 0x00}, + {0x36, 0x00, 0x00, 0x00} + }; + + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + w[i][j] = K[(i * 4) + j]; + } + } + + for (i = 4;i < 44;i++) + { + for (j = 0;j < 4;j++) + { + temp[j] = w[i - 1][j]; + } + + if (i % 4 == 0) + { + subword (rotword (temp)); + + for (j = 0;j < 4;j++) + { + temp[j] ^= rcon[i / 4][j]; + } + } + /* condition in original algorithm for Nk > 6 not included as Nk = 4 for aes128 */ + + for (j = 0;j < 4;j++) + { + w[i][j] = w[i - 4][j] ^ temp[j]; + } + } + + return; +} + +void +LorawanMICTrailer::aes128_addroundkeys (uint8_t state[4][4], uint8_t w[44][4], unsigned int round) +{ + unsigned int i, j; + + for (i = 0;i < 4;i++) + { + for (j = 0;j < 4;j++) + { + state[j][i] ^= w[(4 * round) + i][j]; + } + } + + return; +} + +void +LorawanMICTrailer::rotword (uint8_t word[4]) +{ + uint8_t temp; + unsigned int i; + + /* shift bytes left once */ + temp = word[0]; + + for (i = 0;i < 3;i++) + { + word[i] = word[i + 1]; + } + + word[3] = temp; + + return; +} + +void +LorawanMICTrailer::subword (uint8_t word[4], const uint8_t sbox[16][16]) +{ + uint8_t row, col, i; + + for (i = 0;i < 4;i++) + { + col = word[i] & 0x0f; + row = word[i] >> 4; + + word[i] = sbox[row][col]; + } + + return; +} + +uint32_t +LorawanMICTrailer::aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t len, uint8_t *Bx_msg) +{ + uint8_t Mlast[16], padded[16], X[16], Y[16]; + uint8_t K1[16], K2[16]; + unsigned int i, n; + bool flag; + uint32_t mic; + + aes128_cmac_generate_subkeys (xNwkSIntKey, K1, K2); + + n = (len + 15) / 16; + + if (n == 0) + { + n = 1; + flag = false; + } + else if (len % 16 == 0) + { + flag = true; + } + else + { + flag = false; + } + + /* handle last block */ + if (flag == true) + { + xor_128 (&(Bx_msg[16 * (n - 1)]), K1, Mlast); + } + else + { + padding_128 (&(Bx_msg[16 * (n - 1)]), padded, len % 16); + xor_128 (padded, K2, Mlast); + } + + for (i = 0;i < 16;i++) + { + X[i] = 0; + } + + for (i = 0;i < (n - 1);i++) + { + xor_128 (X, &(Bx_msg[16 * i]), Y); + aes128 (xNwkSIntKey, Y, X); + } + + xor_128 (X, Mlast, Y); + aes128 (xNwkSIntKey, Y, X); + + /* mic is first 4 octets of entire code */ + + for (i = 0, mic = 0;i < 4;i++) + { + mic |= X[i]; + mic <<= 8; + } + + return mic; +} + +uint32_t +LorawanMICTrailer::CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]) +{ + uint8_t B0_msg[msgLen + 16]; + uint32_t mic; + unsigned int j; + + /* concatenate Bx and msg */ + + for (j = 0;j < 16;j++) + { + B0_msg[j] = B0[j]; + } + + for (j = 0;j < msgLen;j++) + { + B0_msg[j + 16] = msg[j]; + } + + mic = aes128_cmac_4(xNwkSIntKey, msgLen + 16, B0_msg); + + return mic; +} + +uint32_t +LorawanMICTrailer::CalcMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]) +{ + uint32_t mic_f, mic_s, mic; + + mic_f = CalcMIC (msgLen, msg, B0, FNwkSIntKey); + mic_s = CalcMIC (msgLen, msg, B1, SNwkSIntKey); + + mic = 0; + mic |= (mic_s & 0xffff0000); /* first two bytes of each */ + mic |= ((mic_f & 0xffff0000) >> 16); + + return mic; +} + +void +LorawanMICTrailer::GenerateB0DL (uint8_t B0[16], uint16_t ConfFCnt, uint32_t DevAddr, uint32_t xFCntDwn, uint8_t msgLen) +{ + B0[0] = 0x49; + B0[1] = (uint8_t)(ConfFCnt >> 8); + B0[2] = (uint8_t)(ConfFCnt & 0x00ff); + B0[3] = 0x00; + B0[4] = 0x00; + B0[5] = 0x01; + B0[6] = (uint8_t)(DevAddr >> 24); + B0[7] = (uint8_t)((DevAddr & 0x00ff0000) >> 16); + B0[8] = (uint8_t)((DevAddr & 0x0000ff00) >> 8); + B0[9] = (uint8_t)(DevAddr & 0x000000ff); + B0[10] = (uint8_t)(xFCntDwn >> 24); + B0[11] = (uint8_t)((xFCntDwn & 0x00ff0000) >> 16); + B0[12] = (uint8_t)((xFCntDwn & 0x0000ff00) >> 8); + B0[13] = (uint8_t)(xFCntDwn & 0x000000ff); + B0[14] = 0x00; + B0[15] = msgLen; + + return; +} + +void +LorawanMICTrailer::GenerateB0UL (uint8_t B0[16], uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen) +{ + B0[0] = 0x49; + B0[1] = 0x00; + B0[2] = 0x00; + B0[3] = 0x00; + B0[4] = 0x00; + B0[5] = 0x00; + B0[6] = (uint8_t)(DevAddr >> 24); + B0[7] = (uint8_t)((DevAddr & 0x00ff0000) >> 16); + B0[8] = (uint8_t)((DevAddr & 0x0000ff00) >> 8); + B0[9] = (uint8_t)(DevAddr & 0x000000ff); + B0[10] = (uint8_t)(FCntUp >> 24); + B0[11] = (uint8_t)((FCntUp & 0x00ff0000) >> 16); + B0[12] = (uint8_t)((FCntUp & 0x0000ff00) >> 8); + B0[13] = (uint8_t)(FCntUp & 0x000000ff); + B0[14] = 0x00; + B0[15] = msgLen; + + return; +} + +void +LorawanMICTrailer::GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen) +{ + B0[0] = 0x49; + B0[1] = (uint8_t)(ConfFCnt >> 8); + B0[2] = (uint8_t)(ConfFCnt & 0x00ff); + B0[3] = TxDr; + B0[4] = TxCh; + B0[5] = 0x00; + B0[6] = (uint8_t)(DevAddr >> 24); + B0[7] = (uint8_t)((DevAddr & 0x00ff0000) >> 16); + B0[8] = (uint8_t)((DevAddr & 0x0000ff00) >> 8); + B0[9] = (uint8_t)(DevAddr & 0x000000ff); + B0[10] = (uint8_t)(FCntUp >> 24); + B0[11] = (uint8_t)((FCntUp & 0x00ff0000) >> 16); + B0[12] = (uint8_t)((FCntUp & 0x0000ff00) >> 8); + B0[13] = (uint8_t)(FCntUp & 0x000000ff); + B0[14] = 0x00; + B0[15] = msgLen; + + return; +} + +} +} diff --git a/model/lorawan-mic-trailer.h b/model/lorawan-mic-trailer.h new file mode 100644 index 0000000000..56533d5886 --- /dev/null +++ b/model/lorawan-mic-trailer.h @@ -0,0 +1,61 @@ +#ifndef __LORAWAN_MIC_TRAILER__ +#define __LORAWAN_MIC_TRAILER__ + +#include "ns3/trailer.h" + +namespace ns3 { +namespace lorawan { + +class LorawanMICTrailer : public Trailer +{ +private: + uint32_t m_mic; /* the 4 byte mic */ + + /* AES-CMAC funcs (taken from RFC4493) */ + uint32_t aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t *Bx_msg, uint8_t msgLen); /* returns first 4 byte of cmac AKA the MIC */ + void aes128_cmac_generate_subkeys (uint8_t K[16], uint8_t K0[16], uint8_t K1[16]); + void leftshift_1bit (uint8_t in[16], uint8_t out[16]); + void xor_128 (uint8_t in1[16], uint8_t in2[16], uint8_t out[16]); + void padding_128 (uint8_t *in, uint8_t out[16], unsigned int length); + + /* AES-128 funcs taken from NIST publication */ + void aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]); + void aes128_subbytes (uint8_t state[4][4], const uint8_t sbox[16][16]); + void aes128_shiftrows (uint8_t state[4][4]); + void aes128_mixcolumns (uint8_t state[4][4]); + void aes128_addroundkeys (uint8_t state[4][4], uint8_t w[44][4], unsigned int round); + void aes128_keyexpansion(uint8_t K[16], uint8_t w[44][4], const uint8_t sbox[16][16]); + uint8_t gfmul (uint8_t x, uint8_t y); /* GF(2^8) multiplication */ + void rotword (uint8_t word[4]); + void subword (uint8_t word[4], const uint8_t sbox[16][16]); + +public: + + LorawanMICTrailer (); + ~LorawanMICTrailer (); + + /* required funcs for trailer*/ + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual uint32_t GetSerializedSize (void) const ; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator end); + virtual void Print (std::ostream &os) const; + + uint32_t GetMIC (void) const; + void SetMIC (uint32_t newMIC); + uint32_t CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); /* Bx and xNwkSIntKey need to be 16 bytes (128 bits) each, uint128_t is not guranteed to be supported */ + uint32_t CalcMIC_1_1_UL(uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); /* special case for UL for 1.1 LoRaWAN network servers */ + bool VerifyMIC (uint8_t msgLen, uint8_t *msg,uint8_t B0[16], uint8_t xNwkSIntKey[16]); + bool VerifyMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); + + /* for making B0 and B1 */ + void GenerateB0DL (uint8_t B0[16], uint16_t ConfFCnt, uint32_t DevAddr, uint32_t xFCntDwn, uint8_t msgLen); + void GenerateB0UL (uint8_t B0[16], uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); + void GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); /* LoRaWAN 1.1 Network servers use B1 and B0 */ +} + +} +} + +#endif /* __LORAWAN_MIC_TRAILER__ */ From 69346db75ca388b738fc69235382672f4b4d7287 Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Tue, 8 Nov 2022 18:57:42 -0400 Subject: [PATCH 02/11] Added in new files to makelists and wscript, added in placeholder MIC(0x00000000) for testing, and fixed de/serialization misalignments for MIC --- CMakeLists.txt | 2 ++ model/end-device-lorawan-mac.cc | 29 ++++++++++++++++-- model/end-device-lorawan-mac.h | 8 +++++ model/lorawan-mic-trailer.cc | 53 ++++++++++++++++++--------------- model/lorawan-mic-trailer.h | 2 +- wscript | 2 ++ 6 files changed, 68 insertions(+), 28 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 767d9dd5c0..fdaf65dcfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ set(source_files model/forwarder.cc model/lorawan-mac-header.cc model/lora-frame-header.cc + model/lorawan-mic-trailer.cc model/mac-command.cc model/lora-device-address.cc model/lora-device-address-generator.cc @@ -71,6 +72,7 @@ set(header_files model/forwarder.h model/lorawan-mac-header.h model/lora-frame-header.h + model/lorawan-mic-trailer.h model/mac-command.h model/lora-device-address.h model/lora-device-address-generator.h diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index aa06d0f9d6..93fb3231e5 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -236,10 +236,15 @@ EndDeviceLorawanMac::DoSend (Ptr packet) LorawanMacHeader macHdr; ApplyNecessaryOptions (macHdr); packet->AddHeader (macHdr); - + + //Add MIC trailer + LorawanMICTrailer micTrlr; + ApplyNecessaryOptions (micTrlr); + packet->AddTrailer (micTrlr); + // Reset MAC command list m_macCommandList.clear (); - + if (m_retxParams.waitingAck) { // Call the callback to notify about the failure @@ -249,6 +254,8 @@ EndDeviceLorawanMac::DoSend (Ptr packet) unsigned(txs) << " transmissions out of a maximum of " << unsigned(m_maxNumbTx) << "."); } + + // Reset retransmission parameters resetRetransmissionParameters (); @@ -291,9 +298,12 @@ EndDeviceLorawanMac::DoSend (Ptr packet) // Remove the headers LorawanMacHeader macHdr; LoraFrameHeader frameHdr; + LorawanMICTrailer micTrlr; + packet->RemoveTrailer (micTrlr); packet->RemoveHeader(macHdr); packet->RemoveHeader(frameHdr); - + + // Add the Lora Frame Header to the packet frameHdr = LoraFrameHeader (); ApplyNecessaryOptions (frameHdr); @@ -306,6 +316,11 @@ EndDeviceLorawanMac::DoSend (Ptr packet) macHdr = LorawanMacHeader (); ApplyNecessaryOptions (macHdr); packet->AddHeader (macHdr); + + micTrlr = LorawanMICTrailer (); + ApplyNecessaryOptions (micTrlr); + packet->AddTrailer (micTrlr); + m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions NS_LOG_DEBUG ("Retransmitting an old packet."); @@ -498,6 +513,14 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) macHeader.SetMajor (1); } +void +EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) +{ + NS_LOG_FUNCTION_NOARGS (); + + micTrlr.SetMIC(0x00000000); /* placeholder */ +} + void EndDeviceLorawanMac::SetMType (LorawanMacHeader::MType mType) { diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index a013a6a1a4..4a714d654f 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -27,6 +27,7 @@ #include "ns3/lorawan-mac.h" #include "ns3/lorawan-mac-header.h" #include "ns3/lora-frame-header.h" +#include "ns3/lorawan-mic-trailer.h" #include "ns3/random-variable-stream.h" #include "ns3/lora-device-address.h" #include "ns3/traced-value.h" @@ -217,6 +218,13 @@ class EndDeviceLorawanMac : public LorawanMac */ void ApplyNecessaryOptions (LorawanMacHeader &macHeader); + /** + * Add the necessary options and to the LorawanMICTrailer. + * + * \param micTrlr The MIC trailer to which to apply the options + */ + void ApplyNecessaryOptions (LorawanMICTrailer &micTrlr); + /** * Set the message type to send when the Send method is called. */ diff --git a/model/lorawan-mic-trailer.cc b/model/lorawan-mic-trailer.cc index cf97b5a519..d5886f6a7d 100644 --- a/model/lorawan-mic-trailer.cc +++ b/model/lorawan-mic-trailer.cc @@ -26,7 +26,7 @@ LorawanMICTrailer::GetTypeId (void) } TypeId -LorawanMICTrailer::GetInstanceTypeId (void) +LorawanMICTrailer::GetInstanceTypeId (void) const { return GetTypeId (); } @@ -44,6 +44,9 @@ LorawanMICTrailer::Serialize (Buffer::Iterator start) const { NS_LOG_FUNCTION_NOARGS (); + /* move iterator to start of trailer before writing */ + start.Prev(GetSerializedSize ()); + start.WriteU32 (m_mic); return; @@ -57,13 +60,13 @@ LorawanMICTrailer::Deserialize (Buffer::Iterator end) NS_LOG_FUNCTION_NOARGS (); /* move iterator to start of trailer before reading */ - end.Prev(this->GetSerializedSize ()); + end.Prev(GetSerializedSize ()); trailer_data = end.ReadU32 (); m_mic = trailer_data; - return this->GetSerializedSize (); + return GetSerializedSize (); } void @@ -87,7 +90,7 @@ LorawanMICTrailer::SetMIC (uint32_t newMIC) } uint32_t -LorawanMICTrailer::GetMIC (void) +LorawanMICTrailer::GetMIC (void) const { NS_LOG_FUNCTION_NOARGS (); @@ -193,7 +196,7 @@ void LorawanMICTrailer::aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]) { const uint8_t Nr = 10; /* number of rounds 10 for 128bit key */ - const uint8_t Nb = 4; + //const uint8_t Nb = 4; uint8_t state[4][4]; uint8_t w[44][4]; unsigned int i, j; @@ -404,7 +407,8 @@ LorawanMICTrailer::aes128_keyexpansion (uint8_t K[16], uint8_t w[44][4], const u if (i % 4 == 0) { - subword (rotword (temp)); + rotword (temp); + subword (temp, sbox); for (j = 0;j < 4;j++) { @@ -474,7 +478,7 @@ LorawanMICTrailer::subword (uint8_t word[4], const uint8_t sbox[16][16]) } uint32_t -LorawanMICTrailer::aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t len, uint8_t *Bx_msg) +LorawanMICTrailer::aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t *Bx_msg, uint8_t len) { uint8_t Mlast[16], padded[16], X[16], Y[16]; uint8_t K1[16], K2[16]; @@ -555,11 +559,12 @@ LorawanMICTrailer::CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_ B0_msg[j + 16] = msg[j]; } - mic = aes128_cmac_4(xNwkSIntKey, msgLen + 16, B0_msg); + mic = aes128_cmac_4(xNwkSIntKey, B0_msg, msgLen + (uint8_t)16); return mic; } +/* for LoRaWAN 1.1 Network Servers UL MIC */ uint32_t LorawanMICTrailer::CalcMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]) { @@ -624,22 +629,22 @@ LorawanMICTrailer::GenerateB0UL (uint8_t B0[16], uint32_t DevAddr, uint32_t FCnt void LorawanMICTrailer::GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen) { - B0[0] = 0x49; - B0[1] = (uint8_t)(ConfFCnt >> 8); - B0[2] = (uint8_t)(ConfFCnt & 0x00ff); - B0[3] = TxDr; - B0[4] = TxCh; - B0[5] = 0x00; - B0[6] = (uint8_t)(DevAddr >> 24); - B0[7] = (uint8_t)((DevAddr & 0x00ff0000) >> 16); - B0[8] = (uint8_t)((DevAddr & 0x0000ff00) >> 8); - B0[9] = (uint8_t)(DevAddr & 0x000000ff); - B0[10] = (uint8_t)(FCntUp >> 24); - B0[11] = (uint8_t)((FCntUp & 0x00ff0000) >> 16); - B0[12] = (uint8_t)((FCntUp & 0x0000ff00) >> 8); - B0[13] = (uint8_t)(FCntUp & 0x000000ff); - B0[14] = 0x00; - B0[15] = msgLen; + B1[0] = 0x49; + B1[1] = (uint8_t)(ConfFCnt >> 8); + B1[2] = (uint8_t)(ConfFCnt & 0x00ff); + B1[3] = TxDr; + B1[4] = TxCh; + B1[5] = 0x00; + B1[6] = (uint8_t)(DevAddr >> 24); + B1[7] = (uint8_t)((DevAddr & 0x00ff0000) >> 16); + B1[8] = (uint8_t)((DevAddr & 0x0000ff00) >> 8); + B1[9] = (uint8_t)(DevAddr & 0x000000ff); + B1[10] = (uint8_t)(FCntUp >> 24); + B1[11] = (uint8_t)((FCntUp & 0x00ff0000) >> 16); + B1[12] = (uint8_t)((FCntUp & 0x0000ff00) >> 8); + B1[13] = (uint8_t)(FCntUp & 0x000000ff); + B1[14] = 0x00; + B1[15] = msgLen; return; } diff --git a/model/lorawan-mic-trailer.h b/model/lorawan-mic-trailer.h index 56533d5886..5337faa148 100644 --- a/model/lorawan-mic-trailer.h +++ b/model/lorawan-mic-trailer.h @@ -53,7 +53,7 @@ class LorawanMICTrailer : public Trailer void GenerateB0DL (uint8_t B0[16], uint16_t ConfFCnt, uint32_t DevAddr, uint32_t xFCntDwn, uint8_t msgLen); void GenerateB0UL (uint8_t B0[16], uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); void GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); /* LoRaWAN 1.1 Network servers use B1 and B0 */ -} +}; } } diff --git a/wscript b/wscript index e1c1e78ff7..6b16e7b090 100644 --- a/wscript +++ b/wscript @@ -34,6 +34,7 @@ def build(bld): 'model/forwarder.cc', 'model/lorawan-mac-header.cc', 'model/lora-frame-header.cc', + 'model/lorawan-mic-trailer.cc', 'model/mac-command.cc', 'model/lora-device-address.cc', 'model/lora-device-address-generator.cc', @@ -95,6 +96,7 @@ def build(bld): 'model/forwarder.h', 'model/lorawan-mac-header.h', 'model/lora-frame-header.h', + 'model/lorawan-mic-trailer.h', 'model/mac-command.h', 'model/lora-device-address.h', 'model/lora-device-address-generator.h', From 602baa1570f3608a0ee2c5ab9efaa4fc8faaceca Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Tue, 8 Nov 2022 20:25:18 -0400 Subject: [PATCH 03/11] Added in function for parsing arguments for MIC calculations based on UL/DL and LoRaWAN version --- model/end-device-lorawan-mac.cc | 52 +++++++++++++++++++++++++++++++-- model/end-device-lorawan-mac.h | 8 +++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 93fb3231e5..d867e3fe0e 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -513,12 +513,60 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) macHeader.SetMajor (1); } +/* For usage only put values in for the parameters which you need for the tranmission type, send zero placeholders for unnecessary ones */ void -EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) +EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, bool isuplink, bool isLorawan_1_1, bool isAck, uint16_t fcnt, + uint32_t devaddr, uint32_t xFCntDwn, uint32_t FCntUp, uint8_t msgLen, uint8_t *msg, uint8_t SNwkSIntKey[16], + uint8_t FNwkSIntKey[16], uint8_t txch) +{ + uint8_t B0[16]; + uint8_t B1[16]; + uint16_t ConfFCnt; + uint32_t mic_temp; + + NS_LOG_FUNCTION_NOARGS (); + + if (isLorawan_1_1 && isAck) + { + ConfFCnt = fcnt; /* only value is of uint16_t so modding by 2^16 does nothing? maybe misunderstanding smth */ + } + else + { + ConfFCnt = 0x0000; + } + + if (!isuplink) + { + /* downlink only needs B0 */ + + micTrlr.GenerateB0DL (B0, ConfFCnt, devaddr, xFCntDwn, msgLen); + mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, SNwkSIntKey); + micTrlr.SetMIC (mic_temp); + } + else + { + micTrlr.GenerateB0UL (B0, devaddr, FCntUp, msgLen); + + if (isLorawan_1_1) + { + micTrlr.GenerateB1UL (B1, ConfFCnt, m_dataRate, txch, devaddr, FCntUp, msgLen); + mic_temp = micTrlr.CalcMIC_1_1_UL (msgLen, msg, B0 ,B1, SNwkSIntKey, FNwkSIntKey); + micTrlr.SetMIC (mic_temp); + } + else + { + mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, FNwkSIntKey); + micTrlr.SetMIC (mic_temp); + } + } +} + +/* placeholder func until all parameters are better organized for MIC calc */ +void EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) { NS_LOG_FUNCTION_NOARGS (); - micTrlr.SetMIC(0x00000000); /* placeholder */ + micTrlr.SetMIC (0x00000000); } void diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 4a714d654f..fcba9692e2 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -220,10 +220,12 @@ class EndDeviceLorawanMac : public LorawanMac /** * Add the necessary options and to the LorawanMICTrailer. - * - * \param micTrlr The MIC trailer to which to apply the options */ - void ApplyNecessaryOptions (LorawanMICTrailer &micTrlr); + void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr); + + void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, bool isuplink, bool isLorawan_1_1, bool isAck, uint16_t fcnt, + uint32_t devaddr, uint32_t xFCntDwn, uint32_t FCntUp, uint8_t msgLen, uint8_t *msg, uint8_t SNwkSIntKey[16], + uint8_t FNwkSIntKey[16], uint8_t txch); /** * Set the message type to send when the Send method is called. From cee86120c72ebee3636788569354e4b4ad98faae Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Tue, 16 May 2023 19:40:05 -0400 Subject: [PATCH 04/11] Organised the network server version and JoinNonce parameters for MIC calculation --- model/class-a-end-device-lorawan-mac.cc | 23 +++++- model/end-device-lorawan-mac.cc | 103 ++++++++++++------------ model/end-device-lorawan-mac.h | 11 ++- model/network-server.cc | 15 ++++ model/network-server.h | 5 ++ 5 files changed, 101 insertions(+), 56 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 7b958375fe..7ffbe170e6 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -150,7 +150,7 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) // Remove the Mac Header to get some information LorawanMacHeader mHdr; packetCopy->RemoveHeader (mHdr); - + NS_LOG_DEBUG ("Mac Header: " << mHdr); // Only keep analyzing the packet if it's downlink @@ -176,7 +176,26 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) // THIS WILL BE GetReceiveWindow() Simulator::Cancel (m_secondReceiveWindow); - + if (mHdr.GetMType() == JOIN_ACCEPT) + { + uint8_t temp[3]; + uint32_t newJoinNonce = 0; + packetCopy->CopyData(temp, 3); /* get the new joinNonce value */ + + for (i = 0;i < 3;i++) + { + newJoinNonce <<= 8; + newJoinNonce |= temp[i]; + } + + if (newJoinNonce > m_joinNonce) + { + /* update is value is greater */ + m_joinNonce = newJoinNonce; + } + + } + // Parse the MAC commands ParseCommands (fHdr); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index d867e3fe0e..4e05e2ae18 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -126,7 +126,8 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () m_lastKnownGatewayCount (0), m_aggregatedDutyCycle (1), m_mType (LorawanMacHeader::CONFIRMED_DATA_UP), - m_currentFCnt (0) + m_currentFCnt (0), + m_joinNonce (0) { NS_LOG_FUNCTION (this); @@ -239,7 +240,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) //Add MIC trailer LorawanMICTrailer micTrlr; - ApplyNecessaryOptions (micTrlr); + //ApplyNecessaryOptions (micTrlr); packet->AddTrailer (micTrlr); // Reset MAC command list @@ -318,7 +319,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) packet->AddHeader (macHdr); micTrlr = LorawanMICTrailer (); - ApplyNecessaryOptions (micTrlr); + //ApplyNecessaryOptions (micTrlr); packet->AddTrailer (micTrlr); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -513,53 +514,47 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) macHeader.SetMajor (1); } -/* For usage only put values in for the parameters which you need for the tranmission type, send zero placeholders for unnecessary ones */ -void -EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, bool isuplink, bool isLorawan_1_1, bool isAck, uint16_t fcnt, - uint32_t devaddr, uint32_t xFCntDwn, uint32_t FCntUp, uint8_t msgLen, uint8_t *msg, uint8_t SNwkSIntKey[16], - uint8_t FNwkSIntKey[16], uint8_t txch) -{ - uint8_t B0[16]; - uint8_t B1[16]; - uint16_t ConfFCnt; - uint32_t mic_temp; - - NS_LOG_FUNCTION_NOARGS (); - - if (isLorawan_1_1 && isAck) - { - ConfFCnt = fcnt; /* only value is of uint16_t so modding by 2^16 does nothing? maybe misunderstanding smth */ - } - else - { - ConfFCnt = 0x0000; - } - - if (!isuplink) - { - /* downlink only needs B0 */ - - micTrlr.GenerateB0DL (B0, ConfFCnt, devaddr, xFCntDwn, msgLen); - mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, SNwkSIntKey); - micTrlr.SetMIC (mic_temp); - } - else - { - micTrlr.GenerateB0UL (B0, devaddr, FCntUp, msgLen); - - if (isLorawan_1_1) - { - micTrlr.GenerateB1UL (B1, ConfFCnt, m_dataRate, txch, devaddr, FCntUp, msgLen); - mic_temp = micTrlr.CalcMIC_1_1_UL (msgLen, msg, B0 ,B1, SNwkSIntKey, FNwkSIntKey); - micTrlr.SetMIC (mic_temp); - } - else - { - mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, FNwkSIntKey); - micTrlr.SetMIC (mic_temp); - } - } -} +// void +// EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) +// { +// uint8_t B0[16]; +// uint8_t B1[16]; +// uint16_t ConfFCnt; +// uint32_t mic_temp; +// +// NS_LOG_FUNCTION_NOARGS (); +// +// if (isLorawan_1_1 && isAck) +// { +// ConfFCnt = fcnt; /* only value is of uint16_t so modding by 2^16 does nothing? maybe misunderstanding smth */ +// } +// else +// { +// ConfFCnt = 0x0000; +// } +// +// /* +// * Network ID => m_address.GetNwkID() +// * Network Addresss => m_address.GetNwkID() +// * Network Server Version => m_networkServer->IsVersion1() +// * JoinNonce => m_joinNonce +// */ +// +// micTrlr.GenerateB0UL (B0, m_address.GetNwkAddr(), FCntUp, msgLen); +// +// if (isLorawan_1_1) +// { +// micTrlr.GenerateB1UL (B1, ConfFCnt, m_dataRate, txch, m_address.GetNwkAddr(), FCntUp, msgLen); +// mic_temp = micTrlr.CalcMIC_1_1_UL (msgLen, msg, B0 ,B1, SNwkSIntKey, FNwkSIntKey); +// micTrlr.SetMIC (mic_temp); +// } +// else +// { +// mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, FNwkSIntKey); +// micTrlr.SetMIC (mic_temp); +// } +// +// } /* placeholder func until all parameters are better organized for MIC calc */ void EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) @@ -996,6 +991,14 @@ EndDeviceLorawanMac::AddMacCommand (Ptr macCommand) m_macCommandList.push_back (macCommand); } +void +EndDeviceLorawanMac::SetNwkServer(Ptr nwkServer); +{ + m_networkServer = nwkServer; + + return; +} + uint8_t EndDeviceLorawanMac::GetTransmissionPower (void) { diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index fcba9692e2..6b2dcecc76 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -31,6 +31,7 @@ #include "ns3/random-variable-stream.h" #include "ns3/lora-device-address.h" #include "ns3/traced-value.h" +#include "ns3/network-server.h" namespace ns3 { namespace lorawan { @@ -223,10 +224,6 @@ class EndDeviceLorawanMac : public LorawanMac */ void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr); - void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, bool isuplink, bool isLorawan_1_1, bool isAck, uint16_t fcnt, - uint32_t devaddr, uint32_t xFCntDwn, uint32_t FCntUp, uint8_t msgLen, uint8_t *msg, uint8_t SNwkSIntKey[16], - uint8_t FNwkSIntKey[16], uint8_t txch); - /** * Set the message type to send when the Send method is called. */ @@ -340,6 +337,8 @@ class EndDeviceLorawanMac : public LorawanMac * packet. */ void AddMacCommand (Ptr macCommand); + + void SetNwkServer(Ptr nwkServer); protected: /** @@ -429,6 +428,10 @@ class EndDeviceLorawanMac : public LorawanMac * the channel list. */ Ptr m_uniformRV; + + Ptr m_networkServer; + + uint32_t m_joinNonce; /* should be 3 bytes long */ ///////////////// // Callbacks // diff --git a/model/network-server.cc b/model/network-server.cc index c3150ff4f1..8954a3aa56 100644 --- a/model/network-server.cc +++ b/model/network-server.cc @@ -145,6 +145,8 @@ NetworkServer::AddNode (Ptr node) Ptr edLorawanMac = loraNetDevice->GetMac ()->GetObject (); + edLorawanMac->SetNwkServer(this); + // Update the NetworkStatus about the existence of this node m_status->AddNode (edLorawanMac); } @@ -187,5 +189,18 @@ NetworkServer::GetNetworkStatus (void) return m_status; } +bool +NetworkServer::IsVersion1(void) const +{ + return m_isVersion1; +} + +void +NetworkServer::SetIsVersion1(bool isVersion1) +{ + m_isVersion1 = isVersion1; + return; +} + } } diff --git a/model/network-server.h b/model/network-server.h index 3610d4a364..0e590f124e 100644 --- a/model/network-server.h +++ b/model/network-server.h @@ -98,11 +98,16 @@ class NetworkServer : public Application const Address &address); Ptr GetNetworkStatus (void); + + bool IsVersion1(void) const; + void SetIsVersion1(bool isVersion1); protected: Ptr m_status; Ptr m_controller; Ptr m_scheduler; + + bool m_isVersion1; /* whether or not the network server version is v1.0 or not */ TracedCallback> m_receivedPacket; }; From 80d3908d01eabd3401cd09c11cf9b7abd4067040 Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Wed, 17 May 2023 18:00:14 -0400 Subject: [PATCH 05/11] Moved declarations of RX1DROffset and RX2DataRate parameters for MIC from ClassAEndDeviceLorawanMac to EndDeviceLorawanMac, and added in DevNonce (join-accept counter) --- model/class-a-end-device-lorawan-mac.cc | 9 +++++++++ model/class-a-end-device-lorawan-mac.h | 9 --------- model/end-device-lorawan-mac.cc | 8 ++++++-- model/end-device-lorawan-mac.h | 16 ++++++++++++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 7ffbe170e6..169a866c51 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -90,6 +90,15 @@ ClassAEndDeviceLorawanMac::SendToPhy (Ptr packetToSend) m_dataRate = m_dataRate - 1; } + Ptr packetCopy = packetToSend->Copy(); + LorawanMacHeader mHdr; + packetCopy->RemoveHeader(mHdr); + + if (mHdr.GetMType() == JOIN_REQUEST) + { + m_devNonce++; + } + // Craft LoraTxParameters object LoraTxParameters params; params.sf = GetSfFromDataRate (m_dataRate); diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index 2facb632ae..4b3f31c95f 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -203,15 +203,6 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac */ double m_secondReceiveWindowFrequency; - /** - * The Data Rate to listen for during the second downlink transmission. - */ - uint8_t m_secondReceiveWindowDataRate; - - /** - * The RX1DROffset parameter value - */ - uint8_t m_rx1DrOffset; }; /* ClassAEndDeviceLorawanMac */ } /* namespace lorawan */ diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 4e05e2ae18..6e72657c9d 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -127,7 +127,8 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () m_aggregatedDutyCycle (1), m_mType (LorawanMacHeader::CONFIRMED_DATA_UP), m_currentFCnt (0), - m_joinNonce (0) + m_joinNonce (0), + m_devNonce (0) { NS_LOG_FUNCTION (this); @@ -537,7 +538,10 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) // * Network ID => m_address.GetNwkID() // * Network Addresss => m_address.GetNwkID() // * Network Server Version => m_networkServer->IsVersion1() -// * JoinNonce => m_joinNonce +// * JoinNonce => m_joinNonce +// * RX1DROffset => m_rx1DROffset +// * RX2DataRate => m_secondReceiveWindowDataRate +// * DevNonce => m_devNonce // */ // // micTrlr.GenerateB0UL (B0, m_address.GetNwkAddr(), FCntUp, msgLen); diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 6b2dcecc76..d0eecc5af7 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -431,8 +431,20 @@ class EndDeviceLorawanMac : public LorawanMac Ptr m_networkServer; - uint32_t m_joinNonce; /* should be 3 bytes long */ - + uint32_t m_joinNonce; /* join accept count - should be 3 bytes long */ + + uint16_t m_devNonce; /* join request count */ + + /** + * The RX1DROffset parameter value + */ + uint8_t m_rx1DrOffset; + + /** + * The Data Rate to listen for during the second downlink transmission. + */ + uint8_t m_secondReceiveWindowDataRate; + ///////////////// // Callbacks // ///////////////// From a77db8a2bbab9d340eb7b5dd29bb1b42175c1134 Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Sat, 20 May 2023 18:42:57 -0400 Subject: [PATCH 06/11] Added in remaining NwkKey and JoinEUI parameters for MIC calculation --- model/class-a-end-device-lorawan-mac.cc | 46 ++++++++--------- model/end-device-lorawan-mac.cc | 65 +++++++++++++++++++++++-- model/end-device-lorawan-mac.h | 9 ++++ 3 files changed, 94 insertions(+), 26 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 169a866c51..72da22bfd0 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -94,10 +94,10 @@ ClassAEndDeviceLorawanMac::SendToPhy (Ptr packetToSend) LorawanMacHeader mHdr; packetCopy->RemoveHeader(mHdr); - if (mHdr.GetMType() == JOIN_REQUEST) - { - m_devNonce++; - } +// if (mHdr.GetMType() == JOIN_REQUEST) +// { +// m_devNonce++; +// } // Craft LoraTxParameters object LoraTxParameters params; @@ -185,25 +185,25 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) // THIS WILL BE GetReceiveWindow() Simulator::Cancel (m_secondReceiveWindow); - if (mHdr.GetMType() == JOIN_ACCEPT) - { - uint8_t temp[3]; - uint32_t newJoinNonce = 0; - packetCopy->CopyData(temp, 3); /* get the new joinNonce value */ - - for (i = 0;i < 3;i++) - { - newJoinNonce <<= 8; - newJoinNonce |= temp[i]; - } - - if (newJoinNonce > m_joinNonce) - { - /* update is value is greater */ - m_joinNonce = newJoinNonce; - } - - } +// if (mHdr.GetMType() == JOIN_ACCEPT) +// { +// uint8_t temp[3]; +// uint32_t newJoinNonce = 0; +// packetCopy->CopyData(temp, 3); /* get the new joinNonce value */ +// +// for (i = 0;i < 3;i++) +// { +// newJoinNonce <<= 8; +// newJoinNonce |= temp[i]; +// } +// +// if (newJoinNonce > m_joinNonce) +// { +// /* update is value is greater */ +// m_joinNonce = newJoinNonce; +// } +// +// } // Parse the MAC commands ParseCommands (fHdr); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 6e72657c9d..0e80362425 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -127,8 +127,8 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () m_aggregatedDutyCycle (1), m_mType (LorawanMacHeader::CONFIRMED_DATA_UP), m_currentFCnt (0), - m_joinNonce (0), - m_devNonce (0) + m_joinNonce (1), + m_devNonce (1) { NS_LOG_FUNCTION (this); @@ -320,7 +320,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) packet->AddHeader (macHdr); micTrlr = LorawanMICTrailer (); - //ApplyNecessaryOptions (micTrlr); + ApplyNecessaryOptions (micTrlr); packet->AddTrailer (micTrlr); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -542,6 +542,12 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) // * RX1DROffset => m_rx1DROffset // * RX2DataRate => m_secondReceiveWindowDataRate // * DevNonce => m_devNonce +// * NwkKey => m_nwkKey +// * JoinEUI => m_joinEUI +// * FCntUp => m_currentFCnt +// * TxDR => m_dataRate +// * TxCh => +// * ConfFCnt => 0x0000 // */ // // micTrlr.GenerateB0UL (B0, m_address.GetNwkAddr(), FCntUp, msgLen); @@ -1008,5 +1014,58 @@ EndDeviceLorawanMac::GetTransmissionPower (void) { return m_txPower; } + +void +EndDeviceLorawanMac::SetNwkKey(uint8_t nwkKey[16]) +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + m_nwkKey[i] = nwkKey[i]; + } + + return; +} + +void +EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) const +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + nwkKey[i] = m_nwkKey[i]; + } + + return; +} + +void +EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[16]) +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + m_joinEUI[i] = joinEUI[i]; + } + + return; +} + +void +EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[16]) const +{ + unsigned int i; + + for (i = 0;i < 16;i++) + { + joinEUI[i] = m_joinEUI[i]; + } + + return; +} + } } diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index d0eecc5af7..47891b6488 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -340,6 +340,12 @@ class EndDeviceLorawanMac : public LorawanMac void SetNwkServer(Ptr nwkServer); + void SetNwkKey(uint8_t nwkKey[16]); + void GetNwkKey(uint8_t nwkKey[16]) const; + + void SetJoinEUI(uint8_t joinEUI[16]); + void GetJoinEUI(uint8_t joinEUI[16]) const; + protected: /** * Structure representing the parameters that will be used in the @@ -517,6 +523,9 @@ class EndDeviceLorawanMac : public LorawanMac LorawanMacHeader::MType m_mType; uint16_t m_currentFCnt; + + uint8_t m_nwkKey[16]; + uint8_t m_joinEUI[16]; }; From e79522825cb66e16e9b3bedbc942be5a0b3d81ab Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Sun, 21 May 2023 18:44:23 -0400 Subject: [PATCH 07/11] Added generation of NwkKey's in LorawanMacHelper --- helper/lorawan-mac-helper.cc | 30 ++++++++++++++++++++++++++++++ helper/lorawan-mac-helper.h | 4 ++++ 2 files changed, 34 insertions(+) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 3de51c6de3..972fc90d45 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -32,6 +32,10 @@ NS_LOG_COMPONENT_DEFINE ("LorawanMacHelper"); LorawanMacHelper::LorawanMacHelper () : m_region (LorawanMacHelper::EU) { + m_CurNwkKey = { 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0}; } void @@ -106,6 +110,9 @@ LorawanMacHelper::Create (Ptr node, Ptr device) const break; } } + + mac->SetNwkKey(m_CurNwkKey); + GenerateNwkKey(); } else { @@ -668,5 +675,28 @@ LorawanMacHelper::SetSpreadingFactorsGivenDistribution (NodeContainer endDevices } // end function +void +LorawanMacHelper::GenerateNwkKey(void) +{ + /* just increment from the last one */ + int i; + + for (i = 15;i >= 0;i--) + { + if (m_CurNwkKey[i] == 255) + { + /* carry over to next byte */ + m_CurNwkKey[i] = 0; + } + else + { + m_CurNwkKey[i]++; + break; + } + } + + return; +} + } // namespace lorawan } // namespace ns3 diff --git a/helper/lorawan-mac-helper.h b/helper/lorawan-mac-helper.h index e472fa1e44..ffc7de1da9 100644 --- a/helper/lorawan-mac-helper.h +++ b/helper/lorawan-mac-helper.h @@ -166,10 +166,14 @@ class LorawanMacHelper */ void ApplyCommonAlohaConfigurations (Ptr lorawanMac) const; + virtual void GenerateNwkKey(void); + ObjectFactory m_mac; Ptr m_addrGen; //!< Pointer to the address generator to use enum DeviceType m_deviceType; //!< The kind of device to install enum Regions m_region; //!< The region in which the device will operate + + uint8_t m_CurNwkKey[16]; }; } // namespace lorawan From 6e3f332844c81454580888189ce3349eb1c46abe Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Mon, 22 May 2023 20:34:56 -0400 Subject: [PATCH 08/11] Organised TxCh and JoinEUI parameters --- helper/lorawan-mac-helper.cc | 30 ++++++++++- helper/lorawan-mac-helper.h | 2 + model/class-a-end-device-lorawan-mac.cc | 2 +- model/end-device-lorawan-mac.cc | 66 ++++++++++++++++++++----- model/end-device-lorawan-mac.h | 18 +++++-- 5 files changed, 101 insertions(+), 17 deletions(-) diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 972fc90d45..720c9a2580 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -32,10 +32,13 @@ NS_LOG_COMPONENT_DEFINE ("LorawanMacHelper"); LorawanMacHelper::LorawanMacHelper () : m_region (LorawanMacHelper::EU) { - m_CurNwkKey = { 0, 0, 0, 0, + m_CurNwkKey = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + m_CurJoinEUI = {0, 0, 0, 0 + 0, 0, 0, 0}; } void @@ -113,6 +116,8 @@ LorawanMacHelper::Create (Ptr node, Ptr device) const mac->SetNwkKey(m_CurNwkKey); GenerateNwkKey(); + mac->SetJoinEUI(m_CurJoinEUI); + GenerateJoinEUI(); } else { @@ -698,5 +703,28 @@ LorawanMacHelper::GenerateNwkKey(void) return; } +void +LorawanMacHelper::GenerateJoinEUI(void) +{ + /* just increment from the last one */ + int i; + + for (i = 7;i >= 0;i--) + { + if (m_CurJoinEUI[i] == 255) + { + /* carry over to next byte */ + m_CurJoinEUI[i] = 0; + } + else + { + m_CurJoinEUI[i]++; + break; + } + } + + return; +} + } // namespace lorawan } // namespace ns3 diff --git a/helper/lorawan-mac-helper.h b/helper/lorawan-mac-helper.h index ffc7de1da9..4d9dcac09d 100644 --- a/helper/lorawan-mac-helper.h +++ b/helper/lorawan-mac-helper.h @@ -167,6 +167,7 @@ class LorawanMacHelper void ApplyCommonAlohaConfigurations (Ptr lorawanMac) const; virtual void GenerateNwkKey(void); + virtual void GenerateJoinEUI(void); ObjectFactory m_mac; Ptr m_addrGen; //!< Pointer to the address generator to use @@ -174,6 +175,7 @@ class LorawanMacHelper enum Regions m_region; //!< The region in which the device will operate uint8_t m_CurNwkKey[16]; + uint8_t m_CurJoinEUI[8] }; } // namespace lorawan diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 72da22bfd0..ba2133031c 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -111,7 +111,7 @@ ClassAEndDeviceLorawanMac::SendToPhy (Ptr packetToSend) // Wake up PHY layer and directly send the packet - Ptr txChannel = GetChannelForTx (); + Ptr txChannel = m_txCh; NS_LOG_DEBUG ("PacketToSend: " << packetToSend); m_phy->Send (packetToSend, params, txChannel->GetFrequency (), m_txPower); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 0e80362425..3fd0c03744 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -239,9 +239,11 @@ EndDeviceLorawanMac::DoSend (Ptr packet) ApplyNecessaryOptions (macHdr); packet->AddHeader (macHdr); + m_txCh = GetChannelForTx(); + //Add MIC trailer LorawanMICTrailer micTrlr; - //ApplyNecessaryOptions (micTrlr); + ApplyNecessaryOptions (micTrlr); packet->AddTrailer (micTrlr); // Reset MAC command list @@ -275,7 +277,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) NS_LOG_INFO ("Added MAC header of size " << macHdr.GetSerializedSize () << " bytes."); - + // Sent a new packet NS_LOG_DEBUG ("Copied packet: " << m_retxParams.packet); m_sentNewPacket (m_retxParams.packet); @@ -314,6 +316,8 @@ EndDeviceLorawanMac::DoSend (Ptr packet) NS_LOG_INFO ("Added frame header of size " << frameHdr.GetSerializedSize () << " bytes."); + m_txCh = GetChannelForTx(); + // Add the Lorawan Mac header to the packet macHdr = LorawanMacHeader (); ApplyNecessaryOptions (macHdr); @@ -546,7 +550,7 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) // * JoinEUI => m_joinEUI // * FCntUp => m_currentFCnt // * TxDR => m_dataRate -// * TxCh => +// * TxCh => m_txChIndex (check (m_txCh == 0)) // * ConfFCnt => 0x0000 // */ // @@ -632,7 +636,7 @@ EndDeviceLorawanMac::GetNextTransmissionDelay (void) return waitingTime; } -Ptr +uint8_t EndDeviceLorawanMac::GetChannelForTx (void) { NS_LOG_FUNCTION_NOARGS (); @@ -644,7 +648,9 @@ EndDeviceLorawanMac::GetChannelForTx (void) // Try every channel std::vector >::iterator it; - for (it = logicalChannels.begin (); it != logicalChannels.end (); ++it) + unsigned int i; + + for (it = logicalChannels.begin (), i = 0; it != logicalChannels.end (); ++it, i++) { // Pointer to the current channel Ptr logicalChannel = *it; @@ -661,7 +667,8 @@ EndDeviceLorawanMac::GetChannelForTx (void) // Send immediately if we can if (waitingTime == Seconds (0)) { - return *it; + m_txCh = *it; + return i; } else { @@ -669,7 +676,9 @@ EndDeviceLorawanMac::GetChannelForTx (void) "the current channel because of duty cycle limitations."); } } - return 0; // In this case, no suitable channel was found + + m_txCh = 0; // In this case, no suitable channel was found + return 0; } @@ -1042,11 +1051,11 @@ EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) const } void -EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[16]) +EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[8]) { unsigned int i; - for (i = 0;i < 16;i++) + for (i = 0;i < 8;i++) { m_joinEUI[i] = joinEUI[i]; } @@ -1055,11 +1064,11 @@ EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[16]) } void -EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[16]) const +EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) const { unsigned int i; - for (i = 0;i < 16;i++) + for (i = 0;i < 8;i++) { joinEUI[i] = m_joinEUI[i]; } @@ -1067,5 +1076,40 @@ EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[16]) const return; } +void +EndDeviceLorawanMac::SetJoinNonce(uint32_t joinNonce) +{ + /* three bytes long and should be at least one to be in the network */ + if (joinNonce > 0 && joinNonce < 0x01000000) + { + m_joinNonce = joinNonce; + } + + return; +} + +uint32_t +EndDeviceLorawanMac::GetJoinNonce(void) const +{ + return m_joinNonce; +} + +void +EndDeviceLorawanMac::SetDevNonce(uint16_t devNonce) +{ + if (devNonce > 0) + { + m_devNonce = devNonce; + } + + return; +} + +uint16_t +EndDeviceLorawanMac::GetDevNonce(void) const +{ + return m_devNonce; +} + } } diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 47891b6488..7de9b0025b 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -340,11 +340,17 @@ class EndDeviceLorawanMac : public LorawanMac void SetNwkServer(Ptr nwkServer); + void SetJoinNonce(uint32_t joinNonce); + uint32_t GetJoinNonce(void) const; + + void SetDevNonce(uint16_t devNonce); + uint16_t GetDevNonce(void) const; + void SetNwkKey(uint8_t nwkKey[16]); void GetNwkKey(uint8_t nwkKey[16]) const; - void SetJoinEUI(uint8_t joinEUI[16]); - void GetJoinEUI(uint8_t joinEUI[16]) const; + void SetJoinEUI(uint8_t joinEUI[8]); + void GetJoinEUI(uint8_t joinEUI[8]) const; protected: /** @@ -405,7 +411,7 @@ class EndDeviceLorawanMac : public LorawanMac * ones that are available in the ED's LogicalLoraChannel, based on their duty * cycle limitations. */ - Ptr GetChannelForTx (void); + uint8_t GetChannelForTx (void); /** * The duration of a receive window in number of symbols. This should be @@ -451,6 +457,10 @@ class EndDeviceLorawanMac : public LorawanMac */ uint8_t m_secondReceiveWindowDataRate; + Ptr m_txCh; + + uint8_t m_txChIndex; + ///////////////// // Callbacks // ///////////////// @@ -525,7 +535,7 @@ class EndDeviceLorawanMac : public LorawanMac uint16_t m_currentFCnt; uint8_t m_nwkKey[16]; - uint8_t m_joinEUI[16]; + uint8_t m_joinEUI[8]; }; From 1bddf5ba55c77c41b2bc24470372e1f4d7811eb1 Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Tue, 23 May 2023 20:51:16 -0400 Subject: [PATCH 09/11] Finished up MIC Trailer calculation for packets in end device --- model/end-device-lorawan-mac.cc | 156 ++++++++++++++++++++------------ model/end-device-lorawan-mac.h | 14 +-- model/lorawan-mic-trailer.cc | 2 + model/lorawan-mic-trailer.h | 5 +- model/network-controller.h | 1 + 5 files changed, 111 insertions(+), 67 deletions(-) diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 3fd0c03744..e7956ccc1b 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -216,6 +216,11 @@ EndDeviceLorawanMac::DoSend (Ptr packet) m_currentFCnt++; NS_LOG_DEBUG ("APP packet: " << packet << "."); + /* for MIC calculation later */ + uint8_t msglen = packet->GetSize(); + std::vector msg(msglen); + packet->CopyData(msg.data(), msglen); + // Add the Lora Frame Header to the packet LoraFrameHeader frameHdr; ApplyNecessaryOptions (frameHdr); @@ -243,7 +248,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) //Add MIC trailer LorawanMICTrailer micTrlr; - ApplyNecessaryOptions (micTrlr); + ApplyNecessaryOptions (micTrlr, msg, msglen); packet->AddTrailer (micTrlr); // Reset MAC command list @@ -307,6 +312,10 @@ EndDeviceLorawanMac::DoSend (Ptr packet) packet->RemoveHeader(macHdr); packet->RemoveHeader(frameHdr); + /* for MIC calculation later */ + uint8_t msglen = packet->GetSize(); + std::vector msg(msglen); + packet->CopyData(msg.data(), msglen); // Add the Lora Frame Header to the packet frameHdr = LoraFrameHeader (); @@ -324,7 +333,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) packet->AddHeader (macHdr); micTrlr = LorawanMICTrailer (); - ApplyNecessaryOptions (micTrlr); + ApplyNecessaryOptions (micTrlr, msg, msglen); packet->AddTrailer (micTrlr); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -519,63 +528,94 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMacHeader& macHeader) macHeader.SetMajor (1); } -// void -// EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) -// { -// uint8_t B0[16]; -// uint8_t B1[16]; -// uint16_t ConfFCnt; -// uint32_t mic_temp; -// -// NS_LOG_FUNCTION_NOARGS (); -// -// if (isLorawan_1_1 && isAck) -// { -// ConfFCnt = fcnt; /* only value is of uint16_t so modding by 2^16 does nothing? maybe misunderstanding smth */ -// } -// else -// { -// ConfFCnt = 0x0000; -// } -// -// /* -// * Network ID => m_address.GetNwkID() -// * Network Addresss => m_address.GetNwkID() -// * Network Server Version => m_networkServer->IsVersion1() -// * JoinNonce => m_joinNonce -// * RX1DROffset => m_rx1DROffset -// * RX2DataRate => m_secondReceiveWindowDataRate -// * DevNonce => m_devNonce -// * NwkKey => m_nwkKey -// * JoinEUI => m_joinEUI -// * FCntUp => m_currentFCnt -// * TxDR => m_dataRate -// * TxCh => m_txChIndex (check (m_txCh == 0)) -// * ConfFCnt => 0x0000 -// */ -// -// micTrlr.GenerateB0UL (B0, m_address.GetNwkAddr(), FCntUp, msgLen); -// -// if (isLorawan_1_1) -// { -// micTrlr.GenerateB1UL (B1, ConfFCnt, m_dataRate, txch, m_address.GetNwkAddr(), FCntUp, msgLen); -// mic_temp = micTrlr.CalcMIC_1_1_UL (msgLen, msg, B0 ,B1, SNwkSIntKey, FNwkSIntKey); -// micTrlr.SetMIC (mic_temp); -// } -// else -// { -// mic_temp = micTrlr.CalcMIC (msgLen, msg, B0, FNwkSIntKey); -// micTrlr.SetMIC (mic_temp); -// } -// -// } - -/* placeholder func until all parameters are better organized for MIC calc */ -void EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr) +void +EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t *msg, uint8_t len) { + uint8_t B0[16]; + uint8_t B1[16]; + uint8_t FNwkSIntKey[16]; + uint8_t SNwkSIntKey[16]; + + + uint16_t ConfFCnt; + uint32_t mic_temp; + NS_LOG_FUNCTION_NOARGS (); - micTrlr.SetMIC (0x00000000); + /* + * Network ID => m_address.GetNwkID().Get() + * DevAddr => m_address.GetNwkAddr().Get() + * Network Server Version => m_networkServer->IsVersion1() + * JoinNonce => m_joinNonce + * RX1DROffset => m_rx1DROffset + * RX2DataRate => m_secondReceiveWindowDataRate + * DevNonce => m_devNonce + * NwkKey => m_nwkKey + * JoinEUI => m_joinEUI + * FCntUp => m_currentFCnt + * TxDR => m_dataRate + * TxCh => m_txChIndex (check (m_txCh == 0)) + * ConfFCnt => 0x0000 + */ + + if (m_networkServer->IsVersion1()) + { + /* temp <= 0x01 | JoinNonce(3) | NetID(1) | DevNonce(2) | 0x000000000000000000 */ + uint8_t temp[16] = { + 0x01, (uint8_t)((GetJoinNonce() & 0x00FF0000) >> 16), + (uint8_t)((GetJoinNonce() & 0x0000FF00) >> 8), (uint8_t)(GetJoinNonce() & 0x000000FF), + m_address.GetNwkID.Get(), (uint8_t)((GetDevNonce() & 0xFF00) >> 8), + (uint8_t)(GetDevNonce() & 0x00FF), 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00 + }; + + micTrlr.aes128(m_nwkKey, temp, FNwkSIntKey); + micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr().Get(), (uint32_t)m_currentFCnt, len); + mic_temp = micTrlr.CalcMIC(len, msg, B0, FNwkSIntKey); + } + else /* v1.1 or later */ + { + /* tempf <= 0x01 | JoinNonce(3) | JoinEUI(8) | DevNonce(2) | 0x0000 */ + uint8_t tempf[16] = { + 0x01, (uint8_t)((GetJoinNonce() & 0x00FF0000) >> 16), + (uint8_t)((GetJoinNonce() & 0x0000FF00) >> 8), (uint8_t)(GetJoinNonce() & 0x000000FF), + m_joinEUI[7], m_joinEUI[6], + m_joinEUI[5], m_joinEUI[4], + m_joinEUI[3], m_joinEUI[2], + m_joinEUI[1], m_joinEUI[0], + (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF) + 0x00, 0x00 + }; + + /* temps <= 0x03 | JoinNonce(3) | JoinEUI(8) | DevNonce(2) | 0x0000 */ + uint8_t temps[16] = { + 0x03, (uint8_t)((GetJoinNonce() & 0x00FF0000) >> 16), + (uint8_t)((GetJoinNonce() & 0x0000FF00) >> 8), (uint8_t)(GetJoinNonce() & 0x000000FF), + m_joinEUI[7], m_joinEUI[6], + m_joinEUI[5], m_joinEUI[4], + m_joinEUI[3], m_joinEUI[2], + m_joinEUI[1], m_joinEUI[0], + (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF) + 0x00, 0x00 + }; + + micTrlr.aes128(m_nwkKey, tempf, FNwkSIntKey); + micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr().Get(), (uint32_t)m_currentFCnt, len); + + + micTrlr.aes128(m_nwkKey, temps, SNwkSIntKey); + micTrlr.GenerateB1UL(B1, 0x0000, m_dataRate, m_txChIndex, m_address.GetNwkAddr().Get(), + (uint32_t)m_currentFCnt, len); + + mic_temp = micTrlr.CalcMIC_1_1_UL(len, msg, B0, B1, SNwkSIntKey, FNwkSIntKey); + } + + micTrlr.SetMIC(mic_temp); + + return; } void @@ -1038,7 +1078,7 @@ EndDeviceLorawanMac::SetNwkKey(uint8_t nwkKey[16]) } void -EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) const +EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) { unsigned int i; @@ -1064,7 +1104,7 @@ EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[8]) } void -EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) const +EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) { unsigned int i; diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 7de9b0025b..efc4aca115 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -222,7 +222,7 @@ class EndDeviceLorawanMac : public LorawanMac /** * Add the necessary options and to the LorawanMICTrailer. */ - void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr); + void ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t *msg, uint8_t len); /** * Set the message type to send when the Send method is called. @@ -347,10 +347,10 @@ class EndDeviceLorawanMac : public LorawanMac uint16_t GetDevNonce(void) const; void SetNwkKey(uint8_t nwkKey[16]); - void GetNwkKey(uint8_t nwkKey[16]) const; + void GetNwkKey(uint8_t nwkKey[16]); void SetJoinEUI(uint8_t joinEUI[8]); - void GetJoinEUI(uint8_t joinEUI[8]) const; + void GetJoinEUI(uint8_t joinEUI[8]); protected: /** @@ -443,10 +443,6 @@ class EndDeviceLorawanMac : public LorawanMac Ptr m_networkServer; - uint32_t m_joinNonce; /* join accept count - should be 3 bytes long */ - - uint16_t m_devNonce; /* join request count */ - /** * The RX1DROffset parameter value */ @@ -534,6 +530,10 @@ class EndDeviceLorawanMac : public LorawanMac uint16_t m_currentFCnt; + uint32_t m_joinNonce; /* join accept count - should be 3 bytes long */ + + uint16_t m_devNonce; /* join request count */ + uint8_t m_nwkKey[16]; uint8_t m_joinEUI[8]; }; diff --git a/model/lorawan-mic-trailer.cc b/model/lorawan-mic-trailer.cc index d5886f6a7d..6fc947093d 100644 --- a/model/lorawan-mic-trailer.cc +++ b/model/lorawan-mic-trailer.cc @@ -221,6 +221,8 @@ LorawanMICTrailer::aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]) {0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16} }; + aes128_keyexpansion(K, w, sbox); + /* move input into state matrix */ for (i = 0;i < 4;i++) { diff --git a/model/lorawan-mic-trailer.h b/model/lorawan-mic-trailer.h index 5337faa148..bf11a2f01e 100644 --- a/model/lorawan-mic-trailer.h +++ b/model/lorawan-mic-trailer.h @@ -19,7 +19,6 @@ class LorawanMICTrailer : public Trailer void padding_128 (uint8_t *in, uint8_t out[16], unsigned int length); /* AES-128 funcs taken from NIST publication */ - void aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]); void aes128_subbytes (uint8_t state[4][4], const uint8_t sbox[16][16]); void aes128_shiftrows (uint8_t state[4][4]); void aes128_mixcolumns (uint8_t state[4][4]); @@ -42,11 +41,13 @@ class LorawanMICTrailer : public Trailer virtual uint32_t Deserialize (Buffer::Iterator end); virtual void Print (std::ostream &os) const; + void aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]); + uint32_t GetMIC (void) const; void SetMIC (uint32_t newMIC); uint32_t CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); /* Bx and xNwkSIntKey need to be 16 bytes (128 bits) each, uint128_t is not guranteed to be supported */ uint32_t CalcMIC_1_1_UL(uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); /* special case for UL for 1.1 LoRaWAN network servers */ - bool VerifyMIC (uint8_t msgLen, uint8_t *msg,uint8_t B0[16], uint8_t xNwkSIntKey[16]); + bool VerifyMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); bool VerifyMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); /* for making B0 and B1 */ diff --git a/model/network-controller.h b/model/network-controller.h index 7e7ee3e9ab..09cb17db80 100644 --- a/model/network-controller.h +++ b/model/network-controller.h @@ -25,6 +25,7 @@ #include "ns3/packet.h" #include "ns3/network-status.h" #include "ns3/network-controller-components.h" +#include "ns3/end-device-status.h" namespace ns3 { namespace lorawan { From d2bf8949a36354515bcb8585a5b55e5b3e533f54 Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Thu, 25 May 2023 05:52:26 -0400 Subject: [PATCH 10/11] Moved the network server version from being stored only on the network server to each endnode having its own record --- helper/lora-helper.cc | 12 ++-- helper/lora-helper.h | 12 ++-- helper/lorawan-mac-helper.cc | 24 +++---- helper/lorawan-mac-helper.h | 12 ++-- model/class-a-end-device-lorawan-mac.cc | 3 +- model/class-a-end-device-lorawan-mac.h | 9 +-- model/end-device-lorawan-mac.cc | 87 +++++++++++++------------ model/end-device-lorawan-mac.h | 22 ++++--- model/end-device-status.h | 3 +- model/network-server.cc | 15 +---- model/network-server.h | 7 +- model/network-status.h | 2 +- 12 files changed, 98 insertions(+), 110 deletions(-) diff --git a/helper/lora-helper.cc b/helper/lora-helper.cc index 80a5822ccf..b57c2fffc4 100644 --- a/helper/lora-helper.cc +++ b/helper/lora-helper.cc @@ -39,9 +39,9 @@ NS_LOG_COMPONENT_DEFINE ("LoraHelper"); } NetDeviceContainer - LoraHelper::Install ( const LoraPhyHelper &phyHelper, - const LorawanMacHelper &macHelper, - NodeContainer c) const + LoraHelper::Install ( LoraPhyHelper &phyHelper, + LorawanMacHelper &macHelper, + NodeContainer c) { NS_LOG_FUNCTION_NOARGS (); @@ -147,9 +147,9 @@ NS_LOG_COMPONENT_DEFINE ("LoraHelper"); } NetDeviceContainer -LoraHelper::Install ( const LoraPhyHelper &phy, - const LorawanMacHelper &mac, - Ptr node) const +LoraHelper::Install ( LoraPhyHelper &phy, + LorawanMacHelper &mac, + Ptr node) { return Install (phy, mac, NodeContainer (node)); } diff --git a/helper/lora-helper.h b/helper/lora-helper.h index 98403224c7..a153d764de 100644 --- a/helper/lora-helper.h +++ b/helper/lora-helper.h @@ -56,9 +56,9 @@ class LoraHelper * \returns a device container which contains all the devices created by this * method. */ - virtual NetDeviceContainer Install (const LoraPhyHelper &phyHelper, - const LorawanMacHelper &macHelper, - NodeContainer c) const; + virtual NetDeviceContainer Install (LoraPhyHelper &phyHelper, + LorawanMacHelper &macHelper, + NodeContainer c); /** * Install LoraNetDevice on a single node @@ -69,9 +69,9 @@ class LoraHelper * \returns a device container which contains all the devices created by this * method. */ - virtual NetDeviceContainer Install (const LoraPhyHelper &phyHelper, - const LorawanMacHelper &macHelper, - Ptr node) const; + virtual NetDeviceContainer Install (LoraPhyHelper &phyHelper, + LorawanMacHelper &macHelper, + Ptr node); /** * Enable tracking of packets via trace sources. diff --git a/helper/lorawan-mac-helper.cc b/helper/lorawan-mac-helper.cc index 720c9a2580..ff039389e9 100644 --- a/helper/lorawan-mac-helper.cc +++ b/helper/lorawan-mac-helper.cc @@ -32,13 +32,15 @@ NS_LOG_COMPONENT_DEFINE ("LorawanMacHelper"); LorawanMacHelper::LorawanMacHelper () : m_region (LorawanMacHelper::EU) { - m_CurNwkKey = { 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0}; + for (unsigned int i = 0;i < 16;i++) + { + m_CurNwkKey[i] = 0; + } - m_CurJoinEUI = {0, 0, 0, 0 - 0, 0, 0, 0}; + for (unsigned int i = 0;i < 8;i++) + { + m_CurJoinEUI[i] = 0; + } } void @@ -78,7 +80,7 @@ LorawanMacHelper::SetRegion (enum LorawanMacHelper::Regions region) } Ptr -LorawanMacHelper::Create (Ptr node, Ptr device) const +LorawanMacHelper::Create (Ptr node, Ptr device) { Ptr mac = m_mac.Create (); mac->SetDevice (device); @@ -114,9 +116,9 @@ LorawanMacHelper::Create (Ptr node, Ptr device) const } } - mac->SetNwkKey(m_CurNwkKey); + edMac->SetNwkKey(m_CurNwkKey); GenerateNwkKey(); - mac->SetJoinEUI(m_CurJoinEUI); + edMac->SetJoinEUI(m_CurJoinEUI); GenerateJoinEUI(); } else @@ -680,7 +682,7 @@ LorawanMacHelper::SetSpreadingFactorsGivenDistribution (NodeContainer endDevices } // end function -void +void LorawanMacHelper::GenerateNwkKey(void) { /* just increment from the last one */ @@ -703,7 +705,7 @@ LorawanMacHelper::GenerateNwkKey(void) return; } -void +void LorawanMacHelper::GenerateJoinEUI(void) { /* just increment from the last one */ diff --git a/helper/lorawan-mac-helper.h b/helper/lorawan-mac-helper.h index 4d9dcac09d..923edeef64 100644 --- a/helper/lorawan-mac-helper.h +++ b/helper/lorawan-mac-helper.h @@ -96,7 +96,7 @@ class LorawanMacHelper * \param device the device within which this MAC will be created. * \returns a newly-created LorawanMac object. */ - Ptr Create (Ptr node, Ptr device) const; + Ptr Create (Ptr node, Ptr device); /** * Set up the end device's data rates @@ -116,7 +116,7 @@ class LorawanMacHelper static std::vector SetSpreadingFactorsGivenDistribution (NodeContainer endDevices, NodeContainer gateways, std::vector distribution); - + private: /** * Perform region-specific configurations for the 868 MHz EU band. @@ -165,17 +165,17 @@ class LorawanMacHelper * ClassAEndDeviceLorawanMac classes. */ void ApplyCommonAlohaConfigurations (Ptr lorawanMac) const; - - virtual void GenerateNwkKey(void); - virtual void GenerateJoinEUI(void); ObjectFactory m_mac; Ptr m_addrGen; //!< Pointer to the address generator to use enum DeviceType m_deviceType; //!< The kind of device to install enum Regions m_region; //!< The region in which the device will operate + void GenerateNwkKey(void); + void GenerateJoinEUI(void); + uint8_t m_CurNwkKey[16]; - uint8_t m_CurJoinEUI[8] + uint8_t m_CurJoinEUI[8]; }; } // namespace lorawan diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index ba2133031c..0ffa39be5d 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -49,8 +49,7 @@ ClassAEndDeviceLorawanMac::ClassAEndDeviceLorawanMac () : // LoraWAN default m_receiveDelay1 (Seconds (1)), // LoraWAN default - m_receiveDelay2 (Seconds (2)), - m_rx1DrOffset (0) + m_receiveDelay2 (Seconds (2)) { NS_LOG_FUNCTION (this); diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index 4b3f31c95f..845fff7765 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -27,17 +27,18 @@ #include "ns3/lorawan-mac.h" // Packet #include "ns3/end-device-lorawan-mac.h" // EndDeviceLorawanMac #include "ns3/lora-frame-header.h" // RxParamSetupReq -// #include "ns3/random-variable-stream.h" +//#include "ns3/random-variable-stream.h" #include "ns3/lora-device-address.h" -// #include "ns3/traced-value.h" +//#include "ns3/traced-value.h" namespace ns3 { namespace lorawan { - + /** * Class representing the MAC layer of a Class A LoRaWAN device. */ -class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac + +class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac { public: static TypeId GetTypeId (void); diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index e7956ccc1b..54d4f2cd6b 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -126,9 +126,7 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () m_lastKnownGatewayCount (0), m_aggregatedDutyCycle (1), m_mType (LorawanMacHeader::CONFIRMED_DATA_UP), - m_currentFCnt (0), - m_joinNonce (1), - m_devNonce (1) + m_currentFCnt (0) { NS_LOG_FUNCTION (this); @@ -143,6 +141,11 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () // Initialize structure for retransmission parameters m_retxParams = EndDeviceLorawanMac::LoraRetxParameters (); m_retxParams.retxLeft = m_maxNumbTx; + + m_joinNonce = 1; + m_devNonce = 1; + m_rx1DrOffset = 0; + m_isVersion1 = false; } EndDeviceLorawanMac::~EndDeviceLorawanMac () @@ -170,11 +173,11 @@ EndDeviceLorawanMac::Send (Ptr packet) } // Pick a channel on which to transmit the packet - Ptr txChannel = GetChannelForTx (); + m_txChIndex = GetChannelForTx(); - if (!(txChannel && m_retxParams.retxLeft > 0)) + if (!(m_txCh && m_retxParams.retxLeft > 0)) { - if (!txChannel) + if (!m_txCh) { m_cannotSendBecauseDutyCycle (packet); } @@ -187,7 +190,7 @@ EndDeviceLorawanMac::Send (Ptr packet) // the transmitting channel is available and we have not run out the maximum number of retransmissions { // Make sure we can transmit at the current power on this channel - NS_ASSERT_MSG (m_txPower <= m_channelHelper.GetTxPowerForChannel (txChannel), + NS_ASSERT_MSG (m_txPower <= m_channelHelper.GetTxPowerForChannel (m_txCh), " The selected power is too hight to be supported by this channel."); DoSend (packet); } @@ -244,11 +247,9 @@ EndDeviceLorawanMac::DoSend (Ptr packet) ApplyNecessaryOptions (macHdr); packet->AddHeader (macHdr); - m_txCh = GetChannelForTx(); - //Add MIC trailer LorawanMICTrailer micTrlr; - ApplyNecessaryOptions (micTrlr, msg, msglen); + ApplyNecessaryOptions (micTrlr, msg.data(), msglen); packet->AddTrailer (micTrlr); // Reset MAC command list @@ -324,8 +325,6 @@ EndDeviceLorawanMac::DoSend (Ptr packet) NS_LOG_INFO ("Added frame header of size " << frameHdr.GetSerializedSize () << " bytes."); - - m_txCh = GetChannelForTx(); // Add the Lorawan Mac header to the packet macHdr = LorawanMacHeader (); @@ -333,7 +332,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) packet->AddHeader (macHdr); micTrlr = LorawanMICTrailer (); - ApplyNecessaryOptions (micTrlr, msg, msglen); + ApplyNecessaryOptions (micTrlr, msg.data(), msglen); packet->AddTrailer (micTrlr); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -535,16 +534,13 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t uint8_t B1[16]; uint8_t FNwkSIntKey[16]; uint8_t SNwkSIntKey[16]; - - - uint16_t ConfFCnt; uint32_t mic_temp; NS_LOG_FUNCTION_NOARGS (); /* - * Network ID => m_address.GetNwkID().Get() - * DevAddr => m_address.GetNwkAddr().Get() + * Network ID => m_address.GetNwkID() + * DevAddr => m_address.GetNwkAddr() * Network Server Version => m_networkServer->IsVersion1() * JoinNonce => m_joinNonce * RX1DROffset => m_rx1DROffset @@ -558,13 +554,13 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t * ConfFCnt => 0x0000 */ - if (m_networkServer->IsVersion1()) + if (IsVersion1()) { /* temp <= 0x01 | JoinNonce(3) | NetID(1) | DevNonce(2) | 0x000000000000000000 */ uint8_t temp[16] = { 0x01, (uint8_t)((GetJoinNonce() & 0x00FF0000) >> 16), (uint8_t)((GetJoinNonce() & 0x0000FF00) >> 8), (uint8_t)(GetJoinNonce() & 0x000000FF), - m_address.GetNwkID.Get(), (uint8_t)((GetDevNonce() & 0xFF00) >> 8), + m_address.GetNwkID(), (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF), 0x00, 0x00, 0x00, 0x00, 0x00, @@ -573,7 +569,7 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t }; micTrlr.aes128(m_nwkKey, temp, FNwkSIntKey); - micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr().Get(), (uint32_t)m_currentFCnt, len); + micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr(), (uint32_t)m_currentFCnt, len); mic_temp = micTrlr.CalcMIC(len, msg, B0, FNwkSIntKey); } else /* v1.1 or later */ @@ -586,7 +582,7 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t m_joinEUI[5], m_joinEUI[4], m_joinEUI[3], m_joinEUI[2], m_joinEUI[1], m_joinEUI[0], - (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF) + (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF), 0x00, 0x00 }; @@ -598,16 +594,16 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t m_joinEUI[5], m_joinEUI[4], m_joinEUI[3], m_joinEUI[2], m_joinEUI[1], m_joinEUI[0], - (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF) + (uint8_t)((GetDevNonce() & 0xFF00) >> 8), (uint8_t)(GetDevNonce() & 0x00FF), 0x00, 0x00 }; micTrlr.aes128(m_nwkKey, tempf, FNwkSIntKey); - micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr().Get(), (uint32_t)m_currentFCnt, len); + micTrlr.GenerateB0UL(B0, m_address.GetNwkAddr(), (uint32_t)m_currentFCnt, len); micTrlr.aes128(m_nwkKey, temps, SNwkSIntKey); - micTrlr.GenerateB1UL(B1, 0x0000, m_dataRate, m_txChIndex, m_address.GetNwkAddr().Get(), + micTrlr.GenerateB1UL(B1, 0x0000, m_dataRate, m_txChIndex, m_address.GetNwkAddr(), (uint32_t)m_currentFCnt, len); mic_temp = micTrlr.CalcMIC_1_1_UL(len, msg, B0, B1, SNwkSIntKey, FNwkSIntKey); @@ -1042,7 +1038,7 @@ EndDeviceLorawanMac::GetAggregatedDutyCycle (void) return m_aggregatedDutyCycle; } -void +void EndDeviceLorawanMac::AddMacCommand (Ptr macCommand) { NS_LOG_FUNCTION (this << macCommand); @@ -1050,15 +1046,7 @@ EndDeviceLorawanMac::AddMacCommand (Ptr macCommand) m_macCommandList.push_back (macCommand); } -void -EndDeviceLorawanMac::SetNwkServer(Ptr nwkServer); -{ - m_networkServer = nwkServer; - - return; -} - -uint8_t +uint8_t EndDeviceLorawanMac::GetTransmissionPower (void) { return m_txPower; @@ -1077,7 +1065,7 @@ EndDeviceLorawanMac::SetNwkKey(uint8_t nwkKey[16]) return; } -void +void EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) { unsigned int i; @@ -1103,7 +1091,7 @@ EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[8]) return; } -void +void EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) { unsigned int i; @@ -1116,7 +1104,7 @@ EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) return; } -void +void EndDeviceLorawanMac::SetJoinNonce(uint32_t joinNonce) { /* three bytes long and should be at least one to be in the network */ @@ -1128,13 +1116,13 @@ EndDeviceLorawanMac::SetJoinNonce(uint32_t joinNonce) return; } -uint32_t -EndDeviceLorawanMac::GetJoinNonce(void) const +uint32_t +EndDeviceLorawanMac::GetJoinNonce(void) { return m_joinNonce; } -void +void EndDeviceLorawanMac::SetDevNonce(uint16_t devNonce) { if (devNonce > 0) @@ -1145,11 +1133,24 @@ EndDeviceLorawanMac::SetDevNonce(uint16_t devNonce) return; } -uint16_t -EndDeviceLorawanMac::GetDevNonce(void) const +uint16_t +EndDeviceLorawanMac::GetDevNonce(void) { return m_devNonce; } +bool +EndDeviceLorawanMac::IsVersion1(void) const +{ + return m_isVersion1; +} + +void +EndDeviceLorawanMac::SetIsVersion1(bool isVersion1) +{ + m_isVersion1 = isVersion1; + return; +} + } } diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index efc4aca115..55b12ab31a 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -31,11 +31,10 @@ #include "ns3/random-variable-stream.h" #include "ns3/lora-device-address.h" #include "ns3/traced-value.h" -#include "ns3/network-server.h" namespace ns3 { namespace lorawan { - + /** * Class representing the MAC layer of a LoRaWAN device. */ @@ -338,13 +337,13 @@ class EndDeviceLorawanMac : public LorawanMac */ void AddMacCommand (Ptr macCommand); - void SetNwkServer(Ptr nwkServer); + //void SetNwkServer(Ptr nwkServer); void SetJoinNonce(uint32_t joinNonce); - uint32_t GetJoinNonce(void) const; + uint32_t GetJoinNonce(void); void SetDevNonce(uint16_t devNonce); - uint16_t GetDevNonce(void) const; + uint16_t GetDevNonce(void); void SetNwkKey(uint8_t nwkKey[16]); void GetNwkKey(uint8_t nwkKey[16]); @@ -352,6 +351,9 @@ class EndDeviceLorawanMac : public LorawanMac void SetJoinEUI(uint8_t joinEUI[8]); void GetJoinEUI(uint8_t joinEUI[8]); + bool IsVersion1(void) const; + void SetIsVersion1(bool isVersion1); + protected: /** * Structure representing the parameters that will be used in the @@ -441,8 +443,6 @@ class EndDeviceLorawanMac : public LorawanMac */ Ptr m_uniformRV; - Ptr m_networkServer; - /** * The RX1DROffset parameter value */ @@ -530,12 +530,16 @@ class EndDeviceLorawanMac : public LorawanMac uint16_t m_currentFCnt; - uint32_t m_joinNonce; /* join accept count - should be 3 bytes long */ + /* join accept count - should be 3 bytes long */ + uint32_t m_joinNonce; - uint16_t m_devNonce; /* join request count */ + /* join request count */ + uint16_t m_devNonce; uint8_t m_nwkKey[16]; uint8_t m_joinEUI[8]; + + bool m_isVersion1; /* whether or not the network server version is v1.0 or not */ }; diff --git a/model/end-device-status.h b/model/end-device-status.h index f6d15bc136..62bf7a9859 100644 --- a/model/end-device-status.h +++ b/model/end-device-status.h @@ -28,12 +28,11 @@ #include "ns3/class-a-end-device-lorawan-mac.h" #include "ns3/lora-frame-header.h" #include "ns3/pointer.h" -#include "ns3/lora-frame-header.h" #include namespace ns3 { namespace lorawan { - + /** * This class represents the Network Server's knowledge about an End Device in * the LoRaWAN network it is administering. diff --git a/model/network-server.cc b/model/network-server.cc index 8954a3aa56..a8d61526b4 100644 --- a/model/network-server.cc +++ b/model/network-server.cc @@ -145,7 +145,7 @@ NetworkServer::AddNode (Ptr node) Ptr edLorawanMac = loraNetDevice->GetMac ()->GetObject (); - edLorawanMac->SetNwkServer(this); + //edLorawanMac->SetNwkServer(this); // Update the NetworkStatus about the existence of this node m_status->AddNode (edLorawanMac); @@ -189,18 +189,5 @@ NetworkServer::GetNetworkStatus (void) return m_status; } -bool -NetworkServer::IsVersion1(void) const -{ - return m_isVersion1; -} - -void -NetworkServer::SetIsVersion1(bool isVersion1) -{ - m_isVersion1 = isVersion1; - return; -} - } } diff --git a/model/network-server.h b/model/network-server.h index 0e590f124e..169f6a05af 100644 --- a/model/network-server.h +++ b/model/network-server.h @@ -38,7 +38,7 @@ namespace ns3 { namespace lorawan { - + /** * The NetworkServer is an application standing on top of a node equipped with * links that connect it with the gateways. @@ -98,16 +98,11 @@ class NetworkServer : public Application const Address &address); Ptr GetNetworkStatus (void); - - bool IsVersion1(void) const; - void SetIsVersion1(bool isVersion1); protected: Ptr m_status; Ptr m_controller; Ptr m_scheduler; - - bool m_isVersion1; /* whether or not the network server version is v1.0 or not */ TracedCallback> m_receivedPacket; }; diff --git a/model/network-status.h b/model/network-status.h index 600559d602..ddcf509876 100644 --- a/model/network-status.h +++ b/model/network-status.h @@ -32,7 +32,7 @@ namespace ns3 { namespace lorawan { - + /** * This class represents the knowledge about the state of the network that is * available at the Network Server. It is essentially a collection of two maps: From 6f8cb3cf2192e080f55ef0c5156e12e0717b444f Mon Sep 17 00:00:00 2001 From: sanjay-charran Date: Thu, 25 May 2023 16:53:05 -0400 Subject: [PATCH 11/11] Added in documentation for the new classes functions added for MIC calculation --- model/class-a-end-device-lorawan-mac.cc | 3 +- model/class-a-end-device-lorawan-mac.h | 9 ++ model/end-device-lorawan-mac.cc | 25 +--- model/end-device-lorawan-mac.h | 75 ++++++++--- model/lorawan-mic-trailer.h | 172 ++++++++++++++++++++---- 5 files changed, 221 insertions(+), 63 deletions(-) diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index 0ffa39be5d..ba2133031c 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -49,7 +49,8 @@ ClassAEndDeviceLorawanMac::ClassAEndDeviceLorawanMac () : // LoraWAN default m_receiveDelay1 (Seconds (1)), // LoraWAN default - m_receiveDelay2 (Seconds (2)) + m_receiveDelay2 (Seconds (2)), + m_rx1DrOffset (0) { NS_LOG_FUNCTION (this); diff --git a/model/class-a-end-device-lorawan-mac.h b/model/class-a-end-device-lorawan-mac.h index 845fff7765..79e97ad86d 100644 --- a/model/class-a-end-device-lorawan-mac.h +++ b/model/class-a-end-device-lorawan-mac.h @@ -204,6 +204,15 @@ class ClassAEndDeviceLorawanMac : public EndDeviceLorawanMac */ double m_secondReceiveWindowFrequency; + /** + * The Data Rate to listen for during the second downlink transmission. + */ + uint8_t m_secondReceiveWindowDataRate; + + /** + * The RX1DROffset parameter value + */ + uint8_t m_rx1DrOffset; }; /* ClassAEndDeviceLorawanMac */ } /* namespace lorawan */ diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index 54d4f2cd6b..73ea770cb8 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -144,7 +144,6 @@ EndDeviceLorawanMac::EndDeviceLorawanMac () m_joinNonce = 1; m_devNonce = 1; - m_rx1DrOffset = 0; m_isVersion1 = false; } @@ -538,22 +537,6 @@ EndDeviceLorawanMac::ApplyNecessaryOptions (LorawanMICTrailer& micTrlr, uint8_t NS_LOG_FUNCTION_NOARGS (); - /* - * Network ID => m_address.GetNwkID() - * DevAddr => m_address.GetNwkAddr() - * Network Server Version => m_networkServer->IsVersion1() - * JoinNonce => m_joinNonce - * RX1DROffset => m_rx1DROffset - * RX2DataRate => m_secondReceiveWindowDataRate - * DevNonce => m_devNonce - * NwkKey => m_nwkKey - * JoinEUI => m_joinEUI - * FCntUp => m_currentFCnt - * TxDR => m_dataRate - * TxCh => m_txChIndex (check (m_txCh == 0)) - * ConfFCnt => 0x0000 - */ - if (IsVersion1()) { /* temp <= 0x01 | JoinNonce(3) | NetID(1) | DevNonce(2) | 0x000000000000000000 */ @@ -1066,7 +1049,7 @@ EndDeviceLorawanMac::SetNwkKey(uint8_t nwkKey[16]) } void -EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) +EndDeviceLorawanMac::GetNwkKey(uint8_t nwkKey[16]) const { unsigned int i; @@ -1092,7 +1075,7 @@ EndDeviceLorawanMac::SetJoinEUI(uint8_t joinEUI[8]) } void -EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) +EndDeviceLorawanMac::GetJoinEUI(uint8_t joinEUI[8]) const { unsigned int i; @@ -1117,7 +1100,7 @@ EndDeviceLorawanMac::SetJoinNonce(uint32_t joinNonce) } uint32_t -EndDeviceLorawanMac::GetJoinNonce(void) +EndDeviceLorawanMac::GetJoinNonce(void) const { return m_joinNonce; } @@ -1134,7 +1117,7 @@ EndDeviceLorawanMac::SetDevNonce(uint16_t devNonce) } uint16_t -EndDeviceLorawanMac::GetDevNonce(void) +EndDeviceLorawanMac::GetDevNonce(void) const { return m_devNonce; } diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index 55b12ab31a..435fb7a502 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -336,22 +336,75 @@ class EndDeviceLorawanMac : public LorawanMac * packet. */ void AddMacCommand (Ptr macCommand); - - //void SetNwkServer(Ptr nwkServer); + /** + * Sets the JoinNonce value stored on this end device + * + * \param joinNonce the new JoinNonce value being set + */ void SetJoinNonce(uint32_t joinNonce); - uint32_t GetJoinNonce(void); + /** + * Gets the JoinNonce value stored on this end device + * + * \return the currently stored JoinNonce value + */ + uint32_t GetJoinNonce(void) const; + + /** + * Sets the DevNonce value stored in this end device + * + * \param devNonce the new DevNonce value being set + */ void SetDevNonce(uint16_t devNonce); - uint16_t GetDevNonce(void); + + /** + * Gets the DevNonce value stored in this device + * + * \return the currently stored devNonce value + */ + uint16_t GetDevNonce(void) const; + /** + * Sets the NwkKey stored on this end device + * + * \param nwkKey the new 128-bit network key + */ void SetNwkKey(uint8_t nwkKey[16]); - void GetNwkKey(uint8_t nwkKey[16]); + /** + * Gets the NwkKey stored on this device + * + * \param nwkKey container to copy the currently stored NwkKey in this device to + */ + void GetNwkKey(uint8_t nwkKey[16]) const; + + /** + * Sets the JoinEUI stored on this end device + * + * \param joinEUI the new JoinEUI to be used by this device + */ void SetJoinEUI(uint8_t joinEUI[8]); - void GetJoinEUI(uint8_t joinEUI[8]); + /** + * Gets the JoinEUI stored in this end device + * + * \param joinEUI container to JOinEUI stored on this device to + */ + void GetJoinEUI(uint8_t joinEUI[8]) const; + + /** + * Whether the version the LoRaWAN network this device is apart of is v1.0 or not + * + * \return true if v1.0, false if not + */ bool IsVersion1(void) const; + + /** + * Set whether the LoRaWAN version of the network is v1.0 or not + * + * \param isVersion1 whether the version of the network is v1.0 or not + */ void SetIsVersion1(bool isVersion1); protected: @@ -443,16 +496,6 @@ class EndDeviceLorawanMac : public LorawanMac */ Ptr m_uniformRV; - /** - * The RX1DROffset parameter value - */ - uint8_t m_rx1DrOffset; - - /** - * The Data Rate to listen for during the second downlink transmission. - */ - uint8_t m_secondReceiveWindowDataRate; - Ptr m_txCh; uint8_t m_txChIndex; diff --git a/model/lorawan-mic-trailer.h b/model/lorawan-mic-trailer.h index bf11a2f01e..a1fc060766 100644 --- a/model/lorawan-mic-trailer.h +++ b/model/lorawan-mic-trailer.h @@ -6,28 +6,13 @@ namespace ns3 { namespace lorawan { +/** + * Class used to hold and manage the Message Integrity Code (MIC) trailer + * of a LoRaWAN packet + */ + class LorawanMICTrailer : public Trailer { -private: - uint32_t m_mic; /* the 4 byte mic */ - - /* AES-CMAC funcs (taken from RFC4493) */ - uint32_t aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t *Bx_msg, uint8_t msgLen); /* returns first 4 byte of cmac AKA the MIC */ - void aes128_cmac_generate_subkeys (uint8_t K[16], uint8_t K0[16], uint8_t K1[16]); - void leftshift_1bit (uint8_t in[16], uint8_t out[16]); - void xor_128 (uint8_t in1[16], uint8_t in2[16], uint8_t out[16]); - void padding_128 (uint8_t *in, uint8_t out[16], unsigned int length); - - /* AES-128 funcs taken from NIST publication */ - void aes128_subbytes (uint8_t state[4][4], const uint8_t sbox[16][16]); - void aes128_shiftrows (uint8_t state[4][4]); - void aes128_mixcolumns (uint8_t state[4][4]); - void aes128_addroundkeys (uint8_t state[4][4], uint8_t w[44][4], unsigned int round); - void aes128_keyexpansion(uint8_t K[16], uint8_t w[44][4], const uint8_t sbox[16][16]); - uint8_t gfmul (uint8_t x, uint8_t y); /* GF(2^8) multiplication */ - void rotword (uint8_t word[4]); - void subword (uint8_t word[4], const uint8_t sbox[16][16]); - public: LorawanMICTrailer (); @@ -41,19 +26,156 @@ class LorawanMICTrailer : public Trailer virtual uint32_t Deserialize (Buffer::Iterator end); virtual void Print (std::ostream &os) const; + /** + * Performs AES-128 to encrypt data + * + * \param K the 128-bit key to be used for encryption + * \param M the 128-bit message to be encrypted + * \param O the 128-bit container passed to hold the encrypted output + */ void aes128 (uint8_t K[16], uint8_t M[16], uint8_t O[16]); + /** + * Gets the currently stored MIC + * + * \return the 4-byte MIC currently stored in the trailer + */ uint32_t GetMIC (void) const; + + /** + * Sets the MIC being used in the trailer + * + * \param newMIC the new MIC value to be used by the trailer + */ void SetMIC (uint32_t newMIC); - uint32_t CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); /* Bx and xNwkSIntKey need to be 16 bytes (128 bits) each, uint128_t is not guranteed to be supported */ - uint32_t CalcMIC_1_1_UL(uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); /* special case for UL for 1.1 LoRaWAN network servers */ + + /** + * Calculates a MIC for DL and v1.0 LoRaWAN network UL packets + * + * \param msgLen the length (in bytes) of the "msg" parameter + * \param msg the message being sent in the packet for which the MIC is to be attached to + * \param B0 the B0 (128-bit) MIC computation block (See Figures 18 (DL) and 19 (UL) + * in LoRaWAN specification) + * \param xNwkSIntKey either the SNwkSIntKey (DL) or FNwkSIntKey (UL) 128-bit keys + * generated for this device + */ + uint32_t CalcMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); + + /** + * Calculates a MIC for v1.1 LoRaWAN networks UL packets + * + * \param msgLen the length in bytes of the "msg" parameter + * \param msg the message being sent in the packet for which the MIC is to be attached to + * \param B0 the UL B0 (128-bit) MIC computation block (See Figure 19 in LoRaWAN specification) + * \param B1 the UL B1 (128-bit) MIC computation block (See Figure 20 in LoRaWAN specification) + * \param SNwkSIntKey Serving Network session integrity 128-bit key + * \param FNwkSIntKey Forwarding Network session integrity 128-bit key + * + * \return the 4-byte MIC used for the packet trailer + */ + uint32_t CalcMIC_1_1_UL(uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], + uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); + + /** + * Used to verify the MIC currently stored in the trailer against that of a newly calculated one + * based on the parameters provided (for DL and v1.0 UL) + * + * \param msgLen the length (in bytes) of the "msg" parameter + * \param msg the message being sent in the packet for which the MIC is to be attached to + * \param B0 the B0 (128-bit) MIC computation block (See Figures 18 (DL) and 19 (UL) + * in LoRaWAN specification) + * \param xNwkSIntKey either the SNwkSIntKey (DL) or FNwkSIntKey (UL) 128-bit keys + * generated for this device + * + * \return whether the MIC calculated matches the one stored in the trailer or not + */ bool VerifyMIC (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t xNwkSIntKey[16]); - bool VerifyMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); - /* for making B0 and B1 */ + /** + * Used to verify the MIC currently stored in the trailer against that of a newly calculated one + * based on the parameters provided (for v1.1 UL) + * + * \param msgLen the length in bytes of the "msg" parameter + * \param msg the message being sent in the packet for which the MIC is to be attached to + * \param B0 the UL B0 (128-bit) MIC computation block (See Figure 19 in LoRaWAN specification) + * \param B1 the UL B1 (128-bit) MIC computation block (See Figure 20 in LoRaWAN specification) + * \param SNwkSIntKey Serving Network session integrity 128-bit key + * \param FNwkSIntKey Forwarding Network session integrity 128-bit key + * + * \return whether the MIC calculated matches the one stored in the trailer or not + */ + bool VerifyMIC_1_1_UL (uint8_t msgLen, uint8_t *msg, uint8_t B0[16], uint8_t B1[16], + uint8_t SNwkSIntKey[16], uint8_t FNwkSIntKey[16]); + + /** + * Generates the DL B0 computation block (See Figure 18 in LoRaWAN specification) needed for + * MIC calaculation + * + * \param B0 the container for storing the 128-bit B0 block once calculated + * \param ConfFCnt If the device is connected to a LoRaWAN1.1 Network Server and the + * ACK bit of the downlink frame is set, meaning this frame is + * acknowledging an uplink “confirmed” frame, then ConfFCnt is the frame + * counter value modulo 2^16 of the “confirmed” uplink frame that is + * being acknowledged. In all other cases ConfFCnt = 0x0000 + * \param DevAddr the end-device address + * \param xFCntDwn either AFCntDown or NFCntDown + * \param msgLen the length of the message being sent in the packet for which the + * MIC is to be attached to + */ void GenerateB0DL (uint8_t B0[16], uint16_t ConfFCnt, uint32_t DevAddr, uint32_t xFCntDwn, uint8_t msgLen); + + /** + * Generates the UL B0 computation block (See Figure 19 in LoRaWAN specification) needed for + * MIC calaculation + * + * \param B0 the container for storing the 128-bit B0 block once calculated + * \param DevAddr the end-device address + * \param FCntUp current UL frame counter value + * \param msgLen the length of the message being sent in the packet for which the + * MIC is to be attached to + */ void GenerateB0UL (uint8_t B0[16], uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); - void GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); /* LoRaWAN 1.1 Network servers use B1 and B0 */ + + /** + * Generates the UL B1 computation block (See Figure 20 in LoRaWAN specification) needed for + * MIC calaculation + * + * \param B1 the container for storing the 128-bit B1 block once calculated + * \param ConfFCnt If the ACK bit of the uplink frame is set, meaning this frame is + * acknowledging a downlink “confirmed” frame, then ConfFCnt is + * the frame counter value modulo 2^16 of the “confirmed” downlink + * frame that is being acknowledged. In all other cases ConfFCnt = 0x0000 + * \param TxDr the data rate that will be used for the UL transmission + * \param TxCh the index of the channel being used + * \param DevAddr the end-device address + * \param FCntUp current UL frame coutner value + * \param msgLen the length of the message being sent in the packet for which the + * MIC is to be attached to + * + */ + void GenerateB1UL (uint8_t B1[16], uint16_t ConfFCnt, uint8_t TxDr, uint8_t TxCh, + uint32_t DevAddr, uint32_t FCntUp, uint8_t msgLen); + +private: + uint32_t m_mic; /* the 4 byte mic */ + + /* AES-CMAC funcs (taken from RFC4493) */ + uint32_t aes128_cmac_4 (uint8_t xNwkSIntKey[16], uint8_t *Bx_msg, uint8_t msgLen); /* returns first 4 byte of cmac AKA the MIC */ + void aes128_cmac_generate_subkeys (uint8_t K[16], uint8_t K0[16], uint8_t K1[16]); + void leftshift_1bit (uint8_t in[16], uint8_t out[16]); + void xor_128 (uint8_t in1[16], uint8_t in2[16], uint8_t out[16]); + void padding_128 (uint8_t *in, uint8_t out[16], unsigned int length); + + /* AES-128 funcs taken from NIST publication */ + void aes128_subbytes (uint8_t state[4][4], const uint8_t sbox[16][16]); + void aes128_shiftrows (uint8_t state[4][4]); + void aes128_mixcolumns (uint8_t state[4][4]); + void aes128_addroundkeys (uint8_t state[4][4], uint8_t w[44][4], unsigned int round); + void aes128_keyexpansion(uint8_t K[16], uint8_t w[44][4], const uint8_t sbox[16][16]); + uint8_t gfmul (uint8_t x, uint8_t y); /* GF(2^8) multiplication */ + void rotword (uint8_t word[4]); + void subword (uint8_t word[4], const uint8_t sbox[16][16]); + }; }