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
39 #include "../rt_config.h"
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};
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};
61 static VOID ConstructEapolKeyData(
62 IN PMAC_TABLE_ENTRY pEntry,
63 IN UCHAR GroupKeyWepStatus,
66 IN UCHAR DefaultKeyIdx,
70 OUT PEAPOL_PACKET pMsg);
72 static VOID CalculateMIC(
75 OUT PEAPOL_PACKET pMsg);
77 static VOID WpaEAPPacketAction(
79 IN MLME_QUEUE_ELEM *Elem);
81 static VOID WpaEAPOLASFAlertAction(
83 IN MLME_QUEUE_ELEM *Elem);
85 static VOID WpaEAPOLLogoffAction(
87 IN MLME_QUEUE_ELEM *Elem);
89 static VOID WpaEAPOLStartAction(
91 IN MLME_QUEUE_ELEM *Elem);
93 static VOID WpaEAPOLKeyAction(
95 IN MLME_QUEUE_ELEM *Elem);
98 ==========================================================================
100 association state machine init, including state transition and timer init
102 S - pointer to the association state machine
103 ==========================================================================
105 VOID WpaStateMachineInit(
106 IN PRTMP_ADAPTER pAd,
108 OUT STATE_MACHINE_FUNC Trans[])
110 StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_WPA_PTK_STATE, MAX_WPA_MSG, (STATE_MACHINE_FUNC)Drop, WPA_PTK, WPA_MACHINE_BASE);
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);
120 ==========================================================================
122 this is state machine function.
123 When receiving EAP packets which is for 802.1x authentication use.
126 ==========================================================================
128 VOID WpaEAPPacketAction(
129 IN PRTMP_ADAPTER pAd,
130 IN MLME_QUEUE_ELEM *Elem)
134 VOID WpaEAPOLASFAlertAction(
135 IN PRTMP_ADAPTER pAd,
136 IN MLME_QUEUE_ELEM *Elem)
140 VOID WpaEAPOLLogoffAction(
141 IN PRTMP_ADAPTER pAd,
142 IN MLME_QUEUE_ELEM *Elem)
147 ==========================================================================
149 Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
151 ==========================================================================
153 VOID WpaEAPOLStartAction(
154 IN PRTMP_ADAPTER pAd,
155 IN MLME_QUEUE_ELEM *Elem)
157 MAC_TABLE_ENTRY *pEntry;
158 PHEADER_802_11 pHeader;
160 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
162 pHeader = (PHEADER_802_11)Elem->Msg;
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);
169 pEntry = MacTableLookup(pAd, pHeader->Addr2);
174 DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx));
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))))
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;
186 WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
192 ==========================================================================
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
202 ==========================================================================
204 VOID WpaEAPOLKeyAction(
205 IN PRTMP_ADAPTER pAd,
206 IN MLME_QUEUE_ELEM *Elem)
208 MAC_TABLE_ENTRY *pEntry;
209 PHEADER_802_11 pHeader;
210 PEAPOL_PACKET pEapol_packet;
211 KEY_INFO peerKeyInfo;
213 DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
215 pHeader = (PHEADER_802_11)Elem->Msg;
216 pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
218 NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
219 NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO));
221 hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet, (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
223 *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
227 pEntry = MacTableLookup(pAd, pHeader->Addr2);
229 if (!pEntry || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
232 if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
235 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr)));
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)))
240 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n"));
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))
248 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n"));
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))
255 DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) \n"));
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))
262 // Check the Key Ack (bit 7) of the Key Information to determine the Authenticator
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)
268 // The frame is snet by Authenticator.
269 // So the Supplicant side shall handle this.
271 if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) &&
272 (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY))
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);
281 PeerPairMsg3Action(pAd, pEntry, Elem);
283 else if ((peerKeyInfo.Secure == 1) &&
284 (peerKeyInfo.KeyMic == 1) &&
285 (peerKeyInfo.Request == 0) &&
286 (peerKeyInfo.Error == 0))
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);
295 PeerGroupMsg1Action(pAd, pEntry, Elem);
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))
306 if (peerKeyInfo.Secure == 0 && peerKeyInfo.KeyType == PAIRWISEKEY)
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)
313 PeerPairMsg4Action(pAd, pEntry, Elem);
317 PeerPairMsg2Action(pAd, pEntry, Elem);
320 else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == PAIRWISEKEY)
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);
326 else if (peerKeyInfo.Secure == 1 && peerKeyInfo.KeyType == GROUPKEY)
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));
339 ========================================================================
342 Copy frame from waiting queue into relative ring buffer and set
343 appropriate ASIC register to kick hardware encryption before really
347 pAd Pointer to our adapter
348 PNDIS_PACKET Pointer to outgoing Ndis frame
349 NumberOfFrag Number of fragment required
356 ========================================================================
358 VOID RTMPToWirelessSta(
359 IN PRTMP_ADAPTER pAd,
360 IN PMAC_TABLE_ENTRY pEntry,
361 IN PUCHAR pHeader802_3,
365 IN BOOLEAN bClearFrame)
367 PNDIS_PACKET pPacket;
370 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
374 // build a NDIS packet
375 Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen);
376 if (Status != NDIS_STATUS_SUCCESS)
381 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
383 RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
385 RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
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);
391 RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->Aid);
392 RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
395 #ifdef CONFIG_STA_SUPPORT
396 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
398 // send out the packet
399 Status = STASendPacket(pAd, pPacket);
400 if (Status == NDIS_STATUS_SUCCESS)
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)))
412 for(Index = 0; Index < 5; Index ++)
413 if(pAd->TxSwQueue[Index].Number > 0)
414 RTMPDeQueuePacket(pAd, FALSE, Index, MAX_TX_PROCESS);
418 #endif // CONFIG_STA_SUPPORT //
424 ==========================================================================
426 This is a function to initilize 4-way handshake
430 ==========================================================================
433 IN PRTMP_ADAPTER pAd,
434 IN MAC_TABLE_ENTRY *pEntry,
435 IN ULONG TimeInterval)
437 UCHAR Header802_3[14];
438 EAPOL_PACKET EAPOLPKT;
439 PUINT8 pBssid = NULL;
440 UCHAR group_cipher = Ndis802_11WEPDisabled;
442 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
444 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
446 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
453 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
458 if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK))
460 DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
465 // Increment replay counter by 1
466 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
468 // Randomly generate ANonce
469 GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce);
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,
477 0, // Default key index
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);
493 // Trigger Retry Timer
494 RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
497 pEntry->WpaState = AS_PTKSTART;
499 DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
504 ========================================================================
507 Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
510 pAd Pointer to our adapter
518 ========================================================================
520 VOID PeerPairMsg1Action(
521 IN PRTMP_ADAPTER pAd,
522 IN MAC_TABLE_ENTRY *pEntry,
523 IN MLME_QUEUE_ELEM *Elem)
526 UCHAR Header802_3[14];
529 EAPOL_PACKET EAPOLPKT;
530 PUINT8 pCurrentAddr = NULL;
531 PUINT8 pmk_ptr = NULL;
532 UCHAR group_cipher = Ndis802_11WEPDisabled;
533 PUINT8 rsnie_ptr = NULL;
536 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
538 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
541 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
544 #ifdef CONFIG_STA_SUPPORT
545 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
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;
553 #endif // CONFIG_STA_SUPPORT //
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;
559 // Sanity Check peer Pairwise message 1 - Replay Counter
560 if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE)
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);
567 NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
569 // Generate random SNonce
570 GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce);
573 // Calculate PTK(ANonce, SNonce)
583 // Save key to PTK entry
584 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
588 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
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,
604 // Make outgoing frame
605 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
607 RTMPToWirelessSta(pAd, pEntry,
608 Header802_3, sizeof(Header802_3), (PUCHAR)&EAPOLPKT,
609 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
611 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
616 ==========================================================================
618 When receiving the second packet of 4-way pairwisekey handshake.
620 ==========================================================================
622 VOID PeerPairMsg2Action(
623 IN PRTMP_ADAPTER pAd,
624 IN MAC_TABLE_ENTRY *pEntry,
625 IN MLME_QUEUE_ELEM *Elem)
629 PHEADER_802_11 pHeader;
630 EAPOL_PACKET EAPOLPKT;
633 UCHAR Header802_3[LENGTH_802_3];
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;
643 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
645 if ((!pEntry) || (!pEntry->ValidAsCLI))
648 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
651 // check Entry in valid State
652 if (pEntry->WpaState < AS_PTKSTART)
657 // pointer to 802.11 header
658 pHeader = (PHEADER_802_11)Elem->Msg;
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;
665 NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
671 pEntry->ANonce, // ANONCE
673 pEntry->SNonce, // SNONCE
678 NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
681 // Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE
682 if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE)
687 // delete retry timer
688 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
691 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
693 // Increment replay counter by 1
694 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
696 // Construct EAPoL message - Pairwise Msg 3
697 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
698 ConstructEapolMsg(pEntry,
709 // Make outgoing frame
710 MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
711 RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
713 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4,
714 (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
716 pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
717 RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
720 pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
723 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
727 ========================================================================
730 Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
733 pAd Pointer to our adapter
741 ========================================================================
743 VOID PeerPairMsg3Action(
744 IN PRTMP_ADAPTER pAd,
745 IN MAC_TABLE_ENTRY *pEntry,
746 IN MLME_QUEUE_ELEM *Elem)
748 PHEADER_802_11 pHeader;
749 UCHAR Header802_3[14];
750 EAPOL_PACKET EAPOLPKT;
753 PUINT8 pCurrentAddr = NULL;
754 UCHAR group_cipher = Ndis802_11WEPDisabled;
756 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
758 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
761 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
764 #ifdef CONFIG_STA_SUPPORT
765 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
767 pCurrentAddr = pAd->CurrentAddress;
768 group_cipher = pAd->StaCfg.GroupCipher;
771 #endif // CONFIG_STA_SUPPORT //
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;
778 // Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE
779 if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE)
782 // Save Replay counter, it will use construct message 4
783 NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
785 // Double check ANonce
786 if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
791 // Construct EAPoL message - Pairwise Msg 4
792 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
793 ConstructEapolMsg(pEntry,
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
805 pEntry->WpaState = AS_PTKINITDONE;
807 // Update pairwise key
808 #ifdef CONFIG_STA_SUPPORT
809 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
811 PCIPHER_KEY pSharedKey;
813 pSharedKey = &pAd->SharedKey[BSS0][0];
815 NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
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);
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;
830 pSharedKey->CipherAlg = CIPHER_NONE;
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;
839 // Update pairwise key information to ASIC Shared Key Table
840 AsicAddSharedKeyEntry(pAd,
843 pSharedKey->CipherAlg,
848 // Update ASIC WCID attribute table and IVEIV table
849 RTMPAddWcidAttributeEntry(pAd,
852 pSharedKey->CipherAlg,
856 #endif // CONFIG_STA_SUPPORT //
858 // open 802.1x port control and privacy filter
859 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
860 pEntry->AuthMode == Ndis802_11AuthModeWPA2)
862 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
863 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
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)));
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),
884 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, TRUE);
886 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
890 ==========================================================================
892 When receiving the last packet of 4-way pairwisekey handshake.
893 Initilize 2-way groupkey handshake following.
895 ==========================================================================
897 VOID PeerPairMsg4Action(
898 IN PRTMP_ADAPTER pAd,
899 IN MAC_TABLE_ENTRY *pEntry,
900 IN MLME_QUEUE_ELEM *Elem)
903 PHEADER_802_11 pHeader;
906 UCHAR group_cipher = Ndis802_11WEPDisabled;
908 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
912 if ((!pEntry) || (!pEntry->ValidAsCLI))
915 if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2 ) )
918 if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
922 // pointer to 802.11 header
923 pHeader = (PHEADER_802_11)Elem->Msg;
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;
929 // Sanity Check peer Pairwise message 4 - Replay Counter, MIC
930 if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
933 // 3. uses the MLME.SETKEYS.request to configure PTK into MAC
934 NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
936 // reset IVEIV in Asic
937 AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
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);
944 // Set pairwise key to Asic
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;
952 // Add Pair-wise key to Asic
953 AsicAddPairwiseKeyEntry(
957 &pEntry->PairwiseKey);
959 // update WCID attribute table and IVEIV table for this entry
960 RTMPAddWcidAttributeEntry(
964 pEntry->PairwiseKey.CipherAlg,
969 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
970 pEntry->WpaState = AS_PTKINITDONE;
971 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
974 if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
975 pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
977 pEntry->GTKState = REKEY_ESTABLISHED;
978 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
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);
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),
989 GetEncryptType(group_cipher)));
993 // 5. init Group 2-way handshake if necessary.
994 WPAStart2WayGroupHS(pAd, pEntry);
996 pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
997 RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
1004 ==========================================================================
1006 This is a function to send the first packet of 2-way groupkey handshake
1009 ==========================================================================
1011 VOID WPAStart2WayGroupHS(
1012 IN PRTMP_ADAPTER pAd,
1013 IN MAC_TABLE_ENTRY *pEntry)
1015 UCHAR Header802_3[14];
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;
1024 DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
1026 if ((!pEntry) || (!pEntry->ValidAsCLI))
1032 // Increment replay counter by 1
1033 ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
1035 // Construct EAPoL message - Group Msg 1
1036 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1037 ConstructEapolMsg(pEntry,
1041 (UCHAR *)gnonce_ptr,
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,
1053 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1059 DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
1065 ========================================================================
1067 Routine Description:
1068 Process Group key 2-way handshaking
1071 pAd Pointer to our adapter
1079 ========================================================================
1081 VOID PeerGroupMsg1Action(
1082 IN PRTMP_ADAPTER pAd,
1083 IN MAC_TABLE_ENTRY *pEntry,
1084 IN MLME_QUEUE_ELEM *Elem)
1086 UCHAR Header802_3[14];
1087 EAPOL_PACKET EAPOLPKT;
1088 PEAPOL_PACKET pGroup;
1091 UCHAR default_key = 0;
1092 UCHAR group_cipher = Ndis802_11WEPDisabled;
1093 PUINT8 pCurrentAddr = NULL;
1095 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
1097 if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
1100 #ifdef CONFIG_STA_SUPPORT
1101 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1103 pCurrentAddr = pAd->CurrentAddress;
1104 group_cipher = pAd->StaCfg.GroupCipher;
1105 default_key = pAd->StaCfg.DefaultKeyId;
1107 #endif // CONFIG_STA_SUPPORT //
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;
1113 // Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE
1114 if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry) == FALSE)
1117 // delete retry timer
1118 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1120 // Save Replay counter, it will use to construct message 2
1121 NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
1123 // Construct EAPoL message - Group Msg 2
1124 NdisZeroMemory(&EAPOLPKT, sizeof(EAPOL_PACKET));
1125 ConstructEapolMsg(pEntry,
1129 NULL, // Nonce not used
1130 NULL, // TxRSC not used
1131 NULL, // GTK not used
1132 NULL, // RSN IE not used
1136 // open 802.1x port control and privacy filter
1137 pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
1138 pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
1140 #ifdef CONFIG_STA_SUPPORT
1141 STA_PORT_SECURED(pAd);
1142 // Indicate Connected for GUI
1143 pAd->IndicateMediaState = NdisMediaStateConnected;
1144 #endif // CONFIG_STA_SUPPORT //
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)));
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),
1156 CONV_ARRARY_TO_UINT16(EAPOLPKT.Body_Len) + 4, FALSE);
1158 DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: sned group message 2\n"));
1162 ==========================================================================
1164 When receiving the last packet of 2-way groupkey handshake.
1166 ==========================================================================
1168 VOID PeerGroupMsg2Action(
1169 IN PRTMP_ADAPTER pAd,
1170 IN MAC_TABLE_ENTRY *pEntry,
1177 PEAPOL_PACKET pMsg2;
1178 UCHAR group_cipher = Ndis802_11WEPDisabled;
1180 DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
1184 if ((!pEntry) || (!pEntry->ValidAsCLI))
1187 if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE - 2))
1190 if (pEntry->WpaState != AS_PTKINITDONE)
1194 pData = (PUCHAR)Msg;
1195 pMsg2 = (PEAPOL_PACKET) (pData + LENGTH_802_1_H);
1196 Len = MsgLen - LENGTH_802_1_H;
1198 // Sanity Check peer group message 2 - Replay Counter, MIC
1199 if (PeerWpaMessageSanity(pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
1204 RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
1205 pEntry->GTKState = REKEY_ESTABLISHED;
1207 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
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);
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)));
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);
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)));
1233 ========================================================================
1235 Routine Description:
1236 Classify WPA EAP message type
1239 EAPType Value of EAP message type
1240 MsgType Internal Message definition for MLME state machine
1243 TRUE Found appropriate message type
1244 FALSE No appropriate message type
1246 IRQL = DISPATCH_LEVEL
1249 All these constants are defined in wpa.h
1250 For supplicant, there is only EAPOL Key message avaliable
1252 ========================================================================
1254 BOOLEAN WpaMsgTypeSubst(
1261 *MsgType = MT2_EAPPacket;
1264 *MsgType = MT2_EAPOLStart;
1267 *MsgType = MT2_EAPOLLogoff;
1270 *MsgType = MT2_EAPOLKey;
1273 *MsgType = MT2_EAPOLASFAlert;
1282 ========================================================================
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.
1289 It is used to generate PTK, GTK or some specific random value.
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
1301 UCHAR *output - the calculated result
1304 802.11i-2004 Annex H.3
1306 ========================================================================
1320 INT currentindex = 0;
1323 // Allocate memory for input
1324 os_alloc_mem(NULL, (PUCHAR *)&input, 1024);
1328 DBGPRINT(RT_DEBUG_ERROR, ("!!!PRF: no memory!!!\n"));
1332 // Generate concatenation input
1333 NdisMoveMemory(input, prefix, prefix_len);
1335 // Concatenate a single octet containing 0
1336 input[prefix_len] = 0;
1338 // Concatenate specific data
1339 NdisMoveMemory(&input[prefix_len + 1], data, data_len);
1340 total_len = prefix_len + 1 + data_len;
1342 // Concatenate a single octet containing 0
1343 // This octet shall be update later
1344 input[total_len] = 0;
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++)
1351 HMAC_SHA1(key, key_len, input, total_len, &output[currentindex], SHA1_DIGEST_SIZE);
1354 // update the last octet
1355 input[total_len - 1]++;
1357 os_free_mem(NULL, input);
1361 * F(P, S, c, i) = U1 xor U2 xor ... Uc
1362 * U1 = PRF(P, S || Int(i))
1367 static void F(char *password, unsigned char *ssid, int ssidlength, int iterations, int count, unsigned char *output)
1369 unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
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
1381 memcpy(output, digest1, SHA1_DIGEST_SIZE);
1383 for (i = 1; i < iterations; i++)
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);
1389 /* output = output xor Un */
1390 for (j = 0; j < SHA1_DIGEST_SIZE; j++)
1392 output[j] ^= digest[j];
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
1403 int PasswordHash(PSTRING password, PUCHAR ssid, INT ssidlength, PUCHAR output)
1405 if ((strlen(password) > 63) || (ssidlength > 32))
1408 F(password, ssid, ssidlength, 4096, 1, output);
1409 F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
1416 ========================================================================
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.
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)
1432 Output pointer to the PTK
1435 Refer to IEEE 802.11i-2004 8.5.1.2
1437 ========================================================================
1440 IN PRTMP_ADAPTER pAd,
1449 UCHAR concatenation[76];
1452 UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
1453 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'};
1455 // initiate the concatenation input
1456 NdisZeroMemory(temp, sizeof(temp));
1457 NdisZeroMemory(concatenation, 76);
1459 // Get smaller address
1460 if (RTMPCompareMemory(SA, AA, 6) == 1)
1461 NdisMoveMemory(concatenation, AA, 6);
1463 NdisMoveMemory(concatenation, SA, 6);
1466 // Get larger address
1467 if (RTMPCompareMemory(SA, AA, 6) == 1)
1468 NdisMoveMemory(&concatenation[CurrPos], SA, 6);
1470 NdisMoveMemory(&concatenation[CurrPos], AA, 6);
1472 // store the larger mac address for backward compatible of
1473 // ralink proprietary STA-key issue
1474 NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
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);
1483 NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
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);
1492 NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
1495 hex_dump("concatenation=", concatenation, 76);
1497 // Use PRF to generate PTK
1498 PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
1503 ========================================================================
1505 Routine Description:
1506 Generate random number by software.
1509 pAd - pointer to our pAdapter context
1510 macAddr - pointer to local MAC address
1515 802.1ii-2004 Annex H.5
1517 ========================================================================
1520 IN PRTMP_ADAPTER pAd,
1525 UCHAR local[80], KeyCounter[32];
1528 UCHAR prefix[] = {'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r'};
1530 // Zero the related information
1531 NdisZeroMemory(result, 80);
1532 NdisZeroMemory(local, 80);
1533 NdisZeroMemory(KeyCounter, 32);
1535 for (i = 0; i < 32; i++)
1537 // copy the local MAC address
1538 COPY_MAC_ADDR(local, macAddr);
1539 curr = MAC_ADDR_LEN;
1541 // concatenate the current time
1542 NdisGetSystemUpTime(&CurrentTime);
1543 NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
1544 curr += sizeof(CurrentTime);
1546 // concatenate the last result
1547 NdisMoveMemory(&local[curr], result, 32);
1550 // concatenate a variable
1551 NdisMoveMemory(&local[curr], &i, 2);
1554 // calculate the result
1555 PRF(KeyCounter, 32, prefix,12, local, curr, result, 32);
1558 NdisMoveMemory(random, result, 32);
1562 ========================================================================
1564 Routine Description:
1565 Build cipher suite in RSN-IE.
1566 It only shall be called by RTMPMakeRSNIE.
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
1579 ========================================================================
1581 static VOID RTMPMakeRsnIeCipher(
1582 IN PRTMP_ADAPTER pAd,
1585 IN BOOLEAN bMixCipher,
1586 IN UCHAR FlexibleCipher,
1594 // decide WPA2 or WPA1
1595 if (ElementID == Wpa2Ie)
1597 RSNIE2 *pRsnie_cipher = (RSNIE2*)pRsnIe;
1599 // Assign the verson as 1
1600 pRsnie_cipher->version = 1;
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);
1613 case Ndis802_11Encryption3Enabled:
1615 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
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);
1623 // TKIP-AES mix mode
1624 case Ndis802_11Encryption4Enabled:
1625 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
1628 // Insert WPA2 TKIP as the first pairwise cipher
1629 if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher))
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))
1635 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA2_CCMP, 4);
1641 // Insert WPA2 AES as the first pairwise cipher
1642 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4);
1645 pRsnie_cipher->ucount = PairwiseCnt;
1646 *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1));
1650 #ifdef CONFIG_STA_SUPPORT
1651 if ((pAd->OpMode == OPMODE_STA) &&
1652 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1653 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1655 UINT GroupCipher = pAd->StaCfg.GroupCipher;
1658 case Ndis802_11GroupWEP40Enabled:
1659 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP40, 4);
1661 case Ndis802_11GroupWEP104Enabled:
1662 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_WEP104, 4);
1666 #endif // CONFIG_STA_SUPPORT //
1668 // swap for big-endian platform
1669 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1670 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1674 RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe;
1676 // Assign OUI and version
1677 NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
1678 pRsnie_cipher->version = 1;
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);
1691 case Ndis802_11Encryption3Enabled:
1693 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
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);
1701 // TKIP-AES mix mode
1702 case Ndis802_11Encryption4Enabled:
1703 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
1706 // Insert WPA TKIP as the first pairwise cipher
1707 if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher))
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))
1713 NdisMoveMemory(pRsnie_cipher->ucast[0].oui + 4, OUI_WPA_CCMP, 4);
1719 // Insert WPA AES as the first pairwise cipher
1720 NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4);
1723 pRsnie_cipher->ucount = PairwiseCnt;
1724 *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1));
1728 #ifdef CONFIG_STA_SUPPORT
1729 if ((pAd->OpMode == OPMODE_STA) &&
1730 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
1731 (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled))
1733 UINT GroupCipher = pAd->StaCfg.GroupCipher;
1736 case Ndis802_11GroupWEP40Enabled:
1737 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP40, 4);
1739 case Ndis802_11GroupWEP104Enabled:
1740 NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_WEP104, 4);
1744 #endif // CONFIG_STA_SUPPORT //
1746 // swap for big-endian platform
1747 pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
1748 pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
1753 ========================================================================
1755 Routine Description:
1756 Build AKM suite in RSN-IE.
1757 It only shall be called by RTMPMakeRSNIE.
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
1769 ========================================================================
1771 static VOID RTMPMakeRsnIeAKM(
1772 IN PRTMP_ADAPTER pAd,
1779 RSNIE_AUTH *pRsnie_auth;
1780 UCHAR AkmCnt = 1; // default as 1
1782 pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len));
1784 // decide WPA2 or WPA1
1785 if (ElementID == Wpa2Ie)
1790 case Ndis802_11AuthModeWPA2:
1791 case Ndis802_11AuthModeWPA1WPA2:
1792 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4);
1795 case Ndis802_11AuthModeWPA2PSK:
1796 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1797 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4);
1809 case Ndis802_11AuthModeWPA:
1810 case Ndis802_11AuthModeWPA1WPA2:
1811 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4);
1814 case Ndis802_11AuthModeWPAPSK:
1815 case Ndis802_11AuthModeWPA1PSKWPA2PSK:
1816 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4);
1819 case Ndis802_11AuthModeWPANone:
1820 NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4);
1828 pRsnie_auth->acount = AkmCnt;
1829 pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
1831 // update current RSNIE length
1832 (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1)));
1837 ========================================================================
1839 Routine Description:
1840 Build capability in RSN-IE.
1841 It only shall be called by RTMPMakeRSNIE.
1844 pAd - pointer to our pAdapter context
1845 ElementID - indicate the WPA1 or WPA2
1846 apidx - indicate the interface index
1852 ========================================================================
1854 static VOID RTMPMakeRsnIeCap(
1855 IN PRTMP_ADAPTER pAd,
1861 RSN_CAPABILITIES *pRSN_Cap;
1863 // it could be ignored in WPA1 mode
1864 if (ElementID == WpaIe)
1867 pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len));
1870 pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
1872 (*rsn_len) += sizeof(RSN_CAPABILITIES); // update current RSNIE length
1878 ========================================================================
1880 Routine Description:
1881 Build RSN IE context. It is not included element-ID and length.
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
1893 ========================================================================
1896 IN PRTMP_ADAPTER pAd,
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
1905 BOOLEAN bMixCipher = FALSE; // indicate the pairwise and group cipher are different
1907 WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; // it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode
1909 rsnielen_cur_p = NULL;
1910 rsnielen_ex_cur_p = NULL;
1913 #ifdef CONFIG_STA_SUPPORT
1914 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1916 #ifdef WPA_SUPPLICANT_SUPPORT
1917 if (pAd->StaCfg.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE)
1919 if (AuthMode < Ndis802_11AuthModeWPA)
1923 #endif // WPA_SUPPLICANT_SUPPORT //
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)
1934 DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(STA)\n"));
1936 // Zero RSNIE context
1937 pAd->StaCfg.RSNIE_Len = 0;
1938 NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
1941 rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
1942 pRsnIe = pAd->StaCfg.RSN_IE;
1944 bMixCipher = pAd->StaCfg.bMixCipher;
1946 #endif // CONFIG_STA_SUPPORT //
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;
1957 PrimaryRsnie = Wpa2Ie;
1960 // Build the primary RSNIE
1961 // 1. insert cipher suite
1962 RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher, FlexibleCipher, pRsnIe, &p_offset);
1965 RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset);
1967 // 3. insert capability
1968 RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
1971 // 4. update the RSNIE length
1972 *rsnielen_cur_p = p_offset;
1974 hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
1980 ==========================================================================
1982 Check whether the received frame is EAP frame.
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
1992 TRUE - This frame is EAP frame
1994 ==========================================================================
1996 BOOLEAN RTMPCheckWPAframe(
1997 IN PRTMP_ADAPTER pAd,
1998 IN PMAC_TABLE_ENTRY pEntry,
2000 IN ULONG DataByteCount,
2001 IN UCHAR FromWhichBSSID)
2007 if(DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
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))
2018 // Skip 2-bytes EAPoL type
2019 if (NdisEqualMemory(EAPOL, pData, 2))
2020 // if (*(UINT16 *)EAPOL == *(UINT16 *)pData)
2030 Body_len = (*(pData+2)<<8) | (*(pData+3));
2031 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n", Body_len));
2034 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Start frame, TYPE = 1 \n"));
2035 if (pEntry->EnqueueEapolStartTimerRunning != EAPOL_START_DISABLE)
2037 DBGPRINT(RT_DEBUG_TRACE, ("Cancel the EnqueueEapolStartTimerRunning \n"));
2038 RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
2039 pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE;
2043 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
2046 Body_len = (*(pData+2)<<8) | (*(pData+3));
2047 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len));
2050 DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
2060 ==========================================================================
2062 Report the EAP message type
2065 msg - EAPOL_PAIR_MSG_1
2075 ==========================================================================
2077 PSTRING GetEapolMsgType(CHAR msg)
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";
2092 return "Invalid Message";
2097 ========================================================================
2099 Routine Description:
2100 Check Sanity RSN IE of EAPoL message
2107 ========================================================================
2109 BOOLEAN RTMPCheckRSNIE(
2110 IN PRTMP_ADAPTER pAd,
2113 IN MAC_TABLE_ENTRY *pEntry,
2119 BOOLEAN result = FALSE;
2125 while (len > sizeof(RSNIE2))
2127 pEid = (PEID_STRUCT) pVIE;
2129 if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)))
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)))
2138 *Offset += (pEid->Len + 2);
2141 else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)))
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)))
2152 *Offset += (pEid->Len + 2);
2159 pVIE += (pEid->Len + 2);
2160 len -= (pEid->Len + 2);
2170 ========================================================================
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
2183 ========================================================================
2185 BOOLEAN RTMPParseEapolKeyData(
2186 IN PRTMP_ADAPTER pAd,
2188 IN UCHAR KeyDataLen,
2189 IN UCHAR GroupKeyIndex,
2192 IN MAC_TABLE_ENTRY *pEntry)
2194 PKDE_ENCAP pKDE = NULL;
2195 PUCHAR pMyKeyData = pKeyData;
2196 UCHAR KeyDataLength = KeyDataLen;
2198 UCHAR DefaultIdx = 0;
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)
2204 // Check RSN IE whether it is WPA2/WPA2PSK
2205 if (!RTMPCheckRSNIE(pAd, pKeyData, KeyDataLen, pEntry, &skip_offset))
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);
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);
2219 if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3)
2221 WpaShowAllsuite(pMyKeyData, skip_offset);
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));
2233 DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength));
2234 //hex_dump("remain data", pMyKeyData, KeyDataLength);
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))
2240 if (KeyDataLength >= 8) // KDE format exclude GTK length
2242 pKDE = (PKDE_ENCAP) pMyKeyData;
2245 DefaultIdx = pKDE->GTKEncap.Kid;
2247 // Sanity check - KED length
2248 if (KeyDataLength < (pKDE->Len + 2))
2250 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The len from KDE is too short \n"));
2254 // Get GTK length - refer to IEEE 802.11i-2004 p.82
2255 GTKLEN = pKDE->Len -6;
2256 if (GTKLEN < LEN_AES_KEY)
2258 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN));
2265 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: KDE format length is too short \n"));
2269 DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN));
2275 else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1)
2277 DefaultIdx = GroupKeyIndex;
2278 DBGPRINT(RT_DEBUG_TRACE, ("GTK DefaultKeyID=%d \n", DefaultIdx));
2281 // Sanity check - shared key index must be 1 ~ 3
2282 if (DefaultIdx < 1 || DefaultIdx > 3)
2284 DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
2289 #ifdef CONFIG_STA_SUPPORT
2290 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2292 PCIPHER_KEY pSharedKey;
2294 // set key material, TxMic and RxMic
2295 NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
2296 pAd->StaCfg.DefaultKeyId = DefaultIdx;
2298 pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
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);
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;
2319 // Update group key information to ASIC Shared Key Table
2320 AsicAddSharedKeyEntry(pAd,
2322 pAd->StaCfg.DefaultKeyId,
2323 pSharedKey->CipherAlg,
2328 // Update ASIC WCID attribute table and IVEIV table
2329 RTMPAddWcidAttributeEntry(pAd,
2331 pAd->StaCfg.DefaultKeyId,
2332 pSharedKey->CipherAlg,
2335 #endif // CONFIG_STA_SUPPORT //
2343 ========================================================================
2345 Routine Description:
2346 Construct EAPoL message for WPA handshaking
2347 Its format is below,
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 +--------------------+
2381 pAd Pointer to our adapter
2388 ========================================================================
2390 VOID ConstructEapolMsg(
2391 IN PMAC_TABLE_ENTRY pEntry,
2392 IN UCHAR GroupKeyWepStatus,
2394 IN UCHAR DefaultKeyIdx,
2400 OUT PEAPOL_PACKET pMsg)
2402 BOOLEAN bWPA2 = FALSE;
2405 // Choose WPA2 or not
2406 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2407 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2410 // Init Packet and Fill header
2411 pMsg->ProVer = EAPOL_VER;
2412 pMsg->ProType = EAPOLKey;
2414 // Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field
2415 SET_UINT16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
2417 // Fill in EAPoL descriptor
2419 pMsg->KeyDesc.Type = WPA2_KEY_DESC;
2421 pMsg->KeyDesc.Type = WPA1_KEY_DESC;
2423 // Key Descriptor Version (bits 0-2) specifies the key descriptor version type
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));
2431 pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
2433 // Specify Key Type as Group(0) or Pairwise(1)
2434 if (MsgType >= EAPOL_GROUP_MSG_1)
2435 pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
2437 pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
2439 // Specify Key Index, only group_msg1_WPA1
2440 if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
2441 pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
2443 if (MsgType == EAPOL_PAIR_MSG_3)
2444 pMsg->KeyDesc.KeyInfo.Install = 1;
2446 if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
2447 pMsg->KeyDesc.KeyInfo.KeyAck = 1;
2449 if (MsgType != EAPOL_PAIR_MSG_1)
2450 pMsg->KeyDesc.KeyInfo.KeyMic = 1;
2452 if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
2453 (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
2455 pMsg->KeyDesc.KeyInfo.Secure = 1;
2458 if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
2459 (MsgType == EAPOL_GROUP_MSG_1)))
2461 pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
2464 // key Information element has done.
2465 *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo));
2467 // Fill in Key Length
2469 if (MsgType >= EAPOL_GROUP_MSG_1)
2471 // the length of group key cipher
2472 pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH : LEN_AES_KEY);
2476 // the length of pairwise key cipher
2477 pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY : LEN_AES_KEY);
2481 // Fill in replay counter
2482 NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY);
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);
2491 // Fill key IV - WPA2 as 0, WPA1 as random
2492 if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
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;
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))
2503 NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
2506 // Clear Key MIC field for MIC calculation later
2507 NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
2509 ConstructEapolKeyData(pEntry,
2519 // Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.
2520 if (MsgType != EAPOL_PAIR_MSG_1)
2522 CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
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)));
2533 ========================================================================
2535 Routine Description:
2536 Construct the Key Data field of EAPoL message
2539 pAd Pointer to our adapter
2547 ========================================================================
2549 VOID ConstructEapolKeyData(
2550 IN PMAC_TABLE_ENTRY pEntry,
2551 IN UCHAR GroupKeyWepStatus,
2552 IN UCHAR keyDescVer,
2554 IN UCHAR DefaultKeyIdx,
2558 OUT PEAPOL_PACKET pMsg)
2560 UCHAR *mpool, *Key_Data, *Rc4GTK;
2561 UCHAR ekey[(LEN_KEY_DESC_IV+LEN_EAP_EK)];
2563 BOOLEAN bWPA2Capable = FALSE;
2564 PRTMP_ADAPTER pAd = pEntry->pAd;
2565 BOOLEAN GTK_Included = FALSE;
2567 // Choose WPA2 or not
2568 if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
2569 (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
2570 bWPA2Capable = TRUE;
2572 if (MsgType == EAPOL_PAIR_MSG_1 ||
2573 MsgType == EAPOL_PAIR_MSG_4 ||
2574 MsgType == EAPOL_GROUP_MSG_2)
2577 // allocate memory pool
2578 os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500);
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);
2588 NdisZeroMemory(Key_Data, 512);
2589 SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
2592 // Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3
2593 if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3)))
2595 PUINT8 pmkid_ptr = NULL;
2596 UINT8 pmkid_len = 0;
2599 RTMPInsertRSNIE(&Key_Data[data_offset],
2600 (PULONG)&data_offset,
2608 // Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2
2609 if (bWPA2Capable && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
2611 // Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h
2612 Key_Data[data_offset + 0] = 0xDD;
2614 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2616 Key_Data[data_offset + 1] = 0x16;// 4+2+16(OUI+DataType+DataField)
2620 Key_Data[data_offset + 1] = 0x26;// 4+2+32(OUI+DataType+DataField)
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;
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
2637 // Only for pairwise_msg3_WPA2 and group_msg1
2638 if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
2641 if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
2643 NdisMoveMemory(&Key_Data[data_offset], GTK, LEN_AES_KEY);
2644 data_offset += LEN_AES_KEY;
2648 NdisMoveMemory(&Key_Data[data_offset], GTK, TKIP_GTK_LENGTH);
2649 data_offset += TKIP_GTK_LENGTH;
2652 GTK_Included = TRUE;
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
2660 //hex_dump("GTK_Included", Key_Data, data_offset);
2663 (keyDescVer == DESC_TYPE_AES))
2665 UCHAR remainder = 0;
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
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)
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;
2685 data_offset += pad_len;
2688 AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data, data_offset, Rc4GTK);
2689 // AES wrap function will grow 8 bytes in length
2694 /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
2695 using the KEK field from the derived PTK. */
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.
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);
2709 NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
2713 NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
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);
2720 os_free_mem(NULL, mpool);
2725 ========================================================================
2727 Routine Description:
2728 Calcaulate MIC. It is used during 4-ways handsharking.
2731 pAd - pointer to our pAdapter context
2732 PeerWepStatus - indicate the encryption type
2738 ========================================================================
2740 static VOID CalculateMIC(
2741 IN UCHAR KeyDescVer,
2743 OUT PEAPOL_PACKET pMsg)
2747 UCHAR mic[LEN_KEY_DESC_MIC];
2750 // allocate memory for MIC calculation
2751 os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512);
2753 if (OutBuffer == NULL)
2755 DBGPRINT(RT_DEBUG_ERROR, ("!!!CalculateMIC: no memory!!!\n"));
2759 // make a frame for calculating MIC.
2760 MakeOutgoingFrame(OutBuffer, &FrameLen,
2761 CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4, pMsg,
2764 NdisZeroMemory(mic, sizeof(mic));
2767 if (KeyDescVer == DESC_TYPE_AES)
2769 HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
2770 NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
2774 HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
2777 // store the calculated MIC
2778 NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
2780 os_free_mem(NULL, OutBuffer);
2784 ========================================================================
2786 Routine Description:
2787 Some received frames can't decrypt by Asic, so decrypt them by software.
2790 pAd - pointer to our pAdapter context
2791 PeerWepStatus - indicate the encryption type
2794 NDIS_STATUS_SUCCESS - decryption successful
2795 NDIS_STATUS_FAILURE - decryption failure
2797 ========================================================================
2799 NDIS_STATUS RTMPSoftDecryptBroadCastData(
2800 IN PRTMP_ADAPTER pAd,
2802 IN NDIS_802_11_ENCRYPTION_STATUS GroupCipher,
2803 IN PCIPHER_KEY pShard_key)
2805 PRXWI_STRUC pRxWI = pRxBlk->pRxWI;
2809 // handle WEP decryption
2810 if (GroupCipher == Ndis802_11Encryption1Enabled)
2812 if (RTMPSoftDecryptWEP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, pShard_key))
2815 //Minus IV[4] & ICV[4]
2816 pRxWI->MPDUtotalByteCount -= 8;
2820 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : Software decrypt WEP data fails.\n"));
2821 // give up this frame
2822 return NDIS_STATUS_FAILURE;
2825 // handle TKIP decryption
2826 else if (GroupCipher == Ndis802_11Encryption2Enabled)
2828 if (RTMPSoftDecryptTKIP(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0, pShard_key))
2831 //Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV
2832 pRxWI->MPDUtotalByteCount -= 20;
2836 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
2837 // give up this frame
2838 return NDIS_STATUS_FAILURE;
2841 // handle AES decryption
2842 else if (GroupCipher == Ndis802_11Encryption3Enabled)
2844 if (RTMPSoftDecryptAES(pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount , pShard_key))
2847 //8 bytes MIC, 8 bytes IV/EIV (CCMP Header)
2848 pRxWI->MPDUtotalByteCount -= 16;
2852 DBGPRINT(RT_DEBUG_ERROR, ("ERROR : RTMPSoftDecryptAES Failed\n"));
2853 // give up this frame
2854 return NDIS_STATUS_FAILURE;
2859 // give up this frame
2860 return NDIS_STATUS_FAILURE;
2863 return NDIS_STATUS_SUCCESS;
2868 PUINT8 GetSuiteFromRSNIE(
2880 BOOLEAN isWPA2 = FALSE;
2882 pEid = (PEID_STRUCT)rsnie;
2883 len = rsnie_len - 2; // exclude IE and length
2884 pBuf = (PUINT8)&pEid->Octet[0];
2888 // set default value
2892 if ((len <= 0) || (pEid->Len != len))
2894 DBGPRINT_ERR(("%s : The length is invalid\n", __FUNCTION__));
2898 // Check WPA or WPA2
2899 if (pEid->Eid == IE_WPA)
2901 PRSNIE pRsnie = (PRSNIE)pBuf;
2904 if (len < sizeof(RSNIE))
2906 DBGPRINT_ERR(("%s : The length is too short for WPA\n", __FUNCTION__));
2910 // Get the count of pairwise cipher
2911 ucount = cpu2le16(pRsnie->ucount);
2914 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2915 __FUNCTION__, ucount));
2919 // Get the group cipher
2920 if (type == GROUP_SUITE)
2923 return pRsnie->mcast;
2925 // Get the pairwise cipher suite
2926 else if (type == PAIRWISE_SUITE)
2928 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2929 __FUNCTION__, ucount));
2931 return pRsnie->ucast[0].oui;
2934 offset = sizeof(RSNIE) + (4 * (ucount - 1));
2937 else if (pEid->Eid == IE_RSN)
2939 PRSNIE2 pRsnie = (PRSNIE2)pBuf;
2944 if (len < sizeof(RSNIE2))
2946 DBGPRINT_ERR(("%s : The length is too short for WPA2\n", __FUNCTION__));
2950 // Get the count of pairwise cipher
2951 ucount = cpu2le16(pRsnie->ucount);
2954 DBGPRINT_ERR(("%s : The count(%d) of pairwise cipher is invlaid\n",
2955 __FUNCTION__, ucount));
2959 // Get the group cipher
2960 if (type == GROUP_SUITE)
2963 return pRsnie->mcast;
2965 // Get the pairwise cipher suite
2966 else if (type == PAIRWISE_SUITE)
2968 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of pairwise cipher is %d\n",
2969 __FUNCTION__, ucount));
2971 return pRsnie->ucast[0].oui;
2974 offset = sizeof(RSNIE2) + (4 * (ucount - 1));
2979 DBGPRINT_ERR(("%s : Unknown IE (%d)\n", __FUNCTION__, pEid->Eid));
2983 // skip group cipher and pairwise cipher suite
2987 if (len < sizeof(RSNIE_AUTH))
2989 DBGPRINT_ERR(("%s : The length of RSNIE is too short\n", __FUNCTION__));
2993 // pointer to AKM count
2994 pAkm = (PRSNIE_AUTH)pBuf;
2996 // Get the count of pairwise cipher
2997 acount = cpu2le16(pAkm->acount);
3000 DBGPRINT_ERR(("%s : The count(%d) of AKM is invlaid\n",
3001 __FUNCTION__, acount));
3005 // Get the AKM suite
3006 if (type == AKM_SUITE)
3008 DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
3009 __FUNCTION__, acount));
3011 return pAkm->auth[0].oui;
3013 offset = sizeof(RSNIE_AUTH) + (4 * (acount - 1));
3018 // The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~))
3019 if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID))
3021 // Skip RSN capability and PMKID-Count
3022 pBuf += (sizeof(RSN_CAPABILITIES) + 2);
3023 len -= (sizeof(RSN_CAPABILITIES) + 2);
3026 if (type == PMKID_LIST)
3034 DBGPRINT_ERR(("%s : it can't get any more information beyond AKM \n", __FUNCTION__));
3039 //DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __FUNCTION__, type));
3044 VOID WpaShowAllsuite(
3048 PUINT8 pSuite = NULL;
3051 hex_dump("RSNIE", rsnie, rsnie_len);
3054 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL)
3056 hex_dump("group cipher", pSuite, 4*count);
3060 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL)
3062 hex_dump("pairwise cipher", pSuite, 4*count);
3066 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL)
3068 hex_dump("AKM suite", pSuite, 4*count);
3072 if ((pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL)
3074 hex_dump("PMKID", pSuite, LEN_PMKID);
3079 VOID RTMPInsertRSNIE(
3080 IN PUCHAR pFrameBuf,
3081 OUT PULONG pFrameLen,
3082 IN PUINT8 rsnie_ptr,
3084 IN PUINT8 pmkid_ptr,
3089 UINT8 extra_len = 0;
3090 UINT16 pmk_count = 0;
3092 UINT8 total_len = 0;
3093 UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
3095 pTmpBuf = pFrameBuf;
3097 /* PMKID-List Must larger than 0 and the multiple of 16. */
3098 if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0))
3100 extra_len = sizeof(UINT16) + pmkid_len;
3102 pmk_count = (pmkid_len >> 4);
3103 pmk_count = cpu2le16(pmk_count);
3107 DBGPRINT(RT_DEBUG_WARN, ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
3108 __FUNCTION__, pmkid_len));
3114 total_len = rsnie_len;
3116 if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI)))
3119 total_len += extra_len;
3122 /* construct RSNIE body */
3123 MakeOutgoingFrame(pTmpBuf, &TempLen,
3126 rsnie_len, rsnie_ptr,
3130 *pFrameLen = *pFrameLen + TempLen;
3132 if (ie_num == IE_RSN)
3134 /* Insert PMKID-List field */
3137 MakeOutgoingFrame(pTmpBuf, &TempLen,
3139 pmkid_len, pmkid_ptr,
3143 *pFrameLen = *pFrameLen + TempLen;