AllWize Library
AllWize_LoRaWAN.cpp
Go to the documentation of this file.
1 /*
2 
3 AllWize LoRaWAN Library
4 
5 This code is based on Adafruit's TinyLora Library and thus
6 
7 Copyright (C) 2015, 2016 Ideetron B.V.
8 Modified by Brent Rubell for Adafruit Industries.
9 Copyright (C) 2018-2019 by AllWize <github@allwize.io>
10 
11 This program is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU Lesser General Public License for more details.
20 
21 You should have received a copy of the GNU Lesser General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 
24 */
25 
31 #include "AllWize_LoRaWAN.h"
32 
40 bool AllWize_LoRaWAN::joinABP(uint8_t *DevAddr, uint8_t *AppSKey, uint8_t * NwkSKey) {
41  memcpy(_devaddr, DevAddr, 4);
42  memcpy(_appskey, AppSKey, 16);
43  memcpy(_nwkskey, NwkSKey, 16);
44  return true;
45 }
46 
54 bool AllWize_LoRaWAN::send(uint8_t *Data, uint8_t Data_Length, uint8_t Frame_Port) {
55 
56  // Define variables
57  uint8_t i;
58  uint8_t LoRaWAN_Data[64] = {0};
59  uint8_t LoRaWAN_Data_Length = 0;
60  uint8_t MIC[4] = {0};
61 
62  // Direction of frame is up
63  uint8_t Direction = 0x00;
64 
65  // Unconfirmed data up
66  // [7..5] MType (010 unconfirmed up, 100 confirmed up,...)
67  // [4..2] RFU
68  // [1..0] Major
69  uint8_t Mac_Header = 0x40;
70 
71  // Frame control
72  // [7] ADR
73  // [6] ADRACKReq
74  // [5] ACK
75  // [4] ClassB
76  // [3..0] FOptsLen
77  uint8_t Frame_Control = 0x00;
78 
79  // Make a copy of Data
80  uint8_t tmpData[Data_Length];
81  for (int i = 0; i < Data_Length; i++) {
82  tmpData[i] = Data[i];
83  }
84 
85  // Encrypt Data (data argument is overwritten in this function)
86  Encrypt_Payload(tmpData, Data_Length, _frame_counter, Direction);
87 
88  // MAC Header
89  LoRaWAN_Data[0] = Mac_Header;
90 
91  // MAC Payload - Frame Header
92  LoRaWAN_Data[1] = _devaddr[3];
93  LoRaWAN_Data[2] = _devaddr[2];
94  LoRaWAN_Data[3] = _devaddr[1];
95  LoRaWAN_Data[4] = _devaddr[0];
96  LoRaWAN_Data[5] = Frame_Control;
97  LoRaWAN_Data[6] = (_frame_counter & 0x00FF);
98  LoRaWAN_Data[7] = ((_frame_counter >> 8) & 0x00FF);
99 
100  // MAC Payload - Frame Port
101  LoRaWAN_Data[8] = Frame_Port;
102 
103  //Set Current package length
104  LoRaWAN_Data_Length = 9;
105 
106  // MAC Payload - Frame Payload
107  for(i = 0; i < Data_Length; i++) {
108  LoRaWAN_Data[LoRaWAN_Data_Length + i] = tmpData[i];
109  }
110  LoRaWAN_Data_Length += Data_Length;
111 
112  // Calculate MIC
113  Calculate_MIC(LoRaWAN_Data, MIC, LoRaWAN_Data_Length, _frame_counter, Direction);
114 
115  // Load MIC in package
116  for(i = 0; i < 4; i++) {
117  LoRaWAN_Data[i + LoRaWAN_Data_Length] = MIC[i];
118  }
119  LoRaWAN_Data_Length += 4;
120 
121  // Update frame counter
122  ++_frame_counter;
123 
124  // Send Package
125  return AllWize::send(LoRaWAN_Data, LoRaWAN_Data_Length);
126 
127 }
128 
134  return _frame_counter;
135 }
136 
141 void AllWize_LoRaWAN::setFrameCounter(uint16_t value) {
142  _frame_counter = value;
143 }
144 
145 // ----------------------------------------------------------------------------
146 
155 void AllWize_LoRaWAN::Encrypt_Payload(uint8_t *Data, uint8_t Data_Length, uint16_t Frame_Counter, uint8_t Direction) {
156 
157  uint8_t i = 0x00;
158  uint8_t j;
159  uint8_t Number_of_Blocks = 0x00;
160  uint8_t Incomplete_Block_Size = 0x00;
161 
162  uint8_t Block_A[16];
163 
164  //Calculate number of blocks
165  Number_of_Blocks = Data_Length / 16;
166  Incomplete_Block_Size = Data_Length % 16;
167  if (Incomplete_Block_Size != 0) {
168  Number_of_Blocks++;
169  }
170 
171  for (i = 1; i <= Number_of_Blocks; i++) {
172  Block_A[0] = 0x01;
173  Block_A[1] = 0x00;
174  Block_A[2] = 0x00;
175  Block_A[3] = 0x00;
176  Block_A[4] = 0x00;
177 
178  Block_A[5] = Direction;
179 
180  Block_A[6] = _devaddr[3];
181  Block_A[7] = _devaddr[2];
182  Block_A[8] = _devaddr[1];
183  Block_A[9] = _devaddr[0];
184 
185  Block_A[10] = (Frame_Counter & 0x00FF);
186  Block_A[11] = ((Frame_Counter >> 8) & 0x00FF);
187 
188  Block_A[12] = 0x00; //Frame counter upper Bytes
189  Block_A[13] = 0x00;
190 
191  Block_A[14] = 0x00;
192 
193  Block_A[15] = i;
194 
195  //Calculate S
196  AES_Encrypt(Block_A, _appskey); //original
197 
198  //Check for last block
199  if (i != Number_of_Blocks) {
200  for (j = 0; j < 16; j++) {
201  *Data = *Data ^ Block_A[j];
202  Data++;
203  }
204  } else {
205  if (Incomplete_Block_Size == 0) {
206  Incomplete_Block_Size = 16;
207  }
208  for (j = 0; j < Incomplete_Block_Size; j++) {
209  *Data = *Data ^ Block_A[j];
210  Data++;
211  }
212  }
213  }
214 }
215 
225 void AllWize_LoRaWAN::Calculate_MIC(uint8_t *Data, uint8_t *Final_MIC, uint8_t Data_Length, uint16_t Frame_Counter, uint8_t Direction) {
226 
227  uint8_t i;
228  uint8_t Block_B[16];
229 
230  uint8_t Key_K1[16] = {
231  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
233  uint8_t Key_K2[16] = {
234  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
236 
237  //uint8_t Data_Copy[16];
238 
239  uint8_t Old_Data[16] = {
240  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
242  uint8_t New_Data[16] = {
243  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
245 
246  uint8_t Number_of_Blocks = 0x00;
247  uint8_t Incomplete_Block_Size = 0x00;
248  uint8_t Block_Counter = 0x01;
249 
250  //Create Block_B
251  Block_B[0] = 0x49;
252  Block_B[1] = 0x00;
253  Block_B[2] = 0x00;
254  Block_B[3] = 0x00;
255  Block_B[4] = 0x00;
256 
257  Block_B[5] = Direction;
258 
259  Block_B[6] = _devaddr[3];
260  Block_B[7] = _devaddr[2];
261  Block_B[8] = _devaddr[1];
262  Block_B[9] = _devaddr[0];
263 
264  Block_B[10] = (Frame_Counter & 0x00FF);
265  Block_B[11] = ((Frame_Counter >> 8) & 0x00FF);
266 
267  Block_B[12] = 0x00; //Frame counter upper bytes
268  Block_B[13] = 0x00;
269 
270  Block_B[14] = 0x00;
271  Block_B[15] = Data_Length;
272 
273  //Calculate number of Blocks and blocksize of last block
274  Number_of_Blocks = Data_Length / 16;
275  Incomplete_Block_Size = Data_Length % 16;
276 
277  if (Incomplete_Block_Size != 0) {
278  Number_of_Blocks++;
279  }
280 
281  Generate_Keys(Key_K1, Key_K2);
282 
283  //Preform Calculation on Block B0
284 
285  //Preform AES encryption
286  AES_Encrypt(Block_B, _nwkskey);
287 
288  //Copy Block_B to Old_Data
289  for (i = 0; i < 16; i++) {
290  Old_Data[i] = Block_B[i];
291  }
292 
293  //Preform full calculating until n-1 messsage blocks
294  while (Block_Counter < Number_of_Blocks) {
295 
296  //Copy data into array
297  for (i = 0; i < 16; i++) {
298  New_Data[i] = *Data;
299  Data++;
300  }
301 
302  //Preform XOR with old data
303  XOR(New_Data, Old_Data);
304 
305  //Preform AES encryption
306  AES_Encrypt(New_Data, _nwkskey);
307 
308  //Copy New_Data to Old_Data
309  for (i = 0; i < 16; i++) {
310  Old_Data[i] = New_Data[i];
311  }
312 
313  //Raise Block counter
314  Block_Counter++;
315 
316  }
317 
318  //Perform calculation on last block
319  //Check if Datalength is a multiple of 16
320  if (Incomplete_Block_Size == 0) {
321 
322  //Copy last data into array
323  for (i = 0; i < 16; i++) {
324  New_Data[i] = *Data;
325  Data++;
326  }
327 
328  //Preform XOR with Key 1
329  XOR(New_Data, Key_K1);
330 
331  //Preform XOR with old data
332  XOR(New_Data, Old_Data);
333 
334  //Preform last AES routine
335  // read _nwkskey from PROGMEM
336  AES_Encrypt(New_Data, _nwkskey);
337 
338  } else {
339 
340  //Copy the remaining data and fill the rest
341  for (i = 0; i < 16; i++) {
342  if (i < Incomplete_Block_Size) {
343  New_Data[i] = *Data;
344  Data++;
345  }
346  if (i == Incomplete_Block_Size) {
347  New_Data[i] = 0x80;
348  }
349  if (i > Incomplete_Block_Size) {
350  New_Data[i] = 0x00;
351  }
352  }
353 
354  //Preform XOR with Key 2
355  XOR(New_Data, Key_K2);
356 
357  //Preform XOR with Old data
358  XOR(New_Data, Old_Data);
359 
360  //Preform last AES routine
361  AES_Encrypt(New_Data, _nwkskey);
362 
363  }
364 
365  Final_MIC[0] = New_Data[0];
366  Final_MIC[1] = New_Data[1];
367  Final_MIC[2] = New_Data[2];
368  Final_MIC[3] = New_Data[3];
369 
370 }
371 
378 void AllWize_LoRaWAN::Generate_Keys(uint8_t *K1, uint8_t *K2) {
379 
380  uint8_t i;
381  uint8_t MSB_Key;
382 
383  //Encrypt the zeros in K1 with the _nwkskey
384  AES_Encrypt(K1, _nwkskey);
385 
386  //Create K1
387  //Check if MSB is 1
388  if ((K1[0] & 0x80) == 0x80) {
389  MSB_Key = 1;
390  } else {
391  MSB_Key = 0;
392  }
393 
394  //Shift K1 one bit left
395  Shift_Left(K1);
396 
397  //if MSB was 1
398  if (MSB_Key == 1) {
399  K1[15] = K1[15] ^ 0x87;
400  }
401 
402  //Copy K1 to K2
403  for (i = 0; i < 16; i++) {
404  K2[i] = K1[i];
405  }
406 
407  //Check if MSB is 1
408  if ((K2[0] & 0x80) == 0x80) {
409  MSB_Key = 1;
410  } else {
411  MSB_Key = 0;
412  }
413 
414  //Shift K2 one bit left
415  Shift_Left(K2);
416 
417  //Check if MSB was 1
418  if (MSB_Key == 1) {
419  K2[15] = K2[15] ^ 0x87;
420  }
421 
422 }
423 
429 void AllWize_LoRaWAN::Shift_Left(uint8_t *Data) {
430 
431  uint8_t i;
432  uint8_t Overflow = 0;
433  //uint8_t High_Byte, Low_Byte;
434 
435  for (i = 0; i < 16; i++) {
436 
437  //Check for overflow on next byte except for the last byte
438  if (i < 15) {
439  //Check if upper bit is one
440  if ((Data[i + 1] & 0x80) == 0x80) {
441  Overflow = 1;
442  } else {
443  Overflow = 0;
444  }
445  } else {
446  Overflow = 0;
447  }
448 
449  //Shift one left
450  Data[i] = (Data[i] << 1) + Overflow;
451 
452  }
453 
454 }
455 
462 void AllWize_LoRaWAN::XOR(uint8_t *New_Data, uint8_t *Old_Data) {
463 
464  uint8_t i;
465  for (i = 0; i < 16; i++) {
466  New_Data[i] = New_Data[i] ^ Old_Data[i];
467  }
468 
469 }
470 
471 //-----------------------------------------------------------------------------
472 // AES Encryption methods
473 //-----------------------------------------------------------------------------
474 
475 /*
476  * Description: S_Table used for AES encription
477  */
478 const uint8_t PROGMEM AllWize_LoRaWAN::S_Table[16][16] = {
479  {0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76},
480  {0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0},
481  {0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15},
482  {0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75},
483  {0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84},
484  {0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF},
485  {0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8},
486  {0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2},
487  {0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73},
488  {0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB},
489  {0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79},
490  {0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08},
491  {0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A},
492  {0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E},
493  {0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF},
494  {0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16}
495  };
496 
503 void AllWize_LoRaWAN::AES_Encrypt(uint8_t *Data, const uint8_t *Key) {
504 
505  uint8_t Row, Column, Round = 0;
506  uint8_t Round_Key[16];
507  uint8_t State[4][4];
508 
509  // Copy input to State arry
510  for (Column = 0; Column < 4; Column++) {
511  for (Row = 0; Row < 4; Row++) {
512  State[Row][Column] = Data[Row + (Column << 2)];
513  }
514  }
515 
516  // Copy key to round key
517  memcpy(&Round_Key[0], &Key[0], 16);
518 
519  // Add round key
520  AES_Add_Round_Key(Round_Key, State);
521 
522  // Preform 9 full rounds with mixed collums
523  for (Round = 1; Round < 10; Round++) {
524 
525  // Perform Byte substitution with S table
526  for (Column = 0; Column < 4; Column++) {
527  for (Row = 0; Row < 4; Row++) {
528  State[Row][Column] = AES_Sub_Byte(State[Row][Column]);
529  }
530  }
531 
532  // Perform Row Shift
533  AES_Shift_Rows(State);
534 
535  // Mix Collums
536  AES_Mix_Collums(State);
537 
538  // Calculate new round key
539  AES_Calculate_Round_Key(Round, Round_Key);
540 
541  // Add the round key to the Round_key
542  AES_Add_Round_Key(Round_Key, State);
543 
544  }
545 
546  // Perform Byte substitution with S table whitout mix collums
547  for (Column = 0; Column < 4; Column++) {
548  for (Row = 0; Row < 4; Row++) {
549  State[Row][Column] = AES_Sub_Byte(State[Row][Column]);
550  }
551  }
552 
553  // Shift rows
554  AES_Shift_Rows(State);
555 
556  // Calculate new round key
557  AES_Calculate_Round_Key(Round, Round_Key);
558 
559  // Add round key
560  AES_Add_Round_Key(Round_Key, State);
561 
562  // Copy the State into the data array
563  for (Column = 0; Column < 4; Column++) {
564  for (Row = 0; Row < 4; Row++) {
565  Data[Row + (Column << 2)] = State[Row][Column];
566  }
567  }
568 
569 }
570 
577 void AllWize_LoRaWAN::AES_Add_Round_Key(uint8_t *Round_Key, uint8_t (*State)[4]) {
578 
579  uint8_t Row, Collum;
580 
581  for (Collum = 0; Collum < 4; Collum++) {
582  for (Row = 0; Row < 4; Row++) {
583  State[Row][Collum] ^= Round_Key[Row + (Collum << 2)];
584  }
585  }
586 
587 }
588 
595 uint8_t AllWize_LoRaWAN::AES_Sub_Byte(uint8_t Byte) {
596 
597  // uint8_t S_Row,S_Collum;
598  // uint8_t S_Byte;
599  //
600  // S_Row = ((Byte >> 4) & 0x0F);
601  // S_Collum = ((Byte >> 0) & 0x0F);
602  // S_Byte = S_Table [S_Row][S_Collum];
603 
604  //return S_Table [ ((Byte >> 4) & 0x0F) ] [ ((Byte >> 0) & 0x0F) ]; // original
605  return pgm_read_byte(&(S_Table[((Byte >> 4) & 0x0F)][((Byte >> 0) & 0x0F)]));
606 
607 }
608 
614 void AllWize_LoRaWAN::AES_Shift_Rows(uint8_t (*State)[4]) {
615 
616  uint8_t Buffer;
617 
618  //Store firt byte in buffer
619  Buffer = State[1][0];
620  //Shift all bytes
621  State[1][0] = State[1][1];
622  State[1][1] = State[1][2];
623  State[1][2] = State[1][3];
624  State[1][3] = Buffer;
625 
626  Buffer = State[2][0];
627  State[2][0] = State[2][2];
628  State[2][2] = Buffer;
629  Buffer = State[2][1];
630  State[2][1] = State[2][3];
631  State[2][3] = Buffer;
632 
633  Buffer = State[3][3];
634  State[3][3] = State[3][2];
635  State[3][2] = State[3][1];
636  State[3][1] = State[3][0];
637  State[3][0] = Buffer;
638 
639 }
640 
646 void AllWize_LoRaWAN::AES_Mix_Collums(uint8_t (*State)[4]) {
647 
648  uint8_t Row, Collum;
649  uint8_t a[4], b[4];
650 
651  for (Collum = 0; Collum < 4; Collum++) {
652  for (Row = 0; Row < 4; Row++) {
653  a[Row] = State[Row][Collum];
654  b[Row] = (State[Row][Collum] << 1);
655 
656  if ((State[Row][Collum] & 0x80) == 0x80) {
657  b[Row] ^= 0x1B;
658  }
659  }
660 
661  State[0][Collum] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3];
662  State[1][Collum] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3];
663  State[2][Collum] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3];
664  State[3][Collum] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3];
665  }
666 
667 }
668 
675 void AllWize_LoRaWAN::AES_Calculate_Round_Key(uint8_t Round, uint8_t *Round_Key) {
676 
677  uint8_t i, j, b, Rcon;
678  uint8_t Temp[4];
679 
680  //Calculate Rcon
681  Rcon = 0x01;
682  while (Round != 1) {
683  b = Rcon & 0x80;
684  Rcon = Rcon << 1;
685 
686  if (b == 0x80) {
687  Rcon ^= 0x1b;
688  }
689  Round--;
690  }
691 
692  // Calculate first Temp
693  // Copy laste byte from previous key and subsitute the byte, but shift the array contents around by 1.
694  Temp[0] = AES_Sub_Byte(Round_Key[12 + 1]);
695  Temp[1] = AES_Sub_Byte(Round_Key[12 + 2]);
696  Temp[2] = AES_Sub_Byte(Round_Key[12 + 3]);
697  Temp[3] = AES_Sub_Byte(Round_Key[12 + 0]);
698 
699  // XOR with Rcon
700  Temp[0] ^= Rcon;
701 
702  // Calculate new key
703  for (i = 0; i < 4; i++) {
704  for (j = 0; j < 4; j++) {
705  Round_Key[j + (i << 2)] ^= Temp[j];
706  Temp[j] = Round_Key[j + (i << 2)];
707  }
708  }
709 
710 }
bool send(uint8_t *buffer, uint8_t len)
Sends a byte array.
Definition: AllWize.cpp:366
bool send(uint8_t *Data, uint8_t Data_Length, uint8_t Frame_Port=0x01)
Function to assemble and send a LoRaWAN package.
bool joinABP(uint8_t *DevAddr, uint8_t *AppSKey, uint8_t *NwkSKey)
Stores the application and network keys for ABP activation.
uint16_t getFrameCounter()
Returns current frame counter.
void setFrameCounter(uint16_t value)
Sets new frame counter.