1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "wifi_provision_internal.h"
5
6 #ifndef AWSS_DISABLE_ENROLLEE
7
8 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
9 extern "C" {
10 #endif
11
12 const uint8_t probe_req_frame[ZC_PROBE_LEN] = {
13 0x40, 0x00, /* mgnt type, frame control */
14 0x00, 0x00, /* duration */
15 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
16 0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
17 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
18 0xC0, 0x79, /* seq */
19 0x00, 0x00, /* hide ssid, */
20 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96,
21 0x8C, 0x92, 0x98, 0xA4, /* supported rates */
22 0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
23 0x3F, 0x84, 0x10, 0x9E /* FCS */
24 };
25
26 static uint8_t *g_dev_sign; /* pointer to dev_name_len start pos */
27 static uint8_t *g_product_key; /* pointer to model_len start pos */
28 static uint8_t *enrollee_frame;
29 static uint16_t enrollee_frame_len;
30
31 static int decrypt_ssid_passwd(uint8_t *ie, uint8_t ie_len,
32 uint8_t out_ssid[OS_MAX_SSID_LEN],
33 uint8_t out_passwd[OS_MAX_PASSWD_LEN],
34 uint8_t out_bssid[ETH_ALEN]);
35
awss_init_enrollee_info(void)36 void awss_init_enrollee_info(void) /* void enrollee_raw_frame_init(void) */
37 {
38 char *pk = NULL, *dev_name = NULL, *text = NULL;
39 uint8_t sign[ENROLLEE_SIGN_SIZE + 1] = { 0 };
40 char key[OS_DEVICE_SECRET_LEN + 1] = { 0 };
41 int dev_name_len, pk_len;
42 int len, ie_len;
43
44 if (enrollee_frame_len)
45 return;
46
47 dev_name = awss_zalloc(OS_DEVICE_NAME_LEN + 1);
48 if (NULL == dev_name) {
49 return;
50 }
51 pk = awss_zalloc(OS_PRODUCT_KEY_LEN + 1);
52 if (NULL == pk) {
53 HAL_Free(dev_name);
54 return;
55 }
56 printf("pk:%s\r\n", pk);
57 HAL_GetProductKey(pk);
58 pk_len = strlen(pk);
59
60 HAL_GetDeviceName(dev_name);
61 dev_name_len = strlen(dev_name);
62 printf("dev_name:%s\r\n", dev_name);
63 len = RANDOM_MAX_LEN + dev_name_len + pk_len;
64 text = awss_zalloc(len + 1); /* +1 for string print */
65
66 awss_build_sign_src(text, &len);
67
68 for (int i = 0; i < len; i++) {
69 printf("0x%x ", *(unsigned char *)(text + i));
70 }
71 printf("\r\n");
72 if (awss_get_encrypt_type() == 3) { /* aes-key per product */
73 HAL_GetProductSecret(key);
74 } else { /* aes-key per device */
75 HAL_GetDeviceSecret(key);
76 }
77
78 printf("key:%s\r\n", key);
79 produce_signature(sign, (uint8_t *)text, len, key);
80 for (int i = 0; i < SHA1_DIGEST_SIZE; i++) {
81 printf("0x%x ", *(unsigned char *)(sign + i));
82 }
83 printf("\r\n");
84
85 HAL_Free(text);
86
87 ie_len = pk_len + dev_name_len + ENROLLEE_IE_FIX_LEN;
88 enrollee_frame_len = sizeof(probe_req_frame) + ie_len;
89
90 enrollee_frame = awss_zalloc(enrollee_frame_len);
91
92 /* construct the enrollee frame right now */
93 len = sizeof(probe_req_frame) - FCS_SIZE;
94 memcpy(enrollee_frame, probe_req_frame, len);
95
96 enrollee_frame[len++] = 221; /* vendor ie */
97 enrollee_frame[len++] = ie_len - 2; /* exclude 221 & len */
98 enrollee_frame[len++] = 0xD8;
99 enrollee_frame[len++] = 0x96;
100 enrollee_frame[len++] = 0xE0;
101 enrollee_frame[len++] = 0xAA; /* OUI type */
102 enrollee_frame[len++] = DEVICE_TYPE_VERSION; /* version & dev type */
103
104 enrollee_frame[len++] = dev_name_len; /* dev name len*/
105 memcpy(&enrollee_frame[len], dev_name, dev_name_len);
106 len += dev_name_len;
107
108 enrollee_frame[len++] = ENROLLEE_FRAME_TYPE; /* frame type */
109
110 g_product_key =
111 &enrollee_frame[len]; /* pointer to pk len, see decrypt func */
112 enrollee_frame[len++] = pk_len;
113 memcpy(&enrollee_frame[len], pk, pk_len);
114 len += pk_len;
115
116 enrollee_frame[len++] = RANDOM_MAX_LEN;
117 memcpy(&enrollee_frame[len], aes_random, RANDOM_MAX_LEN);
118 len += RANDOM_MAX_LEN;
119
120 enrollee_frame[len++] = awss_get_encrypt_type(); /*encrypt type */
121 enrollee_frame[len++] =
122 0; /* signature method, 0: hmacsha1, 1: hmacsha256 */
123 enrollee_frame[len++] = ENROLLEE_SIGN_SIZE; /* signature length */
124 g_dev_sign = &enrollee_frame[len];
125 memcpy(&enrollee_frame[len], sign, ENROLLEE_SIGN_SIZE);
126 len += ENROLLEE_SIGN_SIZE;
127
128 memcpy(&enrollee_frame[len],
129 &probe_req_frame[sizeof(probe_req_frame) - FCS_SIZE], FCS_SIZE);
130
131 /* update probe request frame src mac */
132 os_wifi_get_mac(enrollee_frame + SA_POS);
133
134 for (int i = 0; i < 6; i++) {
135 printf("0x%x ", *(unsigned char *)(enrollee_frame + SA_POS + i));
136 }
137
138 HAL_Free(pk);
139 HAL_Free(dev_name);
140 }
141
awss_destroy_enrollee_info(void)142 void awss_destroy_enrollee_info(void)
143 {
144 if (enrollee_frame_len) {
145 if (NULL != enrollee_frame) {
146 HAL_Free(enrollee_frame);
147 }
148 enrollee_frame_len = 0;
149 enrollee_frame = NULL;
150 g_dev_sign = NULL;
151 g_product_key = NULL;
152 }
153 }
154
awss_broadcast_enrollee_info(void)155 void awss_broadcast_enrollee_info(void)
156 {
157 if (enrollee_frame_len == 0 || enrollee_frame == NULL)
158 return;
159
160 HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, enrollee_frame,
161 enrollee_frame_len);
162 }
163
164 /* return 0 for success, -1 dev_name not match, otherwise return -2 */
decrypt_ssid_passwd(uint8_t * ie,uint8_t ie_len,uint8_t out_ssid[OS_MAX_SSID_LEN],uint8_t out_passwd[OS_MAX_PASSWD_LEN],uint8_t out_bssid[ETH_ALEN])165 static int decrypt_ssid_passwd(uint8_t *ie, uint8_t ie_len,
166 uint8_t out_ssid[OS_MAX_SSID_LEN],
167 uint8_t out_passwd[OS_MAX_PASSWD_LEN],
168 uint8_t out_bssid[ETH_ALEN])
169 {
170 uint8_t tmp_ssid[OS_MAX_SSID_LEN + 1] = { 0 },
171 tmp_passwd[OS_MAX_PASSWD_LEN + 1] = {
172 0
173 };
174 uint8_t *p_dev_name_sign = NULL, *p_ssid = NULL, *p_passwd = NULL,
175 *p_bssid = NULL;
176
177 /* ignore ie hdr: 221, len, oui[3], type(0xAB) */
178 #define REGISTRAR_IE_HDR (6)
179 ie += REGISTRAR_IE_HDR;
180 printf("ethan registrar(devtype/ver=%d\r\n", ie[0]);
181 if (ie[0] != DEVICE_TYPE_VERSION) {
182 awss_debug("registrar(devtype/ver=%d not supported!", ie[0]);
183 return -1;
184 }
185
186 ie++; /* skip version */
187 p_dev_name_sign = ie;
188
189 if (!g_dev_sign ||
190 memcmp(g_dev_sign, p_dev_name_sign + 1, p_dev_name_sign[0])) {
191 p_dev_name_sign[p_dev_name_sign[0]] = '\0';
192 awss_debug("dev_name not match, expect:");
193 printf("dev_name not match, expect\r\n");
194 if (g_dev_sign)
195 dump_hex(g_dev_sign, p_dev_name_sign[0], 16);
196 awss_debug("\r\nbut recv:");
197 dump_hex(p_dev_name_sign + 1, p_dev_name_sign[0], 16);
198 return -2;
199 }
200 ie += ie[0] + 1; /* eating device name sign length & device name sign[n] */
201 printf("ethan registrar(frametype/ver=%d\r\n", ie[0]);
202 if (ie[0] != REGISTRAR_FRAME_TYPE) {
203 awss_debug("registrar(frametype=%d not supported!", ie[0]);
204 return -1;
205 }
206
207 ie++; /* eating frame type */
208 p_ssid = ie;
209 if (ie[0] >= OS_MAX_SSID_LEN) {
210 awss_debug("registrar(ssidlen=%d invalid!", ie[0]);
211 printf("registrar(ssidlen=%d invalid!\r\n", ie[0]);
212 return -1;
213 }
214 memcpy(tmp_ssid, &p_ssid[1], p_ssid[0]);
215 awss_debug("Registrar ssid:%s", tmp_ssid);
216 printf("Registrar ssid:%s\r\n", tmp_ssid);
217
218 ie += ie[0] + 1; /* eating ssid_len & ssid[n] */
219
220 p_passwd = ie;
221 if (p_passwd[0] >= OS_MAX_PASSWD_LEN) {
222 awss_debug("registrar(passwdlen=%d invalid!", p_passwd[0]);
223 printf("registrar(passwdlen=%d invalid!\r\n", p_passwd[0]);
224 return -1;
225 }
226
227 ie += ie[0] + 1; /* eating passwd_len & passwd */
228
229 p_bssid = ie;
230 ie += ETH_ALEN; /* eating bssid len */
231
232 AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX, AWSS_STATIS_TYPE_TIME_START);
233
234 aes_decrypt_string((char *)p_passwd + 1, (char *)tmp_passwd, p_passwd[0], 1,
235 awss_get_encrypt_type(), 0,
236 (const char *)aes_random); /* aes128 cfb */
237 if (is_utf8((const char *)tmp_passwd, p_passwd[0]) != 1) {
238 awss_debug("registrar(passwd invalid!");
239 printf("registrar(passwd invalid!\r\n");
240 AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX,
241 AWSS_STATIS_TYPE_PASSWD_ERR);
242 return -1;
243 }
244 awss_debug("ssid:%s\r\n", tmp_ssid);
245 printf("ssid:%s, tmp_passwd:%s\r\n", tmp_ssid, tmp_passwd);
246 strncpy((char *)out_passwd, (const char *)tmp_passwd,
247 OS_MAX_PASSWD_LEN - 1);
248 strncpy((char *)out_ssid, (const char *)tmp_ssid, OS_MAX_SSID_LEN - 1);
249 memcpy((char *)out_bssid, (char *)p_bssid, ETH_ALEN);
250
251 return 0; /* success */
252 }
253
awss_ieee80211_zconfig_process(uint8_t * mgmt_header,int len,int link_type,struct parser_res * res,signed char rssi)254 int awss_ieee80211_zconfig_process(uint8_t *mgmt_header, int len, int link_type,
255 struct parser_res *res, signed char rssi)
256 {
257 const uint8_t *registrar_ie = NULL;
258 struct ieee80211_hdr *hdr;
259 uint16_t ieoffset;
260 int fc;
261
262 /*
263 * when device try to connect current router (include aha)
264 * skip the new aha and process the new aha in the next scope.
265 */
266 if (mgmt_header == NULL || zconfig_finished)
267 return ALINK_INVALID;
268
269 /*
270 * we don't process zconfig used by enrollee until user press configure
271 * button
272 */
273 if (awss_get_config_press() == 0)
274 return ALINK_INVALID;
275 hdr = (struct ieee80211_hdr *)mgmt_header;
276 fc = hdr->frame_control;
277
278 if (!ieee80211_is_probe_resp(fc))
279 return ALINK_INVALID;
280 ieoffset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
281 if (ieoffset > len)
282 return ALINK_INVALID;
283
284 registrar_ie = (const uint8_t *)cfg80211_find_vendor_ie(
285 WLAN_OUI_ALIBABA, WLAN_OUI_TYPE_REGISTRAR, mgmt_header + ieoffset,
286 len - ieoffset);
287 if (registrar_ie == NULL)
288 return ALINK_INVALID;
289
290 res->u.ie.alink_ie_len = len - (registrar_ie - mgmt_header);
291 res->u.ie.alink_ie = (uint8_t *)registrar_ie;
292 return ALINK_ZERO_CONFIG;
293 }
294
awss_recv_callback_zconfig(struct parser_res * res)295 int awss_recv_callback_zconfig(struct parser_res *res)
296 {
297 uint8_t tods = res->tods;
298 uint8_t channel = res->channel;
299
300 uint8_t *ie = res->u.ie.alink_ie;
301 uint8_t ie_len = ie[1];
302 int ret;
303 if (res->u.ie.alink_ie_len < ie_len)
304 return PKG_INVALID;
305
306 ret = decrypt_ssid_passwd(ie, ie_len, zc_ssid, zc_passwd, zc_bssid);
307 if (ret)
308 return PKG_INVALID;
309
310 zconfig_set_state(STATE_RCV_DONE, tods, channel);
311
312 AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_SUC);
313
314 return PKG_END;
315 }
316 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
317 }
318 #endif
319
320 #endif
321