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