]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rt3090/sta/wpa.c
2dbdba541c3f25a7d1d44ebbdd65855f0fd50622
[net-next-2.6.git] / drivers / staging / rt3090 / sta / wpa.c
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
42 void 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 */
63 VOID    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)).
129 INT         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
152 VOID    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
168 VOID    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  */
270 void 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
281 VOID 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
299 VOID 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
355 VOID 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 }