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