]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt3090/sta/wpa.c
Staging: rt2860: add RT3090 chipset support
[net-next-2.6.git] / drivers / staging / rt3090 / sta / wpa.c
CommitLineData
36c7928c
BZ
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
39#include "../rt_config.h"
40
41
42void inc_byte_array(UCHAR *counter, int len);
43
44/*
45 ========================================================================
46
47 Routine Description:
48 Process MIC error indication and record MIC error timer.
49
50 Arguments:
51 pAd Pointer to our adapter
52 pWpaKey Pointer to the WPA key structure
53
54 Return Value:
55 None
56
57 IRQL = DISPATCH_LEVEL
58
59 Note:
60
61 ========================================================================
62*/
63VOID RTMPReportMicError(
64 IN PRTMP_ADAPTER pAd,
65 IN PCIPHER_KEY pWpaKey)
66{
67 ULONG Now;
68 UCHAR unicastKey = (pWpaKey->Type == PAIRWISE_KEY ? 1:0);
69
70 // Record Last MIC error time and count
71 NdisGetSystemUpTime(&Now);
72 if (pAd->StaCfg.MicErrCnt == 0)
73 {
74 pAd->StaCfg.MicErrCnt++;
75 pAd->StaCfg.LastMicErrorTime = Now;
76 NdisZeroMemory(pAd->StaCfg.ReplayCounter, 8);
77 }
78 else if (pAd->StaCfg.MicErrCnt == 1)
79 {
80 if ((pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ)) < Now)
81 {
82 // Update Last MIC error time, this did not violate two MIC errors within 60 seconds
83 pAd->StaCfg.LastMicErrorTime = Now;
84 }
85 else
86 {
87
88 if (pAd->CommonCfg.bWirelessEvent)
89 RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
90
91 pAd->StaCfg.LastMicErrorTime = Now;
92 // Violate MIC error counts, MIC countermeasures kicks in
93 pAd->StaCfg.MicErrCnt++;
94 // We shall block all reception
95 // We shall clean all Tx ring and disassoicate from AP after next EAPOL frame
96 //
97 // No necessary to clean all Tx ring, on RTMPHardTransmit will stop sending non-802.1X EAPOL packets
98 // if pAd->StaCfg.MicErrCnt greater than 2.
99 //
100 // RTMPRingCleanUp(pAd, QID_AC_BK);
101 // RTMPRingCleanUp(pAd, QID_AC_BE);
102 // RTMPRingCleanUp(pAd, QID_AC_VI);
103 // RTMPRingCleanUp(pAd, QID_AC_VO);
104 // RTMPRingCleanUp(pAd, QID_HCCA);
105 }
106 }
107 else
108 {
109 // MIC error count >= 2
110 // This should not happen
111 ;
112 }
113 MlmeEnqueue(pAd,
114 MLME_CNTL_STATE_MACHINE,
115 OID_802_11_MIC_FAILURE_REPORT_FRAME,
116 1,
117 &unicastKey);
118
119 if (pAd->StaCfg.MicErrCnt == 2)
120 {
121 RTMPSetTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, 100);
122 }
123}
124
125
126#ifdef WPA_SUPPLICANT_SUPPORT
127#define LENGTH_EAP_H 4
128// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
129INT WpaCheckEapCode(
130 IN PRTMP_ADAPTER pAd,
131 IN PUCHAR pFrame,
132 IN USHORT FrameLen,
133 IN USHORT OffSet)
134{
135
136 PUCHAR pData;
137 INT result = 0;
138
139 if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H )
140 return result;
141
142 pData = pFrame + OffSet; // skip offset bytes
143
144 if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type
145 {
146 result = *(pData+4); // EAP header - Code
147 }
148
149 return result;
150}
151
152VOID WpaSendMicFailureToWpaSupplicant(
153 IN PRTMP_ADAPTER pAd,
154 IN BOOLEAN bUnicast)
155{
156 char custom[IW_CUSTOM_MAX] = {0};
157
158 sprintf(custom, "MLME-MICHAELMICFAILURE.indication");
159 if(bUnicast)
160 sprintf(custom, "%s unicast", custom);
161
162 RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, -1, NULL, (PUCHAR)custom, strlen(custom));
163
164 return;
165}
166#endif // WPA_SUPPLICANT_SUPPORT //
167
168VOID WpaMicFailureReportFrame(
169 IN PRTMP_ADAPTER pAd,
170 IN MLME_QUEUE_ELEM *Elem)
171{
172 PUCHAR pOutBuffer = NULL;
173 UCHAR Header802_3[14];
174 ULONG FrameLen = 0;
175 EAPOL_PACKET Packet;
176 UCHAR Mic[16];
177 BOOLEAN bUnicast;
178
179 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame ----->\n"));
180
181 bUnicast = (Elem->Msg[0] == 1 ? TRUE:FALSE);
182 pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER);
183
184 // init 802.3 header and Fill Packet
185 MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
186
187 NdisZeroMemory(&Packet, sizeof(Packet));
188 Packet.ProVer = EAPOL_VER;
189 Packet.ProType = EAPOLKey;
190
191 Packet.KeyDesc.Type = WPA1_KEY_DESC;
192
193 // Request field presented
194 Packet.KeyDesc.KeyInfo.Request = 1;
195
196 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
197 {
198 Packet.KeyDesc.KeyInfo.KeyDescVer = 2;
199 }
200 else // TKIP
201 {
202 Packet.KeyDesc.KeyInfo.KeyDescVer = 1;
203 }
204
205 Packet.KeyDesc.KeyInfo.KeyType = (bUnicast ? PAIRWISEKEY : GROUPKEY);
206
207 // KeyMic field presented
208 Packet.KeyDesc.KeyInfo.KeyMic = 1;
209
210 // Error field presented
211 Packet.KeyDesc.KeyInfo.Error = 1;
212
213 // Update packet length after decide Key data payload
214 SET_UINT16_TO_ARRARY(Packet.Body_Len, LEN_EAPOL_KEY_MSG)
215
216 // Key Replay Count
217 NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY);
218 inc_byte_array(pAd->StaCfg.ReplayCounter, 8);
219
220 // Convert to little-endian format.
221 *((USHORT *)&Packet.KeyDesc.KeyInfo) = cpu2le16(*((USHORT *)&Packet.KeyDesc.KeyInfo));
222
223
224 MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); // allocate memory
225 if(pOutBuffer == NULL)
226 {
227 return;
228 }
229
230 // Prepare EAPOL frame for MIC calculation
231 // Be careful, only EAPOL frame is counted for MIC calculation
232 MakeOutgoingFrame(pOutBuffer, &FrameLen,
233 CONV_ARRARY_TO_UINT16(Packet.Body_Len) + 4, &Packet,
234 END_OF_ARGS);
235
236 // Prepare and Fill MIC value
237 NdisZeroMemory(Mic, sizeof(Mic));
238 if(pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
239 { // AES
240 UCHAR digest[20] = {0};
241 HMAC_SHA1(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
242 NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
243 }
244 else
245 { // TKIP
246 HMAC_MD5(pAd->StaCfg.PTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic, MD5_DIGEST_SIZE);
247 }
248 NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
249
250 // copy frame to Tx ring and send MIC failure report frame to authenticator
251 RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID],
252 Header802_3, LENGTH_802_3,
253 (PUCHAR)&Packet,
254 CONV_ARRARY_TO_UINT16(Packet.Body_Len) + 4, FALSE);
255
256 MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
257
258 DBGPRINT(RT_DEBUG_TRACE, ("WpaMicFailureReportFrame <-----\n"));
259}
260
261/** from wpa_supplicant
262 * inc_byte_array - Increment arbitrary length byte array by one
263 * @counter: Pointer to byte array
264 * @len: Length of the counter in bytes
265 *
266 * This function increments the last byte of the counter by one and continues
267 * rolling over to more significant bytes if the byte was incremented from
268 * 0xff to 0x00.
269 */
270void inc_byte_array(UCHAR *counter, int len)
271{
272 int pos = len - 1;
273 while (pos >= 0) {
274 counter[pos]++;
275 if (counter[pos] != 0)
276 break;
277 pos--;
278 }
279}
280
281VOID WpaDisassocApAndBlockAssoc(
282 IN PVOID SystemSpecific1,
283 IN PVOID FunctionContext,
284 IN PVOID SystemSpecific2,
285 IN PVOID SystemSpecific3)
286{
287 RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)FunctionContext;
288 MLME_DISASSOC_REQ_STRUCT DisassocReq;
289
290 // disassoc from current AP first
291 DBGPRINT(RT_DEBUG_TRACE, ("RTMPReportMicError - disassociate with current AP after sending second continuous EAPOL frame\n"));
292 DisassocParmFill(pAd, &DisassocReq, pAd->CommonCfg.Bssid, REASON_MIC_FAILURE);
293 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE, MT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq);
294
295 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
296 pAd->StaCfg.bBlockAssoc = TRUE;
297}
298
299VOID WpaStaPairwiseKeySetting(
300 IN PRTMP_ADAPTER pAd)
301{
302 PCIPHER_KEY pSharedKey;
303 PMAC_TABLE_ENTRY pEntry;
304
305 pEntry = &pAd->MacTab.Content[BSSID_WCID];
306
307 // Pairwise key shall use key#0
308 pSharedKey = &pAd->SharedKey[BSS0][0];
309
310 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
311
312 // Prepare pair-wise key information into shared key table
313 NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
314 pSharedKey->KeyLen = LEN_TKIP_EK;
315 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
316 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
317 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
318
319 // Decide its ChiperAlg
320 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
321 pSharedKey->CipherAlg = CIPHER_TKIP;
322 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
323 pSharedKey->CipherAlg = CIPHER_AES;
324 else
325 pSharedKey->CipherAlg = CIPHER_NONE;
326
327 // Update these related information to MAC_TABLE_ENTRY
328 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
329 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
330 NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
331 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
332
333 // Update pairwise key information to ASIC Shared Key Table
334 AsicAddSharedKeyEntry(pAd,
335 BSS0,
336 0,
337 pSharedKey->CipherAlg,
338 pSharedKey->Key,
339 pSharedKey->TxMic,
340 pSharedKey->RxMic);
341
342 // Update ASIC WCID attribute table and IVEIV table
343 RTMPAddWcidAttributeEntry(pAd,
344 BSS0,
345 0,
346 pSharedKey->CipherAlg,
347 pEntry);
348 STA_PORT_SECURED(pAd);
349 pAd->IndicateMediaState = NdisMediaStateConnected;
350
351 DBGPRINT(RT_DEBUG_TRACE, ("%s : AID(%d) port secured\n", __FUNCTION__, pEntry->Aid));
352
353}
354
355VOID WpaStaGroupKeySetting(
356 IN PRTMP_ADAPTER pAd)
357{
358 PCIPHER_KEY pSharedKey;
359
360 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
361
362 // Prepare pair-wise key information into shared key table
363 NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
364 pSharedKey->KeyLen = LEN_TKIP_EK;
365 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
366 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_RXMICK);
367 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_TXMICK);
368
369 // Update Shared Key CipherAlg
370 pSharedKey->CipherAlg = CIPHER_NONE;
371 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
372 pSharedKey->CipherAlg = CIPHER_TKIP;
373 else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
374 pSharedKey->CipherAlg = CIPHER_AES;
375 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
376 pSharedKey->CipherAlg = CIPHER_WEP64;
377 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
378 pSharedKey->CipherAlg = CIPHER_WEP128;
379
380 // Update group key information to ASIC Shared Key Table
381 AsicAddSharedKeyEntry(pAd,
382 BSS0,
383 pAd->StaCfg.DefaultKeyId,
384 pSharedKey->CipherAlg,
385 pSharedKey->Key,
386 pSharedKey->TxMic,
387 pSharedKey->RxMic);
388
389 // Update ASIC WCID attribute table and IVEIV table
390 RTMPAddWcidAttributeEntry(pAd,
391 BSS0,
392 pAd->StaCfg.DefaultKeyId,
393 pSharedKey->CipherAlg,
394 NULL);
395
396}