-
Notifications
You must be signed in to change notification settings - Fork 112
/
airkiss.c
422 lines (361 loc) · 12.9 KB
/
airkiss.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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#include "airkiss.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define PASSWORD_MAX_LEN 32
#define ESSID_MAX_LEN 32
#define USR_DATA_BUFF_MAX_SIZE (PASSWORD_MAX_LEN + 1 + ESSID_MAX_LEN)
typedef enum
{
AIRKISS_STATE_STOPED = 0,
AIRKISS_STATE_IDLE,
AIRKISS_STATE_SRC_LOCKED,
AIRKISS_STATE_MAGIC_CODE_COMPLETE,
AIRKISS_STATE_PREFIX_CODE_COMPLETE,
AIRKISS_STATE_COMPLETE
} AIR_KISS_STATE;
#define MAX_GUIDE_RECORD 4
typedef struct
{
unsigned short length_record[MAX_GUIDE_RECORD + 1];
}guide_code_record;
#define MAX_MAGIC_CODE_RECORD 4
typedef struct
{
unsigned short record[MAX_MAGIC_CODE_RECORD + 1];
}magic_code_record;
#define MAX_PREFIX_CODE_RECORD 4
typedef struct
{
unsigned short record[MAX_PREFIX_CODE_RECORD + 1];
}prfix_code_record;
#define MAX_SEQ_CODE_RECORD 6
typedef struct
{
unsigned short record[MAX_SEQ_CODE_RECORD + 1];
}seq_code_record;
union airkiss_data{
guide_code_record guide_code;
magic_code_record magic_code;
prfix_code_record prefix_code;
seq_code_record seq_code;
};
typedef struct
{
char* pwd;
char* ssid;
unsigned char pswd_len;
unsigned char ssid_len;
unsigned char random_num;
unsigned char ssid_crc; //reserved used as ssid_crc
//above is airkiss_context_t
unsigned char usr_data[USR_DATA_BUFF_MAX_SIZE];
AIR_KISS_STATE airkiss_state;
unsigned char src_mac[6];
//unsigned char cur_seq;
unsigned char need_seq;
unsigned char base_len;
unsigned char total_len;
unsigned char pswd_lencrc;
unsigned char recv_len;
unsigned short seq_success_map;
unsigned short seq_success_map_cmp;
union airkiss_data data;
}_airkiss_local_context;
const char airkiss_vers[] = "V1.3";
static airkiss_config_t *akconf = 0;
static airkiss_context_t *akcontex = 0;
static _airkiss_local_context _akcontext;
//crc8
unsigned char calcrc_1byte(unsigned char abyte)
{
unsigned char i,crc_1byte;
crc_1byte=0;
for(i = 0; i < 8; i++)
{
if(((crc_1byte^abyte)&0x01))
{
crc_1byte^=0x18;
crc_1byte>>=1;
crc_1byte|=0x80;
}
else
{
crc_1byte>>=1;
}
abyte>>=1;
}
return crc_1byte;
}
unsigned char calcrc_bytes(unsigned char *p,unsigned int num_of_bytes)
{
unsigned char crc=0;
while(num_of_bytes--)
{
crc=calcrc_1byte(crc^*p++);
}
return crc;
}
const char* airkiss_version(void)
{
return airkiss_vers;
}
/* return 1 is valid
* return 0 is invalid
* */
int airkiss_filter(const unsigned char *frame, int size)
{
int isvalid = 0;
// after discover
if(size < 24)
goto invalid;
int i;
unsigned char ch;
for(i=0; i<24; i++)
{
ch = *((unsigned char*)frame + i);
akcontex->dummy[i] = ch;
}
//Address 1
for(i=4; i<10; i++)
if(akcontex->dummy[i]!=akcontex->dummyap[i])
goto invalid;
//Address 2
for(i=10; i<16; i++)
if(akcontex->dummy[i]!=akcontex->dummyap[i])
goto invalid;
//Address 3
for(i=16; i<22; i++)
if(akcontex->dummy[i]!=akcontex->dummyap[i])
goto invalid;
isvalid = 1;
invalid:
return isvalid;
}
/* return 1 is valid
* return 0 is invalid
* */
int airkiss_discover_filter(const unsigned char *frame, int size)
{
int isvalid = 0;
// before discover
if(size < 50)
goto invalid;
isvalid = 1;
invalid:
return isvalid;
}
static void airkiss_record_move_ones(void *base_addr, int record_num)
{
int i;
unsigned short *record_base = base_addr;
for(i = 0; i < record_num; i++)
{
record_base[i] = record_base[i+1];
}
}
static void airkiss_add_seq_data(const unsigned char *data, int seq)
{
if(seq < _akcontext.need_seq)
{
if((seq*4 + 4) <= USR_DATA_BUFF_MAX_SIZE)
{
if((_akcontext.seq_success_map & (1 << seq)) == 0)
{
akconf->memcpy(_akcontext.usr_data + seq*4, data, 4);
_akcontext.seq_success_map |= (1 << seq);
}
}
}
}
int airkiss_init(airkiss_context_t* context,
const airkiss_config_t* config)
{
if(!context || !config)
return -1;
akcontex = context;
akconf = (airkiss_config_t*)config;
akconf->memset(&_akcontext , 0, sizeof(_airkiss_local_context));
_akcontext.airkiss_state = AIRKISS_STATE_IDLE;
akconf->printf("airkiss_local_context size:%ld\n", sizeof(_airkiss_local_context));
return 0;
}
static void resest_airkiss_data()
{
akconf->memset(&_akcontext.data, 0, sizeof(union airkiss_data));
}
static void airkiss_recv_discover(const void* frame, unsigned short length)
{
int success = 0;
_akcontext.data.guide_code.length_record[MAX_GUIDE_RECORD] = length;
airkiss_record_move_ones(_akcontext.data.guide_code.length_record, MAX_GUIDE_RECORD);
// 1 2 3 4
if((_akcontext.data.guide_code.length_record[1] - _akcontext.data.guide_code.length_record[0] == 1) &&
(_akcontext.data.guide_code.length_record[2] - _akcontext.data.guide_code.length_record[1] == 1) &&
(_akcontext.data.guide_code.length_record[3] - _akcontext.data.guide_code.length_record[2] == 1))
{
_akcontext.base_len = _akcontext.data.guide_code.length_record[0] - 1;
success = 1;
}
if(success)
{
_akcontext.airkiss_state = AIRKISS_STATE_SRC_LOCKED;
resest_airkiss_data();
akconf->printf("airkiss_recv_discover success\n");
akconf->printf("base len:%d\n", _akcontext.base_len);
int i;
unsigned char ch;
for(i=0; i<24; i++)
{
ch = *((unsigned char*)frame + i);
akcontex->dummyap[i] = ch;
//akconf->printf("0x%02x ", akcontex->dummyap[i]);
}
}
}
static void airkiss_process_magic_code(unsigned short length)
{
_akcontext.data.magic_code.record[MAX_MAGIC_CODE_RECORD] = length - _akcontext.base_len;
airkiss_record_move_ones(_akcontext.data.magic_code.record, MAX_MAGIC_CODE_RECORD);
if(((_akcontext.data.magic_code.record[0]&0x01f0)==0x0000)&&
((_akcontext.data.magic_code.record[1]&0x01f0)==0x0010)&&
((_akcontext.data.magic_code.record[2]&0x01f0)==0x0020)&&
((_akcontext.data.magic_code.record[3]&0x01f0)==0x0030))
{
_akcontext.total_len = ((_akcontext.data.magic_code.record[0] & 0x000F) << 4) + (_akcontext.data.magic_code.record[1] & 0x000F);
_akcontext.ssid_crc = ((_akcontext.data.magic_code.record[2] & 0x000F) << 4) + (_akcontext.data.magic_code.record[3] & 0x000F);
//TODO:double check magic code
_akcontext.airkiss_state = AIRKISS_STATE_MAGIC_CODE_COMPLETE;
resest_airkiss_data();
akconf->printf("airkiss_process_magic_code success\n");
akconf->printf("total_len:%d, ssid crc:%x\n", _akcontext.total_len, _akcontext.ssid_crc);
}
}
static void airkiss_process_prefix_code(unsigned short length)
{
_akcontext.data.prefix_code.record[MAX_PREFIX_CODE_RECORD] = length - _akcontext.base_len;
airkiss_record_move_ones(_akcontext.data.prefix_code.record, MAX_PREFIX_CODE_RECORD );
if((_akcontext.data.prefix_code.record[0]&0x01f0)==0x0040&&
(_akcontext.data.prefix_code.record[1]&0x01f0)==0x0050&&
(_akcontext.data.prefix_code.record[2]&0x01f0)==0x0060&&
(_akcontext.data.prefix_code.record[3]&0x01f0)==0x0070)
{
_akcontext.pswd_len = ((_akcontext.data.prefix_code.record[0] & 0x000F) << 4) + (_akcontext.data.prefix_code.record[1] & 0x000F);
if(_akcontext.pswd_len > PASSWORD_MAX_LEN)
_akcontext.pswd_len = 0;
_akcontext.pswd_lencrc = ((_akcontext.data.prefix_code.record[2] & 0x000F) << 4) + (_akcontext.data.prefix_code.record[3] & 0x000F);
if(calcrc_1byte(_akcontext.pswd_len)==_akcontext.pswd_lencrc)
{
_akcontext.airkiss_state = AIRKISS_STATE_PREFIX_CODE_COMPLETE;
}
else
{
akconf->printf("password length crc error.\n");
resest_airkiss_data();
return;
}
// only receive password and random
_akcontext.need_seq = ((_akcontext.pswd_len + 1) + 3)/4;
_akcontext.seq_success_map_cmp = (1 << _akcontext.need_seq) - 1; // EXAMPLE: need_seq = 5; seq_success_map_cmp = 0x1f; 独热码
resest_airkiss_data();
akconf->printf("airkiss_process_prefix_code success\n");
akconf->printf("pswd_len:%d, pswd_lencrc:%x, need seq:%d, seq map:%x\n",
_akcontext.pswd_len, _akcontext.pswd_lencrc, _akcontext.need_seq, _akcontext.seq_success_map_cmp);
}
}
static void airkiss_process_sequence(unsigned short length)
{
_akcontext.data.seq_code.record[MAX_SEQ_CODE_RECORD] = length - _akcontext.base_len;
airkiss_record_move_ones(_akcontext.data.seq_code.record, MAX_SEQ_CODE_RECORD);
if(((_akcontext.data.seq_code.record[0]&0x180)==0x80) &&
((_akcontext.data.seq_code.record[1]&0x180)==0x80) &&
((_akcontext.data.seq_code.record[2]&0x0100)==0x0100) &&
((_akcontext.data.seq_code.record[3]&0x0100)==0x0100) &&
((_akcontext.data.seq_code.record[4]&0x0100)==0x0100) &&
((_akcontext.data.seq_code.record[5]&0x0100)==0x0100) &&
((_akcontext.data.seq_code.record[1]&0x7F) <= ((_akcontext.total_len>>2)+1)))
{
unsigned char tempBuffer[6] = {0};
tempBuffer[0]=_akcontext.data.seq_code.record[0]&0x7F; //seq crc
tempBuffer[1]=_akcontext.data.seq_code.record[1]&0x7F; //seq index
tempBuffer[2]=_akcontext.data.seq_code.record[2]&0xFF; //data, same as following
tempBuffer[3]=_akcontext.data.seq_code.record[3]&0xFF;
tempBuffer[4]=_akcontext.data.seq_code.record[4]&0xFF;
tempBuffer[5]=_akcontext.data.seq_code.record[5]&0xFF;
akconf->printf("[crc:%02x][index:%d]:%02x,%02x,%02x,%02x; ",
tempBuffer[0], tempBuffer[1],
tempBuffer[2], tempBuffer[3], tempBuffer[4], tempBuffer[5]);
if(tempBuffer[0] == (calcrc_bytes(tempBuffer+1,5)&0x7F) )
{
int cur_seq = tempBuffer[1];
airkiss_add_seq_data(&tempBuffer[2], cur_seq);
akconf->printf("seq mapped:%x\n", _akcontext.seq_success_map);
resest_airkiss_data();
if(_akcontext.seq_success_map_cmp == _akcontext.seq_success_map)
{
int i;
akconf->printf("User data is :");
for(i=0;i<_akcontext.pswd_len + 1 + 10; i++) {
akconf->printf("%02x ",_akcontext.usr_data[i]);
}
akconf->printf("\n");
_akcontext.random_num = _akcontext.usr_data[_akcontext.pswd_len];
_akcontext.usr_data[_akcontext.pswd_len] = 0;
_akcontext.pwd = (char*)_akcontext.usr_data;
//_akcontext.ssid = (char*)_akcontext.usr_data + _akcontext.pswd_len + 1;
//_akcontext.usr_data[_akcontext.pswd_len + 1 + _akcontext.ssid_len] = 0;
_akcontext.airkiss_state = AIRKISS_STATE_COMPLETE;
}
}
else
{
akconf->printf("crc check error. calc crc:[%02x]\n",
tempBuffer[0],
calcrc_bytes(tempBuffer+1,5));
}
}
}
int airkiss_recv(airkiss_context_t* context,
const void* frame, unsigned short length)
{
if(_akcontext.airkiss_state != AIRKISS_STATE_IDLE)
if(!airkiss_filter(frame, length))
return AIRKISS_STATUS_CONTINUE;
switch(_akcontext.airkiss_state)
{
case AIRKISS_STATE_IDLE:
if(airkiss_discover_filter(frame, length)) {
airkiss_recv_discover(frame, length);
if(_akcontext.airkiss_state == AIRKISS_STATE_SRC_LOCKED)
return AIRKISS_STATUS_CHANNEL_LOCKED;
}
break;
case AIRKISS_STATE_SRC_LOCKED:
airkiss_process_magic_code(length);
break;
case AIRKISS_STATE_MAGIC_CODE_COMPLETE:
airkiss_process_prefix_code(length);
break;
case AIRKISS_STATE_PREFIX_CODE_COMPLETE:
airkiss_process_sequence(length);
if(_akcontext.airkiss_state == AIRKISS_STATE_COMPLETE)
return AIRKISS_STATUS_COMPLETE;
break;
default:
_akcontext.airkiss_state = AIRKISS_STATE_IDLE;
break;
}
return AIRKISS_STATUS_CONTINUE;
}
int airkiss_get_result(airkiss_context_t* context,
airkiss_result_t* result)
{
memcpy(result, &_akcontext, sizeof(airkiss_result_t));
return 0;
}
int airkiss_change_channel(airkiss_context_t* context)
{
memset(context, 0, sizeof(airkiss_context_t));
resest_airkiss_data();
return 0;
}