Merge branch 'for-next' of git://git.o-hand.com/linux-mfd
[linux-2.6] / drivers / staging / rt3070 / sta / auth.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         auth.c
29
30         Abstract:
31
32         Revision History:
33         Who                     When                    What
34         --------        ----------              ----------------------------------------------
35         John            2004-9-3                porting from RT2500
36 */
37 #include "../rt_config.h"
38
39 /*
40     ==========================================================================
41     Description:
42         authenticate state machine init, including state transition and timer init
43     Parameters:
44         Sm - pointer to the auth state machine
45     Note:
46         The state machine looks like this
47
48                         AUTH_REQ_IDLE           AUTH_WAIT_SEQ2                   AUTH_WAIT_SEQ4
49     MT2_MLME_AUTH_REQ   mlme_auth_req_action    invalid_state_when_auth          invalid_state_when_auth
50     MT2_PEER_AUTH_EVEN  drop                    peer_auth_even_at_seq2_action    peer_auth_even_at_seq4_action
51     MT2_AUTH_TIMEOUT    Drop                    auth_timeout_action              auth_timeout_action
52
53         IRQL = PASSIVE_LEVEL
54
55     ==========================================================================
56  */
57
58 void AuthStateMachineInit(
59     IN PRTMP_ADAPTER pAd,
60     IN STATE_MACHINE *Sm,
61     OUT STATE_MACHINE_FUNC Trans[])
62 {
63     StateMachineInit(Sm, Trans, MAX_AUTH_STATE, MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop, AUTH_REQ_IDLE, AUTH_MACHINE_BASE);
64
65     // the first column
66     StateMachineSetAction(Sm, AUTH_REQ_IDLE, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)MlmeAuthReqAction);
67
68     // the second column
69     StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
70     StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq2Action);
71     StateMachineSetAction(Sm, AUTH_WAIT_SEQ2, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
72
73     // the third column
74     StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)InvalidStateWhenAuth);
75     StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)PeerAuthRspAtSeq4Action);
76     StateMachineSetAction(Sm, AUTH_WAIT_SEQ4, MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)AuthTimeoutAction);
77
78         RTMPInitTimer(pAd, &pAd->MlmeAux.AuthTimer, GET_TIMER_FUNCTION(AuthTimeout), pAd, FALSE);
79 }
80
81 /*
82     ==========================================================================
83     Description:
84         function to be executed at timer thread when auth timer expires
85
86         IRQL = DISPATCH_LEVEL
87
88     ==========================================================================
89  */
90 VOID AuthTimeout(
91     IN PVOID SystemSpecific1,
92     IN PVOID FunctionContext,
93     IN PVOID SystemSpecific2,
94     IN PVOID SystemSpecific3)
95 {
96     RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
97
98     DBGPRINT(RT_DEBUG_TRACE,("AUTH - AuthTimeout\n"));
99
100         // Do nothing if the driver is starting halt state.
101         // This might happen when timer already been fired before cancel timer with mlmehalt
102         if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
103                 return;
104
105         // send a de-auth to reset AP's state machine (Patch AP-Dir635)
106         if (pAd->Mlme.AuthMachine.CurrState == AUTH_WAIT_SEQ2)
107                 Cls2errAction(pAd, pAd->MlmeAux.Bssid);
108
109
110     MlmeEnqueue(pAd, AUTH_STATE_MACHINE, MT2_AUTH_TIMEOUT, 0, NULL);
111     RT28XX_MLME_HANDLER(pAd);
112 }
113
114
115 /*
116     ==========================================================================
117     Description:
118
119         IRQL = DISPATCH_LEVEL
120
121     ==========================================================================
122  */
123 VOID MlmeAuthReqAction(
124     IN PRTMP_ADAPTER pAd,
125     IN MLME_QUEUE_ELEM *Elem)
126 {
127     UCHAR              Addr[6];
128     USHORT             Alg, Seq, Status;
129     ULONG              Timeout;
130     HEADER_802_11      AuthHdr;
131     BOOLEAN            TimerCancelled;
132     NDIS_STATUS        NStatus;
133     PUCHAR             pOutBuffer = NULL;
134     ULONG              FrameLen = 0;
135
136         // Block all authentication request durning WPA block period
137         if (pAd->StaCfg.bBlockAssoc == TRUE)
138         {
139         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Block Auth request durning WPA block period!\n"));
140         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
141         Status = MLME_STATE_MACHINE_REJECT;
142         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
143         }
144     else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
145     {
146         // reset timer
147         RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
148         COPY_MAC_ADDR(pAd->MlmeAux.Bssid, Addr);
149         pAd->MlmeAux.Alg  = Alg;
150         Seq = 1;
151         Status = MLME_SUCCESS;
152
153         NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
154         if(NStatus != NDIS_STATUS_SUCCESS)
155         {
156             DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeAuthReqAction(Alg:%d) allocate memory failed\n", Alg));
157             pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
158             Status = MLME_FAIL_NO_RESOURCE;
159             MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
160             return;
161         }
162
163         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
164         MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->MlmeAux.Bssid);
165         MakeOutgoingFrame(pOutBuffer,           &FrameLen,
166                           sizeof(HEADER_802_11),&AuthHdr,
167                           2,                    &Alg,
168                           2,                    &Seq,
169                           2,                    &Status,
170                           END_OF_ARGS);
171         MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
172         MlmeFreeMemory(pAd, pOutBuffer);
173
174         RTMPSetTimer(&pAd->MlmeAux.AuthTimer, Timeout);
175         pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ2;
176     }
177     else
178     {
179         DBGPRINT_ERR(("AUTH - MlmeAuthReqAction() sanity check failed\n"));
180         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
181         Status = MLME_INVALID_FORMAT;
182         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
183     }
184 }
185
186 /*
187     ==========================================================================
188     Description:
189
190         IRQL = DISPATCH_LEVEL
191
192     ==========================================================================
193  */
194 VOID PeerAuthRspAtSeq2Action(
195     IN PRTMP_ADAPTER pAd,
196     IN MLME_QUEUE_ELEM *Elem)
197 {
198     UCHAR         Addr2[MAC_ADDR_LEN];
199     USHORT        Seq, Status, RemoteStatus, Alg;
200     UCHAR         ChlgText[CIPHER_TEXT_LEN];
201     UCHAR         CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
202     UCHAR         Element[2];
203     HEADER_802_11 AuthHdr;
204     BOOLEAN       TimerCancelled;
205     PUCHAR        pOutBuffer = NULL;
206     NDIS_STATUS   NStatus;
207     ULONG         FrameLen = 0;
208     USHORT        Status2;
209
210     if (PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
211     {
212         if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 2)
213         {
214             DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
215             RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
216
217             if (Status == MLME_SUCCESS)
218             {
219                 // Authentication Mode "LEAP" has allow for CCX 1.X
220                 if ((pAd->MlmeAux.Alg == Ndis802_11AuthModeOpen)
221 #ifdef LEAP_SUPPORT
222                                         || (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
223 #endif // LEAP_SUPPORT //
224                                 )
225                 {
226                     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
227 #ifdef LEAP_SUPPORT
228                     pAd->Mlme.LeapMachine.CurrState = LEAP_IDLE;
229 #endif // LEAP_SUPPORT //
230                     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
231                 }
232                 else
233                 {
234                     // 2. shared key, need to be challenged
235                     Seq++;
236                     RemoteStatus = MLME_SUCCESS;
237
238                                         // Get an unused nonpaged memory
239                     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
240                     if(NStatus != NDIS_STATUS_SUCCESS)
241                     {
242                         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
243                         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
244                         Status2 = MLME_FAIL_NO_RESOURCE;
245                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
246                         return;
247                     }
248
249                     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
250                     MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
251                     AuthHdr.FC.Wep = 1;
252                     // Encrypt challenge text & auth information
253                     RTMPInitWepEngine(
254                         pAd,
255                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
256                         pAd->StaCfg.DefaultKeyId,
257                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
258                         CyperChlgText);
259
260                                         Alg = cpu2le16(*(USHORT *)&Alg);
261                                         Seq = cpu2le16(*(USHORT *)&Seq);
262                                         RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
263
264                                         RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
265                                         RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
266                                         RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
267                                         Element[0] = 16;
268                                         Element[1] = 128;
269                                         RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
270                                         RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
271                                         RTMPSetICV(pAd, CyperChlgText + 140);
272                     MakeOutgoingFrame(pOutBuffer,               &FrameLen,
273                                       sizeof(HEADER_802_11),    &AuthHdr,
274                                       CIPHER_TEXT_LEN + 16,     CyperChlgText,
275                                       END_OF_ARGS);
276                     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
277                         MlmeFreeMemory(pAd, pOutBuffer);
278
279                     RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
280                     pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
281                 }
282             }
283             else
284             {
285 #ifdef LEAP_SUPPORT
286                 if (pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP)
287                 {
288                     //Invalid Authentication possible rogue AP
289                     //Add this Ap to Rogue AP.
290                     RogueApTableSetEntry(pAd, &pAd->StaCfg.RogueApTab, Addr2, LEAP_REASON_INVALID_AUTH);
291                                 }
292 #endif // LEAP_SUPPORT //
293                 pAd->StaCfg.AuthFailReason = Status;
294                 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
295                 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
296                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
297             }
298         }
299     }
300     else
301     {
302         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
303     }
304 }
305
306 /*
307     ==========================================================================
308     Description:
309
310         IRQL = DISPATCH_LEVEL
311
312     ==========================================================================
313  */
314 VOID PeerAuthRspAtSeq4Action(
315     IN PRTMP_ADAPTER pAd,
316     IN MLME_QUEUE_ELEM *Elem)
317 {
318     UCHAR         Addr2[MAC_ADDR_LEN];
319     USHORT        Alg, Seq, Status;
320     CHAR          ChlgText[CIPHER_TEXT_LEN];
321     BOOLEAN       TimerCancelled;
322
323     if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
324     {
325         if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
326         {
327             DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
328             RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
329
330             if (Status != MLME_SUCCESS)
331             {
332                 pAd->StaCfg.AuthFailReason = Status;
333                 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
334             }
335
336             pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
337             MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
338         }
339     }
340     else
341     {
342         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
343     }
344 }
345
346 /*
347     ==========================================================================
348     Description:
349
350         IRQL = DISPATCH_LEVEL
351
352     ==========================================================================
353  */
354 VOID MlmeDeauthReqAction(
355     IN PRTMP_ADAPTER pAd,
356     IN MLME_QUEUE_ELEM *Elem)
357 {
358     MLME_DEAUTH_REQ_STRUCT *pInfo;
359     HEADER_802_11 DeauthHdr;
360     PUCHAR        pOutBuffer = NULL;
361     NDIS_STATUS   NStatus;
362     ULONG         FrameLen = 0;
363     USHORT        Status;
364
365     pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
366
367     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
368     if (NStatus != NDIS_STATUS_SUCCESS)
369     {
370         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
371         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
372         Status = MLME_FAIL_NO_RESOURCE;
373         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
374         return;
375     }
376
377
378     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
379     MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
380     MakeOutgoingFrame(pOutBuffer,           &FrameLen,
381                       sizeof(HEADER_802_11),&DeauthHdr,
382                       2,                    &pInfo->Reason,
383                       END_OF_ARGS);
384     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
385         MlmeFreeMemory(pAd, pOutBuffer);
386
387     pAd->StaCfg.DeauthReason = pInfo->Reason;
388     COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
389     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
390     Status = MLME_SUCCESS;
391     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
392
393         // send wireless event - for deauthentication
394         if (pAd->CommonCfg.bWirelessEvent)
395                 RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
396 }
397
398 /*
399     ==========================================================================
400     Description:
401
402         IRQL = DISPATCH_LEVEL
403
404     ==========================================================================
405  */
406 VOID AuthTimeoutAction(
407     IN PRTMP_ADAPTER pAd,
408     IN MLME_QUEUE_ELEM *Elem)
409 {
410     USHORT Status;
411     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
412     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
413     Status = MLME_REJ_TIMEOUT;
414     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
415 }
416
417 /*
418     ==========================================================================
419     Description:
420
421         IRQL = DISPATCH_LEVEL
422
423     ==========================================================================
424  */
425 VOID InvalidStateWhenAuth(
426     IN PRTMP_ADAPTER pAd,
427     IN MLME_QUEUE_ELEM *Elem)
428 {
429     USHORT Status;
430     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
431     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
432     Status = MLME_STATE_MACHINE_REJECT;
433     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
434 }
435
436 /*
437     ==========================================================================
438     Description:
439         Some STA/AP
440     Note:
441         This action should never trigger AUTH state transition, therefore we
442         separate it from AUTH state machine, and make it as a standalone service
443
444         IRQL = DISPATCH_LEVEL
445
446     ==========================================================================
447  */
448 VOID Cls2errAction(
449     IN PRTMP_ADAPTER pAd,
450     IN PUCHAR pAddr)
451 {
452     HEADER_802_11 DeauthHdr;
453     PUCHAR        pOutBuffer = NULL;
454     NDIS_STATUS   NStatus;
455     ULONG         FrameLen = 0;
456     USHORT        Reason = REASON_CLS2ERR;
457
458     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
459     if (NStatus != NDIS_STATUS_SUCCESS)
460         return;
461
462     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
463     MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
464     MakeOutgoingFrame(pOutBuffer,           &FrameLen,
465                       sizeof(HEADER_802_11),&DeauthHdr,
466                       2,                    &Reason,
467                       END_OF_ARGS);
468     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
469         MlmeFreeMemory(pAd, pOutBuffer);
470
471     pAd->StaCfg.DeauthReason = Reason;
472     COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
473 }
474
475