Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
[pandora-kernel.git] / drivers / staging / rt2860 / common / cmm_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 #include "../rt_config.h"
39 /* WPA OUI */
40 u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 };
41 u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 };
42 u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 };
43 u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 };
44 u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 };
45 u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 };
46 u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 };
47 u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 };
48
49 /* WPA2 OUI */
50 u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
51 u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
52 u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
53 u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 };
54 u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 };
55 u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
56
57 static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
58                                   u8 GroupKeyWepStatus,
59                                   u8 keyDescVer,
60                                   u8 MsgType,
61                                   u8 DefaultKeyIdx,
62                                   u8 * GTK,
63                                   u8 * RSNIE,
64                                   u8 RSNIE_LEN, struct rt_eapol_packet * pMsg);
65
66 static void CalculateMIC(u8 KeyDescVer,
67                          u8 * PTK, struct rt_eapol_packet * pMsg);
68
69 static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
70
71 static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd,
72                                    struct rt_mlme_queue_elem *Elem);
73
74 static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd,
75                                  struct rt_mlme_queue_elem *Elem);
76
77 static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd,
78                                 struct rt_mlme_queue_elem *Elem);
79
80 static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
81
82 /*
83     ==========================================================================
84     Description:
85         association state machine init, including state transition and timer init
86     Parameters:
87         S - pointer to the association state machine
88     ==========================================================================
89  */
90 void WpaStateMachineInit(struct rt_rtmp_adapter *pAd,
91                          struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
92 {
93         StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE,
94                          MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK,
95                          WPA_MACHINE_BASE);
96
97         StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket,
98                               (STATE_MACHINE_FUNC) WpaEAPPacketAction);
99         StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart,
100                               (STATE_MACHINE_FUNC) WpaEAPOLStartAction);
101         StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff,
102                               (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction);
103         StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey,
104                               (STATE_MACHINE_FUNC) WpaEAPOLKeyAction);
105         StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert,
106                               (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction);
107 }
108
109 /*
110     ==========================================================================
111     Description:
112         this is state machine function.
113         When receiving EAP packets which is  for 802.1x authentication use.
114         Not use in PSK case
115     Return:
116     ==========================================================================
117 */
118 void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
119 {
120 }
121
122 void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
123 {
124 }
125
126 void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
127 {
128 }
129
130 /*
131     ==========================================================================
132     Description:
133        Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
134     Return:
135     ==========================================================================
136 */
137 void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
138 {
139         struct rt_mac_table_entry *pEntry;
140         struct rt_header_802_11 * pHeader;
141
142         DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
143
144         pHeader = (struct rt_header_802_11 *) Elem->Msg;
145
146         /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */
147         if (Elem->MsgLen == 6)
148                 pEntry = MacTableLookup(pAd, Elem->Msg);
149         else {
150                 pEntry = MacTableLookup(pAd, pHeader->Addr2);
151         }
152
153         if (pEntry) {
154                 DBGPRINT(RT_DEBUG_TRACE,
155                          (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n",
156                           pEntry->PortSecured, pEntry->WpaState,
157                           pEntry->AuthMode, pEntry->PMKID_CacheIdx));
158
159                 if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
160                     && (pEntry->WpaState < AS_PTKSTART)
161                     && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
162                         || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
163                         || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
164                             && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) {
165                         pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
166                         pEntry->WpaState = AS_INITPSK;
167                         pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
168                         NdisZeroMemory(pEntry->R_Counter,
169                                        sizeof(pEntry->R_Counter));
170                         pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
171
172                         WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
173                 }
174         }
175 }
176
177 /*
178     ==========================================================================
179     Description:
180         This is state machine function.
181         When receiving EAPOL packets which is  for 802.1x key management.
182         Use both in WPA, and WPAPSK case.
183         In this function, further dispatch to different functions according to the received packet.  3 categories are :
184           1.  normal 4-way pairwisekey and 2-way groupkey handshake
185           2.  MIC error (Countermeasures attack)  report packet from STA.
186           3.  Request for pairwise/group key update from STA
187     Return:
188     ==========================================================================
189 */
190 void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
191 {
192         struct rt_mac_table_entry *pEntry;
193         struct rt_header_802_11 * pHeader;
194         struct rt_eapol_packet * pEapol_packet;
195         struct rt_key_info peerKeyInfo;
196
197         DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
198
199         pHeader = (struct rt_header_802_11 *) Elem->Msg;
200         pEapol_packet =
201             (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
202
203         NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo));
204         NdisMoveMemory((u8 *)& peerKeyInfo,
205                        (u8 *)& pEapol_packet->KeyDesc.KeyInfo,
206                        sizeof(struct rt_key_info));
207
208         hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet,
209                  (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
210
211         *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo));
212
213         do {
214                 pEntry = MacTableLookup(pAd, pHeader->Addr2);
215
216                 if (!pEntry
217                     || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
218                         break;
219
220                 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
221                         break;
222
223                 DBGPRINT(RT_DEBUG_TRACE,
224                         ("Receive EAPoL-Key frame from STA %pMF\n",
225                                 pEntry->Addr));
226
227                 if (((pEapol_packet->ProVer != EAPOL_VER)
228                      && (pEapol_packet->ProVer != EAPOL_VER2))
229                     || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC)
230                         && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) {
231                         DBGPRINT(RT_DEBUG_ERROR,
232                                  ("Key descripter does not match with WPA rule\n"));
233                         break;
234                 }
235                 /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */
236                 /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */
237                 if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled)
238                     && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) {
239                         DBGPRINT(RT_DEBUG_ERROR,
240                                  ("Key descripter version not match(TKIP) \n"));
241                         break;
242                 }
243                 /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */
244                 /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */
245                 else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
246                          && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) {
247                         DBGPRINT(RT_DEBUG_ERROR,
248                                  ("Key descripter version not match(AES) \n"));
249                         break;
250                 }
251                 /* Check if this STA is in class 3 state and the WPA state is started */
252                 if ((pEntry->Sst == SST_ASSOC)
253                     && (pEntry->WpaState >= AS_INITPSK)) {
254                         /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */
255                         /* or not. */
256                         /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */
257                         /* Key frame from the Authenticator must not have the Ack bit set. */
258                         if (peerKeyInfo.KeyAck == 1) {
259                                 /* The frame is snet by Authenticator. */
260                                 /* So the Supplicant side shall handle this. */
261
262                                 if ((peerKeyInfo.Secure == 0)
263                                     && (peerKeyInfo.Request == 0)
264                                     && (peerKeyInfo.Error == 0)
265                                     && (peerKeyInfo.KeyType == PAIRWISEKEY)) {
266                                         /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */
267                                         /*                        EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
268                                         /*                 2. the message 3 of 4-way HS in WPA */
269                                         /*                        EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
270                                         if (peerKeyInfo.KeyMic == 0)
271                                                 PeerPairMsg1Action(pAd, pEntry,
272                                                                    Elem);
273                                         else
274                                                 PeerPairMsg3Action(pAd, pEntry,
275                                                                    Elem);
276                                 } else if ((peerKeyInfo.Secure == 1)
277                                            && (peerKeyInfo.KeyMic == 1)
278                                            && (peerKeyInfo.Request == 0)
279                                            && (peerKeyInfo.Error == 0)) {
280                                         /* Process 1. the message 3 of 4-way HS in WPA2 */
281                                         /*                        EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
282                                         /*                 2. the message 1 of group KS in WPA or WPA2 */
283                                         /*                        EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */
284                                         if (peerKeyInfo.KeyType == PAIRWISEKEY)
285                                                 PeerPairMsg3Action(pAd, pEntry,
286                                                                    Elem);
287                                         else
288                                                 PeerGroupMsg1Action(pAd, pEntry,
289                                                                     Elem);
290                                 }
291                         } else {
292                                 /* The frame is snet by Supplicant. */
293                                 /* So the Authenticator side shall handle this. */
294                                 if ((peerKeyInfo.Request == 0) &&
295                                     (peerKeyInfo.Error == 0) &&
296                                     (peerKeyInfo.KeyMic == 1)) {
297                                         if (peerKeyInfo.Secure == 0
298                                             && peerKeyInfo.KeyType ==
299                                             PAIRWISEKEY) {
300                                                 /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */
301                                                 /* Process 1. message 2 of 4-way HS in WPA or WPA2 */
302                                                 /*                 2. message 4 of 4-way HS in WPA */
303                                                 if (CONV_ARRARY_TO_u16
304                                                     (pEapol_packet->KeyDesc.
305                                                      KeyDataLen) == 0) {
306                                                         PeerPairMsg4Action(pAd,
307                                                                            pEntry,
308                                                                            Elem);
309                                                 } else {
310                                                         PeerPairMsg2Action(pAd,
311                                                                            pEntry,
312                                                                            Elem);
313                                                 }
314                                         } else if (peerKeyInfo.Secure == 1
315                                                    && peerKeyInfo.KeyType ==
316                                                    PAIRWISEKEY) {
317                                                 /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
318                                                 /* Process message 4 of 4-way HS in WPA2 */
319                                                 PeerPairMsg4Action(pAd, pEntry,
320                                                                    Elem);
321                                         } else if (peerKeyInfo.Secure == 1
322                                                    && peerKeyInfo.KeyType ==
323                                                    GROUPKEY) {
324                                                 /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */
325                                                 /* Process message 2 of Group key HS in WPA or WPA2 */
326                                                 PeerGroupMsg2Action(pAd, pEntry,
327                                                                     &Elem->
328                                                                     Msg
329                                                                     [LENGTH_802_11],
330                                                                     (Elem->
331                                                                      MsgLen -
332                                                                      LENGTH_802_11));
333                                         }
334                                 }
335                         }
336                 }
337         } while (FALSE);
338 }
339
340 /*
341         ========================================================================
342
343         Routine Description:
344                 Copy frame from waiting queue into relative ring buffer and set
345         appropriate ASIC register to kick hardware encryption before really
346         sent out to air.
347
348         Arguments:
349                 pAd             Pointer to our adapter
350                 void *  Pointer to outgoing Ndis frame
351                 NumberOfFrag    Number of fragment required
352
353         Return Value:
354                 None
355
356         Note:
357
358         ========================================================================
359 */
360 void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd,
361                        struct rt_mac_table_entry *pEntry,
362                        u8 *pHeader802_3,
363                        u32 HdrLen,
364                        u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame)
365 {
366         void *pPacket;
367         int Status;
368
369         if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
370                 return;
371
372         do {
373                 /* build a NDIS packet */
374                 Status =
375                     RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen,
376                                            pData, DataLen);
377                 if (Status != NDIS_STATUS_SUCCESS)
378                         break;
379
380                 if (bClearFrame)
381                         RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
382                 else
383                         RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
384                 {
385                         RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
386
387                         RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID);        /* set a default value */
388                         if (pEntry->apidx != 0)
389                                 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket,
390                                                                   pEntry->
391                                                                   apidx);
392
393                         RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
394                         RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
395                 }
396
397                 {
398                         /* send out the packet */
399                         Status = STASendPacket(pAd, pPacket);
400                         if (Status == NDIS_STATUS_SUCCESS) {
401                                 u8 Index;
402
403                                 /* Dequeue one frame from TxSwQueue0..3 queue and process it */
404                                 /* There are three place calling dequeue for TX ring. */
405                                 /* 1. Here, right after queueing the frame. */
406                                 /* 2. At the end of TxRingTxDone service routine. */
407                                 /* 3. Upon NDIS call RTMPSendPackets */
408                                 if ((!RTMP_TEST_FLAG
409                                      (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
410                                     &&
411                                     (!RTMP_TEST_FLAG
412                                      (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) {
413                                         for (Index = 0; Index < 5; Index++)
414                                                 if (pAd->TxSwQueue[Index].
415                                                     Number > 0)
416                                                         RTMPDeQueuePacket(pAd,
417                                                                           FALSE,
418                                                                           Index,
419                                                                           MAX_TX_PROCESS);
420                                 }
421                         }
422                 }
423
424         } while (FALSE);
425 }
426
427 /*
428     ==========================================================================
429     Description:
430         This is a function to initialize 4-way handshake
431
432     Return:
433
434     ==========================================================================
435 */
436 void WPAStart4WayHS(struct rt_rtmp_adapter *pAd,
437                     struct rt_mac_table_entry *pEntry, unsigned long TimeInterval)
438 {
439         u8 Header802_3[14];
440         struct rt_eapol_packet EAPOLPKT;
441         u8 *pBssid = NULL;
442         u8 group_cipher = Ndis802_11WEPDisabled;
443
444         DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
445
446         if (RTMP_TEST_FLAG
447             (pAd,
448              fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
449         {
450                 DBGPRINT(RT_DEBUG_ERROR,
451                          ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
452                 return;
453         }
454
455         if (pBssid == NULL) {
456                 DBGPRINT(RT_DEBUG_ERROR,
457                          ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
458                 return;
459         }
460         /* Check the status */
461         if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) {
462                 DBGPRINT(RT_DEBUG_ERROR,
463                          ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
464                 return;
465         }
466
467         /* Increment replay counter by 1 */
468         ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
469
470         /* Randomly generate ANonce */
471         GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce);
472
473         /* Construct EAPoL message - Pairwise Msg 1 */
474         /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
475         NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
476         ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0,    /* Default key index */
477                           pEntry->ANonce, NULL, /* TxRSC */
478                           NULL, /* GTK */
479                           NULL, /* RSNIE */
480                           0,    /* RSNIE length */
481                           &EAPOLPKT);
482
483         /* Make outgoing frame */
484         MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
485         RTMPToWirelessSta(pAd, pEntry, Header802_3,
486                           LENGTH_802_3, (u8 *)& EAPOLPKT,
487                           CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
488                           (pEntry->PortSecured ==
489                            WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
490
491         /* Trigger Retry Timer */
492         RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
493
494         /* Update State */
495         pEntry->WpaState = AS_PTKSTART;
496
497         DBGPRINT(RT_DEBUG_TRACE,
498                  ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
499
500 }
501
502 /*
503         ========================================================================
504
505         Routine Description:
506                 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
507
508         Arguments:
509                 pAd                     Pointer to our adapter
510                 Elem            Message body
511
512         Return Value:
513                 None
514
515         Note:
516
517         ========================================================================
518 */
519 void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd,
520                         struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
521 {
522         u8 PTK[80];
523         u8 Header802_3[14];
524         struct rt_eapol_packet * pMsg1;
525         u32 MsgLen;
526         struct rt_eapol_packet EAPOLPKT;
527         u8 *pCurrentAddr = NULL;
528         u8 *pmk_ptr = NULL;
529         u8 group_cipher = Ndis802_11WEPDisabled;
530         u8 *rsnie_ptr = NULL;
531         u8 rsnie_len = 0;
532
533         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
534
535         if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
536                 return;
537
538         if (Elem->MsgLen <
539             (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
540              sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
541                 return;
542
543         {
544                 pCurrentAddr = pAd->CurrentAddress;
545                 pmk_ptr = pAd->StaCfg.PMK;
546                 group_cipher = pAd->StaCfg.GroupCipher;
547                 rsnie_ptr = pAd->StaCfg.RSN_IE;
548                 rsnie_len = pAd->StaCfg.RSNIE_Len;
549         }
550
551         /* Store the received frame */
552         pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
553         MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
554
555         /* Sanity Check peer Pairwise message 1 - Replay Counter */
556         if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry)
557             == FALSE)
558                 return;
559
560         /* Store Replay counter, it will use to verify message 3 and construct message 2 */
561         NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter,
562                        LEN_KEY_DESC_REPLAY);
563
564         /* Store ANonce */
565         NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce,
566                        LEN_KEY_DESC_NONCE);
567
568         /* Generate random SNonce */
569         GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce);
570
571         {
572                 /* Calculate PTK(ANonce, SNonce) */
573                 WpaDerivePTK(pAd,
574                              pmk_ptr,
575                              pEntry->ANonce,
576                              pEntry->Addr,
577                              pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK);
578
579                 /* Save key to PTK entry */
580                 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
581         }
582
583         /* Update WpaState */
584         pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
585
586         /* Construct EAPoL message - Pairwise Msg 2 */
587         /*  EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
588         NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
589         ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0,    /* DefaultKeyIdx */
590                           pEntry->SNonce, NULL, /* TxRsc */
591                           NULL, /* GTK */
592                           (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
593
594         /* Make outgoing frame */
595         MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
596
597         RTMPToWirelessSta(pAd, pEntry,
598                           Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT,
599                           CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
600
601         DBGPRINT(RT_DEBUG_TRACE,
602                  ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
603 }
604
605 /*
606     ==========================================================================
607     Description:
608         When receiving the second packet of 4-way pairwisekey handshake.
609     Return:
610     ==========================================================================
611 */
612 void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd,
613                         struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
614 {
615         u8 PTK[80];
616         BOOLEAN Cancelled;
617         struct rt_header_802_11 * pHeader;
618         struct rt_eapol_packet EAPOLPKT;
619         struct rt_eapol_packet * pMsg2;
620         u32 MsgLen;
621         u8 Header802_3[LENGTH_802_3];
622         u8 TxTsc[6];
623         u8 *pBssid = NULL;
624         u8 *pmk_ptr = NULL;
625         u8 *gtk_ptr = NULL;
626         u8 default_key = 0;
627         u8 group_cipher = Ndis802_11WEPDisabled;
628         u8 *rsnie_ptr = NULL;
629         u8 rsnie_len = 0;
630
631         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
632
633         if ((!pEntry) || (!pEntry->ValidAsCLI))
634                 return;
635
636         if (Elem->MsgLen <
637             (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
638              sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
639                 return;
640
641         /* check Entry in valid State */
642         if (pEntry->WpaState < AS_PTKSTART)
643                 return;
644
645         /* pointer to 802.11 header */
646         pHeader = (struct rt_header_802_11 *) Elem->Msg;
647
648         /* skip 802.11_header(24-byte) and LLC_header(8) */
649         pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
650         MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
651
652         /* Store SNonce */
653         NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce,
654                        LEN_KEY_DESC_NONCE);
655
656         {
657                 /* Derive PTK */
658                 WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce,       /* ANONCE */
659                              (u8 *) pBssid, pEntry->SNonce,     /* SNONCE */
660                              pEntry->Addr, PTK, LEN_PTK);
661
662                 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
663         }
664
665         /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
666         if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry)
667             == FALSE)
668                 return;
669
670         do {
671                 /* delete retry timer */
672                 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
673
674                 /* Change state */
675                 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
676
677                 /* Increment replay counter by 1 */
678                 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
679
680                 /* Construct EAPoL message - Pairwise Msg 3 */
681                 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
682                 ConstructEapolMsg(pEntry,
683                                   group_cipher,
684                                   EAPOL_PAIR_MSG_3,
685                                   default_key,
686                                   pEntry->ANonce,
687                                   TxTsc,
688                                   (u8 *) gtk_ptr,
689                                   (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
690
691                 /* Make outgoing frame */
692                 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
693                 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
694                                   (u8 *)& EAPOLPKT,
695                                   CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
696                                   (pEntry->PortSecured ==
697                                    WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
698
699                 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
700                 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
701
702                 /* Update State */
703                 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
704         } while (FALSE);
705
706         DBGPRINT(RT_DEBUG_TRACE,
707                  ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
708 }
709
710 /*
711         ========================================================================
712
713         Routine Description:
714                 Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
715
716         Arguments:
717                 pAd     Pointer to our adapter
718                 Elem            Message body
719
720         Return Value:
721                 None
722
723         Note:
724
725         ========================================================================
726 */
727 void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd,
728                         struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
729 {
730         struct rt_header_802_11 * pHeader;
731         u8 Header802_3[14];
732         struct rt_eapol_packet EAPOLPKT;
733         struct rt_eapol_packet * pMsg3;
734         u32 MsgLen;
735         u8 *pCurrentAddr = NULL;
736         u8 group_cipher = Ndis802_11WEPDisabled;
737
738         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
739
740         if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
741                 return;
742
743         if (Elem->MsgLen <
744             (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
745              sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
746                 return;
747
748         {
749                 pCurrentAddr = pAd->CurrentAddress;
750                 group_cipher = pAd->StaCfg.GroupCipher;
751
752         }
753
754         /* Record 802.11 header & the received EAPOL packet Msg3 */
755         pHeader = (struct rt_header_802_11 *) Elem->Msg;
756         pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
757         MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
758
759         /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */
760         if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry)
761             == FALSE)
762                 return;
763
764         /* Save Replay counter, it will use construct message 4 */
765         NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter,
766                        LEN_KEY_DESC_REPLAY);
767
768         /* Double check ANonce */
769         if (!NdisEqualMemory
770             (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) {
771                 return;
772         }
773         /* Construct EAPoL message - Pairwise Msg 4 */
774         NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
775         ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0,    /* group key index not used in message 4 */
776                           NULL, /* Nonce not used in message 4 */
777                           NULL, /* TxRSC not used in message 4 */
778                           NULL, /* GTK not used in message 4 */
779                           NULL, /* RSN IE not used in message 4 */
780                           0, &EAPOLPKT);
781
782         /* Update WpaState */
783         pEntry->WpaState = AS_PTKINITDONE;
784
785         /* Update pairwise key */
786         {
787                 struct rt_cipher_key *pSharedKey;
788
789                 pSharedKey = &pAd->SharedKey[BSS0][0];
790
791                 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
792
793                 /* Prepare pair-wise key information into shared key table */
794                 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
795                 pSharedKey->KeyLen = LEN_TKIP_EK;
796                 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32],
797                                LEN_TKIP_EK);
798                 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
799                                LEN_TKIP_RXMICK);
800                 NdisMoveMemory(pSharedKey->TxMic,
801                                &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
802                                LEN_TKIP_TXMICK);
803
804                 /* Decide its ChiperAlg */
805                 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
806                         pSharedKey->CipherAlg = CIPHER_TKIP;
807                 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
808                         pSharedKey->CipherAlg = CIPHER_AES;
809                 else
810                         pSharedKey->CipherAlg = CIPHER_NONE;
811
812                 /* Update these related information to struct rt_mac_table_entry */
813                 pEntry = &pAd->MacTab.Content[BSSID_WCID];
814                 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
815                                LEN_TKIP_EK);
816                 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
817                                LEN_TKIP_RXMICK);
818                 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
819                                &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
820                                LEN_TKIP_TXMICK);
821                 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
822
823                 /* Update pairwise key information to ASIC Shared Key Table */
824                 AsicAddSharedKeyEntry(pAd,
825                                       BSS0,
826                                       0,
827                                       pSharedKey->CipherAlg,
828                                       pSharedKey->Key,
829                                       pSharedKey->TxMic, pSharedKey->RxMic);
830
831                 /* Update ASIC WCID attribute table and IVEIV table */
832                 RTMPAddWcidAttributeEntry(pAd,
833                                           BSS0,
834                                           0, pSharedKey->CipherAlg, pEntry);
835
836         }
837
838         /* open 802.1x port control and privacy filter */
839         if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
840             pEntry->AuthMode == Ndis802_11AuthModeWPA2) {
841                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
842                 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
843
844                 STA_PORT_SECURED(pAd);
845                 /* Indicate Connected for GUI */
846                 pAd->IndicateMediaState = NdisMediaStateConnected;
847                 DBGPRINT(RT_DEBUG_TRACE,
848                          ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
849                           GetAuthMode(pEntry->AuthMode),
850                           GetEncryptType(pEntry->WepStatus),
851                           GetEncryptType(group_cipher)));
852         } else {
853         }
854
855         /* Init 802.3 header and send out */
856         MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
857         RTMPToWirelessSta(pAd, pEntry,
858                           Header802_3, sizeof(Header802_3),
859                           (u8 *)& EAPOLPKT,
860                           CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
861
862         DBGPRINT(RT_DEBUG_TRACE,
863                  ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
864 }
865
866 /*
867     ==========================================================================
868     Description:
869         When receiving the last packet of 4-way pairwisekey handshake.
870         Initialize 2-way groupkey handshake following.
871     Return:
872     ==========================================================================
873 */
874 void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd,
875                         struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
876 {
877         struct rt_eapol_packet * pMsg4;
878         struct rt_header_802_11 * pHeader;
879         u32 MsgLen;
880         BOOLEAN Cancelled;
881         u8 group_cipher = Ndis802_11WEPDisabled;
882
883         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
884
885         do {
886                 if ((!pEntry) || (!pEntry->ValidAsCLI))
887                         break;
888
889                 if (Elem->MsgLen <
890                     (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
891                      sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
892                         break;
893
894                 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
895                         break;
896
897                 /* pointer to 802.11 header */
898                 pHeader = (struct rt_header_802_11 *) Elem->Msg;
899
900                 /* skip 802.11_header(24-byte) and LLC_header(8) */
901                 pMsg4 =
902                     (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
903                 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
904
905                 /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */
906                 if (PeerWpaMessageSanity
907                     (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
908                         break;
909
910                 /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */
911                 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key));
912
913                 /* reset IVEIV in Asic */
914                 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
915
916                 pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
917                 NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32],
918                                LEN_TKIP_EK);
919                 NdisMoveMemory(pEntry->PairwiseKey.RxMic,
920                                &pEntry->PTK[TKIP_AP_RXMICK_OFFSET],
921                                LEN_TKIP_RXMICK);
922                 NdisMoveMemory(pEntry->PairwiseKey.TxMic,
923                                &pEntry->PTK[TKIP_AP_TXMICK_OFFSET],
924                                LEN_TKIP_TXMICK);
925
926                 /* Set pairwise key to Asic */
927                 {
928                         pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
929                         if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
930                                 pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
931                         else if (pEntry->WepStatus ==
932                                  Ndis802_11Encryption3Enabled)
933                                 pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
934
935                         /* Add Pair-wise key to Asic */
936                         AsicAddPairwiseKeyEntry(pAd,
937                                                 pEntry->Addr,
938                                                 (u8)pEntry->Aid,
939                                                 &pEntry->PairwiseKey);
940
941                         /* update WCID attribute table and IVEIV table for this entry */
942                         RTMPAddWcidAttributeEntry(pAd,
943                                                   pEntry->apidx,
944                                                   0,
945                                                   pEntry->PairwiseKey.CipherAlg,
946                                                   pEntry);
947                 }
948
949                 /* 4. upgrade state */
950                 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
951                 pEntry->WpaState = AS_PTKINITDONE;
952                 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
953
954                 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
955                     pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) {
956                         pEntry->GTKState = REKEY_ESTABLISHED;
957                         RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
958
959                         /* send wireless event - for set key done WPA2 */
960                         if (pAd->CommonCfg.bWirelessEvent)
961                                 RTMPSendWirelessEvent(pAd,
962                                                       IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
963                                                       pEntry->Addr,
964                                                       pEntry->apidx, 0);
965
966                         DBGPRINT(RT_DEBUG_OFF,
967                                  ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
968                                   pEntry->AuthMode,
969                                   GetAuthMode(pEntry->AuthMode),
970                                   pEntry->WepStatus,
971                                   GetEncryptType(pEntry->WepStatus),
972                                   group_cipher, GetEncryptType(group_cipher)));
973                 } else {
974                         /* 5. init Group 2-way handshake if necessary. */
975                         WPAStart2WayGroupHS(pAd, pEntry);
976
977                         pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
978                         RTMPModTimer(&pEntry->RetryTimer,
979                                      PEER_MSG3_RETRY_EXEC_INTV);
980                 }
981         } while (FALSE);
982
983 }
984
985 /*
986     ==========================================================================
987     Description:
988         This is a function to send the first packet of 2-way groupkey handshake
989     Return:
990
991     ==========================================================================
992 */
993 void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
994 {
995         u8 Header802_3[14];
996         u8 TxTsc[6];
997         struct rt_eapol_packet EAPOLPKT;
998         u8 group_cipher = Ndis802_11WEPDisabled;
999         u8 default_key = 0;
1000         u8 *gnonce_ptr = NULL;
1001         u8 *gtk_ptr = NULL;
1002         u8 *pBssid = NULL;
1003
1004         DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1005
1006         if ((!pEntry) || (!pEntry->ValidAsCLI))
1007                 return;
1008
1009         do {
1010                 /* Increment replay counter by 1 */
1011                 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1012
1013                 /* Construct EAPoL message - Group Msg 1 */
1014                 NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
1015                 ConstructEapolMsg(pEntry,
1016                                   group_cipher,
1017                                   EAPOL_GROUP_MSG_1,
1018                                   default_key,
1019                                   (u8 *) gnonce_ptr,
1020                                   TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT);
1021
1022                 /* Make outgoing frame */
1023                 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1024                 RTMPToWirelessSta(pAd, pEntry,
1025                                   Header802_3, LENGTH_802_3,
1026                                   (u8 *)& EAPOLPKT,
1027                                   CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
1028                                   FALSE);
1029
1030         } while (FALSE);
1031
1032         DBGPRINT(RT_DEBUG_TRACE,
1033                  ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
1034
1035         return;
1036 }
1037
1038 /*
1039         ========================================================================
1040
1041         Routine Description:
1042                 Process Group key 2-way handshaking
1043
1044         Arguments:
1045                 pAd     Pointer to our adapter
1046                 Elem            Message body
1047
1048         Return Value:
1049                 None
1050
1051         Note:
1052
1053         ========================================================================
1054 */
1055 void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd,
1056                          struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
1057 {
1058         u8 Header802_3[14];
1059         struct rt_eapol_packet EAPOLPKT;
1060         struct rt_eapol_packet * pGroup;
1061         u32 MsgLen;
1062         BOOLEAN Cancelled;
1063         u8 default_key = 0;
1064         u8 group_cipher = Ndis802_11WEPDisabled;
1065         u8 *pCurrentAddr = NULL;
1066
1067         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1068
1069         if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
1070                 return;
1071
1072         {
1073                 pCurrentAddr = pAd->CurrentAddress;
1074                 group_cipher = pAd->StaCfg.GroupCipher;
1075                 default_key = pAd->StaCfg.DefaultKeyId;
1076         }
1077
1078         /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */
1079         pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1080         MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1081
1082         /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */
1083         if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry)
1084             == FALSE)
1085                 return;
1086
1087         /* delete retry timer */
1088         RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1089
1090         /* Save Replay counter, it will use to construct message 2 */
1091         NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter,
1092                        LEN_KEY_DESC_REPLAY);
1093
1094         /* Construct EAPoL message - Group Msg 2 */
1095         NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
1096         ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL,   /* Nonce not used */
1097                           NULL, /* TxRSC not used */
1098                           NULL, /* GTK not used */
1099                           NULL, /* RSN IE not used */
1100                           0, &EAPOLPKT);
1101
1102         /* open 802.1x port control and privacy filter */
1103         pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1104         pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1105
1106         STA_PORT_SECURED(pAd);
1107         /* Indicate Connected for GUI */
1108         pAd->IndicateMediaState = NdisMediaStateConnected;
1109
1110         DBGPRINT(RT_DEBUG_TRACE,
1111                  ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
1112                   GetAuthMode(pEntry->AuthMode),
1113                   GetEncryptType(pEntry->WepStatus),
1114                   GetEncryptType(group_cipher)));
1115
1116         /* init header and Fill Packet and send Msg 2 to authenticator */
1117         MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1118         RTMPToWirelessSta(pAd, pEntry,
1119                           Header802_3, sizeof(Header802_3),
1120                           (u8 *)& EAPOLPKT,
1121                           CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE);
1122
1123         DBGPRINT(RT_DEBUG_TRACE,
1124                  ("<=== PeerGroupMsg1Action: sned group message 2\n"));
1125 }
1126
1127 /*
1128     ==========================================================================
1129     Description:
1130         When receiving the last packet of 2-way groupkey handshake.
1131     Return:
1132     ==========================================================================
1133 */
1134 void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd,
1135                          struct rt_mac_table_entry *pEntry,
1136                          void * Msg, u32 MsgLen)
1137 {
1138         u32 Len;
1139         u8 *pData;
1140         BOOLEAN Cancelled;
1141         struct rt_eapol_packet * pMsg2;
1142         u8 group_cipher = Ndis802_11WEPDisabled;
1143
1144         DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1145
1146         do {
1147                 if ((!pEntry) || (!pEntry->ValidAsCLI))
1148                         break;
1149
1150                 if (MsgLen <
1151                     (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) -
1152                      MAX_LEN_OF_RSNIE - 2))
1153                         break;
1154
1155                 if (pEntry->WpaState != AS_PTKINITDONE)
1156                         break;
1157
1158                 pData = (u8 *)Msg;
1159                 pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H);
1160                 Len = MsgLen - LENGTH_802_1_H;
1161
1162                 /* Sanity Check peer group message 2 - Replay Counter, MIC */
1163                 if (PeerWpaMessageSanity
1164                     (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1165                         break;
1166
1167                 /* 3.  upgrade state */
1168
1169                 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1170                 pEntry->GTKState = REKEY_ESTABLISHED;
1171
1172                 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
1173                     || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
1174                         /* send wireless event - for set key done WPA2 */
1175                         if (pAd->CommonCfg.bWirelessEvent)
1176                                 RTMPSendWirelessEvent(pAd,
1177                                                       IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
1178                                                       pEntry->Addr,
1179                                                       pEntry->apidx, 0);
1180
1181                         DBGPRINT(RT_DEBUG_OFF,
1182                                  ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1183                                   pEntry->AuthMode,
1184                                   GetAuthMode(pEntry->AuthMode),
1185                                   pEntry->WepStatus,
1186                                   GetEncryptType(pEntry->WepStatus),
1187                                   group_cipher, GetEncryptType(group_cipher)));
1188                 } else {
1189                         /* send wireless event - for set key done WPA */
1190                         if (pAd->CommonCfg.bWirelessEvent)
1191                                 RTMPSendWirelessEvent(pAd,
1192                                                       IW_SET_KEY_DONE_WPA1_EVENT_FLAG,
1193                                                       pEntry->Addr,
1194                                                       pEntry->apidx, 0);
1195
1196                         DBGPRINT(RT_DEBUG_OFF,
1197                                  ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1198                                   pEntry->AuthMode,
1199                                   GetAuthMode(pEntry->AuthMode),
1200                                   pEntry->WepStatus,
1201                                   GetEncryptType(pEntry->WepStatus),
1202                                   group_cipher, GetEncryptType(group_cipher)));
1203                 }
1204         } while (FALSE);
1205 }
1206
1207 /*
1208         ========================================================================
1209
1210         Routine Description:
1211                 Classify WPA EAP message type
1212
1213         Arguments:
1214                 EAPType         Value of EAP message type
1215                 MsgType         Internal Message definition for MLME state machine
1216
1217         Return Value:
1218                 TRUE            Found appropriate message type
1219                 FALSE           No appropriate message type
1220
1221         IRQL = DISPATCH_LEVEL
1222
1223         Note:
1224                 All these constants are defined in wpa.h
1225                 For supplicant, there is only EAPOL Key message avaliable
1226
1227         ========================================================================
1228 */
1229 BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType)
1230 {
1231         switch (EAPType) {
1232         case EAPPacket:
1233                 *MsgType = MT2_EAPPacket;
1234                 break;
1235         case EAPOLStart:
1236                 *MsgType = MT2_EAPOLStart;
1237                 break;
1238         case EAPOLLogoff:
1239                 *MsgType = MT2_EAPOLLogoff;
1240                 break;
1241         case EAPOLKey:
1242                 *MsgType = MT2_EAPOLKey;
1243                 break;
1244         case EAPOLASFAlert:
1245                 *MsgType = MT2_EAPOLASFAlert;
1246                 break;
1247         default:
1248                 return FALSE;
1249         }
1250         return TRUE;
1251 }
1252
1253 /*
1254         ========================================================================
1255
1256         Routine Description:
1257                 The pseudo-random function(PRF) that hashes various inputs to
1258                 derive a pseudo-random value. To add liveness to the pseudo-random
1259                 value, a nonce should be one of the inputs.
1260
1261                 It is used to generate PTK, GTK or some specific random value.
1262
1263         Arguments:
1264                 u8      *key,           -       the key material for HMAC_SHA1 use
1265                 int             key_len         -       the length of key
1266                 u8      *prefix         -       a prefix label
1267                 int             prefix_len      -       the length of the label
1268                 u8      *data           -       a specific data with variable length
1269                 int             data_len        -       the length of a specific data
1270                 int             len                     -       the output lenght
1271
1272         Return Value:
1273                 u8      *output         -       the calculated result
1274
1275         Note:
1276                 802.11i-2004    Annex H.3
1277
1278         ========================================================================
1279 */
1280 void PRF(u8 * key,
1281          int key_len,
1282          u8 * prefix,
1283          int prefix_len,
1284          u8 * data, int data_len, u8 * output, int len)
1285 {
1286         int i;
1287         u8 *input;
1288         int currentindex = 0;
1289         int total_len;
1290
1291         /* Allocate memory for input */
1292         os_alloc_mem(NULL, (u8 **) & input, 1024);
1293
1294         if (input == NULL) {
1295                 DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n"));
1296                 return;
1297         }
1298         /* Generate concatenation input */
1299         NdisMoveMemory(input, prefix, prefix_len);
1300
1301         /* Concatenate a single octet containing 0 */
1302         input[prefix_len] = 0;
1303
1304         /* Concatenate specific data */
1305         NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1306         total_len = prefix_len + 1 + data_len;
1307
1308         /* Concatenate a single octet containing 0 */
1309         /* This octet shall be update later */
1310         input[total_len] = 0;
1311         total_len++;
1312
1313         /* Iterate to calculate the result by hmac-sha-1 */
1314         /* Then concatenate to last result */
1315         for (i = 0; i < (len + 19) / 20; i++) {
1316                 HMAC_SHA1(key, key_len, input, total_len, &output[currentindex],
1317                           SHA1_DIGEST_SIZE);
1318                 currentindex += 20;
1319
1320                 /* update the last octet */
1321                 input[total_len - 1]++;
1322         }
1323         os_free_mem(NULL, input);
1324 }
1325
1326 /*
1327 * F(P, S, c, i) = U1 xor U2 xor ... Uc
1328 * U1 = PRF(P, S || Int(i))
1329 * U2 = PRF(P, U1)
1330 * Uc = PRF(P, Uc-1)
1331 */
1332
1333 static void F(char *password, unsigned char *ssid, int ssidlength,
1334               int iterations, int count, unsigned char *output)
1335 {
1336         unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
1337         int i, j;
1338
1339         /* U1 = PRF(P, S || int(i)) */
1340         memcpy(digest, ssid, ssidlength);
1341         digest[ssidlength] = (unsigned char)((count >> 24) & 0xff);
1342         digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff);
1343         digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff);
1344         digest[ssidlength + 3] = (unsigned char)(count & 0xff);
1345         HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */
1346
1347         /* output = U1 */
1348         memcpy(output, digest1, SHA1_DIGEST_SIZE);
1349
1350         for (i = 1; i < iterations; i++) {
1351                 /* Un = PRF(P, Un-1) */
1352                 HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE);       /* for WPA update */
1353                 memcpy(digest1, digest, SHA1_DIGEST_SIZE);
1354
1355                 /* output = output xor Un */
1356                 for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
1357                         output[j] ^= digest[j];
1358                 }
1359         }
1360 }
1361
1362 /*
1363 * password - ascii string up to 63 characters in length
1364 * ssid - octet string up to 32 octets
1365 * ssidlength - length of ssid in octets
1366 * output must be 40 octets in length and outputs 256 bits of key
1367 */
1368 int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output)
1369 {
1370         if ((strlen(password) > 63) || (ssidlength > 32))
1371                 return 0;
1372
1373         F(password, ssid, ssidlength, 4096, 1, output);
1374         F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1375         return 1;
1376 }
1377
1378 /*
1379         ========================================================================
1380
1381         Routine Description:
1382                 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
1383                 It shall be called by 4-way handshake processing.
1384
1385         Arguments:
1386                 pAd     -       pointer to our pAdapter context
1387                 PMK             -       pointer to PMK
1388                 ANonce  -       pointer to ANonce
1389                 AA              -       pointer to Authenticator Address
1390                 SNonce  -       pointer to SNonce
1391                 SA              -       pointer to Supplicant Address
1392                 len             -       indicate the length of PTK (octet)
1393
1394         Return Value:
1395                 Output          pointer to the PTK
1396
1397         Note:
1398                 Refer to IEEE 802.11i-2004 8.5.1.2
1399
1400         ========================================================================
1401 */
1402 void WpaDerivePTK(struct rt_rtmp_adapter *pAd,
1403                   u8 * PMK,
1404                   u8 * ANonce,
1405                   u8 * AA,
1406                   u8 * SNonce,
1407                   u8 * SA, u8 * output, u32 len)
1408 {
1409         u8 concatenation[76];
1410         u32 CurrPos = 0;
1411         u8 temp[32];
1412         u8 Prefix[] =
1413             { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1414                 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'
1415         };
1416
1417         /* initiate the concatenation input */
1418         NdisZeroMemory(temp, sizeof(temp));
1419         NdisZeroMemory(concatenation, 76);
1420
1421         /* Get smaller address */
1422         if (RTMPCompareMemory(SA, AA, 6) == 1)
1423                 NdisMoveMemory(concatenation, AA, 6);
1424         else
1425                 NdisMoveMemory(concatenation, SA, 6);
1426         CurrPos += 6;
1427
1428         /* Get larger address */
1429         if (RTMPCompareMemory(SA, AA, 6) == 1)
1430                 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1431         else
1432                 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1433
1434         /* store the larger mac address for backward compatible of */
1435         /* ralink proprietary STA-key issue */
1436         NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1437         CurrPos += 6;
1438
1439         /* Get smaller Nonce */
1440         if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1441                 NdisMoveMemory(&concatenation[CurrPos], temp, 32);      /* patch for ralink proprietary STA-key issue */
1442         else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1443                 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1444         else
1445                 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1446         CurrPos += 32;
1447
1448         /* Get larger Nonce */
1449         if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1450                 NdisMoveMemory(&concatenation[CurrPos], temp, 32);      /* patch for ralink proprietary STA-key issue */
1451         else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1452                 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1453         else
1454                 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1455         CurrPos += 32;
1456
1457         hex_dump("concatenation=", concatenation, 76);
1458
1459         /* Use PRF to generate PTK */
1460         PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1461
1462 }
1463
1464 /*
1465         ========================================================================
1466
1467         Routine Description:
1468                 Generate random number by software.
1469
1470         Arguments:
1471                 pAd             -       pointer to our pAdapter context
1472                 macAddr -       pointer to local MAC address
1473
1474         Return Value:
1475
1476         Note:
1477                 802.1ii-2004  Annex H.5
1478
1479         ========================================================================
1480 */
1481 void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random)
1482 {
1483         int i, curr;
1484         u8 local[80], KeyCounter[32];
1485         u8 result[80];
1486         unsigned long CurrentTime;
1487         u8 prefix[] =
1488             { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' };
1489
1490         /* Zero the related information */
1491         NdisZeroMemory(result, 80);
1492         NdisZeroMemory(local, 80);
1493         NdisZeroMemory(KeyCounter, 32);
1494
1495         for (i = 0; i < 32; i++) {
1496                 /* copy the local MAC address */
1497                 COPY_MAC_ADDR(local, macAddr);
1498                 curr = MAC_ADDR_LEN;
1499
1500                 /* concatenate the current time */
1501                 NdisGetSystemUpTime(&CurrentTime);
1502                 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1503                 curr += sizeof(CurrentTime);
1504
1505                 /* concatenate the last result */
1506                 NdisMoveMemory(&local[curr], result, 32);
1507                 curr += 32;
1508
1509                 /* concatenate a variable */
1510                 NdisMoveMemory(&local[curr], &i, 2);
1511                 curr += 2;
1512
1513                 /* calculate the result */
1514                 PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32);
1515         }
1516
1517         NdisMoveMemory(random, result, 32);
1518 }
1519
1520 /*
1521         ========================================================================
1522
1523         Routine Description:
1524                 Build cipher suite in RSN-IE.
1525                 It only shall be called by RTMPMakeRSNIE.
1526
1527         Arguments:
1528                 pAd                     -       pointer to our pAdapter context
1529         ElementID       -       indicate the WPA1 or WPA2
1530         WepStatus       -       indicate the encryption type
1531                 bMixCipher      -       a boolean to indicate the pairwise cipher and group
1532                                                 cipher are the same or not
1533
1534         Return Value:
1535
1536         Note:
1537
1538         ========================================================================
1539 */
1540 static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd,
1541                                 u8 ElementID,
1542                                 u32 WepStatus,
1543                                 IN BOOLEAN bMixCipher,
1544                                 u8 FlexibleCipher,
1545                                 u8 *pRsnIe, u8 * rsn_len)
1546 {
1547         u8 PairwiseCnt;
1548
1549         *rsn_len = 0;
1550
1551         /* decide WPA2 or WPA1 */
1552         if (ElementID == Wpa2Ie) {
1553                 struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe;
1554
1555                 /* Assign the verson as 1 */
1556                 pRsnie_cipher->version = 1;
1557
1558                 switch (WepStatus) {
1559                         /* TKIP mode */
1560                 case Ndis802_11Encryption2Enabled:
1561                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1562                         pRsnie_cipher->ucount = 1;
1563                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1564                                        OUI_WPA2_TKIP, 4);
1565                         *rsn_len = sizeof(struct rt_rsnie2);
1566                         break;
1567
1568                         /* AES mode */
1569                 case Ndis802_11Encryption3Enabled:
1570                         if (bMixCipher)
1571                                 NdisMoveMemory(pRsnie_cipher->mcast,
1572                                                OUI_WPA2_TKIP, 4);
1573                         else
1574                                 NdisMoveMemory(pRsnie_cipher->mcast,
1575                                                OUI_WPA2_CCMP, 4);
1576                         pRsnie_cipher->ucount = 1;
1577                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1578                                        OUI_WPA2_CCMP, 4);
1579                         *rsn_len = sizeof(struct rt_rsnie2);
1580                         break;
1581
1582                         /* TKIP-AES mix mode */
1583                 case Ndis802_11Encryption4Enabled:
1584                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1585
1586                         PairwiseCnt = 1;
1587                         /* Insert WPA2 TKIP as the first pairwise cipher */
1588                         if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) {
1589                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1590                                                OUI_WPA2_TKIP, 4);
1591                                 /* Insert WPA2 AES as the secondary pairwise cipher */
1592                                 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) {
1593                                         NdisMoveMemory(pRsnie_cipher->ucast[0].
1594                                                        oui + 4, OUI_WPA2_CCMP,
1595                                                        4);
1596                                         PairwiseCnt = 2;
1597                                 }
1598                         } else {
1599                                 /* Insert WPA2 AES as the first pairwise cipher */
1600                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1601                                                OUI_WPA2_CCMP, 4);
1602                         }
1603
1604                         pRsnie_cipher->ucount = PairwiseCnt;
1605                         *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1));
1606                         break;
1607                 }
1608
1609                 if ((pAd->OpMode == OPMODE_STA) &&
1610                     (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1611                     (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
1612                         u32 GroupCipher = pAd->StaCfg.GroupCipher;
1613                         switch (GroupCipher) {
1614                         case Ndis802_11GroupWEP40Enabled:
1615                                 NdisMoveMemory(pRsnie_cipher->mcast,
1616                                                OUI_WPA2_WEP40, 4);
1617                                 break;
1618                         case Ndis802_11GroupWEP104Enabled:
1619                                 NdisMoveMemory(pRsnie_cipher->mcast,
1620                                                OUI_WPA2_WEP104, 4);
1621                                 break;
1622                         }
1623                 }
1624                 /* swap for big-endian platform */
1625                 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1626                 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1627         } else {
1628                 struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe;
1629
1630                 /* Assign OUI and version */
1631                 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
1632                 pRsnie_cipher->version = 1;
1633
1634                 switch (WepStatus) {
1635                         /* TKIP mode */
1636                 case Ndis802_11Encryption2Enabled:
1637                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1638                         pRsnie_cipher->ucount = 1;
1639                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1640                                        OUI_WPA_TKIP, 4);
1641                         *rsn_len = sizeof(struct rt_rsnie);
1642                         break;
1643
1644                         /* AES mode */
1645                 case Ndis802_11Encryption3Enabled:
1646                         if (bMixCipher)
1647                                 NdisMoveMemory(pRsnie_cipher->mcast,
1648                                                OUI_WPA_TKIP, 4);
1649                         else
1650                                 NdisMoveMemory(pRsnie_cipher->mcast,
1651                                                OUI_WPA_CCMP, 4);
1652                         pRsnie_cipher->ucount = 1;
1653                         NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1654                                        OUI_WPA_CCMP, 4);
1655                         *rsn_len = sizeof(struct rt_rsnie);
1656                         break;
1657
1658                         /* TKIP-AES mix mode */
1659                 case Ndis802_11Encryption4Enabled:
1660                         NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1661
1662                         PairwiseCnt = 1;
1663                         /* Insert WPA TKIP as the first pairwise cipher */
1664                         if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) {
1665                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1666                                                OUI_WPA_TKIP, 4);
1667                                 /* Insert WPA AES as the secondary pairwise cipher */
1668                                 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) {
1669                                         NdisMoveMemory(pRsnie_cipher->ucast[0].
1670                                                        oui + 4, OUI_WPA_CCMP,
1671                                                        4);
1672                                         PairwiseCnt = 2;
1673                                 }
1674                         } else {
1675                                 /* Insert WPA AES as the first pairwise cipher */
1676                                 NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
1677                                                OUI_WPA_CCMP, 4);
1678                         }
1679
1680                         pRsnie_cipher->ucount = PairwiseCnt;
1681                         *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1));
1682                         break;
1683                 }
1684
1685                 if ((pAd->OpMode == OPMODE_STA) &&
1686                     (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1687                     (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
1688                         u32 GroupCipher = pAd->StaCfg.GroupCipher;
1689                         switch (GroupCipher) {
1690                         case Ndis802_11GroupWEP40Enabled:
1691                                 NdisMoveMemory(pRsnie_cipher->mcast,
1692                                                OUI_WPA_WEP40, 4);
1693                                 break;
1694                         case Ndis802_11GroupWEP104Enabled:
1695                                 NdisMoveMemory(pRsnie_cipher->mcast,
1696                                                OUI_WPA_WEP104, 4);
1697                                 break;
1698                         }
1699                 }
1700                 /* swap for big-endian platform */
1701                 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1702                 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1703         }
1704 }
1705
1706 /*
1707         ========================================================================
1708
1709         Routine Description:
1710                 Build AKM suite in RSN-IE.
1711                 It only shall be called by RTMPMakeRSNIE.
1712
1713         Arguments:
1714                 pAd                     -       pointer to our pAdapter context
1715         ElementID       -       indicate the WPA1 or WPA2
1716         AuthMode        -       indicate the authentication mode
1717                 apidx           -       indicate the interface index
1718
1719         Return Value:
1720
1721         Note:
1722
1723         ========================================================================
1724 */
1725 static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd,
1726                              u8 ElementID,
1727                              u32 AuthMode,
1728                              u8 apidx,
1729                              u8 *pRsnIe, u8 * rsn_len)
1730 {
1731         struct rt_rsnie_auth *pRsnie_auth;
1732         u8 AkmCnt = 1;  /* default as 1 */
1733
1734         pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len));
1735
1736         /* decide WPA2 or WPA1 */
1737         if (ElementID == Wpa2Ie) {
1738
1739                 switch (AuthMode) {
1740                 case Ndis802_11AuthModeWPA2:
1741                 case Ndis802_11AuthModeWPA1WPA2:
1742                         NdisMoveMemory(pRsnie_auth->auth[0].oui,
1743                                        OUI_WPA2_8021X_AKM, 4);
1744                         break;
1745
1746                 case Ndis802_11AuthModeWPA2PSK:
1747                 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1748                         NdisMoveMemory(pRsnie_auth->auth[0].oui,
1749                                        OUI_WPA2_PSK_AKM, 4);
1750                         break;
1751                 default:
1752                         AkmCnt = 0;
1753                         break;
1754
1755                 }
1756         } else {
1757                 switch (AuthMode) {
1758                 case Ndis802_11AuthModeWPA:
1759                 case Ndis802_11AuthModeWPA1WPA2:
1760                         NdisMoveMemory(pRsnie_auth->auth[0].oui,
1761                                        OUI_WPA_8021X_AKM, 4);
1762                         break;
1763
1764                 case Ndis802_11AuthModeWPAPSK:
1765                 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1766                         NdisMoveMemory(pRsnie_auth->auth[0].oui,
1767                                        OUI_WPA_PSK_AKM, 4);
1768                         break;
1769
1770                 case Ndis802_11AuthModeWPANone:
1771                         NdisMoveMemory(pRsnie_auth->auth[0].oui,
1772                                        OUI_WPA_NONE_AKM, 4);
1773                         break;
1774                 default:
1775                         AkmCnt = 0;
1776                         break;
1777                 }
1778         }
1779
1780         pRsnie_auth->acount = AkmCnt;
1781         pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1782
1783         /* update current RSNIE length */
1784         (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1)));
1785
1786 }
1787
1788 /*
1789         ========================================================================
1790
1791         Routine Description:
1792                 Build capability in RSN-IE.
1793                 It only shall be called by RTMPMakeRSNIE.
1794
1795         Arguments:
1796                 pAd                     -       pointer to our pAdapter context
1797         ElementID       -       indicate the WPA1 or WPA2
1798                 apidx           -       indicate the interface index
1799
1800         Return Value:
1801
1802         Note:
1803
1804         ========================================================================
1805 */
1806 static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd,
1807                              u8 ElementID,
1808                              u8 apidx,
1809                              u8 *pRsnIe, u8 * rsn_len)
1810 {
1811         RSN_CAPABILITIES *pRSN_Cap;
1812
1813         /* it could be ignored in WPA1 mode */
1814         if (ElementID == WpaIe)
1815                 return;
1816
1817         pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len));
1818
1819         pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1820
1821         (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */
1822
1823 }
1824
1825 /*
1826         ========================================================================
1827
1828         Routine Description:
1829                 Build RSN IE context. It is not included element-ID and length.
1830
1831         Arguments:
1832                 pAd                     -       pointer to our pAdapter context
1833         AuthMode        -       indicate the authentication mode
1834         WepStatus       -       indicate the encryption type
1835                 apidx           -       indicate the interface index
1836
1837         Return Value:
1838
1839         Note:
1840
1841         ========================================================================
1842 */
1843 void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd,
1844                    u32 AuthMode, u32 WepStatus, u8 apidx)
1845 {
1846         u8 *pRsnIe = NULL;      /* primary RSNIE */
1847         u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */
1848         u8 *rsnielen_ex_cur_p = 0;      /* the length of the secondary RSNIE */
1849         u8 PrimaryRsnie;
1850         BOOLEAN bMixCipher = FALSE;     /* indicate the pairwise and group cipher are different */
1851         u8 p_offset;
1852         WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES;  /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */
1853
1854         rsnielen_cur_p = NULL;
1855         rsnielen_ex_cur_p = NULL;
1856
1857         {
1858                 {
1859                         if (pAd->StaCfg.WpaSupplicantUP !=
1860                             WPA_SUPPLICANT_DISABLE) {
1861                                 if (AuthMode < Ndis802_11AuthModeWPA)
1862                                         return;
1863                         } else {
1864                                 /* Support WPAPSK or WPA2PSK in STA-Infra mode */
1865                                 /* Support WPANone in STA-Adhoc mode */
1866                                 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
1867                                     (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1868                                     (AuthMode != Ndis802_11AuthModeWPANone)
1869                                     )
1870                                         return;
1871                         }
1872
1873                         DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n"));
1874
1875                         /* Zero RSNIE context */
1876                         pAd->StaCfg.RSNIE_Len = 0;
1877                         NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1878
1879                         /* Pointer to RSNIE */
1880                         rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1881                         pRsnIe = pAd->StaCfg.RSN_IE;
1882
1883                         bMixCipher = pAd->StaCfg.bMixCipher;
1884                 }
1885         }
1886
1887         /* indicate primary RSNIE as WPA or WPA2 */
1888         if ((AuthMode == Ndis802_11AuthModeWPA) ||
1889             (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1890             (AuthMode == Ndis802_11AuthModeWPANone) ||
1891             (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1892             (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
1893                 PrimaryRsnie = WpaIe;
1894         else
1895                 PrimaryRsnie = Wpa2Ie;
1896
1897         {
1898                 /* Build the primary RSNIE */
1899                 /* 1. insert cipher suite */
1900                 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher,
1901                                     FlexibleCipher, pRsnIe, &p_offset);
1902
1903                 /* 2. insert AKM */
1904                 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe,
1905                                  &p_offset);
1906
1907                 /* 3. insert capability */
1908                 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1909         }
1910
1911         /* 4. update the RSNIE length */
1912         *rsnielen_cur_p = p_offset;
1913
1914         hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1915
1916 }
1917
1918 /*
1919     ==========================================================================
1920     Description:
1921                 Check whether the received frame is EAP frame.
1922
1923         Arguments:
1924                 pAd                             -       pointer to our pAdapter context
1925                 pEntry                  -       pointer to active entry
1926                 pData                   -       the received frame
1927                 DataByteCount   -       the received frame's length
1928                 FromWhichBSSID  -       indicate the interface index
1929
1930     Return:
1931          TRUE                   -       This frame is EAP frame
1932          FALSE                  -       otherwise
1933     ==========================================================================
1934 */
1935 BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd,
1936                           struct rt_mac_table_entry *pEntry,
1937                           u8 *pData,
1938                           unsigned long DataByteCount, u8 FromWhichBSSID)
1939 {
1940         unsigned long Body_len;
1941         BOOLEAN Cancelled;
1942
1943         if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
1944                 return FALSE;
1945
1946         /* Skip LLC header */
1947         if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
1948             /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */
1949             NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) {
1950                 pData += 6;
1951         }
1952         /* Skip 2-bytes EAPoL type */
1953         if (NdisEqualMemory(EAPOL, pData, 2)) {
1954                 pData += 2;
1955         } else
1956                 return FALSE;
1957
1958         switch (*(pData + 1)) {
1959         case EAPPacket:
1960                 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1961                 DBGPRINT(RT_DEBUG_TRACE,
1962                          ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n",
1963                           Body_len));
1964                 break;
1965         case EAPOLStart:
1966                 DBGPRINT(RT_DEBUG_TRACE,
1967                          ("Receive EAPOL-Start frame, TYPE = 1 \n"));
1968                 if (pEntry->EnqueueEapolStartTimerRunning !=
1969                     EAPOL_START_DISABLE) {
1970                         DBGPRINT(RT_DEBUG_TRACE,
1971                                  ("Cancel the EnqueueEapolStartTimerRunning \n"));
1972                         RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer,
1973                                         &Cancelled);
1974                         pEntry->EnqueueEapolStartTimerRunning =
1975                             EAPOL_START_DISABLE;
1976                 }
1977                 break;
1978         case EAPOLLogoff:
1979                 DBGPRINT(RT_DEBUG_TRACE,
1980                          ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
1981                 break;
1982         case EAPOLKey:
1983                 Body_len = (*(pData + 2) << 8) | (*(pData + 3));
1984                 DBGPRINT(RT_DEBUG_TRACE,
1985                          ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n",
1986                           Body_len));
1987                 break;
1988         case EAPOLASFAlert:
1989                 DBGPRINT(RT_DEBUG_TRACE,
1990                          ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
1991                 break;
1992         default:
1993                 return FALSE;
1994
1995         }
1996         return TRUE;
1997 }
1998
1999 /*
2000     ==========================================================================
2001     Description:
2002                 Report the EAP message type
2003
2004         Arguments:
2005                 msg             -       EAPOL_PAIR_MSG_1
2006                                         EAPOL_PAIR_MSG_2
2007                                         EAPOL_PAIR_MSG_3
2008                                         EAPOL_PAIR_MSG_4
2009                                         EAPOL_GROUP_MSG_1
2010                                         EAPOL_GROUP_MSG_2
2011
2012     Return:
2013          message type string
2014
2015     ==========================================================================
2016 */
2017 char *GetEapolMsgType(char msg)
2018 {
2019         if (msg == EAPOL_PAIR_MSG_1)
2020                 return "Pairwise Message 1";
2021         else if (msg == EAPOL_PAIR_MSG_2)
2022                 return "Pairwise Message 2";
2023         else if (msg == EAPOL_PAIR_MSG_3)
2024                 return "Pairwise Message 3";
2025         else if (msg == EAPOL_PAIR_MSG_4)
2026                 return "Pairwise Message 4";
2027         else if (msg == EAPOL_GROUP_MSG_1)
2028                 return "Group Message 1";
2029         else if (msg == EAPOL_GROUP_MSG_2)
2030                 return "Group Message 2";
2031         else
2032                 return "Invalid Message";
2033 }
2034
2035 /*
2036         ========================================================================
2037
2038         Routine Description:
2039     Check Sanity RSN IE of EAPoL message
2040
2041         Arguments:
2042
2043         Return Value:
2044
2045         ========================================================================
2046 */
2047 BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd,
2048                        u8 *pData,
2049                        u8 DataLen,
2050                        struct rt_mac_table_entry *pEntry, u8 * Offset)
2051 {
2052         u8 *pVIE;
2053         u8 len;
2054         struct rt_eid * pEid;
2055         BOOLEAN result = FALSE;
2056
2057         pVIE = pData;
2058         len = DataLen;
2059         *Offset = 0;
2060
2061         while (len > sizeof(struct rt_rsnie2)) {
2062                 pEid = (struct rt_eid *) pVIE;
2063                 /* WPA RSN IE */
2064                 if ((pEid->Eid == IE_WPA)
2065                     && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) {
2066                         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA
2067                              || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
2068                             &&
2069                             (NdisEqualMemory
2070                              (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len))
2071                             && (pEntry->RSNIE_Len == (pEid->Len + 2))) {
2072                                 result = TRUE;
2073                         }
2074
2075                         *Offset += (pEid->Len + 2);
2076                 }
2077                 /* WPA2 RSN IE */
2078                 else if ((pEid->Eid == IE_RSN)
2079                          && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) {
2080                         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2
2081                              || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
2082                             && (pEid->Eid == pEntry->RSN_IE[0])
2083                             && ((pEid->Len + 2) >= pEntry->RSNIE_Len)
2084                             &&
2085                             (NdisEqualMemory
2086                              (pEid->Octet, &pEntry->RSN_IE[2],
2087                               pEntry->RSNIE_Len - 2))) {
2088
2089                                 result = TRUE;
2090                         }
2091
2092                         *Offset += (pEid->Len + 2);
2093                 } else {
2094                         break;
2095                 }
2096
2097                 pVIE += (pEid->Len + 2);
2098                 len -= (pEid->Len + 2);
2099         }
2100
2101         return result;
2102
2103 }
2104
2105 /*
2106         ========================================================================
2107
2108         Routine Description:
2109     Parse KEYDATA field.  KEYDATA[] May contain 2 RSN IE and optionally GTK.
2110     GTK  is encaptulated in KDE format at  p.83 802.11i D10
2111
2112         Arguments:
2113
2114         Return Value:
2115
2116         Note:
2117         802.11i D10
2118
2119         ========================================================================
2120 */
2121 BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd,
2122                               u8 *pKeyData,
2123                               u8 KeyDataLen,
2124                               u8 GroupKeyIndex,
2125                               u8 MsgType,
2126                               IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry)
2127 {
2128         struct rt_kde_encap * pKDE = NULL;
2129         u8 *pMyKeyData = pKeyData;
2130         u8 KeyDataLength = KeyDataLen;
2131         u8 GTKLEN = 0;
2132         u8 DefaultIdx = 0;
2133         u8 skip_offset;
2134
2135         /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */
2136         if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) {
2137                 /* Check RSN IE whether it is WPA2/WPA2PSK */
2138                 if (!RTMPCheckRSNIE
2139                     (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) {
2140                         /* send wireless event - for RSN IE different */
2141                         if (pAd->CommonCfg.bWirelessEvent)
2142                                 RTMPSendWirelessEvent(pAd,
2143                                                       IW_RSNIE_DIFF_EVENT_FLAG,
2144                                                       pEntry->Addr,
2145                                                       pEntry->apidx, 0);
2146
2147                         DBGPRINT(RT_DEBUG_ERROR,
2148                                  ("RSN_IE Different in msg %d of 4-way handshake!\n",
2149                                   MsgType));
2150                         hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
2151                         hex_dump("Desired RSN_IE ", pEntry->RSN_IE,
2152                                  pEntry->RSNIE_Len);
2153
2154                         return FALSE;
2155                 } else {
2156                         if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) {
2157                                 WpaShowAllsuite(pMyKeyData, skip_offset);
2158
2159                                 /* skip RSN IE */
2160                                 pMyKeyData += skip_offset;
2161                                 KeyDataLength -= skip_offset;
2162                                 DBGPRINT(RT_DEBUG_TRACE,
2163                                          ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n",
2164                                           skip_offset));
2165                         } else
2166                                 return TRUE;
2167                 }
2168         }
2169
2170         DBGPRINT(RT_DEBUG_TRACE,
2171                  ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n",
2172                   KeyDataLength));
2173         /*hex_dump("remain data", pMyKeyData, KeyDataLength); */
2174
2175         /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */
2176         if (bWPA2
2177             && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) {
2178                 if (KeyDataLength >= 8) /* KDE format exclude GTK length */
2179                 {
2180                         pKDE = (struct rt_kde_encap *) pMyKeyData;
2181
2182                         DefaultIdx = pKDE->GTKEncap.Kid;
2183
2184                         /* Sanity check - KED length */
2185                         if (KeyDataLength < (pKDE->Len + 2)) {
2186                                 DBGPRINT(RT_DEBUG_ERROR,
2187                                          ("ERROR: The len from KDE is too short \n"));
2188                                 return FALSE;
2189                         }
2190                         /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
2191                         GTKLEN = pKDE->Len - 6;
2192                         if (GTKLEN < LEN_AES_KEY) {
2193                                 DBGPRINT(RT_DEBUG_ERROR,
2194                                          ("ERROR: GTK Key length is too short (%d) \n",
2195                                           GTKLEN));
2196                                 return FALSE;
2197                         }
2198
2199                 } else {
2200                         DBGPRINT(RT_DEBUG_ERROR,
2201                                  ("ERROR: KDE format length is too short \n"));
2202                         return FALSE;
2203                 }
2204
2205                 DBGPRINT(RT_DEBUG_TRACE,
2206                          ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n",
2207                           DefaultIdx, GTKLEN));
2208                 /* skip it */
2209                 pMyKeyData += 8;
2210                 KeyDataLength -= 8;
2211
2212         } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) {
2213                 DefaultIdx = GroupKeyIndex;
2214                 DBGPRINT(RT_DEBUG_TRACE,
2215                          ("GTK DefaultKeyID=%d \n", DefaultIdx));
2216         }
2217         /* Sanity check - shared key index must be 1 ~ 3 */
2218         if (DefaultIdx < 1 || DefaultIdx > 3) {
2219                 DBGPRINT(RT_DEBUG_ERROR,
2220                          ("ERROR: GTK Key index(%d) is invalid in %s %s \n",
2221                           DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"),
2222                           GetEapolMsgType(MsgType)));
2223                 return FALSE;
2224         }
2225
2226         {
2227                 struct rt_cipher_key *pSharedKey;
2228
2229                 /* set key material, TxMic and RxMic */
2230                 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2231                 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2232
2233                 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2234
2235                 /* Prepare pair-wise key information into shared key table */
2236                 NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
2237                 pSharedKey->KeyLen = LEN_TKIP_EK;
2238                 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
2239                 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
2240                                LEN_TKIP_RXMICK);
2241                 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
2242                                LEN_TKIP_TXMICK);
2243
2244                 /* Update Shared Key CipherAlg */
2245                 pSharedKey->CipherAlg = CIPHER_NONE;
2246                 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2247                         pSharedKey->CipherAlg = CIPHER_TKIP;
2248                 else if (pAd->StaCfg.GroupCipher ==
2249                          Ndis802_11Encryption3Enabled)
2250                         pSharedKey->CipherAlg = CIPHER_AES;
2251                 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2252                         pSharedKey->CipherAlg = CIPHER_WEP64;
2253                 else if (pAd->StaCfg.GroupCipher ==
2254                          Ndis802_11GroupWEP104Enabled)
2255                         pSharedKey->CipherAlg = CIPHER_WEP128;
2256
2257                 /* Update group key information to ASIC Shared Key Table */
2258                 AsicAddSharedKeyEntry(pAd,
2259                                       BSS0,
2260                                       pAd->StaCfg.DefaultKeyId,
2261                                       pSharedKey->CipherAlg,
2262                                       pSharedKey->Key,
2263                                       pSharedKey->TxMic, pSharedKey->RxMic);
2264
2265                 /* Update ASIC WCID attribute table and IVEIV table */
2266                 RTMPAddWcidAttributeEntry(pAd,
2267                                           BSS0,
2268                                           pAd->StaCfg.DefaultKeyId,
2269                                           pSharedKey->CipherAlg, NULL);
2270         }
2271
2272         return TRUE;
2273
2274 }
2275
2276 /*
2277         ========================================================================
2278
2279         Routine Description:
2280                 Construct EAPoL message for WPA handshaking
2281                 Its format is below,
2282
2283                 +--------------------+
2284                 | Protocol Version       |  1 octet
2285                 +--------------------+
2286                 | Protocol Type          |      1 octet
2287                 +--------------------+
2288                 | Body Length            |  2 octets
2289                 +--------------------+
2290                 | Descriptor Type        |      1 octet
2291                 +--------------------+
2292                 | Key Information    |  2 octets
2293                 +--------------------+
2294                 | Key Length         |  1 octet
2295                 +--------------------+
2296                 | Key Repaly Counter |  8 octets
2297                 +--------------------+
2298                 | Key Nonce                  |  32 octets
2299                 +--------------------+
2300                 | Key IV                         |  16 octets
2301                 +--------------------+
2302                 | Key RSC                        |  8 octets
2303                 +--------------------+
2304                 | Key ID or Reserved |  8 octets
2305                 +--------------------+
2306                 | Key MIC                        |      16 octets
2307                 +--------------------+
2308                 | Key Data Length        |      2 octets
2309                 +--------------------+
2310                 | Key Data                       |      n octets
2311                 +--------------------+
2312
2313         Arguments:
2314                 pAd                     Pointer to our adapter
2315
2316         Return Value:
2317                 None
2318
2319         Note:
2320
2321         ========================================================================
2322 */
2323 void ConstructEapolMsg(struct rt_mac_table_entry *pEntry,
2324                        u8 GroupKeyWepStatus,
2325                        u8 MsgType,
2326                        u8 DefaultKeyIdx,
2327                        u8 * KeyNonce,
2328                        u8 * TxRSC,
2329                        u8 * GTK,
2330                        u8 * RSNIE,
2331                        u8 RSNIE_Len, struct rt_eapol_packet * pMsg)
2332 {
2333         BOOLEAN bWPA2 = FALSE;
2334         u8 KeyDescVer;
2335
2336         /* Choose WPA2 or not */
2337         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2338             (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2339                 bWPA2 = TRUE;
2340
2341         /* Init Packet and Fill header */
2342         pMsg->ProVer = EAPOL_VER;
2343         pMsg->ProType = EAPOLKey;
2344
2345         /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */
2346         SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
2347
2348         /* Fill in EAPoL descriptor */
2349         if (bWPA2)
2350                 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2351         else
2352                 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2353
2354         /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */
2355         {
2356                 /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */
2357                 /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */
2358                 KeyDescVer =
2359                     (((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
2360                       || (GroupKeyWepStatus ==
2361                           Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES)
2362                      : (DESC_TYPE_TKIP));
2363         }
2364
2365         pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2366
2367         /* Specify Key Type as Group(0) or Pairwise(1) */
2368         if (MsgType >= EAPOL_GROUP_MSG_1)
2369                 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
2370         else
2371                 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2372
2373         /* Specify Key Index, only group_msg1_WPA1 */
2374         if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2375                 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2376
2377         if (MsgType == EAPOL_PAIR_MSG_3)
2378                 pMsg->KeyDesc.KeyInfo.Install = 1;
2379
2380         if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)
2381             || (MsgType == EAPOL_GROUP_MSG_1))
2382                 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2383
2384         if (MsgType != EAPOL_PAIR_MSG_1)
2385                 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2386
2387         if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
2388             (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) {
2389                 pMsg->KeyDesc.KeyInfo.Secure = 1;
2390         }
2391
2392         if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
2393                       (MsgType == EAPOL_GROUP_MSG_1))) {
2394                 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2395         }
2396         /* key Information element has done. */
2397         *(u16 *) (&pMsg->KeyDesc.KeyInfo) =
2398             cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo));
2399
2400         /* Fill in Key Length */
2401         {
2402                 if (MsgType >= EAPOL_GROUP_MSG_1) {
2403                         /* the length of group key cipher */
2404                         pMsg->KeyDesc.KeyLength[1] =
2405                             ((GroupKeyWepStatus ==
2406                               Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH :
2407                              LEN_AES_KEY);
2408                 } else {
2409                         /* the length of pairwise key cipher */
2410                         pMsg->KeyDesc.KeyLength[1] =
2411                             ((pEntry->WepStatus ==
2412                               Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY :
2413                              LEN_AES_KEY);
2414                 }
2415         }
2416
2417         /* Fill in replay counter */
2418         NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter,
2419                        LEN_KEY_DESC_REPLAY);
2420
2421         /* Fill Key Nonce field */
2422         /* ANonce : pairwise_msg1 & pairwise_msg3 */
2423         /* SNonce : pairwise_msg2 */
2424         /* GNonce : group_msg1_wpa1 */
2425         if ((MsgType <= EAPOL_PAIR_MSG_3)
2426             || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
2427                 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce,
2428                                LEN_KEY_DESC_NONCE);
2429
2430         /* Fill key IV - WPA2 as 0, WPA1 as random */
2431         if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) {
2432                 /* Suggest IV be random number plus some number, */
2433                 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16],
2434                                LEN_KEY_DESC_IV);
2435                 pMsg->KeyDesc.KeyIv[15] += 2;
2436         }
2437         /* Fill Key RSC field */
2438         /* It contains the RSC for the GTK being installed. */
2439         if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2)
2440             || (MsgType == EAPOL_GROUP_MSG_1)) {
2441                 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2442         }
2443         /* Clear Key MIC field for MIC calculation later */
2444         NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
2445
2446         ConstructEapolKeyData(pEntry,
2447                               GroupKeyWepStatus,
2448                               KeyDescVer,
2449                               MsgType,
2450                               DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg);
2451
2452         /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
2453         if (MsgType != EAPOL_PAIR_MSG_1) {
2454                 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
2455         }
2456
2457         DBGPRINT(RT_DEBUG_TRACE,
2458                  ("===> ConstructEapolMsg for %s %s\n",
2459                   ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2460         DBGPRINT(RT_DEBUG_TRACE,
2461                  ("          Body length = %d \n",
2462                   CONV_ARRARY_TO_u16(pMsg->Body_Len)));
2463         DBGPRINT(RT_DEBUG_TRACE,
2464                  ("          Key length  = %d \n",
2465                   CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength)));
2466
2467 }
2468
2469 /*
2470         ========================================================================
2471
2472         Routine Description:
2473                 Construct the Key Data field of EAPoL message
2474
2475         Arguments:
2476                 pAd                     Pointer to our adapter
2477                 Elem            Message body
2478
2479         Return Value:
2480                 None
2481
2482         Note:
2483
2484         ========================================================================
2485 */
2486 void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
2487                            u8 GroupKeyWepStatus,
2488                            u8 keyDescVer,
2489                            u8 MsgType,
2490                            u8 DefaultKeyIdx,
2491                            u8 * GTK,
2492                            u8 * RSNIE,
2493                            u8 RSNIE_LEN, struct rt_eapol_packet * pMsg)
2494 {
2495         u8 *mpool, *Key_Data, *Rc4GTK;
2496         u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)];
2497         unsigned long data_offset;
2498         BOOLEAN bWPA2Capable = FALSE;
2499         struct rt_rtmp_adapter *pAd = pEntry->pAd;
2500         BOOLEAN GTK_Included = FALSE;
2501
2502         /* Choose WPA2 or not */
2503         if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2504             (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2505                 bWPA2Capable = TRUE;
2506
2507         if (MsgType == EAPOL_PAIR_MSG_1 ||
2508             MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
2509                 return;
2510
2511         /* allocate memory pool */
2512         os_alloc_mem(NULL, (u8 **) & mpool, 1500);
2513
2514         if (mpool == NULL)
2515                 return;
2516
2517         /* Rc4GTK Len = 512 */
2518         Rc4GTK = (u8 *) ROUND_UP(mpool, 4);
2519         /* Key_Data Len = 512 */
2520         Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4);
2521
2522         NdisZeroMemory(Key_Data, 512);
2523         SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
2524         data_offset = 0;
2525
2526         /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
2527         if (RSNIE_LEN
2528             && ((MsgType == EAPOL_PAIR_MSG_2)
2529                 || (MsgType == EAPOL_PAIR_MSG_3))) {
2530                 u8 *pmkid_ptr = NULL;
2531                 u8 pmkid_len = 0;
2532
2533                 RTMPInsertRSNIE(&Key_Data[data_offset],
2534                                 &data_offset,
2535                                 RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len);
2536         }
2537
2538         /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */
2539         if (bWPA2Capable
2540             && ((MsgType == EAPOL_PAIR_MSG_3)
2541                 || (MsgType == EAPOL_GROUP_MSG_1))) {
2542                 /* Key Data Encapsulation (KDE) format - 802.11i-2004  Figure-43w and Table-20h */
2543                 Key_Data[data_offset + 0] = 0xDD;
2544
2545                 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2546                         Key_Data[data_offset + 1] = 0x16;       /* 4+2+16(OUI+DataType+DataField) */
2547                 } else {
2548                         Key_Data[data_offset + 1] = 0x26;       /* 4+2+32(OUI+DataType+DataField) */
2549                 }
2550
2551                 Key_Data[data_offset + 2] = 0x00;
2552                 Key_Data[data_offset + 3] = 0x0F;
2553                 Key_Data[data_offset + 4] = 0xAC;
2554                 Key_Data[data_offset + 5] = 0x01;
2555
2556                 /* GTK KDE format - 802.11i-2004  Figure-43x */
2557                 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
2558                 Key_Data[data_offset + 7] = 0x00;       /* Reserved Byte */
2559
2560                 data_offset += 8;
2561         }
2562
2563         /* Encapsulate GTK */
2564         /* Only for pairwise_msg3_WPA2 and group_msg1 */
2565         if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
2566             || (MsgType == EAPOL_GROUP_MSG_1)) {
2567                 /* Fill in GTK */
2568                 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
2569                         NdisMoveMemory(&Key_Data[data_offset], GTK,
2570                                        LEN_AES_KEY);
2571                         data_offset += LEN_AES_KEY;
2572                 } else {
2573                         NdisMoveMemory(&Key_Data[data_offset], GTK,
2574                                        TKIP_GTK_LENGTH);
2575                         data_offset += TKIP_GTK_LENGTH;
2576                 }
2577
2578                 GTK_Included = TRUE;
2579         }
2580
2581         /* This whole key-data field shall be encrypted if a GTK is included. */
2582         /* Encrypt the data material in key data field with KEK */
2583         if (GTK_Included) {
2584                 /*hex_dump("GTK_Included", Key_Data, data_offset); */
2585
2586                 if ((keyDescVer == DESC_TYPE_AES)) {
2587                         u8 remainder = 0;
2588                         u8 pad_len = 0;
2589
2590                         /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */
2591                         /* shall be used to encrypt the Key Data field using the KEK field from */
2592                         /* the derived PTK. */
2593
2594                         /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */
2595                         /* shall be padded before encrypting if the key data length is less than 16 */
2596                         /* octets or if it is not a multiple of 8. The padding consists of appending */
2597                         /* a single octet 0xdd followed by zero or more 0x00 octets. */
2598                         if ((remainder = data_offset & 0x07) != 0) {
2599                                 int i;
2600
2601                                 pad_len = (8 - remainder);
2602                                 Key_Data[data_offset] = 0xDD;
2603                                 for (i = 1; i < pad_len; i++)
2604                                         Key_Data[data_offset + i] = 0;
2605
2606                                 data_offset += pad_len;
2607                         }
2608
2609                         AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data,
2610                                          data_offset, Rc4GTK);
2611                         /* AES wrap function will grow 8 bytes in length */
2612                         data_offset += 8;
2613                 } else {
2614                         /*      Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2615                            using the KEK field from the derived PTK. */
2616
2617                         /* PREPARE Encrypted  "Key DATA" field.  (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */
2618                         /* put TxTsc in Key RSC field */
2619                         pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32;       /*Init crc32. */
2620
2621                         /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */
2622                         NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv,
2623                                        LEN_KEY_DESC_IV);
2624                         NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16],
2625                                        LEN_EAP_EK);
2626                         ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */
2627                         pAd->PrivateInfo.FCSCRC32 =
2628                             RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data,
2629                                             data_offset);
2630                         WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK,
2631                                            Key_Data, data_offset);
2632                 }
2633
2634                 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
2635         } else {
2636                 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
2637         }
2638
2639         /* Update key data length field and total body length */
2640         SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2641         INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset);
2642
2643         os_free_mem(NULL, mpool);
2644
2645 }
2646
2647 /*
2648         ========================================================================
2649
2650         Routine Description:
2651                 Calcaulate MIC. It is used during 4-ways handsharking.
2652
2653         Arguments:
2654                 pAd                     -       pointer to our pAdapter context
2655         PeerWepStatus   -       indicate the encryption type
2656
2657         Return Value:
2658
2659         Note:
2660
2661         ========================================================================
2662 */
2663 static void CalculateMIC(u8 KeyDescVer,
2664                          u8 * PTK, struct rt_eapol_packet * pMsg)
2665 {
2666         u8 *OutBuffer;
2667         unsigned long FrameLen = 0;
2668         u8 mic[LEN_KEY_DESC_MIC];
2669         u8 digest[80];
2670
2671         /* allocate memory for MIC calculation */
2672         os_alloc_mem(NULL, (u8 **) & OutBuffer, 512);
2673
2674         if (OutBuffer == NULL) {
2675                 DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n"));
2676                 return;
2677         }
2678         /* make a frame for calculating MIC. */
2679         MakeOutgoingFrame(OutBuffer, &FrameLen,
2680                           CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg,
2681                           END_OF_ARGS);
2682
2683         NdisZeroMemory(mic, sizeof(mic));
2684
2685         /* Calculate MIC */
2686         if (KeyDescVer == DESC_TYPE_AES) {
2687                 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest,
2688                           SHA1_DIGEST_SIZE);
2689                 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
2690         } else {
2691                 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic,
2692                          MD5_DIGEST_SIZE);
2693         }
2694
2695         /* store the calculated MIC */
2696         NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2697
2698         os_free_mem(NULL, OutBuffer);
2699 }
2700
2701 /*
2702         ========================================================================
2703
2704         Routine Description:
2705                 Some received frames can't decrypt by Asic, so decrypt them by software.
2706
2707         Arguments:
2708                 pAd                     -       pointer to our pAdapter context
2709         PeerWepStatus   -       indicate the encryption type
2710
2711         Return Value:
2712                 NDIS_STATUS_SUCCESS             -       decryption successful
2713                 NDIS_STATUS_FAILURE             -       decryption failure
2714
2715         ========================================================================
2716 */
2717 int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd,
2718                                          struct rt_rx_blk *pRxBlk,
2719                                          IN NDIS_802_11_ENCRYPTION_STATUS
2720                                          GroupCipher, struct rt_cipher_key *pShard_key)
2721 {
2722         struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
2723
2724         /* handle WEP decryption */
2725         if (GroupCipher == Ndis802_11Encryption1Enabled) {
2726                 if (RTMPSoftDecryptWEP
2727                     (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2728                      pShard_key)) {
2729
2730                         /*Minus IV[4] & ICV[4] */
2731                         pRxWI->MPDUtotalByteCount -= 8;
2732                 } else {
2733                         DBGPRINT(RT_DEBUG_ERROR,
2734                                  ("ERROR : Software decrypt WEP data fails.\n"));
2735                         /* give up this frame */
2736                         return NDIS_STATUS_FAILURE;
2737                 }
2738         }
2739         /* handle TKIP decryption */
2740         else if (GroupCipher == Ndis802_11Encryption2Enabled) {
2741                 if (RTMPSoftDecryptTKIP
2742                     (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0,
2743                      pShard_key)) {
2744
2745                         /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */
2746                         pRxWI->MPDUtotalByteCount -= 20;
2747                 } else {
2748                         DBGPRINT(RT_DEBUG_ERROR,
2749                                  ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
2750                         /* give up this frame */
2751                         return NDIS_STATUS_FAILURE;
2752                 }
2753         }
2754         /* handle AES decryption */
2755         else if (GroupCipher == Ndis802_11Encryption3Enabled) {
2756                 if (RTMPSoftDecryptAES
2757                     (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
2758                      pShard_key)) {
2759
2760                         /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */
2761                         pRxWI->MPDUtotalByteCount -= 16;
2762                 } else {
2763                         DBGPRINT(RT_DEBUG_ERROR,
2764                                  ("ERROR : RTMPSoftDecryptAES Failed\n"));
2765                         /* give up this frame */
2766                         return NDIS_STATUS_FAILURE;
2767                 }
2768         } else {
2769                 /* give up this frame */
2770                 return NDIS_STATUS_FAILURE;
2771         }
2772
2773         return NDIS_STATUS_SUCCESS;
2774
2775 }
2776
2777 u8 *GetSuiteFromRSNIE(u8 *rsnie,
2778                          u32 rsnie_len, u8 type, u8 * count)
2779 {
2780         struct rt_eid * pEid;
2781         int len;
2782         u8 *pBuf;
2783         int offset = 0;
2784         struct rt_rsnie_auth *pAkm;
2785         u16 acount;
2786         BOOLEAN isWPA2 = FALSE;
2787
2788         pEid = (struct rt_eid *) rsnie;
2789         len = rsnie_len - 2;    /* exclude IE and length */
2790         pBuf = (u8 *)& pEid->Octet[0];
2791
2792         /* set default value */
2793         *count = 0;
2794
2795         /* Check length */
2796         if ((len <= 0) || (pEid->Len != len)) {
2797                 DBGPRINT_ERR(("%s : The length is invalid\n", __func__));
2798                 return NULL;
2799         }
2800         /* Check WPA or WPA2 */
2801         if (pEid->Eid == IE_WPA) {
2802                 struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf;
2803                 u16 ucount;
2804
2805                 if (len < sizeof(struct rt_rsnie)) {
2806                         DBGPRINT_ERR(("%s : The length is too short for WPA\n",
2807                                       __func__));
2808                         return NULL;
2809                 }
2810                 /* Get the count of pairwise cipher */
2811                 ucount = cpu2le16(pRsnie->ucount);
2812                 if (ucount > 2) {
2813                         DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
2814                         return NULL;
2815                 }
2816                 /* Get the group cipher */
2817                 if (type == GROUP_SUITE) {
2818                         *count = 1;
2819                         return pRsnie->mcast;
2820                 }
2821                 /* Get the pairwise cipher suite */
2822                 else if (type == PAIRWISE_SUITE) {
2823                         DBGPRINT(RT_DEBUG_TRACE,
2824                                  ("%s : The count of pairwise cipher is %d\n",
2825                                   __func__, ucount));
2826                         *count = ucount;
2827                         return pRsnie->ucast[0].oui;
2828                 }
2829
2830                 offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1));
2831
2832         } else if (pEid->Eid == IE_RSN) {
2833                 struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf;
2834                 u16 ucount;
2835
2836                 isWPA2 = TRUE;
2837
2838                 if (len < sizeof(struct rt_rsnie2)) {
2839                         DBGPRINT_ERR(("%s : The length is too short for WPA2\n",
2840                                       __func__));
2841                         return NULL;
2842                 }
2843                 /* Get the count of pairwise cipher */
2844                 ucount = cpu2le16(pRsnie->ucount);
2845                 if (ucount > 2) {
2846                         DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount));
2847                         return NULL;
2848                 }
2849                 /* Get the group cipher */
2850                 if (type == GROUP_SUITE) {
2851                         *count = 1;
2852                         return pRsnie->mcast;
2853                 }
2854                 /* Get the pairwise cipher suite */
2855                 else if (type == PAIRWISE_SUITE) {
2856                         DBGPRINT(RT_DEBUG_TRACE,
2857                                  ("%s : The count of pairwise cipher is %d\n",
2858                                   __func__, ucount));
2859                         *count = ucount;
2860                         return pRsnie->ucast[0].oui;
2861                 }
2862
2863                 offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1));
2864
2865         } else {
2866                 DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid));
2867                 return NULL;
2868         }
2869
2870         /* skip group cipher and pairwise cipher suite */
2871         pBuf += offset;
2872         len -= offset;
2873
2874         if (len < sizeof(struct rt_rsnie_auth)) {
2875                 DBGPRINT_ERR(("%s : The length of RSNIE is too short\n",
2876                               __func__));
2877                 return NULL;
2878         }
2879         /* pointer to AKM count */
2880         pAkm = (struct rt_rsnie_auth *)pBuf;
2881
2882         /* Get the count of pairwise cipher */
2883         acount = cpu2le16(pAkm->acount);
2884         if (acount > 2) {
2885                 DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
2886                               __func__, acount));
2887                 return NULL;
2888         }
2889         /* Get the AKM suite */
2890         if (type == AKM_SUITE) {
2891                 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
2892                                           __func__, acount));
2893                 *count = acount;
2894                 return pAkm->auth[0].oui;
2895         }
2896         offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1));
2897
2898         pBuf += offset;
2899         len -= offset;
2900
2901         /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */
2902         if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) {
2903                 /* Skip RSN capability and PMKID-Count */
2904                 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
2905                 len -= (sizeof(RSN_CAPABILITIES) + 2);
2906
2907                 /* Get PMKID */
2908                 if (type == PMKID_LIST) {
2909                         *count = 1;
2910                         return pBuf;
2911                 }
2912         } else {
2913                 DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__));
2914                 return NULL;
2915         }
2916
2917         *count = 0;
2918         /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */
2919         return NULL;
2920
2921 }
2922
2923 void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len)
2924 {
2925         u8 *pSuite = NULL;
2926         u8 count;
2927
2928         hex_dump("RSNIE", rsnie, rsnie_len);
2929
2930         /* group cipher */
2931         pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count);
2932         if (pSuite != NULL) {
2933                 hex_dump("group cipher", pSuite, 4 * count);
2934         }
2935         /* pairwise cipher */
2936         pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count);
2937         if (pSuite != NULL) {
2938                 hex_dump("pairwise cipher", pSuite, 4 * count);
2939         }
2940         /* AKM */
2941         pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count);
2942         if (pSuite != NULL) {
2943                 hex_dump("AKM suite", pSuite, 4 * count);
2944         }
2945         /* PMKID */
2946         pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count);
2947         if (pSuite != NULL) {
2948                 hex_dump("PMKID", pSuite, LEN_PMKID);
2949         }
2950
2951 }
2952
2953 void RTMPInsertRSNIE(u8 *pFrameBuf,
2954                      unsigned long *pFrameLen,
2955                      u8 *rsnie_ptr,
2956                      u8 rsnie_len,
2957                      u8 *pmkid_ptr, u8 pmkid_len)
2958 {
2959         u8 *pTmpBuf;
2960         unsigned long TempLen = 0;
2961         u8 extra_len = 0;
2962         u16 pmk_count = 0;
2963         u8 ie_num;
2964         u8 total_len = 0;
2965         u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
2966
2967         pTmpBuf = pFrameBuf;
2968
2969         /* PMKID-List Must larger than 0 and the multiple of 16. */
2970         if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) {
2971                 extra_len = sizeof(u16)+ pmkid_len;
2972
2973                 pmk_count = (pmkid_len >> 4);
2974                 pmk_count = cpu2le16(pmk_count);
2975         } else {
2976                 DBGPRINT(RT_DEBUG_WARN,
2977                          ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
2978                           __func__, pmkid_len));
2979         }
2980
2981         if (rsnie_len != 0) {
2982                 ie_num = IE_WPA;
2983                 total_len = rsnie_len;
2984
2985                 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) {
2986                         ie_num = IE_RSN;
2987                         total_len += extra_len;
2988                 }
2989
2990                 /* construct RSNIE body */
2991                 MakeOutgoingFrame(pTmpBuf, &TempLen,
2992                                   1, &ie_num,
2993                                   1, &total_len,
2994                                   rsnie_len, rsnie_ptr, END_OF_ARGS);
2995
2996                 pTmpBuf += TempLen;
2997                 *pFrameLen = *pFrameLen + TempLen;
2998
2999                 if (ie_num == IE_RSN) {
3000                         /* Insert PMKID-List field */
3001                         if (extra_len > 0) {
3002                                 MakeOutgoingFrame(pTmpBuf, &TempLen,
3003                                                   2, &pmk_count,
3004                                                   pmkid_len, pmkid_ptr,
3005                                                   END_OF_ARGS);
3006
3007                                 pTmpBuf += TempLen;
3008                                 *pFrameLen = *pFrameLen + TempLen;
3009                         }
3010                 }
3011         }
3012
3013         return;
3014 }