• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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