1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: WAPI Implementation
15 */
16
17 #include "securec.h"
18 #include "utils/includes.h"
19 #include "utils/common.h"
20 #include "utils/os.h"
21 #include "utils/eloop.h"
22 #include "utils/base64.h"
23 #include "utils/wpabuf.h"
24 #include "common/wpa_common.h"
25 #include "common/defs.h"
26 #include "common/wpa_ctrl.h"
27 #include "l2_packet/l2_packet.h"
28 #include "wpa_supplicant_i.h"
29 #include "driver_i.h"
30 #include "bss.h"
31 #include "wapi.h"
32 #include "wai_rxtx.h"
33 #include "wai_crypto.h"
34 #include "wai_sm.h"
35
36 #define WAPI_IE_INFO_AKM_SUITE_TYPE_OFFSET 9
37
38 static const wapi_cipher_suite_stru g_wai_cipher_suite[] = {
39 {
40 .wpa_alg_type = WPA_ALG_NONE,
41 .wpa_cipher_flag = WPA_CIPHER_NONE,
42 .wai_cipher_type = CIPHER_TYPE_NONE,
43 .wai_decrypt_cb = NULL,
44 },
45 {
46 .wpa_alg_type = WPA_ALG_SMS4,
47 .wpa_cipher_flag = WPA_CIPHER_SMS4,
48 .wai_cipher_type = CIPHER_TYPE_SM4_OFB,
49 .wai_decrypt_cb = wai_sm4_ofb_decrypt,
50 },
51 };
52
53 static int g_ucast_cipher_suite = (int)CIPHER_TYPE_NONE;
54 static int g_mcast_cipher_suite = (int)CIPHER_TYPE_NONE;
55
wapi_iface_init(struct wapi_asue_struct * wapi)56 void wapi_iface_init(struct wapi_asue_struct *wapi)
57 {
58 if (wapi == NULL)
59 return;
60
61 wapi->state = WAISM_INIT;
62 wapi->next_frame_seq = 1;
63 wapi->tx_frame_seq = 0;
64 (void)memset_s(&wapi->usksa, sizeof(wapi_usksa_stru), 0, sizeof(wapi_usksa_stru));
65 (void)memset_s(&wapi->msksa, sizeof(wapi_msksa_stru), 0, sizeof(wapi_msksa_stru));
66 }
67
wapi_iface_deinit(struct wapi_asue_struct * wapi)68 void wapi_iface_deinit(struct wapi_asue_struct *wapi)
69 {
70 if (wapi == NULL)
71 return;
72
73 if (wapi->tx_framebuf != NULL) {
74 wpabuf_free(wapi->tx_framebuf);
75 wapi->tx_framebuf = NULL;
76 }
77
78 (void)memset_s(&wapi->bksa, sizeof(wapi_bksa_stru), 0, sizeof(wapi_bksa_stru));
79 (void)memset_s(&wapi->usksa, sizeof(wapi_usksa_stru), 0, sizeof(wapi_usksa_stru));
80 (void)memset_s(&wapi->msksa, sizeof(wapi_msksa_stru), 0, sizeof(wapi_msksa_stru));
81 }
82
wapi_init_ie(struct wpa_supplicant * wpa)83 int wapi_init_ie(struct wpa_supplicant *wpa)
84 {
85 /* Framing in little-endian mode.
86 * OUI is "0x00 0x14 0x72".
87 * Information about the WAPI information element supported by the current device:
88 * Name Length Value(Bytes)
89 * IE 1 68
90 * Pkg length 1 22
91 * Version 2 1
92 * AKM count 2 1
93 * AKM suite type 4 OUI + 2(Default support PSK)
94 * ucast cipher suite cnt 2 1
95 * ucast cipher suite type 4 OUI + 1(Only support SM4)
96 * mcast cipher suite type 4 OUI + 1(Only support SM4)
97 * WAPI Capability info 2 0x0
98 * Number of BKID 2 0x0
99 */
100 unsigned char wapi_ie[] = {
101 0x44, 0x16, 0x01, 0x00, 0x01, 0x00, 0x00, 0x14,
102 0x72, 0x02, 0x01, 0x00, 0x00, 0x14, 0x72, 0x01,
103 0x00, 0x14, 0x72, 0x01, 0x00, 0x00, 0x00, 0x00
104 };
105 struct wapi_asue_struct *wapi = NULL;
106
107 if ((wpa == NULL) || (wpa->wapi == NULL)) {
108 wpa_printf(MSG_ERROR, "wapi struct error");
109 return WAPI_FAILED;
110 }
111
112 wapi = wpa->wapi;
113 if (wapi->auth_type == AUTH_TYPE_NONE_WAPI) {
114 wpa_printf(MSG_ERROR, "open, needn't set wapi-ie");
115 return WAPI_SUCCESS;
116 }
117
118 if (memset_s(wapi->assoc_wapi_ie, WAPI_IE_MAX_SIZE, 0, sizeof(wapi->assoc_wapi_ie)) != EOK) {
119 wpa_printf(MSG_ERROR, "memset assoc_wapi_ie failed");
120 return WAPI_FAILED;
121 }
122 wapi->assoc_wapi_ie_len = 0;
123
124 if ((unsigned int)wpa->key_mgmt == WPA_KEY_MGMT_WAPI_PSK) {
125 wapi_ie[WAPI_IE_INFO_AKM_SUITE_TYPE_OFFSET] = AUTH_TYPE_WAPI_PSK;
126 } else if ((unsigned int)wpa->key_mgmt == WPA_KEY_MGMT_WAPI_CERT) {
127 wapi_ie[WAPI_IE_INFO_AKM_SUITE_TYPE_OFFSET] = AUTH_TYPE_WAPI_CERT;
128 } else {
129 wpa_printf(MSG_ERROR, "invalid key_mgmt %#x", (unsigned int)wpa->key_mgmt);
130 return WAPI_FAILED;
131 }
132
133 if (memcpy_s(wapi->assoc_wapi_ie, WAPI_IE_MAX_SIZE, wapi_ie, sizeof(wapi_ie)) != EOK) {
134 wpa_printf(MSG_ERROR, "memcpy wapi ie failed");
135 return WAPI_FAILED;
136 }
137 wapi->assoc_wapi_ie_len = sizeof(wapi_ie);
138
139 return WAPI_SUCCESS;
140 }
141
wapi_parse_ie(const unsigned char * wapi_ie,unsigned int ie_len,struct wpa_ie_data * ie_data)142 int wapi_parse_ie(const unsigned char *wapi_ie, unsigned int ie_len,
143 struct wpa_ie_data *ie_data)
144 {
145 const unsigned char wapi_oui[] = {0x00, 0x14, 0x72};
146 wapi_cipher_suite_stru *cipher_suite = NULL;
147 unsigned short version;
148 unsigned short suite_cnt;
149 unsigned char suite_type;
150 unsigned char *ptr = NULL;
151 unsigned short cnt;
152 int left;
153
154 if ((wapi_ie == NULL) || (ie_data == NULL))
155 return WAPI_FAILED;
156
157 if (memset_s(ie_data, sizeof(struct wpa_ie_data), 0, sizeof(struct wpa_ie_data)) != EOK)
158 return WAPI_FAILED;
159
160 /* default setting */
161 ie_data->proto = (int)WPA_PROTO_WAPI;
162 ie_data->pairwise_cipher = (int)WPA_CIPHER_SMS4;
163 ie_data->group_cipher = (int)WPA_CIPHER_SMS4;
164 ie_data->key_mgmt = (int)WPA_KEY_MGMT_WAPI_PSK;
165 ie_data->capabilities = 0;
166 ie_data->pmkid = NULL;
167 ie_data->num_pmkid = 0;
168 ie_data->mgmt_group_cipher = 0;
169
170 /* wapi_ie[1]: IE data length */
171 if ((ie_len != (wapi_ie[1] + (unsigned int)WAPI_IE_ID_SIZE + (unsigned int)WAPI_IE_LENGTH_SIZE)) ||
172 (ie_len < (WAPI_IE_ID_SIZE + WAPI_IE_LENGTH_SIZE + WAPI_IE_VERSION_SIZE + WAPI_IE_AKM_CNT_LEN))) {
173 wpa_printf(MSG_ERROR, "ie_len error");
174 return WAPI_FAILED;
175 }
176
177 ptr = (unsigned char *)wapi_ie + WAPI_IE_ID_SIZE + WAPI_IE_LENGTH_SIZE;
178 version = *((unsigned short *)ptr);
179 if (version != WAI_VERSION)
180 return WAPI_FAILED;
181
182 ptr += WAPI_IE_VERSION_SIZE;
183
184 /* check akm suite type */
185 suite_cnt = WPA_GET_LE16(ptr);
186 ptr += WAPI_IE_AKM_CNT_LEN;
187 left = (int)((((ie_len - WAPI_IE_ID_SIZE) - WAPI_IE_LENGTH_SIZE) - WAPI_IE_VERSION_SIZE) - WAPI_IE_AKM_CNT_LEN);
188 for (cnt = 0; cnt < suite_cnt; ++cnt) {
189 if (left < (WAPI_IE_OUI_SIZE + WAPI_IE_AKM_SUIT_LEN))
190 return WAPI_FAILED;
191
192 /* check akm suite oui */
193 if (os_memcmp(ptr, wapi_oui, sizeof(wapi_oui)) != 0)
194 return WAPI_FAILED;
195
196 ptr += WAPI_IE_OUI_SIZE;
197 suite_type = *ptr;
198
199 wpa_printf(MSG_DEBUG, "akm suite %#x", (unsigned int)suite_type);
200
201 if (suite_type == (int)AUTH_TYPE_WAPI_PSK)
202 ie_data->key_mgmt |= (int)WPA_KEY_MGMT_WAPI_PSK;
203 else if (suite_type == (int)AUTH_TYPE_WAPI_CERT)
204 ie_data->key_mgmt |= (int)WPA_KEY_MGMT_WAPI_CERT;
205 else
206 return WAPI_FAILED;
207
208 ptr += WAPI_IE_AKM_SUIT_LEN;
209 left -= WAPI_IE_OUI_SIZE + WAPI_IE_AKM_SUIT_LEN;
210 }
211
212 if (left < WAPI_IE_CIPHER_CNT_LEN)
213 return WAPI_FAILED;
214
215 /* check ucast cipher suite type */
216 suite_cnt = WPA_GET_LE16(ptr);
217 ptr += WAPI_IE_CIPHER_CNT_LEN;
218 left -= WAPI_IE_CIPHER_CNT_LEN;
219 for (cnt = 0; cnt < suite_cnt; ++cnt) {
220 if (left < (WAPI_IE_OUI_SIZE + WAPI_IE_CIPHER_SUIT_LEN))
221 return WAPI_FAILED;
222
223 /* check akm suite oui */
224 if (os_memcmp(ptr, wapi_oui, sizeof(wapi_oui)) != 0)
225 return WAPI_FAILED;
226
227 ptr += WAPI_IE_OUI_SIZE;
228 suite_type = *ptr;
229 wpa_printf(MSG_DEBUG, "ucast cipher suite %#x", (unsigned int)suite_type);
230
231 if (suite_type >= (unsigned int)CIPHER_TYPE_MAX)
232 return WAPI_FAILED;
233
234 cipher_suite = (wapi_cipher_suite_stru *)&g_wai_cipher_suite[suite_type];
235 ie_data->pairwise_cipher |= cipher_suite->wpa_cipher_flag;
236 g_ucast_cipher_suite = (int)suite_type;
237 ptr += WAPI_IE_CIPHER_SUIT_LEN;
238 left -= WAPI_IE_OUI_SIZE + WAPI_IE_CIPHER_SUIT_LEN;
239 }
240 ie_data->has_pairwise = (int)suite_cnt;
241
242 if (left < (WAPI_IE_OUI_SIZE + WAPI_IE_CIPHER_SUIT_LEN))
243 return WAPI_FAILED;
244
245 /* check akm suite oui */
246 if (os_memcmp(ptr, wapi_oui, sizeof(wapi_oui)) != 0)
247 return WAPI_FAILED;
248
249 ptr += WAPI_IE_OUI_SIZE;
250
251 /* check mcast cipher suite type */
252 suite_type = *ptr;
253 wpa_printf(MSG_DEBUG, "mcast cipher suite %#x", (unsigned int)suite_type);
254
255 if (suite_type >= (unsigned int)CIPHER_TYPE_MAX)
256 return WAPI_FAILED;
257
258 cipher_suite = (wapi_cipher_suite_stru *)&g_wai_cipher_suite[suite_type];
259 ie_data->group_cipher |= cipher_suite->wpa_cipher_flag;
260 g_mcast_cipher_suite = (int)suite_type;
261 ie_data->has_group = 1;
262
263 wpa_printf(MSG_DEBUG, "parse wapi info element success");
264 return WAPI_SUCCESS;
265 }
266
wapi_generate_addid(struct wapi_asue_struct * wapi,struct wpa_bss * bss)267 int wapi_generate_addid(struct wapi_asue_struct *wapi, struct wpa_bss *bss)
268 {
269 if ((wapi == NULL) || (bss == NULL))
270 return WAPI_FAILED;
271
272 if (memcpy_s(wapi->addid, WAI_ADDID_SIZE, bss->bssid, ETH_ALEN) != EOK) {
273 wpa_error_log0(MSG_WARNING, "memcpy ae mac failed");
274 return WAPI_FAILED;
275 }
276 if (memcpy_s(&wapi->addid[ETH_ALEN], (WAI_ADDID_SIZE - ETH_ALEN), wapi->own_mac, ETH_ALEN) != EOK) {
277 wpa_error_log0(MSG_WARNING, "memcpy asue mac failed");
278 return WAPI_FAILED;
279 }
280 return WAPI_SUCCESS;
281 }
282
wapi_event_process(struct wapi_asue_struct * wapi,conn_status_enum action,const unsigned char * assoc_ie,size_t assoc_ie_len)283 int wapi_event_process(struct wapi_asue_struct *wapi, conn_status_enum action,
284 const unsigned char *assoc_ie, size_t assoc_ie_len)
285 {
286 unsigned char bkid[WAI_BKID_SIZE] = { 0 };
287
288 if (wapi == NULL ||
289 (assoc_ie != NULL && assoc_ie_len == 0) ||
290 (assoc_ie == NULL && assoc_ie_len != 0)) {
291 wpa_printf(MSG_WARNING, "param is null");
292 return WAPI_FAILED;
293 }
294
295 wpa_printf(MSG_DEBUG, "action %u auth_type %u assoc_ie_len %u",
296 (unsigned int)action, (unsigned int)wapi->auth_type, assoc_ie_len);
297
298 if (action == CONN_ASSOC) {
299 if (wapi->auth_type == AUTH_TYPE_WAPI_PSK) {
300 if (wai_kd_hmac_sha256(wapi->addid, WAI_ADDID_SIZE, wapi->bk, WAI_BK_SIZE,
301 bkid, WAI_BKID_SIZE) != WAPI_SUCCESS) {
302 forced_memzero(bkid, WAI_BKID_SIZE);
303 wpa_printf(MSG_WARNING, "hmac_sha256 calc bkid failed");
304 return WAPI_FAILED;
305 }
306 if (memcpy_s(wapi->bksa.bk, WAI_BK_SIZE, wapi->bk, WAI_BK_SIZE) != EOK) {
307 forced_memzero(bkid, WAI_BKID_SIZE);
308 forced_memzero(&wapi->bksa, sizeof(wapi_bksa_stru));
309 wpa_printf(MSG_WARNING, "memcpy bk failed");
310 return WAPI_FAILED;
311 }
312 if (memcpy_s(wapi->bksa.bkid, WAI_BKID_SIZE, bkid, WAI_BKID_SIZE) != EOK) {
313 forced_memzero(bkid, WAI_BKID_SIZE);
314 forced_memzero(&wapi->bksa, sizeof(wapi_bksa_stru));
315 wpa_printf(MSG_WARNING, "memcpy bkid failed");
316 return WAPI_FAILED;
317 }
318 forced_memzero(bkid, WAI_BKID_SIZE);
319 if (memcpy_s(wapi->bksa.ae_mac, ETH_ALEN, wapi->bssid, ETH_ALEN) != EOK) {
320 forced_memzero(&wapi->bksa, sizeof(wapi_bksa_stru));
321 wpa_printf(MSG_WARNING, "memcpy ae mac failed");
322 return WAPI_FAILED;
323 }
324 if (memcpy_s(wapi->bksa.asue_mac, ETH_ALEN, wapi->own_mac, ETH_ALEN) != EOK) {
325 forced_memzero(&wapi->bksa, sizeof(wapi_bksa_stru));
326 wpa_printf(MSG_WARNING, "memcpy asue mac failed");
327 return WAPI_FAILED;
328 }
329 }
330
331 if (wapi->auth_type != AUTH_TYPE_NONE_WAPI) {
332 if (assoc_ie_len > (sizeof(wapi->wapi_ie) - 1))
333 assoc_ie_len = sizeof(wapi->wapi_ie) - 1;
334
335 if (memcpy_s(wapi->wapi_ie, WAPI_IE_MAX_SIZE, assoc_ie, assoc_ie_len) != EOK) {
336 forced_memzero(&wapi->bksa, sizeof(wapi_bksa_stru));
337 wpa_printf(MSG_WARNING, "memcpy wapi ie failed");
338 return WAPI_FAILED;
339 }
340 wapi->wapi_ie_len = assoc_ie_len;
341 }
342 /* The BK cache is cleared only after the ASSOC RSP is successful,
343 * because the BK cache will still be used in retransmission. */
344 (void)memset_s(wapi->bk, WAI_BK_SIZE, 0, WAI_BK_SIZE);
345
346 /* Reset state when new association start */
347 wapi->state = WAISM_INIT;
348 wapi->next_frame_seq = 1;
349 wapi->tx_frame_seq = 0;
350 (void)memset_s(&wapi->usksa, sizeof(wapi_usksa_stru), 0, sizeof(wapi_usksa_stru));
351 (void)memset_s(&wapi->msksa, sizeof(wapi_msksa_stru), 0, sizeof(wapi_msksa_stru));
352
353 wapi->ucast_cipher_suite = &g_wai_cipher_suite[g_ucast_cipher_suite];
354 wapi->mcast_cipher_suite = &g_wai_cipher_suite[g_mcast_cipher_suite];
355 wapi->state = WAISM_ALREADY_ASSOC;
356 } else if (action == CONN_DISASSOC) {
357 wapi->state = WAISM_INIT;
358 (void)memset_s(wapi->bk, WAI_BK_SIZE, 0, WAI_BK_SIZE);
359 (void)memset_s(&wapi->bksa, sizeof(wapi_bksa_stru), 0, sizeof(wapi_bksa_stru));
360 (void)memset_s(&wapi->usksa, sizeof(wapi_usksa_stru), 0, sizeof(wapi_usksa_stru));
361 (void)memset_s(&wapi->msksa, sizeof(wapi_msksa_stru), 0, sizeof(wapi_msksa_stru));
362 }
363
364 return WAPI_SUCCESS;
365 }
366