MT7601u/src/common/cmm_wpa_adhoc.c
Murat Demirtas 612db32659 FIXED
2016-10-30 14:40:00 +00:00

1636 lines
52 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_wpa_adhoc.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#ifdef ADHOC_WPA2PSK_SUPPORT
#include "rt_config.h"
VOID Adhoc_RTMPGetTxTscFromAsic(
IN PRTMP_ADAPTER pAd,
IN UCHAR apidx,
OUT PUCHAR pTxTsc)
{
USHORT Wcid;
USHORT offset;
UCHAR IvEiv[8];
/* int i; */
UINT32 IV = 0;
UINT32 EIV = 0;
/* Get apidx for this BSSID */
GET_GroupKey_WCID(pAd, Wcid, apidx);
/* Read IVEIV from Asic */
offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
NdisZeroMemory(IvEiv, 8);
NdisZeroMemory(pTxTsc, 6);
RTMP_IO_READ32(pAd, offset, &IV);
RTMP_IO_READ32(pAd, offset + 4, &EIV);
*pTxTsc = IV & 0x000000ff;
*(pTxTsc+1) = IV & 0x0000ff00;
*(pTxTsc+2) = EIV & 0x000000ff;
*(pTxTsc+3) = EIV & 0x0000ff00;
*(pTxTsc+4) = EIV & 0x00ff0000;
*(pTxTsc+5) = EIV & 0xff000000;
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n",
Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5)));
}
/*
==========================================================================
Description:
Start 4-way HS when rcv EAPOL_START which may create by our driver in assoc.c
Return:
==========================================================================
*/
VOID Adhoc_WpaEAPOLStartAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
MAC_TABLE_ENTRY *pEntry;
PHEADER_802_11 pHeader;
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WpaEAPOLStartAction ===> \n"));
pHeader = (PHEADER_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)
{
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = &pEntry->WPA_Authenticator;
DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", pEntry->PortSecured, pAuthenticator->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx));
if ((pEntry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)
&& (pAuthenticator->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->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
/*Added by Eddy */
pAuthenticator->WpaState = AS_INITPSK;
pAuthenticator->MsgRetryCounter = 4;
Adhoc_WpaStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
}
}
}
/*
==========================================================================
Description:
Check the validity of the received EAPoL frame
Return:
TRUE if all parameters are OK,
FALSE otherwise
==========================================================================
*/
BOOLEAN Adhoc_PeerWpaMessageSanity (
IN PRTMP_ADAPTER pAd,
IN PEAPOL_PACKET pMsg,
IN ULONG MsgLen,
IN UCHAR MsgType,
IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile,
IN MAC_TABLE_ENTRY *pEntry)
{
UCHAR mic[LEN_KEY_DESC_MIC], digest[80], KEYDATA[MAX_LEN_OF_RSNIE];
BOOLEAN bReplayDiff = FALSE;
BOOLEAN bWPA2 = FALSE;
KEY_INFO EapolKeyInfo;
UCHAR GroupKeyIndex = 0;
NdisZeroMemory(mic, sizeof(mic));
NdisZeroMemory(digest, sizeof(digest));
NdisZeroMemory(KEYDATA, sizeof(KEYDATA));
NdisZeroMemory((PUCHAR)&EapolKeyInfo, sizeof(EapolKeyInfo));
NdisMoveMemory((PUCHAR)&EapolKeyInfo, (PUCHAR)&pMsg->KeyDesc.KeyInfo, sizeof(KEY_INFO));
*((USHORT *)&EapolKeyInfo) = cpu2le16(*((USHORT *)&EapolKeyInfo));
/* Choose WPA2 or not */
if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
bWPA2 = TRUE;
/* 0. Check MsgType */
if ((MsgType > EAPOL_GROUP_MSG_2) || (MsgType < EAPOL_PAIR_MSG_1))
{
DBGPRINT(RT_DEBUG_ERROR, ("The message type is invalid(%d)! \n", MsgType));
return FALSE;
}
/* 1. Replay counter check */
if (MsgType == EAPOL_PAIR_MSG_1 || MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1) /* For supplicant */
{
/* First validate replay counter, only accept message with larger replay counter. */
/* Let equal pass, some AP start with all zero replay counter */
UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
if ((RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
(RTMPCompareMemory(pMsg->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
{
bReplayDiff = TRUE;
}
}
else if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_4 || MsgType == EAPOL_GROUP_MSG_2) /* For authenticator */
{
/* check Replay Counter coresponds to MSG from authenticator, otherwise discard */
if (!NdisEqualMemory(pMsg->KeyDesc.ReplayCounter, p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY))
{
bReplayDiff = TRUE;
}
}
/* Replay Counter different condition */
if (bReplayDiff)
{
/* send wireless event - for replay counter different */
RTMPSendWirelessEvent(pAd, IW_REPLAY_COUNTER_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
if (MsgType < EAPOL_GROUP_MSG_1)
{
DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in pairwise msg %d of 4-way handshake!\n", MsgType));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
}
hex_dump("Receive replay counter ", pMsg->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
hex_dump("Current replay counter ", p4WayProfile->ReplayCounter, LEN_KEY_DESC_REPLAY);
return FALSE;
}
/* 2. Verify MIC except Pairwise Msg1 */
if (MsgType != EAPOL_PAIR_MSG_1)
{
UCHAR rcvd_mic[LEN_KEY_DESC_MIC];
UINT eapol_len = CONV_ARRARY_TO_UINT16(pMsg->Body_Len) + 4;
/* Record the received MIC for check later */
NdisMoveMemory(rcvd_mic, pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
if (EapolKeyInfo.KeyDescVer == KEY_DESC_TKIP) /* TKIP */
{
RT_HMAC_MD5(p4WayProfile->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, mic, MD5_DIGEST_SIZE);
}
else if (EapolKeyInfo.KeyDescVer == KEY_DESC_AES) /* AES */
{
RT_HMAC_SHA1(p4WayProfile->PTK, LEN_PTK_KCK, (PUCHAR)pMsg, eapol_len, digest, SHA1_DIGEST_SIZE);
NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
}
if (!NdisEqualMemory(rcvd_mic, mic, LEN_KEY_DESC_MIC))
{
/* send wireless event - for MIC different */
RTMPSendWirelessEvent(pAd, IW_MIC_DIFF_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
if (MsgType < EAPOL_GROUP_MSG_1)
{
DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in pairwise msg %d of 4-way handshake!\n", MsgType));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in group msg %d of 2-way handshake!\n", (MsgType - EAPOL_PAIR_MSG_4)));
}
hex_dump("Received MIC", rcvd_mic, LEN_KEY_DESC_MIC);
hex_dump("Desired MIC", mic, LEN_KEY_DESC_MIC);
return FALSE;
}
}
/* 1. Decrypt the Key Data field if GTK is included. */
/* 2. Extract the context of the Key Data field if it exist. */
/* The field in pairwise_msg_2_WPA1(WPA2) & pairwise_msg_3_WPA1 is clear. */
/* The field in group_msg_1_WPA1(WPA2) & pairwise_msg_3_WPA2 is encrypted. */
if (CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen) > 0)
{
/* Decrypt this field */
if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1))
{
if((EapolKeyInfo.KeyDescVer == KEY_DESC_AES))
{
UINT aes_unwrap_len = 0;
AES_Key_Unwrap(pMsg->KeyDesc.KeyData,
CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
&p4WayProfile->PTK[LEN_PTK_KCK], LEN_PTK_KEK,
KEYDATA, &aes_unwrap_len);
SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, aes_unwrap_len);
}
else
{
TKIP_GTK_KEY_UNWRAP(&pEntry->PTK[LEN_PTK_KCK],
pMsg->KeyDesc.KeyIv,
pMsg->KeyDesc.KeyData,
CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
KEYDATA);
}
if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1))
GroupKeyIndex = EapolKeyInfo.KeyIndex;
}
else if ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3 && !bWPA2))
{
NdisMoveMemory(KEYDATA, pMsg->KeyDesc.KeyData, CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen));
}
else
{
return TRUE;
}
/* Parse Key Data field to */
/* 1. verify RSN IE for pairwise_msg_2_WPA1(WPA2) ,pairwise_msg_3_WPA1(WPA2) */
/* 2. verify KDE format for pairwise_msg_3_WPA2, group_msg_1_WPA2 */
/* 3. update shared key for pairwise_msg_3_WPA2, group_msg_1_WPA1(WPA2) */
if (!RTMPParseEapolKeyData(pAd, KEYDATA,
CONV_ARRARY_TO_UINT16(pMsg->KeyDesc.KeyDataLen),
GroupKeyIndex, MsgType, bWPA2, pEntry))
{
return FALSE;
}
}
return TRUE;
}
/*
==========================================================================
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 Adhoc_WpaEAPOLKeyAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
MAC_TABLE_ENTRY *pEntry;
PHEADER_802_11 pHeader;
PEAPOL_PACKET pEapol_packet;
KEY_INFO peerKeyInfo;
UINT eapol_len;
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WpaEAPOLKeyAction ===>\n"));
pHeader = (PHEADER_802_11)Elem->Msg;
pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
eapol_len = CONV_ARRARY_TO_UINT16(pEapol_packet->Body_Len) + LENGTH_EAPOL_H;
NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pEapol_packet->KeyDesc.KeyInfo, sizeof(KEY_INFO));
*((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
do
{
pEntry = MacTableLookup(pAd, pHeader->Addr2);
if (!pEntry || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
break;
if (pEntry->AuthMode < Ndis802_11AuthModeWPA)
break;
DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPoL-Key frame from STA %02X-%02X-%02X-%02X-%02X-%02X\n", PRINT_MAC(pEntry->Addr)));
if (eapol_len > Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H)
{
DBGPRINT(RT_DEBUG_ERROR, ("The length of EAPoL packet is invalid \n"));
break;
}
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 != KEY_DESC_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 != KEY_DESC_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)
{
/* 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) && (pEntry->WPA_Supplicant.WpaState >= AS_INITPSK))
{
/* 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) {
Adhoc_PeerPairMsg1Action(pAd, pEntry, Elem);
} else {
Adhoc_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) {
Adhoc_PeerPairMsg3Action(pAd, pEntry, Elem);
} else {
Adhoc_PeerGroupMsg1Action(pAd, pEntry, Elem);
}
}
}
else if (pEntry->WPA_Authenticator.WpaState >= AS_INITPSK)
{
/* The frame is snet by Supplicant. */
/* So the Authenticator side shall handle this. */
if ((peerKeyInfo.KeyMic == 1) &&
(peerKeyInfo.Request == 1) &&
(peerKeyInfo.Error == 1))
{
/* The Supplicant uses a single Michael MIC Failure Report frame */
/* to report a MIC failure event to the Authenticator. */
/* A Michael MIC Failure Report is an EAPOL-Key frame with */
/* the following Key Information field bits set to 1: */
/* MIC bit, Error bit, Request bit, Secure bit. */
DBGPRINT(RT_DEBUG_ERROR, ("Received an Michael MIC Failure Report, active countermeasure \n"));
}
else 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_UINT16(pEapol_packet->KeyDesc.KeyDataLen) == 0)
{
Adhoc_PeerPairMsg4Action(pAd, pEntry, Elem);
}
else
{
Adhoc_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 */
Adhoc_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 */
/* Adhoc_PeerGroupMsg2Action(pAd, pEntry, &Elem->Msg[LENGTH_802_11], (Elem->MsgLen - LENGTH_802_11)); */
}
}
}
}
}while(FALSE);
}
/*
==========================================================================
Description:
This is a function to initilize 4-way handshake
Return:
==========================================================================
*/
VOID Adhoc_WpaStart4WayHS(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN ULONG TimeInterval)
{
UCHAR Header802_3[14];
UCHAR *mpool;
PEAPOL_PACKET pEapolFrame;
PUINT8 pBssid = NULL;
BOOLEAN Cancelled;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_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 (!pEntry) {
DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n"));
return;
}
pAuthenticator = &pEntry->WPA_Authenticator;
pBssid = pAd->CommonCfg.Bssid;
group_cipher = pAd->StaCfg.GroupCipher;
/* delete retry timer */
RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled);
if (pBssid == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n"));
return;
}
/* Check the status */
if ((pAuthenticator->WpaState > AS_PTKSTART) || (pAuthenticator->WpaState < AS_INITPMK))
{
DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling=%d\n", pAuthenticator->WpaState));
return;
}
/* Increment replay counter by 1 */
ADD_ONE_To_64BIT_VAR(pAuthenticator->ReplayCounter);
/* Randomly generate ANonce */
GenRandom(pAd, (UCHAR *)pBssid, pAuthenticator->ANonce);
/* Allocate memory for output */
os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
if (mpool == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
return;
}
pEapolFrame = (PEAPOL_PACKET)mpool;
NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
/* Construct EAPoL message - Pairwise Msg 1 */
/* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */
Adhoc_ConstructEapolMsg(pEntry,
group_cipher,
EAPOL_PAIR_MSG_1,
0, /* Default key index */
pAuthenticator->ANonce,
NULL, /* TxRSC */
NULL, /* GTK */
NULL, /* RSNIE */
0, /* RSNIE length */
pAuthenticator,
pEapolFrame);
if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
{
UCHAR digest[80], PMK_key[20];
PKEY_DESCRIPTER pKeyDesc = &pEapolFrame->KeyDesc;
pKeyDesc->KeyData[0] = 0xDD;
pKeyDesc->KeyData[2] = 0x00;
pKeyDesc->KeyData[3] = 0x0F;
pKeyDesc->KeyData[4] = 0xAC;
pKeyDesc->KeyData[5] = 0x04;
NdisMoveMemory(&PMK_key[0], "PMK Name", 8);
NdisMoveMemory(&PMK_key[8], pAd->CurrentAddress, MAC_ADDR_LEN);
NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN);
RT_HMAC_SHA1(pAd->StaCfg.PMK, PMK_LEN, PMK_key, 20, digest, LEN_PMKID);
NdisMoveMemory(&pKeyDesc->KeyData[6], digest, LEN_PMKID);
pKeyDesc->KeyData[1] = 0x14;/* 4+LEN_PMKID */
INC_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, 6 + LEN_PMKID);
INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID);
}
/* Make outgoing frame */
MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
RTMPToWirelessSta(pAd, pEntry, Header802_3,
LENGTH_802_3, (PUCHAR)pEapolFrame,
CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
(pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
/* Trigger Retry Timer */
pAuthenticator->MsgType = EAPOL_PAIR_MSG_1;
RTMPSetTimer(&pAuthenticator->MsgRetryTimer, TimeInterval);
/* Update State */
pAuthenticator->WpaState = AS_PTKSTART;
os_free_mem(NULL, mpool);
DBGPRINT(RT_DEBUG_TRACE, ("<=== Adhoc_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 Adhoc_PeerPairMsg1Action(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR PTK[80];
UCHAR Header802_3[14];
PEAPOL_PACKET pMsg1;
UINT MsgLen;
UCHAR *mpool;
PEAPOL_PACKET pEapolFrame;
PUINT8 pCurrentAddr = NULL;
PUINT8 pmk_ptr = NULL;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PUINT8 rsnie_ptr = NULL;
UCHAR rsnie_len = 0;
PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg1Action \n"));
if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
return;
if (ADHOC_ON(pAd) && (pEntry->WPA_Supplicant.WpaState == AS_PTKINITDONE))
{
MlmeDeAuthAction(pAd, pEntry, REASON_DEAUTH_STA_LEAVING, FALSE);
return;
}
pSupplicant = &pEntry->WPA_Supplicant;
if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
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 = (PEAPOL_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 (Adhoc_PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pSupplicant, pEntry) == FALSE)
return;
/* Store Replay counter, it will use to verify message 3 and construct message 2 */
NdisMoveMemory(pSupplicant->ReplayCounter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
/* Store ANonce */
NdisMoveMemory(pSupplicant->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
/* Generate random SNonce */
GenRandom(pAd, (UCHAR *)pCurrentAddr, pSupplicant->SNonce);
/* Calculate PTK(ANonce, SNonce) */
WpaDerivePTK(pAd,
pmk_ptr,
pSupplicant->ANonce,
pEntry->Addr,
pSupplicant->SNonce,
pCurrentAddr,
PTK,
LEN_PTK);
/* Save key to PTK entry */
NdisMoveMemory(pSupplicant->PTK, PTK, LEN_PTK);
/* Update WpaState */
pSupplicant->WpaState = AS_PTKINIT_NEGOTIATING;
/* Allocate memory for output */
os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
if (mpool == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
return;
}
pEapolFrame = (PEAPOL_PACKET)mpool;
NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
/* Construct EAPoL message - Pairwise Msg 2 */
/* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2) */
Adhoc_ConstructEapolMsg(pEntry,
group_cipher,
EAPOL_PAIR_MSG_2,
0, /* DefaultKeyIdx */
pSupplicant->SNonce,
NULL, /* TxRsc */
NULL, /* GTK */
(UCHAR *)rsnie_ptr,
rsnie_len,
pSupplicant,
pEapolFrame);
/* Make outgoing frame */
MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL);
RTMPToWirelessSta(pAd, pEntry,
Header802_3, sizeof(Header802_3), (PUCHAR)pEapolFrame,
CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
(pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
os_free_mem(NULL, mpool);
DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n"));
}
/*
==========================================================================
Description:
When receiving the second packet of 4-way pairwisekey handshake.
Return:
==========================================================================
*/
VOID Adhoc_PeerPairMsg2Action(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR PTK[80];
BOOLEAN Cancelled;
PHEADER_802_11 pHeader;
UCHAR *mpool;
PEAPOL_PACKET pEapolFrame;
PEAPOL_PACKET pMsg2;
UINT MsgLen;
UCHAR Header802_3[LENGTH_802_3];
UCHAR TxTsc[6];
PUINT8 pBssid = NULL;
PUINT8 pmk_ptr = NULL;
PUINT8 gtk_ptr = NULL;
UCHAR default_key = 0;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PUCHAR rsnie_ptr = NULL;
UCHAR rsnie_len = 0;
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg2Action \n"));
if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
return;
pAuthenticator = &pEntry->WPA_Authenticator;
if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
return;
/* check Entry in valid State */
if (pAuthenticator->WpaState < AS_PTKSTART)
return;
pBssid = pAd->CommonCfg.Bssid;
pmk_ptr = pAd->StaCfg.PMK;
gtk_ptr = pAd->StaCfg.GTK;
group_cipher = pAd->StaCfg.GroupCipher;
default_key = pAd->StaCfg.DefaultKeyId;
if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)
{
rsnie_len = pAd->StaCfg.RSNIE_Len;
rsnie_ptr = pAd->StaCfg.RSN_IE;
}
/* pointer to 802.11 header */
pHeader = (PHEADER_802_11)Elem->Msg;
/* skip 802.11_header(24-byte) and LLC_header(8) */
pMsg2 = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H];
MsgLen = Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H;
/* Store SNonce */
NdisMoveMemory(pAuthenticator->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE);
/* Derive PTK */
WpaDerivePTK(pAd,
(UCHAR *)pmk_ptr,
pAuthenticator->ANonce, /* ANONCE */
pAd->CurrentAddress,
pAuthenticator->SNonce, /* SNONCE */
pEntry->Addr,
PTK,
LEN_PTK);
/* Get Group TxTsc form Asic */
Adhoc_RTMPGetTxTscFromAsic(pAd, BSS0, TxTsc);
NdisMoveMemory(pAuthenticator->PTK, PTK, LEN_PTK);
/* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE */
if (Adhoc_PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pAuthenticator, pEntry) == FALSE)
return;
do
{
/* Allocate memory for input */
os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
if (mpool == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
return;
}
pEapolFrame = (PEAPOL_PACKET)mpool;
NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
/* delete retry timer */
RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled);
/* Increment replay counter by 1 */
ADD_ONE_To_64BIT_VAR(pAuthenticator->ReplayCounter);
/* Construct EAPoL message - Pairwise Msg 3 */
Adhoc_ConstructEapolMsg(pEntry,
group_cipher,
EAPOL_PAIR_MSG_3,
default_key,
pAuthenticator->ANonce,
TxTsc,
(UCHAR *)gtk_ptr,
(UCHAR *)rsnie_ptr,
rsnie_len,
pAuthenticator,
pEapolFrame);
/* Make outgoing frame */
MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL);
RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3,
(PUCHAR)pEapolFrame,
CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
(pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
pAuthenticator->MsgType = EAPOL_PAIR_MSG_3;
RTMPSetTimer(&pAuthenticator->MsgRetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
/* Update State */
pAuthenticator->WpaState = AS_PTKINIT_NEGOTIATING;
os_free_mem(NULL, mpool);
}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 Adhoc_PeerPairMsg3Action(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN MLME_QUEUE_ELEM *Elem)
{
PHEADER_802_11 pHeader;
UCHAR Header802_3[14];
UCHAR *mpool;
PEAPOL_PACKET pEapolFrame;
PEAPOL_PACKET pMsg3;
UINT MsgLen;
PUINT8 pCurrentAddr = NULL;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL;
DBGPRINT(RT_DEBUG_ERROR, ("===> Adhoc_PeerPairMsg3Action \n"));
if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
return;
pSupplicant = &pEntry->WPA_Supplicant;
if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG))
return;
pCurrentAddr = pAd->CurrentAddress;
group_cipher = pAd->StaCfg.GroupCipher;
/* Record 802.11 header & the received EAPOL packet Msg3 */
pHeader = (PHEADER_802_11) Elem->Msg;
pMsg3 = (PEAPOL_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 (Adhoc_PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pSupplicant, pEntry) == FALSE)
return;
/* Save Replay counter, it will use construct message 4 */
NdisMoveMemory(pSupplicant->ReplayCounter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
/* Double check ANonce */
if (!NdisEqualMemory(pSupplicant->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE))
{
return;
}
/* Allocate memory for output */
os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
if (mpool == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
return;
}
pEapolFrame = (PEAPOL_PACKET)mpool;
NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
/* Construct EAPoL message - Pairwise Msg 4 */
Adhoc_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,
pSupplicant,
pEapolFrame);
/* open 802.1x port control and privacy filter */
if (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK ||
pEntry->AuthMode == Ndis802_11AuthModeWPA2)
{
DBGPRINT(RT_DEBUG_TRACE, ("PeerPairMsg3Action: AuthMode(%s) PairwiseCipher(%s) GroupCipher(%s) \n",
GetAuthMode(pEntry->AuthMode),
GetEncryptType(pEntry->WepStatus),
GetEncryptType(group_cipher)));
}
/* 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),
(PUCHAR)pEapolFrame,
CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4,
(pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
/* Update WpaState */
pSupplicant->WpaState = AS_PTKINITDONE;
Adhoc_Wpa4WayComplete(pAd, pEntry);
os_free_mem(NULL, mpool);
DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg3Action: send Msg4 of 4-way \n"));
}
/*
==========================================================================
Description:
When receiving the last packet of 4-way pairwisekey handshake.
Initilize 2-way groupkey handshake following.
Return:
==========================================================================
*/
VOID Adhoc_PeerPairMsg4Action(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN MLME_QUEUE_ELEM *Elem)
{
PEAPOL_PACKET pMsg4;
PHEADER_802_11 pHeader;
UINT MsgLen;
BOOLEAN Cancelled;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_PeerPairMsg4Action\n"));
if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry))
return;
pAuthenticator = &pEntry->WPA_Authenticator;
do
{
if (Elem->MsgLen < (LENGTH_802_11 + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG ) )
break;
if (pAuthenticator->WpaState < AS_PTKINIT_NEGOTIATING)
break;
group_cipher = pAd->StaCfg.GroupCipher;
/* pointer to 802.11 header */
pHeader = (PHEADER_802_11)Elem->Msg;
/* skip 802.11_header(24-byte) and LLC_header(8) */
pMsg4 = (PEAPOL_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 (Adhoc_PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pAuthenticator, pEntry) == FALSE)
break;
pAuthenticator->WpaState = AS_PTKINITDONE;
RTMPCancelTimer(&pAuthenticator->MsgRetryTimer, &Cancelled);
RTMPCancelTimer(&pEntry->EnqueueStartForPSKTimer, &Cancelled);
Adhoc_Wpa4WayComplete(pAd, pEntry);
if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK)
{
pEntry->GTKState = REKEY_ESTABLISHED;
/* send wireless event - for set key done WPA2 */
RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
}
}while(FALSE);
}
VOID Adhoc_PeerGroupMsg1Action(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR Header802_3[14];
UCHAR *mpool;
PEAPOL_PACKET pEapolFrame;
PEAPOL_PACKET pGroup;
UINT MsgLen;
UCHAR default_key = 0;
UCHAR group_cipher = Ndis802_11WEPDisabled;
PUINT8 pCurrentAddr = NULL;
PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL;
DBGPRINT(RT_DEBUG_ERROR, ("===> Adhoc_PeerGroupMsg1Action \n"));
if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry)))
return;
pSupplicant = &pEntry->WPA_Supplicant;
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 = (PEAPOL_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 (Adhoc_PeerWpaMessageSanity(pAd, pGroup, MsgLen, EAPOL_GROUP_MSG_1, pSupplicant, pEntry) == FALSE)
return;
/* Save Replay counter, it will use to construct message 2 */
NdisMoveMemory(pSupplicant->ReplayCounter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
/* Allocate memory for output */
os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
if (mpool == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
return;
}
pEapolFrame = (PEAPOL_PACKET)mpool;
NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER);
/* Construct EAPoL message - Group Msg 2 */
Adhoc_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,
pSupplicant,
pEapolFrame);
/* open 802.1x port control and privacy filter */
pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
#ifdef CONFIG_STA_SUPPORT
STA_PORT_SECURED(pAd);
/* Indicate Connected for GUI */
pAd->IndicateMediaState = NdisMediaStateConnected;
#endif /* CONFIG_STA_SUPPORT */
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);
#ifdef CONFIG_STA_SUPPORT
if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) &&
OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) &&
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) &&
(pAd->MlmeAux.Channel == pAd->CommonCfg.Channel))
{
/* Now stop the scanning and need to send the rekey packet out */
pAd->MlmeAux.Channel = 0;
}
#endif /* CONFIG_STA_SUPPORT */
RTMPToWirelessSta(pAd, pEntry,
Header802_3, sizeof(Header802_3),
(PUCHAR)pEapolFrame,
CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE);
os_free_mem(NULL, mpool);
DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerGroupMsg1Action: send group message 2\n"));
}
VOID Adhoc_Wpa4WayComplete(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry)
{
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = NULL;
PFOUR_WAY_HANDSHAKE_PROFILE pSupplicant = NULL;
INT compare_address;
DBGPRINT(RT_DEBUG_TRACE, ("===> Adhoc_Wpa4WayComplete\n"));
if (!pEntry)
return;
pAuthenticator = &pEntry->WPA_Authenticator;
pSupplicant = &pEntry->WPA_Supplicant;
compare_address = NdisCmpMemory(pAd->CurrentAddress, pEntry->Addr, MAC_ADDR_LEN);
if ((compare_address > 0) && (pAuthenticator->WpaState == AS_PTKINITDONE)) {
NdisMoveMemory(pEntry->PTK, pAuthenticator->PTK, 64);
} else if ((compare_address < 0) && (pSupplicant->WpaState == AS_PTKINITDONE)) {
NdisMoveMemory(pEntry->PTK, pSupplicant->PTK, 64);
} else
return;
#ifdef IWSC_SUPPORT
if (pEntry)
{
PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl;
PWSC_PEER_ENTRY pWscPeerEntry = NULL;
RTMP_SEM_LOCK(&pWpsCtrl->WscConfiguredPeerListSemLock);
pWscPeerEntry = WscFindPeerEntry(&pWpsCtrl->WscConfiguredPeerList, pEntry->Addr);
if (pWscPeerEntry)
{
WscDelListEntryByMAC(&pWpsCtrl->WscConfiguredPeerList, pEntry->Addr);
}
RTMP_SEM_UNLOCK(&pWpsCtrl->WscConfiguredPeerListSemLock);
}
#endif /* IWSC_SUPPORT */
WPAInstallPairwiseKey(pAd,
BSS0,
pEntry,
FALSE);
pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
STA_PORT_SECURED(pAd);
/* Indicate Connected for GUI */
pAd->IndicateMediaState = NdisMediaStateConnected;
DBGPRINT(RT_DEBUG_OFF, ("Adhoc_Wpa4WayComplete - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n",
pEntry->AuthMode, GetAuthMode(pEntry->AuthMode),
pEntry->WepStatus, GetEncryptType(pEntry->WepStatus),
pAd->StaCfg.GroupCipher,
GetEncryptType(pAd->StaCfg.GroupCipher)));
}
VOID Adhoc_WpaRetryExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext;
if ((pEntry) && IS_ENTRY_CLIENT(pEntry))
{
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
PFOUR_WAY_HANDSHAKE_PROFILE pAuthenticator = &pEntry->WPA_Authenticator;
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec---> ReTryCounter=%d, WpaState=%d \n", pAuthenticator->MsgRetryCounter, pAuthenticator->WpaState));
switch (pEntry->AuthMode)
{
case Ndis802_11AuthModeWPA:
case Ndis802_11AuthModeWPAPSK:
case Ndis802_11AuthModeWPA2:
case Ndis802_11AuthModeWPA2PSK:
if (pAuthenticator->MsgRetryCounter == 0)
{
/* send wireless event - for pairwise key handshaking timeout */
RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
pEntry->WPA_Authenticator.WpaState = AS_NOTUSE;
#ifdef IWSC_SUPPORT
if (pAd->StaCfg.WscControl.bWscTrigger == FALSE)
#endif // IWSC_SUPPORT //
{
MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE);
DBGPRINT(RT_DEBUG_ERROR, ("Adhoc_WPARetryExec::MSG1 timeout\n"));
}
}
else if (pAuthenticator->MsgType == EAPOL_PAIR_MSG_1)
{
if ((pAuthenticator->WpaState == AS_PTKSTART) || (pAuthenticator->WpaState == AS_INITPSK) || (pAuthenticator->WpaState == AS_INITPMK))
{
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec::ReTry MSG1 of 4-way Handshake\n"));
Adhoc_WpaStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
}
}
else if (pAuthenticator->MsgType == EAPOL_PAIR_MSG_3)
{
pEntry->WPA_Authenticator.WpaState = AS_INITPSK;
#ifdef IWSC_SUPPORT
if (pAd->StaCfg.WscControl.bWscTrigger == FALSE)
#endif // IWSC_SUPPORT //
{
MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE);
DBGPRINT(RT_DEBUG_TRACE, ("Adhoc_WPARetryExec::Retry MSG3, TIMEOUT\n"));
}
}
break;
default:
break;
}
pAuthenticator->MsgRetryCounter--;
}
}
/*
========================================================================
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 Adhoc_ConstructEapolMsg(
IN PMAC_TABLE_ENTRY pEntry,
IN UCHAR GroupKeyWepStatus,
IN UCHAR MsgType,
IN UCHAR DefaultKeyIdx,
IN UCHAR *KeyNonce,
IN UCHAR *TxRSC,
IN UCHAR *GTK,
IN UCHAR *RSNIE,
IN UCHAR RSNIE_Len,
IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile,
OUT PEAPOL_PACKET pMsg)
{
BOOLEAN bWPA2 = FALSE;
UCHAR KeyDescVer;
PKEY_DESCRIPTER pKeyDesc = &pMsg->KeyDesc;
PKEY_INFO pKeyInfo = &pMsg->KeyDesc.KeyInfo;
/* 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_UINT16_TO_ARRARY(pMsg->Body_Len, MIN_LEN_OF_EAPOL_KEY_MSG);
/* Fill in EAPoL descriptor */
if (bWPA2)
pKeyDesc->Type = WPA2_KEY_DESC;
else
pKeyDesc->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 KEY_DESC_AES shall be used. */
KeyDescVer = (((pEntry->WepStatus == Ndis802_11Encryption3Enabled) ||
(GroupKeyWepStatus == Ndis802_11Encryption3Enabled)) ? (KEY_DESC_AES) : (KEY_DESC_TKIP));
pKeyInfo->KeyDescVer = KeyDescVer;
/* Specify Key Type as Group(0) or Pairwise(1) */
if (MsgType >= EAPOL_GROUP_MSG_1)
pKeyInfo->KeyType = GROUPKEY;
else
pKeyInfo->KeyType = PAIRWISEKEY;
/* Specify Key Index, only group_msg1_WPA1 */
if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))
pKeyInfo->KeyIndex = DefaultKeyIdx;
if (MsgType == EAPOL_PAIR_MSG_3)
pKeyInfo->Install = 1;
if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1))
pKeyInfo->KeyAck = 1;
if (MsgType != EAPOL_PAIR_MSG_1)
pKeyInfo->KeyMic = 1;
if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)))
pKeyInfo->Secure = 1;
/* This subfield shall be set, and the Key Data field shall be encrypted, if
any key material (e.g., GTK or SMK) is included in the frame. */
if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)))
pKeyInfo->EKD_DL = 1;
/* key Information element has done. */
*(USHORT *)(pKeyInfo) = cpu2le16(*(USHORT *)(pKeyInfo));
/* Fill in Key Length */
if (bWPA2)
{
/* In WPA2 mode, the field indicates the length of pairwise key cipher, */
/* so only pairwise_msg_1 and pairwise_msg_3 need to fill. */
if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3))
pKeyDesc->KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK);
}
else
{
if (MsgType >= EAPOL_GROUP_MSG_1)
{
/* the length of group key cipher */
pKeyDesc->KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_GTK : LEN_AES_GTK);
}
else
{
/* the length of pairwise key cipher */
pKeyDesc->KeyLength[1] = ((pEntry->WepStatus == Ndis802_11Encryption2Enabled) ? LEN_TKIP_TK : LEN_AES_TK);
}
}
/* Fill in replay counter */
NdisMoveMemory(pKeyDesc->ReplayCounter, p4WayProfile->ReplayCounter, 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(pKeyDesc->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(pKeyDesc->KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV);
pKeyDesc->KeyIv[15] += 2;
}
/* Fill Key RSC field */
/* It contains the RSC for the GTK being installed. */
if ((TxRSC != NULL) && ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)))
{
NdisMoveMemory(pKeyDesc->KeyRsc, TxRSC, 6);
}
/* Clear Key MIC field for MIC calculation later */
NdisZeroMemory(pKeyDesc->KeyMic, LEN_KEY_DESC_MIC);
Adhoc_ConstructEapolKeyData(pEntry,
GroupKeyWepStatus,
KeyDescVer,
MsgType,
DefaultKeyIdx,
GTK,
RSNIE,
RSNIE_Len,
p4WayProfile,
pMsg);
/* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1. */
if (MsgType != EAPOL_PAIR_MSG_1)
CalculateMIC(KeyDescVer, p4WayProfile->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_UINT16(pMsg->Body_Len)));
DBGPRINT(RT_DEBUG_TRACE, (" Key length = %d \n", CONV_ARRARY_TO_UINT16(pKeyDesc->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 Adhoc_ConstructEapolKeyData(
IN PMAC_TABLE_ENTRY pEntry,
IN UCHAR GroupKeyWepStatus,
IN UCHAR keyDescVer,
IN UCHAR MsgType,
IN UCHAR DefaultKeyIdx,
IN UCHAR *GTK,
IN UCHAR *RSNIE,
IN UCHAR RSNIE_LEN,
IN PFOUR_WAY_HANDSHAKE_PROFILE p4WayProfile,
OUT PEAPOL_PACKET pMsg)
{
UCHAR *mpool, *Key_Data, *eGTK;
ULONG data_offset;
BOOLEAN bWPA2Capable = FALSE;
BOOLEAN GTK_Included = FALSE;
PKEY_DESCRIPTER pKeyDesc = &pMsg->KeyDesc;
/* 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, (PUCHAR *)&mpool, 1500);
if (mpool == NULL)
return;
/* eGTK Len = 512 */
eGTK = (UCHAR *) ROUND_UP(mpool, 4);
/* Key_Data Len = 512 */
Key_Data = (UCHAR *) ROUND_UP(eGTK + 512, 4);
NdisZeroMemory(Key_Data, 512);
SET_UINT16_TO_ARRARY(pKeyDesc->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)))
{
PUINT8 pmkid_ptr = NULL;
UINT8 pmkid_len = 0;
RTMPInsertRSNIE(&Key_Data[data_offset],
&data_offset,
RSNIE,
RSNIE_LEN,
pmkid_ptr,
pmkid_len);
}
/* Encapsulate GTK */
/* Only for pairwise_msg3_WPA2 and group_msg1 */
if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1))
{
UINT8 gtk_len;
/* Decide the GTK length */
if (GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
gtk_len = LEN_AES_GTK;
else
gtk_len = LEN_TKIP_GTK;
/* Insert GTK KDE format in WAP2 mode */
if (bWPA2Capable)
{
/* Construct the common KDE format */
WPA_ConstructKdeHdr(KDE_GTK, 2 + gtk_len, &Key_Data[data_offset]);
data_offset += sizeof(KDE_HDR);
/* GTK KDE format - 802.11i-2004 Figure-43x */
Key_Data[data_offset] = (DefaultKeyIdx & 0x03);
Key_Data[data_offset + 1] = 0x00; /* Reserved Byte */
data_offset += 2;
}
/* Fill in GTK */
NdisMoveMemory(&Key_Data[data_offset], GTK, gtk_len);
data_offset += gtk_len;
GTK_Included = TRUE;
}
/* If the Encrypted Key Data subfield (of the Key Information field)
is set, the entire Key Data field shall be encrypted. */
/* 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)
{
if ((keyDescVer == KEY_DESC_AES))
{
UCHAR remainder = 0;
UCHAR pad_len = 0;
UINT wrap_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_Key_Wrap(Key_Data, (UINT) data_offset,
&p4WayProfile->PTK[LEN_PTK_KCK], LEN_PTK_KEK,
eGTK, &wrap_len);
data_offset = wrap_len;
}
else
{
TKIP_GTK_KEY_WRAP(&p4WayProfile->PTK[LEN_PTK_KCK],
pMsg->KeyDesc.KeyIv,
Key_Data,
data_offset,
eGTK);
}
NdisMoveMemory(pKeyDesc->KeyData, eGTK, data_offset);
}
else
{
NdisMoveMemory(pKeyDesc->KeyData, Key_Data, data_offset);
}
/* Update key data length field and total body length */
SET_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, data_offset);
INC_UINT16_TO_ARRARY(pMsg->Body_Len, data_offset);
os_free_mem(NULL, mpool);
}
#endif /* ADHOC_WPA2PSK_SUPPORT */