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