-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlorawan_aes_cmac.c
179 lines (156 loc) · 4.81 KB
/
lorawan_aes_cmac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/********************************************************************
* Copyright (C) 2016 Microchip Technology Inc. and its subsidiaries
* (Microchip). All rights reserved.
*
* You are permitted to use the software and its derivatives with Microchip
* products. See the license agreement accompanying this software, if any, for
* more info about your rights and obligations.
*
* SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
* MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR
* PURPOSE. IN NO EVENT SHALL MICROCHIP, SMSC, OR ITS LICENSORS BE LIABLE OR
* OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH
* OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY FOR ANY DIRECT OR INDIRECT
* DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES, OR OTHER SIMILAR COSTS. To the fullest
* extend allowed by law, Microchip and its licensors liability will not exceed
* the amount of fees, if any, that you paid directly to Microchip to use this
* software.
*************************************************************************
*
* lorawan_aes_cmac.c
*
* LoRaWAN AES - CMAC file
*
******************************************************************************/
/****************************** INCLUDES **************************************/
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "lorawan_aes.h"
#include "lorawan_defs.h"
/************************ PRIVATE FUNCTION PROTOTYPES *************************/
static void GenerateSubkey (uint8_t* key, uint8_t* k1, uint8_t* k2);
static void FillSubKey( uint8_t *source, uint8_t *key, uint8_t size);
/****************************** PUBLIC FUNCTIONS ******************************/
void AESCmac(uint8_t* key, uint8_t* output, uint8_t* input, uint8_t size)
{
uint8_t n = 0, i = 0, j =0;
bool flag = false;
uint8_t k1[16], k2[16];
uint8_t x[16], y[16], mLast[16], padded[16];
uint8_t *ptr = NULL;
GenerateSubkey(key, k1, k2);
n = (size + 15) >> SHIFT4;
if (n == 0)
{
n = 1;
flag = 0;
}
else
{
flag = !(size % 16);
}
if ( flag == 1 )
{
j = 0;
for (i=((n-1) << SHIFT4); i<(n << SHIFT4); i++)
{
mLast[j] = input[i] ^ k1[j];
j++;
}
}
else
{
// padding
ptr = &input[size - (size%16)];
for (i=0; i<16; i++)
{
if ( i < (size%16) )
{
padded[i] = ptr[i];
}
else
{
if ( i == (size%16) )
{
padded[i] = 0x80;
}
else
{
padded[i] = 0x00;
}
}
}
// XOR
for (i=0; i<sizeof(mLast); i++)
{
mLast[i] = padded[i] ^ k2[i];
}
}
memset(x, 0, sizeof(x));
for (i=0; i<(n-1); i++)
{
for (j=0; j<16; j++)
{
y[j] = x[j] ^ input[(i << SHIFT4)+j];
}
memcpy(x, y, sizeof(y));
AESEncodeLoRa(x,key);
}
for (i=0; i<sizeof(x); i++)
{
y[i] = x[i] ^ mLast[i];
}
AESEncodeLoRa(y, key);
memcpy(output, y, sizeof(y));
}
/****************************** PRIVATE FUNCTIONS *****************************/
static void GenerateSubkey (uint8_t* key, uint8_t* k1, uint8_t* k2)
{
uint8_t i = 0;
uint8_t l[16];
uint8_t const_Rb[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
memset(l, 0, sizeof(l));
AESEncodeLoRa(l, key);
// compute k1 sub-key
if ( (l[0] & 0x80) == 0x00 ) // MSB( bufferLocal[0] ) is '0'
{
FillSubKey( l, k1, (sizeof(l) ) );
}
else
{
FillSubKey( l, k1, (sizeof(l) ) );
for (i=0; i<sizeof(l); i++)
{
k1[i] ^= const_Rb[i];
}
}
// compute k2 sub-key
if ( (k1[0] & 0x80) == 0x00 ) // MSB( k1[0] ) is '0'
{
FillSubKey( k1, k2, (sizeof(l)) );
}
else
{
FillSubKey( k1, k2, (sizeof(l) ) );
for (i=0; i<sizeof(l); i++)
{
k2[i] = k2[i] ^ const_Rb[i];
}
}
}
static void FillSubKey( uint8_t *source, uint8_t *key, uint8_t size)
{
uint8_t i = 0;
uint8_t carry = 0;
i=size;
while(i--)
{
key[i] = (source[i] << SHIFT1) | carry;
carry = !!(source[i] & 0x80);
}
}