2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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. *
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. *
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. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 Jan Lee 03-07-22 Initial
36 Paul Lin 03-11-28 Modify for supplicant
38 #include "../rt_config.h"
40 UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00};
41 UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01};
42 UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01};
43 UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02};
44 UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04};
45 UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05};
46 UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01};
47 UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02};
49 UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01};
50 UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02};
51 UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04};
52 UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01};
53 UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02};
54 UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05};
58 static VOID ConstructEapolKeyData(
59 IN PMAC_TABLE_ENTRY pEntry,
60 IN UCHAR GroupKeyWepStatus,
63 IN UCHAR DefaultKeyIdx,
67 OUT PEAPOL_PACKET pMsg);
69 static VOID CalculateMIC(
72 OUT PEAPOL_PACKET pMsg);
74 static VOID WpaEAPPacketAction(
76 IN MLME_QUEUE_ELEM *Elem);
78 static VOID WpaEAPOLASFAlertAction(
80 IN MLME_QUEUE_ELEM *Elem);
82 static VOID WpaEAPOLLogoffAction(
84 IN MLME_QUEUE_ELEM *Elem);
86 static VOID WpaEAPOLStartAction(
88 IN MLME_QUEUE_ELEM *Elem);
90 static VOID WpaEAPOLKeyAction(
92 IN MLME_QUEUE_ELEM *Elem);
95 ==========================================================================
97 association state machine init, including state transition and timer init
99 S - pointer to the association state machine
100 ==========================================================================
102 VOID WpaStateMachineInit(
103 IN PRTMP_ADAPTER pAd,
105 OUT STATE_MACHINE_FUNC Trans[])
107 StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE);
109 StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket, (STATE_MACHINE_FUNC)WpaEAPPacketAction);
110 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart, (STATE_MACHINE_FUNC)WpaEAPOLStartAction);
111 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff, (STATE_MACHINE_FUNC)WpaEAPOLLogoffAction);
112 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey, (STATE_MACHINE_FUNC)WpaEAPOLKeyAction);
113 StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert, (STATE_MACHINE_FUNC)WpaEAPOLASFAlertAction);
117 ==========================================================================
119 this is state machine function.
120 When receiving EAP packets which is for 802.1x authentication use.
123 ==========================================================================
125 VOID WpaEAPPacketAction(
126 IN PRTMP_ADAPTER pAd,
127 IN MLME_QUEUE_ELEM *Elem)
131 VOID WpaEAPOLASFAlertAction(
132 IN PRTMP_ADAPTER pAd,
133 IN MLME_QUEUE_ELEM *Elem)
137 VOID WpaEAPOLLogoffAction(
138 IN PRTMP_ADAPTER pAd,
139 IN MLME_QUEUE_ELEM *Elem)
144 ==========================================================================
146 Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
148 ==========================================================================
150 VOID WpaEAPOLStartAction(
151 IN PRTMP_ADAPTER pAd,
152 IN MLME_QUEUE_ELEM *Elem)
154 MAC_TABLE_ENTRY *pEntry;
155 PHEADER_802_11 pHeader;
157 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
159 pHeader = (PHEADER_802_11)Elem->Msg;
161 //For normaol PSK, we enqueue an EAPOL-Start command to trigger the process.
162 if (Elem->MsgLen == 6)
163 pEntry = MacTableLookup(pAd, Elem->Msg);
166 pEntry = MacTableLookup(pAd, pHeader->Addr2);
171 DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx));
173 if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
174 && (pEntry->WpaState < AS_PTKSTART)
175 && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND))))
177 pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
178 pEntry->WpaState = AS_INITPSK;
179 pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
180 NdisZeroMemory(pEntry->R_Counter, sizeof(pEntry->R_Counter));
181 pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
183 WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
189 ==========================================================================
191 This is state machine function.
192 When receiving EAPOL packets which is for 802.1x key management.
193 Use both in WPA, and WPAPSK case.
194 In this function, further dispatch to different functions according to the received packet. 3 categories are :
195 1. normal 4-way pairwisekey and 2-way groupkey handshake
196 2. MIC error (Countermeasures attack) report packet from STA.
197 3. Request for pairwise/group key update from STA
199 ==========================================================================
201 VOID WpaEAPOLKeyAction(
202 IN PRTMP_ADAPTER pAd,
203 IN MLME_QUEUE_ELEM *Elem)
205 MAC_TABLE_ENTRY *pEntry;
206 PHEADER_802_11 pHeader;
207 PEAPOL_PACKET pEapol_packet;
208 KEY_INFO peerKeyInfo;
210 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
212 pHeader = (PHEADER_802_11)Elem->Msg;
213 pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
215 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
216 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO));
218 hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
220 *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
224 pEntry = MacTableLookup(pAd, pHeader->Addr2);
226 if (!pEntry || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
229 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
232 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr)));
234 if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) ||
235 ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC)))
237 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
241 // The value 1 shall be used for all EAPOL-Key frames to and from a STA when
242 // neither the group nor pairwise ciphers are CCMP for Key Descriptor 1.
243 if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP))
245 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n"));
248 // The value 2 shall be used for all EAPOL-Key frames to and from a STA when
249 // either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2.
250 else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled) && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES))
252 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) \n"));
256 // Check if this STA is in class 3 state and the WPA state is started
257 if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK))
259 // Check the Key Ack (bit 7) of the Key Information to determine the Authenticator
261 // An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL-
262 // Key frame from the Authenticator must not have the Ack bit set.
263 if (peerKeyInfo.KeyAck == 1)
265 // The frame is snet by Authenticator.
266 // So the Supplicant side shall handle this.
268 if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) &&
269 (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY))
271 // Process 1. the message 1 of 4-way HS in WPA or WPA2
272 // EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1)
273 // 2. the message 3 of 4-way HS in WPA
274 // EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
275 if (peerKeyInfo.KeyMic == 0)
276 PeerPairMsg1Action(pAd, pEntry, Elem);
278 PeerPairMsg3Action(pAd, pEntry, Elem);
280 else if ((peerKeyInfo.Secure == 1) &&
281 (peerKeyInfo.KeyMic == 1) &&
282 (peerKeyInfo.Request == 0) &&
283 (peerKeyInfo.Error == 0))
285 // Process 1. the message 3 of 4-way HS in WPA2
286 // EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3)
287 // 2. the message 1 of group KS in WPA or WPA2
288 // EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N])
289 if (peerKeyInfo.KeyType == PAIRWISEKEY)
290 PeerPairMsg3Action(pAd, pEntry, Elem);
292 PeerGroupMsg1Action(pAd, pEntry, Elem);
297 // The frame is snet by Supplicant.
298 // So the Authenticator side shall handle this.
299 if ((peerKeyInfo.Request == 0) &&
300 (peerKeyInfo.Error == 0) &&
301 (peerKeyInfo.KeyMic == 1))
303 if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY)
305 // EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data)
306 // Process 1. message 2 of 4-way HS in WPA or WPA2
307 // 2. message 4 of 4-way HS in WPA
308 if (CONV_ARRARY_TO_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0)
310 PeerPairMsg4Action(pAd, pEntry, Elem);
314 PeerPairMsg2Action(pAd, pEntry, Elem);
317 else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY)
319 // EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0)
320 // Process message 4 of 4-way HS in WPA2
321 PeerPairMsg4Action(pAd, pEntry, Elem);
323 else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY)
325 // EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0)
326 // Process message 2 of Group key HS in WPA or WPA2
327 PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11));
336 ========================================================================
339 Copy frame from waiting queue into relative ring buffer and set
340 appropriate ASIC register to kick hardware encryption before really
344 pAd Pointer to our adapter
345 PNDIS_PACKET Pointer to outgoing Ndis frame
346 NumberOfFrag Number of fragment required
353 ========================================================================
355 VOID RTMPToWirelessSta(
356 IN PRTMP_ADAPTER pAd,
357 IN PMAC_TABLE_ENTRY pEntry,
358 IN PUCHAR pHeader802_3,
362 IN BOOLEAN bClearFrame)
364 PNDIS_PACKET pPacket;
367 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
371 // build a NDIS packet
372 Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
373 if (Status != NDIS_STATUS_SUCCESS)
378 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
380 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
382 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
384 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); // set a default value
385 if(pEntry->apidx != 0)
386 RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, pEntry->apidx);
388 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
389 RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
393 // send out the packet
394 Status = STASendPacket(pAd, pPacket);
395 if (Status == NDIS_STATUS_SUCCESS)
399 // Dequeue one frame from TxSwQueue0..3 queue and process it
400 // There are three place calling dequeue for TX ring.
401 // 1. Here, right after queueing the frame.
402 // 2. At the end of TxRingTxDone service routine.
403 // 3. Upon NDIS call RTMPSendPackets
404 if((!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
405 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
407 for(Index = 0; Index < 5; Index ++)
408 if(pAd->TxSwQueue[Index].Number > 0)
409 RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
418 ==========================================================================
420 This is a function to initilize 4-way handshake
424 ==========================================================================
427 IN PRTMP_ADAPTER pAd,
428 IN MAC_TABLE_ENTRY *pEntry,
429 IN ULONG TimeInterval)
431 UCHAR Header802_3[14];
432 EAPOL_PACKET EAPOLPKT;
433 PUINT8 pBssid = NULL;
434 UCHAR group_cipher = Ndis802_11WEPDisabled;
436 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
438 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
440 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
447 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
452 if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK))
454 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
459 // Increment replay counter by 1
460 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
462 // Randomly generate ANonce
463 GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce);
465 // Construct EAPoL message - Pairwise Msg 1
466 // EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1)
467 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
468 ConstructEapolMsg(pEntry,
471 0, // Default key index
480 // Make outgoing frame
481 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
482 RTMPToWirelessSta(pAd, pEntry, Header802_3,
483 LENGTH_802_3, (PUCHAR)&EAPOLPKT,
484 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4,
485 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
487 // Trigger Retry Timer
488 RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
491 pEntry->WpaState = AS_PTKSTART;
493 DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
498 ========================================================================
501 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
504 pAd Pointer to our adapter
512 ========================================================================
514 VOID PeerPairMsg1Action(
515 IN PRTMP_ADAPTER pAd,
516 IN MAC_TABLE_ENTRY *pEntry,
517 IN MLME_QUEUE_ELEM *Elem)
520 UCHAR Header802_3[14];
523 EAPOL_PACKET EAPOLPKT;
524 PUINT8 pCurrentAddr = NULL;
525 PUINT8 pmk_ptr = NULL;
526 UCHAR group_cipher = Ndis802_11WEPDisabled;
527 PUINT8 rsnie_ptr = NULL;
530 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
532 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
535 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
539 pCurrentAddr = pAd->CurrentAddress;
540 pmk_ptr = pAd->StaCfg.PMK;
541 group_cipher = pAd->StaCfg.GroupCipher;
542 rsnie_ptr = pAd->StaCfg.RSN_IE;
543 rsnie_len = pAd->StaCfg.RSNIE_Len;
546 // Store the received frame
547 pMsg1 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
548 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
550 // Sanity Check peer Pairwise message 1 - Replay Counter
551 if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE)
554 // Store Replay counter, it will use to verify message 3 and construct message 2
555 NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
558 NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
560 // Generate random SNonce
561 GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce);
564 // Calculate PTK(ANonce, SNonce)
574 // Save key to PTK entry
575 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
579 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
581 // Construct EAPoL message - Pairwise Msg 2
582 // EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2)
583 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
584 ConstructEapolMsg(pEntry,
595 // Make outgoing frame
596 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
598 RTMPToWirelessSta(pAd, pEntry,
599 Header802_3, sizeof(Header802_3), (PUCHAR)&EAPOLPKT,
600 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
602 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
607 ==========================================================================
609 When receiving the second packet of 4-way pairwisekey handshake.
611 ==========================================================================
613 VOID PeerPairMsg2Action(
614 IN PRTMP_ADAPTER pAd,
615 IN MAC_TABLE_ENTRY *pEntry,
616 IN MLME_QUEUE_ELEM *Elem)
620 PHEADER_802_11 pHeader;
621 EAPOL_PACKET EAPOLPKT;
624 UCHAR Header802_3[LENGTH_802_3];
626 PUINT8 pBssid = NULL;
627 PUINT8 pmk_ptr = NULL;
628 PUINT8 gtk_ptr = NULL;
629 UCHAR default_key = 0;
630 UCHAR group_cipher = Ndis802_11WEPDisabled;
631 PUINT8 rsnie_ptr = NULL;
634 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
636 if ((!pEntry) || (!pEntry->ValidAsCLI))
639 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
642 // check Entry in valid State
643 if (pEntry->WpaState < AS_PTKSTART)
648 // pointer to 802.11 header
649 pHeader = (PHEADER_802_11)Elem->Msg;
651 // skip 802.11_header(24-byte) and LLC_header(8)
652 pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
653 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
656 NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
662 pEntry->ANonce, // ANONCE
664 pEntry->SNonce, // SNONCE
669 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
672 // Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE
673 if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE)
678 // delete retry timer
679 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
682 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
684 // Increment replay counter by 1
685 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
687 // Construct EAPoL message - Pairwise Msg 3
688 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
689 ConstructEapolMsg(pEntry,
700 // Make outgoing frame
701 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
702 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
704 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4,
705 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
707 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
708 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
711 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
714 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
718 ========================================================================
721 Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
724 pAd Pointer to our adapter
732 ========================================================================
734 VOID PeerPairMsg3Action(
735 IN PRTMP_ADAPTER pAd,
736 IN MAC_TABLE_ENTRY *pEntry,
737 IN MLME_QUEUE_ELEM *Elem)
739 PHEADER_802_11 pHeader;
740 UCHAR Header802_3[14];
741 EAPOL_PACKET EAPOLPKT;
744 PUINT8 pCurrentAddr = NULL;
745 UCHAR group_cipher = Ndis802_11WEPDisabled;
747 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
749 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
752 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
756 pCurrentAddr = pAd->CurrentAddress;
757 group_cipher = pAd->StaCfg.GroupCipher;
761 // Record 802.11 header & the received EAPOL packet Msg3
762 pHeader = (PHEADER_802_11) Elem->Msg;
763 pMsg3 = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
764 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
766 // Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE
767 if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE)
770 // Save Replay counter, it will use construct message 4
771 NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
773 // Double check ANonce
774 if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
779 // Construct EAPoL message - Pairwise Msg 4
780 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
781 ConstructEapolMsg(pEntry,
784 0, // group key index not used in message 4
785 NULL, // Nonce not used in message 4
786 NULL, // TxRSC not used in message 4
787 NULL, // GTK not used in message 4
788 NULL, // RSN IE not used in message 4
793 pEntry->WpaState = AS_PTKINITDONE;
795 // Update pairwise key
797 PCIPHER_KEY pSharedKey;
799 pSharedKey = &pAd->SharedKey[BSS0][0];
801 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
803 // Prepare pair-wise key information into shared key table
804 NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
805 pSharedKey->KeyLen = LEN_TKIP_EK;
806 NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
807 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
808 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
810 // Decide its ChiperAlg
811 if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
812 pSharedKey->CipherAlg = CIPHER_TKIP;
813 else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
814 pSharedKey->CipherAlg = CIPHER_AES;
816 pSharedKey->CipherAlg = CIPHER_NONE;
818 // Update these related information to MAC_TABLE_ENTRY
819 pEntry = &pAd->MacTab.Content[BSSID_WCID];
820 NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32], LEN_TKIP_EK);
821 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48], LEN_TKIP_RXMICK);
822 NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pAd->StaCfg.PTK[48+LEN_TKIP_RXMICK], LEN_TKIP_TXMICK);
823 pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
825 // Update pairwise key information to ASIC Shared Key Table
826 AsicAddSharedKeyEntry(pAd,
829 pSharedKey->CipherAlg,
834 // Update ASIC WCID attribute table and IVEIV table
835 RTMPAddWcidAttributeEntry(pAd,
838 pSharedKey->CipherAlg,
843 // open 802.1x port control and privacy filter
844 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
845 pEntry->AuthMode == Ndis802_11AuthModeWPA2)
847 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
848 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
850 STA_PORT_SECURED(pAd);
851 // Indicate Connected for GUI
852 pAd->IndicateMediaState = NdisMediaStateConnected;
853 DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
854 GetAuthMode(pEntry->AuthMode),
855 GetEncryptType(pEntry->WepStatus),
856 GetEncryptType(group_cipher)));
862 // Init 802.3 header and send out
863 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
864 RTMPToWirelessSta(pAd, pEntry,
865 Header802_3, sizeof(Header802_3),
867 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
869 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
873 ==========================================================================
875 When receiving the last packet of 4-way pairwisekey handshake.
876 Initilize 2-way groupkey handshake following.
878 ==========================================================================
880 VOID PeerPairMsg4Action(
881 IN PRTMP_ADAPTER pAd,
882 IN MAC_TABLE_ENTRY *pEntry,
883 IN MLME_QUEUE_ELEM *Elem)
886 PHEADER_802_11 pHeader;
889 UCHAR group_cipher = Ndis802_11WEPDisabled;
891 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
895 if ((!pEntry) || (!pEntry->ValidAsCLI))
898 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2 ) )
901 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
905 // pointer to 802.11 header
906 pHeader = (PHEADER_802_11)Elem->Msg;
908 // skip 802.11_header(24-byte) and LLC_header(8)
909 pMsg4 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
910 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
912 // Sanity Check peer Pairwise message 4 - Replay Counter, MIC
913 if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
916 // 3. uses the MLME.SETKEYS.request to configure PTK into MAC
917 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
919 // reset IVEIV in Asic
920 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
922 pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
923 NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32], LEN_TKIP_EK);
924 NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[TKIP_AP_RXMICK_OFFSET], LEN_TKIP_RXMICK);
925 NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[TKIP_AP_TXMICK_OFFSET], LEN_TKIP_TXMICK);
927 // Set pairwise key to Asic
929 pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
930 if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
931 pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
932 else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
933 pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
935 // Add Pair-wise key to Asic
936 AsicAddPairwiseKeyEntry(
940 &pEntry->PairwiseKey);
942 // update WCID attribute table and IVEIV table for this entry
943 RTMPAddWcidAttributeEntry(
947 pEntry->PairwiseKey.CipherAlg,
952 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
953 pEntry->WpaState = AS_PTKINITDONE;
954 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
957 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
958 pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
960 pEntry->GTKState = REKEY_ESTABLISHED;
961 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
964 // send wireless event - for set key done WPA2
965 if (pAd->CommonCfg.bWirelessEvent)
966 RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
968 DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
969 pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
970 pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
972 GetEncryptType(group_cipher)));
976 // 5. init Group 2-way handshake if necessary.
977 WPAStart2WayGroupHS(pAd, pEntry);
979 pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
980 RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
987 ==========================================================================
989 This is a function to send the first packet of 2-way groupkey handshake
992 ==========================================================================
994 VOID WPAStart2WayGroupHS(
995 IN PRTMP_ADAPTER pAd,
996 IN MAC_TABLE_ENTRY *pEntry)
998 UCHAR Header802_3[14];
1000 EAPOL_PACKET EAPOLPKT;
1001 UCHAR group_cipher = Ndis802_11WEPDisabled;
1002 UCHAR default_key = 0;
1003 PUINT8 gnonce_ptr = NULL;
1004 PUINT8 gtk_ptr = NULL;
1005 PUINT8 pBssid = NULL;
1007 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1009 if ((!pEntry) || (!pEntry->ValidAsCLI))
1015 // Increment replay counter by 1
1016 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1018 // Construct EAPoL message - Group Msg 1
1019 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1020 ConstructEapolMsg(pEntry,
1024 (UCHAR *)gnonce_ptr,
1031 // Make outgoing frame
1032 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
1033 RTMPToWirelessSta(pAd, pEntry,
1034 Header802_3, LENGTH_802_3,
1036 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1042 DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
1048 ========================================================================
1050 Routine Description:
1051 Process Group key 2-way handshaking
1054 pAd Pointer to our adapter
1062 ========================================================================
1064 VOID PeerGroupMsg1Action(
1065 IN PRTMP_ADAPTER pAd,
1066 IN MAC_TABLE_ENTRY *pEntry,
1067 IN MLME_QUEUE_ELEM *Elem)
1069 UCHAR Header802_3[14];
1070 EAPOL_PACKET EAPOLPKT;
1071 PEAPOL_PACKET pGroup;
1074 UCHAR default_key = 0;
1075 UCHAR group_cipher = Ndis802_11WEPDisabled;
1076 PUINT8 pCurrentAddr = NULL;
1078 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1080 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
1084 pCurrentAddr = pAd->CurrentAddress;
1085 group_cipher = pAd->StaCfg.GroupCipher;
1086 default_key = pAd->StaCfg.DefaultKeyId;
1089 // Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8)
1090 pGroup = (PEAPOL_PACKET) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
1091 MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
1093 // Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE
1094 if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE)
1097 // delete retry timer
1098 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1100 // Save Replay counter, it will use to construct message 2
1101 NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1103 // Construct EAPoL message - Group Msg 2
1104 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1105 ConstructEapolMsg(pEntry,
1109 NULL, // Nonce not used
1110 NULL, // TxRSC not used
1111 NULL, // GTK not used
1112 NULL, // RSN IE not used
1116 // open 802.1x port control and privacy filter
1117 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1118 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1120 STA_PORT_SECURED(pAd);
1121 // Indicate Connected for GUI
1122 pAd->IndicateMediaState = NdisMediaStateConnected;
1124 DBGPRINT(RT_DEBUG_TRACE, ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
1125 GetAuthMode(pEntry->AuthMode),
1126 GetEncryptType(pEntry->WepStatus),
1127 GetEncryptType(group_cipher)));
1129 // init header and Fill Packet and send Msg 2 to authenticator
1130 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
1131 RTMPToWirelessSta(pAd, pEntry,
1132 Header802_3, sizeof(Header802_3),
1134 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1136 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: sned group message 2\n"));
1140 ==========================================================================
1142 When receiving the last packet of 2-way groupkey handshake.
1144 ==========================================================================
1146 VOID PeerGroupMsg2Action(
1147 IN PRTMP_ADAPTER pAd,
1148 IN MAC_TABLE_ENTRY *pEntry,
1155 PEAPOL_PACKET pMsg2;
1156 UCHAR group_cipher = Ndis802_11WEPDisabled;
1158 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1162 if ((!pEntry) || (!pEntry->ValidAsCLI))
1165 if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
1168 if (pEntry->WpaState != AS_PTKINITDONE)
1172 pData = (PUCHAR)Msg;
1173 pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H);
1174 Len = MsgLen - LENGTH_802_1_H;
1176 // Sanity Check peer group message 2 - Replay Counter, MIC
1177 if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1182 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1183 pEntry->GTKState = REKEY_ESTABLISHED;
1185 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
1187 // send wireless event - for set key done WPA2
1188 if (pAd->CommonCfg.bWirelessEvent)
1189 RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1191 DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1192 pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
1193 pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
1194 group_cipher, GetEncryptType(group_cipher)));
1198 // send wireless event - for set key done WPA
1199 if (pAd->CommonCfg.bWirelessEvent)
1200 RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA1_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
1202 DBGPRINT(RT_DEBUG_OFF, ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
1203 pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
1204 pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
1205 group_cipher, GetEncryptType(group_cipher)));
1211 ========================================================================
1213 Routine Description:
1214 Classify WPA EAP message type
1217 EAPType Value of EAP message type
1218 MsgType Internal Message definition for MLME state machine
1221 TRUE Found appropriate message type
1222 FALSE No appropriate message type
1224 IRQL = DISPATCH_LEVEL
1227 All these constants are defined in wpa.h
1228 For supplicant, there is only EAPOL Key message avaliable
1230 ========================================================================
1232 BOOLEAN WpaMsgTypeSubst(
1239 *MsgType = MT2_EAPPacket;
1242 *MsgType = MT2_EAPOLStart;
1245 *MsgType = MT2_EAPOLLogoff;
1248 *MsgType = MT2_EAPOLKey;
1251 *MsgType = MT2_EAPOLASFAlert;
1260 ========================================================================
1262 Routine Description:
1263 The pseudo-random function(PRF) that hashes various inputs to
1264 derive a pseudo-random value. To add liveness to the pseudo-random
1265 value, a nonce should be one of the inputs.
1267 It is used to generate PTK, GTK or some specific random value.
1270 UCHAR *key, - the key material for HMAC_SHA1 use
1271 INT key_len - the length of key
1272 UCHAR *prefix - a prefix label
1273 INT prefix_len - the length of the label
1274 UCHAR *data - a specific data with variable length
1275 INT data_len - the length of a specific data
1276 INT len - the output lenght
1279 UCHAR *output - the calculated result
1282 802.11i-2004 Annex H.3
1284 ========================================================================
1298 INT currentindex = 0;
1301 // Allocate memory for input
1302 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
1306 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
1310 // Generate concatenation input
1311 NdisMoveMemory(input, prefix, prefix_len);
1313 // Concatenate a single octet containing 0
1314 input[prefix_len] = 0;
1316 // Concatenate specific data
1317 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1318 total_len = prefix_len + 1 + data_len;
1320 // Concatenate a single octet containing 0
1321 // This octet shall be update later
1322 input[total_len] = 0;
1325 // Iterate to calculate the result by hmac-sha-1
1326 // Then concatenate to last result
1327 for (i = 0; i < (len + 19) / 20; i++)
1329 HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE);
1332 // update the last octet
1333 input[total_len - 1]++;
1335 os_free_mem(NULL, input);
1339 * F(P, S, c, i) = U1 xor U2 xor ... Uc
1340 * U1 = PRF(P, S || Int(i))
1345 static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
1347 unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
1350 /* U1 = PRF(P, S || int(i)) */
1351 memcpy(digest, ssid, ssidlength);
1352 digest[ssidlength] = (unsigned char)((count>>24) & 0xff);
1353 digest[ssidlength+1] = (unsigned char)((count>>16) & 0xff);
1354 digest[ssidlength+2] = (unsigned char)((count>>8) & 0xff);
1355 digest[ssidlength+3] = (unsigned char)(count & 0xff);
1356 HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest, ssidlength+4, digest1, SHA1_DIGEST_SIZE); // for WPA update
1359 memcpy(output, digest1, SHA1_DIGEST_SIZE);
1361 for (i = 1; i < iterations; i++)
1363 /* Un = PRF(P, Un-1) */
1364 HMAC_SHA1((unsigned char*) password, (int) strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); // for WPA update
1365 memcpy(digest1, digest, SHA1_DIGEST_SIZE);
1367 /* output = output xor Un */
1368 for (j = 0; j < SHA1_DIGEST_SIZE; j++)
1370 output[j] ^= digest[j];
1376 * password - ascii string up to 63 characters in length
1377 * ssid - octet string up to 32 octets
1378 * ssidlength - length of ssid in octets
1379 * output must be 40 octets in length and outputs 256 bits of key
1381 int PasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output)
1383 if ((strlen(password) > 63) || (ssidlength > 32))
1386 F(password, ssid, ssidlength, 4096, 1, output);
1387 F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1394 ========================================================================
1396 Routine Description:
1397 It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
1398 It shall be called by 4-way handshake processing.
1401 pAd - pointer to our pAdapter context
1402 PMK - pointer to PMK
1403 ANonce - pointer to ANonce
1404 AA - pointer to Authenticator Address
1405 SNonce - pointer to SNonce
1406 SA - pointer to Supplicant Address
1407 len - indicate the length of PTK (octet)
1410 Output pointer to the PTK
1413 Refer to IEEE 802.11i-2004 8.5.1.2
1415 ========================================================================
1418 IN PRTMP_ADAPTER pAd,
1427 UCHAR concatenation[76];
1430 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1431 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
1433 // initiate the concatenation input
1434 NdisZeroMemory(temp, sizeof(temp));
1435 NdisZeroMemory(concatenation, 76);
1437 // Get smaller address
1438 if (RTMPCompareMemory(SA, AA, 6) == 1)
1439 NdisMoveMemory(concatenation, AA, 6);
1441 NdisMoveMemory(concatenation, SA, 6);
1444 // Get larger address
1445 if (RTMPCompareMemory(SA, AA, 6) == 1)
1446 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1448 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1450 // store the larger mac address for backward compatible of
1451 // ralink proprietary STA-key issue
1452 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
1455 // Get smaller Nonce
1456 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1457 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
1458 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1459 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1461 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1465 if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
1466 NdisMoveMemory(&concatenation[CurrPos], temp, 32); // patch for ralink proprietary STA-key issue
1467 else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
1468 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
1470 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1473 hex_dump("concatenation=", concatenation, 76);
1475 // Use PRF to generate PTK
1476 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1481 ========================================================================
1483 Routine Description:
1484 Generate random number by software.
1487 pAd - pointer to our pAdapter context
1488 macAddr - pointer to local MAC address
1493 802.1ii-2004 Annex H.5
1495 ========================================================================
1498 IN PRTMP_ADAPTER pAd,
1503 UCHAR local[80], KeyCounter[32];
1506 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
1508 // Zero the related information
1509 NdisZeroMemory(result, 80);
1510 NdisZeroMemory(local, 80);
1511 NdisZeroMemory(KeyCounter, 32);
1513 for (i = 0; i < 32; i++)
1515 // copy the local MAC address
1516 COPY_MAC_ADDR(local, macAddr);
1517 curr = MAC_ADDR_LEN;
1519 // concatenate the current time
1520 NdisGetSystemUpTime(&CurrentTime);
1521 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1522 curr += sizeof(CurrentTime);
1524 // concatenate the last result
1525 NdisMoveMemory(&local[curr], result, 32);
1528 // concatenate a variable
1529 NdisMoveMemory(&local[curr], &i, 2);
1532 // calculate the result
1533 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
1536 NdisMoveMemory(random, result, 32);
1540 ========================================================================
1542 Routine Description:
1543 Build cipher suite in RSN-IE.
1544 It only shall be called by RTMPMakeRSNIE.
1547 pAd - pointer to our pAdapter context
1548 ElementID - indicate the WPA1 or WPA2
1549 WepStatus - indicate the encryption type
1550 bMixCipher - a boolean to indicate the pairwise cipher and group
1551 cipher are the same or not
1557 ========================================================================
1559 static VOID RTMPMakeRsnIeCipher(
1560 IN PRTMP_ADAPTER pAd,
1563 IN BOOLEAN bMixCipher,
1564 IN UCHAR FlexibleCipher,
1572 // decide WPA2 or WPA1
1573 if (ElementID == Wpa2Ie)
1575 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
1577 // Assign the verson as 1
1578 pRsnie_cipher->version = 1;
1583 case Ndis802_11Encryption2Enabled:
1584 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1585 pRsnie_cipher->ucount = 1;
1586 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
1587 *rsn_len = sizeof(RSNIE2);
1591 case Ndis802_11Encryption3Enabled:
1593 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1595 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4);
1596 pRsnie_cipher->ucount = 1;
1597 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
1598 *rsn_len = sizeof(RSNIE2);
1601 // TKIP-AES mix mode
1602 case Ndis802_11Encryption4Enabled:
1603 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1606 // Insert WPA2 TKIP as the first pairwise cipher
1607 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
1609 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4);
1610 // Insert WPA2 AES as the secondary pairwise cipher
1611 if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher))
1613 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
1619 // Insert WPA2 AES as the first pairwise cipher
1620 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
1623 pRsnie_cipher->ucount = PairwiseCnt;
1624 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
1628 if ((pAd->OpMode == OPMODE_STA) &&
1629 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1630 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1632 UINT GroupCipher = pAd->StaCfg.GroupCipher;
1635 case Ndis802_11GroupWEP40Enabled:
1636 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
1638 case Ndis802_11GroupWEP104Enabled:
1639 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
1644 // swap for big-endian platform
1645 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1646 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1650 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
1652 // Assign OUI and version
1653 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
1654 pRsnie_cipher->version = 1;
1659 case Ndis802_11Encryption2Enabled:
1660 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1661 pRsnie_cipher->ucount = 1;
1662 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
1663 *rsn_len = sizeof(RSNIE);
1667 case Ndis802_11Encryption3Enabled:
1669 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1671 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4);
1672 pRsnie_cipher->ucount = 1;
1673 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
1674 *rsn_len = sizeof(RSNIE);
1677 // TKIP-AES mix mode
1678 case Ndis802_11Encryption4Enabled:
1679 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1682 // Insert WPA TKIP as the first pairwise cipher
1683 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
1685 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4);
1686 // Insert WPA AES as the secondary pairwise cipher
1687 if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher))
1689 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
1695 // Insert WPA AES as the first pairwise cipher
1696 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
1699 pRsnie_cipher->ucount = PairwiseCnt;
1700 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
1704 if ((pAd->OpMode == OPMODE_STA) &&
1705 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1706 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1708 UINT GroupCipher = pAd->StaCfg.GroupCipher;
1711 case Ndis802_11GroupWEP40Enabled:
1712 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
1714 case Ndis802_11GroupWEP104Enabled:
1715 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
1720 // swap for big-endian platform
1721 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1722 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1727 ========================================================================
1729 Routine Description:
1730 Build AKM suite in RSN-IE.
1731 It only shall be called by RTMPMakeRSNIE.
1734 pAd - pointer to our pAdapter context
1735 ElementID - indicate the WPA1 or WPA2
1736 AuthMode - indicate the authentication mode
1737 apidx - indicate the interface index
1743 ========================================================================
1745 static VOID RTMPMakeRsnIeAKM(
1746 IN PRTMP_ADAPTER pAd,
1753 RSNIE_AUTH *pRsnie_auth;
1754 UCHAR AkmCnt = 1; // default as 1
1756 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
1758 // decide WPA2 or WPA1
1759 if (ElementID == Wpa2Ie)
1764 case Ndis802_11AuthModeWPA2:
1765 case Ndis802_11AuthModeWPA1WPA2:
1766 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
1769 case Ndis802_11AuthModeWPA2PSK:
1770 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1771 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
1783 case Ndis802_11AuthModeWPA:
1784 case Ndis802_11AuthModeWPA1WPA2:
1785 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
1788 case Ndis802_11AuthModeWPAPSK:
1789 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1790 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
1793 case Ndis802_11AuthModeWPANone:
1794 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
1802 pRsnie_auth->acount = AkmCnt;
1803 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1805 // update current RSNIE length
1806 (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1)));
1811 ========================================================================
1813 Routine Description:
1814 Build capability in RSN-IE.
1815 It only shall be called by RTMPMakeRSNIE.
1818 pAd - pointer to our pAdapter context
1819 ElementID - indicate the WPA1 or WPA2
1820 apidx - indicate the interface index
1826 ========================================================================
1828 static VOID RTMPMakeRsnIeCap(
1829 IN PRTMP_ADAPTER pAd,
1835 RSN_CAPABILITIES *pRSN_Cap;
1837 // it could be ignored in WPA1 mode
1838 if (ElementID == WpaIe)
1841 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
1844 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1846 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
1852 ========================================================================
1854 Routine Description:
1855 Build RSN IE context. It is not included element-ID and length.
1858 pAd - pointer to our pAdapter context
1859 AuthMode - indicate the authentication mode
1860 WepStatus - indicate the encryption type
1861 apidx - indicate the interface index
1867 ========================================================================
1870 IN PRTMP_ADAPTER pAd,
1875 PUCHAR pRsnIe = NULL; // primary RSNIE
1876 UCHAR *rsnielen_cur_p = 0; // the length of the primary RSNIE
1877 UCHAR *rsnielen_ex_cur_p = 0; // the length of the secondary RSNIE
1879 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
1881 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
1883 rsnielen_cur_p = NULL;
1884 rsnielen_ex_cur_p = NULL;
1888 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
1890 if (AuthMode < Ndis802_11AuthModeWPA)
1895 // Support WPAPSK or WPA2PSK in STA-Infra mode
1896 // Support WPANone in STA-Adhoc mode
1897 if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
1898 (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
1899 (AuthMode != Ndis802_11AuthModeWPANone)
1904 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
1906 // Zero RSNIE context
1907 pAd->StaCfg.RSNIE_Len = 0;
1908 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1911 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1912 pRsnIe = pAd->StaCfg.RSN_IE;
1914 bMixCipher = pAd->StaCfg.bMixCipher;
1918 // indicate primary RSNIE as WPA or WPA2
1919 if ((AuthMode == Ndis802_11AuthModeWPA) ||
1920 (AuthMode == Ndis802_11AuthModeWPAPSK) ||
1921 (AuthMode == Ndis802_11AuthModeWPANone) ||
1922 (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
1923 (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
1924 PrimaryRsnie = WpaIe;
1926 PrimaryRsnie = Wpa2Ie;
1929 // Build the primary RSNIE
1930 // 1. insert cipher suite
1931 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
1934 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
1936 // 3. insert capability
1937 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1940 // 4. update the RSNIE length
1941 *rsnielen_cur_p = p_offset;
1943 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1949 ==========================================================================
1951 Check whether the received frame is EAP frame.
1954 pAd - pointer to our pAdapter context
1955 pEntry - pointer to active entry
1956 pData - the received frame
1957 DataByteCount - the received frame's length
1958 FromWhichBSSID - indicate the interface index
1961 TRUE - This frame is EAP frame
1963 ==========================================================================
1965 BOOLEAN RTMPCheckWPAframe(
1966 IN PRTMP_ADAPTER pAd,
1967 IN PMAC_TABLE_ENTRY pEntry,
1969 IN ULONG DataByteCount,
1970 IN UCHAR FromWhichBSSID)
1976 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
1981 if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
1982 // Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL
1983 NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6))
1987 // Skip 2-bytes EAPoL type
1988 if (NdisEqualMemory(EAPOL, pData, 2))
1998 Body_len = (*(pData+2)<<8) | (*(pData+3));
1999 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
2002 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
2003 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2005 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
2006 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2007 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2011 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
2014 Body_len = (*(pData+2)<<8) | (*(pData+3));
2015 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
2018 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
2028 ==========================================================================
2030 Report the EAP message type
2033 msg - EAPOL_PAIR_MSG_1
2043 ==========================================================================
2045 PSTRING GetEapolMsgType(CHAR msg)
2047 if(msg == EAPOL_PAIR_MSG_1)
2048 return "Pairwise Message 1";
2049 else if(msg == EAPOL_PAIR_MSG_2)
2050 return "Pairwise Message 2";
2051 else if(msg == EAPOL_PAIR_MSG_3)
2052 return "Pairwise Message 3";
2053 else if(msg == EAPOL_PAIR_MSG_4)
2054 return "Pairwise Message 4";
2055 else if(msg == EAPOL_GROUP_MSG_1)
2056 return "Group Message 1";
2057 else if(msg == EAPOL_GROUP_MSG_2)
2058 return "Group Message 2";
2060 return "Invalid Message";
2065 ========================================================================
2067 Routine Description:
2068 Check Sanity RSN IE of EAPoL message
2075 ========================================================================
2077 BOOLEAN RTMPCheckRSNIE(
2078 IN PRTMP_ADAPTER pAd,
2081 IN MAC_TABLE_ENTRY *pEntry,
2087 BOOLEAN result = FALSE;
2093 while (len > sizeof(RSNIE2))
2095 pEid = (PEID_STRUCT) pVIE;
2097 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
2099 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) &&
2100 (NdisEqualMemory(pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len)) &&
2101 (pEntry->RSNIE_Len == (pEid->Len + 2)))
2106 *Offset += (pEid->Len + 2);
2109 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
2111 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) &&
2112 (pEid->Eid == pEntry->RSN_IE[0]) &&
2113 ((pEid->Len + 2) >= pEntry->RSNIE_Len) &&
2114 (NdisEqualMemory(pEid->Octet, &pEntry->RSN_IE[2], pEntry->RSNIE_Len - 2)))
2120 *Offset += (pEid->Len + 2);
2127 pVIE += (pEid->Len + 2);
2128 len -= (pEid->Len + 2);
2137 ========================================================================
2139 Routine Description:
2140 Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
2141 GTK is encaptulated in KDE format at p.83 802.11i D10
2150 ========================================================================
2152 BOOLEAN RTMPParseEapolKeyData(
2153 IN PRTMP_ADAPTER pAd,
2155 IN UCHAR KeyDataLen,
2156 IN UCHAR GroupKeyIndex,
2159 IN MAC_TABLE_ENTRY *pEntry)
2161 PKDE_ENCAP pKDE = NULL;
2162 PUCHAR pMyKeyData = pKeyData;
2163 UCHAR KeyDataLength = KeyDataLen;
2165 UCHAR DefaultIdx = 0;
2168 // Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it
2169 if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3)
2171 // Check RSN IE whether it is WPA2/WPA2PSK
2172 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
2174 // send wireless event - for RSN IE different
2175 if (pAd->CommonCfg.bWirelessEvent)
2176 RTMPSendWirelessEvent(pAd, IW_RSNIE_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
2178 DBGPRINT(RT_DEBUG_ERROR, ("RSN_IE Different in msg %d of 4-way handshake!\n", MsgType));
2179 hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
2180 hex_dump("Desired RSN_IE ", pEntry->RSN_IE, pEntry->RSNIE_Len);
2186 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
2188 WpaShowAllsuite(pMyKeyData, skip_offset);
2191 pMyKeyData += skip_offset;
2192 KeyDataLength -= skip_offset;
2193 DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset));
2200 DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
2201 //hex_dump("remain data", pMyKeyData, KeyDataLength);
2204 // Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2
2205 if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1))
2207 if (KeyDataLength >= 8) // KDE format exclude GTK length
2209 pKDE = (PKDE_ENCAP) pMyKeyData;
2212 DefaultIdx = pKDE->GTKEncap.Kid;
2214 // Sanity check - KED length
2215 if (KeyDataLength < (pKDE->Len + 2))
2217 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
2221 // Get GTK length - refer to IEEE 802.11i-2004 p.82
2222 GTKLEN = pKDE->Len -6;
2223 if (GTKLEN < LEN_AES_KEY)
2225 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
2232 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
2236 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
2242 else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
2244 DefaultIdx = GroupKeyIndex;
2245 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
2248 // Sanity check - shared key index must be 1 ~ 3
2249 if (DefaultIdx < 1 || DefaultIdx > 3)
2251 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2256 PCIPHER_KEY pSharedKey;
2258 // set key material, TxMic and RxMic
2259 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2260 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2262 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
2264 // Prepare pair-wise key information into shared key table
2265 NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
2266 pSharedKey->KeyLen = LEN_TKIP_EK;
2267 NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
2268 NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16], LEN_TKIP_RXMICK);
2269 NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24], LEN_TKIP_TXMICK);
2271 // Update Shared Key CipherAlg
2272 pSharedKey->CipherAlg = CIPHER_NONE;
2273 if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
2274 pSharedKey->CipherAlg = CIPHER_TKIP;
2275 else if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)
2276 pSharedKey->CipherAlg = CIPHER_AES;
2277 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
2278 pSharedKey->CipherAlg = CIPHER_WEP64;
2279 else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP104Enabled)
2280 pSharedKey->CipherAlg = CIPHER_WEP128;
2283 // Update group key information to ASIC Shared Key Table
2284 AsicAddSharedKeyEntry(pAd,
2286 pAd->StaCfg.DefaultKeyId,
2287 pSharedKey->CipherAlg,
2292 // Update ASIC WCID attribute table and IVEIV table
2293 RTMPAddWcidAttributeEntry(pAd,
2295 pAd->StaCfg.DefaultKeyId,
2296 pSharedKey->CipherAlg,
2306 ========================================================================
2308 Routine Description:
2309 Construct EAPoL message for WPA handshaking
2310 Its format is below,
2312 +--------------------+
2313 | Protocol Version | 1 octet
2314 +--------------------+
2315 | Protocol Type | 1 octet
2316 +--------------------+
2317 | Body Length | 2 octets
2318 +--------------------+
2319 | Descriptor Type | 1 octet
2320 +--------------------+
2321 | Key Information | 2 octets
2322 +--------------------+
2323 | Key Length | 1 octet
2324 +--------------------+
2325 | Key Repaly Counter | 8 octets
2326 +--------------------+
2327 | Key Nonce | 32 octets
2328 +--------------------+
2329 | Key IV | 16 octets
2330 +--------------------+
2331 | Key RSC | 8 octets
2332 +--------------------+
2333 | Key ID or Reserved | 8 octets
2334 +--------------------+
2335 | Key MIC | 16 octets
2336 +--------------------+
2337 | Key Data Length | 2 octets
2338 +--------------------+
2339 | Key Data | n octets
2340 +--------------------+
2344 pAd Pointer to our adapter
2351 ========================================================================
2353 VOID ConstructEapolMsg(
2354 IN PMAC_TABLE_ENTRY pEntry,
2355 IN UCHAR GroupKeyWepStatus,
2357 IN UCHAR DefaultKeyIdx,
2363 OUT PEAPOL_PACKET pMsg)
2365 BOOLEAN bWPA2 = FALSE;
2368 // Choose WPA2 or not
2369 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2370 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2373 // Init Packet and Fill header
2374 pMsg->ProVer = EAPOL_VER;
2375 pMsg->ProType = EAPOLKey;
2377 // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
2378 SET_UINT16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
2380 // Fill in EAPoL descriptor
2382 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2384 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2386 // Key Descriptor Version (bits 0-2) specifies the key descriptor version type
2388 // Fill in Key information, refer to IEEE Std 802.11i-2004 page 78
2389 // When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used.
2390 KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) ||
2391 (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
2394 pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2396 // Specify Key Type as Group(0) or Pairwise(1)
2397 if (MsgType >= EAPOL_GROUP_MSG_1)
2398 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
2400 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2402 // Specify Key Index, only group_msg1_WPA1
2403 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2404 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2406 if (MsgType == EAPOL_PAIR_MSG_3)
2407 pMsg->KeyDesc.KeyInfo.Install = 1;
2409 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
2410 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2412 if (MsgType != EAPOL_PAIR_MSG_1)
2413 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2415 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
2416 (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
2418 pMsg->KeyDesc.KeyInfo.Secure = 1;
2421 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
2422 (MsgType == EAPOL_GROUP_MSG_1)))
2424 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2427 // key Information element has done.
2428 *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
2430 // Fill in Key Length
2432 if (MsgType >= EAPOL_GROUP_MSG_1)
2434 // the length of group key cipher
2435 pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
2439 // the length of pairwise key cipher
2440 pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
2444 // Fill in replay counter
2445 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
2447 // Fill Key Nonce field
2448 // ANonce : pairwise_msg1 & pairwise_msg3
2449 // SNonce : pairwise_msg2
2450 // GNonce : group_msg1_wpa1
2451 if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
2452 NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE);
2454 // Fill key IV - WPA2 as 0, WPA1 as random
2455 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
2457 // Suggest IV be random number plus some number,
2458 NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
2459 pMsg->KeyDesc.KeyIv[15] += 2;
2462 // Fill Key RSC field
2463 // It contains the RSC for the GTK being installed.
2464 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
2466 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2469 // Clear Key MIC field for MIC calculation later
2470 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
2472 ConstructEapolKeyData(pEntry,
2482 // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
2483 if (MsgType != EAPOL_PAIR_MSG_1)
2485 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
2488 DBGPRINT(RT_DEBUG_TRACE, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2489 DBGPRINT(RT_DEBUG_TRACE, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len)));
2490 DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyLength)));
2496 ========================================================================
2498 Routine Description:
2499 Construct the Key Data field of EAPoL message
2502 pAd Pointer to our adapter
2510 ========================================================================
2512 VOID ConstructEapolKeyData(
2513 IN PMAC_TABLE_ENTRY pEntry,
2514 IN UCHAR GroupKeyWepStatus,
2515 IN UCHAR keyDescVer,
2517 IN UCHAR DefaultKeyIdx,
2521 OUT PEAPOL_PACKET pMsg)
2523 UCHAR *mpool, *Key_Data, *Rc4GTK;
2524 UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
2526 BOOLEAN bWPA2Capable = FALSE;
2527 PRTMP_ADAPTER pAd = pEntry->pAd;
2528 BOOLEAN GTK_Included = FALSE;
2530 // Choose WPA2 or not
2531 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2532 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2533 bWPA2Capable = TRUE;
2535 if (MsgType == EAPOL_PAIR_MSG_1 ||
2536 MsgType == EAPOL_PAIR_MSG_4 ||
2537 MsgType == EAPOL_GROUP_MSG_2)
2540 // allocate memory pool
2541 os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500);
2546 /* Rc4GTK Len = 512 */
2547 Rc4GTK = (UCHAR *) ROUND_UP(mpool, 4);
2548 /* Key_Data Len = 512 */
2549 Key_Data = (UCHAR *) ROUND_UP(Rc4GTK + 512, 4);
2551 NdisZeroMemory(Key_Data, 512);
2552 SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
2555 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
2556 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
2558 PUINT8 pmkid_ptr = NULL;
2559 UINT8 pmkid_len = 0;
2562 RTMPInsertRSNIE(&Key_Data[data_offset],
2571 // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
2572 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
2574 // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
2575 Key_Data[data_offset + 0] = 0xDD;
2577 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2579 Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
2583 Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
2586 Key_Data[data_offset + 2] = 0x00;
2587 Key_Data[data_offset + 3] = 0x0F;
2588 Key_Data[data_offset + 4] = 0xAC;
2589 Key_Data[data_offset + 5] = 0x01;
2591 // GTK KDE format - 802.11i-2004 Figure-43x
2592 Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
2593 Key_Data[data_offset + 7] = 0x00; // Reserved Byte
2600 // Only for pairwise_msg3_WPA2 and group_msg1
2601 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
2604 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2606 NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
2607 data_offset += LEN_AES_KEY;
2611 NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
2612 data_offset += TKIP_GTK_LENGTH;
2615 GTK_Included = TRUE;
2619 // This whole key-data field shall be encrypted if a GTK is included.
2620 // Encrypt the data material in key data field with KEK
2623 //hex_dump("GTK_Included", Key_Data, data_offset);
2626 (keyDescVer == DESC_TYPE_AES))
2628 UCHAR remainder = 0;
2631 // Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394,
2632 // shall be used to encrypt the Key Data field using the KEK field from
2635 // If the Key Data field uses the NIST AES key wrap, then the Key Data field
2636 // shall be padded before encrypting if the key data length is less than 16
2637 // octets or if it is not a multiple of 8. The padding consists of appending
2638 // a single octet 0xdd followed by zero or more 0x00 octets.
2639 if ((remainder = data_offset & 0x07) != 0)
2643 pad_len = (8 - remainder);
2644 Key_Data[data_offset] = 0xDD;
2645 for (i = 1; i < pad_len; i++)
2646 Key_Data[data_offset + i] = 0;
2648 data_offset += pad_len;
2651 AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, data_offset, Rc4GTK);
2652 // AES wrap function will grow 8 bytes in length
2657 /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2658 using the KEK field from the derived PTK. */
2660 // PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV)
2661 // put TxTsc in Key RSC field
2662 pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; //Init crc32.
2664 // ekey is the contanetion of IV-field, and PTK[16]->PTK[31]
2665 NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv, LEN_KEY_DESC_IV);
2666 NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16], LEN_EAP_EK);
2667 ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); //INIT SBOX, KEYLEN+3(IV)
2668 pAd->PrivateInfo.FCSCRC32 = RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data, data_offset);
2669 WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK, Key_Data, data_offset);
2672 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
2676 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
2679 // Update key data length field and total body length
2680 SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
2681 INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset);
2683 os_free_mem(NULL, mpool);
2688 ========================================================================
2690 Routine Description:
2691 Calcaulate MIC. It is used during 4-ways handsharking.
2694 pAd - pointer to our pAdapter context
2695 PeerWepStatus - indicate the encryption type
2701 ========================================================================
2703 static VOID CalculateMIC(
2704 IN UCHAR KeyDescVer,
2706 OUT PEAPOL_PACKET pMsg)
2710 UCHAR mic[LEN_KEY_DESC_MIC];
2713 // allocate memory for MIC calculation
2714 os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512);
2716 if (OutBuffer == NULL)
2718 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
2722 // make a frame for calculating MIC.
2723 MakeOutgoingFrame(OutBuffer, &FrameLen,
2724 CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4, pMsg,
2727 NdisZeroMemory(mic, sizeof(mic));
2730 if (KeyDescVer == DESC_TYPE_AES)
2732 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
2733 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
2737 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
2740 // store the calculated MIC
2741 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2743 os_free_mem(NULL, OutBuffer);
2747 ========================================================================
2749 Routine Description:
2750 Some received frames can't decrypt by Asic, so decrypt them by software.
2753 pAd - pointer to our pAdapter context
2754 PeerWepStatus - indicate the encryption type
2757 NDIS_STATUS_SUCCESS - decryption successful
2758 NDIS_STATUS_FAILURE - decryption failure
2760 ========================================================================
2762 NDIS_STATUS RTMPSoftDecryptBroadCastData(
2763 IN PRTMP_ADAPTER pAd,
2765 IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
2766 IN PCIPHER_KEY pShard_key)
2768 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
2772 // handle WEP decryption
2773 if (GroupCipher == Ndis802_11Encryption1Enabled)
2775 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
2778 //Minus IV[4] & ICV[4]
2779 pRxWI->MPDUtotalByteCount -= 8;
2783 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
2784 // give up this frame
2785 return NDIS_STATUS_FAILURE;
2788 // handle TKIP decryption
2789 else if (GroupCipher == Ndis802_11Encryption2Enabled)
2791 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
2794 //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
2795 pRxWI->MPDUtotalByteCount -= 20;
2799 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
2800 // give up this frame
2801 return NDIS_STATUS_FAILURE;
2804 // handle AES decryption
2805 else if (GroupCipher == Ndis802_11Encryption3Enabled)
2807 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
2810 //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
2811 pRxWI->MPDUtotalByteCount -= 16;
2815 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
2816 // give up this frame
2817 return NDIS_STATUS_FAILURE;
2822 // give up this frame
2823 return NDIS_STATUS_FAILURE;
2826 return NDIS_STATUS_SUCCESS;
2831 PUINT8 GetSuiteFromRSNIE(
2843 BOOLEAN isWPA2 = FALSE;
2845 pEid = (PEID_STRUCT)rsnie;
2846 len = rsnie_len - 2; // exclude IE and length
2847 pBuf = (PUINT8)&pEid->Octet[0];
2851 // set default value
2855 if ((len <= 0) || (pEid->Len != len))
2857 DBGPRINT_ERR(("%s : The length is invalid\n", __func__));
2861 // Check WPA or WPA2
2862 if (pEid->Eid == IE_WPA)
2864 PRSNIE pRsnie = (PRSNIE)pBuf;
2867 if (len < sizeof(RSNIE))
2869 DBGPRINT_ERR(("%s : The length is too short for WPA\n", __func__));
2873 // Get the count of pairwise cipher
2874 ucount = cpu2le16(pRsnie->ucount);
2877 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2882 // Get the group cipher
2883 if (type == GROUP_SUITE)
2886 return pRsnie->mcast;
2888 // Get the pairwise cipher suite
2889 else if (type == PAIRWISE_SUITE)
2891 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2894 return pRsnie->ucast[0].oui;
2897 offset = sizeof(RSNIE) + (4 * (ucount - 1));
2900 else if (pEid->Eid == IE_RSN)
2902 PRSNIE2 pRsnie = (PRSNIE2)pBuf;
2907 if (len < sizeof(RSNIE2))
2909 DBGPRINT_ERR(("%s : The length is too short for WPA2\n", __func__));
2913 // Get the count of pairwise cipher
2914 ucount = cpu2le16(pRsnie->ucount);
2917 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2922 // Get the group cipher
2923 if (type == GROUP_SUITE)
2926 return pRsnie->mcast;
2928 // Get the pairwise cipher suite
2929 else if (type == PAIRWISE_SUITE)
2931 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2934 return pRsnie->ucast[0].oui;
2937 offset = sizeof(RSNIE2) + (4 * (ucount - 1));
2942 DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __func__, pEid->Eid));
2946 // skip group cipher and pairwise cipher suite
2950 if (len < sizeof(RSNIE_AUTH))
2952 DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", __func__));
2956 // pointer to AKM count
2957 pAkm = (PRSNIE_AUTH)pBuf;
2959 // Get the count of pairwise cipher
2960 acount = cpu2le16(pAkm->acount);
2963 DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
2968 // Get the AKM suite
2969 if (type == AKM_SUITE)
2971 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
2974 return pAkm->auth[0].oui;
2976 offset = sizeof(RSNIE_AUTH) + (4 * (acount - 1));
2981 // The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~))
2982 if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID))
2984 // Skip RSN capability and PMKID-Count
2985 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
2986 len -= (sizeof(RSN_CAPABILITIES) + 2);
2989 if (type == PMKID_LIST)
2997 DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __func__));
3002 //DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type));
3007 VOID WpaShowAllsuite(
3011 PUINT8 pSuite = NULL;
3014 hex_dump("RSNIE", rsnie, rsnie_len);
3017 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL)
3019 hex_dump("group cipher", pSuite, 4*count);
3023 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL)
3025 hex_dump("pairwise cipher", pSuite, 4*count);
3029 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL)
3031 hex_dump("AKM suite", pSuite, 4*count);
3035 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL)
3037 hex_dump("PMKID", pSuite, LEN_PMKID);
3042 VOID RTMPInsertRSNIE(
3043 IN PUCHAR pFrameBuf,
3044 OUT PULONG pFrameLen,
3045 IN PUINT8 rsnie_ptr,
3047 IN PUINT8 pmkid_ptr,
3052 UINT8 extra_len = 0;
3053 UINT16 pmk_count = 0;
3055 UINT8 total_len = 0;
3056 UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
3058 pTmpBuf = pFrameBuf;
3060 /* PMKID-List Must larger than 0 and the multiple of 16. */
3061 if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0))
3063 extra_len = sizeof(UINT16) + pmkid_len;
3065 pmk_count = (pmkid_len >> 4);
3066 pmk_count = cpu2le16(pmk_count);
3070 DBGPRINT(RT_DEBUG_WARN, ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
3071 __func__, pmkid_len));
3077 total_len = rsnie_len;
3079 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI)))
3082 total_len += extra_len;
3085 /* construct RSNIE body */
3086 MakeOutgoingFrame(pTmpBuf, &TempLen,
3089 rsnie_len, rsnie_ptr,
3093 *pFrameLen = *pFrameLen + TempLen;
3095 if (ie_num == IE_RSN)
3097 /* Insert PMKID-List field */
3100 MakeOutgoingFrame(pTmpBuf, &TempLen,
3102 pmkid_len, pmkid_ptr,
3106 *pFrameLen = *pFrameLen + TempLen;