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  ******************************************************************************/
7b97fad10SFabio Aiuto #include <linux/crc32.h>
8554c0a3aSHans de Goede #include <drv_types.h>
9554c0a3aSHans de Goede #include <rtw_debug.h>
107d40753dSFabio Aiuto #include <crypto/aes.h>
11554c0a3aSHans de Goede 
126cf26021SJoe Perches static const char * const _security_type_str[] = {
13554c0a3aSHans de Goede 	"N/A",
14554c0a3aSHans de Goede 	"WEP40",
15554c0a3aSHans de Goede 	"TKIP",
16554c0a3aSHans de Goede 	"TKIP_WM",
17554c0a3aSHans de Goede 	"AES",
18554c0a3aSHans de Goede 	"WEP104",
19554c0a3aSHans de Goede 	"SMS4",
20554c0a3aSHans de Goede 	"WEP_WPA",
21554c0a3aSHans de Goede 	"BIP",
22554c0a3aSHans de Goede };
23554c0a3aSHans de Goede 
security_type_str(u8 value)24554c0a3aSHans de Goede const char *security_type_str(u8 value)
25554c0a3aSHans de Goede {
26554c0a3aSHans de Goede 	if (value <= _BIP_)
27554c0a3aSHans de Goede 		return _security_type_str[value];
28554c0a3aSHans de Goede 	return NULL;
29554c0a3aSHans de Goede }
30554c0a3aSHans de Goede 
31554c0a3aSHans de Goede /* WEP related ===== */
32554c0a3aSHans de Goede 
33554c0a3aSHans de Goede /*
34554c0a3aSHans de Goede 	Need to consider the fragment  situation
35554c0a3aSHans de Goede */
rtw_wep_encrypt(struct adapter * padapter,u8 * pxmitframe)36554c0a3aSHans de Goede void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
37554c0a3aSHans de Goede {																	/*  exclude ICV */
38aef1c966SFabio M. De Francesco 	union {
39aef1c966SFabio M. De Francesco 		__le32 f0;
40aef1c966SFabio M. De Francesco 		unsigned char f1[4];
41aef1c966SFabio M. De Francesco 	} crc;
42554c0a3aSHans de Goede 
43d495c550SMarco Cesati 	signed int	curfragnum, length;
44554c0a3aSHans de Goede 	u32 keylength;
45554c0a3aSHans de Goede 
46554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv;    /* wepkey */
47554c0a3aSHans de Goede 	u8 wepkey[16];
48554c0a3aSHans de Goede 	u8 hw_hdr_offset = 0;
49554c0a3aSHans de Goede 	struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
50554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
51554c0a3aSHans de Goede 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
52a1b8a9bbSFabio Aiuto 	struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx;
53554c0a3aSHans de Goede 
54cd1f1450SMichael Straube 	if (!((struct xmit_frame *)pxmitframe)->buf_addr)
55554c0a3aSHans de Goede 		return;
56554c0a3aSHans de Goede 
57554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
58554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
59554c0a3aSHans de Goede 
60554c0a3aSHans de Goede 	/* start to encrypt each fragment */
61554c0a3aSHans de Goede 	if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
62554c0a3aSHans de Goede 		keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
63554c0a3aSHans de Goede 
64554c0a3aSHans de Goede 		for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
65554c0a3aSHans de Goede 			iv = pframe+pattrib->hdrlen;
66554c0a3aSHans de Goede 			memcpy(&wepkey[0], iv, 3);
67554c0a3aSHans de Goede 			memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength);
68554c0a3aSHans de Goede 			payload = pframe+pattrib->iv_len+pattrib->hdrlen;
69554c0a3aSHans de Goede 
70554c0a3aSHans de Goede 			if ((curfragnum+1) == pattrib->nr_frags) {	/* the last fragment */
71554c0a3aSHans de Goede 
72554c0a3aSHans de Goede 				length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
73554c0a3aSHans de Goede 
74aef1c966SFabio M. De Francesco 				crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
75554c0a3aSHans de Goede 
76a1b8a9bbSFabio Aiuto 				arc4_setkey(ctx, wepkey, 3 + keylength);
77a1b8a9bbSFabio Aiuto 				arc4_crypt(ctx, payload, payload, length);
78aef1c966SFabio M. De Francesco 				arc4_crypt(ctx, payload + length, crc.f1, 4);
79554c0a3aSHans de Goede 
80554c0a3aSHans de Goede 			} else {
81554c0a3aSHans de Goede 				length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
82aef1c966SFabio M. De Francesco 				crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
83a1b8a9bbSFabio Aiuto 				arc4_setkey(ctx, wepkey, 3 + keylength);
84a1b8a9bbSFabio Aiuto 				arc4_crypt(ctx, payload, payload, length);
85aef1c966SFabio M. De Francesco 				arc4_crypt(ctx, payload + length, crc.f1, 4);
86554c0a3aSHans de Goede 
87554c0a3aSHans de Goede 				pframe += pxmitpriv->frag_len;
8887fe08d7SRoss Schmidt 				pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4);
89554c0a3aSHans de Goede 			}
90554c0a3aSHans de Goede 		}
91554c0a3aSHans de Goede 	}
92554c0a3aSHans de Goede }
93554c0a3aSHans de Goede 
rtw_wep_decrypt(struct adapter * padapter,u8 * precvframe)94554c0a3aSHans de Goede void rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
95554c0a3aSHans de Goede {
96554c0a3aSHans de Goede 	/*  exclude ICV */
97554c0a3aSHans de Goede 	u8 crc[4];
98d495c550SMarco Cesati 	signed int	length;
99554c0a3aSHans de Goede 	u32 keylength;
100554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, wepkey[16];
101554c0a3aSHans de Goede 	u8  keyindex;
102554c0a3aSHans de Goede 	struct	rx_pkt_attrib	 *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib);
103554c0a3aSHans de Goede 	struct	security_priv *psecuritypriv = &padapter->securitypriv;
104a1b8a9bbSFabio Aiuto 	struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx;
105554c0a3aSHans de Goede 
106554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
107554c0a3aSHans de Goede 
108554c0a3aSHans de Goede 	/* start to decrypt recvframe */
109554c0a3aSHans de Goede 	if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
110554c0a3aSHans de Goede 		iv = pframe+prxattrib->hdrlen;
111554c0a3aSHans de Goede 		/* keyindex =(iv[3]&0x3); */
112554c0a3aSHans de Goede 		keyindex = prxattrib->key_index;
113554c0a3aSHans de Goede 		keylength = psecuritypriv->dot11DefKeylen[keyindex];
114554c0a3aSHans de Goede 		memcpy(&wepkey[0], iv, 3);
115554c0a3aSHans de Goede 		/* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */
116554c0a3aSHans de Goede 		memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
117554c0a3aSHans de Goede 		length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
118554c0a3aSHans de Goede 
119554c0a3aSHans de Goede 		payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
120554c0a3aSHans de Goede 
121554c0a3aSHans de Goede 		/* decrypt payload include icv */
122a1b8a9bbSFabio Aiuto 		arc4_setkey(ctx, wepkey, 3 + keylength);
123a1b8a9bbSFabio Aiuto 		arc4_crypt(ctx, payload, payload,  length);
124554c0a3aSHans de Goede 
125554c0a3aSHans de Goede 		/* calculate icv and compare the icv */
126aef1c966SFabio M. De Francesco 		*((u32 *)crc) = ~crc32_le(~0, payload, length - 4);
127554c0a3aSHans de Goede 
128554c0a3aSHans de Goede 	}
129554c0a3aSHans de Goede }
130554c0a3aSHans de Goede 
131554c0a3aSHans de Goede /* 3		=====TKIP related ===== */
132554c0a3aSHans de Goede 
secmicgetuint32(u8 * p)133554c0a3aSHans de Goede static u32 secmicgetuint32(u8 *p)
134554c0a3aSHans de Goede /*  Convert from Byte[] to Us3232 in a portable way */
135554c0a3aSHans de Goede {
136554c0a3aSHans de Goede 	s32 i;
137554c0a3aSHans de Goede 	u32 res = 0;
138554c0a3aSHans de Goede 
139df94d3b2SBrother Matthew De Angelis 	for (i = 0; i < 4; i++)
140554c0a3aSHans de Goede 		res |= ((u32)(*p++)) << (8 * i);
141554c0a3aSHans de Goede 
142554c0a3aSHans de Goede 	return res;
143554c0a3aSHans de Goede }
144554c0a3aSHans de Goede 
secmicputuint32(u8 * p,u32 val)145554c0a3aSHans de Goede static void secmicputuint32(u8 *p, u32 val)
146554c0a3aSHans de Goede /*  Convert from Us3232 to Byte[] in a portable way */
147554c0a3aSHans de Goede {
148554c0a3aSHans de Goede 	long i;
149554c0a3aSHans de Goede 
150554c0a3aSHans de Goede 	for (i = 0; i < 4; i++) {
151554c0a3aSHans de Goede 		*p++ = (u8) (val & 0xff);
152554c0a3aSHans de Goede 		val >>= 8;
153554c0a3aSHans de Goede 	}
154554c0a3aSHans de Goede }
155554c0a3aSHans de Goede 
secmicclear(struct mic_data * pmicdata)156554c0a3aSHans de Goede static void secmicclear(struct mic_data *pmicdata)
157554c0a3aSHans de Goede {
158554c0a3aSHans de Goede /*  Reset the state to the empty message. */
159554c0a3aSHans de Goede 	pmicdata->L = pmicdata->K0;
160554c0a3aSHans de Goede 	pmicdata->R = pmicdata->K1;
161554c0a3aSHans de Goede 	pmicdata->nBytesInM = 0;
162554c0a3aSHans de Goede 	pmicdata->M = 0;
163554c0a3aSHans de Goede }
164554c0a3aSHans de Goede 
rtw_secmicsetkey(struct mic_data * pmicdata,u8 * key)165554c0a3aSHans de Goede void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key)
166554c0a3aSHans de Goede {
167554c0a3aSHans de Goede 	/*  Set the key */
168554c0a3aSHans de Goede 	pmicdata->K0 = secmicgetuint32(key);
169554c0a3aSHans de Goede 	pmicdata->K1 = secmicgetuint32(key + 4);
170554c0a3aSHans de Goede 	/*  and reset the message */
171554c0a3aSHans de Goede 	secmicclear(pmicdata);
172554c0a3aSHans de Goede }
173554c0a3aSHans de Goede 
rtw_secmicappendbyte(struct mic_data * pmicdata,u8 b)174554c0a3aSHans de Goede void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b)
175554c0a3aSHans de Goede {
176554c0a3aSHans de Goede 	/*  Append the byte to our word-sized buffer */
177554c0a3aSHans de Goede 	pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
178554c0a3aSHans de Goede 	pmicdata->nBytesInM++;
179554c0a3aSHans de Goede 	/*  Process the word if it is full. */
180554c0a3aSHans de Goede 	if (pmicdata->nBytesInM >= 4) {
181554c0a3aSHans de Goede 		pmicdata->L ^= pmicdata->M;
182554c0a3aSHans de Goede 		pmicdata->R ^= ROL32(pmicdata->L, 17);
183554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
184554c0a3aSHans de Goede 		pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
185554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
186554c0a3aSHans de Goede 		pmicdata->R ^= ROL32(pmicdata->L, 3);
187554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
188554c0a3aSHans de Goede 		pmicdata->R ^= ROR32(pmicdata->L, 2);
189554c0a3aSHans de Goede 		pmicdata->L += pmicdata->R;
190554c0a3aSHans de Goede 		/*  Clear the buffer */
191554c0a3aSHans de Goede 		pmicdata->M = 0;
192554c0a3aSHans de Goede 		pmicdata->nBytesInM = 0;
193554c0a3aSHans de Goede 	}
194554c0a3aSHans de Goede }
195554c0a3aSHans de Goede 
rtw_secmicappend(struct mic_data * pmicdata,u8 * src,u32 nbytes)196554c0a3aSHans de Goede void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
197554c0a3aSHans de Goede {
198554c0a3aSHans de Goede 	/*  This is simple */
199554c0a3aSHans de Goede 	while (nbytes > 0) {
200554c0a3aSHans de Goede 		rtw_secmicappendbyte(pmicdata, *src++);
201554c0a3aSHans de Goede 		nbytes--;
202554c0a3aSHans de Goede 	}
203554c0a3aSHans de Goede }
204554c0a3aSHans de Goede 
rtw_secgetmic(struct mic_data * pmicdata,u8 * dst)205554c0a3aSHans de Goede void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst)
206554c0a3aSHans de Goede {
207554c0a3aSHans de Goede 	/*  Append the minimum padding */
208554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0x5a);
209554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
210554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
211554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
212554c0a3aSHans de Goede 	rtw_secmicappendbyte(pmicdata, 0);
213554c0a3aSHans de Goede 	/*  and then zeroes until the length is a multiple of 4 */
214df94d3b2SBrother Matthew De Angelis 	while (pmicdata->nBytesInM != 0)
215554c0a3aSHans de Goede 		rtw_secmicappendbyte(pmicdata, 0);
216554c0a3aSHans de Goede 	/*  The appendByte function has already computed the result. */
217554c0a3aSHans de Goede 	secmicputuint32(dst, pmicdata->L);
218554c0a3aSHans de Goede 	secmicputuint32(dst + 4, pmicdata->R);
219554c0a3aSHans de Goede 	/*  Reset to the empty message. */
220554c0a3aSHans de Goede 	secmicclear(pmicdata);
221554c0a3aSHans de Goede }
222554c0a3aSHans de Goede 
223554c0a3aSHans de Goede 
rtw_seccalctkipmic(u8 * key,u8 * header,u8 * data,u32 data_len,u8 * mic_code,u8 pri)224554c0a3aSHans de Goede void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri)
225554c0a3aSHans de Goede {
226554c0a3aSHans de Goede 
227554c0a3aSHans de Goede 	struct mic_data	micdata;
228554c0a3aSHans de Goede 	u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
229554c0a3aSHans de Goede 
230554c0a3aSHans de Goede 	rtw_secmicsetkey(&micdata, key);
231554c0a3aSHans de Goede 	priority[0] = pri;
232554c0a3aSHans de Goede 
233554c0a3aSHans de Goede 	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
234554c0a3aSHans de Goede 	if (header[1] & 1) {   /* ToDS == 1 */
235554c0a3aSHans de Goede 		rtw_secmicappend(&micdata, &header[16], 6);  /* DA */
236554c0a3aSHans de Goede 		if (header[1] & 2)  /* From Ds == 1 */
237554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[24], 6);
238554c0a3aSHans de Goede 		else
239554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[10], 6);
240554c0a3aSHans de Goede 	} else {	/* ToDS == 0 */
241554c0a3aSHans de Goede 		rtw_secmicappend(&micdata, &header[4], 6);   /* DA */
242554c0a3aSHans de Goede 		if (header[1] & 2)  /* From Ds == 1 */
243554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[16], 6);
244554c0a3aSHans de Goede 		else
245554c0a3aSHans de Goede 			rtw_secmicappend(&micdata, &header[10], 6);
246554c0a3aSHans de Goede 	}
247554c0a3aSHans de Goede 	rtw_secmicappend(&micdata, &priority[0], 4);
248554c0a3aSHans de Goede 
249554c0a3aSHans de Goede 
250554c0a3aSHans de Goede 	rtw_secmicappend(&micdata, data, data_len);
251554c0a3aSHans de Goede 
252554c0a3aSHans de Goede 	rtw_secgetmic(&micdata, mic_code);
253554c0a3aSHans de Goede }
254554c0a3aSHans de Goede 
255554c0a3aSHans de Goede /* macros for extraction/creation of unsigned char/unsigned short values  */
256554c0a3aSHans de Goede #define RotR1(v16)   ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
257554c0a3aSHans de Goede #define   Lo8(v16)   ((u8)((v16)       & 0x00FF))
258554c0a3aSHans de Goede #define   Hi8(v16)   ((u8)(((v16) >> 8) & 0x00FF))
259554c0a3aSHans de Goede #define  Lo16(v32)   ((u16)((v32)       & 0xFFFF))
260554c0a3aSHans de Goede #define  Hi16(v32)   ((u16)(((v32) >> 16) & 0xFFFF))
261554c0a3aSHans de Goede #define  Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
262554c0a3aSHans de Goede 
263554c0a3aSHans de Goede /* select the Nth 16-bit word of the temporal key unsigned char array TK[]   */
264554c0a3aSHans de Goede #define  TK16(N)     Mk16(tk[2*(N)+1], tk[2*(N)])
265554c0a3aSHans de Goede 
266554c0a3aSHans de Goede /* S-box lookup: 16 bits --> 16 bits */
267554c0a3aSHans de Goede #define _S_(v16)     (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
268554c0a3aSHans de Goede 
269554c0a3aSHans de Goede /* fixed algorithm "parameters" */
270554c0a3aSHans de Goede #define PHASE1_LOOP_CNT   8    /* this needs to be "big enough"     */
271554c0a3aSHans de Goede 
272554c0a3aSHans de Goede /* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
273554c0a3aSHans de Goede static const unsigned short Sbox1[2][256] = {      /* Sbox for hash (can be in ROM)     */
274554c0a3aSHans de Goede {
275554c0a3aSHans de Goede 	 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
276554c0a3aSHans de Goede 	 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
277554c0a3aSHans de Goede 	 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
278554c0a3aSHans de Goede 	 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
279554c0a3aSHans de Goede 	 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
280554c0a3aSHans de Goede 	 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
281554c0a3aSHans de Goede 	 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
282554c0a3aSHans de Goede 	 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
283554c0a3aSHans de Goede 	 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
284554c0a3aSHans de Goede 	 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
285554c0a3aSHans de Goede 	 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
286554c0a3aSHans de Goede 	 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
287554c0a3aSHans de Goede 	 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
288554c0a3aSHans de Goede 	 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
289554c0a3aSHans de Goede 	 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
290554c0a3aSHans de Goede 	 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
291554c0a3aSHans de Goede 	 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
292554c0a3aSHans de Goede 	 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
293554c0a3aSHans de Goede 	 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
294554c0a3aSHans de Goede 	 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
295554c0a3aSHans de Goede 	 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
296554c0a3aSHans de Goede 	 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
297554c0a3aSHans de Goede 	 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
298554c0a3aSHans de Goede 	 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
299554c0a3aSHans de Goede 	 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
300554c0a3aSHans de Goede 	 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
301554c0a3aSHans de Goede 	 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
302554c0a3aSHans de Goede 	 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
303554c0a3aSHans de Goede 	 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
304554c0a3aSHans de Goede 	 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
305554c0a3aSHans de Goede 	 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
306554c0a3aSHans de Goede 	 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
307554c0a3aSHans de Goede 	},
308554c0a3aSHans de Goede 
309554c0a3aSHans de Goede 
310554c0a3aSHans de Goede 	{  /* second half of table is unsigned char-reversed version of first! */
311554c0a3aSHans de Goede 	 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
312554c0a3aSHans de Goede 	 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
313554c0a3aSHans de Goede 	 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
314554c0a3aSHans de Goede 	 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
315554c0a3aSHans de Goede 	 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
316554c0a3aSHans de Goede 	 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
317554c0a3aSHans de Goede 	 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
318554c0a3aSHans de Goede 	 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
319554c0a3aSHans de Goede 	 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
320554c0a3aSHans de Goede 	 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
321554c0a3aSHans de Goede 	 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
322554c0a3aSHans de Goede 	 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
323554c0a3aSHans de Goede 	 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
324554c0a3aSHans de Goede 	 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
325554c0a3aSHans de Goede 	 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
326554c0a3aSHans de Goede 	 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
327554c0a3aSHans de Goede 	 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
328554c0a3aSHans de Goede 	 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
329554c0a3aSHans de Goede 	 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
330554c0a3aSHans de Goede 	 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
331554c0a3aSHans de Goede 	 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
332554c0a3aSHans de Goede 	 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
333554c0a3aSHans de Goede 	 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
334554c0a3aSHans de Goede 	 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
335554c0a3aSHans de Goede 	 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
336554c0a3aSHans de Goede 	 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
337554c0a3aSHans de Goede 	 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
338554c0a3aSHans de Goede 	 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
339554c0a3aSHans de Goede 	 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
340554c0a3aSHans de Goede 	 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
341554c0a3aSHans de Goede 	 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
342554c0a3aSHans de Goede 	 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
343554c0a3aSHans de Goede 	}
344554c0a3aSHans de Goede };
345554c0a3aSHans de Goede 
346554c0a3aSHans de Goede  /*
347554c0a3aSHans de Goede **********************************************************************
348554c0a3aSHans de Goede * Routine: Phase 1 -- generate P1K, given TA, TK, IV32
349554c0a3aSHans de Goede *
350554c0a3aSHans de Goede * Inputs:
351554c0a3aSHans de Goede *     tk[]      = temporal key                         [128 bits]
352554c0a3aSHans de Goede *     ta[]      = transmitter's MAC address            [ 48 bits]
353554c0a3aSHans de Goede *     iv32      = upper 32 bits of IV                  [ 32 bits]
354554c0a3aSHans de Goede * Output:
355554c0a3aSHans de Goede *     p1k[]     = Phase 1 key                          [ 80 bits]
356554c0a3aSHans de Goede *
357554c0a3aSHans de Goede * Note:
358554c0a3aSHans de Goede *     This function only needs to be called every 2**16 packets,
359554c0a3aSHans de Goede *     although in theory it could be called every packet.
360554c0a3aSHans de Goede *
361554c0a3aSHans de Goede **********************************************************************
362554c0a3aSHans de Goede */
phase1(u16 * p1k,const u8 * tk,const u8 * ta,u32 iv32)363554c0a3aSHans de Goede static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
364554c0a3aSHans de Goede {
365d495c550SMarco Cesati 	signed int  i;
366554c0a3aSHans de Goede 
367554c0a3aSHans de Goede 	/* Initialize the 80 bits of P1K[] from IV32 and TA[0..5]     */
368554c0a3aSHans de Goede 	p1k[0]      = Lo16(iv32);
369554c0a3aSHans de Goede 	p1k[1]      = Hi16(iv32);
370554c0a3aSHans de Goede 	p1k[2]      = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
371554c0a3aSHans de Goede 	p1k[3]      = Mk16(ta[3], ta[2]);
372554c0a3aSHans de Goede 	p1k[4]      = Mk16(ta[5], ta[4]);
373554c0a3aSHans de Goede 
374554c0a3aSHans de Goede 	/* Now compute an unbalanced Feistel cipher with 80-bit block */
375554c0a3aSHans de Goede 	/* size on the 80-bit block P1K[], using the 128-bit key TK[] */
376554c0a3aSHans de Goede 	for (i = 0; i < PHASE1_LOOP_CNT; i++) {
377554c0a3aSHans de Goede 		/* Each add operation here is mod 2**16 */
378554c0a3aSHans de Goede 		p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
379554c0a3aSHans de Goede 		p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
380554c0a3aSHans de Goede 		p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
381554c0a3aSHans de Goede 		p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
382554c0a3aSHans de Goede 		p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
383554c0a3aSHans de Goede 		p1k[4] +=  (unsigned short)i;          /* avoid "slide attacks" */
384554c0a3aSHans de Goede 	}
385554c0a3aSHans de Goede }
386554c0a3aSHans de Goede 
387554c0a3aSHans de Goede 
388554c0a3aSHans de Goede /*
389554c0a3aSHans de Goede **********************************************************************
390554c0a3aSHans de Goede * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
391554c0a3aSHans de Goede *
392554c0a3aSHans de Goede * Inputs:
393554c0a3aSHans de Goede *     tk[]      = Temporal key                         [128 bits]
394554c0a3aSHans de Goede *     p1k[]     = Phase 1 output key                   [ 80 bits]
395554c0a3aSHans de Goede *     iv16      = low 16 bits of IV counter            [ 16 bits]
396554c0a3aSHans de Goede * Output:
397554c0a3aSHans de Goede *     rc4key[]  = the key used to encrypt the packet   [128 bits]
398554c0a3aSHans de Goede *
399554c0a3aSHans de Goede * Note:
400554c0a3aSHans de Goede *     The value {TA, IV32, IV16} for Phase1/Phase2 must be unique
401554c0a3aSHans de Goede *     across all packets using the same key TK value. Then, for a
402554c0a3aSHans de Goede *     given value of TK[], this TKIP48 construction guarantees that
403554c0a3aSHans de Goede *     the final RC4KEY value is unique across all packets.
404554c0a3aSHans de Goede *
405554c0a3aSHans de Goede * Suggested implementation optimization: if PPK[] is "overlaid"
406554c0a3aSHans de Goede *     appropriately on RC4KEY[], there is no need for the final
407554c0a3aSHans de Goede *     for loop below that copies the PPK[] result into RC4KEY[].
408554c0a3aSHans de Goede *
409554c0a3aSHans de Goede **********************************************************************
410554c0a3aSHans de Goede */
phase2(u8 * rc4key,const u8 * tk,const u16 * p1k,u16 iv16)411554c0a3aSHans de Goede static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
412554c0a3aSHans de Goede {
413d495c550SMarco Cesati 	signed int  i;
414554c0a3aSHans de Goede 	u16 PPK[6];                          /* temporary key for mixing    */
415554c0a3aSHans de Goede 
416554c0a3aSHans de Goede 	/* Note: all adds in the PPK[] equations below are mod 2**16         */
417554c0a3aSHans de Goede 	for (i = 0; i < 5; i++)
418554c0a3aSHans de Goede 		PPK[i] = p1k[i];      /* first, copy P1K to PPK      */
419554c0a3aSHans de Goede 
420554c0a3aSHans de Goede 	PPK[5]  =  p1k[4]+iv16;             /* next,  add in IV16          */
421554c0a3aSHans de Goede 
422554c0a3aSHans de Goede 	/* Bijective non-linear mixing of the 96 bits of PPK[0..5]           */
423554c0a3aSHans de Goede 	PPK[0] +=    _S_(PPK[5] ^ TK16(0));   /* Mix key in each "round"     */
424554c0a3aSHans de Goede 	PPK[1] +=    _S_(PPK[0] ^ TK16(1));
425554c0a3aSHans de Goede 	PPK[2] +=    _S_(PPK[1] ^ TK16(2));
426554c0a3aSHans de Goede 	PPK[3] +=    _S_(PPK[2] ^ TK16(3));
427554c0a3aSHans de Goede 	PPK[4] +=    _S_(PPK[3] ^ TK16(4));
428554c0a3aSHans de Goede 	PPK[5] +=    _S_(PPK[4] ^ TK16(5));   /* Total # S-box lookups == 6  */
429554c0a3aSHans de Goede 
430554c0a3aSHans de Goede 	/* Final sweep: bijective, "linear". Rotates kill LSB correlations   */
431554c0a3aSHans de Goede 	PPK[0] +=  RotR1(PPK[5] ^ TK16(6));
432554c0a3aSHans de Goede 	PPK[1] +=  RotR1(PPK[0] ^ TK16(7));   /* Use all of TK[] in Phase2   */
433554c0a3aSHans de Goede 	PPK[2] +=  RotR1(PPK[1]);
434554c0a3aSHans de Goede 	PPK[3] +=  RotR1(PPK[2]);
435554c0a3aSHans de Goede 	PPK[4] +=  RotR1(PPK[3]);
436554c0a3aSHans de Goede 	PPK[5] +=  RotR1(PPK[4]);
437554c0a3aSHans de Goede 	/* Note: At this point, for a given key TK[0..15], the 96-bit output */
438554c0a3aSHans de Goede 	/*       value PPK[0..5] is guaranteed to be unique, as a function   */
439554c0a3aSHans de Goede 	/*       of the 96-bit "input" value   {TA, IV32, IV16}. That is, P1K  */
440554c0a3aSHans de Goede 	/*       is now a keyed permutation of {TA, IV32, IV16}.               */
441554c0a3aSHans de Goede 
442554c0a3aSHans de Goede 	/* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key   */
443554c0a3aSHans de Goede 	rc4key[0] = Hi8(iv16);                /* RC4KEY[0..2] is the WEP IV  */
444554c0a3aSHans de Goede 	rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys  */
445554c0a3aSHans de Goede 	rc4key[2] = Lo8(iv16);
446554c0a3aSHans de Goede 	rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
447554c0a3aSHans de Goede 
448554c0a3aSHans de Goede 
449554c0a3aSHans de Goede 	/* Copy 96 bits of PPK[0..5] to RC4KEY[4..15]  (little-endian)       */
450554c0a3aSHans de Goede 	for (i = 0; i < 6; i++) {
451554c0a3aSHans de Goede 		rc4key[4+2*i] = Lo8(PPK[i]);
452554c0a3aSHans de Goede 		rc4key[5+2*i] = Hi8(PPK[i]);
453554c0a3aSHans de Goede 	}
454554c0a3aSHans de Goede }
455554c0a3aSHans de Goede 
456554c0a3aSHans de Goede 
457554c0a3aSHans de Goede /* The hlen isn't include the IV */
rtw_tkip_encrypt(struct adapter * padapter,u8 * pxmitframe)458554c0a3aSHans de Goede u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe)
459554c0a3aSHans de Goede {																	/*  exclude ICV */
460554c0a3aSHans de Goede 	u16 pnl;
461554c0a3aSHans de Goede 	u32 pnh;
462554c0a3aSHans de Goede 	u8 rc4key[16];
463554c0a3aSHans de Goede 	u8   ttkey[16];
464aef1c966SFabio M. De Francesco 	union {
465aef1c966SFabio M. De Francesco 		__le32 f0;
466aef1c966SFabio M. De Francesco 		u8 f1[4];
467aef1c966SFabio M. De Francesco 	} crc;
468554c0a3aSHans de Goede 	u8   hw_hdr_offset = 0;
469d495c550SMarco Cesati 	signed int			curfragnum, length;
470554c0a3aSHans de Goede 
471554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, *prwskey;
472554c0a3aSHans de Goede 	union pn48 dot11txpn;
473554c0a3aSHans de Goede 	struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
474554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
475554c0a3aSHans de Goede 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
476a1b8a9bbSFabio Aiuto 	struct arc4_ctx *ctx = &psecuritypriv->xmit_arc4_ctx;
477554c0a3aSHans de Goede 	u32 res = _SUCCESS;
478554c0a3aSHans de Goede 
479cd1f1450SMichael Straube 	if (!((struct xmit_frame *)pxmitframe)->buf_addr)
480554c0a3aSHans de Goede 		return _FAIL;
481554c0a3aSHans de Goede 
482554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
483554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
484554c0a3aSHans de Goede 
485554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
486554c0a3aSHans de Goede 	if (pattrib->encrypt == _TKIP_) {
487554c0a3aSHans de Goede 
488554c0a3aSHans de Goede 		{
489*be6cded3SRuan Jinjie 			if (is_multicast_ether_addr(pattrib->ra))
490554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
491554c0a3aSHans de Goede 			else
492554c0a3aSHans de Goede 				prwskey = pattrib->dot118021x_UncstKey.skey;
493554c0a3aSHans de Goede 
494554c0a3aSHans de Goede 			for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
495554c0a3aSHans de Goede 				iv = pframe+pattrib->hdrlen;
496554c0a3aSHans de Goede 				payload = pframe+pattrib->iv_len+pattrib->hdrlen;
497554c0a3aSHans de Goede 
498554c0a3aSHans de Goede 				GET_TKIP_PN(iv, dot11txpn);
499554c0a3aSHans de Goede 
500554c0a3aSHans de Goede 				pnl = (u16)(dot11txpn.val);
501554c0a3aSHans de Goede 				pnh = (u32)(dot11txpn.val>>16);
502554c0a3aSHans de Goede 
503554c0a3aSHans de Goede 				phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh);
504554c0a3aSHans de Goede 
505554c0a3aSHans de Goede 				phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl);
506554c0a3aSHans de Goede 
507554c0a3aSHans de Goede 				if ((curfragnum+1) == pattrib->nr_frags) {	/* 4 the last fragment */
508554c0a3aSHans de Goede 					length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
509aef1c966SFabio M. De Francesco 					crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
510554c0a3aSHans de Goede 
511a1b8a9bbSFabio Aiuto 					arc4_setkey(ctx, rc4key, 16);
512a1b8a9bbSFabio Aiuto 					arc4_crypt(ctx, payload, payload, length);
513aef1c966SFabio M. De Francesco 					arc4_crypt(ctx, payload + length, crc.f1, 4);
514554c0a3aSHans de Goede 
515554c0a3aSHans de Goede 				} else {
516554c0a3aSHans de Goede 					length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
517aef1c966SFabio M. De Francesco 					crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length));
5181f5adcfeSFabio Aiuto 
519a1b8a9bbSFabio Aiuto 					arc4_setkey(ctx, rc4key, 16);
520a1b8a9bbSFabio Aiuto 					arc4_crypt(ctx, payload, payload, length);
521aef1c966SFabio M. De Francesco 					arc4_crypt(ctx, payload + length, crc.f1, 4);
522554c0a3aSHans de Goede 
523554c0a3aSHans de Goede 					pframe += pxmitpriv->frag_len;
52487fe08d7SRoss Schmidt 					pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4);
525554c0a3aSHans de Goede 				}
526554c0a3aSHans de Goede 			}
527554c0a3aSHans de Goede 		}
528554c0a3aSHans de Goede 	}
529554c0a3aSHans de Goede 	return res;
530554c0a3aSHans de Goede }
531554c0a3aSHans de Goede 
532554c0a3aSHans de Goede 
533554c0a3aSHans de Goede /* The hlen isn't include the IV */
rtw_tkip_decrypt(struct adapter * padapter,u8 * precvframe)534554c0a3aSHans de Goede u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe)
535554c0a3aSHans de Goede {																	/*  exclude ICV */
536554c0a3aSHans de Goede 	u16 pnl;
537554c0a3aSHans de Goede 	u32 pnh;
538554c0a3aSHans de Goede 	u8   rc4key[16];
539554c0a3aSHans de Goede 	u8   ttkey[16];
540554c0a3aSHans de Goede 	u8 crc[4];
541d495c550SMarco Cesati 	signed int			length;
542554c0a3aSHans de Goede 
543554c0a3aSHans de Goede 	u8 *pframe, *payload, *iv, *prwskey;
544554c0a3aSHans de Goede 	union pn48 dot11txpn;
545554c0a3aSHans de Goede 	struct sta_info *stainfo;
546554c0a3aSHans de Goede 	struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
547554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
548a1b8a9bbSFabio Aiuto 	struct arc4_ctx *ctx = &psecuritypriv->recv_arc4_ctx;
549554c0a3aSHans de Goede 	u32 res = _SUCCESS;
550554c0a3aSHans de Goede 
551554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
552554c0a3aSHans de Goede 
553554c0a3aSHans de Goede 	/* 4 start to decrypt recvframe */
554554c0a3aSHans de Goede 	if (prxattrib->encrypt == _TKIP_) {
555554c0a3aSHans de Goede 		stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
55634557e23SIzabela Bakollari 		if (stainfo) {
557*be6cded3SRuan Jinjie 			if (is_multicast_ether_addr(prxattrib->ra)) {
55840d4aa0fSShreeya Patel 				static unsigned long start;
55940d4aa0fSShreeya Patel 				static u32 no_gkey_bc_cnt;
56040d4aa0fSShreeya Patel 				static u32 no_gkey_mc_cnt;
561554c0a3aSHans de Goede 
5623ac5add1SJohn Oldman 				if (!psecuritypriv->binstallGrpkey) {
563554c0a3aSHans de Goede 					res = _FAIL;
564554c0a3aSHans de Goede 
565554c0a3aSHans de Goede 					if (start == 0)
566554c0a3aSHans de Goede 						start = jiffies;
567554c0a3aSHans de Goede 
568554c0a3aSHans de Goede 					if (is_broadcast_mac_addr(prxattrib->ra))
569554c0a3aSHans de Goede 						no_gkey_bc_cnt++;
570554c0a3aSHans de Goede 					else
571554c0a3aSHans de Goede 						no_gkey_mc_cnt++;
572554c0a3aSHans de Goede 
573554c0a3aSHans de Goede 					if (jiffies_to_msecs(jiffies - start) > 1000) {
574554c0a3aSHans de Goede 						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
57579df841bSFabio Aiuto 							netdev_dbg(padapter->pnetdev,
57679df841bSFabio Aiuto 								   FUNC_ADPT_FMT " no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
57779df841bSFabio Aiuto 								   FUNC_ADPT_ARG(padapter),
57879df841bSFabio Aiuto 								   no_gkey_bc_cnt,
57979df841bSFabio Aiuto 								   no_gkey_mc_cnt);
580554c0a3aSHans de Goede 						}
581554c0a3aSHans de Goede 						start = jiffies;
582554c0a3aSHans de Goede 						no_gkey_bc_cnt = 0;
583554c0a3aSHans de Goede 						no_gkey_mc_cnt = 0;
584554c0a3aSHans de Goede 					}
585554c0a3aSHans de Goede 					goto exit;
586554c0a3aSHans de Goede 				}
587554c0a3aSHans de Goede 
588554c0a3aSHans de Goede 				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
58979df841bSFabio Aiuto 					netdev_dbg(padapter->pnetdev,
59079df841bSFabio Aiuto 						   FUNC_ADPT_FMT " gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
59179df841bSFabio Aiuto 						   FUNC_ADPT_ARG(padapter),
59279df841bSFabio Aiuto 						   no_gkey_bc_cnt,
59379df841bSFabio Aiuto 						   no_gkey_mc_cnt);
594554c0a3aSHans de Goede 				}
595554c0a3aSHans de Goede 				start = 0;
596554c0a3aSHans de Goede 				no_gkey_bc_cnt = 0;
597554c0a3aSHans de Goede 				no_gkey_mc_cnt = 0;
598554c0a3aSHans de Goede 
599554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
600554c0a3aSHans de Goede 			} else {
601554c0a3aSHans de Goede 				prwskey = &stainfo->dot118021x_UncstKey.skey[0];
602554c0a3aSHans de Goede 			}
603554c0a3aSHans de Goede 
604554c0a3aSHans de Goede 			iv = pframe+prxattrib->hdrlen;
605554c0a3aSHans de Goede 			payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
606554c0a3aSHans de Goede 			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
607554c0a3aSHans de Goede 
608554c0a3aSHans de Goede 			GET_TKIP_PN(iv, dot11txpn);
609554c0a3aSHans de Goede 
610554c0a3aSHans de Goede 			pnl = (u16)(dot11txpn.val);
611554c0a3aSHans de Goede 			pnh = (u32)(dot11txpn.val>>16);
612554c0a3aSHans de Goede 
613554c0a3aSHans de Goede 			phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh);
614554c0a3aSHans de Goede 			phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl);
615554c0a3aSHans de Goede 
616554c0a3aSHans de Goede 			/* 4 decrypt payload include icv */
617554c0a3aSHans de Goede 
618a1b8a9bbSFabio Aiuto 			arc4_setkey(ctx, rc4key, 16);
619a1b8a9bbSFabio Aiuto 			arc4_crypt(ctx, payload, payload, length);
620554c0a3aSHans de Goede 
621aef1c966SFabio M. De Francesco 			*((u32 *)crc) = ~crc32_le(~0, payload, length - 4);
622554c0a3aSHans de Goede 
6230e1b6fe2SFabio Aiuto 			if (crc[3] != payload[length - 1] || crc[2] != payload[length - 2] ||
6240e1b6fe2SFabio Aiuto 			    crc[1] != payload[length - 3] || crc[0] != payload[length - 4])
625554c0a3aSHans de Goede 				res = _FAIL;
626554c0a3aSHans de Goede 		} else {
627554c0a3aSHans de Goede 			res = _FAIL;
628554c0a3aSHans de Goede 		}
629554c0a3aSHans de Goede 	}
630554c0a3aSHans de Goede exit:
631554c0a3aSHans de Goede 	return res;
632554c0a3aSHans de Goede }
633554c0a3aSHans de Goede 
634554c0a3aSHans de Goede 
635554c0a3aSHans de Goede /* 3			=====AES related ===== */
636554c0a3aSHans de Goede 
637554c0a3aSHans de Goede 
638554c0a3aSHans de Goede 
639554c0a3aSHans de Goede #define MAX_MSG_SIZE	2048
640554c0a3aSHans de Goede 
641554c0a3aSHans de Goede /*****************************/
642554c0a3aSHans de Goede /**** Function Prototypes ****/
643554c0a3aSHans de Goede /*****************************/
644554c0a3aSHans de Goede 
645554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
6465641eeecSRoss Schmidt static void construct_mic_iv(u8 *mic_header1,
647d495c550SMarco Cesati 			     signed int qc_exists,
648d495c550SMarco Cesati 			     signed int a4_exists,
649554c0a3aSHans de Goede 			     u8 *mpdu,
650554c0a3aSHans de Goede 			     uint payload_length,
651554c0a3aSHans de Goede 			     u8 *pn_vector,
6525641eeecSRoss Schmidt 			     uint frtype); /*  add for CONFIG_IEEE80211W, none 11w also can use */
6535641eeecSRoss Schmidt static void construct_mic_header1(u8 *mic_header1,
654d495c550SMarco Cesati 				  signed int header_length,
655554c0a3aSHans de Goede 				  u8 *mpdu,
6565641eeecSRoss Schmidt 				  uint frtype); /* for CONFIG_IEEE80211W, none 11w also can use */
6575641eeecSRoss Schmidt static void construct_mic_header2(u8 *mic_header2,
658554c0a3aSHans de Goede 				  u8 *mpdu,
659d495c550SMarco Cesati 				  signed int a4_exists,
660d495c550SMarco Cesati 				  signed int qc_exists);
6615641eeecSRoss Schmidt static void construct_ctr_preload(u8 *ctr_preload,
662d495c550SMarco Cesati 				  signed int a4_exists,
663d495c550SMarco Cesati 				  signed int qc_exists,
664554c0a3aSHans de Goede 				  u8 *mpdu,
665554c0a3aSHans de Goede 				  u8 *pn_vector,
666d495c550SMarco Cesati 				  signed int c,
6675641eeecSRoss Schmidt 				  uint frtype); /* for CONFIG_IEEE80211W, none 11w also can use */
6683d3a170fSFabio Aiuto 
669554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
670554c0a3aSHans de Goede 
671554c0a3aSHans de Goede 
672554c0a3aSHans de Goede /****************************************/
673554c0a3aSHans de Goede /* aes128k128d()                        */
674554c0a3aSHans de Goede /* Performs a 128 bit AES encrypt with  */
675554c0a3aSHans de Goede /* 128 bit data.                        */
676554c0a3aSHans de Goede /****************************************/
aes128k128d(u8 * key,u8 * data,u8 * ciphertext)677554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
678554c0a3aSHans de Goede {
6793d3a170fSFabio Aiuto 	struct crypto_aes_ctx ctx;
680554c0a3aSHans de Goede 
6813d3a170fSFabio Aiuto 	aes_expandkey(&ctx, key, 16);
6823d3a170fSFabio Aiuto 	aes_encrypt(&ctx, ciphertext, data);
6833d3a170fSFabio Aiuto 	memzero_explicit(&ctx, sizeof(ctx));
684554c0a3aSHans de Goede }
685554c0a3aSHans de Goede 
686554c0a3aSHans de Goede /************************************************/
687554c0a3aSHans de Goede /* construct_mic_iv()                           */
688554c0a3aSHans de Goede /* Builds the MIC IV from header fields and PN  */
689554c0a3aSHans de Goede /* Baron think the function is construct CCM    */
690554c0a3aSHans de Goede /* nonce                                        */
691554c0a3aSHans de Goede /************************************************/
construct_mic_iv(u8 * mic_iv,signed int qc_exists,signed int a4_exists,u8 * mpdu,uint payload_length,u8 * pn_vector,uint frtype)6925641eeecSRoss Schmidt static void construct_mic_iv(u8 *mic_iv,
693d495c550SMarco Cesati 			     signed int qc_exists,
694d495c550SMarco Cesati 			     signed int a4_exists,
695554c0a3aSHans de Goede 			     u8 *mpdu,
696554c0a3aSHans de Goede 			     uint payload_length,
697554c0a3aSHans de Goede 			     u8 *pn_vector,
6985641eeecSRoss Schmidt 			     uint frtype) /* add for CONFIG_IEEE80211W, none 11w also can use */
699554c0a3aSHans de Goede {
700d495c550SMarco Cesati 		signed int i;
701554c0a3aSHans de Goede 
702554c0a3aSHans de Goede 		mic_iv[0] = 0x59;
703554c0a3aSHans de Goede 
704554c0a3aSHans de Goede 		if (qc_exists && a4_exists)
705554c0a3aSHans de Goede 			mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC           */
706554c0a3aSHans de Goede 
707554c0a3aSHans de Goede 		if (qc_exists && !a4_exists)
708554c0a3aSHans de Goede 			mic_iv[1] = mpdu[24] & 0x0f;   /* mute bits 7-4    */
709554c0a3aSHans de Goede 
710554c0a3aSHans de Goede 		if (!qc_exists)
711554c0a3aSHans de Goede 			mic_iv[1] = 0x00;
712554c0a3aSHans de Goede 
713554c0a3aSHans de Goede 		/* 802.11w management frame should set management bit(4) */
714554c0a3aSHans de Goede 		if (frtype == WIFI_MGT_TYPE)
715554c0a3aSHans de Goede 			mic_iv[1] |= BIT(4);
716554c0a3aSHans de Goede 
717554c0a3aSHans de Goede 		for (i = 2; i < 8; i++)
718554c0a3aSHans de Goede 			mic_iv[i] = mpdu[i + 8];   /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
719554c0a3aSHans de Goede 		#ifdef CONSISTENT_PN_ORDER
720554c0a3aSHans de Goede 		for (i = 8; i < 14; i++)
721554c0a3aSHans de Goede 			mic_iv[i] = pn_vector[i - 8];           /* mic_iv[8:13] = PN[0:5] */
722554c0a3aSHans de Goede 		#else
723554c0a3aSHans de Goede 		for (i = 8; i < 14; i++)
724554c0a3aSHans de Goede 			mic_iv[i] = pn_vector[13 - i];          /* mic_iv[8:13] = PN[5:0] */
725554c0a3aSHans de Goede 		#endif
726554c0a3aSHans de Goede 		mic_iv[14] = (unsigned char) (payload_length / 256);
727554c0a3aSHans de Goede 		mic_iv[15] = (unsigned char) (payload_length % 256);
728554c0a3aSHans de Goede }
729554c0a3aSHans de Goede 
730554c0a3aSHans de Goede /************************************************/
731554c0a3aSHans de Goede /* construct_mic_header1()                      */
732554c0a3aSHans de Goede /* Builds the first MIC header block from       */
733554c0a3aSHans de Goede /* header fields.                               */
734554c0a3aSHans de Goede /* Build AAD SC, A1, A2                           */
735554c0a3aSHans de Goede /************************************************/
construct_mic_header1(u8 * mic_header1,signed int header_length,u8 * mpdu,uint frtype)7365641eeecSRoss Schmidt static void construct_mic_header1(u8 *mic_header1,
737d495c550SMarco Cesati 				  signed int header_length,
738554c0a3aSHans de Goede 				  u8 *mpdu,
7395641eeecSRoss Schmidt 				  uint frtype) /* for CONFIG_IEEE80211W, none 11w also can use */
740554c0a3aSHans de Goede {
741554c0a3aSHans de Goede 		mic_header1[0] = (u8)((header_length - 2) / 256);
742554c0a3aSHans de Goede 		mic_header1[1] = (u8)((header_length - 2) % 256);
743554c0a3aSHans de Goede 
744554c0a3aSHans de Goede 		/* 802.11w management frame don't AND subtype bits 4, 5, 6 of frame control field */
745554c0a3aSHans de Goede 		if (frtype == WIFI_MGT_TYPE)
746554c0a3aSHans de Goede 			mic_header1[2] = mpdu[0];
747554c0a3aSHans de Goede 		else
748554c0a3aSHans de Goede 			mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
749554c0a3aSHans de Goede 
750554c0a3aSHans de Goede 		mic_header1[3] = mpdu[1] & 0xc7;    /* Mute retry, more data and pwr mgt bits */
751554c0a3aSHans de Goede 		mic_header1[4] = mpdu[4];       /* A1 */
752554c0a3aSHans de Goede 		mic_header1[5] = mpdu[5];
753554c0a3aSHans de Goede 		mic_header1[6] = mpdu[6];
754554c0a3aSHans de Goede 		mic_header1[7] = mpdu[7];
755554c0a3aSHans de Goede 		mic_header1[8] = mpdu[8];
756554c0a3aSHans de Goede 		mic_header1[9] = mpdu[9];
757554c0a3aSHans de Goede 		mic_header1[10] = mpdu[10];     /* A2 */
758554c0a3aSHans de Goede 		mic_header1[11] = mpdu[11];
759554c0a3aSHans de Goede 		mic_header1[12] = mpdu[12];
760554c0a3aSHans de Goede 		mic_header1[13] = mpdu[13];
761554c0a3aSHans de Goede 		mic_header1[14] = mpdu[14];
762554c0a3aSHans de Goede 		mic_header1[15] = mpdu[15];
763554c0a3aSHans de Goede }
764554c0a3aSHans de Goede 
765554c0a3aSHans de Goede /************************************************/
766554c0a3aSHans de Goede /* construct_mic_header2()                      */
767554c0a3aSHans de Goede /* Builds the last MIC header block from        */
768554c0a3aSHans de Goede /* header fields.                               */
769554c0a3aSHans de Goede /************************************************/
construct_mic_header2(u8 * mic_header2,u8 * mpdu,signed int a4_exists,signed int qc_exists)7705641eeecSRoss Schmidt static void construct_mic_header2(u8 *mic_header2,
771554c0a3aSHans de Goede 				  u8 *mpdu,
772d495c550SMarco Cesati 				  signed int a4_exists,
773d495c550SMarco Cesati 				  signed int qc_exists)
774554c0a3aSHans de Goede {
775d495c550SMarco Cesati 		signed int i;
776554c0a3aSHans de Goede 
777554c0a3aSHans de Goede 		for (i = 0; i < 16; i++)
778554c0a3aSHans de Goede 			mic_header2[i] = 0x00;
779554c0a3aSHans de Goede 
780554c0a3aSHans de Goede 		mic_header2[0] = mpdu[16];    /* A3 */
781554c0a3aSHans de Goede 		mic_header2[1] = mpdu[17];
782554c0a3aSHans de Goede 		mic_header2[2] = mpdu[18];
783554c0a3aSHans de Goede 		mic_header2[3] = mpdu[19];
784554c0a3aSHans de Goede 		mic_header2[4] = mpdu[20];
785554c0a3aSHans de Goede 		mic_header2[5] = mpdu[21];
786554c0a3aSHans de Goede 
787554c0a3aSHans de Goede 		mic_header2[6] = 0x00;
788554c0a3aSHans de Goede 		mic_header2[7] = 0x00; /* mpdu[23]; */
789554c0a3aSHans de Goede 
790554c0a3aSHans de Goede 		if (!qc_exists && a4_exists) {
791554c0a3aSHans de Goede 			for (i = 0; i < 6; i++)
792554c0a3aSHans de Goede 				mic_header2[8+i] = mpdu[24+i];   /* A4 */
793554c0a3aSHans de Goede 		}
794554c0a3aSHans de Goede 
795554c0a3aSHans de Goede 		if (qc_exists && !a4_exists) {
796554c0a3aSHans de Goede 			mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
797554c0a3aSHans de Goede 			mic_header2[9] = mpdu[25] & 0x00;
798554c0a3aSHans de Goede 		}
799554c0a3aSHans de Goede 
800554c0a3aSHans de Goede 		if (qc_exists && a4_exists) {
801554c0a3aSHans de Goede 			for (i = 0; i < 6; i++)
802554c0a3aSHans de Goede 				mic_header2[8+i] = mpdu[24+i];   /* A4 */
803554c0a3aSHans de Goede 
804554c0a3aSHans de Goede 			mic_header2[14] = mpdu[30] & 0x0f;
805554c0a3aSHans de Goede 			mic_header2[15] = mpdu[31] & 0x00;
806554c0a3aSHans de Goede 		}
807554c0a3aSHans de Goede }
808554c0a3aSHans de Goede 
809554c0a3aSHans de Goede /************************************************/
810554c0a3aSHans de Goede /* construct_mic_header2()                      */
811554c0a3aSHans de Goede /* Builds the last MIC header block from        */
812554c0a3aSHans de Goede /* header fields.                               */
813554c0a3aSHans de Goede /* Baron think the function is construct CCM    */
814554c0a3aSHans de Goede /* nonce                                        */
815554c0a3aSHans de Goede /************************************************/
construct_ctr_preload(u8 * ctr_preload,signed int a4_exists,signed int qc_exists,u8 * mpdu,u8 * pn_vector,signed int c,uint frtype)8165641eeecSRoss Schmidt static void construct_ctr_preload(u8 *ctr_preload,
817d495c550SMarco Cesati 				  signed int a4_exists,
818d495c550SMarco Cesati 				  signed int qc_exists,
819554c0a3aSHans de Goede 				  u8 *mpdu,
820554c0a3aSHans de Goede 				  u8 *pn_vector,
821d495c550SMarco Cesati 				  signed int c,
8225641eeecSRoss Schmidt 				  uint frtype) /* for CONFIG_IEEE80211W, none 11w also can use */
823554c0a3aSHans de Goede {
824d495c550SMarco Cesati 	signed int i = 0;
825554c0a3aSHans de Goede 
826554c0a3aSHans de Goede 	for (i = 0; i < 16; i++)
827554c0a3aSHans de Goede 		ctr_preload[i] = 0x00;
828554c0a3aSHans de Goede 	i = 0;
829554c0a3aSHans de Goede 
830554c0a3aSHans de Goede 	ctr_preload[0] = 0x01;                                  /* flag */
831554c0a3aSHans de Goede 	if (qc_exists && a4_exists)
832554c0a3aSHans de Goede 		ctr_preload[1] = mpdu[30] & 0x0f;   /* QoC_Control */
833554c0a3aSHans de Goede 	if (qc_exists && !a4_exists)
834554c0a3aSHans de Goede 		ctr_preload[1] = mpdu[24] & 0x0f;
835554c0a3aSHans de Goede 
836554c0a3aSHans de Goede 	/* 802.11w management frame should set management bit(4) */
837554c0a3aSHans de Goede 	if (frtype == WIFI_MGT_TYPE)
838554c0a3aSHans de Goede 		ctr_preload[1] |= BIT(4);
839554c0a3aSHans de Goede 
840554c0a3aSHans de Goede 	for (i = 2; i < 8; i++)
841554c0a3aSHans de Goede 		ctr_preload[i] = mpdu[i + 8];                       /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
842554c0a3aSHans de Goede #ifdef CONSISTENT_PN_ORDER
843554c0a3aSHans de Goede 	for (i = 8; i < 14; i++)
844554c0a3aSHans de Goede 		ctr_preload[i] =    pn_vector[i - 8];           /* ctr_preload[8:13] = PN[0:5] */
845554c0a3aSHans de Goede #else
846554c0a3aSHans de Goede 	for (i = 8; i < 14; i++)
847554c0a3aSHans de Goede 		ctr_preload[i] =    pn_vector[13 - i];          /* ctr_preload[8:13] = PN[5:0] */
848554c0a3aSHans de Goede #endif
849554c0a3aSHans de Goede 	ctr_preload[14] =  (unsigned char) (c / 256); /* Ctr */
850554c0a3aSHans de Goede 	ctr_preload[15] =  (unsigned char) (c % 256);
851554c0a3aSHans de Goede }
852554c0a3aSHans de Goede 
853554c0a3aSHans de Goede /************************************/
854554c0a3aSHans de Goede /* bitwise_xor()                    */
855554c0a3aSHans de Goede /* A 128 bit, bitwise exclusive or  */
856554c0a3aSHans de Goede /************************************/
bitwise_xor(u8 * ina,u8 * inb,u8 * out)857554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
858554c0a3aSHans de Goede {
859d495c550SMarco Cesati 		signed int i;
860554c0a3aSHans de Goede 
861df94d3b2SBrother Matthew De Angelis 		for (i = 0; i < 16; i++)
862554c0a3aSHans de Goede 			out[i] = ina[i] ^ inb[i];
863554c0a3aSHans de Goede }
864554c0a3aSHans de Goede 
aes_cipher(u8 * key,uint hdrlen,u8 * pframe,uint plen)865d495c550SMarco Cesati static signed int aes_cipher(u8 *key, uint	hdrlen,
866554c0a3aSHans de Goede 			u8 *pframe, uint plen)
867554c0a3aSHans de Goede {
868554c0a3aSHans de Goede 	uint	qc_exists, a4_exists, i, j, payload_remainder,
869554c0a3aSHans de Goede 		num_blocks, payload_index;
870554c0a3aSHans de Goede 
871554c0a3aSHans de Goede 	u8 pn_vector[6];
872554c0a3aSHans de Goede 	u8 mic_iv[16];
873554c0a3aSHans de Goede 	u8 mic_header1[16];
874554c0a3aSHans de Goede 	u8 mic_header2[16];
875554c0a3aSHans de Goede 	u8 ctr_preload[16];
876554c0a3aSHans de Goede 
877554c0a3aSHans de Goede 	/* Intermediate Buffers */
878554c0a3aSHans de Goede 	u8 chain_buffer[16];
879554c0a3aSHans de Goede 	u8 aes_out[16];
880554c0a3aSHans de Goede 	u8 padded_buffer[16];
881554c0a3aSHans de Goede 	u8 mic[8];
882554c0a3aSHans de Goede 	uint	frtype  = GetFrameType(pframe);
883554c0a3aSHans de Goede 	uint	frsubtype  = GetFrameSubType(pframe);
884554c0a3aSHans de Goede 
885554c0a3aSHans de Goede 	frsubtype = frsubtype>>4;
886554c0a3aSHans de Goede 
887554c0a3aSHans de Goede 	memset((void *)mic_iv, 0, 16);
888554c0a3aSHans de Goede 	memset((void *)mic_header1, 0, 16);
889554c0a3aSHans de Goede 	memset((void *)mic_header2, 0, 16);
890554c0a3aSHans de Goede 	memset((void *)ctr_preload, 0, 16);
891554c0a3aSHans de Goede 	memset((void *)chain_buffer, 0, 16);
892554c0a3aSHans de Goede 	memset((void *)aes_out, 0, 16);
893554c0a3aSHans de Goede 	memset((void *)padded_buffer, 0, 16);
894554c0a3aSHans de Goede 
895554c0a3aSHans de Goede 	if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
896554c0a3aSHans de Goede 		a4_exists = 0;
897554c0a3aSHans de Goede 	else
898554c0a3aSHans de Goede 		a4_exists = 1;
899554c0a3aSHans de Goede 
9000ba8d4b9SLarry Finger 	if (((frtype|frsubtype) == WIFI_DATA_CFACK) ||
901554c0a3aSHans de Goede 	    ((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
902554c0a3aSHans de Goede 	    ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
903554c0a3aSHans de Goede 		qc_exists = 1;
904554c0a3aSHans de Goede 		if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
905554c0a3aSHans de Goede 			hdrlen += 2;
906554c0a3aSHans de Goede 
907554c0a3aSHans de Goede 	} else if ((frtype == WIFI_DATA) && /*  add for CONFIG_IEEE80211W, none 11w also can use */
908554c0a3aSHans de Goede 		   ((frsubtype == 0x08) ||
909554c0a3aSHans de Goede 		   (frsubtype == 0x09) ||
910554c0a3aSHans de Goede 		   (frsubtype == 0x0a) ||
911554c0a3aSHans de Goede 		   (frsubtype == 0x0b))) {
912554c0a3aSHans de Goede 		if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
913554c0a3aSHans de Goede 			hdrlen += 2;
914554c0a3aSHans de Goede 
915554c0a3aSHans de Goede 		qc_exists = 1;
91670466c39SRoss Schmidt 	} else {
917554c0a3aSHans de Goede 		qc_exists = 0;
91870466c39SRoss Schmidt 	}
919554c0a3aSHans de Goede 
920554c0a3aSHans de Goede 	pn_vector[0] = pframe[hdrlen];
921554c0a3aSHans de Goede 	pn_vector[1] = pframe[hdrlen+1];
922554c0a3aSHans de Goede 	pn_vector[2] = pframe[hdrlen+4];
923554c0a3aSHans de Goede 	pn_vector[3] = pframe[hdrlen+5];
924554c0a3aSHans de Goede 	pn_vector[4] = pframe[hdrlen+6];
925554c0a3aSHans de Goede 	pn_vector[5] = pframe[hdrlen+7];
926554c0a3aSHans de Goede 
9275641eeecSRoss Schmidt 	construct_mic_iv(mic_iv,
928554c0a3aSHans de Goede 			 qc_exists,
929554c0a3aSHans de Goede 			 a4_exists,
930554c0a3aSHans de Goede 			 pframe,	 /* message, */
931554c0a3aSHans de Goede 			 plen,
932554c0a3aSHans de Goede 			 pn_vector,
9335641eeecSRoss Schmidt 			 frtype); /*  add for CONFIG_IEEE80211W, none 11w also can use */
934554c0a3aSHans de Goede 
9355641eeecSRoss Schmidt 	construct_mic_header1(mic_header1,
936554c0a3aSHans de Goede 			      hdrlen,
937554c0a3aSHans de Goede 			      pframe,	/* message */
9385641eeecSRoss Schmidt 			      frtype); /*  add for CONFIG_IEEE80211W, none 11w also can use */
9395641eeecSRoss Schmidt 
9405641eeecSRoss Schmidt 	construct_mic_header2(mic_header2,
941554c0a3aSHans de Goede 			      pframe,	/* message, */
942554c0a3aSHans de Goede 			      a4_exists,
9435641eeecSRoss Schmidt 			      qc_exists);
944554c0a3aSHans de Goede 
945554c0a3aSHans de Goede 	payload_remainder = plen % 16;
946554c0a3aSHans de Goede 	num_blocks = plen / 16;
947554c0a3aSHans de Goede 
948554c0a3aSHans de Goede 	/* Find start of payload */
949554c0a3aSHans de Goede 	payload_index = (hdrlen + 8);
950554c0a3aSHans de Goede 
951554c0a3aSHans de Goede 	/* Calculate MIC */
952554c0a3aSHans de Goede 	aes128k128d(key, mic_iv, aes_out);
953554c0a3aSHans de Goede 	bitwise_xor(aes_out, mic_header1, chain_buffer);
954554c0a3aSHans de Goede 	aes128k128d(key, chain_buffer, aes_out);
955554c0a3aSHans de Goede 	bitwise_xor(aes_out, mic_header2, chain_buffer);
956554c0a3aSHans de Goede 	aes128k128d(key, chain_buffer, aes_out);
957554c0a3aSHans de Goede 
958554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
95922b5cbd1SJavier F. Arias 		bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
960554c0a3aSHans de Goede 
961554c0a3aSHans de Goede 		payload_index += 16;
962554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
963554c0a3aSHans de Goede 	}
964554c0a3aSHans de Goede 
965554c0a3aSHans de Goede 	/* Add on the final payload block if it needs padding */
966554c0a3aSHans de Goede 	if (payload_remainder > 0) {
967554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
968554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
96970466c39SRoss Schmidt 		for (j = 0; j < payload_remainder; j++)
97022b5cbd1SJavier F. Arias 			padded_buffer[j] = pframe[payload_index++];
97170466c39SRoss Schmidt 
972554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
973554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
974554c0a3aSHans de Goede 	}
975554c0a3aSHans de Goede 
976554c0a3aSHans de Goede 	for (j = 0 ; j < 8; j++)
977554c0a3aSHans de Goede 		mic[j] = aes_out[j];
978554c0a3aSHans de Goede 
979554c0a3aSHans de Goede 	/* Insert MIC into payload */
980554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
98122b5cbd1SJavier F. Arias 		pframe[payload_index+j] = mic[j];
982554c0a3aSHans de Goede 
983554c0a3aSHans de Goede 	payload_index = hdrlen + 8;
984554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
9855641eeecSRoss Schmidt 		construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, /* message, */
9865641eeecSRoss Schmidt 				      pn_vector, i+1, frtype);
9875641eeecSRoss Schmidt 		/*  add for CONFIG_IEEE80211W, none 11w also can use */
988554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
98922b5cbd1SJavier F. Arias 		bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
990554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
99122b5cbd1SJavier F. Arias 			pframe[payload_index++] = chain_buffer[j];
992554c0a3aSHans de Goede 	}
993554c0a3aSHans de Goede 
994554c0a3aSHans de Goede 	if (payload_remainder > 0) {
995554c0a3aSHans de Goede 		/* If there is a short final block, then pad it,*/
996554c0a3aSHans de Goede 		/* encrypt it and copy the unpadded part back   */
9975641eeecSRoss Schmidt 		construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, /* message, */
9985641eeecSRoss Schmidt 				      pn_vector, num_blocks+1, frtype);
9995641eeecSRoss Schmidt 		/*  add for CONFIG_IEEE80211W, none 11w also can use */
1000554c0a3aSHans de Goede 
1001554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1002554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
10030ba8d4b9SLarry Finger 		for (j = 0; j < payload_remainder; j++)
100422b5cbd1SJavier F. Arias 			padded_buffer[j] = pframe[payload_index+j];
10050ba8d4b9SLarry Finger 
1006554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1007554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1008554c0a3aSHans de Goede 		for (j = 0; j < payload_remainder; j++)
100922b5cbd1SJavier F. Arias 			pframe[payload_index++] = chain_buffer[j];
1010554c0a3aSHans de Goede 	}
1011554c0a3aSHans de Goede 
1012554c0a3aSHans de Goede 	/* Encrypt the MIC */
10135641eeecSRoss Schmidt 	construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, /* message, */
10145641eeecSRoss Schmidt 			      pn_vector, 0, frtype);
10155641eeecSRoss Schmidt 	/*  add for CONFIG_IEEE80211W, none 11w also can use */
1016554c0a3aSHans de Goede 
1017554c0a3aSHans de Goede 	for (j = 0; j < 16; j++)
1018554c0a3aSHans de Goede 		padded_buffer[j] = 0x00;
10190ba8d4b9SLarry Finger 	for (j = 0; j < 8; j++)
102022b5cbd1SJavier F. Arias 		padded_buffer[j] = pframe[j+hdrlen+8+plen];
1021554c0a3aSHans de Goede 
1022554c0a3aSHans de Goede 	aes128k128d(key, ctr_preload, aes_out);
1023554c0a3aSHans de Goede 	bitwise_xor(aes_out, padded_buffer, chain_buffer);
1024554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
102522b5cbd1SJavier F. Arias 		pframe[payload_index++] = chain_buffer[j];
1026554c0a3aSHans de Goede 
1027554c0a3aSHans de Goede 	return _SUCCESS;
1028554c0a3aSHans de Goede }
1029554c0a3aSHans de Goede 
rtw_aes_encrypt(struct adapter * padapter,u8 * pxmitframe)1030554c0a3aSHans de Goede u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe)
1031554c0a3aSHans de Goede {	/*  exclude ICV */
1032554c0a3aSHans de Goede 
1033554c0a3aSHans de Goede 	/*static*/
1034554c0a3aSHans de Goede 	/* unsigned char message[MAX_MSG_SIZE]; */
1035554c0a3aSHans de Goede 
1036554c0a3aSHans de Goede 	/* Intermediate Buffers */
1037d495c550SMarco Cesati 	signed int curfragnum, length;
1038554c0a3aSHans de Goede 	u8 *pframe, *prwskey;	/*  *payload,*iv */
1039554c0a3aSHans de Goede 	u8 hw_hdr_offset = 0;
1040554c0a3aSHans de Goede 	struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
1041554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
1042554c0a3aSHans de Goede 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1043554c0a3aSHans de Goede 
1044554c0a3aSHans de Goede 	u32 res = _SUCCESS;
1045554c0a3aSHans de Goede 
1046cd1f1450SMichael Straube 	if (!((struct xmit_frame *)pxmitframe)->buf_addr)
1047554c0a3aSHans de Goede 		return _FAIL;
1048554c0a3aSHans de Goede 
1049554c0a3aSHans de Goede 	hw_hdr_offset = TXDESC_OFFSET;
1050554c0a3aSHans de Goede 	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
1051554c0a3aSHans de Goede 
1052554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
105307523ee1SColin Ian King 	if (pattrib->encrypt == _AES_) {
1054*be6cded3SRuan Jinjie 		if (is_multicast_ether_addr(pattrib->ra))
1055554c0a3aSHans de Goede 			prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
1056554c0a3aSHans de Goede 		else
1057554c0a3aSHans de Goede 			prwskey = pattrib->dot118021x_UncstKey.skey;
1058554c0a3aSHans de Goede 
1059554c0a3aSHans de Goede 		for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
1060554c0a3aSHans de Goede 			if ((curfragnum+1) == pattrib->nr_frags) {	/* 4 the last fragment */
1061554c0a3aSHans de Goede 				length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
1062554c0a3aSHans de Goede 
1063554c0a3aSHans de Goede 				aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1064554c0a3aSHans de Goede 			} else {
1065554c0a3aSHans de Goede 				length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
1066554c0a3aSHans de Goede 
1067554c0a3aSHans de Goede 				aes_cipher(prwskey, pattrib->hdrlen, pframe, length);
1068554c0a3aSHans de Goede 				pframe += pxmitpriv->frag_len;
106987fe08d7SRoss Schmidt 				pframe = (u8 *)round_up((SIZE_PTR)(pframe), 4);
1070554c0a3aSHans de Goede 			}
1071554c0a3aSHans de Goede 		}
1072554c0a3aSHans de Goede 	}
1073554c0a3aSHans de Goede 	return res;
1074554c0a3aSHans de Goede }
1075554c0a3aSHans de Goede 
aes_decipher(u8 * key,uint hdrlen,u8 * pframe,uint plen)1076d495c550SMarco Cesati static signed int aes_decipher(u8 *key, uint	hdrlen,
1077554c0a3aSHans de Goede 			 u8 *pframe, uint plen)
1078554c0a3aSHans de Goede {
1079554c0a3aSHans de Goede 	static u8 message[MAX_MSG_SIZE];
1080554c0a3aSHans de Goede 	uint qc_exists, a4_exists, i, j, payload_remainder,
1081554c0a3aSHans de Goede 			num_blocks, payload_index;
1082d495c550SMarco Cesati 	signed int res = _SUCCESS;
1083554c0a3aSHans de Goede 	u8 pn_vector[6];
1084554c0a3aSHans de Goede 	u8 mic_iv[16];
1085554c0a3aSHans de Goede 	u8 mic_header1[16];
1086554c0a3aSHans de Goede 	u8 mic_header2[16];
1087554c0a3aSHans de Goede 	u8 ctr_preload[16];
1088554c0a3aSHans de Goede 
1089554c0a3aSHans de Goede 		/* Intermediate Buffers */
1090554c0a3aSHans de Goede 	u8 chain_buffer[16];
1091554c0a3aSHans de Goede 	u8 aes_out[16];
1092554c0a3aSHans de Goede 	u8 padded_buffer[16];
1093554c0a3aSHans de Goede 	u8 mic[8];
1094554c0a3aSHans de Goede 
1095554c0a3aSHans de Goede 	uint frtype  = GetFrameType(pframe);
1096554c0a3aSHans de Goede 	uint frsubtype  = GetFrameSubType(pframe);
1097554c0a3aSHans de Goede 
1098554c0a3aSHans de Goede 	frsubtype = frsubtype>>4;
1099554c0a3aSHans de Goede 
1100554c0a3aSHans de Goede 	memset((void *)mic_iv, 0, 16);
1101554c0a3aSHans de Goede 	memset((void *)mic_header1, 0, 16);
1102554c0a3aSHans de Goede 	memset((void *)mic_header2, 0, 16);
1103554c0a3aSHans de Goede 	memset((void *)ctr_preload, 0, 16);
1104554c0a3aSHans de Goede 	memset((void *)chain_buffer, 0, 16);
1105554c0a3aSHans de Goede 	memset((void *)aes_out, 0, 16);
1106554c0a3aSHans de Goede 	memset((void *)padded_buffer, 0, 16);
1107554c0a3aSHans de Goede 
1108554c0a3aSHans de Goede 	/* start to decrypt the payload */
1109554c0a3aSHans de Goede 
1110554c0a3aSHans de Goede 	num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */
1111554c0a3aSHans de Goede 
1112554c0a3aSHans de Goede 	payload_remainder = (plen-8) % 16;
1113554c0a3aSHans de Goede 
1114554c0a3aSHans de Goede 	pn_vector[0]  = pframe[hdrlen];
1115554c0a3aSHans de Goede 	pn_vector[1]  = pframe[hdrlen + 1];
1116554c0a3aSHans de Goede 	pn_vector[2]  = pframe[hdrlen + 4];
1117554c0a3aSHans de Goede 	pn_vector[3]  = pframe[hdrlen + 5];
1118554c0a3aSHans de Goede 	pn_vector[4]  = pframe[hdrlen + 6];
1119554c0a3aSHans de Goede 	pn_vector[5]  = pframe[hdrlen + 7];
1120554c0a3aSHans de Goede 
1121554c0a3aSHans de Goede 	if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
1122554c0a3aSHans de Goede 		a4_exists = 0;
1123554c0a3aSHans de Goede 	else
1124554c0a3aSHans de Goede 		a4_exists = 1;
1125554c0a3aSHans de Goede 
11260ba8d4b9SLarry Finger 	if (((frtype|frsubtype) == WIFI_DATA_CFACK) ||
1127554c0a3aSHans de Goede 	    ((frtype|frsubtype) == WIFI_DATA_CFPOLL) ||
1128554c0a3aSHans de Goede 	    ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) {
1129554c0a3aSHans de Goede 		qc_exists = 1;
113070466c39SRoss Schmidt 		if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
1131554c0a3aSHans de Goede 			hdrlen += 2;
113270466c39SRoss Schmidt 
1133554c0a3aSHans de Goede 	} else if ((frtype == WIFI_DATA) && /* only for data packet . add for CONFIG_IEEE80211W, none 11w also can use */
1134554c0a3aSHans de Goede 		   ((frsubtype == 0x08) ||
1135554c0a3aSHans de Goede 		   (frsubtype == 0x09) ||
1136554c0a3aSHans de Goede 		   (frsubtype == 0x0a) ||
1137554c0a3aSHans de Goede 		   (frsubtype == 0x0b))) {
113870466c39SRoss Schmidt 		if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
1139554c0a3aSHans de Goede 			hdrlen += 2;
114070466c39SRoss Schmidt 
1141554c0a3aSHans de Goede 		qc_exists = 1;
114270466c39SRoss Schmidt 	} else {
1143554c0a3aSHans de Goede 		qc_exists = 0;
114470466c39SRoss Schmidt 	}
1145554c0a3aSHans de Goede 
1146554c0a3aSHans de Goede 	/*  now, decrypt pframe with hdrlen offset and plen long */
1147554c0a3aSHans de Goede 
1148554c0a3aSHans de Goede 	payload_index = hdrlen + 8; /*  8 is for extiv */
1149554c0a3aSHans de Goede 
1150554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
1151e004d7acSJavier F. Arias 		construct_ctr_preload(ctr_preload, a4_exists,
1152e004d7acSJavier F. Arias 				      qc_exists, pframe,
1153e004d7acSJavier F. Arias 				      pn_vector, i + 1,
1154e004d7acSJavier F. Arias 				      frtype); /*  add for CONFIG_IEEE80211W, none 11w also can use */
1155554c0a3aSHans de Goede 
1156554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1157554c0a3aSHans de Goede 		bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
1158554c0a3aSHans de Goede 
1159554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1160554c0a3aSHans de Goede 			pframe[payload_index++] = chain_buffer[j];
1161554c0a3aSHans de Goede 	}
1162554c0a3aSHans de Goede 
1163554c0a3aSHans de Goede 	if (payload_remainder > 0) {
1164554c0a3aSHans de Goede 		/* If there is a short final block, then pad it,*/
1165554c0a3aSHans de Goede 		/* encrypt it and copy the unpadded part back   */
11665641eeecSRoss Schmidt 		construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector,
11675641eeecSRoss Schmidt 				      num_blocks+1, frtype);
11685641eeecSRoss Schmidt 		/*  add for CONFIG_IEEE80211W, none 11w also can use */
1169554c0a3aSHans de Goede 
1170554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1171554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
117270466c39SRoss Schmidt 		for (j = 0; j < payload_remainder; j++)
1173554c0a3aSHans de Goede 			padded_buffer[j] = pframe[payload_index+j];
117470466c39SRoss Schmidt 
1175554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1176554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1177554c0a3aSHans de Goede 		for (j = 0; j < payload_remainder; j++)
1178554c0a3aSHans de Goede 			pframe[payload_index++] = chain_buffer[j];
1179554c0a3aSHans de Goede 	}
1180554c0a3aSHans de Goede 
1181554c0a3aSHans de Goede 	/* start to calculate the mic */
1182554c0a3aSHans de Goede 	if ((hdrlen + plen+8) <= MAX_MSG_SIZE)
1183554c0a3aSHans de Goede 		memcpy((void *)message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv len */
1184554c0a3aSHans de Goede 
1185554c0a3aSHans de Goede 	pn_vector[0] = pframe[hdrlen];
1186554c0a3aSHans de Goede 	pn_vector[1] = pframe[hdrlen+1];
1187554c0a3aSHans de Goede 	pn_vector[2] = pframe[hdrlen+4];
1188554c0a3aSHans de Goede 	pn_vector[3] = pframe[hdrlen+5];
1189554c0a3aSHans de Goede 	pn_vector[4] = pframe[hdrlen+6];
1190554c0a3aSHans de Goede 	pn_vector[5] = pframe[hdrlen+7];
1191554c0a3aSHans de Goede 
11925641eeecSRoss Schmidt 	construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen-8, pn_vector, frtype);
11935641eeecSRoss Schmidt 	/*  add for CONFIG_IEEE80211W, none 11w also can use */
1194554c0a3aSHans de Goede 
11955641eeecSRoss Schmidt 	construct_mic_header1(mic_header1, hdrlen, message, frtype);
11965641eeecSRoss Schmidt 	/*  add for CONFIG_IEEE80211W, none 11w also can use */
11975641eeecSRoss Schmidt 	construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
1198554c0a3aSHans de Goede 
1199554c0a3aSHans de Goede 	payload_remainder = (plen-8) % 16;
1200554c0a3aSHans de Goede 	num_blocks = (plen-8) / 16;
1201554c0a3aSHans de Goede 
1202554c0a3aSHans de Goede 	/* Find start of payload */
1203554c0a3aSHans de Goede 	payload_index = (hdrlen + 8);
1204554c0a3aSHans de Goede 
1205554c0a3aSHans de Goede 	/* Calculate MIC */
1206554c0a3aSHans de Goede 	aes128k128d(key, mic_iv, aes_out);
1207554c0a3aSHans de Goede 	bitwise_xor(aes_out, mic_header1, chain_buffer);
1208554c0a3aSHans de Goede 	aes128k128d(key, chain_buffer, aes_out);
1209554c0a3aSHans de Goede 	bitwise_xor(aes_out, mic_header2, chain_buffer);
1210554c0a3aSHans de Goede 	aes128k128d(key, chain_buffer, aes_out);
1211554c0a3aSHans de Goede 
1212554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
1213554c0a3aSHans de Goede 		bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1214554c0a3aSHans de Goede 
1215554c0a3aSHans de Goede 		payload_index += 16;
1216554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1217554c0a3aSHans de Goede 	}
1218554c0a3aSHans de Goede 
1219554c0a3aSHans de Goede 	/* Add on the final payload block if it needs padding */
1220554c0a3aSHans de Goede 	if (payload_remainder > 0) {
1221554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1222554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
122370466c39SRoss Schmidt 		for (j = 0; j < payload_remainder; j++)
1224554c0a3aSHans de Goede 			padded_buffer[j] = message[payload_index++];
122570466c39SRoss Schmidt 
1226554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1227554c0a3aSHans de Goede 		aes128k128d(key, chain_buffer, aes_out);
1228554c0a3aSHans de Goede 	}
1229554c0a3aSHans de Goede 
1230554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
1231554c0a3aSHans de Goede 		mic[j] = aes_out[j];
1232554c0a3aSHans de Goede 
1233554c0a3aSHans de Goede 	/* Insert MIC into payload */
1234554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
1235554c0a3aSHans de Goede 		message[payload_index+j] = mic[j];
1236554c0a3aSHans de Goede 
1237554c0a3aSHans de Goede 	payload_index = hdrlen + 8;
1238554c0a3aSHans de Goede 	for (i = 0; i < num_blocks; i++) {
12395641eeecSRoss Schmidt 		construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, i+1,
12405641eeecSRoss Schmidt 				      frtype);
12415641eeecSRoss Schmidt 		/*  add for CONFIG_IEEE80211W, none 11w also can use */
1242554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1243554c0a3aSHans de Goede 		bitwise_xor(aes_out, &message[payload_index], chain_buffer);
1244554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1245554c0a3aSHans de Goede 			message[payload_index++] = chain_buffer[j];
1246554c0a3aSHans de Goede 	}
1247554c0a3aSHans de Goede 
1248554c0a3aSHans de Goede 	if (payload_remainder > 0) {
1249554c0a3aSHans de Goede 		/* If there is a short final block, then pad it,*/
1250554c0a3aSHans de Goede 		/* encrypt it and copy the unpadded part back   */
12515641eeecSRoss Schmidt 		construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector,
12525641eeecSRoss Schmidt 				      num_blocks+1, frtype);
12535641eeecSRoss Schmidt 		/*  add for CONFIG_IEEE80211W, none 11w also can use */
1254554c0a3aSHans de Goede 
1255554c0a3aSHans de Goede 		for (j = 0; j < 16; j++)
1256554c0a3aSHans de Goede 			padded_buffer[j] = 0x00;
125770466c39SRoss Schmidt 		for (j = 0; j < payload_remainder; j++)
1258554c0a3aSHans de Goede 			padded_buffer[j] = message[payload_index+j];
125970466c39SRoss Schmidt 
1260554c0a3aSHans de Goede 		aes128k128d(key, ctr_preload, aes_out);
1261554c0a3aSHans de Goede 		bitwise_xor(aes_out, padded_buffer, chain_buffer);
1262554c0a3aSHans de Goede 		for (j = 0; j < payload_remainder; j++)
1263554c0a3aSHans de Goede 			message[payload_index++] = chain_buffer[j];
1264554c0a3aSHans de Goede 	}
1265554c0a3aSHans de Goede 
1266554c0a3aSHans de Goede 	/* Encrypt the MIC */
12675641eeecSRoss Schmidt 	construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, 0, frtype);
12685641eeecSRoss Schmidt 	/*  add for CONFIG_IEEE80211W, none 11w also can use */
1269554c0a3aSHans de Goede 
1270554c0a3aSHans de Goede 	for (j = 0; j < 16; j++)
1271554c0a3aSHans de Goede 		padded_buffer[j] = 0x00;
127270466c39SRoss Schmidt 	for (j = 0; j < 8; j++)
1273554c0a3aSHans de Goede 		padded_buffer[j] = message[j+hdrlen+8+plen-8];
1274554c0a3aSHans de Goede 
1275554c0a3aSHans de Goede 	aes128k128d(key, ctr_preload, aes_out);
1276554c0a3aSHans de Goede 	bitwise_xor(aes_out, padded_buffer, chain_buffer);
1277554c0a3aSHans de Goede 	for (j = 0; j < 8; j++)
1278554c0a3aSHans de Goede 		message[payload_index++] = chain_buffer[j];
1279554c0a3aSHans de Goede 
1280554c0a3aSHans de Goede 	/* compare the mic */
1281554c0a3aSHans de Goede 	for (i = 0; i < 8; i++) {
1282709c8e49SFabio Aiuto 		if (pframe[hdrlen + 8 + plen - 8 + i] != message[hdrlen + 8 + plen - 8 + i])
1283554c0a3aSHans de Goede 			res = _FAIL;
1284554c0a3aSHans de Goede 	}
1285554c0a3aSHans de Goede 	return res;
1286554c0a3aSHans de Goede }
1287554c0a3aSHans de Goede 
rtw_aes_decrypt(struct adapter * padapter,u8 * precvframe)1288554c0a3aSHans de Goede u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
1289554c0a3aSHans de Goede {	/*  exclude ICV */
1290554c0a3aSHans de Goede 
1291554c0a3aSHans de Goede 	/*static*/
1292554c0a3aSHans de Goede 	/* unsigned char message[MAX_MSG_SIZE]; */
1293554c0a3aSHans de Goede 
1294554c0a3aSHans de Goede 	/* Intermediate Buffers */
1295554c0a3aSHans de Goede 
1296d495c550SMarco Cesati 	signed int length;
1297554c0a3aSHans de Goede 	u8 *pframe, *prwskey;	/*  *payload,*iv */
1298554c0a3aSHans de Goede 	struct sta_info *stainfo;
1299554c0a3aSHans de Goede 	struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
1300554c0a3aSHans de Goede 	struct security_priv *psecuritypriv = &padapter->securitypriv;
1301554c0a3aSHans de Goede 	u32 res = _SUCCESS;
1302554c0a3aSHans de Goede 
1303554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
1304554c0a3aSHans de Goede 	/* 4 start to encrypt each fragment */
130507523ee1SColin Ian King 	if (prxattrib->encrypt == _AES_) {
1306554c0a3aSHans de Goede 		stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]);
130734557e23SIzabela Bakollari 		if (stainfo) {
1308*be6cded3SRuan Jinjie 			if (is_multicast_ether_addr(prxattrib->ra)) {
130940d4aa0fSShreeya Patel 				static unsigned long start;
131040d4aa0fSShreeya Patel 				static u32 no_gkey_bc_cnt;
131140d4aa0fSShreeya Patel 				static u32 no_gkey_mc_cnt;
1312554c0a3aSHans de Goede 
13133ac5add1SJohn Oldman 				if (!psecuritypriv->binstallGrpkey) {
1314554c0a3aSHans de Goede 					res = _FAIL;
1315554c0a3aSHans de Goede 
1316554c0a3aSHans de Goede 					if (start == 0)
1317554c0a3aSHans de Goede 						start = jiffies;
1318554c0a3aSHans de Goede 
1319554c0a3aSHans de Goede 					if (is_broadcast_mac_addr(prxattrib->ra))
1320554c0a3aSHans de Goede 						no_gkey_bc_cnt++;
1321554c0a3aSHans de Goede 					else
1322554c0a3aSHans de Goede 						no_gkey_mc_cnt++;
1323554c0a3aSHans de Goede 
1324554c0a3aSHans de Goede 					if (jiffies_to_msecs(jiffies - start) > 1000) {
1325554c0a3aSHans de Goede 						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
132679df841bSFabio Aiuto 							netdev_dbg(padapter->pnetdev,
132779df841bSFabio Aiuto 								   FUNC_ADPT_FMT " no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
132879df841bSFabio Aiuto 								   FUNC_ADPT_ARG(padapter),
132979df841bSFabio Aiuto 								   no_gkey_bc_cnt,
133079df841bSFabio Aiuto 								   no_gkey_mc_cnt);
1331554c0a3aSHans de Goede 						}
1332554c0a3aSHans de Goede 						start = jiffies;
1333554c0a3aSHans de Goede 						no_gkey_bc_cnt = 0;
1334554c0a3aSHans de Goede 						no_gkey_mc_cnt = 0;
1335554c0a3aSHans de Goede 					}
1336554c0a3aSHans de Goede 
1337554c0a3aSHans de Goede 					goto exit;
1338554c0a3aSHans de Goede 				}
1339554c0a3aSHans de Goede 
1340554c0a3aSHans de Goede 				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
134179df841bSFabio Aiuto 					netdev_dbg(padapter->pnetdev,
134279df841bSFabio Aiuto 						   FUNC_ADPT_FMT " gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
134379df841bSFabio Aiuto 						   FUNC_ADPT_ARG(padapter),
134479df841bSFabio Aiuto 						   no_gkey_bc_cnt,
134579df841bSFabio Aiuto 						   no_gkey_mc_cnt);
1346554c0a3aSHans de Goede 				}
1347554c0a3aSHans de Goede 				start = 0;
1348554c0a3aSHans de Goede 				no_gkey_bc_cnt = 0;
1349554c0a3aSHans de Goede 				no_gkey_mc_cnt = 0;
1350554c0a3aSHans de Goede 
1351554c0a3aSHans de Goede 				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
1352554c0a3aSHans de Goede 				if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) {
1353554c0a3aSHans de Goede 					res = _FAIL;
1354554c0a3aSHans de Goede 					goto exit;
1355554c0a3aSHans de Goede 				}
135670466c39SRoss Schmidt 			} else {
1357554c0a3aSHans de Goede 				prwskey = &stainfo->dot118021x_UncstKey.skey[0];
135870466c39SRoss Schmidt 			}
1359554c0a3aSHans de Goede 
1360554c0a3aSHans de Goede 			length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
1361554c0a3aSHans de Goede 
1362554c0a3aSHans de Goede 			res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length);
1363554c0a3aSHans de Goede 
1364554c0a3aSHans de Goede 		} else {
1365554c0a3aSHans de Goede 			res = _FAIL;
1366554c0a3aSHans de Goede 		}
1367554c0a3aSHans de Goede 	}
1368554c0a3aSHans de Goede exit:
1369554c0a3aSHans de Goede 	return res;
1370554c0a3aSHans de Goede }
1371554c0a3aSHans de Goede 
rtw_BIP_verify(struct adapter * padapter,u8 * precvframe)1372554c0a3aSHans de Goede u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe)
1373554c0a3aSHans de Goede {
1374554c0a3aSHans de Goede 	struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
1375554c0a3aSHans de Goede 	u8 *pframe;
1376554c0a3aSHans de Goede 	u8 *BIP_AAD, *p;
1377554c0a3aSHans de Goede 	u32 res = _FAIL;
1378554c0a3aSHans de Goede 	uint len, ori_len;
1379554c0a3aSHans de Goede 	struct ieee80211_hdr *pwlanhdr;
1380554c0a3aSHans de Goede 	u8 mic[16];
1381554c0a3aSHans de Goede 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1382554c0a3aSHans de Goede 	__le16 le_tmp;
1383554c0a3aSHans de Goede 	__le64 le_tmp64;
1384554c0a3aSHans de Goede 
1385554c0a3aSHans de Goede 	ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
1386554c0a3aSHans de Goede 	BIP_AAD = rtw_zmalloc(ori_len);
1387554c0a3aSHans de Goede 
1388e427bdd8SFabio Aiuto 	if (!BIP_AAD)
1389554c0a3aSHans de Goede 		return _FAIL;
1390709c8e49SFabio Aiuto 
1391554c0a3aSHans de Goede 	/* PKT start */
1392554c0a3aSHans de Goede 	pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data;
1393554c0a3aSHans de Goede 	/* mapping to wlan header */
1394554c0a3aSHans de Goede 	pwlanhdr = (struct ieee80211_hdr *)pframe;
1395554c0a3aSHans de Goede 	/* save the frame body + MME */
1396554c0a3aSHans de Goede 	memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN);
1397554c0a3aSHans de Goede 	/* find MME IE pointer */
139899bb7769SRoss Schmidt 	p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, WLAN_EID_MMIE, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN);
1399554c0a3aSHans de Goede 	/* Baron */
1400554c0a3aSHans de Goede 	if (p) {
1401554c0a3aSHans de Goede 		u16 keyid = 0;
1402554c0a3aSHans de Goede 		u64 temp_ipn = 0;
1403554c0a3aSHans de Goede 		/* save packet number */
1404554c0a3aSHans de Goede 		memcpy(&le_tmp64, p+4, 6);
1405554c0a3aSHans de Goede 		temp_ipn = le64_to_cpu(le_tmp64);
1406554c0a3aSHans de Goede 		/* BIP packet number should bigger than previous BIP packet */
1407709c8e49SFabio Aiuto 		if (temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx)
1408554c0a3aSHans de Goede 			goto BIP_exit;
1409709c8e49SFabio Aiuto 
1410554c0a3aSHans de Goede 		/* copy key index */
1411554c0a3aSHans de Goede 		memcpy(&le_tmp, p+2, 2);
1412554c0a3aSHans de Goede 		keyid = le16_to_cpu(le_tmp);
1413709c8e49SFabio Aiuto 		if (keyid != padapter->securitypriv.dot11wBIPKeyid)
1414554c0a3aSHans de Goede 			goto BIP_exit;
1415709c8e49SFabio Aiuto 
1416554c0a3aSHans de Goede 		/* clear the MIC field of MME to zero */
1417554c0a3aSHans de Goede 		memset(p+2+len-8, 0, 8);
1418554c0a3aSHans de Goede 
1419554c0a3aSHans de Goede 		/* conscruct AAD, copy frame control field */
1420554c0a3aSHans de Goede 		memcpy(BIP_AAD, &pwlanhdr->frame_control, 2);
1421554c0a3aSHans de Goede 		ClearRetry(BIP_AAD);
1422554c0a3aSHans de Goede 		ClearPwrMgt(BIP_AAD);
1423554c0a3aSHans de Goede 		ClearMData(BIP_AAD);
1424554c0a3aSHans de Goede 		/* conscruct AAD, copy address 1 to address 3 */
1425554c0a3aSHans de Goede 		memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
1426554c0a3aSHans de Goede 
1427554c0a3aSHans de Goede 		if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
1428554c0a3aSHans de Goede 			, BIP_AAD, ori_len, mic))
1429554c0a3aSHans de Goede 			goto BIP_exit;
1430554c0a3aSHans de Goede 
1431554c0a3aSHans de Goede 		/* MIC field should be last 8 bytes of packet (packet without FCS) */
1432554c0a3aSHans de Goede 		if (!memcmp(mic, pframe+pattrib->pkt_len-8, 8)) {
1433554c0a3aSHans de Goede 			pmlmeext->mgnt_80211w_IPN_rx = temp_ipn;
1434554c0a3aSHans de Goede 			res = _SUCCESS;
143570466c39SRoss Schmidt 		} else {
143670466c39SRoss Schmidt 		}
1437554c0a3aSHans de Goede 
143870466c39SRoss Schmidt 	} else {
1439554c0a3aSHans de Goede 		res = RTW_RX_HANDLED;
144070466c39SRoss Schmidt 	}
1441554c0a3aSHans de Goede BIP_exit:
1442554c0a3aSHans de Goede 
1443554c0a3aSHans de Goede 	kfree(BIP_AAD);
1444554c0a3aSHans de Goede 	return res;
1445554c0a3aSHans de Goede }
1446554c0a3aSHans de Goede 
gf_mulx(u8 * pad)1447554c0a3aSHans de Goede static void gf_mulx(u8 *pad)
1448554c0a3aSHans de Goede {
1449554c0a3aSHans de Goede 	int i, carry;
1450554c0a3aSHans de Goede 
1451554c0a3aSHans de Goede 	carry = pad[0] & 0x80;
1452554c0a3aSHans de Goede 	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
1453554c0a3aSHans de Goede 		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
1454554c0a3aSHans de Goede 
1455554c0a3aSHans de Goede 	pad[AES_BLOCK_SIZE - 1] <<= 1;
1456554c0a3aSHans de Goede 	if (carry)
1457554c0a3aSHans de Goede 		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
1458554c0a3aSHans de Goede }
1459554c0a3aSHans de Goede 
1460554c0a3aSHans de Goede /**
1461554c0a3aSHans de Goede  * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
1462554c0a3aSHans de Goede  * @key: 128-bit key for the hash operation
1463554c0a3aSHans de Goede  * @num_elem: Number of elements in the data vector
1464554c0a3aSHans de Goede  * @addr: Pointers to the data areas
1465554c0a3aSHans de Goede  * @len: Lengths of the data blocks
1466554c0a3aSHans de Goede  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
1467554c0a3aSHans de Goede  * Returns: 0 on success, -1 on failure
1468554c0a3aSHans de Goede  *
1469554c0a3aSHans de Goede  * This is a mode for using block cipher (AES in this case) for authentication.
1470554c0a3aSHans de Goede  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
1471554c0a3aSHans de Goede  * (SP) 800-38B.
1472554c0a3aSHans de Goede  */
omac1_aes_128_vector(u8 * key,size_t num_elem,u8 * addr[],size_t * len,u8 * mac)1473554c0a3aSHans de Goede static int omac1_aes_128_vector(u8 *key, size_t num_elem,
1474554c0a3aSHans de Goede 				u8 *addr[], size_t *len, u8 *mac)
1475554c0a3aSHans de Goede {
14767d40753dSFabio Aiuto 	struct crypto_aes_ctx ctx;
1477554c0a3aSHans de Goede 	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
1478554c0a3aSHans de Goede 	u8 *pos, *end;
1479554c0a3aSHans de Goede 	size_t i, e, left, total_len;
14807d40753dSFabio Aiuto 	int ret;
1481554c0a3aSHans de Goede 
14827d40753dSFabio Aiuto 	ret = aes_expandkey(&ctx, key, 16);
14837d40753dSFabio Aiuto 	if (ret)
1484554c0a3aSHans de Goede 		return -1;
1485554c0a3aSHans de Goede 	memset(cbc, 0, AES_BLOCK_SIZE);
1486554c0a3aSHans de Goede 
1487554c0a3aSHans de Goede 	total_len = 0;
1488554c0a3aSHans de Goede 	for (e = 0; e < num_elem; e++)
1489554c0a3aSHans de Goede 		total_len += len[e];
1490554c0a3aSHans de Goede 	left = total_len;
1491554c0a3aSHans de Goede 
1492554c0a3aSHans de Goede 	e = 0;
1493554c0a3aSHans de Goede 	pos = addr[0];
1494554c0a3aSHans de Goede 	end = pos + len[0];
1495554c0a3aSHans de Goede 
1496554c0a3aSHans de Goede 	while (left >= AES_BLOCK_SIZE) {
1497554c0a3aSHans de Goede 		for (i = 0; i < AES_BLOCK_SIZE; i++) {
1498554c0a3aSHans de Goede 			cbc[i] ^= *pos++;
1499554c0a3aSHans de Goede 			if (pos >= end) {
1500554c0a3aSHans de Goede 				e++;
1501554c0a3aSHans de Goede 				pos = addr[e];
1502554c0a3aSHans de Goede 				end = pos + len[e];
1503554c0a3aSHans de Goede 			}
1504554c0a3aSHans de Goede 		}
1505554c0a3aSHans de Goede 		if (left > AES_BLOCK_SIZE)
15067d40753dSFabio Aiuto 			aes_encrypt(&ctx, cbc, cbc);
1507554c0a3aSHans de Goede 		left -= AES_BLOCK_SIZE;
1508554c0a3aSHans de Goede 	}
1509554c0a3aSHans de Goede 
1510554c0a3aSHans de Goede 	memset(pad, 0, AES_BLOCK_SIZE);
15117d40753dSFabio Aiuto 	aes_encrypt(&ctx, pad, pad);
1512554c0a3aSHans de Goede 	gf_mulx(pad);
1513554c0a3aSHans de Goede 
1514554c0a3aSHans de Goede 	if (left || total_len == 0) {
1515554c0a3aSHans de Goede 		for (i = 0; i < left; i++) {
1516554c0a3aSHans de Goede 			cbc[i] ^= *pos++;
1517554c0a3aSHans de Goede 			if (pos >= end) {
1518554c0a3aSHans de Goede 				e++;
1519554c0a3aSHans de Goede 				pos = addr[e];
1520554c0a3aSHans de Goede 				end = pos + len[e];
1521554c0a3aSHans de Goede 			}
1522554c0a3aSHans de Goede 		}
1523554c0a3aSHans de Goede 		cbc[left] ^= 0x80;
1524554c0a3aSHans de Goede 		gf_mulx(pad);
1525554c0a3aSHans de Goede 	}
1526554c0a3aSHans de Goede 
1527554c0a3aSHans de Goede 	for (i = 0; i < AES_BLOCK_SIZE; i++)
1528554c0a3aSHans de Goede 		pad[i] ^= cbc[i];
15297d40753dSFabio Aiuto 	aes_encrypt(&ctx, pad, mac);
15307d40753dSFabio Aiuto 	memzero_explicit(&ctx, sizeof(ctx));
1531554c0a3aSHans de Goede 	return 0;
1532554c0a3aSHans de Goede }
1533554c0a3aSHans de Goede 
1534554c0a3aSHans de Goede /**
1535554c0a3aSHans de Goede  * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
1536554c0a3aSHans de Goede  * @key: 128-bit key for the hash operation
1537554c0a3aSHans de Goede  * @data: Data buffer for which a MAC is determined
1538554c0a3aSHans de Goede  * @data_len: Length of data buffer in bytes
1539554c0a3aSHans de Goede  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
1540554c0a3aSHans de Goede  * Returns: 0 on success, -1 on failure
1541554c0a3aSHans de Goede  *
1542554c0a3aSHans de Goede  * This is a mode for using block cipher (AES in this case) for authentication.
1543554c0a3aSHans de Goede  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
1544554c0a3aSHans de Goede  * (SP) 800-38B.
1545554c0a3aSHans de Goede  * modify for CONFIG_IEEE80211W */
omac1_aes_128(u8 * key,u8 * data,size_t data_len,u8 * mac)1546554c0a3aSHans de Goede int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
1547554c0a3aSHans de Goede {
1548554c0a3aSHans de Goede 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
1549554c0a3aSHans de Goede }
1550554c0a3aSHans de Goede 
1551554c0a3aSHans de Goede /* Restore HW wep key setting according to key_mask */
rtw_sec_restore_wep_key(struct adapter * adapter)1552554c0a3aSHans de Goede void rtw_sec_restore_wep_key(struct adapter *adapter)
1553554c0a3aSHans de Goede {
1554554c0a3aSHans de Goede 	struct security_priv *securitypriv = &(adapter->securitypriv);
1555d495c550SMarco Cesati 	signed int keyid;
1556554c0a3aSHans de Goede 
1557554c0a3aSHans de Goede 	if ((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) || (_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) {
1558554c0a3aSHans de Goede 		for (keyid = 0; keyid < 4; keyid++) {
1559554c0a3aSHans de Goede 			if (securitypriv->key_mask & BIT(keyid)) {
1560554c0a3aSHans de Goede 				if (keyid == securitypriv->dot11PrivacyKeyIndex)
1561554c0a3aSHans de Goede 					rtw_set_key(adapter, securitypriv, keyid, 1, false);
1562554c0a3aSHans de Goede 				else
1563554c0a3aSHans de Goede 					rtw_set_key(adapter, securitypriv, keyid, 0, false);
1564554c0a3aSHans de Goede 			}
1565554c0a3aSHans de Goede 		}
1566554c0a3aSHans de Goede 	}
1567554c0a3aSHans de Goede }
1568554c0a3aSHans de Goede 
rtw_handle_tkip_countermeasure(struct adapter * adapter,const char * caller)1569554c0a3aSHans de Goede u8 rtw_handle_tkip_countermeasure(struct adapter *adapter, const char *caller)
1570554c0a3aSHans de Goede {
1571554c0a3aSHans de Goede 	struct security_priv *securitypriv = &(adapter->securitypriv);
1572554c0a3aSHans de Goede 	u8 status = _SUCCESS;
1573554c0a3aSHans de Goede 
15743ac5add1SJohn Oldman 	if (securitypriv->btkip_countermeasure) {
1575554c0a3aSHans de Goede 		unsigned long passing_ms = jiffies_to_msecs(jiffies - securitypriv->btkip_countermeasure_time);
157622045712SRoss Schmidt 
1577554c0a3aSHans de Goede 		if (passing_ms > 60*1000) {
157879df841bSFabio Aiuto 			netdev_dbg(adapter->pnetdev,
157979df841bSFabio Aiuto 				   "%s(%s) countermeasure time:%lus > 60s\n",
158079df841bSFabio Aiuto 				   caller, ADPT_ARG(adapter),
158179df841bSFabio Aiuto 				   passing_ms / 1000);
1582554c0a3aSHans de Goede 			securitypriv->btkip_countermeasure = false;
1583554c0a3aSHans de Goede 			securitypriv->btkip_countermeasure_time = 0;
1584554c0a3aSHans de Goede 		} else {
158579df841bSFabio Aiuto 			netdev_dbg(adapter->pnetdev,
158679df841bSFabio Aiuto 				   "%s(%s) countermeasure time:%lus < 60s\n",
158779df841bSFabio Aiuto 				   caller, ADPT_ARG(adapter),
158879df841bSFabio Aiuto 				   passing_ms / 1000);
1589554c0a3aSHans de Goede 			status = _FAIL;
1590554c0a3aSHans de Goede 		}
1591554c0a3aSHans de Goede 	}
1592554c0a3aSHans de Goede 
1593554c0a3aSHans de Goede 	return status;
1594554c0a3aSHans de Goede }
1595