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