aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rt2860/common/cmm_wpa.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rt2860/common/cmm_wpa.c')
-rw-r--r--drivers/staging/rt2860/common/cmm_wpa.c3010
1 files changed, 0 insertions, 3010 deletions
diff --git a/drivers/staging/rt2860/common/cmm_wpa.c b/drivers/staging/rt2860/common/cmm_wpa.c
deleted file mode 100644
index 616ebec50c61..000000000000
--- a/drivers/staging/rt2860/common/cmm_wpa.c
+++ /dev/null
@@ -1,3010 +0,0 @@
-/*
- *************************************************************************
- * Ralink Tech Inc.
- * 5F., No.36, Taiyuan St., Jhubei City,
- * Hsinchu County 302,
- * Taiwan, R.O.C.
- *
- * (c) Copyright 2002-2007, Ralink Technology, Inc.
- *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- *************************************************************************
-
- Module Name:
- wpa.c
-
- Abstract:
-
- Revision History:
- Who When What
- -------- ---------- ----------------------------------------------
- Jan Lee 03-07-22 Initial
- Paul Lin 03-11-28 Modify for supplicant
-*/
-#include "../rt_config.h"
-/* WPA OUI */
-u8 OUI_WPA_NONE_AKM[4] = { 0x00, 0x50, 0xF2, 0x00 };
-u8 OUI_WPA_VERSION[4] = { 0x00, 0x50, 0xF2, 0x01 };
-u8 OUI_WPA_WEP40[4] = { 0x00, 0x50, 0xF2, 0x01 };
-u8 OUI_WPA_TKIP[4] = { 0x00, 0x50, 0xF2, 0x02 };
-u8 OUI_WPA_CCMP[4] = { 0x00, 0x50, 0xF2, 0x04 };
-u8 OUI_WPA_WEP104[4] = { 0x00, 0x50, 0xF2, 0x05 };
-u8 OUI_WPA_8021X_AKM[4] = { 0x00, 0x50, 0xF2, 0x01 };
-u8 OUI_WPA_PSK_AKM[4] = { 0x00, 0x50, 0xF2, 0x02 };
-
-/* WPA2 OUI */
-u8 OUI_WPA2_WEP40[4] = { 0x00, 0x0F, 0xAC, 0x01 };
-u8 OUI_WPA2_TKIP[4] = { 0x00, 0x0F, 0xAC, 0x02 };
-u8 OUI_WPA2_CCMP[4] = { 0x00, 0x0F, 0xAC, 0x04 };
-u8 OUI_WPA2_8021X_AKM[4] = { 0x00, 0x0F, 0xAC, 0x01 };
-u8 OUI_WPA2_PSK_AKM[4] = { 0x00, 0x0F, 0xAC, 0x02 };
-u8 OUI_WPA2_WEP104[4] = { 0x00, 0x0F, 0xAC, 0x05 };
-
-static void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
- u8 GroupKeyWepStatus,
- u8 keyDescVer,
- u8 MsgType,
- u8 DefaultKeyIdx,
- u8 * GTK,
- u8 * RSNIE,
- u8 RSNIE_LEN, struct rt_eapol_packet * pMsg);
-
-static void CalculateMIC(u8 KeyDescVer,
- u8 * PTK, struct rt_eapol_packet * pMsg);
-
-static void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
-
-static void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd,
- struct rt_mlme_queue_elem *Elem);
-
-static void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd,
- struct rt_mlme_queue_elem *Elem);
-
-static void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd,
- struct rt_mlme_queue_elem *Elem);
-
-static void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem);
-
-/*
- ==========================================================================
- Description:
- association state machine init, including state transition and timer init
- Parameters:
- S - pointer to the association state machine
- ==========================================================================
- */
-void WpaStateMachineInit(struct rt_rtmp_adapter *pAd,
- struct rt_state_machine *S, OUT STATE_MACHINE_FUNC Trans[])
-{
- StateMachineInit(S, (STATE_MACHINE_FUNC *) Trans, MAX_WPA_PTK_STATE,
- MAX_WPA_MSG, (STATE_MACHINE_FUNC) Drop, WPA_PTK,
- WPA_MACHINE_BASE);
-
- StateMachineSetAction(S, WPA_PTK, MT2_EAPPacket,
- (STATE_MACHINE_FUNC) WpaEAPPacketAction);
- StateMachineSetAction(S, WPA_PTK, MT2_EAPOLStart,
- (STATE_MACHINE_FUNC) WpaEAPOLStartAction);
- StateMachineSetAction(S, WPA_PTK, MT2_EAPOLLogoff,
- (STATE_MACHINE_FUNC) WpaEAPOLLogoffAction);
- StateMachineSetAction(S, WPA_PTK, MT2_EAPOLKey,
- (STATE_MACHINE_FUNC) WpaEAPOLKeyAction);
- StateMachineSetAction(S, WPA_PTK, MT2_EAPOLASFAlert,
- (STATE_MACHINE_FUNC) WpaEAPOLASFAlertAction);
-}
-
-/*
- ==========================================================================
- Description:
- this is state machine function.
- When receiving EAP packets which is for 802.1x authentication use.
- Not use in PSK case
- Return:
- ==========================================================================
-*/
-void WpaEAPPacketAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
-{
-}
-
-void WpaEAPOLASFAlertAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
-{
-}
-
-void WpaEAPOLLogoffAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
-{
-}
-
-/*
- ==========================================================================
- Description:
- Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
- Return:
- ==========================================================================
-*/
-void WpaEAPOLStartAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
-{
- struct rt_mac_table_entry *pEntry;
- struct rt_header_802_11 * pHeader;
-
- DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLStartAction ===> \n"));
-
- pHeader = (struct rt_header_802_11 *) Elem->Msg;
-
- /*For normaol PSK, we enqueue an EAPOL-Start command to trigger the process. */
- if (Elem->MsgLen == 6)
- pEntry = MacTableLookup(pAd, Elem->Msg);
- else {
- pEntry = MacTableLookup(pAd, pHeader->Addr2);
- }
-
- if (pEntry) {
- DBGPRINT(RT_DEBUG_TRACE,
- (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n",
- pEntry->PortSecured, pEntry->WpaState,
- pEntry->AuthMode, pEntry->PMKID_CacheIdx));
-
- if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
- && (pEntry->WpaState < AS_PTKSTART)
- && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
- || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
- || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
- && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) {
- pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP;
- pEntry->WpaState = AS_INITPSK;
- pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
- NdisZeroMemory(pEntry->R_Counter,
- sizeof(pEntry->R_Counter));
- pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
-
- WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
- }
- }
-}
-
-/*
- ==========================================================================
- Description:
- This is state machine function.
- When receiving EAPOL packets which is for 802.1x key management.
- Use both in WPA, and WPAPSK case.
- In this function, further dispatch to different functions according to the received packet. 3 categories are :
- 1. normal 4-way pairwisekey and 2-way groupkey handshake
- 2. MIC error (Countermeasures attack) report packet from STA.
- 3. Request for pairwise/group key update from STA
- Return:
- ==========================================================================
-*/
-void WpaEAPOLKeyAction(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
-{
- struct rt_mac_table_entry *pEntry;
- struct rt_header_802_11 * pHeader;
- struct rt_eapol_packet * pEapol_packet;
- struct rt_key_info peerKeyInfo;
-
- DBGPRINT(RT_DEBUG_TRACE, ("WpaEAPOLKeyAction ===>\n"));
-
- pHeader = (struct rt_header_802_11 *) Elem->Msg;
- pEapol_packet =
- (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
-
- NdisZeroMemory((u8 *)& peerKeyInfo, sizeof(peerKeyInfo));
- NdisMoveMemory((u8 *)& peerKeyInfo,
- (u8 *)& pEapol_packet->KeyDesc.KeyInfo,
- sizeof(struct rt_key_info));
-
- hex_dump("Received Eapol frame", (unsigned char *)pEapol_packet,
- (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H));
-
- *((u16 *) & peerKeyInfo) = cpu2le16(*((u16 *) & peerKeyInfo));
-
- do {
- pEntry = MacTableLookup(pAd, pHeader->Addr2);
-
- if (!pEntry
- || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
- break;
-
- if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
- break;
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAPoL-Key frame from STA %pMF\n",
- pEntry->Addr));
-
- if (((pEapol_packet->ProVer != EAPOL_VER)
- && (pEapol_packet->ProVer != EAPOL_VER2))
- || ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC)
- && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("Key descripter does not match with WPA rule\n"));
- break;
- }
- /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */
- /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1. */
- if ((pEntry->WepStatus == Ndis802_11Encryption2Enabled)
- && (peerKeyInfo.KeyDescVer != DESC_TYPE_TKIP)) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("Key descripter version not match(TKIP) \n"));
- break;
- }
- /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */
- /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2. */
- else if ((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
- && (peerKeyInfo.KeyDescVer != DESC_TYPE_AES)) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("Key descripter version not match(AES) \n"));
- break;
- }
- /* Check if this STA is in class 3 state and the WPA state is started */
- if ((pEntry->Sst == SST_ASSOC)
- && (pEntry->WpaState >= AS_INITPSK)) {
- /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */
- /* or not. */
- /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL- */
- /* Key frame from the Authenticator must not have the Ack bit set. */
- if (peerKeyInfo.KeyAck == 1) {
- /* The frame is snet by Authenticator. */
- /* So the Supplicant side shall handle this. */
-
- if ((peerKeyInfo.Secure == 0)
- && (peerKeyInfo.Request == 0)
- && (peerKeyInfo.Error == 0)
- && (peerKeyInfo.KeyType == PAIRWISEKEY)) {
- /* Process 1. the message 1 of 4-way HS in WPA or WPA2 */
- /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
- /* 2. the message 3 of 4-way HS in WPA */
- /* EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
- if (peerKeyInfo.KeyMic == 0)
- PeerPairMsg1Action(pAd, pEntry,
- Elem);
- else
- PeerPairMsg3Action(pAd, pEntry,
- Elem);
- } else if ((peerKeyInfo.Secure == 1)
- && (peerKeyInfo.KeyMic == 1)
- && (peerKeyInfo.Request == 0)
- && (peerKeyInfo.Error == 0)) {
- /* Process 1. the message 3 of 4-way HS in WPA2 */
- /* EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) */
- /* 2. the message 1 of group KS in WPA or WPA2 */
- /* EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) */
- if (peerKeyInfo.KeyType == PAIRWISEKEY)
- PeerPairMsg3Action(pAd, pEntry,
- Elem);
- else
- PeerGroupMsg1Action(pAd, pEntry,
- Elem);
- }
- } else {
- /* The frame is snet by Supplicant. */
- /* So the Authenticator side shall handle this. */
- if ((peerKeyInfo.Request == 0) &&
- (peerKeyInfo.Error == 0) &&
- (peerKeyInfo.KeyMic == 1)) {
- if (peerKeyInfo.Secure == 0
- && peerKeyInfo.KeyType ==
- PAIRWISEKEY) {
- /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,Data) */
- /* Process 1. message 2 of 4-way HS in WPA or WPA2 */
- /* 2. message 4 of 4-way HS in WPA */
- if (CONV_ARRARY_TO_u16
- (pEapol_packet->KeyDesc.
- KeyDataLen) == 0) {
- PeerPairMsg4Action(pAd,
- pEntry,
- Elem);
- } else {
- PeerPairMsg2Action(pAd,
- pEntry,
- Elem);
- }
- } else if (peerKeyInfo.Secure == 1
- && peerKeyInfo.KeyType ==
- PAIRWISEKEY) {
- /* EAPOL-Key(1,1,0,0,P,0,0,0,MIC,0) */
- /* Process message 4 of 4-way HS in WPA2 */
- PeerPairMsg4Action(pAd, pEntry,
- Elem);
- } else if (peerKeyInfo.Secure == 1
- && peerKeyInfo.KeyType ==
- GROUPKEY) {
- /* EAPOL-Key(1,1,0,0,G,0,0,0,MIC,0) */
- /* Process message 2 of Group key HS in WPA or WPA2 */
- PeerGroupMsg2Action(pAd, pEntry,
- &Elem->
- Msg
- [LENGTH_802_11],
- (Elem->
- MsgLen -
- LENGTH_802_11));
- }
- }
- }
- }
- } while (FALSE);
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Copy frame from waiting queue into relative ring buffer and set
- appropriate ASIC register to kick hardware encryption before really
- sent out to air.
-
- Arguments:
- pAd Pointer to our adapter
- void * Pointer to outgoing Ndis frame
- NumberOfFrag Number of fragment required
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void RTMPToWirelessSta(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry,
- u8 *pHeader802_3,
- u32 HdrLen,
- u8 *pData, u32 DataLen, IN BOOLEAN bClearFrame)
-{
- void *pPacket;
- int Status;
-
- if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
- return;
-
- do {
- /* build a NDIS packet */
- Status =
- RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen,
- pData, DataLen);
- if (Status != NDIS_STATUS_SUCCESS)
- break;
-
- if (bClearFrame)
- RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 1);
- else
- RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, 0);
- {
- RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
-
- RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket, MAIN_MBSSID); /* set a default value */
- if (pEntry->apidx != 0)
- RTMP_SET_PACKET_NET_DEVICE_MBSSID(pPacket,
- pEntry->
- apidx);
-
- RTMP_SET_PACKET_WCID(pPacket, (u8)pEntry->Aid);
- RTMP_SET_PACKET_MOREDATA(pPacket, FALSE);
- }
-
- {
- /* send out the packet */
- Status = STASendPacket(pAd, pPacket);
- if (Status == NDIS_STATUS_SUCCESS) {
- u8 Index;
-
- /* Dequeue one frame from TxSwQueue0..3 queue and process it */
- /* There are three place calling dequeue for TX ring. */
- /* 1. Here, right after queueing the frame. */
- /* 2. At the end of TxRingTxDone service routine. */
- /* 3. Upon NDIS call RTMPSendPackets */
- if ((!RTMP_TEST_FLAG
- (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
- &&
- (!RTMP_TEST_FLAG
- (pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS))) {
- for (Index = 0; Index < 5; Index++)
- if (pAd->TxSwQueue[Index].
- Number > 0)
- RTMPDeQueuePacket(pAd,
- FALSE,
- Index,
- MAX_TX_PROCESS);
- }
- }
- }
-
- } while (FALSE);
-}
-
-/*
- ==========================================================================
- Description:
- This is a function to initialize 4-way handshake
-
- Return:
-
- ==========================================================================
-*/
-void WPAStart4WayHS(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, unsigned long TimeInterval)
-{
- u8 Header802_3[14];
- struct rt_eapol_packet EAPOLPKT;
- u8 *pBssid = NULL;
- u8 group_cipher = Ndis802_11WEPDisabled;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n"));
-
- if (RTMP_TEST_FLAG
- (pAd,
- fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_HALT_IN_PROGRESS))
- {
- DBGPRINT(RT_DEBUG_ERROR,
- ("[ERROR]WPAStart4WayHS : The interface is closed...\n"));
- return;
- }
-
- if (pBssid == NULL) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
- return;
- }
- /* Check the status */
- if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("[ERROR]WPAStart4WayHS : Not expect calling\n"));
- return;
- }
-
- /* Increment replay counter by 1 */
- ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
-
- /* Randomly generate ANonce */
- GenRandom(pAd, (u8 *) pBssid, pEntry->ANonce);
-
- /* Construct EAPoL message - Pairwise Msg 1 */
- /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_1, 0, /* Default key index */
- pEntry->ANonce, NULL, /* TxRSC */
- NULL, /* GTK */
- NULL, /* RSNIE */
- 0, /* RSNIE length */
- &EAPOLPKT);
-
- /* Make outgoing frame */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
- RTMPToWirelessSta(pAd, pEntry, Header802_3,
- LENGTH_802_3, (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
- (pEntry->PortSecured ==
- WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
-
- /* Trigger Retry Timer */
- RTMPModTimer(&pEntry->RetryTimer, TimeInterval);
-
- /* Update State */
- pEntry->WpaState = AS_PTKSTART;
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== WPAStart4WayHS: send Msg1 of 4-way \n"));
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Process Pairwise key Msg-1 of 4-way handshaking and send Msg-2
-
- Arguments:
- pAd Pointer to our adapter
- Elem Message body
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void PeerPairMsg1Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
-{
- u8 PTK[80];
- u8 Header802_3[14];
- struct rt_eapol_packet * pMsg1;
- u32 MsgLen;
- struct rt_eapol_packet EAPOLPKT;
- u8 *pCurrentAddr = NULL;
- u8 *pmk_ptr = NULL;
- u8 group_cipher = Ndis802_11WEPDisabled;
- u8 *rsnie_ptr = NULL;
- u8 rsnie_len = 0;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n"));
-
- if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
- return;
-
- if (Elem->MsgLen <
- (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
- sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
- return;
-
- {
- pCurrentAddr = pAd->CurrentAddress;
- pmk_ptr = pAd->StaCfg.PMK;
- group_cipher = pAd->StaCfg.GroupCipher;
- rsnie_ptr = pAd->StaCfg.RSN_IE;
- rsnie_len = pAd->StaCfg.RSNIE_Len;
- }
-
- /* Store the received frame */
- pMsg1 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
- MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
-
- /* Sanity Check peer Pairwise message 1 - Replay Counter */
- if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry)
- == FALSE)
- return;
-
- /* Store Replay counter, it will use to verify message 3 and construct message 2 */
- NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter,
- LEN_KEY_DESC_REPLAY);
-
- /* Store ANonce */
- NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce,
- LEN_KEY_DESC_NONCE);
-
- /* Generate random SNonce */
- GenRandom(pAd, (u8 *) pCurrentAddr, pEntry->SNonce);
-
- {
- /* Calculate PTK(ANonce, SNonce) */
- WpaDerivePTK(pAd,
- pmk_ptr,
- pEntry->ANonce,
- pEntry->Addr,
- pEntry->SNonce, pCurrentAddr, PTK, LEN_PTK);
-
- /* Save key to PTK entry */
- NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
- }
-
- /* Update WpaState */
- pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
-
- /* Construct EAPoL message - Pairwise Msg 2 */
- /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_2, 0, /* DefaultKeyIdx */
- pEntry->SNonce, NULL, /* TxRsc */
- NULL, /* GTK */
- (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
-
- /* Make outgoing frame */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
-
- RTMPToWirelessSta(pAd, pEntry,
- Header802_3, sizeof(Header802_3), (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
-}
-
-/*
- ==========================================================================
- Description:
- When receiving the second packet of 4-way pairwisekey handshake.
- Return:
- ==========================================================================
-*/
-void PeerPairMsg2Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
-{
- u8 PTK[80];
- BOOLEAN Cancelled;
- struct rt_header_802_11 * pHeader;
- struct rt_eapol_packet EAPOLPKT;
- struct rt_eapol_packet * pMsg2;
- u32 MsgLen;
- u8 Header802_3[LENGTH_802_3];
- u8 TxTsc[6];
- u8 *pBssid = NULL;
- u8 *pmk_ptr = NULL;
- u8 *gtk_ptr = NULL;
- u8 default_key = 0;
- u8 group_cipher = Ndis802_11WEPDisabled;
- u8 *rsnie_ptr = NULL;
- u8 rsnie_len = 0;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n"));
-
- if ((!pEntry) || (!pEntry->ValidAsCLI))
- return;
-
- if (Elem->MsgLen <
- (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
- sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
- return;
-
- /* check Entry in valid State */
- if (pEntry->WpaState < AS_PTKSTART)
- return;
-
- /* pointer to 802.11 header */
- pHeader = (struct rt_header_802_11 *) Elem->Msg;
-
- /* skip 802.11_header(24-byte) and LLC_header(8) */
- pMsg2 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
- MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
-
- /* Store SNonce */
- NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce,
- LEN_KEY_DESC_NONCE);
-
- {
- /* Derive PTK */
- WpaDerivePTK(pAd, (u8 *) pmk_ptr, pEntry->ANonce, /* ANONCE */
- (u8 *) pBssid, pEntry->SNonce, /* SNONCE */
- pEntry->Addr, PTK, LEN_PTK);
-
- NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK);
- }
-
- /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
- if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry)
- == FALSE)
- return;
-
- do {
- /* delete retry timer */
- RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
-
- /* Change state */
- pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
-
- /* Increment replay counter by 1 */
- ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
-
- /* Construct EAPoL message - Pairwise Msg 3 */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry,
- group_cipher,
- EAPOL_PAIR_MSG_3,
- default_key,
- pEntry->ANonce,
- TxTsc,
- (u8 *) gtk_ptr,
- (u8 *) rsnie_ptr, rsnie_len, &EAPOLPKT);
-
- /* Make outgoing frame */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
- RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
- (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
- (pEntry->PortSecured ==
- WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
-
- pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR;
- RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
-
- /* Update State */
- pEntry->WpaState = AS_PTKINIT_NEGOTIATING;
- } while (FALSE);
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n"));
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4
-
- Arguments:
- pAd Pointer to our adapter
- Elem Message body
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void PeerPairMsg3Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
-{
- struct rt_header_802_11 * pHeader;
- u8 Header802_3[14];
- struct rt_eapol_packet EAPOLPKT;
- struct rt_eapol_packet * pMsg3;
- u32 MsgLen;
- u8 *pCurrentAddr = NULL;
- u8 group_cipher = Ndis802_11WEPDisabled;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n"));
-
- if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
- return;
-
- if (Elem->MsgLen <
- (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
- sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
- return;
-
- {
- pCurrentAddr = pAd->CurrentAddress;
- group_cipher = pAd->StaCfg.GroupCipher;
-
- }
-
- /* Record 802.11 header & the received EAPOL packet Msg3 */
- pHeader = (struct rt_header_802_11 *) Elem->Msg;
- pMsg3 = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
- MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
-
- /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE */
- if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry)
- == FALSE)
- return;
-
- /* Save Replay counter, it will use construct message 4 */
- NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter,
- LEN_KEY_DESC_REPLAY);
-
- /* Double check ANonce */
- if (!NdisEqualMemory
- (pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) {
- return;
- }
- /* Construct EAPoL message - Pairwise Msg 4 */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry, group_cipher, EAPOL_PAIR_MSG_4, 0, /* group key index not used in message 4 */
- NULL, /* Nonce not used in message 4 */
- NULL, /* TxRSC not used in message 4 */
- NULL, /* GTK not used in message 4 */
- NULL, /* RSN IE not used in message 4 */
- 0, &EAPOLPKT);
-
- /* Update WpaState */
- pEntry->WpaState = AS_PTKINITDONE;
-
- /* Update pairwise key */
- {
- struct rt_cipher_key *pSharedKey;
-
- pSharedKey = &pAd->SharedKey[BSS0][0];
-
- NdisMoveMemory(pAd->StaCfg.PTK, pEntry->PTK, LEN_PTK);
-
- /* Prepare pair-wise key information into shared key table */
- NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
- pSharedKey->KeyLen = LEN_TKIP_EK;
- NdisMoveMemory(pSharedKey->Key, &pAd->StaCfg.PTK[32],
- LEN_TKIP_EK);
- NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.PTK[48],
- LEN_TKIP_RXMICK);
- NdisMoveMemory(pSharedKey->TxMic,
- &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
- LEN_TKIP_TXMICK);
-
- /* Decide its ChiperAlg */
- if (pAd->StaCfg.PairCipher == Ndis802_11Encryption2Enabled)
- pSharedKey->CipherAlg = CIPHER_TKIP;
- else if (pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled)
- pSharedKey->CipherAlg = CIPHER_AES;
- else
- pSharedKey->CipherAlg = CIPHER_NONE;
-
- /* Update these related information to struct rt_mac_table_entry */
- pEntry = &pAd->MacTab.Content[BSSID_WCID];
- NdisMoveMemory(pEntry->PairwiseKey.Key, &pAd->StaCfg.PTK[32],
- LEN_TKIP_EK);
- NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pAd->StaCfg.PTK[48],
- LEN_TKIP_RXMICK);
- NdisMoveMemory(pEntry->PairwiseKey.TxMic,
- &pAd->StaCfg.PTK[48 + LEN_TKIP_RXMICK],
- LEN_TKIP_TXMICK);
- pEntry->PairwiseKey.CipherAlg = pSharedKey->CipherAlg;
-
- /* Update pairwise key information to ASIC Shared Key Table */
- AsicAddSharedKeyEntry(pAd,
- BSS0,
- 0,
- pSharedKey->CipherAlg,
- pSharedKey->Key,
- pSharedKey->TxMic, pSharedKey->RxMic);
-
- /* Update ASIC WCID attribute table and IVEIV table */
- RTMPAddWcidAttributeEntry(pAd,
- BSS0,
- 0, pSharedKey->CipherAlg, pEntry);
-
- }
-
- /* open 802.1x port control and privacy filter */
- if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
- pEntry->AuthMode == Ndis802_11AuthModeWPA2) {
- pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
- pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
-
- STA_PORT_SECURED(pAd);
- /* Indicate Connected for GUI */
- pAd->IndicateMediaState = NdisMediaStateConnected;
- DBGPRINT(RT_DEBUG_TRACE,
- ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
- GetAuthMode(pEntry->AuthMode),
- GetEncryptType(pEntry->WepStatus),
- GetEncryptType(group_cipher)));
- } else {
- }
-
- /* Init 802.3 header and send out */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
- RTMPToWirelessSta(pAd, pEntry,
- Header802_3, sizeof(Header802_3),
- (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, TRUE);
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
-}
-
-/*
- ==========================================================================
- Description:
- When receiving the last packet of 4-way pairwisekey handshake.
- Initialize 2-way groupkey handshake following.
- Return:
- ==========================================================================
-*/
-void PeerPairMsg4Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
-{
- struct rt_eapol_packet * pMsg4;
- struct rt_header_802_11 * pHeader;
- u32 MsgLen;
- BOOLEAN Cancelled;
- u8 group_cipher = Ndis802_11WEPDisabled;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n"));
-
- do {
- if ((!pEntry) || (!pEntry->ValidAsCLI))
- break;
-
- if (Elem->MsgLen <
- (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H +
- sizeof(struct rt_key_descripter) - MAX_LEN_OF_RSNIE - 2))
- break;
-
- if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING)
- break;
-
- /* pointer to 802.11 header */
- pHeader = (struct rt_header_802_11 *) Elem->Msg;
-
- /* skip 802.11_header(24-byte) and LLC_header(8) */
- pMsg4 =
- (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
- MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
-
- /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC */
- if (PeerWpaMessageSanity
- (pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE)
- break;
-
- /* 3. uses the MLME.SETKEYS.request to configure PTK into MAC */
- NdisZeroMemory(&pEntry->PairwiseKey, sizeof(struct rt_cipher_key));
-
- /* reset IVEIV in Asic */
- AsicUpdateWCIDIVEIV(pAd, pEntry->Aid, 1, 0);
-
- pEntry->PairwiseKey.KeyLen = LEN_TKIP_EK;
- NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[32],
- LEN_TKIP_EK);
- NdisMoveMemory(pEntry->PairwiseKey.RxMic,
- &pEntry->PTK[TKIP_AP_RXMICK_OFFSET],
- LEN_TKIP_RXMICK);
- NdisMoveMemory(pEntry->PairwiseKey.TxMic,
- &pEntry->PTK[TKIP_AP_TXMICK_OFFSET],
- LEN_TKIP_TXMICK);
-
- /* Set pairwise key to Asic */
- {
- pEntry->PairwiseKey.CipherAlg = CIPHER_NONE;
- if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
- pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP;
- else if (pEntry->WepStatus ==
- Ndis802_11Encryption3Enabled)
- pEntry->PairwiseKey.CipherAlg = CIPHER_AES;
-
- /* Add Pair-wise key to Asic */
- AsicAddPairwiseKeyEntry(pAd,
- pEntry->Addr,
- (u8)pEntry->Aid,
- &pEntry->PairwiseKey);
-
- /* update WCID attribute table and IVEIV table for this entry */
- RTMPAddWcidAttributeEntry(pAd,
- pEntry->apidx,
- 0,
- pEntry->PairwiseKey.CipherAlg,
- pEntry);
- }
-
- /* 4. upgrade state */
- pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
- pEntry->WpaState = AS_PTKINITDONE;
- pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
-
- if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
- pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) {
- pEntry->GTKState = REKEY_ESTABLISHED;
- RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
-
- /* send wireless event - for set key done WPA2 */
- if (pAd->CommonCfg.bWirelessEvent)
- RTMPSendWirelessEvent(pAd,
- IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
- pEntry->Addr,
- pEntry->apidx, 0);
-
- DBGPRINT(RT_DEBUG_OFF,
- ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
- pEntry->AuthMode,
- GetAuthMode(pEntry->AuthMode),
- pEntry->WepStatus,
- GetEncryptType(pEntry->WepStatus),
- group_cipher, GetEncryptType(group_cipher)));
- } else {
- /* 5. init Group 2-way handshake if necessary. */
- WPAStart2WayGroupHS(pAd, pEntry);
-
- pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR;
- RTMPModTimer(&pEntry->RetryTimer,
- PEER_MSG3_RETRY_EXEC_INTV);
- }
- } while (FALSE);
-
-}
-
-/*
- ==========================================================================
- Description:
- This is a function to send the first packet of 2-way groupkey handshake
- Return:
-
- ==========================================================================
-*/
-void WPAStart2WayGroupHS(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
-{
- u8 Header802_3[14];
- u8 TxTsc[6];
- struct rt_eapol_packet EAPOLPKT;
- u8 group_cipher = Ndis802_11WEPDisabled;
- u8 default_key = 0;
- u8 *gnonce_ptr = NULL;
- u8 *gtk_ptr = NULL;
- u8 *pBssid = NULL;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n"));
-
- if ((!pEntry) || (!pEntry->ValidAsCLI))
- return;
-
- do {
- /* Increment replay counter by 1 */
- ADD_ONE_To_64BIT_VAR(pEntry->R_Counter);
-
- /* Construct EAPoL message - Group Msg 1 */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry,
- group_cipher,
- EAPOL_GROUP_MSG_1,
- default_key,
- (u8 *) gnonce_ptr,
- TxTsc, (u8 *) gtk_ptr, NULL, 0, &EAPOLPKT);
-
- /* Make outgoing frame */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
- RTMPToWirelessSta(pAd, pEntry,
- Header802_3, LENGTH_802_3,
- (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4,
- FALSE);
-
- } while (FALSE);
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n"));
-
- return;
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Process Group key 2-way handshaking
-
- Arguments:
- pAd Pointer to our adapter
- Elem Message body
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void PeerGroupMsg1Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry, struct rt_mlme_queue_elem *Elem)
-{
- u8 Header802_3[14];
- struct rt_eapol_packet EAPOLPKT;
- struct rt_eapol_packet * pGroup;
- u32 MsgLen;
- BOOLEAN Cancelled;
- u8 default_key = 0;
- u8 group_cipher = Ndis802_11WEPDisabled;
- u8 *pCurrentAddr = NULL;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n"));
-
- if ((!pEntry) || ((!pEntry->ValidAsCLI) && (!pEntry->ValidAsApCli)))
- return;
-
- {
- pCurrentAddr = pAd->CurrentAddress;
- group_cipher = pAd->StaCfg.GroupCipher;
- default_key = pAd->StaCfg.DefaultKeyId;
- }
-
- /* Process Group Message 1 frame. skip 802.11 header(24) & LLC_SNAP header(8) */
- pGroup = (struct rt_eapol_packet *) & Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
- MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
-
- /* Sanity Check peer group message 1 - Replay Counter, MIC, RSNIE */
- if (PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pEntry)
- == FALSE)
- return;
-
- /* delete retry timer */
- RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
-
- /* Save Replay counter, it will use to construct message 2 */
- NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter,
- LEN_KEY_DESC_REPLAY);
-
- /* Construct EAPoL message - Group Msg 2 */
- NdisZeroMemory(&EAPOLPKT, sizeof(struct rt_eapol_packet));
- ConstructEapolMsg(pEntry, group_cipher, EAPOL_GROUP_MSG_2, default_key, NULL, /* Nonce not used */
- NULL, /* TxRSC not used */
- NULL, /* GTK not used */
- NULL, /* RSN IE not used */
- 0, &EAPOLPKT);
-
- /* open 802.1x port control and privacy filter */
- pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
- pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
-
- STA_PORT_SECURED(pAd);
- /* Indicate Connected for GUI */
- pAd->IndicateMediaState = NdisMediaStateConnected;
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("PeerGroupMsg1Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
- GetAuthMode(pEntry->AuthMode),
- GetEncryptType(pEntry->WepStatus),
- GetEncryptType(group_cipher)));
-
- /* init header and Fill Packet and send Msg 2 to authenticator */
- MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
- RTMPToWirelessSta(pAd, pEntry,
- Header802_3, sizeof(Header802_3),
- (u8 *)& EAPOLPKT,
- CONV_ARRARY_TO_u16(EAPOLPKT.Body_Len) + 4, FALSE);
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("<=== PeerGroupMsg1Action: sned group message 2\n"));
-}
-
-/*
- ==========================================================================
- Description:
- When receiving the last packet of 2-way groupkey handshake.
- Return:
- ==========================================================================
-*/
-void PeerGroupMsg2Action(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry,
- void * Msg, u32 MsgLen)
-{
- u32 Len;
- u8 *pData;
- BOOLEAN Cancelled;
- struct rt_eapol_packet * pMsg2;
- u8 group_cipher = Ndis802_11WEPDisabled;
-
- DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n"));
-
- do {
- if ((!pEntry) || (!pEntry->ValidAsCLI))
- break;
-
- if (MsgLen <
- (LENGTH_802_1_H + LENGTH_EAPOL_H + sizeof(struct rt_key_descripter) -
- MAX_LEN_OF_RSNIE - 2))
- break;
-
- if (pEntry->WpaState != AS_PTKINITDONE)
- break;
-
- pData = (u8 *)Msg;
- pMsg2 = (struct rt_eapol_packet *) (pData + LENGTH_802_1_H);
- Len = MsgLen - LENGTH_802_1_H;
-
- /* Sanity Check peer group message 2 - Replay Counter, MIC */
- if (PeerWpaMessageSanity
- (pAd, pMsg2, Len, EAPOL_GROUP_MSG_2, pEntry) == FALSE)
- break;
-
- /* 3. upgrade state */
-
- RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled);
- pEntry->GTKState = REKEY_ESTABLISHED;
-
- if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2)
- || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)) {
- /* send wireless event - for set key done WPA2 */
- if (pAd->CommonCfg.bWirelessEvent)
- RTMPSendWirelessEvent(pAd,
- IW_SET_KEY_DONE_WPA2_EVENT_FLAG,
- pEntry->Addr,
- pEntry->apidx, 0);
-
- DBGPRINT(RT_DEBUG_OFF,
- ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
- pEntry->AuthMode,
- GetAuthMode(pEntry->AuthMode),
- pEntry->WepStatus,
- GetEncryptType(pEntry->WepStatus),
- group_cipher, GetEncryptType(group_cipher)));
- } else {
- /* send wireless event - for set key done WPA */
- if (pAd->CommonCfg.bWirelessEvent)
- RTMPSendWirelessEvent(pAd,
- IW_SET_KEY_DONE_WPA1_EVENT_FLAG,
- pEntry->Addr,
- pEntry->apidx, 0);
-
- DBGPRINT(RT_DEBUG_OFF,
- ("AP SETKEYS DONE - WPA1, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
- pEntry->AuthMode,
- GetAuthMode(pEntry->AuthMode),
- pEntry->WepStatus,
- GetEncryptType(pEntry->WepStatus),
- group_cipher, GetEncryptType(group_cipher)));
- }
- } while (FALSE);
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Classify WPA EAP message type
-
- Arguments:
- EAPType Value of EAP message type
- MsgType Internal Message definition for MLME state machine
-
- Return Value:
- TRUE Found appropriate message type
- FALSE No appropriate message type
-
- IRQL = DISPATCH_LEVEL
-
- Note:
- All these constants are defined in wpa.h
- For supplicant, there is only EAPOL Key message available
-
- ========================================================================
-*/
-BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType)
-{
- switch (EAPType) {
- case EAPPacket:
- *MsgType = MT2_EAPPacket;
- break;
- case EAPOLStart:
- *MsgType = MT2_EAPOLStart;
- break;
- case EAPOLLogoff:
- *MsgType = MT2_EAPOLLogoff;
- break;
- case EAPOLKey:
- *MsgType = MT2_EAPOLKey;
- break;
- case EAPOLASFAlert:
- *MsgType = MT2_EAPOLASFAlert;
- break;
- default:
- return FALSE;
- }
- return TRUE;
-}
-
-/*
- ========================================================================
-
- Routine Description:
- The pseudo-random function(PRF) that hashes various inputs to
- derive a pseudo-random value. To add liveness to the pseudo-random
- value, a nonce should be one of the inputs.
-
- It is used to generate PTK, GTK or some specific random value.
-
- Arguments:
- u8 *key, - the key material for HMAC_SHA1 use
- int key_len - the length of key
- u8 *prefix - a prefix label
- int prefix_len - the length of the label
- u8 *data - a specific data with variable length
- int data_len - the length of a specific data
- int len - the output length
-
- Return Value:
- u8 *output - the calculated result
-
- Note:
- 802.11i-2004 Annex H.3
-
- ========================================================================
-*/
-void PRF(u8 * key,
- int key_len,
- u8 * prefix,
- int prefix_len,
- u8 * data, int data_len, u8 * output, int len)
-{
- int i;
- u8 *input;
- int currentindex = 0;
- int total_len;
-
- /* Allocate memory for input */
- os_alloc_mem(NULL, (u8 **) & input, 1024);
-
- if (input == NULL) {
- DBGPRINT(RT_DEBUG_ERROR, ("PRF: no memory!\n"));
- return;
- }
- /* Generate concatenation input */
- NdisMoveMemory(input, prefix, prefix_len);
-
- /* Concatenate a single octet containing 0 */
- input[prefix_len] = 0;
-
- /* Concatenate specific data */
- NdisMoveMemory(&input[prefix_len + 1], data, data_len);
- total_len = prefix_len + 1 + data_len;
-
- /* Concatenate a single octet containing 0 */
- /* This octet shall be update later */
- input[total_len] = 0;
- total_len++;
-
- /* Iterate to calculate the result by hmac-sha-1 */
- /* Then concatenate to last result */
- for (i = 0; i < (len + 19) / 20; i++) {
- HMAC_SHA1(key, key_len, input, total_len, &output[currentindex],
- SHA1_DIGEST_SIZE);
- currentindex += 20;
-
- /* update the last octet */
- input[total_len - 1]++;
- }
- os_free_mem(NULL, input);
-}
-
-/*
-* F(P, S, c, i) = U1 xor U2 xor ... Uc
-* U1 = PRF(P, S || Int(i))
-* U2 = PRF(P, U1)
-* Uc = PRF(P, Uc-1)
-*/
-
-static void F(char *password, unsigned char *ssid, int ssidlength,
- int iterations, int count, unsigned char *output)
-{
- unsigned char digest[36], digest1[SHA1_DIGEST_SIZE];
- int i, j;
-
- /* U1 = PRF(P, S || int(i)) */
- memcpy(digest, ssid, ssidlength);
- digest[ssidlength] = (unsigned char)((count >> 24) & 0xff);
- digest[ssidlength + 1] = (unsigned char)((count >> 16) & 0xff);
- digest[ssidlength + 2] = (unsigned char)((count >> 8) & 0xff);
- digest[ssidlength + 3] = (unsigned char)(count & 0xff);
- HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest, ssidlength + 4, digest1, SHA1_DIGEST_SIZE); /* for WPA update */
-
- /* output = U1 */
- memcpy(output, digest1, SHA1_DIGEST_SIZE);
-
- for (i = 1; i < iterations; i++) {
- /* Un = PRF(P, Un-1) */
- HMAC_SHA1((unsigned char *)password, (int)strlen(password), digest1, SHA1_DIGEST_SIZE, digest, SHA1_DIGEST_SIZE); /* for WPA update */
- memcpy(digest1, digest, SHA1_DIGEST_SIZE);
-
- /* output = output xor Un */
- for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
- output[j] ^= digest[j];
- }
- }
-}
-
-/*
-* password - ascii string up to 63 characters in length
-* ssid - octet string up to 32 octets
-* ssidlength - length of ssid in octets
-* output must be 40 octets in length and outputs 256 bits of key
-*/
-int PasswordHash(char *password, u8 *ssid, int ssidlength, u8 *output)
-{
- if ((strlen(password) > 63) || (ssidlength > 32))
- return 0;
-
- F(password, ssid, ssidlength, 4096, 1, output);
- F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]);
- return 1;
-}
-
-/*
- ========================================================================
-
- Routine Description:
- It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK.
- It shall be called by 4-way handshake processing.
-
- Arguments:
- pAd - pointer to our pAdapter context
- PMK - pointer to PMK
- ANonce - pointer to ANonce
- AA - pointer to Authenticator Address
- SNonce - pointer to SNonce
- SA - pointer to Supplicant Address
- len - indicate the length of PTK (octet)
-
- Return Value:
- Output pointer to the PTK
-
- Note:
- Refer to IEEE 802.11i-2004 8.5.1.2
-
- ========================================================================
-*/
-void WpaDerivePTK(struct rt_rtmp_adapter *pAd,
- u8 * PMK,
- u8 * ANonce,
- u8 * AA,
- u8 * SNonce,
- u8 * SA, u8 * output, u32 len)
-{
- u8 concatenation[76];
- u32 CurrPos = 0;
- u8 temp[32];
- u8 Prefix[] =
- { 'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ',
- 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'
- };
-
- /* initiate the concatenation input */
- NdisZeroMemory(temp, sizeof(temp));
- NdisZeroMemory(concatenation, 76);
-
- /* Get smaller address */
- if (RTMPCompareMemory(SA, AA, 6) == 1)
- NdisMoveMemory(concatenation, AA, 6);
- else
- NdisMoveMemory(concatenation, SA, 6);
- CurrPos += 6;
-
- /* Get larger address */
- if (RTMPCompareMemory(SA, AA, 6) == 1)
- NdisMoveMemory(&concatenation[CurrPos], SA, 6);
- else
- NdisMoveMemory(&concatenation[CurrPos], AA, 6);
-
- /* store the larger mac address for backward compatible of */
- /* ralink proprietary STA-key issue */
- NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN);
- CurrPos += 6;
-
- /* Get smaller Nonce */
- if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
- NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
- else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
- NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
- else
- NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
- CurrPos += 32;
-
- /* Get larger Nonce */
- if (RTMPCompareMemory(ANonce, SNonce, 32) == 0)
- NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue */
- else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1)
- NdisMoveMemory(&concatenation[CurrPos], ANonce, 32);
- else
- NdisMoveMemory(&concatenation[CurrPos], SNonce, 32);
- CurrPos += 32;
-
- hex_dump("concatenation=", concatenation, 76);
-
- /* Use PRF to generate PTK */
- PRF(PMK, LEN_MASTER_KEY, Prefix, 22, concatenation, 76, output, len);
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Generate random number by software.
-
- Arguments:
- pAd - pointer to our pAdapter context
- macAddr - pointer to local MAC address
-
- Return Value:
-
- Note:
- 802.1ii-2004 Annex H.5
-
- ========================================================================
-*/
-void GenRandom(struct rt_rtmp_adapter *pAd, u8 * macAddr, u8 * random)
-{
- int i, curr;
- u8 local[80], KeyCounter[32];
- u8 result[80];
- unsigned long CurrentTime;
- u8 prefix[] =
- { 'I', 'n', 'i', 't', ' ', 'C', 'o', 'u', 'n', 't', 'e', 'r' };
-
- /* Zero the related information */
- NdisZeroMemory(result, 80);
- NdisZeroMemory(local, 80);
- NdisZeroMemory(KeyCounter, 32);
-
- for (i = 0; i < 32; i++) {
- /* copy the local MAC address */
- COPY_MAC_ADDR(local, macAddr);
- curr = MAC_ADDR_LEN;
-
- /* concatenate the current time */
- NdisGetSystemUpTime(&CurrentTime);
- NdisMoveMemory(&local[curr], &CurrentTime, sizeof(CurrentTime));
- curr += sizeof(CurrentTime);
-
- /* concatenate the last result */
- NdisMoveMemory(&local[curr], result, 32);
- curr += 32;
-
- /* concatenate a variable */
- NdisMoveMemory(&local[curr], &i, 2);
- curr += 2;
-
- /* calculate the result */
- PRF(KeyCounter, 32, prefix, 12, local, curr, result, 32);
- }
-
- NdisMoveMemory(random, result, 32);
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Build cipher suite in RSN-IE.
- It only shall be called by RTMPMakeRSNIE.
-
- Arguments:
- pAd - pointer to our pAdapter context
- ElementID - indicate the WPA1 or WPA2
- WepStatus - indicate the encryption type
- bMixCipher - a boolean to indicate the pairwise cipher and group
- cipher are the same or not
-
- Return Value:
-
- Note:
-
- ========================================================================
-*/
-static void RTMPMakeRsnIeCipher(struct rt_rtmp_adapter *pAd,
- u8 ElementID,
- u32 WepStatus,
- IN BOOLEAN bMixCipher,
- u8 FlexibleCipher,
- u8 *pRsnIe, u8 * rsn_len)
-{
- u8 PairwiseCnt;
-
- *rsn_len = 0;
-
- /* decide WPA2 or WPA1 */
- if (ElementID == Wpa2Ie) {
- struct rt_rsnie2 *pRsnie_cipher = (struct rt_rsnie2 *)pRsnIe;
-
- /* Assign the verson as 1 */
- pRsnie_cipher->version = 1;
-
- switch (WepStatus) {
- /* TKIP mode */
- case Ndis802_11Encryption2Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
- pRsnie_cipher->ucount = 1;
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA2_TKIP, 4);
- *rsn_len = sizeof(struct rt_rsnie2);
- break;
-
- /* AES mode */
- case Ndis802_11Encryption3Enabled:
- if (bMixCipher)
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA2_TKIP, 4);
- else
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA2_CCMP, 4);
- pRsnie_cipher->ucount = 1;
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA2_CCMP, 4);
- *rsn_len = sizeof(struct rt_rsnie2);
- break;
-
- /* TKIP-AES mix mode */
- case Ndis802_11Encryption4Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4);
-
- PairwiseCnt = 1;
- /* Insert WPA2 TKIP as the first pairwise cipher */
- if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) {
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA2_TKIP, 4);
- /* Insert WPA2 AES as the secondary pairwise cipher */
- if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) {
- NdisMoveMemory(pRsnie_cipher->ucast[0].
- oui + 4, OUI_WPA2_CCMP,
- 4);
- PairwiseCnt = 2;
- }
- } else {
- /* Insert WPA2 AES as the first pairwise cipher */
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA2_CCMP, 4);
- }
-
- pRsnie_cipher->ucount = PairwiseCnt;
- *rsn_len = sizeof(struct rt_rsnie2) + (4 * (PairwiseCnt - 1));
- break;
- }
-
- if ((pAd->OpMode == OPMODE_STA) &&
- (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
- (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
- u32 GroupCipher = pAd->StaCfg.GroupCipher;
- switch (GroupCipher) {
- case Ndis802_11GroupWEP40Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA2_WEP40, 4);
- break;
- case Ndis802_11GroupWEP104Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA2_WEP104, 4);
- break;
- }
- }
- /* swap for big-endian platform */
- pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
- pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
- } else {
- struct rt_rsnie *pRsnie_cipher = (struct rt_rsnie *)pRsnIe;
-
- /* Assign OUI and version */
- NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4);
- pRsnie_cipher->version = 1;
-
- switch (WepStatus) {
- /* TKIP mode */
- case Ndis802_11Encryption2Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
- pRsnie_cipher->ucount = 1;
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA_TKIP, 4);
- *rsn_len = sizeof(struct rt_rsnie);
- break;
-
- /* AES mode */
- case Ndis802_11Encryption3Enabled:
- if (bMixCipher)
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA_TKIP, 4);
- else
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA_CCMP, 4);
- pRsnie_cipher->ucount = 1;
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA_CCMP, 4);
- *rsn_len = sizeof(struct rt_rsnie);
- break;
-
- /* TKIP-AES mix mode */
- case Ndis802_11Encryption4Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4);
-
- PairwiseCnt = 1;
- /* Insert WPA TKIP as the first pairwise cipher */
- if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) {
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA_TKIP, 4);
- /* Insert WPA AES as the secondary pairwise cipher */
- if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) {
- NdisMoveMemory(pRsnie_cipher->ucast[0].
- oui + 4, OUI_WPA_CCMP,
- 4);
- PairwiseCnt = 2;
- }
- } else {
- /* Insert WPA AES as the first pairwise cipher */
- NdisMoveMemory(pRsnie_cipher->ucast[0].oui,
- OUI_WPA_CCMP, 4);
- }
-
- pRsnie_cipher->ucount = PairwiseCnt;
- *rsn_len = sizeof(struct rt_rsnie) + (4 * (PairwiseCnt - 1));
- break;
- }
-
- if ((pAd->OpMode == OPMODE_STA) &&
- (pAd->StaCfg.GroupCipher != Ndis802_11Encryption2Enabled) &&
- (pAd->StaCfg.GroupCipher != Ndis802_11Encryption3Enabled)) {
- u32 GroupCipher = pAd->StaCfg.GroupCipher;
- switch (GroupCipher) {
- case Ndis802_11GroupWEP40Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA_WEP40, 4);
- break;
- case Ndis802_11GroupWEP104Enabled:
- NdisMoveMemory(pRsnie_cipher->mcast,
- OUI_WPA_WEP104, 4);
- break;
- }
- }
- /* swap for big-endian platform */
- pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version);
- pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount);
- }
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Build AKM suite in RSN-IE.
- It only shall be called by RTMPMakeRSNIE.
-
- Arguments:
- pAd - pointer to our pAdapter context
- ElementID - indicate the WPA1 or WPA2
- AuthMode - indicate the authentication mode
- apidx - indicate the interface index
-
- Return Value:
-
- Note:
-
- ========================================================================
-*/
-static void RTMPMakeRsnIeAKM(struct rt_rtmp_adapter *pAd,
- u8 ElementID,
- u32 AuthMode,
- u8 apidx,
- u8 *pRsnIe, u8 * rsn_len)
-{
- struct rt_rsnie_auth *pRsnie_auth;
- u8 AkmCnt = 1; /* default as 1 */
-
- pRsnie_auth = (struct rt_rsnie_auth *) (pRsnIe + (*rsn_len));
-
- /* decide WPA2 or WPA1 */
- if (ElementID == Wpa2Ie) {
-
- switch (AuthMode) {
- case Ndis802_11AuthModeWPA2:
- case Ndis802_11AuthModeWPA1WPA2:
- NdisMoveMemory(pRsnie_auth->auth[0].oui,
- OUI_WPA2_8021X_AKM, 4);
- break;
-
- case Ndis802_11AuthModeWPA2PSK:
- case Ndis802_11AuthModeWPA1PSKWPA2PSK:
- NdisMoveMemory(pRsnie_auth->auth[0].oui,
- OUI_WPA2_PSK_AKM, 4);
- break;
- default:
- AkmCnt = 0;
- break;
-
- }
- } else {
- switch (AuthMode) {
- case Ndis802_11AuthModeWPA:
- case Ndis802_11AuthModeWPA1WPA2:
- NdisMoveMemory(pRsnie_auth->auth[0].oui,
- OUI_WPA_8021X_AKM, 4);
- break;
-
- case Ndis802_11AuthModeWPAPSK:
- case Ndis802_11AuthModeWPA1PSKWPA2PSK:
- NdisMoveMemory(pRsnie_auth->auth[0].oui,
- OUI_WPA_PSK_AKM, 4);
- break;
-
- case Ndis802_11AuthModeWPANone:
- NdisMoveMemory(pRsnie_auth->auth[0].oui,
- OUI_WPA_NONE_AKM, 4);
- break;
- default:
- AkmCnt = 0;
- break;
- }
- }
-
- pRsnie_auth->acount = AkmCnt;
- pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount);
-
- /* update current RSNIE length */
- (*rsn_len) += (sizeof(struct rt_rsnie_auth) + (4 * (AkmCnt - 1)));
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Build capability in RSN-IE.
- It only shall be called by RTMPMakeRSNIE.
-
- Arguments:
- pAd - pointer to our pAdapter context
- ElementID - indicate the WPA1 or WPA2
- apidx - indicate the interface index
-
- Return Value:
-
- Note:
-
- ========================================================================
-*/
-static void RTMPMakeRsnIeCap(struct rt_rtmp_adapter *pAd,
- u8 ElementID,
- u8 apidx,
- u8 *pRsnIe, u8 * rsn_len)
-{
- RSN_CAPABILITIES *pRSN_Cap;
-
- /* it could be ignored in WPA1 mode */
- if (ElementID == WpaIe)
- return;
-
- pRSN_Cap = (RSN_CAPABILITIES *) (pRsnIe + (*rsn_len));
-
- pRSN_Cap->word = cpu2le16(pRSN_Cap->word);
-
- (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length */
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Build RSN IE context. It is not included element-ID and length.
-
- Arguments:
- pAd - pointer to our pAdapter context
- AuthMode - indicate the authentication mode
- WepStatus - indicate the encryption type
- apidx - indicate the interface index
-
- Return Value:
-
- Note:
-
- ========================================================================
-*/
-void RTMPMakeRSNIE(struct rt_rtmp_adapter *pAd,
- u32 AuthMode, u32 WepStatus, u8 apidx)
-{
- u8 *pRsnIe = NULL; /* primary RSNIE */
- u8 *rsnielen_cur_p = 0; /* the length of the primary RSNIE */
- u8 *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */
- u8 PrimaryRsnie;
- BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different */
- u8 p_offset;
- WPA_MIX_PAIR_CIPHER FlexibleCipher = WPA_TKIPAES_WPA2_TKIPAES; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode */
-
- rsnielen_cur_p = NULL;
- rsnielen_ex_cur_p = NULL;
-
- {
- {
- if (pAd->StaCfg.WpaSupplicantUP !=
- WPA_SUPPLICANT_DISABLE) {
- if (AuthMode < Ndis802_11AuthModeWPA)
- return;
- } else {
- /* Support WPAPSK or WPA2PSK in STA-Infra mode */
- /* Support WPANone in STA-Adhoc mode */
- if ((AuthMode != Ndis802_11AuthModeWPAPSK) &&
- (AuthMode != Ndis802_11AuthModeWPA2PSK) &&
- (AuthMode != Ndis802_11AuthModeWPANone)
- )
- return;
- }
-
- DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(STA)\n"));
-
- /* Zero RSNIE context */
- pAd->StaCfg.RSNIE_Len = 0;
- NdisZeroMemory(pAd->StaCfg.RSN_IE, MAX_LEN_OF_RSNIE);
-
- /* Pointer to RSNIE */
- rsnielen_cur_p = &pAd->StaCfg.RSNIE_Len;
- pRsnIe = pAd->StaCfg.RSN_IE;
-
- bMixCipher = pAd->StaCfg.bMixCipher;
- }
- }
-
- /* indicate primary RSNIE as WPA or WPA2 */
- if ((AuthMode == Ndis802_11AuthModeWPA) ||
- (AuthMode == Ndis802_11AuthModeWPAPSK) ||
- (AuthMode == Ndis802_11AuthModeWPANone) ||
- (AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
- (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
- PrimaryRsnie = WpaIe;
- else
- PrimaryRsnie = Wpa2Ie;
-
- {
- /* Build the primary RSNIE */
- /* 1. insert cipher suite */
- RTMPMakeRsnIeCipher(pAd, PrimaryRsnie, WepStatus, bMixCipher,
- FlexibleCipher, pRsnIe, &p_offset);
-
- /* 2. insert AKM */
- RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe,
- &p_offset);
-
- /* 3. insert capability */
- RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset);
- }
-
- /* 4. update the RSNIE length */
- *rsnielen_cur_p = p_offset;
-
- hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p));
-
-}
-
-/*
- ==========================================================================
- Description:
- Check whether the received frame is EAP frame.
-
- Arguments:
- pAd - pointer to our pAdapter context
- pEntry - pointer to active entry
- pData - the received frame
- DataByteCount - the received frame's length
- FromWhichBSSID - indicate the interface index
-
- Return:
- TRUE - This frame is EAP frame
- FALSE - otherwise
- ==========================================================================
-*/
-BOOLEAN RTMPCheckWPAframe(struct rt_rtmp_adapter *pAd,
- struct rt_mac_table_entry *pEntry,
- u8 *pData,
- unsigned long DataByteCount, u8 FromWhichBSSID)
-{
- unsigned long Body_len;
- BOOLEAN Cancelled;
-
- if (DataByteCount < (LENGTH_802_1_H + LENGTH_EAPOL_H))
- return FALSE;
-
- /* Skip LLC header */
- if (NdisEqualMemory(SNAP_802_1H, pData, 6) ||
- /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL */
- NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) {
- pData += 6;
- }
- /* Skip 2-bytes EAPoL type */
- if (NdisEqualMemory(EAPOL, pData, 2)) {
- pData += 2;
- } else
- return FALSE;
-
- switch (*(pData + 1)) {
- case EAPPacket:
- Body_len = (*(pData + 2) << 8) | (*(pData + 3));
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAP-Packet frame, TYPE = 0, Length = %ld\n",
- Body_len));
- break;
- case EAPOLStart:
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAPOL-Start frame, TYPE = 1 \n"));
- if (pEntry->EnqueueEapolStartTimerRunning !=
- EAPOL_START_DISABLE) {
- DBGPRINT(RT_DEBUG_TRACE,
- ("Cancel the EnqueueEapolStartTimerRunning \n"));
- RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer,
- &Cancelled);
- pEntry->EnqueueEapolStartTimerRunning =
- EAPOL_START_DISABLE;
- }
- break;
- case EAPOLLogoff:
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAPOLLogoff frame, TYPE = 2 \n"));
- break;
- case EAPOLKey:
- Body_len = (*(pData + 2) << 8) | (*(pData + 3));
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n",
- Body_len));
- break;
- case EAPOLASFAlert:
- DBGPRINT(RT_DEBUG_TRACE,
- ("Receive EAPOLASFAlert frame, TYPE = 4 \n"));
- break;
- default:
- return FALSE;
-
- }
- return TRUE;
-}
-
-/*
- ==========================================================================
- Description:
- Report the EAP message type
-
- Arguments:
- msg - EAPOL_PAIR_MSG_1
- EAPOL_PAIR_MSG_2
- EAPOL_PAIR_MSG_3
- EAPOL_PAIR_MSG_4
- EAPOL_GROUP_MSG_1
- EAPOL_GROUP_MSG_2
-
- Return:
- message type string
-
- ==========================================================================
-*/
-char *GetEapolMsgType(char msg)
-{
- if (msg == EAPOL_PAIR_MSG_1)
- return "Pairwise Message 1";
- else if (msg == EAPOL_PAIR_MSG_2)
- return "Pairwise Message 2";
- else if (msg == EAPOL_PAIR_MSG_3)
- return "Pairwise Message 3";
- else if (msg == EAPOL_PAIR_MSG_4)
- return "Pairwise Message 4";
- else if (msg == EAPOL_GROUP_MSG_1)
- return "Group Message 1";
- else if (msg == EAPOL_GROUP_MSG_2)
- return "Group Message 2";
- else
- return "Invalid Message";
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Check Sanity RSN IE of EAPoL message
-
- Arguments:
-
- Return Value:
-
- ========================================================================
-*/
-BOOLEAN RTMPCheckRSNIE(struct rt_rtmp_adapter *pAd,
- u8 *pData,
- u8 DataLen,
- struct rt_mac_table_entry *pEntry, u8 * Offset)
-{
- u8 *pVIE;
- u8 len;
- struct rt_eid * pEid;
- BOOLEAN result = FALSE;
-
- pVIE = pData;
- len = DataLen;
- *Offset = 0;
-
- while (len > sizeof(struct rt_rsnie2)) {
- pEid = (struct rt_eid *) pVIE;
- /* WPA RSN IE */
- if ((pEid->Eid == IE_WPA)
- && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))) {
- if ((pEntry->AuthMode == Ndis802_11AuthModeWPA
- || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
- &&
- (NdisEqualMemory
- (pVIE, pEntry->RSN_IE, pEntry->RSNIE_Len))
- && (pEntry->RSNIE_Len == (pEid->Len + 2))) {
- result = TRUE;
- }
-
- *Offset += (pEid->Len + 2);
- }
- /* WPA2 RSN IE */
- else if ((pEid->Eid == IE_RSN)
- && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))) {
- if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2
- || pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
- && (pEid->Eid == pEntry->RSN_IE[0])
- && ((pEid->Len + 2) >= pEntry->RSNIE_Len)
- &&
- (NdisEqualMemory
- (pEid->Octet, &pEntry->RSN_IE[2],
- pEntry->RSNIE_Len - 2))) {
-
- result = TRUE;
- }
-
- *Offset += (pEid->Len + 2);
- } else {
- break;
- }
-
- pVIE += (pEid->Len + 2);
- len -= (pEid->Len + 2);
- }
-
- return result;
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK.
- GTK is encaptulated in KDE format at p.83 802.11i D10
-
- Arguments:
-
- Return Value:
-
- Note:
- 802.11i D10
-
- ========================================================================
-*/
-BOOLEAN RTMPParseEapolKeyData(struct rt_rtmp_adapter *pAd,
- u8 *pKeyData,
- u8 KeyDataLen,
- u8 GroupKeyIndex,
- u8 MsgType,
- IN BOOLEAN bWPA2, struct rt_mac_table_entry *pEntry)
-{
- struct rt_kde_encap * pKDE = NULL;
- u8 *pMyKeyData = pKeyData;
- u8 KeyDataLength = KeyDataLen;
- u8 GTKLEN = 0;
- u8 DefaultIdx = 0;
- u8 skip_offset;
-
- /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it */
- if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) {
- /* Check RSN IE whether it is WPA2/WPA2PSK */
- if (!RTMPCheckRSNIE
- (pAd, pKeyData, KeyDataLen, pEntry, &skip_offset)) {
- /* send wireless event - for RSN IE different */
- if (pAd->CommonCfg.bWirelessEvent)
- RTMPSendWirelessEvent(pAd,
- IW_RSNIE_DIFF_EVENT_FLAG,
- pEntry->Addr,
- pEntry->apidx, 0);
-
- DBGPRINT(RT_DEBUG_ERROR,
- ("RSN_IE Different in msg %d of 4-way handshake!\n",
- MsgType));
- hex_dump("Receive RSN_IE ", pKeyData, KeyDataLen);
- hex_dump("Desired RSN_IE ", pEntry->RSN_IE,
- pEntry->RSNIE_Len);
-
- return FALSE;
- } else {
- if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) {
- WpaShowAllsuite(pMyKeyData, skip_offset);
-
- /* skip RSN IE */
- pMyKeyData += skip_offset;
- KeyDataLength -= skip_offset;
- DBGPRINT(RT_DEBUG_TRACE,
- ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n",
- skip_offset));
- } else
- return TRUE;
- }
- }
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n",
- KeyDataLength));
- /*hex_dump("remain data", pMyKeyData, KeyDataLength); */
-
- /* Parse EKD format in pairwise_msg_3_WPA2 && group_msg_1_WPA2 */
- if (bWPA2
- && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) {
- if (KeyDataLength >= 8) /* KDE format exclude GTK length */
- {
- pKDE = (struct rt_kde_encap *) pMyKeyData;
-
- DefaultIdx = pKDE->GTKEncap.Kid;
-
- /* Sanity check - KED length */
- if (KeyDataLength < (pKDE->Len + 2)) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR: The len from KDE is too short \n"));
- return FALSE;
- }
- /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */
- GTKLEN = pKDE->Len - 6;
- if (GTKLEN < LEN_AES_KEY) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR: GTK Key length is too short (%d) \n",
- GTKLEN));
- return FALSE;
- }
-
- } else {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR: KDE format length is too short \n"));
- return FALSE;
- }
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n",
- DefaultIdx, GTKLEN));
- /* skip it */
- pMyKeyData += 8;
- KeyDataLength -= 8;
-
- } else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) {
- DefaultIdx = GroupKeyIndex;
- DBGPRINT(RT_DEBUG_TRACE,
- ("GTK DefaultKeyID=%d \n", DefaultIdx));
- }
- /* Sanity check - shared key index must be 1 ~ 3 */
- if (DefaultIdx < 1 || DefaultIdx > 3) {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR: GTK Key index(%d) is invalid in %s %s \n",
- DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"),
- GetEapolMsgType(MsgType)));
- return FALSE;
- }
-
- {
- struct rt_cipher_key *pSharedKey;
-
- /* set key material, TxMic and RxMic */
- NdisMoveMemory(pAd->StaCfg.GTK, pMyKeyData, 32);
- pAd->StaCfg.DefaultKeyId = DefaultIdx;
-
- pSharedKey = &pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId];
-
- /* Prepare pair-wise key information into shared key table */
- NdisZeroMemory(pSharedKey, sizeof(struct rt_cipher_key));
- pSharedKey->KeyLen = LEN_TKIP_EK;
- NdisMoveMemory(pSharedKey->Key, pAd->StaCfg.GTK, LEN_TKIP_EK);
- NdisMoveMemory(pSharedKey->RxMic, &pAd->StaCfg.GTK[16],
- LEN_TKIP_RXMICK);
- NdisMoveMemory(pSharedKey->TxMic, &pAd->StaCfg.GTK[24],
- LEN_TKIP_TXMICK);
-
- /* Update Shared Key CipherAlg */
- pSharedKey->CipherAlg = CIPHER_NONE;
- if (pAd->StaCfg.GroupCipher == Ndis802_11Encryption2Enabled)
- pSharedKey->CipherAlg = CIPHER_TKIP;
- else if (pAd->StaCfg.GroupCipher ==
- Ndis802_11Encryption3Enabled)
- pSharedKey->CipherAlg = CIPHER_AES;
- else if (pAd->StaCfg.GroupCipher == Ndis802_11GroupWEP40Enabled)
- pSharedKey->CipherAlg = CIPHER_WEP64;
- else if (pAd->StaCfg.GroupCipher ==
- Ndis802_11GroupWEP104Enabled)
- pSharedKey->CipherAlg = CIPHER_WEP128;
-
- /* Update group key information to ASIC Shared Key Table */
- AsicAddSharedKeyEntry(pAd,
- BSS0,
- pAd->StaCfg.DefaultKeyId,
- pSharedKey->CipherAlg,
- pSharedKey->Key,
- pSharedKey->TxMic, pSharedKey->RxMic);
-
- /* Update ASIC WCID attribute table and IVEIV table */
- RTMPAddWcidAttributeEntry(pAd,
- BSS0,
- pAd->StaCfg.DefaultKeyId,
- pSharedKey->CipherAlg, NULL);
- }
-
- return TRUE;
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Construct EAPoL message for WPA handshaking
- Its format is below,
-
- +--------------------+
- | Protocol Version | 1 octet
- +--------------------+
- | Protocol Type | 1 octet
- +--------------------+
- | Body Length | 2 octets
- +--------------------+
- | Descriptor Type | 1 octet
- +--------------------+
- | Key Information | 2 octets
- +--------------------+
- | Key Length | 1 octet
- +--------------------+
- | Key Repaly Counter | 8 octets
- +--------------------+
- | Key Nonce | 32 octets
- +--------------------+
- | Key IV | 16 octets
- +--------------------+
- | Key RSC | 8 octets
- +--------------------+
- | Key ID or Reserved | 8 octets
- +--------------------+
- | Key MIC | 16 octets
- +--------------------+
- | Key Data Length | 2 octets
- +--------------------+
- | Key Data | n octets
- +--------------------+
-
- Arguments:
- pAd Pointer to our adapter
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void ConstructEapolMsg(struct rt_mac_table_entry *pEntry,
- u8 GroupKeyWepStatus,
- u8 MsgType,
- u8 DefaultKeyIdx,
- u8 * KeyNonce,
- u8 * TxRSC,
- u8 * GTK,
- u8 * RSNIE,
- u8 RSNIE_Len, struct rt_eapol_packet * pMsg)
-{
- BOOLEAN bWPA2 = FALSE;
- u8 KeyDescVer;
-
- /* Choose WPA2 or not */
- if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
- (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
- bWPA2 = TRUE;
-
- /* Init Packet and Fill header */
- pMsg->ProVer = EAPOL_VER;
- pMsg->ProType = EAPOLKey;
-
- /* Default 95 bytes, the EAPoL-Key descriptor exclude Key-data field */
- SET_u16_TO_ARRARY(pMsg->Body_Len, LEN_EAPOL_KEY_MSG);
-
- /* Fill in EAPoL descriptor */
- if (bWPA2)
- pMsg->KeyDesc.Type = WPA2_KEY_DESC;
- else
- pMsg->KeyDesc.Type = WPA1_KEY_DESC;
-
- /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type */
- {
- /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */
- /* When either the pairwise or the group cipher is AES, the DESC_TYPE_AES(2) shall be used. */
- KeyDescVer =
- (((pEntry->WepStatus == Ndis802_11Encryption3Enabled)
- || (GroupKeyWepStatus ==
- Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES)
- : (DESC_TYPE_TKIP));
- }
-
- pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer;
-
- /* Specify Key Type as Group(0) or Pairwise(1) */
- if (MsgType >= EAPOL_GROUP_MSG_1)
- pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY;
- else
- pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY;
-
- /* Specify Key Index, only group_msg1_WPA1 */
- if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
- pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx;
-
- if (MsgType == EAPOL_PAIR_MSG_3)
- pMsg->KeyDesc.KeyInfo.Install = 1;
-
- if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)
- || (MsgType == EAPOL_GROUP_MSG_1))
- pMsg->KeyDesc.KeyInfo.KeyAck = 1;
-
- if (MsgType != EAPOL_PAIR_MSG_1)
- pMsg->KeyDesc.KeyInfo.KeyMic = 1;
-
- if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) ||
- (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) {
- pMsg->KeyDesc.KeyInfo.Secure = 1;
- }
-
- if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) ||
- (MsgType == EAPOL_GROUP_MSG_1))) {
- pMsg->KeyDesc.KeyInfo.EKD_DL = 1;
- }
- /* key Information element has done. */
- *(u16 *) (&pMsg->KeyDesc.KeyInfo) =
- cpu2le16(*(u16 *) (&pMsg->KeyDesc.KeyInfo));
-
- /* Fill in Key Length */
- {
- if (MsgType >= EAPOL_GROUP_MSG_1) {
- /* the length of group key cipher */
- pMsg->KeyDesc.KeyLength[1] =
- ((GroupKeyWepStatus ==
- Ndis802_11Encryption2Enabled) ? TKIP_GTK_LENGTH :
- LEN_AES_KEY);
- } else {
- /* the length of pairwise key cipher */
- pMsg->KeyDesc.KeyLength[1] =
- ((pEntry->WepStatus ==
- Ndis802_11Encryption2Enabled) ? LEN_TKIP_KEY :
- LEN_AES_KEY);
- }
- }
-
- /* Fill in replay counter */
- NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter,
- LEN_KEY_DESC_REPLAY);
-
- /* Fill Key Nonce field */
- /* ANonce : pairwise_msg1 & pairwise_msg3 */
- /* SNonce : pairwise_msg2 */
- /* GNonce : group_msg1_wpa1 */
- if ((MsgType <= EAPOL_PAIR_MSG_3)
- || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))))
- NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce,
- LEN_KEY_DESC_NONCE);
-
- /* Fill key IV - WPA2 as 0, WPA1 as random */
- if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) {
- /* Suggest IV be random number plus some number, */
- NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16],
- LEN_KEY_DESC_IV);
- pMsg->KeyDesc.KeyIv[15] += 2;
- }
- /* Fill Key RSC field */
- /* It contains the RSC for the GTK being installed. */
- if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2)
- || (MsgType == EAPOL_GROUP_MSG_1)) {
- NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6);
- }
- /* Clear Key MIC field for MIC calculation later */
- NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
-
- ConstructEapolKeyData(pEntry,
- GroupKeyWepStatus,
- KeyDescVer,
- MsgType,
- DefaultKeyIdx, GTK, RSNIE, RSNIE_Len, pMsg);
-
- /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
- if (MsgType != EAPOL_PAIR_MSG_1) {
- CalculateMIC(KeyDescVer, pEntry->PTK, pMsg);
- }
-
- DBGPRINT(RT_DEBUG_TRACE,
- ("===> ConstructEapolMsg for %s %s\n",
- ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType)));
- DBGPRINT(RT_DEBUG_TRACE,
- (" Body length = %d \n",
- CONV_ARRARY_TO_u16(pMsg->Body_Len)));
- DBGPRINT(RT_DEBUG_TRACE,
- (" Key length = %d \n",
- CONV_ARRARY_TO_u16(pMsg->KeyDesc.KeyLength)));
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Construct the Key Data field of EAPoL message
-
- Arguments:
- pAd Pointer to our adapter
- Elem Message body
-
- Return Value:
- None
-
- Note:
-
- ========================================================================
-*/
-void ConstructEapolKeyData(struct rt_mac_table_entry *pEntry,
- u8 GroupKeyWepStatus,
- u8 keyDescVer,
- u8 MsgType,
- u8 DefaultKeyIdx,
- u8 * GTK,
- u8 * RSNIE,
- u8 RSNIE_LEN, struct rt_eapol_packet * pMsg)
-{
- u8 *mpool, *Key_Data, *Rc4GTK;
- u8 ekey[(LEN_KEY_DESC_IV + LEN_EAP_EK)];
- unsigned long data_offset;
- BOOLEAN bWPA2Capable = FALSE;
- struct rt_rtmp_adapter *pAd = pEntry->pAd;
- BOOLEAN GTK_Included = FALSE;
-
- /* Choose WPA2 or not */
- if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) ||
- (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
- bWPA2Capable = TRUE;
-
- if (MsgType == EAPOL_PAIR_MSG_1 ||
- MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2)
- return;
-
- /* allocate memory pool */
- os_alloc_mem(NULL, (u8 **) & mpool, 1500);
-
- if (mpool == NULL)
- return;
-
- /* Rc4GTK Len = 512 */
- Rc4GTK = (u8 *) ROUND_UP(mpool, 4);
- /* Key_Data Len = 512 */
- Key_Data = (u8 *) ROUND_UP(Rc4GTK + 512, 4);
-
- NdisZeroMemory(Key_Data, 512);
- SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0);
- data_offset = 0;
-
- /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */
- if (RSNIE_LEN
- && ((MsgType == EAPOL_PAIR_MSG_2)
- || (MsgType == EAPOL_PAIR_MSG_3))) {
- u8 *pmkid_ptr = NULL;
- u8 pmkid_len = 0;
-
- RTMPInsertRSNIE(&Key_Data[data_offset],
- &data_offset,
- RSNIE, RSNIE_LEN, pmkid_ptr, pmkid_len);
- }
-
- /* Encapsulate KDE format in pairwise_msg3_WPA2 & group_msg1_WPA2 */
- if (bWPA2Capable
- && ((MsgType == EAPOL_PAIR_MSG_3)
- || (MsgType == EAPOL_GROUP_MSG_1))) {
- /* Key Data Encapsulation (KDE) format - 802.11i-2004 Figure-43w and Table-20h */
- Key_Data[data_offset + 0] = 0xDD;
-
- if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
- Key_Data[data_offset + 1] = 0x16; /* 4+2+16(OUI+DataType+DataField) */
- } else {
- Key_Data[data_offset + 1] = 0x26; /* 4+2+32(OUI+DataType+DataField) */
- }
-
- Key_Data[data_offset + 2] = 0x00;
- Key_Data[data_offset + 3] = 0x0F;
- Key_Data[data_offset + 4] = 0xAC;
- Key_Data[data_offset + 5] = 0x01;
-
- /* GTK KDE format - 802.11i-2004 Figure-43x */
- Key_Data[data_offset + 6] = (DefaultKeyIdx & 0x03);
- Key_Data[data_offset + 7] = 0x00; /* Reserved Byte */
-
- data_offset += 8;
- }
-
- /* Encapsulate GTK */
- /* Only for pairwise_msg3_WPA2 and group_msg1 */
- if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable)
- || (MsgType == EAPOL_GROUP_MSG_1)) {
- /* Fill in GTK */
- if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled) {
- NdisMoveMemory(&Key_Data[data_offset], GTK,
- LEN_AES_KEY);
- data_offset += LEN_AES_KEY;
- } else {
- NdisMoveMemory(&Key_Data[data_offset], GTK,
- TKIP_GTK_LENGTH);
- data_offset += TKIP_GTK_LENGTH;
- }
-
- GTK_Included = TRUE;
- }
-
- /* This whole key-data field shall be encrypted if a GTK is included. */
- /* Encrypt the data material in key data field with KEK */
- if (GTK_Included) {
- /*hex_dump("GTK_Included", Key_Data, data_offset); */
-
- if ((keyDescVer == DESC_TYPE_AES)) {
- u8 remainder = 0;
- u8 pad_len = 0;
-
- /* Key Descriptor Version 2 or 3: AES key wrap, defined in IETF RFC 3394, */
- /* shall be used to encrypt the Key Data field using the KEK field from */
- /* the derived PTK. */
-
- /* If the Key Data field uses the NIST AES key wrap, then the Key Data field */
- /* shall be padded before encrypting if the key data length is less than 16 */
- /* octets or if it is not a multiple of 8. The padding consists of appending */
- /* a single octet 0xdd followed by zero or more 0x00 octets. */
- if ((remainder = data_offset & 0x07) != 0) {
- int i;
-
- pad_len = (8 - remainder);
- Key_Data[data_offset] = 0xDD;
- for (i = 1; i < pad_len; i++)
- Key_Data[data_offset + i] = 0;
-
- data_offset += pad_len;
- }
-
- AES_GTK_KEY_WRAP(&pEntry->PTK[16], Key_Data,
- data_offset, Rc4GTK);
- /* AES wrap function will grow 8 bytes in length */
- data_offset += 8;
- } else {
- /* Key Descriptor Version 1: ARC4 is used to encrypt the Key Data field
- using the KEK field from the derived PTK. */
-
- /* PREPARE Encrypted "Key DATA" field. (Encrypt GTK with RC4, usinf PTK[16]->[31] as Key, IV-field as IV) */
- /* put TxTsc in Key RSC field */
- pAd->PrivateInfo.FCSCRC32 = PPPINITFCS32; /*Init crc32. */
-
- /* ekey is the contanetion of IV-field, and PTK[16]->PTK[31] */
- NdisMoveMemory(ekey, pMsg->KeyDesc.KeyIv,
- LEN_KEY_DESC_IV);
- NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], &pEntry->PTK[16],
- LEN_EAP_EK);
- ARCFOUR_INIT(&pAd->PrivateInfo.WEPCONTEXT, ekey, sizeof(ekey)); /*INIT SBOX, KEYLEN+3(IV) */
- pAd->PrivateInfo.FCSCRC32 =
- RTMP_CALC_FCS32(pAd->PrivateInfo.FCSCRC32, Key_Data,
- data_offset);
- WPAARCFOUR_ENCRYPT(&pAd->PrivateInfo.WEPCONTEXT, Rc4GTK,
- Key_Data, data_offset);
- }
-
- NdisMoveMemory(pMsg->KeyDesc.KeyData, Rc4GTK, data_offset);
- } else {
- NdisMoveMemory(pMsg->KeyDesc.KeyData, Key_Data, data_offset);
- }
-
- /* Update key data length field and total body length */
- SET_u16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, data_offset);
- INC_u16_TO_ARRARY(pMsg->Body_Len, data_offset);
-
- os_free_mem(NULL, mpool);
-
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Calcaulate MIC. It is used during 4-ways handsharking.
-
- Arguments:
- pAd - pointer to our pAdapter context
- PeerWepStatus - indicate the encryption type
-
- Return Value:
-
- Note:
-
- ========================================================================
-*/
-static void CalculateMIC(u8 KeyDescVer,
- u8 * PTK, struct rt_eapol_packet * pMsg)
-{
- u8 *OutBuffer;
- unsigned long FrameLen = 0;
- u8 mic[LEN_KEY_DESC_MIC];
- u8 digest[80];
-
- /* allocate memory for MIC calculation */
- os_alloc_mem(NULL, (u8 **) & OutBuffer, 512);
-
- if (OutBuffer == NULL) {
- DBGPRINT(RT_DEBUG_ERROR, ("CalculateMIC: no memory!\n"));
- return;
- }
- /* make a frame for calculating MIC. */
- MakeOutgoingFrame(OutBuffer, &FrameLen,
- CONV_ARRARY_TO_u16(pMsg->Body_Len) + 4, pMsg,
- END_OF_ARGS);
-
- NdisZeroMemory(mic, sizeof(mic));
-
- /* Calculate MIC */
- if (KeyDescVer == DESC_TYPE_AES) {
- HMAC_SHA1(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, digest,
- SHA1_DIGEST_SIZE);
- NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
- } else {
- HMAC_MD5(PTK, LEN_EAP_MICK, OutBuffer, FrameLen, mic,
- MD5_DIGEST_SIZE);
- }
-
- /* store the calculated MIC */
- NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
-
- os_free_mem(NULL, OutBuffer);
-}
-
-/*
- ========================================================================
-
- Routine Description:
- Some received frames can't decrypt by Asic, so decrypt them by software.
-
- Arguments:
- pAd - pointer to our pAdapter context
- PeerWepStatus - indicate the encryption type
-
- Return Value:
- NDIS_STATUS_SUCCESS - decryption successful
- NDIS_STATUS_FAILURE - decryption failure
-
- ========================================================================
-*/
-int RTMPSoftDecryptBroadCastData(struct rt_rtmp_adapter *pAd,
- struct rt_rx_blk *pRxBlk,
- IN NDIS_802_11_ENCRYPTION_STATUS
- GroupCipher, struct rt_cipher_key *pShard_key)
-{
- struct rt_rxwi * pRxWI = pRxBlk->pRxWI;
-
- /* handle WEP decryption */
- if (GroupCipher == Ndis802_11Encryption1Enabled) {
- if (RTMPSoftDecryptWEP
- (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
- pShard_key)) {
-
- /*Minus IV[4] & ICV[4] */
- pRxWI->MPDUtotalByteCount -= 8;
- } else {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR : Software decrypt WEP data fails.\n"));
- /* give up this frame */
- return NDIS_STATUS_FAILURE;
- }
- }
- /* handle TKIP decryption */
- else if (GroupCipher == Ndis802_11Encryption2Enabled) {
- if (RTMPSoftDecryptTKIP
- (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount, 0,
- pShard_key)) {
-
- /*Minus 8 bytes MIC, 8 bytes IV/EIV, 4 bytes ICV */
- pRxWI->MPDUtotalByteCount -= 20;
- } else {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR : RTMPSoftDecryptTKIP Failed\n"));
- /* give up this frame */
- return NDIS_STATUS_FAILURE;
- }
- }
- /* handle AES decryption */
- else if (GroupCipher == Ndis802_11Encryption3Enabled) {
- if (RTMPSoftDecryptAES
- (pAd, pRxBlk->pData, pRxWI->MPDUtotalByteCount,
- pShard_key)) {
-
- /*8 bytes MIC, 8 bytes IV/EIV (CCMP Header) */
- pRxWI->MPDUtotalByteCount -= 16;
- } else {
- DBGPRINT(RT_DEBUG_ERROR,
- ("ERROR : RTMPSoftDecryptAES Failed\n"));
- /* give up this frame */
- return NDIS_STATUS_FAILURE;
- }
- } else {
- /* give up this frame */
- return NDIS_STATUS_FAILURE;
- }
-
- return NDIS_STATUS_SUCCESS;
-
-}
-
-u8 *GetSuiteFromRSNIE(u8 *rsnie,
- u32 rsnie_len, u8 type, u8 * count)
-{
- struct rt_eid * pEid;
- int len;
- u8 *pBuf;
- int offset = 0;
- struct rt_rsnie_auth *pAkm;
- u16 acount;
- BOOLEAN isWPA2 = FALSE;
-
- pEid = (struct rt_eid *) rsnie;
- len = rsnie_len - 2; /* exclude IE and length */
- pBuf = (u8 *)& pEid->Octet[0];
-
- /* set default value */
- *count = 0;
-
- /* Check length */
- if ((len <= 0) || (pEid->Len != len)) {
- DBGPRINT_ERR("%s : The length is invalid\n", __func__);
- return NULL;
- }
- /* Check WPA or WPA2 */
- if (pEid->Eid == IE_WPA) {
- struct rt_rsnie *pRsnie = (struct rt_rsnie *)pBuf;
- u16 ucount;
-
- if (len < sizeof(struct rt_rsnie)) {
- DBGPRINT_ERR("%s : The length is too short for WPA\n", __func__);
- return NULL;
- }
- /* Get the count of pairwise cipher */
- ucount = cpu2le16(pRsnie->ucount);
- if (ucount > 2) {
- DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount);
- return NULL;
- }
- /* Get the group cipher */
- if (type == GROUP_SUITE) {
- *count = 1;
- return pRsnie->mcast;
- }
- /* Get the pairwise cipher suite */
- else if (type == PAIRWISE_SUITE) {
- DBGPRINT(RT_DEBUG_TRACE,
- ("%s : The count of pairwise cipher is %d\n",
- __func__, ucount));
- *count = ucount;
- return pRsnie->ucast[0].oui;
- }
-
- offset = sizeof(struct rt_rsnie) + (4 * (ucount - 1));
-
- } else if (pEid->Eid == IE_RSN) {
- struct rt_rsnie2 *pRsnie = (struct rt_rsnie2 *)pBuf;
- u16 ucount;
-
- isWPA2 = TRUE;
-
- if (len < sizeof(struct rt_rsnie2)) {
- DBGPRINT_ERR("%s : The length is too short for WPA2\n", __func__);
- return NULL;
- }
- /* Get the count of pairwise cipher */
- ucount = cpu2le16(pRsnie->ucount);
- if (ucount > 2) {
- DBGPRINT_ERR("%s : The count(%d) of pairwise cipher is invlaid\n", __func__, ucount);
- return NULL;
- }
- /* Get the group cipher */
- if (type == GROUP_SUITE) {
- *count = 1;
- return pRsnie->mcast;
- }
- /* Get the pairwise cipher suite */
- else if (type == PAIRWISE_SUITE) {
- DBGPRINT(RT_DEBUG_TRACE,
- ("%s : The count of pairwise cipher is %d\n",
- __func__, ucount));
- *count = ucount;
- return pRsnie->ucast[0].oui;
- }
-
- offset = sizeof(struct rt_rsnie2) + (4 * (ucount - 1));
-
- } else {
- DBGPRINT_ERR("%s : Unknown IE (%d)\n", __func__, pEid->Eid);
- return NULL;
- }
-
- /* skip group cipher and pairwise cipher suite */
- pBuf += offset;
- len -= offset;
-
- if (len < sizeof(struct rt_rsnie_auth)) {
- DBGPRINT_ERR("%s : The length of RSNIE is too short\n", __func__);
- return NULL;
- }
- /* pointer to AKM count */
- pAkm = (struct rt_rsnie_auth *)pBuf;
-
- /* Get the count of pairwise cipher */
- acount = cpu2le16(pAkm->acount);
- if (acount > 2) {
- DBGPRINT_ERR("%s : The count(%d) of AKM is invlaid\n", __func__, acount);
- return NULL;
- }
- /* Get the AKM suite */
- if (type == AKM_SUITE) {
- DBGPRINT(RT_DEBUG_TRACE, ("%s : The count of AKM is %d\n",
- __func__, acount));
- *count = acount;
- return pAkm->auth[0].oui;
- }
- offset = sizeof(struct rt_rsnie_auth) + (4 * (acount - 1));
-
- pBuf += offset;
- len -= offset;
-
- /* The remaining length must larger than (RSN-Capability(2) + PMKID-Count(2) + PMKID(16~)) */
- if (len >= (sizeof(RSN_CAPABILITIES) + 2 + LEN_PMKID)) {
- /* Skip RSN capability and PMKID-Count */
- pBuf += (sizeof(RSN_CAPABILITIES) + 2);
- len -= (sizeof(RSN_CAPABILITIES) + 2);
-
- /* Get PMKID */
- if (type == PMKID_LIST) {
- *count = 1;
- return pBuf;
- }
- } else {
- DBGPRINT_ERR("%s : it can't get any more information beyond AKM \n", __func__);
- return NULL;
- }
-
- *count = 0;
- /*DBGPRINT_ERR(("%s : The type(%d) doesn't support \n", __func__, type)); */
- return NULL;
-
-}
-
-void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len)
-{
- u8 *pSuite = NULL;
- u8 count;
-
- hex_dump("RSNIE", rsnie, rsnie_len);
-
- /* group cipher */
- pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count);
- if (pSuite != NULL) {
- hex_dump("group cipher", pSuite, 4 * count);
- }
- /* pairwise cipher */
- pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count);
- if (pSuite != NULL) {
- hex_dump("pairwise cipher", pSuite, 4 * count);
- }
- /* AKM */
- pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count);
- if (pSuite != NULL) {
- hex_dump("AKM suite", pSuite, 4 * count);
- }
- /* PMKID */
- pSuite = GetSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count);
- if (pSuite != NULL) {
- hex_dump("PMKID", pSuite, LEN_PMKID);
- }
-
-}
-
-void RTMPInsertRSNIE(u8 *pFrameBuf,
- unsigned long *pFrameLen,
- u8 *rsnie_ptr,
- u8 rsnie_len,
- u8 *pmkid_ptr, u8 pmkid_len)
-{
- u8 *pTmpBuf;
- unsigned long TempLen = 0;
- u8 extra_len = 0;
- u16 pmk_count = 0;
- u8 ie_num;
- u8 total_len = 0;
- u8 WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
-
- pTmpBuf = pFrameBuf;
-
- /* PMKID-List Must larger than 0 and the multiple of 16. */
- if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) {
- extra_len = sizeof(u16)+ pmkid_len;
-
- pmk_count = (pmkid_len >> 4);
- pmk_count = cpu2le16(pmk_count);
- } else {
- DBGPRINT(RT_DEBUG_WARN,
- ("%s : The length is PMKID-List is invalid (%d), so don't insert it.\n",
- __func__, pmkid_len));
- }
-
- if (rsnie_len != 0) {
- ie_num = IE_WPA;
- total_len = rsnie_len;
-
- if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) {
- ie_num = IE_RSN;
- total_len += extra_len;
- }
-
- /* construct RSNIE body */
- MakeOutgoingFrame(pTmpBuf, &TempLen,
- 1, &ie_num,
- 1, &total_len,
- rsnie_len, rsnie_ptr, END_OF_ARGS);
-
- pTmpBuf += TempLen;
- *pFrameLen = *pFrameLen + TempLen;
-
- if (ie_num == IE_RSN) {
- /* Insert PMKID-List field */
- if (extra_len > 0) {
- MakeOutgoingFrame(pTmpBuf, &TempLen,
- 2, &pmk_count,
- pmkid_len, pmkid_ptr,
- END_OF_ARGS);
-
- pTmpBuf += TempLen;
- *pFrameLen = *pFrameLen + TempLen;
- }
- }
- }
-
- return;
-}