Linux 2.6.31-rc6
[linux-2.6] / drivers / staging / rt2860 / 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                                 )
222                 {
223                     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
224                     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
225                 }
226                 else
227                 {
228                     // 2. shared key, need to be challenged
229                     Seq++;
230                     RemoteStatus = MLME_SUCCESS;
231
232                                         // Get an unused nonpaged memory
233                     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
234                     if(NStatus != NDIS_STATUS_SUCCESS)
235                     {
236                         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq2Action() allocate memory fail\n"));
237                         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
238                         Status2 = MLME_FAIL_NO_RESOURCE;
239                         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status2);
240                         return;
241                     }
242
243                     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
244                     MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, pAd->MlmeAux.Bssid);
245                     AuthHdr.FC.Wep = 1;
246                     // Encrypt challenge text & auth information
247                     RTMPInitWepEngine(
248                         pAd,
249                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].Key,
250                         pAd->StaCfg.DefaultKeyId,
251                         pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].KeyLen,
252                         CyperChlgText);
253
254                                         Alg = cpu2le16(*(USHORT *)&Alg);
255                                         Seq = cpu2le16(*(USHORT *)&Seq);
256                                         RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
257
258                                         RTMPEncryptData(pAd, (PUCHAR) &Alg, CyperChlgText + 4, 2);
259                                         RTMPEncryptData(pAd, (PUCHAR) &Seq, CyperChlgText + 6, 2);
260                                         RTMPEncryptData(pAd, (PUCHAR) &RemoteStatus, CyperChlgText + 8, 2);
261                                         Element[0] = 16;
262                                         Element[1] = 128;
263                                         RTMPEncryptData(pAd, Element, CyperChlgText + 10, 2);
264                                         RTMPEncryptData(pAd, ChlgText, CyperChlgText + 12, 128);
265                                         RTMPSetICV(pAd, CyperChlgText + 140);
266                     MakeOutgoingFrame(pOutBuffer,               &FrameLen,
267                                       sizeof(HEADER_802_11),    &AuthHdr,
268                                       CIPHER_TEXT_LEN + 16,     CyperChlgText,
269                                       END_OF_ARGS);
270                     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
271                         MlmeFreeMemory(pAd, pOutBuffer);
272
273                     RTMPSetTimer(&pAd->MlmeAux.AuthTimer, AUTH_TIMEOUT);
274                     pAd->Mlme.AuthMachine.CurrState = AUTH_WAIT_SEQ4;
275                 }
276             }
277             else
278             {
279                 pAd->StaCfg.AuthFailReason = Status;
280                 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
281                 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
282                 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
283             }
284         }
285     }
286     else
287     {
288         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthSanity() sanity check fail\n"));
289     }
290 }
291
292 /*
293     ==========================================================================
294     Description:
295
296         IRQL = DISPATCH_LEVEL
297
298     ==========================================================================
299  */
300 VOID PeerAuthRspAtSeq4Action(
301     IN PRTMP_ADAPTER pAd,
302     IN MLME_QUEUE_ELEM *Elem)
303 {
304     UCHAR         Addr2[MAC_ADDR_LEN];
305     USHORT        Alg, Seq, Status;
306     CHAR          ChlgText[CIPHER_TEXT_LEN];
307     BOOLEAN       TimerCancelled;
308
309     if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
310     {
311         if(MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, Addr2) && Seq == 4)
312         {
313             DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Receive AUTH_RSP seq#4 to me\n"));
314             RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &TimerCancelled);
315
316             if (Status != MLME_SUCCESS)
317             {
318                 pAd->StaCfg.AuthFailReason = Status;
319                 COPY_MAC_ADDR(pAd->StaCfg.AuthFailSta, Addr2);
320             }
321
322             pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
323             MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
324         }
325     }
326     else
327     {
328         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - PeerAuthRspAtSeq4Action() sanity check fail\n"));
329     }
330 }
331
332 /*
333     ==========================================================================
334     Description:
335
336         IRQL = DISPATCH_LEVEL
337
338     ==========================================================================
339  */
340 VOID MlmeDeauthReqAction(
341     IN PRTMP_ADAPTER pAd,
342     IN MLME_QUEUE_ELEM *Elem)
343 {
344     MLME_DEAUTH_REQ_STRUCT *pInfo;
345     HEADER_802_11 DeauthHdr;
346     PUCHAR        pOutBuffer = NULL;
347     NDIS_STATUS   NStatus;
348     ULONG         FrameLen = 0;
349     USHORT        Status;
350
351     pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
352
353     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
354     if (NStatus != NDIS_STATUS_SUCCESS)
355     {
356         DBGPRINT(RT_DEBUG_TRACE, ("AUTH - MlmeDeauthReqAction() allocate memory fail\n"));
357         pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
358         Status = MLME_FAIL_NO_RESOURCE;
359         MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
360         return;
361     }
362
363     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pInfo->Reason));
364     MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, pAd->MlmeAux.Bssid);
365     MakeOutgoingFrame(pOutBuffer,           &FrameLen,
366                       sizeof(HEADER_802_11),&DeauthHdr,
367                       2,                    &pInfo->Reason,
368                       END_OF_ARGS);
369     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
370         MlmeFreeMemory(pAd, pOutBuffer);
371
372     pAd->StaCfg.DeauthReason = pInfo->Reason;
373     COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pInfo->Addr);
374     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
375     Status = MLME_SUCCESS;
376     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_DEAUTH_CONF, 2, &Status);
377
378         // send wireless event - for deauthentication
379         if (pAd->CommonCfg.bWirelessEvent)
380                 RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
381 }
382
383 /*
384     ==========================================================================
385     Description:
386
387         IRQL = DISPATCH_LEVEL
388
389     ==========================================================================
390  */
391 VOID AuthTimeoutAction(
392     IN PRTMP_ADAPTER pAd,
393     IN MLME_QUEUE_ELEM *Elem)
394 {
395     USHORT Status;
396     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - AuthTimeoutAction\n"));
397     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
398     Status = MLME_REJ_TIMEOUT;
399     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
400 }
401
402 /*
403     ==========================================================================
404     Description:
405
406         IRQL = DISPATCH_LEVEL
407
408     ==========================================================================
409  */
410 VOID InvalidStateWhenAuth(
411     IN PRTMP_ADAPTER pAd,
412     IN MLME_QUEUE_ELEM *Elem)
413 {
414     USHORT Status;
415     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", pAd->Mlme.AuthMachine.CurrState));
416     pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
417     Status = MLME_STATE_MACHINE_REJECT;
418     MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_AUTH_CONF, 2, &Status);
419 }
420
421 /*
422     ==========================================================================
423     Description:
424         Some STA/AP
425     Note:
426         This action should never trigger AUTH state transition, therefore we
427         separate it from AUTH state machine, and make it as a standalone service
428
429         IRQL = DISPATCH_LEVEL
430
431     ==========================================================================
432  */
433 VOID Cls2errAction(
434     IN PRTMP_ADAPTER pAd,
435     IN PUCHAR pAddr)
436 {
437     HEADER_802_11 DeauthHdr;
438     PUCHAR        pOutBuffer = NULL;
439     NDIS_STATUS   NStatus;
440     ULONG         FrameLen = 0;
441     USHORT        Reason = REASON_CLS2ERR;
442
443     NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);  //Get an unused nonpaged memory
444     if (NStatus != NDIS_STATUS_SUCCESS)
445         return;
446
447     DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Class 2 error, Send DEAUTH frame...\n"));
448     MgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pAddr, pAd->MlmeAux.Bssid);
449     MakeOutgoingFrame(pOutBuffer,           &FrameLen,
450                       sizeof(HEADER_802_11),&DeauthHdr,
451                       2,                    &Reason,
452                       END_OF_ARGS);
453     MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
454         MlmeFreeMemory(pAd, pOutBuffer);
455
456     pAd->StaCfg.DeauthReason = Reason;
457     COPY_MAC_ADDR(pAd->StaCfg.DeauthSta, pAddr);
458 }
459
460