• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rt2860/sta/
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify  *
11 * it under the terms of the GNU General Public License as published by  *
12 * the Free Software Foundation; either version 2 of the License, or     *
13 * (at your option) any later version.                                   *
14 *                                                                       *
15 * This program is distributed in the hope that it will be useful,       *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
18 * GNU General Public License for more details.                          *
19 *                                                                       *
20 * You should have received a copy of the GNU General Public License     *
21 * along with this program; if not, write to the                         *
22 * Free Software Foundation, Inc.,                                       *
23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
24 *                                                                       *
25 *************************************************************************
26
27	Module Name:
28	wpa.c
29
30	Abstract:
31
32	Revision History:
33	Who			When			What
34	--------	----------		----------------------------------------------
35	Jan	Lee		03-07-22		Initial
36	Paul Lin	03-11-28		Modify for supplicant
37*/
38#include "../rt_config.h"
39
40void inc_byte_array(u8 * counter, int len);
41
42/*
43	========================================================================
44
45	Routine Description:
46		Process MIC error indication and record MIC error timer.
47
48	Arguments:
49		pAd 	Pointer to our adapter
50		pWpaKey 		Pointer to the WPA key structure
51
52	Return Value:
53		None
54
55	IRQL = DISPATCH_LEVEL
56
57	Note:
58
59	========================================================================
60*/
61void RTMPReportMicError(struct rt_rtmp_adapter *pAd, struct rt_cipher_key *pWpaKey)
62{
63	unsigned long Now;
64	u8 unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1 : 0);
65
66	/* Record Last MIC error time and count */
67	NdisGetSystemUpTime(&Now);
68	if (pAd->StaCfg.MicErrCnt == 0) {
69		pAd->StaCfg.MicErrCnt++;
70		pAd->StaCfg.LastMicErrorTime = Now;
71		NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
72	} else if (pAd->StaCfg.MicErrCnt == 1) {
73		if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now) {
74			/* Update Last MIC error time, this did not violate two MIC errors within 60 seconds */
75			pAd->StaCfg.LastMicErrorTime = Now;
76		} else {
77
78			if (pAd->CommonCfg.bWirelessEvent)
79				RTMPSendWirelessEvent(pAd,
80						      IW_COUNTER_MEASURES_EVENT_FLAG,
81						      pAd->MacTab.
82						      Content[BSSID_WCID].Addr,
83						      BSS0, 0);
84
85			pAd->StaCfg.LastMicErrorTime = Now;
86			/* Violate MIC error counts, MIC countermeasures kicks in */
87			pAd->StaCfg.MicErrCnt++;
88			/* We shall block all reception */
89			/* We shall clean all Tx ring and disassoicate from AP after next EAPOL frame */
90			/* */
91			/* No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets */
92			/* if pAd->StaCfg.MicErrCnt greater than 2. */
93			/* */
94			/* RTMPRingCleanUp(pAd, QID_AC_BK); */
95			/* RTMPRingCleanUp(pAd, QID_AC_BE); */
96			/* RTMPRingCleanUp(pAd, QID_AC_VI); */
97			/* RTMPRingCleanUp(pAd, QID_AC_VO); */
98			/* RTMPRingCleanUp(pAd, QID_HCCA); */
99		}
100	} else {
101		/* MIC error count >= 2 */
102		/* This should not happen */
103		;
104	}
105	MlmeEnqueue(pAd,
106		    MLME_CNTL_STATE_MACHINE,
107		    OID_802_11_MIC_FAILURE_REPORT_FRAME, 1, &unicastKey);
108
109	if (pAd->StaCfg.MicErrCnt == 2) {
110		RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
111	}
112}
113
114#define	LENGTH_EAP_H    4
115/* If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)). */
116int WpaCheckEapCode(struct rt_rtmp_adapter *pAd,
117		    u8 *pFrame, u16 FrameLen, u16 OffSet)
118{
119
120	u8 *pData;
121	int result = 0;
122
123	if (FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H)
124		return result;
125
126	pData = pFrame + OffSet;	/* skip offset bytes */
127
128	if (*(pData + 1) == EAPPacket)	/* 802.1x header - Packet Type */
129	{
130		result = *(pData + 4);	/* EAP header - Code */
131	}
132
133	return result;
134}
135
136void WpaSendMicFailureToWpaSupplicant(struct rt_rtmp_adapter *pAd, IN BOOLEAN bUnicast)
137{
138	char custom[IW_CUSTOM_MAX] = { 0 };
139
140	sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
141	if (bUnicast)
142		sprintf(custom, "%s unicast", custom);
143
144	RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (u8 *)custom,
145				strlen(custom));
146
147	return;
148}
149
150void WpaMicFailureReportFrame(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
151{
152	u8 *pOutBuffer = NULL;
153	u8 Header802_3[14];
154	unsigned long FrameLen = 0;
155	struct rt_eapol_packet Packet;
156	u8 Mic[16];
157	BOOLEAN bUnicast;
158
159	DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
160
161	bUnicast = (Elem->Msg[0] == 1 ? TRUE : FALSE);
162	pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
163
164	/* init 802.3 header and Fill Packet */
165	MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid,
166			  pAd->CurrentAddress, EAPOL);
167
168	NdisZeroMemory(&Packet, sizeof(Packet));
169	Packet.ProVer = EAPOL_VER;
170	Packet.ProType = EAPOLKey;
171
172	Packet.KeyDesc.Type = WPA1_KEY_DESC;
173
174	/* Request field presented */
175	Packet.KeyDesc.KeyInfo.Request = 1;
176
177	if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) {
178		Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
179	} else			/* TKIP */
180	{
181		Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
182	}
183
184	Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
185
186	/* KeyMic field presented */
187	Packet.KeyDesc.KeyInfo.KeyMic = 1;
188
189	/* Error field presented */
190	Packet.KeyDesc.KeyInfo.Error = 1;
191
192	/* Update packet length after decide Key data payload */
193	SET_u16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG)
194	    /* Key Replay Count */
195	    NdisMoveMemory(Packet.KeyDesc.ReplayCounter,
196			   pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
197	inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
198
199	/* Convert to little-endian format. */
200	*((u16 *) & Packet.KeyDesc.KeyInfo) =
201	    cpu2le16(*((u16 *) & Packet.KeyDesc.KeyInfo));
202
203	MlmeAllocateMemory(pAd, (u8 **) & pOutBuffer);	/* allocate memory */
204	if (pOutBuffer == NULL) {
205		return;
206	}
207	/* Prepare EAPOL frame for MIC calculation */
208	/* Be careful, only EAPOL frame is counted for MIC calculation */
209	MakeOutgoingFrame(pOutBuffer, &FrameLen,
210			  CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, &Packet,
211			  END_OF_ARGS);
212
213	/* Prepare and Fill MIC value */
214	NdisZeroMemory(Mic, sizeof(Mic));
215	if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled) {	/* AES */
216		u8 digest[20] = { 0 };
217		HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
218			  digest, SHA1_DIGEST_SIZE);
219		NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
220	} else {		/* TKIP */
221		HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen,
222			 Mic, MD5_DIGEST_SIZE);
223	}
224	NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
225
226	/* copy frame to Tx ring and send MIC failure report frame to authenticator */
227	RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID],
228			  Header802_3, LENGTH_802_3,
229			  (u8 *)& Packet,
230			  CONV_ARRARY_TO_u16(Packet.Body_Len) + 4, FALSE);
231
232	MlmeFreeMemory(pAd, (u8 *)pOutBuffer);
233
234	DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
235}
236
237/** from wpa_supplicant
238 * inc_byte_array - Increment arbitrary length byte array by one
239 * @counter: Pointer to byte array
240 * @len: Length of the counter in bytes
241 *
242 * This function increments the last byte of the counter by one and continues
243 * rolling over to more significant bytes if the byte was incremented from
244 * 0xff to 0x00.
245 */
246void inc_byte_array(u8 * counter, int len)
247{
248	int pos = len - 1;
249	while (pos >= 0) {
250		counter[pos]++;
251		if (counter[pos] != 0)
252			break;
253		pos--;
254	}
255}
256
257void WpaDisassocApAndBlockAssoc(void *SystemSpecific1,
258				void *FunctionContext,
259				void *SystemSpecific2,
260				void *SystemSpecific3)
261{
262	struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
263	struct rt_mlme_disassoc_req DisassocReq;
264
265	/* disassoc from current AP first */
266	DBGPRINT(RT_DEBUG_TRACE,
267		 ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
268	DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid,
269			 REASON_MIC_FAILURE);
270	MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ,
271		    sizeof(struct rt_mlme_disassoc_req), &DisassocReq);
272
273	pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
274	pAd->StaCfg.bBlockAssoc = TRUE;
275}
276
277void WpaStaPairwiseKeySetting(struct rt_rtmp_adapter *pAd)
278{
279	struct rt_cipher_key *pSharedKey;
280	struct rt_mac_table_entry *pEntry;
281
282	pEntry = &pAd->MacTab.Content[BSSID_WCID];
283
284	/* Pairwise key shall use key#0 */
285	pSharedKey = &pAd->SharedKey[BSS0][0];
286
287	NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
288
289	/* Prepare pair-wise key information into shared key table */
290	NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
291	pSharedKey->KeyLen = LEN_TKIP_EK;
292	NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
293	NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
294		       LEN_TKIP_RXMICK);
295	NdisMoveMemory(pSharedKey->TxMic,
296		       &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
297
298	/* Decide its ChiperAlg */
299	if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
300		pSharedKey->CipherAlg = CIPHER_TKIP;
301	else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
302		pSharedKey->CipherAlg = CIPHER_AES;
303	else
304		pSharedKey->CipherAlg = CIPHER_NONE;
305
306	/* Update these related information to struct rt_mac_table_entry */
307	NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
308		       LEN_TKIP_EK);
309	NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
310		       LEN_TKIP_RXMICK);
311	NdisMoveMemory(pEntry->PairwiseKey.TxMic,
312		       &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
313	pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
314
315	/* Update pairwise key information to ASIC Shared Key Table */
316	AsicAddSharedKeyEntry(pAd,
317			      BSS0,
318			      0,
319			      pSharedKey->CipherAlg,
320			      pSharedKey->Key,
321			      pSharedKey->TxMic, pSharedKey->RxMic);
322
323	/* Update ASIC WCID attribute table and IVEIV table */
324	RTMPAddWcidAttributeEntry(pAd, BSS0, 0, pSharedKey->CipherAlg, pEntry);
325	STA_PORT_SECURED(pAd);
326	pAd->IndicateMediaState = NdisMediaStateConnected;
327
328	DBGPRINT(RT_DEBUG_TRACE,
329		 ("%s : AID(%d) port secured\n", __func__, pEntry->Aid));
330
331}
332
333void WpaStaGroupKeySetting(struct rt_rtmp_adapter *pAd)
334{
335	struct rt_cipher_key *pSharedKey;
336
337	pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
338
339	/* Prepare pair-wise key information into shared key table */
340	NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
341	pSharedKey->KeyLen = LEN_TKIP_EK;
342	NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
343	NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
344		       LEN_TKIP_RXMICK);
345	NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
346		       LEN_TKIP_TXMICK);
347
348	/* Update Shared Key CipherAlg */
349	pSharedKey->CipherAlg = CIPHER_NONE;
350	if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
351		pSharedKey->CipherAlg = CIPHER_TKIP;
352	else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
353		pSharedKey->CipherAlg = CIPHER_AES;
354	else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
355		pSharedKey->CipherAlg = CIPHER_WEP64;
356	else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
357		pSharedKey->CipherAlg = CIPHER_WEP128;
358
359	/* Update group key information to ASIC Shared Key Table */
360	AsicAddSharedKeyEntry(pAd,
361			      BSS0,
362			      pAd->StaCfg.DefaultKeyId,
363			      pSharedKey->CipherAlg,
364			      pSharedKey->Key,
365			      pSharedKey->TxMic, pSharedKey->RxMic);
366
367	/* Update ASIC WCID attribute table and IVEIV table */
368	RTMPAddWcidAttributeEntry(pAd,
369				  BSS0,
370				  pAd->StaCfg.DefaultKeyId,
371				  pSharedKey->CipherAlg, NULL);
372
373}
374