1554c0a3aSHans de Goede /******************************************************************************
2554c0a3aSHans de Goede  *
3554c0a3aSHans de Goede  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4554c0a3aSHans de Goede  *
5554c0a3aSHans de Goede  * This program is free software; you can redistribute it and/or modify it
6554c0a3aSHans de Goede  * under the terms of version 2 of the GNU General Public License as
7554c0a3aSHans de Goede  * published by the Free Software Foundation.
8554c0a3aSHans de Goede  *
9554c0a3aSHans de Goede  * This program is distributed in the hope that it will be useful, but WITHOUT
10554c0a3aSHans de Goede  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11554c0a3aSHans de Goede  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12554c0a3aSHans de Goede  * more details.
13554c0a3aSHans de Goede  *
14554c0a3aSHans de Goede  ******************************************************************************/
15554c0a3aSHans de Goede #define  _RTW_SECURITY_C_
16554c0a3aSHans de Goede 
17554c0a3aSHans de Goede #include <drv_types.h>
18554c0a3aSHans de Goede #include <rtw_debug.h>
19554c0a3aSHans de Goede 
20554c0a3aSHans de Goede static const char *_security_type_str[] = {
21554c0a3aSHans de Goede 	"N/A",
22554c0a3aSHans de Goede 	"WEP40",
23554c0a3aSHans de Goede 	"TKIP",
24554c0a3aSHans de Goede 	"TKIP_WM",
25554c0a3aSHans de Goede 	"AES",
26554c0a3aSHans de Goede 	"WEP104",
27554c0a3aSHans de Goede 	"SMS4",
28554c0a3aSHans de Goede 	"WEP_WPA",
29554c0a3aSHans de Goede 	"BIP",
30554c0a3aSHans de Goede };
31554c0a3aSHans de Goede 
32554c0a3aSHans de Goede const char *security_type_str(u8 value)
33554c0a3aSHans de Goede {
34554c0a3aSHans de Goede 	if (value <= _BIP_)
35554c0a3aSHans de Goede 		return _security_type_str[value];
36554c0a3aSHans de Goede 	return NULL;
37554c0a3aSHans de Goede }
38554c0a3aSHans de Goede 
39554c0a3aSHans de Goede #ifdef DBG_SW_SEC_CNT
40554c0a3aSHans de Goede #define WEP_SW_ENC_CNT_INC(sec, ra) \
41554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
42554c0a3aSHans de Goede 		sec->wep_sw_enc_cnt_bc++; \
43554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
44554c0a3aSHans de Goede 		sec->wep_sw_enc_cnt_mc++; \
45554c0a3aSHans de Goede 	else \
46554c0a3aSHans de Goede 		sec->wep_sw_enc_cnt_uc++;
47554c0a3aSHans de Goede 
48554c0a3aSHans de Goede #define WEP_SW_DEC_CNT_INC(sec, ra) \
49554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
50554c0a3aSHans de Goede 		sec->wep_sw_dec_cnt_bc++; \
51554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
52554c0a3aSHans de Goede 		sec->wep_sw_dec_cnt_mc++; \
53554c0a3aSHans de Goede 	else \
54554c0a3aSHans de Goede 		sec->wep_sw_dec_cnt_uc++;
55554c0a3aSHans de Goede 
56554c0a3aSHans de Goede #define TKIP_SW_ENC_CNT_INC(sec, ra) \
57554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
58554c0a3aSHans de Goede 		sec->tkip_sw_enc_cnt_bc++; \
59554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
60554c0a3aSHans de Goede 		sec->tkip_sw_enc_cnt_mc++; \
61554c0a3aSHans de Goede 	else \
62554c0a3aSHans de Goede 		sec->tkip_sw_enc_cnt_uc++;
63554c0a3aSHans de Goede 
64554c0a3aSHans de Goede #define TKIP_SW_DEC_CNT_INC(sec, ra) \
65554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
66554c0a3aSHans de Goede 		sec->tkip_sw_dec_cnt_bc++; \
67554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
68554c0a3aSHans de Goede 		sec->tkip_sw_dec_cnt_mc++; \
69554c0a3aSHans de Goede 	else \
70554c0a3aSHans de Goede 		sec->tkip_sw_dec_cnt_uc++;
71554c0a3aSHans de Goede 
72554c0a3aSHans de Goede #define AES_SW_ENC_CNT_INC(sec, ra) \
73554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
74554c0a3aSHans de Goede 		sec->aes_sw_enc_cnt_bc++; \
75554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
76554c0a3aSHans de Goede 		sec->aes_sw_enc_cnt_mc++; \
77554c0a3aSHans de Goede 	else \
78554c0a3aSHans de Goede 		sec->aes_sw_enc_cnt_uc++;
79554c0a3aSHans de Goede 
80554c0a3aSHans de Goede #define AES_SW_DEC_CNT_INC(sec, ra) \
81554c0a3aSHans de Goede 	if (is_broadcast_mac_addr(ra)) \
82554c0a3aSHans de Goede 		sec->aes_sw_dec_cnt_bc++; \
83554c0a3aSHans de Goede 	else if (is_multicast_mac_addr(ra)) \
84554c0a3aSHans de Goede 		sec->aes_sw_dec_cnt_mc++; \
85554c0a3aSHans de Goede 	else \
86554c0a3aSHans de Goede 		sec->aes_sw_dec_cnt_uc++;
87554c0a3aSHans de Goede #else
88554c0a3aSHans de Goede #define WEP_SW_ENC_CNT_INC(sec, ra)
89554c0a3aSHans de Goede #define WEP_SW_DEC_CNT_INC(sec, ra)
90554c0a3aSHans de Goede #define TKIP_SW_ENC_CNT_INC(sec, ra)
91554c0a3aSHans de Goede #define TKIP_SW_DEC_CNT_INC(sec, ra)
92554c0a3aSHans de Goede #define AES_SW_ENC_CNT_INC(sec, ra)
93554c0a3aSHans de Goede #define AES_SW_DEC_CNT_INC(sec, ra)
94554c0a3aSHans de Goede #endif /* DBG_SW_SEC_CNT */
95554c0a3aSHans de Goede 
96554c0a3aSHans de Goede /* WEP related ===== */
97554c0a3aSHans de Goede 
98554c0a3aSHans de Goede #define CRC32_POLY 0x04c11db7
99554c0a3aSHans de Goede 
100554c0a3aSHans de Goede struct arc4context {
101554c0a3aSHans de Goede 	u32 x;
102554c0a3aSHans de Goede 	u32 y;
103554c0a3aSHans de Goede 	u8 state[256];
104554c0a3aSHans de Goede };
105554c0a3aSHans de Goede 
106554c0a3aSHans de Goede 
107554c0a3aSHans de Goede static void arcfour_init(struct arc4context	*parc4ctx, u8 *key, u32 key_len)
108554c0a3aSHans de Goede {
109554c0a3aSHans de Goede 	u32 t, u;
110554c0a3aSHans de Goede 	u32 keyindex;
111554c0a3aSHans de Goede 	u32 stateindex;
112554c0a3aSHans de Goede 	u8 *state;
113554c0a3aSHans de Goede 	u32 counter;
114554c0a3aSHans de Goede 
115554c0a3aSHans de Goede 	state = parc4ctx->state;
116554c0a3aSHans de Goede 	parc4ctx->x = 0;
117554c0a3aSHans de Goede 	parc4ctx->y = 0;
118554c0a3aSHans de Goede 	for (counter = 0; counter < 256; counter++)
119554c0a3aSHans de Goede 		state[counter] = (u8)counter;
120554c0a3aSHans de Goede 	keyindex = 0;
121554c0a3aSHans de Goede 	stateindex = 0;
122554c0a3aSHans de Goede 	for (counter = 0; counter < 256; counter++) {
123554c0a3aSHans de Goede 		t = state[counter];
124554c0a3aSHans de Goede 		stateindex = (stateindex + key[keyindex] + t) & 0xff;
125554c0a3aSHans de Goede 		u = state[stateindex];
126554c0a3aSHans de Goede 		state[stateindex] = (u8)t;
127554c0a3aSHans de Goede 		state[counter] = (u8)u;
128554c0a3aSHans de Goede 		if (++keyindex >= key_len)
129554c0a3aSHans de Goede 			keyindex = 0;
130554c0a3aSHans de Goede 	}
131554c0a3aSHans de Goede }
132554c0a3aSHans de Goede 
133554c0a3aSHans de Goede static u32 arcfour_byte(struct arc4context	*parc4ctx)
134554c0a3aSHans de Goede {
135554c0a3aSHans de Goede 	u32 x;
136554c0a3aSHans de Goede 	u32 y;
137554c0a3aSHans de Goede 	u32 sx, sy;
138554c0a3aSHans de Goede 	u8 *state;
139554c0a3aSHans de Goede 
140554c0a3aSHans de Goede 	state = parc4ctx->state;
141554c0a3aSHans de Goede 	x = (parc4ctx->x + 1) & 0xff;
142554c0a3aSHans de Goede 	sx = state[x];
143554c0a3aSHans de Goede 	y = (sx + parc4ctx->y) & 0xff;
144554c0a3aSHans de Goede 	sy = state[y];
145554c0a3aSHans de Goede 	parc4ctx->x = x;
146554c0a3aSHans de Goede 	parc4ctx->y = y;
147554c0a3aSHans de Goede 	state[y] = (u8)sx;
148554c0a3aSHans de Goede 	state[x] = (u8)sy;
149554c0a3aSHans de Goede 	return state[(sx + sy) & 0xff];
150554c0a3aSHans de Goede }
151554c0a3aSHans de Goede 
152554c0a3aSHans de Goede static void arcfour_encrypt(
153554c0a3aSHans de Goede 	struct arc4context *parc4ctx,
154554c0a3aSHans de Goede 	u8 *dest,
155554c0a3aSHans de Goede 	u8 *src,
156554c0a3aSHans de Goede 	u32 len
157554c0a3aSHans de Goede )
158554c0a3aSHans de Goede {
159554c0a3aSHans de Goede 	u32 i;
160554c0a3aSHans de Goede 
161554c0a3aSHans de Goede 	for (i = 0; i < len; i++)
162554c0a3aSHans de Goede 		dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
163554c0a3aSHans de Goede }
164554c0a3aSHans de Goede 
165554c0a3aSHans de Goede static sint bcrc32initialized = 0;
166554c0a3aSHans de Goede static u32 crc32_table[256];
167554c0a3aSHans de Goede 
168554c0a3aSHans de Goede 
169554c0a3aSHans de Goede static u8 crc32_reverseBit(u8 data)
170554c0a3aSHans de Goede {
171554c0a3aSHans de Goede 	return((u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01));
172554c0a3aSHans de Goede }
173554c0a3aSHans de Goede 
174554c0a3aSHans de Goede static void crc32_init(void)
175554c0a3aSHans de Goede {
176554c0a3aSHans de Goede 	if (bcrc32initialized == 1)
177554c0a3aSHans de Goede 		return;
178554c0a3aSHans de Goede 	else {
179554c0a3aSHans de Goede 		sint i, j;
180554c0a3aSHans de Goede 		u32 c;
181554c0a3aSHans de Goede 		u8 *p = (u8 *)&c, *p1;
182554c0a3aSHans de Goede 		u8 k;
183554c0a3aSHans de Goede 
184554c0a3aSHans de Goede 		c = 0x12340000;
185554c0a3aSHans de Goede 
186554c0a3aSHans de Goede 		for (i = 0; i < 256; ++i) {
187554c0a3aSHans de Goede 			k = crc32_reverseBit((u8)i);
188554c0a3aSHans de Goede 			for (c = ((u32)k) << 24, j = 8; j > 0; --j) {
189554c0a3aSHans de Goede 				c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
190554c0a3aSHans de Goede 			}
191554c0a3aSHans de Goede 			p1 = (u8 *)&crc32_table[i];
192554c0a3aSHans de Goede 
193554c0a3aSHans de Goede 			p1[0] = crc32_reverseBit(p[3]);
194554c0a3aSHans de Goede 			p1[1] = crc32_reverseBit(p[2]);
195554c0a3aSHans de Goede 			p1[2] = crc32_reverseBit(p[1]);
196554c0a3aSHans de Goede 			p1[3] = crc32_reverseBit(p[0]);
197554c0a3aSHans de Goede 		}
198554c0a3aSHans de Goede 		bcrc32initialized = 1;
199554c0a3aSHans de Goede 	}
200554c0a3aSHans de Goede }
201554c0a3aSHans de Goede 
202554c0a3aSHans de Goede static __le32 getcrc32(u8 *buf, sint len)
203554c0a3aSHans de Goede {
204554c0a3aSHans de Goede 	u8 *p;
205554c0a3aSHans de Goede 	u32  crc;
206554c0a3aSHans de Goede 
207554c0a3aSHans de Goede 	if (bcrc32initialized == 0)
208554c0a3aSHans de Goede 		crc32_init();
209554c0a3aSHans de Goede 
210554c0a3aSHans de Goede 	crc = 0xffffffff;       /* preload shift register, per CRC-32 spec */
211554c0a3aSHans de Goede 
212554c0a3aSHans de Goede 	for (p = buf; len > 0; ++p, --len) {
213554c0a3aSHans de Goede 		crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
214554c0a3aSHans de Goede 	}
215554c0a3aSHans de Goede 	return cpu_to_le32(~crc);    /* transmit complement, per CRC-32 spec */
216554c0a3aSHans de Goede }
217554c0a3aSHans de Goede 
218554c0a3aSHans de Goede 
219554c0a3aSHans de Goede /*
220554c0a3aSHans de Goede 	Need to consider the fragment  situation
221554c0a3aSHans de Goede */
222554c0a3aSHans de Goede void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
223554c0a3aSHans de Goede {																	/*  exclude ICV */
224554c0a3aSHans de Goede 
225554c0a3aSHans de Goede 	unsigned char crc[4];
226554c0a3aSHans de Goede 	struct arc4context	 mycontext;
227554c0a3aSHans de Goede 
228554c0a3aSHans de Goede 	sint	curfragnum, length;
229554c0a3aSHans de Goede 	u32 keylength;
230554c0a3aSHans de Goede 
231554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv;    /* wepkey */
232554c0a3aSHans de Goede 	u8 wepkey[16];
233554c0a3aSHans de Goede 	u8   hw_hdr_offset = 0;
234554c0a3aSHans de Goede 	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
235554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
236554c0a3aSHans de Goede 	struct	xmit_priv 	*pxmitpriv = &padapter->xmitpriv;
237554c0a3aSHans de Goede 
238554c0a3aSHans de Goede 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
239554c0a3aSHans de Goede 		return;
240554c0a3aSHans de Goede 
241554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
242554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
243554c0a3aSHans de Goede 
244554c0a3aSHans de Goede 	/* start to encrypt each fragment */
245554c0a3aSHans de Goede 	if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
246554c0a3aSHans de Goede 		keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
247554c0a3aSHans de Goede 
248554c0a3aSHans de Goede 		for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
249554c0a3aSHans de Goede 			iv = pframe+pattrib->hdrlen;
250554c0a3aSHans de Goede 			memcpy(&wepkey[0], iv, 3);
251554c0a3aSHans de Goede 			memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength);
252554c0a3aSHans de Goede 			payload = pframe+pattrib->iv_len+pattrib->hdrlen;
253554c0a3aSHans de Goede 
254554c0a3aSHans de Goede 			if ((curfragnum+1) == pattrib->nr_frags) {	/* the last fragment */
255554c0a3aSHans de Goede 
256554c0a3aSHans de Goede 				length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
257554c0a3aSHans de Goede 
258554c0a3aSHans de Goede 				*((__le32 *)crc) = getcrc32(payload, length);
259554c0a3aSHans de Goede 
260554c0a3aSHans de Goede 				arcfour_init(&mycontext, wepkey, 3+keylength);
261554c0a3aSHans de Goede 				arcfour_encrypt(&mycontext, payload, payload, length);
262554c0a3aSHans de Goede 				arcfour_encrypt(&mycontext, payload+length, crc, 4);
263554c0a3aSHans de Goede 
264554c0a3aSHans de Goede 			} else{
265554c0a3aSHans de Goede 			length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
266554c0a3aSHans de Goede 				*((__le32 *)crc) = getcrc32(payload, length);
267554c0a3aSHans de Goede 				arcfour_init(&mycontext, wepkey, 3+keylength);
268554c0a3aSHans de Goede 				arcfour_encrypt(&mycontext, payload, payload, length);
269554c0a3aSHans de Goede 				arcfour_encrypt(&mycontext, payload+length, crc, 4);
270554c0a3aSHans de Goede 
271554c0a3aSHans de Goede 			pframe += pxmitpriv->frag_len;
272554c0a3aSHans de Goede 			pframe = (u8 *)RND4((SIZE_PTR)(pframe));
273554c0a3aSHans de Goede 
274554c0a3aSHans de Goede 			}
275554c0a3aSHans de Goede 
276554c0a3aSHans de Goede 		}
277554c0a3aSHans de Goede 
278554c0a3aSHans de Goede 		WEP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
279554c0a3aSHans de Goede 	}
280554c0a3aSHans de Goede }
281554c0a3aSHans de Goede 
282554c0a3aSHans de Goede void rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
283554c0a3aSHans de Goede {
284554c0a3aSHans de Goede 	/*  exclude ICV */
285554c0a3aSHans de Goede 	u8 crc[4];
286554c0a3aSHans de Goede 	struct arc4context	 mycontext;
287554c0a3aSHans de Goede 	sint	length;
288554c0a3aSHans de Goede 	u32 keylength;
289554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, wepkey[16];
290554c0a3aSHans de Goede 	u8  keyindex;
291554c0a3aSHans de Goede 	struct	rx_pkt_attrib	 *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib);
292554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
293554c0a3aSHans de Goede 
294554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
295554c0a3aSHans de Goede 
296554c0a3aSHans de Goede 	/* start to decrypt recvframe */
297554c0a3aSHans de Goede 	if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
298554c0a3aSHans de Goede 		iv = pframe+prxattrib->hdrlen;
299554c0a3aSHans de Goede 		/* keyindex =(iv[3]&0x3); */
300554c0a3aSHans de Goede 		keyindex = prxattrib->key_index;
301554c0a3aSHans de Goede 		keylength = psecuritypriv->dot11DefKeylen[keyindex];
302554c0a3aSHans de Goede 		memcpy(&wepkey[0], iv, 3);
303554c0a3aSHans de Goede 		/* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */
304554c0a3aSHans de Goede 		memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
305554c0a3aSHans de Goede 		length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
306554c0a3aSHans de Goede 
307554c0a3aSHans de Goede 		payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
308554c0a3aSHans de Goede 
309554c0a3aSHans de Goede 		/* decrypt payload include icv */
310554c0a3aSHans de Goede 		arcfour_init(&mycontext, wepkey, 3+keylength);
311554c0a3aSHans de Goede 		arcfour_encrypt(&mycontext, payload, payload,  length);
312554c0a3aSHans de Goede 
313554c0a3aSHans de Goede 		/* calculate icv and compare the icv */
314554c0a3aSHans de Goede 		*((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
315554c0a3aSHans de Goede 
316554c0a3aSHans de Goede 		if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
317554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
318554c0a3aSHans de Goede 						crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
319554c0a3aSHans de Goede 		}
320554c0a3aSHans de Goede 
321554c0a3aSHans de Goede 		WEP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
322554c0a3aSHans de Goede 	}
323554c0a3aSHans de Goede 	return;
324554c0a3aSHans de Goede }
325554c0a3aSHans de Goede 
326554c0a3aSHans de Goede /* 3		=====TKIP related ===== */
327554c0a3aSHans de Goede 
328554c0a3aSHans de Goede static u32 secmicgetuint32(u8 *p)
329554c0a3aSHans de Goede /*  Convert from Byte[] to Us3232 in a portable way */
330554c0a3aSHans de Goede {
331554c0a3aSHans de Goede 	s32 i;
332554c0a3aSHans de Goede 	u32 res = 0;
333554c0a3aSHans de Goede 
334554c0a3aSHans de Goede 	for (i = 0; i < 4; i++) {
335554c0a3aSHans de Goede 		res |= ((u32)(*p++)) << (8*i);
336554c0a3aSHans de Goede 	}
337554c0a3aSHans de Goede 
338554c0a3aSHans de Goede 	return res;
339554c0a3aSHans de Goede }
340554c0a3aSHans de Goede 
341554c0a3aSHans de Goede static void secmicputuint32(u8 *p, u32 val)
342554c0a3aSHans de Goede /*  Convert from Us3232 to Byte[] in a portable way */
343554c0a3aSHans de Goede {
344554c0a3aSHans de Goede 	long i;
345554c0a3aSHans de Goede 
346554c0a3aSHans de Goede 	for (i = 0; i < 4; i++) {
347554c0a3aSHans de Goede 		*p++ = (u8) (val & 0xff);
348554c0a3aSHans de Goede 		val >>= 8;
349554c0a3aSHans de Goede 	}
350554c0a3aSHans de Goede }
351554c0a3aSHans de Goede 
352554c0a3aSHans de Goede static void secmicclear(struct mic_data *pmicdata)
353554c0a3aSHans de Goede {
354554c0a3aSHans de Goede /*  Reset the state to the empty message. */
355554c0a3aSHans de Goede 	pmicdata->L = pmicdata->K0;
356554c0a3aSHans de Goede 	pmicdata->R = pmicdata->K1;
357554c0a3aSHans de Goede 	pmicdata->nBytesInM = 0;
358554c0a3aSHans de Goede 	pmicdata->M = 0;
359554c0a3aSHans de Goede }
360554c0a3aSHans de Goede 
361554c0a3aSHans de Goede void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
362554c0a3aSHans de Goede {
363554c0a3aSHans de Goede 	/*  Set the key */
364554c0a3aSHans de Goede 	pmicdata->K0 = secmicgetuint32(key);
365554c0a3aSHans de Goede 	pmicdata->K1 = secmicgetuint32(key + 4);
366554c0a3aSHans de Goede 	/*  and reset the message */
367554c0a3aSHans de Goede 	secmicclear(pmicdata);
368554c0a3aSHans de Goede }
369554c0a3aSHans de Goede 
370554c0a3aSHans de Goede void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
371554c0a3aSHans de Goede {
372554c0a3aSHans de Goede 	/*  Append the byte to our word-sized buffer */
373554c0a3aSHans de Goede 	pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
374554c0a3aSHans de Goede 	pmicdata->nBytesInM++;
375554c0a3aSHans de Goede 	/*  Process the word if it is full. */
376554c0a3aSHans de Goede 	if (pmicdata->nBytesInM >= 4) {
377554c0a3aSHans de Goede 		pmicdata->L ^= pmicdata->M;
378554c0a3aSHans de Goede 		pmicdata->R ^= ROL32(pmicdata->L, 17);
379554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
380554c0a3aSHans de Goede 		pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
381554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
382554c0a3aSHans de Goede 		pmicdata->R ^= ROL32(pmicdata->L, 3);
383554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
384554c0a3aSHans de Goede 		pmicdata->R ^= ROR32(pmicdata->L, 2);
385554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
386554c0a3aSHans de Goede 		/*  Clear the buffer */
387554c0a3aSHans de Goede 		pmicdata->M = 0;
388554c0a3aSHans de Goede 		pmicdata->nBytesInM = 0;
389554c0a3aSHans de Goede 	}
390554c0a3aSHans de Goede }
391554c0a3aSHans de Goede 
392554c0a3aSHans de Goede void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
393554c0a3aSHans de Goede {
394554c0a3aSHans de Goede 	/*  This is simple */
395554c0a3aSHans de Goede 	while (nbytes > 0) {
396554c0a3aSHans de Goede 		rtw_secmicappendbyte(pmicdata, *src++);
397554c0a3aSHans de Goede 		nbytes--;
398554c0a3aSHans de Goede 	}
399554c0a3aSHans de Goede }
400554c0a3aSHans de Goede 
401554c0a3aSHans de Goede void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
402554c0a3aSHans de Goede {
403554c0a3aSHans de Goede 	/*  Append the minimum padding */
404554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0x5a);
405554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
406554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
407554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
408554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
409554c0a3aSHans de Goede 	/*  and then zeroes until the length is a multiple of 4 */
410554c0a3aSHans de Goede 	while (pmicdata->nBytesInM != 0) {
411554c0a3aSHans de Goede 		rtw_secmicappendbyte(pmicdata, 0);
412554c0a3aSHans de Goede 	}
413554c0a3aSHans de Goede 	/*  The appendByte function has already computed the result. */
414554c0a3aSHans de Goede 	secmicputuint32(dst, pmicdata->L);
415554c0a3aSHans de Goede 	secmicputuint32(dst+4, pmicdata->R);
416554c0a3aSHans de Goede 	/*  Reset to the empty message. */
417554c0a3aSHans de Goede 	secmicclear(pmicdata);
418554c0a3aSHans de Goede }
419554c0a3aSHans de Goede 
420554c0a3aSHans de Goede 
421554c0a3aSHans de Goede void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
422554c0a3aSHans de Goede {
423554c0a3aSHans de Goede 
424554c0a3aSHans de Goede 	struct mic_data	micdata;
425554c0a3aSHans de Goede 	u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
426554c0a3aSHans de Goede 
427554c0a3aSHans de Goede 	rtw_secmicsetkey(&micdata, key);
428554c0a3aSHans de Goede 	priority[0] = pri;
429554c0a3aSHans de Goede 
430554c0a3aSHans de Goede 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
431554c0a3aSHans de Goede 	if (header[1]&1) {   /* ToDS == 1 */
432554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[16], 6);  /* DA */
433554c0a3aSHans de Goede 		if (header[1]&2)  /* From Ds == 1 */
434554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[24], 6);
435554c0a3aSHans de Goede 		else
436554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[10], 6);
437554c0a3aSHans de Goede 	} else {	/* ToDS == 0 */
438554c0a3aSHans de Goede 		rtw_secmicappend(&micdata, &header[4], 6);   /* DA */
439554c0a3aSHans de Goede 		if (header[1]&2)  /* From Ds == 1 */
440554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[16], 6);
441554c0a3aSHans de Goede 		else
442554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[10], 6);
443554c0a3aSHans de Goede 
444554c0a3aSHans de Goede 	}
445554c0a3aSHans de Goede 	rtw_secmicappend(&micdata, &priority[0], 4);
446554c0a3aSHans de Goede 
447554c0a3aSHans de Goede 
448554c0a3aSHans de Goede 	rtw_secmicappend(&micdata, data, data_len);
449554c0a3aSHans de Goede 
450554c0a3aSHans de Goede 	rtw_secgetmic(&micdata, mic_code);
451554c0a3aSHans de Goede }
452554c0a3aSHans de Goede 
453554c0a3aSHans de Goede /* macros for extraction/creation of unsigned char/unsigned short values  */
454554c0a3aSHans de Goede #define RotR1(v16)   ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
455554c0a3aSHans de Goede #define   Lo8(v16)   ((u8)((v16)       & 0x00FF))
456554c0a3aSHans de Goede #define   Hi8(v16)   ((u8)(((v16) >> 8) & 0x00FF))
457554c0a3aSHans de Goede #define  Lo16(v32)   ((u16)((v32)       & 0xFFFF))
458554c0a3aSHans de Goede #define  Hi16(v32)   ((u16)(((v32) >> 16) & 0xFFFF))
459554c0a3aSHans de Goede #define  Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
460554c0a3aSHans de Goede 
461554c0a3aSHans de Goede /* select the Nth 16-bit word of the temporal key unsigned char array TK[]   */
462554c0a3aSHans de Goede #define  TK16(N)     Mk16(tk[2*(N)+1], tk[2*(N)])
463554c0a3aSHans de Goede 
464554c0a3aSHans de Goede /* S-box lookup: 16 bits --> 16 bits */
465554c0a3aSHans de Goede #define _S_(v16)     (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
466554c0a3aSHans de Goede 
467554c0a3aSHans de Goede /* fixed algorithm "parameters" */
468554c0a3aSHans de Goede #define PHASE1_LOOP_CNT   8    /* this needs to be "big enough"     */
469554c0a3aSHans de Goede #define TA_SIZE           6    /*  48-bit transmitter address       */
470554c0a3aSHans de Goede #define TK_SIZE          16    /* 128-bit temporal key              */
471554c0a3aSHans de Goede #define P1K_SIZE         10    /*  80-bit Phase1 key                */
472554c0a3aSHans de Goede #define RC4_KEY_SIZE     16    /* 128-bit RC4KEY (104 bits unknown) */
473554c0a3aSHans de Goede 
474554c0a3aSHans de Goede 
475554c0a3aSHans de Goede /* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
476554c0a3aSHans de Goede static const unsigned short Sbox1[2][256] = {      /* Sbox for hash (can be in ROM)     */
477554c0a3aSHans de Goede {
478554c0a3aSHans de Goede 	 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
479554c0a3aSHans de Goede 	 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
480554c0a3aSHans de Goede 	 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
481554c0a3aSHans de Goede 	 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
482554c0a3aSHans de Goede 	 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
483554c0a3aSHans de Goede 	 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
484554c0a3aSHans de Goede 	 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
485554c0a3aSHans de Goede 	 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
486554c0a3aSHans de Goede 	 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
487554c0a3aSHans de Goede 	 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
488554c0a3aSHans de Goede 	 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
489554c0a3aSHans de Goede 	 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
490554c0a3aSHans de Goede 	 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
491554c0a3aSHans de Goede 	 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
492554c0a3aSHans de Goede 	 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
493554c0a3aSHans de Goede 	 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
494554c0a3aSHans de Goede 	 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
495554c0a3aSHans de Goede 	 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
496554c0a3aSHans de Goede 	 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
497554c0a3aSHans de Goede 	 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
498554c0a3aSHans de Goede 	 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
499554c0a3aSHans de Goede 	 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
500554c0a3aSHans de Goede 	 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
501554c0a3aSHans de Goede 	 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
502554c0a3aSHans de Goede 	 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
503554c0a3aSHans de Goede 	 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
504554c0a3aSHans de Goede 	 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
505554c0a3aSHans de Goede 	 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
506554c0a3aSHans de Goede 	 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
507554c0a3aSHans de Goede 	 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
508554c0a3aSHans de Goede 	 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
509554c0a3aSHans de Goede 	 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
510554c0a3aSHans de Goede 	},
511554c0a3aSHans de Goede 
512554c0a3aSHans de Goede 
513554c0a3aSHans de Goede 	{  /* second half of table is unsigned char-reversed version of first! */
514554c0a3aSHans de Goede 	 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
515554c0a3aSHans de Goede 	 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
516554c0a3aSHans de Goede 	 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
517554c0a3aSHans de Goede 	 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
518554c0a3aSHans de Goede 	 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
519554c0a3aSHans de Goede 	 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
520554c0a3aSHans de Goede 	 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
521554c0a3aSHans de Goede 	 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
522554c0a3aSHans de Goede 	 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
523554c0a3aSHans de Goede 	 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
524554c0a3aSHans de Goede 	 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
525554c0a3aSHans de Goede 	 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
526554c0a3aSHans de Goede 	 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
527554c0a3aSHans de Goede 	 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
528554c0a3aSHans de Goede 	 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
529554c0a3aSHans de Goede 	 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
530554c0a3aSHans de Goede 	 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
531554c0a3aSHans de Goede 	 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
532554c0a3aSHans de Goede 	 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
533554c0a3aSHans de Goede 	 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
534554c0a3aSHans de Goede 	 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
535554c0a3aSHans de Goede 	 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
536554c0a3aSHans de Goede 	 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
537554c0a3aSHans de Goede 	 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
538554c0a3aSHans de Goede 	 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
539554c0a3aSHans de Goede 	 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
540554c0a3aSHans de Goede 	 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
541554c0a3aSHans de Goede 	 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
542554c0a3aSHans de Goede 	 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
543554c0a3aSHans de Goede 	 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
544554c0a3aSHans de Goede 	 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
545554c0a3aSHans de Goede 	 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
546554c0a3aSHans de Goede 	}
547554c0a3aSHans de Goede };
548554c0a3aSHans de Goede 
549554c0a3aSHans de Goede  /*
550554c0a3aSHans de Goede **********************************************************************
551554c0a3aSHans de Goede * Routine: Phase 1 -- generate P1K, given TA, TK, IV32
552554c0a3aSHans de Goede *
553554c0a3aSHans de Goede * Inputs:
554554c0a3aSHans de Goede *     tk[]      = temporal key                         [128 bits]
555554c0a3aSHans de Goede *     ta[]      = transmitter's MAC address            [ 48 bits]
556554c0a3aSHans de Goede *     iv32      = upper 32 bits of IV                  [ 32 bits]
557554c0a3aSHans de Goede * Output:
558554c0a3aSHans de Goede *     p1k[]     = Phase 1 key                          [ 80 bits]
559554c0a3aSHans de Goede *
560554c0a3aSHans de Goede * Note:
561554c0a3aSHans de Goede *     This function only needs to be called every 2**16 packets,
562554c0a3aSHans de Goede *     although in theory it could be called every packet.
563554c0a3aSHans de Goede *
564554c0a3aSHans de Goede **********************************************************************
565554c0a3aSHans de Goede */
566554c0a3aSHans de Goede static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
567554c0a3aSHans de Goede {
568554c0a3aSHans de Goede 	sint  i;
569554c0a3aSHans de Goede 
570554c0a3aSHans de Goede 	/* Initialize the 80 bits of P1K[] from IV32 and TA[0..5]     */
571554c0a3aSHans de Goede 	p1k[0]      = Lo16(iv32);
572554c0a3aSHans de Goede 	p1k[1]      = Hi16(iv32);
573554c0a3aSHans de Goede 	p1k[2]      = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
574554c0a3aSHans de Goede 	p1k[3]      = Mk16(ta[3], ta[2]);
575554c0a3aSHans de Goede 	p1k[4]      = Mk16(ta[5], ta[4]);
576554c0a3aSHans de Goede 
577554c0a3aSHans de Goede 	/* Now compute an unbalanced Feistel cipher with 80-bit block */
578554c0a3aSHans de Goede 	/* size on the 80-bit block P1K[], using the 128-bit key TK[] */
579554c0a3aSHans de Goede 	for (i = 0; i < PHASE1_LOOP_CNT; i++) {
580554c0a3aSHans de Goede 		/* Each add operation here is mod 2**16 */
581554c0a3aSHans de Goede 		p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
582554c0a3aSHans de Goede 		p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
583554c0a3aSHans de Goede 		p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
584554c0a3aSHans de Goede 		p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
585554c0a3aSHans de Goede 		p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
586554c0a3aSHans de Goede 		p1k[4] +=  (unsigned short)i;          /* avoid "slide attacks" */
587554c0a3aSHans de Goede 	}
588554c0a3aSHans de Goede }
589554c0a3aSHans de Goede 
590554c0a3aSHans de Goede 
591554c0a3aSHans de Goede /*
592554c0a3aSHans de Goede **********************************************************************
593554c0a3aSHans de Goede * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
594554c0a3aSHans de Goede *
595554c0a3aSHans de Goede * Inputs:
596554c0a3aSHans de Goede *     tk[]      = Temporal key                         [128 bits]
597554c0a3aSHans de Goede *     p1k[]     = Phase 1 output key                   [ 80 bits]
598554c0a3aSHans de Goede *     iv16      = low 16 bits of IV counter            [ 16 bits]
599554c0a3aSHans de Goede * Output:
600554c0a3aSHans de Goede *     rc4key[]  = the key used to encrypt the packet   [128 bits]
601554c0a3aSHans de Goede *
602554c0a3aSHans de Goede * Note:
603554c0a3aSHans de Goede *     The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
604554c0a3aSHans de Goede *     across all packets using the same key TK value. Then, for a
605554c0a3aSHans de Goede *     given value of TK[], this TKIP48 construction guarantees that
606554c0a3aSHans de Goede *     the final RC4KEY value is unique across all packets.
607554c0a3aSHans de Goede *
608554c0a3aSHans de Goede * Suggested implementation optimization: if PPK[] is "overlaid"
609554c0a3aSHans de Goede *     appropriately on RC4KEY[], there is no need for the final
610554c0a3aSHans de Goede *     for loop below that copies the PPK[] result into RC4KEY[].
611554c0a3aSHans de Goede *
612554c0a3aSHans de Goede **********************************************************************
613554c0a3aSHans de Goede */
614554c0a3aSHans de Goede static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
615554c0a3aSHans de Goede {
616554c0a3aSHans de Goede 	sint  i;
617554c0a3aSHans de Goede 	u16 PPK[6];                          /* temporary key for mixing    */
618554c0a3aSHans de Goede 
619554c0a3aSHans de Goede 	/* Note: all adds in the PPK[] equations below are mod 2**16         */
620554c0a3aSHans de Goede 	for (i = 0; i < 5; i++)
621554c0a3aSHans de Goede 		PPK[i] = p1k[i];      /* first, copy P1K to PPK      */
622554c0a3aSHans de Goede 
623554c0a3aSHans de Goede 	PPK[5]  =  p1k[4]+iv16;             /* next,  add in IV16          */
624554c0a3aSHans de Goede 
625554c0a3aSHans de Goede 	/* Bijective non-linear mixing of the 96 bits of PPK[0..5]           */
626554c0a3aSHans de Goede 	PPK[0] +=    _S_(PPK[5] ^ TK16(0));   /* Mix key in each "round"     */
627554c0a3aSHans de Goede 	PPK[1] +=    _S_(PPK[0] ^ TK16(1));
628554c0a3aSHans de Goede 	PPK[2] +=    _S_(PPK[1] ^ TK16(2));
629554c0a3aSHans de Goede 	PPK[3] +=    _S_(PPK[2] ^ TK16(3));
630554c0a3aSHans de Goede 	PPK[4] +=    _S_(PPK[3] ^ TK16(4));
631554c0a3aSHans de Goede 	PPK[5] +=    _S_(PPK[4] ^ TK16(5));   /* Total # S-box lookups == 6  */
632554c0a3aSHans de Goede 
633554c0a3aSHans de Goede 	/* Final sweep: bijective, "linear". Rotates kill LSB correlations   */
634554c0a3aSHans de Goede 	PPK[0] +=  RotR1(PPK[5] ^ TK16(6));
635554c0a3aSHans de Goede 	PPK[1] +=  RotR1(PPK[0] ^ TK16(7));   /* Use all of TK[] in Phase2   */
636554c0a3aSHans de Goede 	PPK[2] +=  RotR1(PPK[1]);
637554c0a3aSHans de Goede 	PPK[3] +=  RotR1(PPK[2]);
638554c0a3aSHans de Goede 	PPK[4] +=  RotR1(PPK[3]);
639554c0a3aSHans de Goede 	PPK[5] +=  RotR1(PPK[4]);
640554c0a3aSHans de Goede 	/* Note: At this point, for a given key TK[0..15], the 96-bit output */
641554c0a3aSHans de Goede 	/*       value PPK[0..5] is guaranteed to be unique, as a function   */
642554c0a3aSHans de Goede 	/*       of the 96-bit "input" value   {TA, IV32, IV16}. That is, P1K  */
643554c0a3aSHans de Goede 	/*       is now a keyed permutation of {TA, IV32, IV16}.               */
644554c0a3aSHans de Goede 
645554c0a3aSHans de Goede 	/* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key   */
646554c0a3aSHans de Goede 	rc4key[0] = Hi8(iv16);                /* RC4KEY[0..2] is the WEP IV  */
647554c0a3aSHans de Goede 	rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys  */
648554c0a3aSHans de Goede 	rc4key[2] = Lo8(iv16);
649554c0a3aSHans de Goede 	rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
650554c0a3aSHans de Goede 
651554c0a3aSHans de Goede 
652554c0a3aSHans de Goede 	/* Copy 96 bits of PPK[0..5] to RC4KEY[4..15]  (little-endian)       */
653554c0a3aSHans de Goede 	for (i = 0; i < 6; i++) {
654554c0a3aSHans de Goede 		rc4key[4+2*i] = Lo8(PPK[i]);
655554c0a3aSHans de Goede 		rc4key[5+2*i] = Hi8(PPK[i]);
656554c0a3aSHans de Goede 	}
657554c0a3aSHans de Goede }
658554c0a3aSHans de Goede 
659554c0a3aSHans de Goede 
660554c0a3aSHans de Goede /* The hlen isn't include the IV */
661554c0a3aSHans de Goede u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
662554c0a3aSHans de Goede {																	/*  exclude ICV */
663554c0a3aSHans de Goede 	u16 pnl;
664554c0a3aSHans de Goede 	u32 pnh;
665554c0a3aSHans de Goede 	u8 rc4key[16];
666554c0a3aSHans de Goede 	u8   ttkey[16];
667554c0a3aSHans de Goede 	u8 crc[4];
668554c0a3aSHans de Goede 	u8   hw_hdr_offset = 0;
669554c0a3aSHans de Goede 	struct arc4context mycontext;
670554c0a3aSHans de Goede 	sint			curfragnum, length;
671554c0a3aSHans de Goede 	u32 prwskeylen;
672554c0a3aSHans de Goede 
673554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, *prwskey;
674554c0a3aSHans de Goede 	union pn48 dot11txpn;
675554c0a3aSHans de Goede 	/* struct	sta_info 	*stainfo; */
676554c0a3aSHans de Goede 	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
677554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
678554c0a3aSHans de Goede 	struct	xmit_priv 	*pxmitpriv = &padapter->xmitpriv;
679554c0a3aSHans de Goede 	u32 res = _SUCCESS;
680554c0a3aSHans de Goede 
681554c0a3aSHans de Goede 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
682554c0a3aSHans de Goede 		return _FAIL;
683554c0a3aSHans de Goede 
684554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
685554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
686554c0a3aSHans de Goede 
687554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
688554c0a3aSHans de Goede 	if (pattrib->encrypt == _TKIP_) {
689554c0a3aSHans de Goede 
690554c0a3aSHans de Goede /*
691554c0a3aSHans de Goede 		if (pattrib->psta)
692554c0a3aSHans de Goede 		{
693554c0a3aSHans de Goede 			stainfo = pattrib->psta;
694554c0a3aSHans de Goede 		}
695554c0a3aSHans de Goede 		else
696554c0a3aSHans de Goede 		{
697554c0a3aSHans de Goede 			DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
698554c0a3aSHans de Goede 			stainfo =rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
699554c0a3aSHans de Goede 		}
700554c0a3aSHans de Goede */
701554c0a3aSHans de Goede 		/* if (stainfo!= NULL) */
702554c0a3aSHans de Goede 		{
703554c0a3aSHans de Goede /*
704554c0a3aSHans de Goede 			if (!(stainfo->state &_FW_LINKED))
705554c0a3aSHans de Goede 			{
706554c0a3aSHans de Goede 				DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
707554c0a3aSHans de Goede 				return _FAIL;
708554c0a3aSHans de Goede 			}
709554c0a3aSHans de Goede */
710554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo!= NULL!!!\n"));
711554c0a3aSHans de Goede 
712554c0a3aSHans de Goede 			if (IS_MCAST(pattrib->ra))
713554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
714554c0a3aSHans de Goede 			else
715554c0a3aSHans de Goede 				/* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
716554c0a3aSHans de Goede 				prwskey = pattrib->dot118021x_UncstKey.skey;
717554c0a3aSHans de Goede 
718554c0a3aSHans de Goede 			prwskeylen = 16;
719554c0a3aSHans de Goede 
720554c0a3aSHans de Goede 			for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
721554c0a3aSHans de Goede 				iv = pframe+pattrib->hdrlen;
722554c0a3aSHans de Goede 				payload = pframe+pattrib->iv_len+pattrib->hdrlen;
723554c0a3aSHans de Goede 
724554c0a3aSHans de Goede 				GET_TKIP_PN(iv, dot11txpn);
725554c0a3aSHans de Goede 
726554c0a3aSHans de Goede 				pnl = (u16)(dot11txpn.val);
727554c0a3aSHans de Goede 				pnh = (u32)(dot11txpn.val>>16);
728554c0a3aSHans de Goede 
729554c0a3aSHans de Goede 				phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
730554c0a3aSHans de Goede 
731554c0a3aSHans de Goede 				phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
732554c0a3aSHans de Goede 
733554c0a3aSHans de Goede 				if ((curfragnum+1) == pattrib->nr_frags) {	/* 4 the last fragment */
734554c0a3aSHans de Goede 					length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
735554c0a3aSHans de Goede 					RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len));
736554c0a3aSHans de Goede 					*((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
737554c0a3aSHans de Goede 
738554c0a3aSHans de Goede 					arcfour_init(&mycontext, rc4key, 16);
739554c0a3aSHans de Goede 					arcfour_encrypt(&mycontext, payload, payload, length);
740554c0a3aSHans de Goede 					arcfour_encrypt(&mycontext, payload+length, crc, 4);
741554c0a3aSHans de Goede 
742554c0a3aSHans de Goede 				} else {
743554c0a3aSHans de Goede 					length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
744554c0a3aSHans de Goede 					*((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/
745554c0a3aSHans de Goede 					arcfour_init(&mycontext, rc4key, 16);
746554c0a3aSHans de Goede 					arcfour_encrypt(&mycontext, payload, payload, length);
747554c0a3aSHans de Goede 					arcfour_encrypt(&mycontext, payload+length, crc, 4);
748554c0a3aSHans de Goede 
749554c0a3aSHans de Goede 				pframe += pxmitpriv->frag_len;
750554c0a3aSHans de Goede 				pframe = (u8 *)RND4((SIZE_PTR)(pframe));
751554c0a3aSHans de Goede 
752554c0a3aSHans de Goede 				}
753554c0a3aSHans de Goede 			}
754554c0a3aSHans de Goede 
755554c0a3aSHans de Goede 			TKIP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
756554c0a3aSHans de Goede 		}
757554c0a3aSHans de Goede /*
758554c0a3aSHans de Goede 		else {
759554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo == NULL!!!\n"));
760554c0a3aSHans de Goede 			DBG_871X("%s, psta ==NUL\n", __func__);
761554c0a3aSHans de Goede 			res = _FAIL;
762554c0a3aSHans de Goede 		}
763554c0a3aSHans de Goede */
764554c0a3aSHans de Goede 
765554c0a3aSHans de Goede 	}
766554c0a3aSHans de Goede 	return res;
767554c0a3aSHans de Goede }
768554c0a3aSHans de Goede 
769554c0a3aSHans de Goede 
770554c0a3aSHans de Goede /* The hlen isn't include the IV */
771554c0a3aSHans de Goede u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
772554c0a3aSHans de Goede {																	/*  exclude ICV */
773554c0a3aSHans de Goede 	u16 pnl;
774554c0a3aSHans de Goede 	u32 pnh;
775554c0a3aSHans de Goede 	u8   rc4key[16];
776554c0a3aSHans de Goede 	u8   ttkey[16];
777554c0a3aSHans de Goede 	u8 crc[4];
778554c0a3aSHans de Goede 	struct arc4context mycontext;
779554c0a3aSHans de Goede 	sint			length;
780554c0a3aSHans de Goede 	u32 prwskeylen;
781554c0a3aSHans de Goede 
782554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, *prwskey;
783554c0a3aSHans de Goede 	union pn48 dot11txpn;
784554c0a3aSHans de Goede 	struct	sta_info 	*stainfo;
785554c0a3aSHans de Goede 	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
786554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
787554c0a3aSHans de Goede /* 	struct	recv_priv 	*precvpriv =&padapter->recvpriv; */
788554c0a3aSHans de Goede 	u32 	res = _SUCCESS;
789554c0a3aSHans de Goede 
790554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
791554c0a3aSHans de Goede 
792554c0a3aSHans de Goede 	/* 4 start to decrypt recvframe */
793554c0a3aSHans de Goede 	if (prxattrib->encrypt == _TKIP_) {
794554c0a3aSHans de Goede 
795554c0a3aSHans de Goede 		stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
796554c0a3aSHans de Goede 		if (stainfo != NULL) {
797554c0a3aSHans de Goede 
798554c0a3aSHans de Goede 			if (IS_MCAST(prxattrib->ra)) {
799554c0a3aSHans de Goede 				static unsigned long start = 0;
800554c0a3aSHans de Goede 				static u32 no_gkey_bc_cnt = 0;
801554c0a3aSHans de Goede 				static u32 no_gkey_mc_cnt = 0;
802554c0a3aSHans de Goede 
803554c0a3aSHans de Goede 				if (psecuritypriv->binstallGrpkey == false) {
804554c0a3aSHans de Goede 					res = _FAIL;
805554c0a3aSHans de Goede 
806554c0a3aSHans de Goede 					if (start == 0)
807554c0a3aSHans de Goede 						start = jiffies;
808554c0a3aSHans de Goede 
809554c0a3aSHans de Goede 					if (is_broadcast_mac_addr(prxattrib->ra))
810554c0a3aSHans de Goede 						no_gkey_bc_cnt++;
811554c0a3aSHans de Goede 					else
812554c0a3aSHans de Goede 						no_gkey_mc_cnt++;
813554c0a3aSHans de Goede 
814554c0a3aSHans de Goede 					if (jiffies_to_msecs(jiffies - start) > 1000) {
815554c0a3aSHans de Goede 						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
816554c0a3aSHans de Goede 							DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
817554c0a3aSHans de Goede 								FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
818554c0a3aSHans de Goede 						}
819554c0a3aSHans de Goede 						start = jiffies;
820554c0a3aSHans de Goede 						no_gkey_bc_cnt = 0;
821554c0a3aSHans de Goede 						no_gkey_mc_cnt = 0;
822554c0a3aSHans de Goede 					}
823554c0a3aSHans de Goede 					goto exit;
824554c0a3aSHans de Goede 				}
825554c0a3aSHans de Goede 
826554c0a3aSHans de Goede 				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
827554c0a3aSHans de Goede 					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
828554c0a3aSHans de Goede 						FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
829554c0a3aSHans de Goede 				}
830554c0a3aSHans de Goede 				start = 0;
831554c0a3aSHans de Goede 				no_gkey_bc_cnt = 0;
832554c0a3aSHans de Goede 				no_gkey_mc_cnt = 0;
833554c0a3aSHans de Goede 
834554c0a3aSHans de Goede 				/* DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n"); */
835554c0a3aSHans de Goede 				/* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
836554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
837554c0a3aSHans de Goede 				prwskeylen = 16;
838554c0a3aSHans de Goede 			} else{
839554c0a3aSHans de Goede 				prwskey = &stainfo->dot118021x_UncstKey.skey[0];
840554c0a3aSHans de Goede 				prwskeylen = 16;
841554c0a3aSHans de Goede 			}
842554c0a3aSHans de Goede 
843554c0a3aSHans de Goede 			iv = pframe+prxattrib->hdrlen;
844554c0a3aSHans de Goede 			payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
845554c0a3aSHans de Goede 			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
846554c0a3aSHans de Goede 
847554c0a3aSHans de Goede 			GET_TKIP_PN(iv, dot11txpn);
848554c0a3aSHans de Goede 
849554c0a3aSHans de Goede 			pnl = (u16)(dot11txpn.val);
850554c0a3aSHans de Goede 			pnh = (u32)(dot11txpn.val>>16);
851554c0a3aSHans de Goede 
852554c0a3aSHans de Goede 			phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
853554c0a3aSHans de Goede 			phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
854554c0a3aSHans de Goede 
855554c0a3aSHans de Goede 			/* 4 decrypt payload include icv */
856554c0a3aSHans de Goede 
857554c0a3aSHans de Goede 			arcfour_init(&mycontext, rc4key, 16);
858554c0a3aSHans de Goede 			arcfour_encrypt(&mycontext, payload, payload, length);
859554c0a3aSHans de Goede 
860554c0a3aSHans de Goede 			*((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4));
861554c0a3aSHans de Goede 
862554c0a3aSHans de Goede 			if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) {
863554c0a3aSHans de Goede 			    RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
864554c0a3aSHans de Goede 						crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4]));
865554c0a3aSHans de Goede 				res = _FAIL;
866554c0a3aSHans de Goede 			}
867554c0a3aSHans de Goede 
868554c0a3aSHans de Goede 			TKIP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
869554c0a3aSHans de Goede 		} else {
870554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo == NULL!!!\n"));
871554c0a3aSHans de Goede 			res = _FAIL;
872554c0a3aSHans de Goede 		}
873554c0a3aSHans de Goede 
874554c0a3aSHans de Goede 	}
875554c0a3aSHans de Goede exit:
876554c0a3aSHans de Goede 	return res;
877554c0a3aSHans de Goede 
878554c0a3aSHans de Goede }
879554c0a3aSHans de Goede 
880554c0a3aSHans de Goede 
881554c0a3aSHans de Goede /* 3			=====AES related ===== */
882554c0a3aSHans de Goede 
883554c0a3aSHans de Goede 
884554c0a3aSHans de Goede 
885554c0a3aSHans de Goede #define MAX_MSG_SIZE	2048
886554c0a3aSHans de Goede /*****************************/
887554c0a3aSHans de Goede /******** SBOX Table *********/
888554c0a3aSHans de Goede /*****************************/
889554c0a3aSHans de Goede 
890554c0a3aSHans de Goede 	static  u8 sbox_table[256] = {
891554c0a3aSHans de Goede 			0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
892554c0a3aSHans de Goede 			0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
893554c0a3aSHans de Goede 			0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
894554c0a3aSHans de Goede 			0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
895554c0a3aSHans de Goede 			0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
896554c0a3aSHans de Goede 			0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
897554c0a3aSHans de Goede 			0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
898554c0a3aSHans de Goede 			0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
899554c0a3aSHans de Goede 			0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
900554c0a3aSHans de Goede 			0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
901554c0a3aSHans de Goede 			0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
902554c0a3aSHans de Goede 			0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
903554c0a3aSHans de Goede 			0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
904554c0a3aSHans de Goede 			0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
905554c0a3aSHans de Goede 			0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
906554c0a3aSHans de Goede 			0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
907554c0a3aSHans de Goede 			0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
908554c0a3aSHans de Goede 			0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
909554c0a3aSHans de Goede 			0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
910554c0a3aSHans de Goede 			0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
911554c0a3aSHans de Goede 			0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
912554c0a3aSHans de Goede 			0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
913554c0a3aSHans de Goede 			0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
914554c0a3aSHans de Goede 			0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
915554c0a3aSHans de Goede 			0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
916554c0a3aSHans de Goede 			0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
917554c0a3aSHans de Goede 			0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
918554c0a3aSHans de Goede 			0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
919554c0a3aSHans de Goede 			0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
920554c0a3aSHans de Goede 			0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
921554c0a3aSHans de Goede 			0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
922554c0a3aSHans de Goede 			0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
923554c0a3aSHans de Goede 		};
924554c0a3aSHans de Goede 
925554c0a3aSHans de Goede /*****************************/
926554c0a3aSHans de Goede /**** Function Prototypes ****/
927554c0a3aSHans de Goede /*****************************/
928554c0a3aSHans de Goede 
929554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
930554c0a3aSHans de Goede static void construct_mic_iv(
931554c0a3aSHans de Goede 	u8 *mic_header1,
932554c0a3aSHans de Goede 	sint qc_exists,
933554c0a3aSHans de Goede 	sint a4_exists,
934554c0a3aSHans de Goede 	u8 *mpdu,
935554c0a3aSHans de Goede 	uint payload_length,
936554c0a3aSHans de Goede 	u8 *pn_vector,
937554c0a3aSHans de Goede 	uint frtype
938554c0a3aSHans de Goede );/*  add for CONFIG_IEEE80211W, none 11w also can use */
939554c0a3aSHans de Goede static void construct_mic_header1(
940554c0a3aSHans de Goede 	u8 *mic_header1,
941554c0a3aSHans de Goede 	sint header_length,
942554c0a3aSHans de Goede 	u8 *mpdu,
943554c0a3aSHans de Goede 	uint frtype
944554c0a3aSHans de Goede );/*  add for CONFIG_IEEE80211W, none 11w also can use */
945554c0a3aSHans de Goede static void construct_mic_header2(
946554c0a3aSHans de Goede 	u8 *mic_header2,
947554c0a3aSHans de Goede 	u8 *mpdu,
948554c0a3aSHans de Goede 	sint a4_exists,
949554c0a3aSHans de Goede 	sint qc_exists
950554c0a3aSHans de Goede );
951554c0a3aSHans de Goede static void construct_ctr_preload(
952554c0a3aSHans de Goede 	u8 *ctr_preload,
953554c0a3aSHans de Goede 	sint a4_exists,
954554c0a3aSHans de Goede 	sint qc_exists,
955554c0a3aSHans de Goede 	u8 *mpdu,
956554c0a3aSHans de Goede 	u8 *pn_vector,
957554c0a3aSHans de Goede 	sint c,
958554c0a3aSHans de Goede 	uint frtype
959554c0a3aSHans de Goede );/*  add for CONFIG_IEEE80211W, none 11w also can use */
960554c0a3aSHans de Goede static void xor_128(u8 *a, u8 *b, u8 *out);
961554c0a3aSHans de Goede static void xor_32(u8 *a, u8 *b, u8 *out);
962554c0a3aSHans de Goede static u8 sbox(u8 a);
963554c0a3aSHans de Goede static void next_key(u8 *key, sint round);
964554c0a3aSHans de Goede static void byte_sub(u8 *in, u8 *out);
965554c0a3aSHans de Goede static void shift_row(u8 *in, u8 *out);
966554c0a3aSHans de Goede static void mix_column(u8 *in, u8 *out);
967554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
968554c0a3aSHans de Goede 
969554c0a3aSHans de Goede 
970554c0a3aSHans de Goede /****************************************/
971554c0a3aSHans de Goede /* aes128k128d()                        */
972554c0a3aSHans de Goede /* Performs a 128 bit AES encrypt with  */
973554c0a3aSHans de Goede /* 128 bit data.                        */
974554c0a3aSHans de Goede /****************************************/
975554c0a3aSHans de Goede static void xor_128(u8 *a, u8 *b, u8 *out)
976554c0a3aSHans de Goede {
977554c0a3aSHans de Goede 		sint i;
978554c0a3aSHans de Goede 
979554c0a3aSHans de Goede 		for (i = 0; i < 16; i++) {
980554c0a3aSHans de Goede 			out[i] = a[i] ^ b[i];
981554c0a3aSHans de Goede 		}
982554c0a3aSHans de Goede }
983554c0a3aSHans de Goede 
984554c0a3aSHans de Goede 
985554c0a3aSHans de Goede static void xor_32(u8 *a, u8 *b, u8 *out)
986554c0a3aSHans de Goede {
987554c0a3aSHans de Goede 		sint i;
988554c0a3aSHans de Goede 
989554c0a3aSHans de Goede 		for (i = 0; i < 4; i++) {
990554c0a3aSHans de Goede 			out[i] = a[i] ^ b[i];
991554c0a3aSHans de Goede 		}
992554c0a3aSHans de Goede }
993554c0a3aSHans de Goede 
994554c0a3aSHans de Goede 
995554c0a3aSHans de Goede static u8 sbox(u8 a)
996554c0a3aSHans de Goede {
997554c0a3aSHans de Goede 		return sbox_table[(sint)a];
998554c0a3aSHans de Goede }
999554c0a3aSHans de Goede 
1000554c0a3aSHans de Goede 
1001554c0a3aSHans de Goede static void next_key(u8 *key, sint round)
1002554c0a3aSHans de Goede {
1003554c0a3aSHans de Goede 		u8 rcon;
1004554c0a3aSHans de Goede 		u8 sbox_key[4];
1005554c0a3aSHans de Goede 		u8 rcon_table[12] = {
1006554c0a3aSHans de Goede 			0x01, 0x02, 0x04, 0x08,
1007554c0a3aSHans de Goede 			0x10, 0x20, 0x40, 0x80,
1008554c0a3aSHans de Goede 			0x1b, 0x36, 0x36, 0x36
1009554c0a3aSHans de Goede 		};
1010554c0a3aSHans de Goede 		sbox_key[0] = sbox(key[13]);
1011554c0a3aSHans de Goede 		sbox_key[1] = sbox(key[14]);
1012554c0a3aSHans de Goede 		sbox_key[2] = sbox(key[15]);
1013554c0a3aSHans de Goede 		sbox_key[3] = sbox(key[12]);
1014554c0a3aSHans de Goede 
1015554c0a3aSHans de Goede 		rcon = rcon_table[round];
1016554c0a3aSHans de Goede 
1017554c0a3aSHans de Goede 		xor_32(&key[0], sbox_key, &key[0]);
1018554c0a3aSHans de Goede 		key[0] = key[0] ^ rcon;
1019554c0a3aSHans de Goede 
1020554c0a3aSHans de Goede 		xor_32(&key[4], &key[0], &key[4]);
1021554c0a3aSHans de Goede 		xor_32(&key[8], &key[4], &key[8]);
1022554c0a3aSHans de Goede 		xor_32(&key[12], &key[8], &key[12]);
1023554c0a3aSHans de Goede }
1024554c0a3aSHans de Goede 
1025554c0a3aSHans de Goede 
1026554c0a3aSHans de Goede static void byte_sub(u8 *in, u8 *out)
1027554c0a3aSHans de Goede {
1028554c0a3aSHans de Goede 		sint i;
1029554c0a3aSHans de Goede 
1030554c0a3aSHans de Goede 		for (i = 0; i < 16; i++) {
1031554c0a3aSHans de Goede 			out[i] = sbox(in[i]);
1032554c0a3aSHans de Goede 		}
1033554c0a3aSHans de Goede }
1034554c0a3aSHans de Goede 
1035554c0a3aSHans de Goede 
1036554c0a3aSHans de Goede static void shift_row(u8 *in, u8 *out)
1037554c0a3aSHans de Goede {
1038554c0a3aSHans de Goede 		out[0] =  in[0];
1039554c0a3aSHans de Goede 		out[1] =  in[5];
1040554c0a3aSHans de Goede 		out[2] =  in[10];
1041554c0a3aSHans de Goede 		out[3] =  in[15];
1042554c0a3aSHans de Goede 		out[4] =  in[4];
1043554c0a3aSHans de Goede 		out[5] =  in[9];
1044554c0a3aSHans de Goede 		out[6] =  in[14];
1045554c0a3aSHans de Goede 		out[7] =  in[3];
1046554c0a3aSHans de Goede 		out[8] =  in[8];
1047554c0a3aSHans de Goede 		out[9] =  in[13];
1048554c0a3aSHans de Goede 		out[10] = in[2];
1049554c0a3aSHans de Goede 		out[11] = in[7];
1050554c0a3aSHans de Goede 		out[12] = in[12];
1051554c0a3aSHans de Goede 		out[13] = in[1];
1052554c0a3aSHans de Goede 		out[14] = in[6];
1053554c0a3aSHans de Goede 		out[15] = in[11];
1054554c0a3aSHans de Goede }
1055554c0a3aSHans de Goede 
1056554c0a3aSHans de Goede 
1057554c0a3aSHans de Goede static void mix_column(u8 *in, u8 *out)
1058554c0a3aSHans de Goede {
1059554c0a3aSHans de Goede 		sint i;
1060554c0a3aSHans de Goede 		u8 add1b[4];
1061554c0a3aSHans de Goede 		u8 add1bf7[4];
1062554c0a3aSHans de Goede 		u8 rotl[4];
1063554c0a3aSHans de Goede 		u8 swap_halfs[4];
1064554c0a3aSHans de Goede 		u8 andf7[4];
1065554c0a3aSHans de Goede 		u8 rotr[4];
1066554c0a3aSHans de Goede 		u8 temp[4];
1067554c0a3aSHans de Goede 		u8 tempb[4];
1068554c0a3aSHans de Goede 
1069554c0a3aSHans de Goede 		for (i = 0; i < 4; i++) {
1070554c0a3aSHans de Goede 			if ((in[i] & 0x80) == 0x80)
1071554c0a3aSHans de Goede 				add1b[i] = 0x1b;
1072554c0a3aSHans de Goede 			else
1073554c0a3aSHans de Goede 				add1b[i] = 0x00;
1074554c0a3aSHans de Goede 		}
1075554c0a3aSHans de Goede 
1076554c0a3aSHans de Goede 		swap_halfs[0] = in[2];    /* Swap halfs */
1077554c0a3aSHans de Goede 		swap_halfs[1] = in[3];
1078554c0a3aSHans de Goede 		swap_halfs[2] = in[0];
1079554c0a3aSHans de Goede 		swap_halfs[3] = in[1];
1080554c0a3aSHans de Goede 
1081554c0a3aSHans de Goede 		rotl[0] = in[3];        /* Rotate left 8 bits */
1082554c0a3aSHans de Goede 		rotl[1] = in[0];
1083554c0a3aSHans de Goede 		rotl[2] = in[1];
1084554c0a3aSHans de Goede 		rotl[3] = in[2];
1085554c0a3aSHans de Goede 
1086554c0a3aSHans de Goede 		andf7[0] = in[0] & 0x7f;
1087554c0a3aSHans de Goede 		andf7[1] = in[1] & 0x7f;
1088554c0a3aSHans de Goede 		andf7[2] = in[2] & 0x7f;
1089554c0a3aSHans de Goede 		andf7[3] = in[3] & 0x7f;
1090554c0a3aSHans de Goede 
1091554c0a3aSHans de Goede 		for (i = 3; i > 0; i--) {  /* logical shift left 1 bit */
1092554c0a3aSHans de Goede 			andf7[i] = andf7[i] << 1;
1093554c0a3aSHans de Goede 			if ((andf7[i-1] & 0x80) == 0x80)
1094554c0a3aSHans de Goede 				andf7[i] = (andf7[i] | 0x01);
1095554c0a3aSHans de Goede 		}
1096554c0a3aSHans de Goede 		andf7[0] = andf7[0] << 1;
1097554c0a3aSHans de Goede 		andf7[0] = andf7[0] & 0xfe;
1098554c0a3aSHans de Goede 
1099554c0a3aSHans de Goede 		xor_32(add1b, andf7, add1bf7);
1100554c0a3aSHans de Goede 
1101554c0a3aSHans de Goede 		xor_32(in, add1bf7, rotr);
1102554c0a3aSHans de Goede 
1103554c0a3aSHans de Goede 		temp[0] = rotr[0];         /* Rotate right 8 bits */
1104554c0a3aSHans de Goede 		rotr[0] = rotr[1];
1105554c0a3aSHans de Goede 		rotr[1] = rotr[2];
1106554c0a3aSHans de Goede 		rotr[2] = rotr[3];
1107554c0a3aSHans de Goede 		rotr[3] = temp[0];
1108554c0a3aSHans de Goede 
1109554c0a3aSHans de Goede 		xor_32(add1bf7, rotr, temp);
1110554c0a3aSHans de Goede 		xor_32(swap_halfs, rotl, tempb);
1111554c0a3aSHans de Goede 		xor_32(temp, tempb, out);
1112554c0a3aSHans de Goede }
1113554c0a3aSHans de Goede 
1114554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
1115554c0a3aSHans de Goede {
1116554c0a3aSHans de Goede 		sint round;
1117554c0a3aSHans de Goede 		sint i;
1118554c0a3aSHans de Goede 		u8 intermediatea[16];
1119554c0a3aSHans de Goede 		u8 intermediateb[16];
1120554c0a3aSHans de Goede 		u8 round_key[16];
1121554c0a3aSHans de Goede 
1122554c0a3aSHans de Goede 		for (i = 0; i < 16; i++)
1123554c0a3aSHans de Goede 			round_key[i] = key[i];
1124554c0a3aSHans de Goede 
1125554c0a3aSHans de Goede 		for (round = 0; round < 11; round++) {
1126554c0a3aSHans de Goede 			if (round == 0) {
1127554c0a3aSHans de Goede 				xor_128(round_key, data, ciphertext);
1128554c0a3aSHans de Goede 				next_key(round_key, round);
1129554c0a3aSHans de Goede 			} else if (round == 10) {
1130554c0a3aSHans de Goede 				byte_sub(ciphertext, intermediatea);
1131554c0a3aSHans de Goede 				shift_row(intermediatea, intermediateb);
1132554c0a3aSHans de Goede 				xor_128(intermediateb, round_key, ciphertext);
1133554c0a3aSHans de Goede 			} else{   /* 1 - 9 */
1134554c0a3aSHans de Goede 				byte_sub(ciphertext, intermediatea);
1135554c0a3aSHans de Goede 				shift_row(intermediatea, intermediateb);
1136554c0a3aSHans de Goede 				mix_column(&intermediateb[0], &intermediatea[0]);
1137554c0a3aSHans de Goede 				mix_column(&intermediateb[4], &intermediatea[4]);
1138554c0a3aSHans de Goede 				mix_column(&intermediateb[8], &intermediatea[8]);
1139554c0a3aSHans de Goede 				mix_column(&intermediateb[12], &intermediatea[12]);
1140554c0a3aSHans de Goede 				xor_128(intermediatea, round_key, ciphertext);
1141554c0a3aSHans de Goede 				next_key(round_key, round);
1142554c0a3aSHans de Goede 			}
1143554c0a3aSHans de Goede 		}
1144554c0a3aSHans de Goede }
1145554c0a3aSHans de Goede 
1146554c0a3aSHans de Goede 
1147554c0a3aSHans de Goede /************************************************/
1148554c0a3aSHans de Goede /* construct_mic_iv()                           */
1149554c0a3aSHans de Goede /* Builds the MIC IV from header fields and PN  */
1150554c0a3aSHans de Goede /* Baron think the function is construct CCM    */
1151554c0a3aSHans de Goede /* nonce                                        */
1152554c0a3aSHans de Goede /************************************************/
1153554c0a3aSHans de Goede static void construct_mic_iv(
1154554c0a3aSHans de Goede 	u8 *mic_iv,
1155554c0a3aSHans de Goede 	sint qc_exists,
1156554c0a3aSHans de Goede 	sint a4_exists,
1157554c0a3aSHans de Goede 	u8 *mpdu,
1158554c0a3aSHans de Goede 	uint payload_length,
1159554c0a3aSHans de Goede 	u8 *pn_vector,
1160554c0a3aSHans de Goede 	uint frtype/*  add for CONFIG_IEEE80211W, none 11w also can use */
1161554c0a3aSHans de Goede )
1162554c0a3aSHans de Goede {
1163554c0a3aSHans de Goede 		sint i;
1164554c0a3aSHans de Goede 
1165554c0a3aSHans de Goede 		mic_iv[0] = 0x59;
1166554c0a3aSHans de Goede 
1167554c0a3aSHans de Goede 		if (qc_exists && a4_exists)
1168554c0a3aSHans de Goede 			mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC           */
1169554c0a3aSHans de Goede 
1170554c0a3aSHans de Goede 		if (qc_exists && !a4_exists)
1171554c0a3aSHans de Goede 			mic_iv[1] = mpdu[24] & 0x0f;   /* mute bits 7-4    */
1172554c0a3aSHans de Goede 
1173554c0a3aSHans de Goede 		if (!qc_exists)
1174554c0a3aSHans de Goede 			mic_iv[1] = 0x00;
1175554c0a3aSHans de Goede 
1176554c0a3aSHans de Goede 		/* 802.11w management frame should set management bit(4) */
1177554c0a3aSHans de Goede 		if (frtype == WIFI_MGT_TYPE)
1178554c0a3aSHans de Goede 			mic_iv[1] |= BIT(4);
1179554c0a3aSHans de Goede 
1180554c0a3aSHans de Goede 		for (i = 2; i < 8; i++)
1181554c0a3aSHans de Goede 			mic_iv[i] = mpdu[i + 8];   /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
1182554c0a3aSHans de Goede 		#ifdef CONSISTENT_PN_ORDER
1183554c0a3aSHans de Goede 		for (i = 8; i < 14; i++)
1184554c0a3aSHans de Goede 			mic_iv[i] = pn_vector[i - 8];           /* mic_iv[8:13] = PN[0:5] */
1185554c0a3aSHans de Goede 		#else
1186554c0a3aSHans de Goede 		for (i = 8; i < 14; i++)
1187554c0a3aSHans de Goede 			mic_iv[i] = pn_vector[13 - i];          /* mic_iv[8:13] = PN[5:0] */
1188554c0a3aSHans de Goede 		#endif
1189554c0a3aSHans de Goede 		mic_iv[14] = (unsigned char) (payload_length / 256);
1190554c0a3aSHans de Goede 		mic_iv[15] = (unsigned char) (payload_length % 256);
1191554c0a3aSHans de Goede }
1192554c0a3aSHans de Goede 
1193554c0a3aSHans de Goede 
1194554c0a3aSHans de Goede /************************************************/
1195554c0a3aSHans de Goede /* construct_mic_header1()                      */
1196554c0a3aSHans de Goede /* Builds the first MIC header block from       */
1197554c0a3aSHans de Goede /* header fields.                               */
1198554c0a3aSHans de Goede /* Build AAD SC, A1, A2                           */
1199554c0a3aSHans de Goede /************************************************/
1200554c0a3aSHans de Goede static void construct_mic_header1(
1201554c0a3aSHans de Goede 	u8 *mic_header1,
1202554c0a3aSHans de Goede 	sint header_length,
1203554c0a3aSHans de Goede 	u8 *mpdu,
1204554c0a3aSHans de Goede 	uint frtype/*  add for CONFIG_IEEE80211W, none 11w also can use */
1205554c0a3aSHans de Goede )
1206554c0a3aSHans de Goede {
1207554c0a3aSHans de Goede 		mic_header1[0] = (u8)((header_length - 2) / 256);
1208554c0a3aSHans de Goede 		mic_header1[1] = (u8)((header_length - 2) % 256);
1209554c0a3aSHans de Goede 
1210554c0a3aSHans de Goede 		/* 802.11w management frame don't AND subtype bits 4, 5, 6 of frame control field */
1211554c0a3aSHans de Goede 		if (frtype == WIFI_MGT_TYPE)
1212554c0a3aSHans de Goede 			mic_header1[2] = mpdu[0];
1213554c0a3aSHans de Goede 		else
1214554c0a3aSHans de Goede 			mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
1215554c0a3aSHans de Goede 
1216554c0a3aSHans de Goede 		mic_header1[3] = mpdu[1] & 0xc7;    /* Mute retry, more data and pwr mgt bits */
1217554c0a3aSHans de Goede 		mic_header1[4] = mpdu[4];       /* A1 */
1218554c0a3aSHans de Goede 		mic_header1[5] = mpdu[5];
1219554c0a3aSHans de Goede 		mic_header1[6] = mpdu[6];
1220554c0a3aSHans de Goede 		mic_header1[7] = mpdu[7];
1221554c0a3aSHans de Goede 		mic_header1[8] = mpdu[8];
1222554c0a3aSHans de Goede 		mic_header1[9] = mpdu[9];
1223554c0a3aSHans de Goede 		mic_header1[10] = mpdu[10];     /* A2 */
1224554c0a3aSHans de Goede 		mic_header1[11] = mpdu[11];
1225554c0a3aSHans de Goede 		mic_header1[12] = mpdu[12];
1226554c0a3aSHans de Goede 		mic_header1[13] = mpdu[13];
1227554c0a3aSHans de Goede 		mic_header1[14] = mpdu[14];
1228554c0a3aSHans de Goede 		mic_header1[15] = mpdu[15];
1229554c0a3aSHans de Goede }
1230554c0a3aSHans de Goede 
1231554c0a3aSHans de Goede 
1232554c0a3aSHans de Goede /************************************************/
1233554c0a3aSHans de Goede /* construct_mic_header2()                      */
1234554c0a3aSHans de Goede /* Builds the last MIC header block from        */
1235554c0a3aSHans de Goede /* header fields.                               */
1236554c0a3aSHans de Goede /************************************************/
1237554c0a3aSHans de Goede static void construct_mic_header2(
1238554c0a3aSHans de Goede 	u8 *mic_header2,
1239554c0a3aSHans de Goede 	u8 *mpdu,
1240554c0a3aSHans de Goede 	sint a4_exists,
1241554c0a3aSHans de Goede 	sint qc_exists
1242554c0a3aSHans de Goede )
1243554c0a3aSHans de Goede {
1244554c0a3aSHans de Goede 		sint i;
1245554c0a3aSHans de Goede 
1246554c0a3aSHans de Goede 		for (i = 0; i < 16; i++)
1247554c0a3aSHans de Goede 			mic_header2[i] = 0x00;
1248554c0a3aSHans de Goede 
1249554c0a3aSHans de Goede 		mic_header2[0] = mpdu[16];    /* A3 */
1250554c0a3aSHans de Goede 		mic_header2[1] = mpdu[17];
1251554c0a3aSHans de Goede 		mic_header2[2] = mpdu[18];
1252554c0a3aSHans de Goede 		mic_header2[3] = mpdu[19];
1253554c0a3aSHans de Goede 		mic_header2[4] = mpdu[20];
1254554c0a3aSHans de Goede 		mic_header2[5] = mpdu[21];
1255554c0a3aSHans de Goede 
1256554c0a3aSHans de Goede 		mic_header2[6] = 0x00;
1257554c0a3aSHans de Goede 		mic_header2[7] = 0x00; /* mpdu[23]; */
1258554c0a3aSHans de Goede 
1259554c0a3aSHans de Goede 
1260554c0a3aSHans de Goede 		if (!qc_exists && a4_exists) {
1261554c0a3aSHans de Goede 			for (i = 0; i < 6; i++)
1262554c0a3aSHans de Goede 				mic_header2[8+i] = mpdu[24+i];   /* A4 */
1263554c0a3aSHans de Goede 
1264554c0a3aSHans de Goede 		}
1265554c0a3aSHans de Goede 
1266554c0a3aSHans de Goede 		if (qc_exists && !a4_exists) {
1267554c0a3aSHans de Goede 			mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
1268554c0a3aSHans de Goede 			mic_header2[9] = mpdu[25] & 0x00;
1269554c0a3aSHans de Goede 		}
1270554c0a3aSHans de Goede 
1271554c0a3aSHans de Goede 		if (qc_exists && a4_exists) {
1272554c0a3aSHans de Goede 			for (i = 0; i < 6; i++)
1273554c0a3aSHans de Goede 				mic_header2[8+i] = mpdu[24+i];   /* A4 */
1274554c0a3aSHans de Goede 
1275554c0a3aSHans de Goede 			mic_header2[14] = mpdu[30] & 0x0f;
1276554c0a3aSHans de Goede 			mic_header2[15] = mpdu[31] & 0x00;
1277554c0a3aSHans de Goede 		}
1278554c0a3aSHans de Goede 
1279554c0a3aSHans de Goede }
1280554c0a3aSHans de Goede 
1281554c0a3aSHans de Goede /************************************************/
1282554c0a3aSHans de Goede /* construct_mic_header2()                      */
1283554c0a3aSHans de Goede /* Builds the last MIC header block from        */
1284554c0a3aSHans de Goede /* header fields.                               */
1285554c0a3aSHans de Goede /* Baron think the function is construct CCM    */
1286554c0a3aSHans de Goede /* nonce                                        */
1287554c0a3aSHans de Goede /************************************************/
1288554c0a3aSHans de Goede static void construct_ctr_preload(
1289554c0a3aSHans de Goede 	u8 *ctr_preload,
1290554c0a3aSHans de Goede 	sint a4_exists,
1291554c0a3aSHans de Goede 	sint qc_exists,
1292554c0a3aSHans de Goede 	u8 *mpdu,
1293554c0a3aSHans de Goede 	u8 *pn_vector,
1294554c0a3aSHans de Goede 	sint c,
1295554c0a3aSHans de Goede 	uint frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1296554c0a3aSHans de Goede )
1297554c0a3aSHans de Goede {
1298554c0a3aSHans de Goede 	sint i = 0;
1299554c0a3aSHans de Goede 
1300554c0a3aSHans de Goede 	for (i = 0; i < 16; i++)
1301554c0a3aSHans de Goede 		ctr_preload[i] = 0x00;
1302554c0a3aSHans de Goede 	i = 0;
1303554c0a3aSHans de Goede 
1304554c0a3aSHans de Goede 	ctr_preload[0] = 0x01;                                  /* flag */
1305554c0a3aSHans de Goede 	if (qc_exists && a4_exists)
1306554c0a3aSHans de Goede 		ctr_preload[1] = mpdu[30] & 0x0f;   /* QoC_Control */
1307554c0a3aSHans de Goede 	if (qc_exists && !a4_exists)
1308554c0a3aSHans de Goede 		ctr_preload[1] = mpdu[24] & 0x0f;
1309554c0a3aSHans de Goede 
1310554c0a3aSHans de Goede 	/* 802.11w management frame should set management bit(4) */
1311554c0a3aSHans de Goede 	if (frtype == WIFI_MGT_TYPE)
1312554c0a3aSHans de Goede 		ctr_preload[1] |= BIT(4);
1313554c0a3aSHans de Goede 
1314554c0a3aSHans de Goede 	for (i = 2; i < 8; i++)
1315554c0a3aSHans de Goede 		ctr_preload[i] = mpdu[i + 8];                       /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
1316554c0a3aSHans de Goede #ifdef CONSISTENT_PN_ORDER
1317554c0a3aSHans de Goede 	for (i = 8; i < 14; i++)
1318554c0a3aSHans de Goede 		ctr_preload[i] =    pn_vector[i - 8];           /* ctr_preload[8:13] = PN[0:5] */
1319554c0a3aSHans de Goede #else
1320554c0a3aSHans de Goede 	for (i = 8; i < 14; i++)
1321554c0a3aSHans de Goede 		ctr_preload[i] =    pn_vector[13 - i];          /* ctr_preload[8:13] = PN[5:0] */
1322554c0a3aSHans de Goede #endif
1323554c0a3aSHans de Goede 	ctr_preload[14] =  (unsigned char) (c / 256); /* Ctr */
1324554c0a3aSHans de Goede 	ctr_preload[15] =  (unsigned char) (c % 256);
1325554c0a3aSHans de Goede }
1326554c0a3aSHans de Goede 
1327554c0a3aSHans de Goede 
1328554c0a3aSHans de Goede /************************************/
1329554c0a3aSHans de Goede /* bitwise_xor()                    */
1330554c0a3aSHans de Goede /* A 128 bit, bitwise exclusive or  */
1331554c0a3aSHans de Goede /************************************/
1332554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
1333554c0a3aSHans de Goede {
1334554c0a3aSHans de Goede 		sint i;
1335554c0a3aSHans de Goede 
1336554c0a3aSHans de Goede 		for (i = 0; i < 16; i++) {
1337554c0a3aSHans de Goede 			out[i] = ina[i] ^ inb[i];
1338554c0a3aSHans de Goede 		}
1339554c0a3aSHans de Goede }
1340554c0a3aSHans de Goede 
1341554c0a3aSHans de Goede 
1342554c0a3aSHans de Goede static sint aes_cipher(u8 *key, uint	hdrlen,
1343554c0a3aSHans de Goede 			u8 *pframe, uint plen)
1344554c0a3aSHans de Goede {
1345554c0a3aSHans de Goede 	uint	qc_exists, a4_exists, i, j, payload_remainder,
1346554c0a3aSHans de Goede 		num_blocks, payload_index;
1347554c0a3aSHans de Goede 
1348554c0a3aSHans de Goede 	u8 pn_vector[6];
1349554c0a3aSHans de Goede 	u8 mic_iv[16];
1350554c0a3aSHans de Goede 	u8 mic_header1[16];
1351554c0a3aSHans de Goede 	u8 mic_header2[16];
1352554c0a3aSHans de Goede 	u8 ctr_preload[16];
1353554c0a3aSHans de Goede 
1354554c0a3aSHans de Goede 	/* Intermediate Buffers */
1355554c0a3aSHans de Goede 	u8 chain_buffer[16];
1356554c0a3aSHans de Goede 	u8 aes_out[16];
1357554c0a3aSHans de Goede 	u8 padded_buffer[16];
1358554c0a3aSHans de Goede 	u8 mic[8];
1359554c0a3aSHans de Goede 	uint	frtype  = GetFrameType(pframe);
1360554c0a3aSHans de Goede 	uint	frsubtype  = GetFrameSubType(pframe);
1361554c0a3aSHans de Goede 
1362554c0a3aSHans de Goede 	frsubtype = frsubtype>>4;
1363554c0a3aSHans de Goede 
1364554c0a3aSHans de Goede 
1365554c0a3aSHans de Goede 	memset((void *)mic_iv, 0, 16);
1366554c0a3aSHans de Goede 	memset((void *)mic_header1, 0, 16);
1367554c0a3aSHans de Goede 	memset((void *)mic_header2, 0, 16);
1368554c0a3aSHans de Goede 	memset((void *)ctr_preload, 0, 16);
1369554c0a3aSHans de Goede 	memset((void *)chain_buffer, 0, 16);
1370554c0a3aSHans de Goede 	memset((void *)aes_out, 0, 16);
1371554c0a3aSHans de Goede 	memset((void *)padded_buffer, 0, 16);
1372554c0a3aSHans de Goede 
1373554c0a3aSHans de Goede 	if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
1374554c0a3aSHans de Goede 		a4_exists = 0;
1375554c0a3aSHans de Goede 	else
1376554c0a3aSHans de Goede 		a4_exists = 1;
1377554c0a3aSHans de Goede 
1378554c0a3aSHans de Goede 	if (
1379554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFACK) ||
1380554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
1381554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
1382554c0a3aSHans de Goede 			qc_exists = 1;
1383554c0a3aSHans de Goede 					if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
1384554c0a3aSHans de Goede 						hdrlen += 2;
1385554c0a3aSHans de Goede 
1386554c0a3aSHans de Goede 		} else if ((frtype == WIFI_DATA) && /*  add for CONFIG_IEEE80211W, none 11w also can use */
1387554c0a3aSHans de Goede 		((frsubtype == 0x08) ||
1388554c0a3aSHans de Goede 		(frsubtype == 0x09) ||
1389554c0a3aSHans de Goede 		(frsubtype == 0x0a) ||
1390554c0a3aSHans de Goede 		(frsubtype == 0x0b))) {
1391554c0a3aSHans de Goede 			if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
1392554c0a3aSHans de Goede 					hdrlen += 2;
1393554c0a3aSHans de Goede 
1394554c0a3aSHans de Goede 			qc_exists = 1;
1395554c0a3aSHans de Goede 		} else
1396554c0a3aSHans de Goede 			qc_exists = 0;
1397554c0a3aSHans de Goede 
1398554c0a3aSHans de Goede 	pn_vector[0] = pframe[hdrlen];
1399554c0a3aSHans de Goede 	pn_vector[1] = pframe[hdrlen+1];
1400554c0a3aSHans de Goede 	pn_vector[2] = pframe[hdrlen+4];
1401554c0a3aSHans de Goede 	pn_vector[3] = pframe[hdrlen+5];
1402554c0a3aSHans de Goede 	pn_vector[4] = pframe[hdrlen+6];
1403554c0a3aSHans de Goede 	pn_vector[5] = pframe[hdrlen+7];
1404554c0a3aSHans de Goede 
1405554c0a3aSHans de Goede 	construct_mic_iv(
1406554c0a3aSHans de Goede 			mic_iv,
1407554c0a3aSHans de Goede 			qc_exists,
1408554c0a3aSHans de Goede 			a4_exists,
1409554c0a3aSHans de Goede 			pframe,	 /* message, */
1410554c0a3aSHans de Goede 			plen,
1411554c0a3aSHans de Goede 			pn_vector,
1412554c0a3aSHans de Goede 			frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1413554c0a3aSHans de Goede 		);
1414554c0a3aSHans de Goede 
1415554c0a3aSHans de Goede 		construct_mic_header1(
1416554c0a3aSHans de Goede 			mic_header1,
1417554c0a3aSHans de Goede 			hdrlen,
1418554c0a3aSHans de Goede 			pframe,	/* message */
1419554c0a3aSHans de Goede 			frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1420554c0a3aSHans de Goede 		);
1421554c0a3aSHans de Goede 		construct_mic_header2(
1422554c0a3aSHans de Goede 			mic_header2,
1423554c0a3aSHans de Goede 			pframe,	/* message, */
1424554c0a3aSHans de Goede 			a4_exists,
1425554c0a3aSHans de Goede 			qc_exists
1426554c0a3aSHans de Goede 		);
1427554c0a3aSHans de Goede 
1428554c0a3aSHans de Goede 
1429554c0a3aSHans de Goede 	payload_remainder = plen % 16;
1430554c0a3aSHans de Goede 		num_blocks = plen / 16;
1431554c0a3aSHans de Goede 
1432554c0a3aSHans de Goede 		/* Find start of payload */
1433554c0a3aSHans de Goede 		payload_index = (hdrlen + 8);
1434554c0a3aSHans de Goede 
1435554c0a3aSHans de Goede 		/* Calculate MIC */
1436554c0a3aSHans de Goede 		aes128k128d(key, mic_iv, aes_out);
1437554c0a3aSHans de Goede 		bitwise_xor(aes_out, mic_header1, chain_buffer);
1438554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1439554c0a3aSHans de Goede 		bitwise_xor(aes_out, mic_header2, chain_buffer);
1440554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1441554c0a3aSHans de Goede 
1442554c0a3aSHans de Goede 		for (i = 0; i < num_blocks; i++) {
1443554c0a3aSHans de Goede 			bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
1444554c0a3aSHans de Goede 
1445554c0a3aSHans de Goede 			payload_index += 16;
1446554c0a3aSHans de Goede 			aes128k128d(key, chain_buffer, aes_out);
1447554c0a3aSHans de Goede 		}
1448554c0a3aSHans de Goede 
1449554c0a3aSHans de Goede 		/* Add on the final payload block if it needs padding */
1450554c0a3aSHans de Goede 		if (payload_remainder > 0) {
1451554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1452554c0a3aSHans de Goede 				padded_buffer[j] = 0x00;
1453554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++) {
1454554c0a3aSHans de Goede 				padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */
1455554c0a3aSHans de Goede 			}
1456554c0a3aSHans de Goede 			bitwise_xor(aes_out, padded_buffer, chain_buffer);
1457554c0a3aSHans de Goede 			aes128k128d(key, chain_buffer, aes_out);
1458554c0a3aSHans de Goede 
1459554c0a3aSHans de Goede 		}
1460554c0a3aSHans de Goede 
1461554c0a3aSHans de Goede 		for (j = 0 ; j < 8; j++)
1462554c0a3aSHans de Goede 			mic[j] = aes_out[j];
1463554c0a3aSHans de Goede 
1464554c0a3aSHans de Goede 		/* Insert MIC into payload */
1465554c0a3aSHans de Goede 		for (j = 0; j < 8; j++)
1466554c0a3aSHans de Goede 			pframe[payload_index+j] = mic[j];	/* message[payload_index+j] = mic[j]; */
1467554c0a3aSHans de Goede 
1468554c0a3aSHans de Goede 		payload_index = hdrlen + 8;
1469554c0a3aSHans de Goede 		for (i = 0; i < num_blocks; i++) {
1470554c0a3aSHans de Goede 			construct_ctr_preload(
1471554c0a3aSHans de Goede 				ctr_preload,
1472554c0a3aSHans de Goede 				a4_exists,
1473554c0a3aSHans de Goede 				qc_exists,
1474554c0a3aSHans de Goede 				pframe,	/* message, */
1475554c0a3aSHans de Goede 				pn_vector,
1476554c0a3aSHans de Goede 				i+1,
1477554c0a3aSHans de Goede 				frtype
1478554c0a3aSHans de Goede 			); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1479554c0a3aSHans de Goede 			aes128k128d(key, ctr_preload, aes_out);
1480554c0a3aSHans de Goede 			bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */
1481554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1482554c0a3aSHans de Goede 				pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<16;j++) message[payload_index++] = chain_buffer[j]; */
1483554c0a3aSHans de Goede 		}
1484554c0a3aSHans de Goede 
1485554c0a3aSHans de Goede 		if (payload_remainder > 0) {
1486554c0a3aSHans de Goede 			/* If there is a short final block, then pad it,*/
1487554c0a3aSHans de Goede 			/* encrypt it and copy the unpadded part back   */
1488554c0a3aSHans de Goede 			construct_ctr_preload(
1489554c0a3aSHans de Goede 				ctr_preload,
1490554c0a3aSHans de Goede 				a4_exists,
1491554c0a3aSHans de Goede 				qc_exists,
1492554c0a3aSHans de Goede 				pframe,	/* message, */
1493554c0a3aSHans de Goede 				pn_vector,
1494554c0a3aSHans de Goede 				num_blocks+1,
1495554c0a3aSHans de Goede 				frtype
1496554c0a3aSHans de Goede 			); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1497554c0a3aSHans de Goede 
1498554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1499554c0a3aSHans de Goede 				padded_buffer[j] = 0x00;
1500554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++) {
1501554c0a3aSHans de Goede 				padded_buffer[j] = pframe[payload_index+j];/* padded_buffer[j] = message[payload_index+j]; */
1502554c0a3aSHans de Goede 			}
1503554c0a3aSHans de Goede 			aes128k128d(key, ctr_preload, aes_out);
1504554c0a3aSHans de Goede 			bitwise_xor(aes_out, padded_buffer, chain_buffer);
1505554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++)
1506554c0a3aSHans de Goede 				pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<payload_remainder;j++) message[payload_index++] = chain_buffer[j]; */
1507554c0a3aSHans de Goede 		}
1508554c0a3aSHans de Goede 
1509554c0a3aSHans de Goede 		/* Encrypt the MIC */
1510554c0a3aSHans de Goede 		construct_ctr_preload(
1511554c0a3aSHans de Goede 			ctr_preload,
1512554c0a3aSHans de Goede 			a4_exists,
1513554c0a3aSHans de Goede 			qc_exists,
1514554c0a3aSHans de Goede 			pframe,	/* message, */
1515554c0a3aSHans de Goede 			pn_vector,
1516554c0a3aSHans de Goede 			0,
1517554c0a3aSHans de Goede 			frtype
1518554c0a3aSHans de Goede 		); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1519554c0a3aSHans de Goede 
1520554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1521554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
1522554c0a3aSHans de Goede 		for (j = 0; j < 8; j++) {
1523554c0a3aSHans de Goede 			padded_buffer[j] = pframe[j+hdrlen+8+plen];/* padded_buffer[j] = message[j+hdrlen+8+plen]; */
1524554c0a3aSHans de Goede 		}
1525554c0a3aSHans de Goede 
1526554c0a3aSHans de Goede 	aes128k128d(key, ctr_preload, aes_out);
1527554c0a3aSHans de Goede 	bitwise_xor(aes_out, padded_buffer, chain_buffer);
1528554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
1529554c0a3aSHans de Goede 		 pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<8;j++) message[payload_index++] = chain_buffer[j]; */
1530554c0a3aSHans de Goede 
1531554c0a3aSHans de Goede 	return _SUCCESS;
1532554c0a3aSHans de Goede }
1533554c0a3aSHans de Goede 
1534554c0a3aSHans de Goede u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
1535554c0a3aSHans de Goede {	/*  exclude ICV */
1536554c0a3aSHans de Goede 
1537554c0a3aSHans de Goede 
1538554c0a3aSHans de Goede 	/*static*/
1539554c0a3aSHans de Goede /* 	unsigned char message[MAX_MSG_SIZE]; */
1540554c0a3aSHans de Goede 
1541554c0a3aSHans de Goede 	/* Intermediate Buffers */
1542554c0a3aSHans de Goede 	sint	curfragnum, length;
1543554c0a3aSHans de Goede 	u32 prwskeylen;
1544554c0a3aSHans de Goede 	u8 *pframe, *prwskey;	/*  *payload,*iv */
1545554c0a3aSHans de Goede 	u8   hw_hdr_offset = 0;
1546554c0a3aSHans de Goede 	/* struct	sta_info 	*stainfo = NULL; */
1547554c0a3aSHans de Goede 	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
1548554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
1549554c0a3aSHans de Goede 	struct	xmit_priv 	*pxmitpriv = &padapter->xmitpriv;
1550554c0a3aSHans de Goede 
1551554c0a3aSHans de Goede /* 	uint	offset = 0; */
1552554c0a3aSHans de Goede 	u32 res = _SUCCESS;
1553554c0a3aSHans de Goede 
1554554c0a3aSHans de Goede 	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
1555554c0a3aSHans de Goede 		return _FAIL;
1556554c0a3aSHans de Goede 
1557554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
1558554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
1559554c0a3aSHans de Goede 
1560554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
1561554c0a3aSHans de Goede 	if ((pattrib->encrypt == _AES_)) {
1562554c0a3aSHans de Goede 		RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo!= NULL!!!\n"));
1563554c0a3aSHans de Goede 
1564554c0a3aSHans de Goede 		if (IS_MCAST(pattrib->ra))
1565554c0a3aSHans de Goede 			prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
1566554c0a3aSHans de Goede 		else
1567554c0a3aSHans de Goede 			/* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */
1568554c0a3aSHans de Goede 			prwskey = pattrib->dot118021x_UncstKey.skey;
1569554c0a3aSHans de Goede 
1570554c0a3aSHans de Goede 		prwskeylen = 16;
1571554c0a3aSHans de Goede 
1572554c0a3aSHans de Goede 		for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
1573554c0a3aSHans de Goede 
1574554c0a3aSHans de Goede 			if ((curfragnum+1) == pattrib->nr_frags) {	/* 4 the last fragment */
1575554c0a3aSHans de Goede 				length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
1576554c0a3aSHans de Goede 
1577554c0a3aSHans de Goede 				aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1578554c0a3aSHans de Goede 			} else {
1579554c0a3aSHans de Goede 				length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
1580554c0a3aSHans de Goede 
1581554c0a3aSHans de Goede 				aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1582554c0a3aSHans de Goede 			pframe += pxmitpriv->frag_len;
1583554c0a3aSHans de Goede 			pframe = (u8 *)RND4((SIZE_PTR)(pframe));
1584554c0a3aSHans de Goede 
1585554c0a3aSHans de Goede 			}
1586554c0a3aSHans de Goede 		}
1587554c0a3aSHans de Goede 
1588554c0a3aSHans de Goede 		AES_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
1589554c0a3aSHans de Goede 	}
1590554c0a3aSHans de Goede 	return res;
1591554c0a3aSHans de Goede }
1592554c0a3aSHans de Goede 
1593554c0a3aSHans de Goede static sint aes_decipher(u8 *key, uint	hdrlen,
1594554c0a3aSHans de Goede 			u8 *pframe, uint plen)
1595554c0a3aSHans de Goede {
1596554c0a3aSHans de Goede 	static u8 message[MAX_MSG_SIZE];
1597554c0a3aSHans de Goede 	uint	qc_exists, a4_exists, i, j, payload_remainder,
1598554c0a3aSHans de Goede 			num_blocks, payload_index;
1599554c0a3aSHans de Goede 	sint res = _SUCCESS;
1600554c0a3aSHans de Goede 	u8 pn_vector[6];
1601554c0a3aSHans de Goede 	u8 mic_iv[16];
1602554c0a3aSHans de Goede 	u8 mic_header1[16];
1603554c0a3aSHans de Goede 	u8 mic_header2[16];
1604554c0a3aSHans de Goede 	u8 ctr_preload[16];
1605554c0a3aSHans de Goede 
1606554c0a3aSHans de Goede 		/* Intermediate Buffers */
1607554c0a3aSHans de Goede 	u8 chain_buffer[16];
1608554c0a3aSHans de Goede 	u8 aes_out[16];
1609554c0a3aSHans de Goede 	u8 padded_buffer[16];
1610554c0a3aSHans de Goede 	u8 mic[8];
1611554c0a3aSHans de Goede 
1612554c0a3aSHans de Goede 
1613554c0a3aSHans de Goede /* 	uint	offset = 0; */
1614554c0a3aSHans de Goede 	uint	frtype  = GetFrameType(pframe);
1615554c0a3aSHans de Goede 	uint	frsubtype  = GetFrameSubType(pframe);
1616554c0a3aSHans de Goede 
1617554c0a3aSHans de Goede 	frsubtype = frsubtype>>4;
1618554c0a3aSHans de Goede 
1619554c0a3aSHans de Goede 
1620554c0a3aSHans de Goede 	memset((void *)mic_iv, 0, 16);
1621554c0a3aSHans de Goede 	memset((void *)mic_header1, 0, 16);
1622554c0a3aSHans de Goede 	memset((void *)mic_header2, 0, 16);
1623554c0a3aSHans de Goede 	memset((void *)ctr_preload, 0, 16);
1624554c0a3aSHans de Goede 	memset((void *)chain_buffer, 0, 16);
1625554c0a3aSHans de Goede 	memset((void *)aes_out, 0, 16);
1626554c0a3aSHans de Goede 	memset((void *)padded_buffer, 0, 16);
1627554c0a3aSHans de Goede 
1628554c0a3aSHans de Goede 	/* start to decrypt the payload */
1629554c0a3aSHans de Goede 
1630554c0a3aSHans de Goede 	num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */
1631554c0a3aSHans de Goede 
1632554c0a3aSHans de Goede 	payload_remainder = (plen-8) % 16;
1633554c0a3aSHans de Goede 
1634554c0a3aSHans de Goede 	pn_vector[0]  = pframe[hdrlen];
1635554c0a3aSHans de Goede 	pn_vector[1]  = pframe[hdrlen+1];
1636554c0a3aSHans de Goede 	pn_vector[2]  = pframe[hdrlen+4];
1637554c0a3aSHans de Goede 	pn_vector[3]  = pframe[hdrlen+5];
1638554c0a3aSHans de Goede 	pn_vector[4]  = pframe[hdrlen+6];
1639554c0a3aSHans de Goede 	pn_vector[5]  = pframe[hdrlen+7];
1640554c0a3aSHans de Goede 
1641554c0a3aSHans de Goede 	if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
1642554c0a3aSHans de Goede 		a4_exists = 0;
1643554c0a3aSHans de Goede 	else
1644554c0a3aSHans de Goede 		a4_exists = 1;
1645554c0a3aSHans de Goede 
1646554c0a3aSHans de Goede 	if (
1647554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFACK) ||
1648554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
1649554c0a3aSHans de Goede 		((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
1650554c0a3aSHans de Goede 			qc_exists = 1;
1651554c0a3aSHans de Goede 					if (hdrlen !=  WLAN_HDR_A3_QOS_LEN) {
1652554c0a3aSHans de Goede 
1653554c0a3aSHans de Goede 					hdrlen += 2;
1654554c0a3aSHans de Goede 			}
1655554c0a3aSHans de Goede 		} else if ((frtype == WIFI_DATA) && /* only for data packet . add for CONFIG_IEEE80211W, none 11w also can use */
1656554c0a3aSHans de Goede 		((frsubtype == 0x08) ||
1657554c0a3aSHans de Goede 		(frsubtype == 0x09) ||
1658554c0a3aSHans de Goede 		(frsubtype == 0x0a) ||
1659554c0a3aSHans de Goede 		(frsubtype == 0x0b))) {
1660554c0a3aSHans de Goede 			if (hdrlen !=  WLAN_HDR_A3_QOS_LEN) {
1661554c0a3aSHans de Goede 
1662554c0a3aSHans de Goede 					hdrlen += 2;
1663554c0a3aSHans de Goede 			}
1664554c0a3aSHans de Goede 			qc_exists = 1;
1665554c0a3aSHans de Goede 		} else
1666554c0a3aSHans de Goede 			qc_exists = 0;
1667554c0a3aSHans de Goede 
1668554c0a3aSHans de Goede 
1669554c0a3aSHans de Goede 	/*  now, decrypt pframe with hdrlen offset and plen long */
1670554c0a3aSHans de Goede 
1671554c0a3aSHans de Goede 	payload_index = hdrlen + 8; /*  8 is for extiv */
1672554c0a3aSHans de Goede 
1673554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
1674554c0a3aSHans de Goede 			construct_ctr_preload(
1675554c0a3aSHans de Goede 				ctr_preload,
1676554c0a3aSHans de Goede 				a4_exists,
1677554c0a3aSHans de Goede 				qc_exists,
1678554c0a3aSHans de Goede 				pframe,
1679554c0a3aSHans de Goede 				pn_vector,
1680554c0a3aSHans de Goede 				i+1,
1681554c0a3aSHans de Goede 				frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1682554c0a3aSHans de Goede 			);
1683554c0a3aSHans de Goede 
1684554c0a3aSHans de Goede 			aes128k128d(key, ctr_preload, aes_out);
1685554c0a3aSHans de Goede 			bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1686554c0a3aSHans de Goede 
1687554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1688554c0a3aSHans de Goede 				pframe[payload_index++] = chain_buffer[j];
1689554c0a3aSHans de Goede 		}
1690554c0a3aSHans de Goede 
1691554c0a3aSHans de Goede 	if (payload_remainder > 0) {
1692554c0a3aSHans de Goede 		/* If there is a short final block, then pad it,*/
1693554c0a3aSHans de Goede 		/* encrypt it and copy the unpadded part back   */
1694554c0a3aSHans de Goede 		construct_ctr_preload(
1695554c0a3aSHans de Goede 			ctr_preload,
1696554c0a3aSHans de Goede 			a4_exists,
1697554c0a3aSHans de Goede 			qc_exists,
1698554c0a3aSHans de Goede 			pframe,
1699554c0a3aSHans de Goede 			pn_vector,
1700554c0a3aSHans de Goede 			num_blocks+1,
1701554c0a3aSHans de Goede 			frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1702554c0a3aSHans de Goede 		);
1703554c0a3aSHans de Goede 
1704554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1705554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
1706554c0a3aSHans de Goede 		for (j = 0; j < payload_remainder; j++) {
1707554c0a3aSHans de Goede 			padded_buffer[j] = pframe[payload_index+j];
1708554c0a3aSHans de Goede 		}
1709554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1710554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1711554c0a3aSHans de Goede 		for (j = 0; j < payload_remainder; j++)
1712554c0a3aSHans de Goede 			pframe[payload_index++] = chain_buffer[j];
1713554c0a3aSHans de Goede 	}
1714554c0a3aSHans de Goede 
1715554c0a3aSHans de Goede 	/* start to calculate the mic */
1716554c0a3aSHans de Goede 	if ((hdrlen + plen+8) <= MAX_MSG_SIZE)
1717554c0a3aSHans de Goede 		memcpy((void *)message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv len */
1718554c0a3aSHans de Goede 
1719554c0a3aSHans de Goede 
1720554c0a3aSHans de Goede 	pn_vector[0] = pframe[hdrlen];
1721554c0a3aSHans de Goede 	pn_vector[1] = pframe[hdrlen+1];
1722554c0a3aSHans de Goede 	pn_vector[2] = pframe[hdrlen+4];
1723554c0a3aSHans de Goede 	pn_vector[3] = pframe[hdrlen+5];
1724554c0a3aSHans de Goede 	pn_vector[4] = pframe[hdrlen+6];
1725554c0a3aSHans de Goede 	pn_vector[5] = pframe[hdrlen+7];
1726554c0a3aSHans de Goede 
1727554c0a3aSHans de Goede 
1728554c0a3aSHans de Goede 
1729554c0a3aSHans de Goede 	construct_mic_iv(
1730554c0a3aSHans de Goede 			mic_iv,
1731554c0a3aSHans de Goede 			qc_exists,
1732554c0a3aSHans de Goede 			a4_exists,
1733554c0a3aSHans de Goede 			message,
1734554c0a3aSHans de Goede 			plen-8,
1735554c0a3aSHans de Goede 			pn_vector,
1736554c0a3aSHans de Goede 			frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1737554c0a3aSHans de Goede 		);
1738554c0a3aSHans de Goede 
1739554c0a3aSHans de Goede 		construct_mic_header1(
1740554c0a3aSHans de Goede 			mic_header1,
1741554c0a3aSHans de Goede 			hdrlen,
1742554c0a3aSHans de Goede 			message,
1743554c0a3aSHans de Goede 			frtype /*  add for CONFIG_IEEE80211W, none 11w also can use */
1744554c0a3aSHans de Goede 		);
1745554c0a3aSHans de Goede 		construct_mic_header2(
1746554c0a3aSHans de Goede 			mic_header2,
1747554c0a3aSHans de Goede 			message,
1748554c0a3aSHans de Goede 			a4_exists,
1749554c0a3aSHans de Goede 			qc_exists
1750554c0a3aSHans de Goede 		);
1751554c0a3aSHans de Goede 
1752554c0a3aSHans de Goede 
1753554c0a3aSHans de Goede 		payload_remainder = (plen-8) % 16;
1754554c0a3aSHans de Goede 		num_blocks = (plen-8) / 16;
1755554c0a3aSHans de Goede 
1756554c0a3aSHans de Goede 		/* Find start of payload */
1757554c0a3aSHans de Goede 		payload_index = (hdrlen + 8);
1758554c0a3aSHans de Goede 
1759554c0a3aSHans de Goede 		/* Calculate MIC */
1760554c0a3aSHans de Goede 		aes128k128d(key, mic_iv, aes_out);
1761554c0a3aSHans de Goede 		bitwise_xor(aes_out, mic_header1, chain_buffer);
1762554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1763554c0a3aSHans de Goede 		bitwise_xor(aes_out, mic_header2, chain_buffer);
1764554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1765554c0a3aSHans de Goede 
1766554c0a3aSHans de Goede 		for (i = 0; i < num_blocks; i++) {
1767554c0a3aSHans de Goede 			bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1768554c0a3aSHans de Goede 
1769554c0a3aSHans de Goede 			payload_index += 16;
1770554c0a3aSHans de Goede 			aes128k128d(key, chain_buffer, aes_out);
1771554c0a3aSHans de Goede 		}
1772554c0a3aSHans de Goede 
1773554c0a3aSHans de Goede 		/* Add on the final payload block if it needs padding */
1774554c0a3aSHans de Goede 		if (payload_remainder > 0) {
1775554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1776554c0a3aSHans de Goede 				padded_buffer[j] = 0x00;
1777554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++) {
1778554c0a3aSHans de Goede 				padded_buffer[j] = message[payload_index++];
1779554c0a3aSHans de Goede 			}
1780554c0a3aSHans de Goede 			bitwise_xor(aes_out, padded_buffer, chain_buffer);
1781554c0a3aSHans de Goede 			aes128k128d(key, chain_buffer, aes_out);
1782554c0a3aSHans de Goede 
1783554c0a3aSHans de Goede 		}
1784554c0a3aSHans de Goede 
1785554c0a3aSHans de Goede 		for (j = 0; j < 8; j++)
1786554c0a3aSHans de Goede 			mic[j] = aes_out[j];
1787554c0a3aSHans de Goede 
1788554c0a3aSHans de Goede 		/* Insert MIC into payload */
1789554c0a3aSHans de Goede 		for (j = 0; j < 8; j++)
1790554c0a3aSHans de Goede 	message[payload_index+j] = mic[j];
1791554c0a3aSHans de Goede 
1792554c0a3aSHans de Goede 	payload_index = hdrlen + 8;
1793554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
1794554c0a3aSHans de Goede 			construct_ctr_preload(
1795554c0a3aSHans de Goede 				ctr_preload,
1796554c0a3aSHans de Goede 				a4_exists,
1797554c0a3aSHans de Goede 				qc_exists,
1798554c0a3aSHans de Goede 				message,
1799554c0a3aSHans de Goede 				pn_vector,
1800554c0a3aSHans de Goede 				i+1,
1801554c0a3aSHans de Goede 				frtype
1802554c0a3aSHans de Goede 			); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1803554c0a3aSHans de Goede 			aes128k128d(key, ctr_preload, aes_out);
1804554c0a3aSHans de Goede 			bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1805554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1806554c0a3aSHans de Goede 				message[payload_index++] = chain_buffer[j];
1807554c0a3aSHans de Goede 		}
1808554c0a3aSHans de Goede 
1809554c0a3aSHans de Goede 		if (payload_remainder > 0) {
1810554c0a3aSHans de Goede 			/* If there is a short final block, then pad it,*/
1811554c0a3aSHans de Goede 			/* encrypt it and copy the unpadded part back   */
1812554c0a3aSHans de Goede 			construct_ctr_preload(
1813554c0a3aSHans de Goede 				ctr_preload,
1814554c0a3aSHans de Goede 				a4_exists,
1815554c0a3aSHans de Goede 				qc_exists,
1816554c0a3aSHans de Goede 				message,
1817554c0a3aSHans de Goede 				pn_vector,
1818554c0a3aSHans de Goede 				num_blocks+1,
1819554c0a3aSHans de Goede 				frtype
1820554c0a3aSHans de Goede 			); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1821554c0a3aSHans de Goede 
1822554c0a3aSHans de Goede 			for (j = 0; j < 16; j++)
1823554c0a3aSHans de Goede 				padded_buffer[j] = 0x00;
1824554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++) {
1825554c0a3aSHans de Goede 				padded_buffer[j] = message[payload_index+j];
1826554c0a3aSHans de Goede 			}
1827554c0a3aSHans de Goede 			aes128k128d(key, ctr_preload, aes_out);
1828554c0a3aSHans de Goede 			bitwise_xor(aes_out, padded_buffer, chain_buffer);
1829554c0a3aSHans de Goede 			for (j = 0; j < payload_remainder; j++)
1830554c0a3aSHans de Goede 				message[payload_index++] = chain_buffer[j];
1831554c0a3aSHans de Goede 		}
1832554c0a3aSHans de Goede 
1833554c0a3aSHans de Goede 		/* Encrypt the MIC */
1834554c0a3aSHans de Goede 		construct_ctr_preload(
1835554c0a3aSHans de Goede 			ctr_preload,
1836554c0a3aSHans de Goede 			a4_exists,
1837554c0a3aSHans de Goede 			qc_exists,
1838554c0a3aSHans de Goede 			message,
1839554c0a3aSHans de Goede 			pn_vector,
1840554c0a3aSHans de Goede 			0,
1841554c0a3aSHans de Goede 			frtype
1842554c0a3aSHans de Goede 		); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1843554c0a3aSHans de Goede 
1844554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1845554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
1846554c0a3aSHans de Goede 		for (j = 0; j < 8; j++) {
1847554c0a3aSHans de Goede 			padded_buffer[j] = message[j+hdrlen+8+plen-8];
1848554c0a3aSHans de Goede 		}
1849554c0a3aSHans de Goede 
1850554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1851554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1852554c0a3aSHans de Goede 		for (j = 0; j < 8; j++)
1853554c0a3aSHans de Goede 			message[payload_index++] = chain_buffer[j];
1854554c0a3aSHans de Goede 
1855554c0a3aSHans de Goede 	/* compare the mic */
1856554c0a3aSHans de Goede 	for (i = 0; i < 8; i++) {
1857554c0a3aSHans de Goede 		if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
1858554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1859554c0a3aSHans de Goede 						i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]));
1860554c0a3aSHans de Goede 			DBG_871X("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n",
1861554c0a3aSHans de Goede 						i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]);
1862554c0a3aSHans de Goede 			res = _FAIL;
1863554c0a3aSHans de Goede 		}
1864554c0a3aSHans de Goede 	}
1865554c0a3aSHans de Goede 	return res;
1866554c0a3aSHans de Goede }
1867554c0a3aSHans de Goede 
1868554c0a3aSHans de Goede u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
1869554c0a3aSHans de Goede {	/*  exclude ICV */
1870554c0a3aSHans de Goede 
1871554c0a3aSHans de Goede 
1872554c0a3aSHans de Goede 	/*static*/
1873554c0a3aSHans de Goede /* 	unsigned char message[MAX_MSG_SIZE]; */
1874554c0a3aSHans de Goede 
1875554c0a3aSHans de Goede 
1876554c0a3aSHans de Goede 	/* Intermediate Buffers */
1877554c0a3aSHans de Goede 
1878554c0a3aSHans de Goede 
1879554c0a3aSHans de Goede 	sint		length;
1880554c0a3aSHans de Goede 	u8 *pframe, *prwskey;	/*  *payload,*iv */
1881554c0a3aSHans de Goede 	struct	sta_info 	*stainfo;
1882554c0a3aSHans de Goede 	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
1883554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
1884554c0a3aSHans de Goede /* 	struct	recv_priv 	*precvpriv =&padapter->recvpriv; */
1885554c0a3aSHans de Goede 	u32 res = _SUCCESS;
1886554c0a3aSHans de Goede 
1887554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
1888554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
1889554c0a3aSHans de Goede 	if ((prxattrib->encrypt == _AES_)) {
1890554c0a3aSHans de Goede 
1891554c0a3aSHans de Goede 		stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
1892554c0a3aSHans de Goede 		if (stainfo != NULL) {
1893554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo!= NULL!!!\n"));
1894554c0a3aSHans de Goede 
1895554c0a3aSHans de Goede 			if (IS_MCAST(prxattrib->ra)) {
1896554c0a3aSHans de Goede 				static unsigned long start = 0;
1897554c0a3aSHans de Goede 				static u32 no_gkey_bc_cnt = 0;
1898554c0a3aSHans de Goede 				static u32 no_gkey_mc_cnt = 0;
1899554c0a3aSHans de Goede 
1900554c0a3aSHans de Goede 				/* DBG_871X("rx bc/mc packets, to perform sw rtw_aes_decrypt\n"); */
1901554c0a3aSHans de Goede 				/* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */
1902554c0a3aSHans de Goede 				if (psecuritypriv->binstallGrpkey == false) {
1903554c0a3aSHans de Goede 					res = _FAIL;
1904554c0a3aSHans de Goede 
1905554c0a3aSHans de Goede 					if (start == 0)
1906554c0a3aSHans de Goede 						start = jiffies;
1907554c0a3aSHans de Goede 
1908554c0a3aSHans de Goede 					if (is_broadcast_mac_addr(prxattrib->ra))
1909554c0a3aSHans de Goede 						no_gkey_bc_cnt++;
1910554c0a3aSHans de Goede 					else
1911554c0a3aSHans de Goede 						no_gkey_mc_cnt++;
1912554c0a3aSHans de Goede 
1913554c0a3aSHans de Goede 					if (jiffies_to_msecs(jiffies - start) > 1000) {
1914554c0a3aSHans de Goede 						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
1915554c0a3aSHans de Goede 							DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
1916554c0a3aSHans de Goede 								FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
1917554c0a3aSHans de Goede 						}
1918554c0a3aSHans de Goede 						start = jiffies;
1919554c0a3aSHans de Goede 						no_gkey_bc_cnt = 0;
1920554c0a3aSHans de Goede 						no_gkey_mc_cnt = 0;
1921554c0a3aSHans de Goede 					}
1922554c0a3aSHans de Goede 
1923554c0a3aSHans de Goede 					goto exit;
1924554c0a3aSHans de Goede 				}
1925554c0a3aSHans de Goede 
1926554c0a3aSHans de Goede 				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
1927554c0a3aSHans de Goede 					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
1928554c0a3aSHans de Goede 						FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
1929554c0a3aSHans de Goede 				}
1930554c0a3aSHans de Goede 				start = 0;
1931554c0a3aSHans de Goede 				no_gkey_bc_cnt = 0;
1932554c0a3aSHans de Goede 				no_gkey_mc_cnt = 0;
1933554c0a3aSHans de Goede 
1934554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
1935554c0a3aSHans de Goede 				if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
1936554c0a3aSHans de Goede 					DBG_871X("not match packet_index =%d, install_index =%d\n"
1937554c0a3aSHans de Goede 					, prxattrib->key_index, psecuritypriv->dot118021XGrpKeyid);
1938554c0a3aSHans de Goede 					res = _FAIL;
1939554c0a3aSHans de Goede 					goto exit;
1940554c0a3aSHans de Goede 				}
1941554c0a3aSHans de Goede 			} else
1942554c0a3aSHans de Goede 				prwskey = &stainfo->dot118021x_UncstKey.skey[0];
1943554c0a3aSHans de Goede 
1944554c0a3aSHans de Goede 
1945554c0a3aSHans de Goede 			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
1946554c0a3aSHans de Goede 
1947554c0a3aSHans de Goede 			res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
1948554c0a3aSHans de Goede 
1949554c0a3aSHans de Goede 			AES_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
1950554c0a3aSHans de Goede 		} else {
1951554c0a3aSHans de Goede 			RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo == NULL!!!\n"));
1952554c0a3aSHans de Goede 			res = _FAIL;
1953554c0a3aSHans de Goede 		}
1954554c0a3aSHans de Goede 	}
1955554c0a3aSHans de Goede exit:
1956554c0a3aSHans de Goede 	return res;
1957554c0a3aSHans de Goede }
1958554c0a3aSHans de Goede 
1959554c0a3aSHans de Goede u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe)
1960554c0a3aSHans de Goede {
1961554c0a3aSHans de Goede 	struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
1962554c0a3aSHans de Goede 	u8 *pframe;
1963554c0a3aSHans de Goede 	u8 *BIP_AAD, *p;
1964554c0a3aSHans de Goede 	u32 res = _FAIL;
1965554c0a3aSHans de Goede 	uint len, ori_len;
1966554c0a3aSHans de Goede 	struct ieee80211_hdr *pwlanhdr;
1967554c0a3aSHans de Goede 	u8 mic[16];
1968554c0a3aSHans de Goede 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1969554c0a3aSHans de Goede 	__le16 le_tmp;
1970554c0a3aSHans de Goede 	__le64 le_tmp64;
1971554c0a3aSHans de Goede 
1972554c0a3aSHans de Goede 	ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
1973554c0a3aSHans de Goede 	BIP_AAD = rtw_zmalloc(ori_len);
1974554c0a3aSHans de Goede 
1975554c0a3aSHans de Goede 	if (BIP_AAD == NULL) {
1976554c0a3aSHans de Goede 		DBG_871X("BIP AAD allocate fail\n");
1977554c0a3aSHans de Goede 		return _FAIL;
1978554c0a3aSHans de Goede 	}
1979554c0a3aSHans de Goede 	/* PKT start */
1980554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
1981554c0a3aSHans de Goede 	/* mapping to wlan header */
1982554c0a3aSHans de Goede 	pwlanhdr = (struct ieee80211_hdr *)pframe;
1983554c0a3aSHans de Goede 	/* save the frame body + MME */
1984554c0a3aSHans de Goede 	memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN);
1985554c0a3aSHans de Goede 	/* find MME IE pointer */
1986554c0a3aSHans de Goede 	p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN);
1987554c0a3aSHans de Goede 	/* Baron */
1988554c0a3aSHans de Goede 	if (p) {
1989554c0a3aSHans de Goede 		u16 keyid = 0;
1990554c0a3aSHans de Goede 		u64 temp_ipn = 0;
1991554c0a3aSHans de Goede 		/* save packet number */
1992554c0a3aSHans de Goede 		memcpy(&le_tmp64, p+4, 6);
1993554c0a3aSHans de Goede 		temp_ipn = le64_to_cpu(le_tmp64);
1994554c0a3aSHans de Goede 		/* BIP packet number should bigger than previous BIP packet */
1995554c0a3aSHans de Goede 		if (temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx) {
1996554c0a3aSHans de Goede 			DBG_871X("replay BIP packet\n");
1997554c0a3aSHans de Goede 			goto BIP_exit;
1998554c0a3aSHans de Goede 		}
1999554c0a3aSHans de Goede 		/* copy key index */
2000554c0a3aSHans de Goede 		memcpy(&le_tmp, p+2, 2);
2001554c0a3aSHans de Goede 		keyid = le16_to_cpu(le_tmp);
2002554c0a3aSHans de Goede 		if (keyid != padapter->securitypriv.dot11wBIPKeyid) {
2003554c0a3aSHans de Goede 			DBG_871X("BIP key index error!\n");
2004554c0a3aSHans de Goede 			goto BIP_exit;
2005554c0a3aSHans de Goede 		}
2006554c0a3aSHans de Goede 		/* clear the MIC field of MME to zero */
2007554c0a3aSHans de Goede 		memset(p+2+len-8, 0, 8);
2008554c0a3aSHans de Goede 
2009554c0a3aSHans de Goede 		/* conscruct AAD, copy frame control field */
2010554c0a3aSHans de Goede 		memcpy(BIP_AAD, &pwlanhdr->frame_control, 2);
2011554c0a3aSHans de Goede 		ClearRetry(BIP_AAD);
2012554c0a3aSHans de Goede 		ClearPwrMgt(BIP_AAD);
2013554c0a3aSHans de Goede 		ClearMData(BIP_AAD);
2014554c0a3aSHans de Goede 		/* conscruct AAD, copy address 1 to address 3 */
2015554c0a3aSHans de Goede 		memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
2016554c0a3aSHans de Goede 
2017554c0a3aSHans de Goede 		if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
2018554c0a3aSHans de Goede 			, BIP_AAD, ori_len, mic))
2019554c0a3aSHans de Goede 			goto BIP_exit;
2020554c0a3aSHans de Goede 
2021554c0a3aSHans de Goede 		/* MIC field should be last 8 bytes of packet (packet without FCS) */
2022554c0a3aSHans de Goede 		if (!memcmp(mic, pframe+pattrib->pkt_len-8, 8)) {
2023554c0a3aSHans de Goede 			pmlmeext->mgnt_80211w_IPN_rx = temp_ipn;
2024554c0a3aSHans de Goede 			res = _SUCCESS;
2025554c0a3aSHans de Goede 		} else
2026554c0a3aSHans de Goede 			DBG_871X("BIP MIC error!\n");
2027554c0a3aSHans de Goede 
2028554c0a3aSHans de Goede 	} else
2029554c0a3aSHans de Goede 		res = RTW_RX_HANDLED;
2030554c0a3aSHans de Goede BIP_exit:
2031554c0a3aSHans de Goede 
2032554c0a3aSHans de Goede 	kfree(BIP_AAD);
2033554c0a3aSHans de Goede 	return res;
2034554c0a3aSHans de Goede }
2035554c0a3aSHans de Goede 
2036554c0a3aSHans de Goede /* AES tables*/
2037554c0a3aSHans de Goede const u32 Te0[256] = {
2038554c0a3aSHans de Goede 	0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
2039554c0a3aSHans de Goede 	0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
2040554c0a3aSHans de Goede 	0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
2041554c0a3aSHans de Goede 	0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
2042554c0a3aSHans de Goede 	0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
2043554c0a3aSHans de Goede 	0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
2044554c0a3aSHans de Goede 	0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
2045554c0a3aSHans de Goede 	0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
2046554c0a3aSHans de Goede 	0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
2047554c0a3aSHans de Goede 	0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
2048554c0a3aSHans de Goede 	0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
2049554c0a3aSHans de Goede 	0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
2050554c0a3aSHans de Goede 	0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
2051554c0a3aSHans de Goede 	0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
2052554c0a3aSHans de Goede 	0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
2053554c0a3aSHans de Goede 	0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
2054554c0a3aSHans de Goede 	0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
2055554c0a3aSHans de Goede 	0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
2056554c0a3aSHans de Goede 	0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
2057554c0a3aSHans de Goede 	0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
2058554c0a3aSHans de Goede 	0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
2059554c0a3aSHans de Goede 	0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
2060554c0a3aSHans de Goede 	0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
2061554c0a3aSHans de Goede 	0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
2062554c0a3aSHans de Goede 	0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
2063554c0a3aSHans de Goede 	0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
2064554c0a3aSHans de Goede 	0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
2065554c0a3aSHans de Goede 	0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
2066554c0a3aSHans de Goede 	0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
2067554c0a3aSHans de Goede 	0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
2068554c0a3aSHans de Goede 	0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
2069554c0a3aSHans de Goede 	0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
2070554c0a3aSHans de Goede 	0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
2071554c0a3aSHans de Goede 	0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
2072554c0a3aSHans de Goede 	0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
2073554c0a3aSHans de Goede 	0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
2074554c0a3aSHans de Goede 	0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
2075554c0a3aSHans de Goede 	0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
2076554c0a3aSHans de Goede 	0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
2077554c0a3aSHans de Goede 	0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
2078554c0a3aSHans de Goede 	0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
2079554c0a3aSHans de Goede 	0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
2080554c0a3aSHans de Goede 	0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
2081554c0a3aSHans de Goede 	0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
2082554c0a3aSHans de Goede 	0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
2083554c0a3aSHans de Goede 	0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
2084554c0a3aSHans de Goede 	0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
2085554c0a3aSHans de Goede 	0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
2086554c0a3aSHans de Goede 	0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
2087554c0a3aSHans de Goede 	0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
2088554c0a3aSHans de Goede 	0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
2089554c0a3aSHans de Goede 	0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
2090554c0a3aSHans de Goede 	0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
2091554c0a3aSHans de Goede 	0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
2092554c0a3aSHans de Goede 	0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
2093554c0a3aSHans de Goede 	0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
2094554c0a3aSHans de Goede 	0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
2095554c0a3aSHans de Goede 	0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
2096554c0a3aSHans de Goede 	0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
2097554c0a3aSHans de Goede 	0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
2098554c0a3aSHans de Goede 	0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
2099554c0a3aSHans de Goede 	0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
2100554c0a3aSHans de Goede 	0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
2101554c0a3aSHans de Goede 	0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
2102554c0a3aSHans de Goede };
2103554c0a3aSHans de Goede const u32 Td0[256] = {
2104554c0a3aSHans de Goede 	0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
2105554c0a3aSHans de Goede 	0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
2106554c0a3aSHans de Goede 	0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
2107554c0a3aSHans de Goede 	0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
2108554c0a3aSHans de Goede 	0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
2109554c0a3aSHans de Goede 	0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
2110554c0a3aSHans de Goede 	0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
2111554c0a3aSHans de Goede 	0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
2112554c0a3aSHans de Goede 	0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
2113554c0a3aSHans de Goede 	0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
2114554c0a3aSHans de Goede 	0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
2115554c0a3aSHans de Goede 	0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
2116554c0a3aSHans de Goede 	0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
2117554c0a3aSHans de Goede 	0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
2118554c0a3aSHans de Goede 	0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
2119554c0a3aSHans de Goede 	0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
2120554c0a3aSHans de Goede 	0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
2121554c0a3aSHans de Goede 	0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
2122554c0a3aSHans de Goede 	0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
2123554c0a3aSHans de Goede 	0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
2124554c0a3aSHans de Goede 	0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
2125554c0a3aSHans de Goede 	0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
2126554c0a3aSHans de Goede 	0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
2127554c0a3aSHans de Goede 	0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
2128554c0a3aSHans de Goede 	0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
2129554c0a3aSHans de Goede 	0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
2130554c0a3aSHans de Goede 	0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
2131554c0a3aSHans de Goede 	0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
2132554c0a3aSHans de Goede 	0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
2133554c0a3aSHans de Goede 	0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
2134554c0a3aSHans de Goede 	0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
2135554c0a3aSHans de Goede 	0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
2136554c0a3aSHans de Goede 	0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
2137554c0a3aSHans de Goede 	0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
2138554c0a3aSHans de Goede 	0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
2139554c0a3aSHans de Goede 	0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
2140554c0a3aSHans de Goede 	0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
2141554c0a3aSHans de Goede 	0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
2142554c0a3aSHans de Goede 	0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
2143554c0a3aSHans de Goede 	0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
2144554c0a3aSHans de Goede 	0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
2145554c0a3aSHans de Goede 	0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
2146554c0a3aSHans de Goede 	0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
2147554c0a3aSHans de Goede 	0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
2148554c0a3aSHans de Goede 	0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
2149554c0a3aSHans de Goede 	0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
2150554c0a3aSHans de Goede 	0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
2151554c0a3aSHans de Goede 	0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
2152554c0a3aSHans de Goede 	0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
2153554c0a3aSHans de Goede 	0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
2154554c0a3aSHans de Goede 	0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
2155554c0a3aSHans de Goede 	0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
2156554c0a3aSHans de Goede 	0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
2157554c0a3aSHans de Goede 	0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
2158554c0a3aSHans de Goede 	0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
2159554c0a3aSHans de Goede 	0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
2160554c0a3aSHans de Goede 	0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
2161554c0a3aSHans de Goede 	0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
2162554c0a3aSHans de Goede 	0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
2163554c0a3aSHans de Goede 	0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
2164554c0a3aSHans de Goede 	0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
2165554c0a3aSHans de Goede 	0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
2166554c0a3aSHans de Goede 	0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
2167554c0a3aSHans de Goede 	0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
2168554c0a3aSHans de Goede };
2169554c0a3aSHans de Goede const u8 Td4s[256] = {
2170554c0a3aSHans de Goede 	0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
2171554c0a3aSHans de Goede 	0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
2172554c0a3aSHans de Goede 	0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
2173554c0a3aSHans de Goede 	0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
2174554c0a3aSHans de Goede 	0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
2175554c0a3aSHans de Goede 	0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
2176554c0a3aSHans de Goede 	0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
2177554c0a3aSHans de Goede 	0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
2178554c0a3aSHans de Goede 	0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
2179554c0a3aSHans de Goede 	0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
2180554c0a3aSHans de Goede 	0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
2181554c0a3aSHans de Goede 	0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
2182554c0a3aSHans de Goede 	0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
2183554c0a3aSHans de Goede 	0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
2184554c0a3aSHans de Goede 	0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
2185554c0a3aSHans de Goede 	0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
2186554c0a3aSHans de Goede 	0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
2187554c0a3aSHans de Goede 	0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
2188554c0a3aSHans de Goede 	0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
2189554c0a3aSHans de Goede 	0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
2190554c0a3aSHans de Goede 	0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
2191554c0a3aSHans de Goede 	0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
2192554c0a3aSHans de Goede 	0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
2193554c0a3aSHans de Goede 	0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
2194554c0a3aSHans de Goede 	0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
2195554c0a3aSHans de Goede 	0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
2196554c0a3aSHans de Goede 	0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
2197554c0a3aSHans de Goede 	0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
2198554c0a3aSHans de Goede 	0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
2199554c0a3aSHans de Goede 	0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
2200554c0a3aSHans de Goede 	0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
2201554c0a3aSHans de Goede 	0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
2202554c0a3aSHans de Goede };
2203554c0a3aSHans de Goede const u8 rcons[] = {
2204554c0a3aSHans de Goede 	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
2205554c0a3aSHans de Goede 	/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
2206554c0a3aSHans de Goede };
2207554c0a3aSHans de Goede 
2208554c0a3aSHans de Goede /**
2209554c0a3aSHans de Goede  * Expand the cipher key into the encryption key schedule.
2210554c0a3aSHans de Goede  *
2211554c0a3aSHans de Goede  * @return	the number of rounds for the given cipher key size.
2212554c0a3aSHans de Goede  */
2213554c0a3aSHans de Goede static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
2214554c0a3aSHans de Goede {
2215554c0a3aSHans de Goede 	int i;
2216554c0a3aSHans de Goede 	u32 temp;
2217554c0a3aSHans de Goede 
2218554c0a3aSHans de Goede 	rk[0] = GETU32(cipherKey);
2219554c0a3aSHans de Goede 	rk[1] = GETU32(cipherKey +  4);
2220554c0a3aSHans de Goede 	rk[2] = GETU32(cipherKey +  8);
2221554c0a3aSHans de Goede 	rk[3] = GETU32(cipherKey + 12);
2222554c0a3aSHans de Goede 	for (i = 0; i < 10; i++) {
2223554c0a3aSHans de Goede 		temp  = rk[3];
2224554c0a3aSHans de Goede 		rk[4] = rk[0] ^
2225554c0a3aSHans de Goede 			TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
2226554c0a3aSHans de Goede 			RCON(i);
2227554c0a3aSHans de Goede 		rk[5] = rk[1] ^ rk[4];
2228554c0a3aSHans de Goede 		rk[6] = rk[2] ^ rk[5];
2229554c0a3aSHans de Goede 		rk[7] = rk[3] ^ rk[6];
2230554c0a3aSHans de Goede 		rk += 4;
2231554c0a3aSHans de Goede 	}
2232554c0a3aSHans de Goede }
2233554c0a3aSHans de Goede 
2234554c0a3aSHans de Goede static void rijndaelEncrypt(u32 rk[/*44*/], u8 pt[16], u8 ct[16])
2235554c0a3aSHans de Goede {
2236554c0a3aSHans de Goede 	u32 s0, s1, s2, s3, t0, t1, t2, t3;
2237554c0a3aSHans de Goede 	int Nr = 10;
2238554c0a3aSHans de Goede 	int r;
2239554c0a3aSHans de Goede 
2240554c0a3aSHans de Goede 	/*
2241554c0a3aSHans de Goede 	 * map byte array block to cipher state
2242554c0a3aSHans de Goede 	 * and add initial round key:
2243554c0a3aSHans de Goede 	 */
2244554c0a3aSHans de Goede 	s0 = GETU32(pt) ^ rk[0];
2245554c0a3aSHans de Goede 	s1 = GETU32(pt +  4) ^ rk[1];
2246554c0a3aSHans de Goede 	s2 = GETU32(pt +  8) ^ rk[2];
2247554c0a3aSHans de Goede 	s3 = GETU32(pt + 12) ^ rk[3];
2248554c0a3aSHans de Goede 
2249554c0a3aSHans de Goede #define ROUND(i, d, s) \
2250554c0a3aSHans de Goede d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
2251554c0a3aSHans de Goede d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
2252554c0a3aSHans de Goede d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
2253554c0a3aSHans de Goede d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
2254554c0a3aSHans de Goede 
2255554c0a3aSHans de Goede 	/* Nr - 1 full rounds: */
2256554c0a3aSHans de Goede 	r = Nr >> 1;
2257554c0a3aSHans de Goede 	for (;;) {
2258554c0a3aSHans de Goede 		ROUND(1, t, s);
2259554c0a3aSHans de Goede 		rk += 8;
2260554c0a3aSHans de Goede 		if (--r == 0)
2261554c0a3aSHans de Goede 			break;
2262554c0a3aSHans de Goede 		ROUND(0, s, t);
2263554c0a3aSHans de Goede 	}
2264554c0a3aSHans de Goede 
2265554c0a3aSHans de Goede #undef ROUND
2266554c0a3aSHans de Goede 
2267554c0a3aSHans de Goede 	/*
2268554c0a3aSHans de Goede 	 * apply last round and
2269554c0a3aSHans de Goede 	 * map cipher state to byte array block:
2270554c0a3aSHans de Goede 	 */
2271554c0a3aSHans de Goede 	s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
2272554c0a3aSHans de Goede 	PUTU32(ct, s0);
2273554c0a3aSHans de Goede 	s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
2274554c0a3aSHans de Goede 	PUTU32(ct +  4, s1);
2275554c0a3aSHans de Goede 	s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
2276554c0a3aSHans de Goede 	PUTU32(ct +  8, s2);
2277554c0a3aSHans de Goede 	s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
2278554c0a3aSHans de Goede 	PUTU32(ct + 12, s3);
2279554c0a3aSHans de Goede }
2280554c0a3aSHans de Goede 
2281554c0a3aSHans de Goede static void *aes_encrypt_init(u8 *key, size_t len)
2282554c0a3aSHans de Goede {
2283554c0a3aSHans de Goede 	u32 *rk;
2284554c0a3aSHans de Goede 	if (len != 16)
2285554c0a3aSHans de Goede 		return NULL;
2286554c0a3aSHans de Goede 	rk = (u32 *)rtw_malloc(AES_PRIV_SIZE);
2287554c0a3aSHans de Goede 	if (rk == NULL)
2288554c0a3aSHans de Goede 		return NULL;
2289554c0a3aSHans de Goede 	rijndaelKeySetupEnc(rk, key);
2290554c0a3aSHans de Goede 	return rk;
2291554c0a3aSHans de Goede }
2292554c0a3aSHans de Goede 
2293554c0a3aSHans de Goede static void aes_128_encrypt(void *ctx, u8 *plain, u8 *crypt)
2294554c0a3aSHans de Goede {
2295554c0a3aSHans de Goede 	rijndaelEncrypt(ctx, plain, crypt);
2296554c0a3aSHans de Goede }
2297554c0a3aSHans de Goede 
2298554c0a3aSHans de Goede 
2299554c0a3aSHans de Goede static void gf_mulx(u8 *pad)
2300554c0a3aSHans de Goede {
2301554c0a3aSHans de Goede 	int i, carry;
2302554c0a3aSHans de Goede 
2303554c0a3aSHans de Goede 	carry = pad[0] & 0x80;
2304554c0a3aSHans de Goede 	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
2305554c0a3aSHans de Goede 		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
2306554c0a3aSHans de Goede 
2307554c0a3aSHans de Goede 	pad[AES_BLOCK_SIZE - 1] <<= 1;
2308554c0a3aSHans de Goede 	if (carry)
2309554c0a3aSHans de Goede 		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
2310554c0a3aSHans de Goede }
2311554c0a3aSHans de Goede 
2312554c0a3aSHans de Goede static void aes_encrypt_deinit(void *ctx)
2313554c0a3aSHans de Goede {
2314554c0a3aSHans de Goede 	memset(ctx, 0, AES_PRIV_SIZE);
2315554c0a3aSHans de Goede 	kfree(ctx);
2316554c0a3aSHans de Goede }
2317554c0a3aSHans de Goede 
2318554c0a3aSHans de Goede 
2319554c0a3aSHans de Goede /**
2320554c0a3aSHans de Goede  * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
2321554c0a3aSHans de Goede  * @key: 128-bit key for the hash operation
2322554c0a3aSHans de Goede  * @num_elem: Number of elements in the data vector
2323554c0a3aSHans de Goede  * @addr: Pointers to the data areas
2324554c0a3aSHans de Goede  * @len: Lengths of the data blocks
2325554c0a3aSHans de Goede  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
2326554c0a3aSHans de Goede  * Returns: 0 on success, -1 on failure
2327554c0a3aSHans de Goede  *
2328554c0a3aSHans de Goede  * This is a mode for using block cipher (AES in this case) for authentication.
2329554c0a3aSHans de Goede  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
2330554c0a3aSHans de Goede  * (SP) 800-38B.
2331554c0a3aSHans de Goede  */
2332554c0a3aSHans de Goede static int omac1_aes_128_vector(u8 *key, size_t num_elem,
2333554c0a3aSHans de Goede 							 u8 *addr[], size_t *len, u8 *mac)
2334554c0a3aSHans de Goede {
2335554c0a3aSHans de Goede 	void *ctx;
2336554c0a3aSHans de Goede 	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
2337554c0a3aSHans de Goede 	u8 *pos, *end;
2338554c0a3aSHans de Goede 	size_t i, e, left, total_len;
2339554c0a3aSHans de Goede 
2340554c0a3aSHans de Goede 	ctx = aes_encrypt_init(key, 16);
2341554c0a3aSHans de Goede 	if (ctx == NULL)
2342554c0a3aSHans de Goede 		return -1;
2343554c0a3aSHans de Goede 	memset(cbc, 0, AES_BLOCK_SIZE);
2344554c0a3aSHans de Goede 
2345554c0a3aSHans de Goede 	total_len = 0;
2346554c0a3aSHans de Goede 	for (e = 0; e < num_elem; e++)
2347554c0a3aSHans de Goede 		total_len += len[e];
2348554c0a3aSHans de Goede 	left = total_len;
2349554c0a3aSHans de Goede 
2350554c0a3aSHans de Goede 	e = 0;
2351554c0a3aSHans de Goede 	pos = addr[0];
2352554c0a3aSHans de Goede 	end = pos + len[0];
2353554c0a3aSHans de Goede 
2354554c0a3aSHans de Goede 	while (left >= AES_BLOCK_SIZE) {
2355554c0a3aSHans de Goede 		for (i = 0; i < AES_BLOCK_SIZE; i++) {
2356554c0a3aSHans de Goede 			cbc[i] ^= *pos++;
2357554c0a3aSHans de Goede 			if (pos >= end) {
2358554c0a3aSHans de Goede 				e++;
2359554c0a3aSHans de Goede 				pos = addr[e];
2360554c0a3aSHans de Goede 				end = pos + len[e];
2361554c0a3aSHans de Goede 			}
2362554c0a3aSHans de Goede 		}
2363554c0a3aSHans de Goede 		if (left > AES_BLOCK_SIZE)
2364554c0a3aSHans de Goede 			aes_128_encrypt(ctx, cbc, cbc);
2365554c0a3aSHans de Goede 		left -= AES_BLOCK_SIZE;
2366554c0a3aSHans de Goede 	}
2367554c0a3aSHans de Goede 
2368554c0a3aSHans de Goede 	memset(pad, 0, AES_BLOCK_SIZE);
2369554c0a3aSHans de Goede 	aes_128_encrypt(ctx, pad, pad);
2370554c0a3aSHans de Goede 	gf_mulx(pad);
2371554c0a3aSHans de Goede 
2372554c0a3aSHans de Goede 	if (left || total_len == 0) {
2373554c0a3aSHans de Goede 		for (i = 0; i < left; i++) {
2374554c0a3aSHans de Goede 			cbc[i] ^= *pos++;
2375554c0a3aSHans de Goede 			if (pos >= end) {
2376554c0a3aSHans de Goede 				e++;
2377554c0a3aSHans de Goede 				pos = addr[e];
2378554c0a3aSHans de Goede 				end = pos + len[e];
2379554c0a3aSHans de Goede 			}
2380554c0a3aSHans de Goede 		}
2381554c0a3aSHans de Goede 		cbc[left] ^= 0x80;
2382554c0a3aSHans de Goede 		gf_mulx(pad);
2383554c0a3aSHans de Goede 	}
2384554c0a3aSHans de Goede 
2385554c0a3aSHans de Goede 	for (i = 0; i < AES_BLOCK_SIZE; i++)
2386554c0a3aSHans de Goede 		pad[i] ^= cbc[i];
2387554c0a3aSHans de Goede 	aes_128_encrypt(ctx, pad, mac);
2388554c0a3aSHans de Goede 	aes_encrypt_deinit(ctx);
2389554c0a3aSHans de Goede 	return 0;
2390554c0a3aSHans de Goede }
2391554c0a3aSHans de Goede 
2392554c0a3aSHans de Goede 
2393554c0a3aSHans de Goede /**
2394554c0a3aSHans de Goede  * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
2395554c0a3aSHans de Goede  * @key: 128-bit key for the hash operation
2396554c0a3aSHans de Goede  * @data: Data buffer for which a MAC is determined
2397554c0a3aSHans de Goede  * @data_len: Length of data buffer in bytes
2398554c0a3aSHans de Goede  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
2399554c0a3aSHans de Goede  * Returns: 0 on success, -1 on failure
2400554c0a3aSHans de Goede  *
2401554c0a3aSHans de Goede  * This is a mode for using block cipher (AES in this case) for authentication.
2402554c0a3aSHans de Goede  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
2403554c0a3aSHans de Goede  * (SP) 800-38B.
2404554c0a3aSHans de Goede  * modify for CONFIG_IEEE80211W */
2405554c0a3aSHans de Goede int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
2406554c0a3aSHans de Goede {
2407554c0a3aSHans de Goede 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
2408554c0a3aSHans de Goede }
2409554c0a3aSHans de Goede 
2410554c0a3aSHans de Goede /* Restore HW wep key setting according to key_mask */
2411554c0a3aSHans de Goede void rtw_sec_restore_wep_key(struct adapter *adapter)
2412554c0a3aSHans de Goede {
2413554c0a3aSHans de Goede 	struct security_priv *securitypriv = &(adapter->securitypriv);
2414554c0a3aSHans de Goede 	sint keyid;
2415554c0a3aSHans de Goede 
2416554c0a3aSHans de Goede 	if ((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) || (_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) {
2417554c0a3aSHans de Goede 		for (keyid = 0; keyid < 4; keyid++) {
2418554c0a3aSHans de Goede 			if (securitypriv->key_mask & BIT(keyid)) {
2419554c0a3aSHans de Goede 				if (keyid == securitypriv->dot11PrivacyKeyIndex)
2420554c0a3aSHans de Goede 					rtw_set_key(adapter, securitypriv, keyid, 1, false);
2421554c0a3aSHans de Goede 				else
2422554c0a3aSHans de Goede 					rtw_set_key(adapter, securitypriv, keyid, 0, false);
2423554c0a3aSHans de Goede 			}
2424554c0a3aSHans de Goede 		}
2425554c0a3aSHans de Goede 	}
2426554c0a3aSHans de Goede }
2427554c0a3aSHans de Goede 
2428554c0a3aSHans de Goede u8 rtw_handle_tkip_countermeasure(struct adapter *adapter, const char *caller)
2429554c0a3aSHans de Goede {
2430554c0a3aSHans de Goede 	struct security_priv *securitypriv = &(adapter->securitypriv);
2431554c0a3aSHans de Goede 	u8 status = _SUCCESS;
2432554c0a3aSHans de Goede 
2433554c0a3aSHans de Goede 	if (securitypriv->btkip_countermeasure == true) {
2434554c0a3aSHans de Goede 		unsigned long passing_ms = jiffies_to_msecs(jiffies - securitypriv->btkip_countermeasure_time);
2435554c0a3aSHans de Goede 		if (passing_ms > 60*1000) {
2436554c0a3aSHans de Goede 			DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus > 60s\n",
2437554c0a3aSHans de Goede 				caller, ADPT_ARG(adapter), passing_ms/1000);
2438554c0a3aSHans de Goede 			securitypriv->btkip_countermeasure = false;
2439554c0a3aSHans de Goede 			securitypriv->btkip_countermeasure_time = 0;
2440554c0a3aSHans de Goede 		} else {
2441554c0a3aSHans de Goede 			DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus < 60s\n",
2442554c0a3aSHans de Goede 				caller, ADPT_ARG(adapter), passing_ms/1000);
2443554c0a3aSHans de Goede 			status = _FAIL;
2444554c0a3aSHans de Goede 		}
2445554c0a3aSHans de Goede 	}
2446554c0a3aSHans de Goede 
2447554c0a3aSHans de Goede 	return status;
2448554c0a3aSHans de Goede }
2449