-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomms.c
210 lines (164 loc) · 5.31 KB
/
comms.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#define __packed
#include "proto.h"
#include "asmUtil.h"
#include "printf.h"
#include "radio.h"
#include "comms.h"
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
static uint8_t __xdata mCommsBuf[127];
static uint8_t __xdata mSeq = 0;
static uint8_t __xdata mLastLqi = 0;
static int8_t __xdata mLastRSSI = 0;
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
};
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
};
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
};
uint8_t commsGetLastPacketLQI(void)
{
return mLastLqi;
}
int8_t commsGetLastPacketRSSI(void)
{
return mLastRSSI;
}
bool commsTx(struct CommsInfo __xdata *info, bool bcast, const void __xdata *packetP, uint8_t len, uint16_t panId)
{
const uint8_t __xdata *packet = (const uint8_t __xdata*)packetP;
struct AesCcmInfo __xdata ccmNfo = {0, };
volatile uint8_t __xdata hdrSz, ofst;
if (len > COMMS_MAX_PACKET_SZ)
return false;
if (bcast) {
struct MacFrameBcast __xdata *mfb;
mfb = (struct MacFrameBcast __xdata*)(mCommsBuf + 1);
xMemSet(mfb, 0, sizeof(*mfb));
hdrSz = sizeof(struct MacFrameBcast);
mfb->fcs.frameType = FRAME_TYPE_DATA;
mfb->fcs.destAddrType = ADDR_MODE_SHORT;
mfb->fcs.srcAddrType = ADDR_MODE_LONG;
mfb->seq = mSeq++;
mfb->dstPan = 0xffff;
mfb->dstAddr = 0xffff;
mfb->srcPan = panId;
xMemCopy8(mfb->src, info->myMac);
}
else {
struct MacFrameNormal __xdata *mfn;
mfn = (struct MacFrameNormal __xdata*)(mCommsBuf + 1);
xMemSet(mfn, 0, sizeof(*mfn));
hdrSz = sizeof(struct MacFrameNormal);
mfn->fcs.frameType = FRAME_TYPE_DATA;
mfn->fcs.panIdCompressed = 1;
mfn->fcs.destAddrType = ADDR_MODE_LONG;
mfn->fcs.srcAddrType = ADDR_MODE_LONG;
mfn->seq = mSeq++;
mfn->pan = panId;
xMemCopy8(mfn->dst, info->masterMac);
xMemCopy8(mfn->src, info->myMac);
}
ofst = hdrSz + 1;
mathPrvCopyPostinc((uint32_t __xdata*)ccmNfo.nonce, info->nextIV);
xMemCopy8(ccmNfo.nonce + sizeof(uint32_t), info->myMac);
xMemCopyShort(mCommsBuf + ofst, packet, len);
ofst += len;
ccmNfo.authSrcLen = hdrSz;
ccmNfo.encDataLen = len;
ccmNfo.key = info->encrKey;
aesCcmEnc(mCommsBuf + 1, mCommsBuf + 1, &ccmNfo);
xMemCopyShort(mCommsBuf + ofst + AES_CCM_MIC_SIZE, ccmNfo.nonce, 4); //send nonce
len += hdrSz;
len += AES_CCM_MIC_SIZE;
len += sizeof(uint32_t); //nonce
mCommsBuf[0] = len + RADIO_PAD_LEN_BY;
radioTx(mCommsBuf);
return true;
}
int8_t commsRx(struct CommsInfo __xdata *info, void __xdata *data, uint8_t __xdata *fromMacP, uint16_t panId)
{
uint8_t __xdata *dstData = (uint8_t __xdata *)data;
int8_t ret = COMMS_RX_ERR_INVALID_PACKET;
struct AesCcmInfo __xdata ccmNfo = {0, };
struct MacFrameFromMaster __xdata *mfm;
uint8_t len, minNeedLen, hdrLen = 0;
struct MacFrameNormal __xdata *mfn;
uint8_t __xdata *buf = mCommsBuf;
uint8_t __xdata fromMac[8];
uint8_t __xdata * __xdata rxedBuf;
int8_t rxedLen;
rxedLen = radioRxDequeuePktGet((void __xdata * __xdata)&rxedBuf, &mLastLqi, &mLastRSSI);
if (rxedLen < 0)
return COMMS_RX_ERR_NO_PACKETS;
len = rxedLen;
//sort out how many bytes minimum are a valid packet
minNeedLen = sizeof(struct MacFrameFromMaster); //mac header
minNeedLen += sizeof(uint8_t); //packet type
minNeedLen += AES_CCM_MIC_SIZE; //MIC
minNeedLen += sizeof(uint32_t); //nonce counter
minNeedLen += 2 * sizeof(uint8_t); //RSSI/LQI
//some basic checks
mfm = (struct MacFrameFromMaster __xdata*)rxedBuf;
if (len >= sizeof(mCommsBuf) || len < minNeedLen || mfm->fcs.frameType != FRAME_TYPE_DATA ||
mfm->fcs.secure || mfm->fcs.frameVer || mfm->fcs.destAddrType != ADDR_MODE_LONG || !mfm->fcs.panIdCompressed ||
(mfm->fcs.srcAddrType != ADDR_MODE_LONG && mfm->fcs.srcAddrType != ADDR_MODE_SHORT) ||
mfm->pan != panId || !xMemEqual(mfm->dst, info->myMac, 8)) {
radioRxDequeuedPktRelease();
return COMMS_RX_ERR_INVALID_PACKET;
}
//copy out and release buffer
xMemCopyShort(buf, rxedBuf, len);
radioRxDequeuedPktRelease();
mfm = (struct MacFrameFromMaster __xdata*)buf;
mfn = (struct MacFrameNormal __xdata*)buf;
//sort out header len, copy mac into nonce
if (mfm->fcs.srcAddrType == ADDR_MODE_LONG) {
xMemCopy8(fromMac, mfn->src);
hdrLen = sizeof(struct MacFrameNormal);
//re-verify needed length
minNeedLen -= sizeof(struct MacFrameFromMaster);
minNeedLen += sizeof(struct MacFrameNormal);
if (len < minNeedLen)
return COMMS_RX_ERR_INVALID_PACKET;
}
else if (mfm->fcs.srcAddrType == ADDR_MODE_SHORT) {
xMemCopy8(fromMac, info->masterMac);
hdrLen = sizeof(struct MacFrameFromMaster);
}
//sort out the nonce
xMemCopy8(ccmNfo.nonce + sizeof(uint32_t), fromMac);
xMemCopyShort(ccmNfo.nonce, buf + len - sizeof(uint32_t), 4);
//decrypt and auth
len -= hdrLen + AES_CCM_MIC_SIZE + sizeof(uint32_t);
ccmNfo.authSrcLen = hdrLen;
ccmNfo.encDataLen = len;
ccmNfo.key = info->encrKey;
if (!aesCcmDec(buf, buf, &ccmNfo))
return COMMS_RX_ERR_MIC_FAIL;
if (fromMacP)
xMemCopy8(fromMacP, fromMac);
xMemCopyShort(dstData, buf + hdrLen, len);
return len;
}