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