1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 /* ****************************************************************************
20 1 头文件包含
21 **************************************************************************** */
22 #include "oam_ext_if.h"
23 #include "mac_frame.h"
24 #include "dmac_ext_if.h"
25 #include "hmac_crypto_tkip.h"
26
27 #ifdef __cplusplus
28 #if __cplusplus
29 extern "C" {
30 #endif
31 #endif
32
33 /* ****************************************************************************
34 2 函数实现
35 **************************************************************************** */
xswap(hi_u32 val)36 static hi_u32 xswap(hi_u32 val)
37 {
38 return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); /* 8 左移右移位数 */
39 }
40
get_le32_split(hi_u8 b0,hi_u8 b1,hi_u8 b2,hi_u8 b3)41 static hi_u32 get_le32_split(hi_u8 b0, hi_u8 b1, hi_u8 b2, hi_u8 b3)
42 {
43 return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); /* 8 16 24 移动位数 */
44 }
45
get_le32(const hi_u8 * p,hi_u8 le_len)46 static hi_u32 get_le32(const hi_u8 *p, hi_u8 le_len)
47 {
48 hi_unref_param(le_len);
49 return get_le32_split(p[0], p[1], p[2], p[3]); /* 2 3 数组索引 */
50 }
51
put_le32(hi_u8 * p,hi_u32 v)52 static hi_void put_le32(hi_u8 *p, hi_u32 v)
53 {
54 p[0] = (hi_u8)v;
55 p[1] = (hi_u8)(v >> 8); /* 右移8位 */
56 p[2] = (hi_u8)(v >> 16); /* 2 元素索引 右移16位 */
57 p[3] = (hi_u8)(v >> 24); /* 3 元素索引 右移24位 */
58 }
59
60 /* ****************************************************************************
61 功能描述 : mic所需的源mac,目的mac,及TID信息构造
62 输出参数 : hi_void
63 修改历史 :
64 1.日 期 : 2014年3月3日
65 作 者 : HiSilicon
66 修改内容 : 新生成函数
67 **************************************************************************** */
hmac_crypto_tkip_michael_hdr(mac_ieee80211_frame_stru * frame_header,hi_u8 * auc_hdr,hi_u8 hdr_len)68 static hi_void hmac_crypto_tkip_michael_hdr(mac_ieee80211_frame_stru *frame_header, hi_u8 *auc_hdr, hi_u8 hdr_len)
69 {
70 mac_ieee80211_frame_addr4_stru *frame_4addr_hdr = (mac_ieee80211_frame_addr4_stru *)frame_header;
71
72 hi_u8 frame_dir = (frame_4addr_hdr->frame_control.to_ds) ? 1 : 0;
73 frame_dir += (frame_4addr_hdr->frame_control.from_ds) ? 2 : 0; /* 自增2 */
74
75 if (frame_dir == IEEE80211_FC1_DIR_NODS) {
76 if ((memcpy_s(auc_hdr, hdr_len, frame_4addr_hdr->auc_address1, WLAN_MAC_ADDR_LEN) != EOK) ||
77 (memcpy_s(auc_hdr + WLAN_MAC_ADDR_LEN, hdr_len - WLAN_MAC_ADDR_LEN, frame_4addr_hdr->auc_address2,
78 WLAN_MAC_ADDR_LEN) != EOK)) {
79 goto addrerr;
80 }
81 } else if (frame_dir == IEEE80211_FC1_DIR_TODS) {
82 if ((memcpy_s(auc_hdr, hdr_len, frame_4addr_hdr->auc_address3, WLAN_MAC_ADDR_LEN) != EOK) ||
83 (memcpy_s(auc_hdr + WLAN_MAC_ADDR_LEN, hdr_len - WLAN_MAC_ADDR_LEN, frame_4addr_hdr->auc_address2,
84 WLAN_MAC_ADDR_LEN) != EOK)) {
85 goto addrerr;
86 }
87 } else if (frame_dir == IEEE80211_FC1_DIR_FROMDS) {
88 if ((memcpy_s(auc_hdr, hdr_len, frame_4addr_hdr->auc_address1, WLAN_MAC_ADDR_LEN) != EOK) ||
89 (memcpy_s(auc_hdr + WLAN_MAC_ADDR_LEN, hdr_len - WLAN_MAC_ADDR_LEN, frame_4addr_hdr->auc_address3,
90 WLAN_MAC_ADDR_LEN) != EOK)) {
91 goto addrerr;
92 }
93 } else {
94 if ((memcpy_s(auc_hdr, hdr_len, frame_4addr_hdr->auc_address3, WLAN_MAC_ADDR_LEN) != EOK) ||
95 (memcpy_s(auc_hdr + WLAN_MAC_ADDR_LEN, hdr_len - WLAN_MAC_ADDR_LEN, frame_4addr_hdr->auc_address4,
96 WLAN_MAC_ADDR_LEN) != EOK)) {
97 goto addrerr;
98 }
99 }
100
101 auc_hdr[12] = 0; /* 12 元素索引 */
102
103 if (frame_4addr_hdr->frame_control.sub_type == WLAN_QOS_DATA) {
104 if (frame_dir == IEEE80211_FC1_DIR_DSTODS) {
105 auc_hdr[12] = ((mac_ieee80211_qos_frame_addr4_stru *)frame_4addr_hdr)->qc_tid; /* 12 元素索引 */
106 } else {
107 auc_hdr[12] = ((mac_ieee80211_qos_frame_stru *)frame_4addr_hdr)->qc_tid; /* 12 元素索引 */
108 }
109 }
110
111 auc_hdr[13] = auc_hdr[14] = auc_hdr[15] = 0; /* 13 14 15 reserved */
112
113 return;
114
115 addrerr:
116 oam_error_log0(0, OAM_SF_CFG, "hmac_crypto_tkip_michael_hdr:: auc_address memcpy_s fail,check addr num.");
117 return;
118 }
119
120 /* ****************************************************************************
121 功能描述 : 生成mic校验码
122 输入参数 : key 密钥(8byte)
123 返 回 值 : 0:成功,其他:失败
124 修改历史 :
125 1.日 期 : 2014年3月3日
126 作 者 : HiSilicon
127 修改内容 : 新生成函数
128 **************************************************************************** */
129 /* 规则5.1 避免函数过长,函数不超过50行(非空非注释),申请例外: 算法函数,功能内聚,建议屏蔽 */
hmac_crypto_tkip_michael_mic(const hi_u8 * puc_key,const oal_netbuf_stru * netbuf,mac_ieee80211_frame_stru * frame_header,const hmac_michael_mic_info_stru * michael_mic_info)130 static hi_u32 hmac_crypto_tkip_michael_mic(const hi_u8 *puc_key, const oal_netbuf_stru *netbuf,
131 mac_ieee80211_frame_stru *frame_header, const hmac_michael_mic_info_stru *michael_mic_info)
132 {
133 hi_u8 auc_hdr[AUC_HDR_SIZE] = {0};
134 hi_u32 offset = michael_mic_info->offset;
135 hi_u32 data_len = michael_mic_info->data_len;
136
137 hmac_crypto_tkip_michael_hdr(frame_header, auc_hdr, AUC_HDR_SIZE);
138
139 hi_u32 msb = get_le32(puc_key, 4); /* 4 一次计算长度 */
140 hi_u32 lsb = get_le32(puc_key + 4, 4); /* 4 偏移量 */
141
142 /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
143 msb ^= get_le32(auc_hdr, 4); /* 4 一次计算长度 */
144 michael_block(msb, lsb);
145 msb ^= get_le32(&auc_hdr[4], 4); /* 4 元素索引 */
146 michael_block(msb, lsb);
147 msb ^= get_le32(&auc_hdr[8], 4); /* 8 元素索引, 4 一次计算长度 */
148 michael_block(msb, lsb);
149 msb ^= get_le32(&auc_hdr[12], 4); /* 12 元素索引, 4 一次计算长度 */
150 michael_block(msb, lsb);
151
152 /* first buffer has special handling */
153 const hi_u8 *puc_data = oal_netbuf_data(netbuf) + offset;
154 hi_u32 space = oal_netbuf_len(netbuf) - offset;
155
156 for (;;) {
157 space = (space > data_len) ? data_len : space;
158
159 /* collect 32-bit blocks from current buffer */
160 while (space >= sizeof(hi_u32)) {
161 msb ^= get_le32(puc_data, 4); /* 4 一次计算长度 */
162 michael_block(msb, lsb);
163
164 puc_data += sizeof(hi_u32);
165 space -= sizeof(hi_u32);
166 data_len -= sizeof(hi_u32);
167 }
168
169 if (data_len < sizeof(hi_u32)) {
170 break;
171 }
172
173 netbuf = oal_netbuf_list_next(netbuf);
174 if (netbuf == NULL) {
175 return HI_ERR_CODE_SECURITY_BUFF_NUM;
176 }
177
178 if (space != 0) {
179 /*
180 * Block straddles buffers, split references.
181 */
182 const hi_u8 *puc_data_next = oal_netbuf_data(netbuf);
183 if ((sizeof(hi_u32) - space) > oal_netbuf_len(netbuf)) {
184 return HI_ERR_CODE_SECURITY_BUFF_LEN;
185 }
186
187 if (space == 1) {
188 msb ^= get_le32_split(puc_data[0], puc_data_next[0], puc_data_next[1], puc_data_next[2]); /* 2 */
189 puc_data = puc_data_next + 3; /* 3 用于计算 */
190 space = oal_netbuf_len(netbuf) - 3; /* 3 用于计算 */
191 } else if (space == 2) { /* 2 case 标志 */
192 msb ^= get_le32_split(puc_data[0], puc_data[1], puc_data_next[0], puc_data_next[1]);
193 puc_data = puc_data_next + 2; /* 2 用于计算 */
194 space = oal_netbuf_len(netbuf) - 2; /* 2 用于计算 */
195 } else if (space == 3) { /* 3 case 标志 */
196 msb ^= get_le32_split(puc_data[0], puc_data[1], puc_data[2], puc_data_next[0]); /* 2 元素索引 */
197 puc_data = puc_data_next + 1;
198 space = oal_netbuf_len(netbuf) - 1;
199 }
200
201 michael_block(msb, lsb);
202 data_len -= sizeof(hi_u32);
203 } else {
204 /*
205 * Setup for next buffer.
206 */
207 puc_data = oal_netbuf_data(netbuf);
208 space = oal_netbuf_len(netbuf);
209 }
210 }
211
212 /* Last block and padding (0x5a, 4..7 x 0) */
213 if (data_len == 0) {
214 msb ^= get_le32_split(0x5a, 0, 0, 0);
215 } else if (data_len == 1) {
216 msb ^= get_le32_split(puc_data[0], 0x5a, 0, 0);
217 } else if (data_len == 2) { /* 2 case 标志 */
218 msb ^= get_le32_split(puc_data[0], puc_data[1], 0x5a, 0);
219 } else if (data_len == 3) { /* 3 case 标志 */
220 msb ^= get_le32_split(puc_data[0], puc_data[1], puc_data[2], 0x5a); /* 2 数组索引 */
221 }
222
223 michael_block(msb, lsb);
224 /* l ^= 0; */
225 michael_block(msb, lsb);
226
227 put_le32(michael_mic_info->puc_mic, msb);
228 put_le32(michael_mic_info->puc_mic + 4, lsb); /* 4 偏置项 */
229
230 return HI_SUCCESS;
231 }
232
hmac_crypto_tkip_enmic_key(wlan_priv_key_param_stru * key,oal_netbuf_stru * netbuf,const hmac_tx_ctl_stru * cb,hi_u32 pktlen)233 hi_u32 hmac_crypto_tkip_enmic_key(wlan_priv_key_param_stru *key, oal_netbuf_stru *netbuf, const hmac_tx_ctl_stru *cb,
234 hi_u32 pktlen)
235 {
236 hi_u8 auc_mic[IEEE80211_WEP_MICLEN] = { 0 };
237 hmac_michael_mic_info_stru michael_mic_info;
238
239 /* 3.1 获取mic及密钥 */
240 hi_u8 *puc_mic_tail = (hi_u8 *)OAL_NETBUF_TAIL(netbuf);
241 hi_u8 *puc_tx_mic_key = key->auc_key + WLAN_TEMPORAL_KEY_LENGTH;
242
243 oal_netbuf_put(netbuf, IEEE80211_WEP_MICLEN);
244
245 /* 4.1 计算mic */
246 michael_mic_info.offset = cb->frame_header_length;
247 michael_mic_info.data_len = pktlen - cb->frame_header_length;
248 michael_mic_info.puc_mic = auc_mic;
249 hi_u32 ret = hmac_crypto_tkip_michael_mic(puc_tx_mic_key, netbuf, cb->frame_header, &michael_mic_info);
250 if (ret != HI_SUCCESS) {
251 return ret;
252 }
253
254 /* 4.1 拷贝mic到帧尾部 */
255 if (memcpy_s(puc_mic_tail, IEEE80211_WEP_MICLEN, auc_mic, IEEE80211_WEP_MICLEN) != EOK) {
256 oam_error_log0(0, OAM_SF_CFG, "hmac_crypto_tkip_enmic:: auc_mic memcpy_s fail.");
257 return HI_FAIL;
258 }
259
260 return HI_SUCCESS;
261 }
262
263 /* ****************************************************************************
264 功能描述 : 添加tikip mic校验
265 输出参数 : hi_u32
266 返 回 值 : 0:成功,其他:失败
267 修改历史 :
268 1.日 期 : 2014年3月3日
269 作 者 : HiSilicon
270 修改内容 : 新生成函数
271 **************************************************************************** */
hmac_crypto_tkip_enmic(wlan_priv_key_param_stru * key,oal_netbuf_stru * netbuf)272 hi_u32 hmac_crypto_tkip_enmic(wlan_priv_key_param_stru *key, oal_netbuf_stru *netbuf)
273 {
274 if (((hi_u8)key->cipher) != WLAN_80211_CIPHER_SUITE_TKIP) {
275 return HI_ERR_CODE_SECURITY_CHIPER_TYPE;
276 }
277
278 /* 1.1 计算整个报文的长度,不处理存在多个netbuf的情况 */
279 hi_u32 pktlen = oal_netbuf_len(netbuf);
280 if (oal_netbuf_next(netbuf) != HI_NULL) {
281 return HI_ERR_CODE_SECURITY_BUFF_NUM;
282 }
283
284 hmac_tx_ctl_stru *cb = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
285
286 /* 2.1 在netbuf上增加mic空间 */
287 if (oal_netbuf_tailroom(netbuf) < IEEE80211_WEP_MICLEN) {
288 /* 2.2 如果原来的netbuf长度不够,需要重新申请 */
289 #ifdef _PRE_LWIP_ZERO_COPY
290 /* 零拷贝时,尾部空间不足需要往前扩展 */
291 if ((netbuf->mem_head != HI_NULL) && (oal_netbuf_headroom(netbuf) > IEEE80211_WEP_MICLEN)) {
292 hi_u8 *tmp_buff = oal_memalloc(pktlen);
293 if (tmp_buff == HI_NULL) {
294 return HI_ERR_CODE_PTR_NULL;
295 }
296 if (memcpy_s(tmp_buff, pktlen, oal_netbuf_data(netbuf), pktlen) != EOK) {
297 oal_free(tmp_buff);
298 return HI_FAIL;
299 }
300 netbuf->data -= IEEE80211_WEP_MICLEN;
301 netbuf->tail -= IEEE80211_WEP_MICLEN;
302 if (memcpy_s(oal_netbuf_data(netbuf), pktlen, tmp_buff, pktlen) != EOK) {
303 oal_free(tmp_buff);
304 return HI_FAIL;
305 }
306 oal_free(tmp_buff);
307 } else {
308 #endif /* #ifdef _PRE_LWIP_ZERO_COPY */
309 /* sbkbuff时,直接往后扩展 */
310 oam_error_log0(0, 0, "hmac_crypto_tkip_enmic:: netbuf is exceptional!");
311 netbuf = oal_netbuf_realloc_tailroom(netbuf, IEEE80211_WEP_MICLEN);
312 if (netbuf == HI_NULL) {
313 return HI_ERR_CODE_PTR_NULL;
314 }
315 #ifdef _PRE_LWIP_ZERO_COPY
316 }
317 #endif
318 /* 扩展后MAC_HDR地址有变化,需要更新 */
319 if (cb->mac_head_type == 1) {
320 cb->frame_header = (mac_ieee80211_frame_stru *)oal_netbuf_header(netbuf);
321 }
322 }
323
324 return hmac_crypto_tkip_enmic_key(key, netbuf, cb, pktlen);
325 }
326
327 /* ****************************************************************************
328 功能描述 : 比较tkip mic校验,并剥掉mic尾
329 输出参数 : hi_u32
330 返 回 值 : 0:成功,其他:失败
331 修改历史 :
332 1.日 期 : 2014年3月3日
333 作 者 : HiSilicon
334 修改内容 : 新生成函数
335 **************************************************************************** */
hmac_crypto_tkip_demic(wlan_priv_key_param_stru * key,oal_netbuf_stru * netbuf)336 hi_u32 hmac_crypto_tkip_demic(wlan_priv_key_param_stru *key, oal_netbuf_stru *netbuf)
337 {
338 hmac_rx_ctl_stru *cb = HI_NULL;
339 hi_u32 hdrlen; /* 接收时,ul_pktlen里包含80211mac头 */
340 hi_u8 *puc_rx_mic_key = HI_NULL;
341 hi_u32 ret;
342 hi_u32 pktlen;
343 hi_u8 auc_mic[IEEE80211_WEP_MICLEN] = { 0 };
344 hi_u8 auc_mic_peer[IEEE80211_WEP_MICLEN] = { 0 };
345 hmac_michael_mic_info_stru michael_mic_info;
346
347 if (WLAN_80211_CIPHER_SUITE_TKIP != ((hi_u8)key->cipher)) {
348 return HI_ERR_CODE_SECURITY_CHIPER_TYPE;
349 }
350
351 /* 1.1 计算整个报文的长度,不处理存在多个netbuf的情况 */
352 pktlen = oal_netbuf_len(netbuf);
353 if (HI_NULL != oal_netbuf_list_next(netbuf)) {
354 return HI_ERR_CODE_SECURITY_BUFF_NUM;
355 }
356
357 /* 2.1 从CB中获取80211头长度 */
358 cb = (hmac_rx_ctl_stru *)oal_netbuf_cb(netbuf);
359 hdrlen = cb->mac_header_len;
360
361 /* 3.1 只处理数据帧 */
362 /* 4.1 获取解密密钥,接收密钥需要偏移8个字节 */
363 puc_rx_mic_key = key->auc_key + WLAN_TEMPORAL_KEY_LENGTH + WLAN_MIC_KEY_LENGTH;
364
365 /* 5.1 计算mic */
366 michael_mic_info.offset = hdrlen;
367 michael_mic_info.data_len = pktlen - (hdrlen + IEEE80211_WEP_MICLEN);
368 michael_mic_info.puc_mic = auc_mic;
369 ret = hmac_crypto_tkip_michael_mic(puc_rx_mic_key, netbuf,
370 (mac_ieee80211_frame_stru *)cb->pul_mac_hdr_start_addr, &michael_mic_info);
371 if (ret != HI_SUCCESS) {
372 return ret;
373 }
374
375 /* 6.1 获取对端的mic并跟本地计算的mic进行比较 */
376 ret = oal_netbuf_copydata(netbuf, pktlen - IEEE80211_WEP_MICLEN, (hi_void *)auc_mic_peer, IEEE80211_WEP_MICLEN,
377 IEEE80211_WEP_MICLEN);
378 if (ret != HI_SUCCESS) {
379 return ret;
380 }
381
382 if (memcmp(auc_mic, auc_mic_peer, IEEE80211_WEP_MICLEN)) {
383 return HI_ERR_CODE_SECURITY_WRONG_KEY;
384 }
385
386 /* 7.1 去掉mic尾部 */
387 oal_netbuf_trim(netbuf, IEEE80211_WEP_MICLEN);
388 return HI_SUCCESS;
389 }
390
391 #ifdef __cplusplus
392 #if __cplusplus
393 }
394 #endif
395 #endif
396