summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/SecurityGen.c
diff options
context:
space:
mode:
authorAdam Shapiro <[email protected]>2016-02-04 13:02:45 -0800
committerAdam Shapiro <[email protected]>2016-02-04 13:02:45 -0800
commit3c8ac8624f815e66b370ef412bbf13cbd2c732e2 (patch)
tree9e1e9654be00272763677a6fe6891f7cb5fb4995 /network/wlan/WDI/COMMON/SecurityGen.c
parent921231effe018f3939f5b67fc7e44560aa6f3998 (diff)
WDI Sample
Adding WDI sample from partner enablement-China
Diffstat (limited to 'network/wlan/WDI/COMMON/SecurityGen.c')
-rw-r--r--network/wlan/WDI/COMMON/SecurityGen.c6062
1 files changed, 6062 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/SecurityGen.c b/network/wlan/WDI/COMMON/SecurityGen.c
new file mode 100644
index 00000000..23abf5b4
--- /dev/null
+++ b/network/wlan/WDI/COMMON/SecurityGen.c
@@ -0,0 +1,6062 @@
+#include "Mp_Precomp.h"
+
+#if WPP_SOFTWARE_TRACE
+#include "SecurityGen.tmh"
+#endif
+
+
+//===========Define Local Function Protype===================
+
+BOOLEAN
+SecCheckMIC(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ OCTET_STRING frame;
+ u1Byte DestAddr[6];
+ RT_ENC_ALG EncAlgorithm;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ BOOLEAN bResult = TRUE;
+
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ //2004/07/12, kcwu,
+ //Check if the packet is encrypted
+ if(!Frame_WEP(frame))
+ {
+ return bResult;
+ }
+
+ //2004/07/12, kcwu
+ //Find the algorithm that should be used
+ PlatformMoveMemory(DestAddr, Frame_Addr1(frame), ETHERNET_ADDRESS_LENGTH);
+ EncAlgorithm = (MacAddr_isMulticast(DestAddr)?pSec->GroupEncAlgorithm:pSec->PairwiseEncAlgorithm);
+ switch(EncAlgorithm){
+ case RT_ENC_ALG_TKIP:
+ bResult = SecCheckTKIPMIC(Adapter, pRfd);
+ break;
+ case RT_ENC_ALG_AESCCMP:
+ //2004/07/12, kcwu
+ //Check AES MIC
+ break;
+ default:
+ bResult = TRUE;
+ }
+ return bResult;
+
+}
+
+
+//
+// Description:
+// Figure out TKIP MIC from packet content and compare it to
+// MIC of packet received.
+//
+// 2004.10.08, by rcnjko.
+//
+BOOLEAN
+SecCheckTKIPMIC(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ u1Byte DestAddr[6];
+ u1Byte SrcAddr[6];
+ u1Byte Keyidx = 0;
+ u1Byte Qos[4];
+ MicData micdata;
+ u1Byte mic_for_check[8], mic_from_packet[8];
+ OCTET_STRING frame = {0};
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ PRT_RFD pPrevRfd = NULL;
+ PRT_RFD pCurrRfd = NULL;
+ pu1Byte pCurrBuffer = NULL;
+ int CurrBufferLen = 0;
+ PRT_WLAN_STA pEntry =NULL;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte IVKeyIdOffset;
+
+ // <RJ_TODO> This is just a workaround for HCT 12.1, 2005.07.11, by rcnjko.
+ if(pMgntInfo->mIbss)
+ {
+ return TRUE;
+ }
+
+ // <RJ_TODO> This is just a workaround for WiFi 5.2.2.4 S2 might failed
+ // in unknown condition. For example, we think the packets received is TKIP MIC error
+ // during this test and finally trigger counter measure. 2005.09.06, by rcnjko.
+ // Prefast warning C28182: Dereferencing NULL pointer. 'pRfd' contains NULL.
+ if(pRfd != NULL && pRfd->nTotalFrag > 1)
+ {
+ return TRUE;
+ }
+
+ // Initialize first buffer of the packet to as header.
+ // Prefast warning C6011: Dereferencing NULL pointer 'pRfd'.
+ if (pRfd != NULL)
+ {
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, (u2Byte)pRfd->FragLength);
+ }
+ //PRINT_DATA("Recieved Packet==>", pRfd->Buffer.VirtualAddress, pRfd->FragLength);
+
+ // Get offset. Added by Annie, 2005-12-22.
+ if(pRfd != NULL && pRfd->Status.bIsQosData )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ // Prefast warning C6011: Dereferencing NULL pointer 'pRfd'.
+ if(pRfd != NULL && pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+
+ IVKeyIdOffset = IVOffset + KEYID_POS_IN_IV;
+
+
+ // Packet length check.
+ if(pRfd != NULL && pRfd->PacketLength < IVOffset )
+ {
+ RT_TRACE(COMP_DBG, DBG_LOUD, ("SecCheckTKIPMIC(): pRfd->PacketLength < IVOffset\n"));
+ return FALSE; // Drop the packet.
+ }
+
+ // Prefast warning C6011: Dereferencing NULL pointer 'frame.Octet'.
+ if (frame.Octet != NULL)
+ {
+ // Get DestAddr from header. //Modified by Jay 0713
+ PlatformMoveMemory(DestAddr, Frame_pDaddr(frame), ETHERNET_ADDRESS_LENGTH);
+
+ // Get SrcAddr from header.
+ PlatformMoveMemory(SrcAddr, Frame_pSaddr(frame), ETHERNET_ADDRESS_LENGTH);
+ }
+
+ // Step 1. Set key.
+ // Prefast warning C6011: Dereferencing NULL pointer 'frame.Octet'
+ if(ACTING_AS_AP(Adapter) && frame.Octet != NULL) //Added by Jay for SwAP 0708
+ { // AP Mode.
+ pEntry = AsocEntry_GetEntry(pMgntInfo, Frame_pSaddr(frame));
+
+ if(pEntry == NULL)
+ return FALSE;
+
+ if(pEntry->perSTAKeyInfo.RxMICKey == NULL)
+ return FALSE;
+
+ SecMICSetKey(&micdata, pEntry->perSTAKeyInfo.RxMICKey);
+ }
+ else if(pRfd != NULL && pRfd->bTDLPacket)
+ {
+ pEntry = AsocEntry_GetEntry(pMgntInfo, Frame_pSaddr(frame));
+
+ if(pEntry == NULL)
+ return FALSE;
+
+ if(pEntry->perSTAKeyInfo.TxMICKey == NULL)
+ return FALSE;
+
+ SecMICSetKey(&micdata, pEntry->perSTAKeyInfo.TxMICKey);
+ }
+ else
+ { // STA Mode.
+ // Get key index.
+ // Prefast warning C6011: Dereferencing NULL pointer 'frame.Octet'
+ if(frame.Octet != NULL)
+ Keyidx = SecGetRxKeyIdx( Adapter, DestAddr, ((frame.Octet[IVKeyIdOffset]>>6)&0x03) ); // Changed by Annie, 2005-12-22.
+
+ //RT_TRACE(COMP_DBG, DBG_LOUD, ("SecCheckTKIPMIC(): Keyidx: %d\n", Keyidx));
+ if(Keyidx > 4)
+ {
+ RT_TRACE(COMP_SEC, DBG_LOUD, ("SecCheckTKIPMIC(): Keyidx: %d > 4\n", Keyidx));
+ return FALSE; // Drop the packet.
+ }
+
+ SecMICSetKey(&micdata, pSec->KeyBuf[Keyidx]+TKIP_MICKEYTX_POS);
+
+ }
+
+ // Step 2. Append DestAddr and SrcAddr into micdata.
+ SecMICAppend(&micdata, DestAddr, ETHERNET_ADDRESS_LENGTH);
+ SecMICAppend(&micdata, SrcAddr, ETHERNET_ADDRESS_LENGTH);
+
+ // Step 3. Append Qos into micdata.
+ PlatformZeroMemory(Qos, 4);
+ if(pRfd != NULL && pRfd->Status.bIsQosData )
+ {
+ // Parsing priority to calculate TKIP MIC. Annie, 2005-12-22.
+ Qos[0] = GET_QOS_CTRL_WMM_UP(frame.Octet);
+ }
+
+ SecMICAppend(&micdata, Qos, 4);
+
+ // Step 4. Append each buffers of the packet into micdata.
+ pCurrRfd = pRfd;
+ pPrevRfd = pRfd; // 2010/04/30 MH Prevent BSOD when copy mem from NULL ptr at below case.
+ //Exclude header of first buffer of the packet.
+ // Prefast warning C28182: Dereferencing NULL pointer. 'pCurrRfd' contains NULL
+ if (pCurrRfd != NULL)
+ {
+ pCurrBuffer = pCurrRfd->Buffer.VirtualAddress + (IVOffset + pSec->EncryptionHeadOverhead);
+ CurrBufferLen = (int)(pCurrRfd->FragLength) - ((int)(IVOffset)+(int)(pSec->EncryptionHeadOverhead));
+ }
+ while(pCurrRfd != NULL)
+ {
+ // Get MIC of the Last buffer and exclude MIC from it.
+ if(pCurrRfd->NextRfd == NULL)
+ {
+ if(CurrBufferLen >= TKIP_MIC_LEN)
+ { // MIC is not fragmented.
+
+ // Get MIC.
+ PlatformMoveMemory(
+ mic_from_packet,
+ pCurrBuffer + CurrBufferLen - TKIP_MIC_LEN,
+ TKIP_MIC_LEN);
+
+ // Adjust size to append into micdata.
+ CurrBufferLen -= TKIP_MIC_LEN;
+ }
+ else
+ { // MIC is fragmented into two part.
+ int cbMicInPrev = TKIP_MIC_LEN - CurrBufferLen;
+
+ RT_ASSERT(pPrevRfd != NULL, ("SecCheckTKIPMIC(): pRevRfd should not be NULL in this case.\n"));
+
+ // Get MIC.
+ PlatformMoveMemory(
+ mic_from_packet,
+ pPrevRfd->Buffer.VirtualAddress + pPrevRfd->FragLength - cbMicInPrev,
+ cbMicInPrev);
+ PlatformMoveMemory(
+ mic_from_packet + cbMicInPrev,
+ pCurrBuffer,
+ CurrBufferLen);
+
+ // Adjust size to append into micdata.
+ CurrBufferLen = 0;
+ }
+ }
+ else if(pCurrRfd->NextRfd->NextRfd == NULL)
+ { // In case if MIC is fragmented, we must take care about the last two fragment.
+
+ if(pCurrRfd->NextRfd->FragLength < TKIP_MIC_LEN)
+ { // MIC is fragmented.
+ int cbMicInPrev = TKIP_MIC_LEN - pCurrRfd->NextRfd->FragLength;
+
+ RT_ASSERT(CurrBufferLen >= TKIP_MIC_LEN, ("SecCheckTKIPMIC(): the length of last two buffer: %d\n", CurrBufferLen));
+ // Adjust size to append into micdata.
+ CurrBufferLen -= cbMicInPrev;
+ }
+ }
+
+ // Append this buffer into micdata.
+ if(CurrBufferLen > 0)
+ {
+ SecMICAppend(&micdata, pCurrBuffer, CurrBufferLen);
+ }
+
+ // Next one.
+ pPrevRfd = pCurrRfd;
+ pCurrRfd = pCurrRfd->NextRfd;
+ if(pCurrRfd != NULL)
+ {
+ pCurrBuffer = pCurrRfd->Buffer.VirtualAddress + pCurrRfd->FragOffset;
+ CurrBufferLen = pCurrRfd->FragLength;
+ }
+ else
+ {
+ pCurrBuffer = NULL;
+ CurrBufferLen = 0;
+ }
+ }
+
+ // Figure out MIC from micdata.
+ SecMICGetMIC(&micdata, mic_for_check);
+// PRINT_DATA((const void*)"mic_for_check===>", (const void*)mic_for_check, TKIP_MIC_LEN);
+// PRINT_DATA((const void*)"mic_from_packet===>", (const void*)mic_from_packet, TKIP_MIC_LEN);
+
+ // Compare two MICs.
+ if(PlatformCompareMemory(mic_for_check, mic_from_packet,TKIP_MIC_LEN))
+ { // Different!
+ BOOLEAN bMcstDest = MacAddr_isMulticast(DestAddr);
+
+ // Prefast warning 6011: Dereferencing NULL pointer 'pRfd'.
+ if (pRfd != NULL)
+ {
+ RT_TRACE(COMP_SEC, DBG_WARNING,
+ ("Rx:TKIP_MIC Error, Decrypted: %x, bMcstDest: %d\n",
+ pRfd->Status.Decrypted, bMcstDest));
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "SecCheckTKIPMIC(): TKIP_MIC Error packet", pRfd->Buffer.VirtualAddress, pRfd->FragLength);
+ }
+
+ if (frame.Octet != NULL)
+ {
+ if (IsDataFrame(frame.Octet))
+ CountRxTKIPLocalMICFailuresStatistics(Adapter, pRfd);
+ else if (IsMgntFrame(frame.Octet))
+ CountRxMgntTKIPLocalMICFailuresStatistics(Adapter, pRfd);
+ }
+
+ // Handle TKIP MIC error.
+ if(ACTING_AS_AP(Adapter)) //Added by Jay 0708.
+ { // AP Mode.
+ //Enter integrity failure state...
+ Authenticator_StateINTEGRITYFAILURE(Adapter, pEntry);
+ }
+ else if(pRfd != NULL && pRfd->bTDLPacket)
+ {
+ Authenticator_StateINTEGRITYFAILURE(Adapter, pEntry);
+ }
+ else
+ { // STA Mode.
+
+ // We don't indication MIC ERROR in MFP Packet !!
+ // Prefast warning C28182: Dereferencing NULL pointer. 'pRfd' contains the same NULL value as 'pCurrRfd' did.
+ if(pRfd != NULL && !pRfd->Status.bRxMFPPacket )
+ PlatformHandleTKIPMICError(Adapter, bMcstDest, Keyidx, SrcAddr);
+ }
+
+ return FALSE;
+ }
+ else
+ { // The same.
+
+ RT_TRACE(COMP_DBG, DBG_LOUD, ("Rx:TKIP_MIC Ok\n"));
+ return TRUE;
+ }
+}
+
+
+
+u1Byte
+SecGetRxKeyIdx(
+ PADAPTER Adapter,
+ pu1Byte pDestAddr,
+ u1Byte IVKeyIdx
+ )
+{
+ u1Byte keyidx = PAIRWISE_KEYIDX;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ //pairwise keyidx in our driver is 4
+
+
+ if(MacAddr_isMulticast(pDestAddr))
+ {
+ //2004/07/07, kcwu, if it is a multicast packet
+ //keyidx = ((pSec->KeyLen[pSec->GroupTransmitKeyIdx]==0)?5:pSec->GroupTransmitKeyIdx);
+
+ // Use IV's Key ID for group key.
+ // 2004.10.06, by rcnjko.
+ if(pSec->KeyLen[IVKeyIdx] == 0)
+ {
+ keyidx = 5;
+ }
+ else
+ {
+ keyidx = IVKeyIdx;
+ }
+ }
+ else
+ {
+ //2004/07/07, kcwu, if it is a unicast packet
+ if(pSec->KeyLen[PAIRWISE_KEYIDX] == 0)
+ {
+ //2004/07/07, kcwu, if there is no pairwise key
+ keyidx = ((pMgntInfo->mIbss&&pSec->KeyLen[pSec->GroupTransmitKeyIdx]!=0)?pSec->GroupTransmitKeyIdx:5);
+ }
+ }
+ return keyidx;
+}
+
+
+
+/*2004/06/28, kcwu
+We don't fill security header of all fragment here, the for statement should in the outside function,
+not in this function. So just simply provide the start of packet.
+
+*/
+VOID
+SecHeaderFillIV(
+ PADAPTER Adapter,
+ pu1Byte PacketStart
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ OCTET_STRING oFrame = {0,0};
+ RT_ENC_ALG SelectEncAlgorithm = pSec->PairwiseEncAlgorithm;
+ BOOLEAN show = FALSE;
+
+ //Address 1 is always receiver's address
+ pu1Byte pRA = PacketStart+4;
+ pu1Byte pSecHeader = PacketStart + sMacHdrLng;
+
+ if(pMgntInfo->SafeModeEnabled)
+ return;
+
+ if( IsQoSDataFrame(PacketStart) )
+ {
+ pSecHeader += sQoSCtlLng;
+ }
+
+ // Check address 4 valiaddr , add for BT
+ // Note : AP WDS mode need to do ....
+ oFrame.Octet = PacketStart;
+
+ if( Frame_ValidAddr4( oFrame ) )
+ {
+ RT_TRACE( COMP_SEC , DBG_LOUD, ("===>SecHeaderFillIV() : 4 address data \n") );
+ SelectEncAlgorithm = RT_ENC_ALG_AESCCMP;
+ pSecHeader += 6;
+ show = TRUE;
+ }
+
+ switch(SelectEncAlgorithm){
+ case RT_ENC_ALG_WEP104:
+ case RT_ENC_ALG_WEP40:
+ {
+ // CKIP should also go into this case.
+ pSecHeader[0] = EF1Byte( (u1Byte) (((pSec->TxIV&0x00000000ffffffff) >>16) & 0xff) );
+ pSecHeader[1] = EF1Byte( (u1Byte) (((pSec->TxIV&0x00000000ffffffff) >>8) & 0xff) );
+ pSecHeader[2] = EF1Byte( (u1Byte) (((pSec->TxIV&0x00000000ffffffff) >>0) & 0xff) );
+
+
+ pSec->TxIV = (pSec->TxIV == 0xffffff)?0:pSec->TxIV+1;
+ //Default Key ID
+ pSecHeader[3] = EF1Byte( (u1Byte)((pSec->DefaultTransmitKeyIdx<<6)&0xc0) );
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ {
+ if(!ACTING_AS_AP(Adapter))
+ { // STA.
+ u2Byte u2IV16 = (u2Byte)(pSec->TxIV& UINT64_C(0x000000000000ffff) );
+ u4Byte u4IV32 = (u4Byte)(((pSec->TxIV& UINT64_C(0x0000ffffffff0000) ) >> 16)& UINT64_C(0x00000000ffffffff) );
+ pSec->TxIV++;
+
+ //keyid is always 0 for STA
+ TKIP_TSC_DECIMAL2ARRAY(u2IV16, u4IV32, 0, pSecHeader);
+ }
+ else
+ { // AP.
+ if(!MacAddr_isMulticast(pRA))
+ { // Unicast.
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_WLAN_STA pEntry;
+ u2Byte u2IV16;
+ u4Byte u4IV32;
+
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pRA);
+
+ // Annie for debug, 2005-07-25.
+ RT_ASSERT( pEntry!=NULL, ("SecHeaderFillIV(): pEntry is NULL!\n"));
+ if( pEntry==NULL )
+ return;
+ u2IV16 = (u2Byte)(pEntry->perSTAKeyInfo.TxIV & UINT64_C(0x000000000000ffff) );
+ u4IV32 = (u4Byte)(((pEntry->perSTAKeyInfo.TxIV& UINT64_C(0x0000ffffffff0000) ) >> 16)& UINT64_C(0x00000000ffffffff) );
+ pEntry->perSTAKeyInfo.TxIV++;
+
+ //keyid is always 0 for STA
+ TKIP_TSC_DECIMAL2ARRAY(u2IV16, u4IV32, 0, pSecHeader);
+ }
+ else
+ { // Mcst/Bcst
+ u2Byte u2IV16 = (u2Byte)(pSec->TxIV& UINT64_C(0x000000000000ffff) );
+ u4Byte u4IV32 = (u4Byte)(((pSec->TxIV& UINT64_C( 0x0000ffffffff0000) ) >> 16)& UINT64_C(0x00000000ffffffff));
+ pSec->TxIV++;
+
+ // <TODO> This is just a workaround, we assume group keyid=1.
+ TKIP_TSC_DECIMAL2ARRAY(u2IV16, u4IV32, 1, pSecHeader);
+ }
+ }
+ }
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ if(!pMgntInfo->bRSNAPSKMode && !ACTING_AS_AP(Adapter) )
+ {
+ if(show)
+ {
+ RT_TRACE( COMP_SEC , DBG_LOUD , ("===>ccw Ok \n") );
+ }
+
+ PN_DECIMAL2ARRAY((pSec->TxIV& UINT64_C(0xffffffff00000000) ),
+ (pSec->TxIV& UINT64_C(0x00000000ffffffff)),
+ PAIRWISE_KEYIDX, //keyid = 0 for pairwise packet
+ pSecHeader);
+ pSec->TxIV++;
+ }
+ else if( ACTING_AS_AP(Adapter) )
+ {
+
+ if(!MacAddr_isMulticast(pRA))
+ { // Pairwise traffic.
+
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_WLAN_STA pEntry;
+
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pRA);
+
+ if( pEntry==NULL )
+ return;
+
+ PN_DECIMAL2ARRAY((pEntry->perSTAKeyInfo.TxIV& UINT64_C(0xffffffff00000000)),
+ (pEntry->perSTAKeyInfo.TxIV& UINT64_C(0x00000000ffffffff)),
+ 0, //keyid = 0 for pairwise packet
+ pSecHeader);
+ pEntry->perSTAKeyInfo.TxIV++;
+ }
+ else
+ { // Group traffic.
+ PN_DECIMAL2ARRAY((pSec->TxIV& UINT64_C(0xffffffff00000000)),
+ (pSec->TxIV& UINT64_C(0x00000000ffffffff)),
+ pSec->GroupTransmitKeyIdx,// 0,
+ pSecHeader);
+ pSec->TxIV++;
+ }
+
+ }
+ else
+ {
+ if(!MacAddr_isMulticast(pRA))
+ { // Pairwise traffic.
+ PN_DECIMAL2ARRAY((pSec->TxIV& UINT64_C(0xffffffff00000000) ),
+ (pSec->TxIV&0x00000000ffffffff),
+ PAIRWISE_KEYIDX, //keyid = 0 for pairwise packet
+ pSecHeader);
+ }
+ else
+ { // Group traffic.
+ PN_DECIMAL2ARRAY((pSec->TxIV& UINT64_C(0xffffffff00000000) ),
+ (pSec->TxIV& UINT64_C(0x00000000ffffffff) ),
+ pSec->DefaultTransmitKeyIdx,
+ pSecHeader);
+ }
+ pSec->TxIV++;
+ }
+
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ WAPI_SecFuncHandler(WAPI_SECHEADERFILLIV, Adapter, (PVOID)pRA,(PVOID)pSecHeader,WAPI_END);
+ break;
+
+ case RT_ENC_ALG_NO_CIPHER:
+ default:
+ return;
+ }
+}
+
+
+//
+//Note : SecInit() need to Used after SecClearAllKeys();
+// Because Clear CAM Key will check SecInfo Key Buffer Length
+// If Length = 0, CAM entey will "NO" Clear ....
+
+VOID
+SecInit(
+ PADAPTER Adapter
+ )
+{
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ s1Byte i = 0;
+
+ pSec->PairwiseEncAlgorithm = pSec->GroupEncAlgorithm = RT_ENC_ALG_AESCCMP;
+
+ pSec->DefaultTransmitKeyIdx = 0;
+ pSec->GroupTransmitKeyIdx = 0;
+ SecSetSwEncryptionDecryption(Adapter, FALSE, FALSE);
+ pSec->SWRxAESMICFlag = FALSE;
+ pSec->bGroupKeyFixed = FALSE;
+
+ pSec->AuthMode = RT_802_11AuthModeWPA2;
+ pSec->EncryptionStatus = RT802_11EncryptionDisabled;
+ pSec->TxIV = DEFAULT_INIT_TX_IV;
+
+ // 2007.08.08 We must initialize this value, otherwise, software decryption
+ // without initilization of AES mode cause Assertion in Vista. By Lanhsin
+ pSec->AESCCMPMicLen = 8;
+
+ PlatformZeroMemory(pSec->RSNIEBuf, MAXRSNIELEN);
+ pSec->RSNIE.Length = 0;
+ FillOctetString(pSec->RSNIE, pSec->RSNIEBuf, pSec->RSNIE.Length);
+
+ pSec->SecLvl = RT_SEC_LVL_WPA2;
+
+ //2004/09/07, kcwu, initialize key buffer
+ for(i = 0;i<KEY_BUF_SIZE; i++){
+ PlatformZeroMemory(pSec->AESKeyBuf[i], MAX_KEY_LEN);
+ PlatformZeroMemory(pSec->KeyBuf[i], MAX_KEY_LEN);
+ pSec->KeyLen[i] = 0;
+ }
+
+ //kcwu_todo: Clear key buffer
+
+ //Point Pairwise key to appropriate index
+ pSec->PairwiseKey = pSec->KeyBuf[PAIRWISE_KEYIDX];
+ pSec->UseDefaultKey = FALSE;
+
+ // WPA2 Pre-Authentication related. Added by Annie, 2006-05-07.
+ pSec->EnablePreAuthentication = pSec->RegEnablePreAuth; // Added by Annie, 2005-02-15.
+ PlatformZeroMemory(pSec->PMKIDList, sizeof(RT_PMKID_LIST)*NUM_PMKID_CACHE);
+ for( i=0; i<NUM_PMKID_CACHE; i++ )
+ {
+ FillOctetString( pSec->PMKIDList[i].Ssid, pSec->PMKIDList[i].SsidBuf, 0 );
+ }
+
+ PlatformZeroMemory(pSec->szCapability, 256);
+
+ init_crc32();
+
+ // Initialize TKIP MIC error related, 2004.10.06, by rcnjko.
+ pSec->LastPairewiseTKIPMICErrorTime = 0;
+ pSec->bToDisassocAfterMICFailureReportSend = FALSE;
+ for(i = 0; i < MAX_DENY_BSSID_LIST_CNT; i++)
+ {
+ pSec->DenyBssidList[i].bUsed = FALSE;
+ }
+
+}
+
+/*
+
+ IN PADAPTER Adapter,
+ IN u4Byte KeyIndex,
+ IN pu1Byte pMacAddr,
+ IN BOOLEAN IsGroup,
+ IN u1Byte EncAlgo,
+ IN BOOLEAN IsWEPKey//if OID = OID_802_11_WEP
+*/
+
+//
+//Note : SecClearAllKeys() need to Used before SecInit();
+// Because Clear CAM Key will check SecInfo Key Buffer Length
+// If Length = 0, CAM entey will "NO" Clear ....
+
+VOID
+SecClearAllKeys(
+ PADAPTER Adapter
+ )
+{
+ int i;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+
+ PlatformZeroMemory(pSec->TxMICKey, TKIP_MIC_KEY_LEN);
+ PlatformZeroMemory(pSec->RxMICKey, TKIP_MIC_KEY_LEN);
+ pSec->DefaultTransmitKeyIdx = 0;
+ Adapter->HalFunc.SetKeyHandler(Adapter, 0, 0, 0, 0, 0, TRUE);
+
+ //
+ // Clear keys used for RSNA IBSS.
+ //
+ for(i = 0; i < MAX_NUM_PER_STA_KEY; i++)
+ {
+ PlatformZeroMemory( &(pSec->PerStaDefKeyTable[i]), sizeof(PER_STA_DEFAULT_KEY_ENTRY) );
+ PlatformZeroMemory( &(pSec->MAPKEYTable[i]), sizeof(PER_STA_MPAKEY_ENTRY) );
+ }
+}
+
+VOID
+SecClearGroupKeyByIdx(
+ PADAPTER Adapter,
+ u1Byte paraIndex
+){
+ PlatformZeroMemory(Adapter->MgntInfo.SecurityInfo.KeyBuf[paraIndex], MAX_KEY_LEN);
+ Adapter->MgntInfo.SecurityInfo.KeyLen[paraIndex] = 0;
+ Adapter->HalFunc.SetKeyHandler(Adapter, paraIndex, 0, TRUE,
+ Adapter->MgntInfo.SecurityInfo.GroupEncAlgorithm, FALSE, FALSE);
+}
+
+VOID
+SecClearWEPKeyByIdx(
+ PADAPTER Adapter,
+ u1Byte paraIndex
+ )
+{
+ PlatformZeroMemory(Adapter->MgntInfo.SecurityInfo.KeyBuf[paraIndex], MAX_KEY_LEN);
+ Adapter->MgntInfo.SecurityInfo.KeyLen[paraIndex] = 0;
+ Adapter->HalFunc.SetKeyHandler(Adapter, paraIndex, 0, TRUE,
+ Adapter->MgntInfo.SecurityInfo.GroupEncAlgorithm, FALSE, FALSE);
+}
+//for AP mode
+VOID
+SecClearPairwiseKeyByMacAddr(
+ PADAPTER Adapter,
+ pu1Byte paraMacAddr
+ )
+{
+ //2004/09/15, kcwu
+ PlatformZeroMemory(Adapter->MgntInfo.SecurityInfo.PairwiseKey, MAX_KEY_LEN);
+ Adapter->MgntInfo.SecurityInfo.KeyLen[PAIRWISE_KEYIDX] = 0;
+ //2004/09/07, kcwu, disable the key entry in cam
+ Adapter->HalFunc.SetKeyHandler(Adapter, PAIRWISE_KEYIDX, paraMacAddr, FALSE,
+ Adapter->MgntInfo.SecurityInfo.PairwiseEncAlgorithm, FALSE, FALSE);
+}
+
+//
+// Description:
+// Select one AKM suite according to the input self AKM suite and the target info.
+// Arguments:
+// [in] pAdapter -
+// The location of target adapter.
+// [in] AuthMode -
+// The self AKM suite.
+// [in] contentType -
+// The type of pInfoBuf.
+// [in] pInfoBuf -
+// This field is determined by contentType and shall be casted to the corresponding type.
+// pInfoBuf is PRT_WLAN_BSS if contentType is CONTENT_PKT_TYPE_CLIENT.
+// This field may be NULL according to contentType.
+// [in] InfoBufLen -
+// Length in byte of pInfoBuf.
+// [OUT] pAKM -
+// Return the selected AKM.
+// Return:
+// RT_STATUS_SUCCESS, if the content is appended withour error.
+// RT_STATUS_INVALID_DATA, if any of pInfoBuf or InfoBufLen is incorrect.
+// RT_STATUS_INVALID_STATE, if the security parameter is mismatched.
+// Remark:
+// If targetAKMSuite is 0, this function ignores the target setting and only reference the self AuthMode to
+// determine the final AKM_SUITE_TYPE.
+// By Bruce, 2015-12-16.
+//
+RT_STATUS
+Sec_SelAkmFromAuthMode(
+ IN PADAPTER pAdapter,
+ IN RT_AUTH_MODE AuthMode,
+ IN CONTENT_PKT_TYPE contentType,
+ IN PVOID pInfoBuf,
+ IN u4Byte InfoBufLen,
+ OUT PAKM_SUITE_TYPE pAKM
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ BOOLEAN bCCX8021xenable = FALSE;
+ BOOLEAN bAPSuportCCKM = FALSE;
+ PRT_WLAN_BSS pTargetBss = NULL;
+ u4Byte ftMDIeLen = 0;
+ AKM_SUITE_TYPE targetAKMSuites = AKM_SUITE_NONE;
+
+ CHECK_NULL_RETURN_STATUS(pAKM);
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ PFT_INFO_ENTRY pEntry = NULL;
+
+ if(!pInfoBuf || InfoBufLen < sizeof(RT_WLAN_BSS))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_SERIOUS, ("Invalid input buffer or length, pInfoBuf = %p, InfoBufLen = %d\n", pInfoBuf, InfoBufLen));
+ return RT_STATUS_INVALID_DATA;
+ }
+ pTargetBss = (PRT_WLAN_BSS)pInfoBuf;
+
+ targetAKMSuites = pTargetBss->AKMsuit;
+
+ CCX_QueryCCKMSupport(pAdapter, &bCCX8021xenable, &bAPSuportCCKM);
+
+ // Check we shall choose Fast Transition as the AKM
+ if(((TEST_FLAG(pTargetBss->AKMsuit, AKM_FT_1X) && TEST_FLAG(pAdapter->MgntInfo.RegCapAKMSuite, AKM_FT_1X)) ||
+ (TEST_FLAG(pTargetBss->AKMsuit, AKM_FT_PSK) && TEST_FLAG(pAdapter->MgntInfo.RegCapAKMSuite, AKM_FT_PSK))) &&
+ (pEntry = FtGetEntry(pAdapter, pTargetBss->bdBssIdBuf)))
+ {
+ ftMDIeLen = pEntry->MDELen;
+ }
+ }
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("AuthMode = %d, RegCapAKMSuite = 0x%08X\n", AuthMode, pAdapter->MgntInfo.RegCapAKMSuite));
+
+ switch (AuthMode)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case RT_802_11AuthModeWPA:
+ if(bCCX8021xenable && bAPSuportCCKM)
+ {
+ *pAKM = AKM_WPA_CCKM;
+ }
+ else
+ {
+ *pAKM = AKM_WPA_1X;
+ }
+ break;
+
+ case RT_802_11AuthModeWPA2:
+ if(bCCX8021xenable && bAPSuportCCKM)
+ {
+ *pAKM = AKM_WPA2_CCKM;
+ }
+ else if(ftMDIeLen > 0)
+ {
+ *pAKM = AKM_FT_1X;
+ }
+ else if(TEST_FLAG(targetAKMSuites, AKM_RSNA_1X_SHA256) && TEST_FLAG(pAdapter->MgntInfo.RegCapAKMSuite, AKM_RSNA_1X_SHA256))
+ {
+ *pAKM = AKM_RSNA_1X_SHA256;
+ }
+ else
+ {
+ *pAKM = AKM_WPA2_1X;
+ }
+ break;
+
+ case RT_802_11AuthModeWPAPSK:
+ *pAKM = AKM_WPA_PSK;
+ break;
+
+ case RT_802_11AuthModeWPA2PSK:
+ {
+ if(ftMDIeLen > 0)
+ {
+ *pAKM = AKM_FT_PSK;
+ }
+ else if(TEST_FLAG(targetAKMSuites, AKM_RSNA_PSK_SHA256) && TEST_FLAG(pAdapter->MgntInfo.RegCapAKMSuite, AKM_RSNA_PSK_SHA256))
+ {
+ *pAKM = AKM_RSNA_PSK_SHA256;
+ }
+ else
+ {
+ *pAKM = AKM_WPA2_PSK;
+ }
+ }
+ break;
+ }
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Get the OUI and OUI type from the AKM suite.
+// Arguments:
+// [in] AKMSuite -
+// The AKM suite.
+// [out] pOUI -
+// Return the OUI with 3 bytes if returned status is RT_STATUS_SUCCESS.
+// If AKMSuite is AKM_SUITE_NONE , return all 0 in pOUI.
+// [out] pOUIType -
+// Return the OUI type with 1 byte if returned status is RT_STATUS_SUCCESS.
+// If AKMSuite is AKM_SUITE_NONE , return 0 in pOUIType.
+// Return:
+// RT_STATUS_SUCCESS, if the translation succeeds.
+// RT_STATUS_NOT_RECOGNIZED, if the AKMSuite is not recognized.
+//
+RT_STATUS
+Sec_MapAKMSuiteToOUIType(
+ IN AKM_SUITE_TYPE AKMSuite,
+ OUT pu1Byte pOUI,
+ OUT pu1Byte pOUIType
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ switch(AKMSuite)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case AKM_SUITE_NONE:
+ {
+ PlatformZeroMemory(pOUI, SIZE_OUI);
+ PlatformZeroMemory(pOUIType, SIZE_OUI_TYPE);
+ }
+ break;
+
+ case AKM_WPA_1X:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = AKM_WPA_1X_OUI_TYPE;
+ }
+ break;
+
+ case AKM_WPA_PSK:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = AKM_WPA_PSK_OUI_TYPE;
+ }
+ break;
+
+ case AKM_WPA_CCKM:
+ {
+ PlatformMoveMemory(pOUI, CCKM_OUI, SIZE_OUI);
+ *pOUIType = CCKM_OUI_TYPE;
+ }
+ break;
+
+ case AKM_WPA2_1X:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_RSN_1X;
+ }
+ break;
+
+ case AKM_WPA2_PSK:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_RSN_PSK;
+ }
+ break;
+
+ case AKM_WPA2_CCKM:
+ {
+ PlatformMoveMemory(pOUI, CCKM_OUI, SIZE_OUI);
+ *pOUIType = CCKM_OUI_TYPE;
+ }
+ break;
+
+ case AKM_RSNA_1X_SHA256:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_1X_SHA256;
+ }
+ break;
+
+ case AKM_RSNA_PSK_SHA256:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_PSK_SHA256;
+ }
+ break;
+
+ case AKM_FT_1X:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_FT_1X;
+ }
+ break;
+
+ case AKM_FT_PSK:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_AKM_SUITE_OUI_TYPE_FT_PSK;
+ }
+ break;
+ }
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Get the AKM suite in AKM_SUITE_TYPE from OUI and OUI type.
+// Arguments:
+// [out] pOUI -
+// The OUI with 3 bytes.
+// If the input is all 0 in pOUI, return AKM_SUITE_NONE.
+// [out] pOUIType -
+// The OUI type with 1 byte.
+// If the input is all 0 in pOUIType, return AKM_SUITE_NONE.
+// [in] secLevl -
+// Input the security level related to OUI and OUIType
+// [in] pAKMSuite -
+// Return The tcipher suite.
+// Return:
+// RT_STATUS_SUCCESS, if the translation succeeds.
+// RT_STATUS_NOT_RECOGNIZED, if the pOUI/pOUIType is not recognized.
+// RT_STATUS_INVALID_DATA, if any of pOUI, pOUIType, or secLevl is invalid.
+//
+RT_STATUS
+Sec_MapOUITypeToAKMSuite(
+ IN pu1Byte pOUI,
+ IN pu1Byte pOUIType,
+ IN RT_SECURITY_LEVEL secLevl,
+ OUT PAKM_SUITE_TYPE pAKMSuite
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ CHECK_NULL_RETURN_STATUS(pOUI);
+ CHECK_NULL_RETURN_STATUS(pOUIType);
+ CHECK_NULL_RETURN_STATUS(pAKMSuite);
+
+ if(RT_SEC_LVL_NONE == secLevl)
+ {
+ *pAKMSuite = AKM_SUITE_NONE;
+ }
+ else if(RT_SEC_LVL_WPA == secLevl)
+ {
+ if(eqOUI(pOUI, WPA_OUI))
+ {
+ switch(*pOUIType)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case AKM_WPA_1X_OUI_TYPE:
+ *pAKMSuite = AKM_WPA_1X;
+ break;
+
+ case AKM_WPA_PSK_OUI_TYPE:
+ *pAKMSuite = AKM_WPA_PSK;
+ break;
+ }
+ }
+ else if(eqOUI(pOUI, CCKM_OUI) && CCKM_OUI_TYPE == *pOUIType)
+ {
+ *pAKMSuite = AKM_WPA_CCKM;
+ }
+ else
+ {
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ }
+ }
+ else if(RT_SEC_LVL_WPA2 == secLevl)
+ {
+ if(eqOUI(pOUI, RSN_OUI))
+ {
+ switch(*pOUIType)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_RSN_1X:
+ *pAKMSuite = AKM_WPA2_1X;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_RSN_PSK:
+ *pAKMSuite = AKM_WPA2_PSK;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_FT_1X:
+ *pAKMSuite = AKM_FT_1X;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_FT_PSK:
+ *pAKMSuite = AKM_FT_PSK;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_1X_SHA256:
+ *pAKMSuite = AKM_RSNA_1X_SHA256;
+ break;
+
+ case RSN_AKM_SUITE_OUI_TYPE_PSK_SHA256:
+ *pAKMSuite = AKM_RSNA_PSK_SHA256;
+ break;
+ }
+ }
+ else if(eqOUI(pOUI, CCKM_OUI) && CCKM_OUI_TYPE == *pOUIType)
+ {
+ *pAKMSuite = AKM_WPA2_CCKM;
+ }
+ else
+ {
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ }
+ }
+
+ return RT_STATUS_NOT_SUPPORT;
+}
+
+
+//
+// Description:
+// Get the OUI and OUI type from the cipher suite in RT_ENC_ALG.
+// Arguments:
+// [in] cipherSuite -
+// The cipher suite.
+// [in] secLevl -
+// Security level such WPA or WPA2.
+// [out] pOUI -
+// Return the OUI with 3 bytes if returned status is RT_STATUS_SUCCESS.
+// If cipherSuite is RT_ENC_ALG_NO_CIPHER , return all 0 in pOUI.
+// [out] pOUIType -
+// Return the OUI type with 1 byte if returned status is RT_STATUS_SUCCESS.
+// If AKMSuite is RT_ENC_ALG_NO_CIPHER , return 0 in pOUIType.
+// Return:
+// RT_STATUS_SUCCESS, if the translation succeeds.
+// RT_STATUS_NOT_RECOGNIZED, if the cipherSuite is not recognized.
+// RT_STATUS_INVALID_DATA, if the cipherSuite is invalid.
+//
+RT_STATUS
+Sec_MapCipherSuiteToOUIType(
+ IN RT_ENC_ALG cipherSuite,
+ IN RT_SECURITY_LEVEL secLevl,
+ OUT pu1Byte pOUI,
+ OUT pu1Byte pOUIType
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ if(RT_SEC_LVL_NONE == secLevl)
+ {
+ PlatformZeroMemory(pOUI, SIZE_OUI);
+ PlatformZeroMemory(pOUIType, SIZE_OUI_TYPE);
+ }
+ else if(RT_SEC_LVL_WPA == secLevl)
+ {
+ switch(cipherSuite)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case RT_ENC_ALG_NO_CIPHER:
+ {
+ PlatformZeroMemory(pOUI, SIZE_OUI);
+ PlatformZeroMemory(pOUIType, SIZE_OUI_TYPE);
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = WPA_CIPHER_SUITE_OUI_TYPE_TKIP;
+ }
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = WPA_CIPHER_SUITE_OUI_TYPE_CCMP;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP40:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = WPA_CIPHER_SUITE_OUI_TYPE_WEP40;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP104:
+ {
+ PlatformMoveMemory(pOUI, WPA_OUI, SIZE_OUI);
+ *pOUIType = WPA_CIPHER_SUITE_OUI_TYPE_WEP104;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP:
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Invalid Cipher suite RT_ENC_ALG_WEP to map OUI\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ }
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ { // WAPI does NOT have the cipher suite OUI/Type
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Invalid Cipher suite RT_ENC_ALG_SMS4 to map OUI\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ }
+ break;
+ }
+ }
+ else if(RT_SEC_LVL_WPA2 == secLevl)
+ {
+ switch(cipherSuite)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case RT_ENC_ALG_NO_CIPHER:
+ {
+ PlatformZeroMemory(pOUI, SIZE_OUI);
+ PlatformZeroMemory(pOUIType, SIZE_OUI_TYPE);
+ }
+ break;
+
+ case RT_ENC_ALG_USE_GROUP:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_USE_GROUP_CIPHER;
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_TKIP;
+ }
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_CCMP;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP40:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_WEP40;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP104:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_WEP104;
+ }
+ break;
+
+ case RT_ENC_ALG_WEP:
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Invalid Cipher suite RT_ENC_ALG_WEP to map OUI\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ }
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ { // WAPI does NOT have the cipher suite OUI/Type
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Invalid Cipher suite RT_ENC_ALG_SMS4 to map OUI\n"));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ }
+ break;
+
+ case RT_ENC_ALG_BIP:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_BIP;
+ }
+ break;
+
+ case RT_ENC_ALG_GROUP_ADDR_TRAFFIC_DISALLOWED:
+ {
+ PlatformMoveMemory(pOUI, RSN_OUI, SIZE_OUI);
+ *pOUIType = RSN_CIPHER_SUITE_OUI_TYPE_GRP_ADDR_DISALLOWED;
+ }
+ break;
+ }
+ }
+ else
+ {
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ }
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Get the cipher suite in RT_ENC_ALG from OUI and OUI type.
+// Arguments:
+// [out] pOUI -
+// The OUI with 3 bytes.
+// If the input is all 0 in pOUI, return RT_ENC_ALG_NO_CIPHER.
+// [out] pOUIType -
+// The OUI type with 1 byte.
+// If the input is all 0 in pOUIType, return RT_ENC_ALG_NO_CIPHER.
+// [in] secLevl -
+// Input the security level related to OUI and OUIType
+// [in] pCipherSuite -
+// Return The tcipher suite.
+// Return:
+// RT_STATUS_SUCCESS, if the translation succeeds.
+// RT_STATUS_NOT_RECOGNIZED, if the pOUI/pOUIType is not recognized.
+// RT_STATUS_INVALID_DATA, if any of pOUI, pOUIType, or secLevl is invalid.
+//
+RT_STATUS
+Sec_MapOUITypeToCipherSuite(
+ IN pu1Byte pOUI,
+ IN pu1Byte pOUIType,
+ IN RT_SECURITY_LEVEL secLevl,
+ OUT PRT_ENC_ALG pCipherSuite
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ CHECK_NULL_RETURN_STATUS(pOUI);
+ CHECK_NULL_RETURN_STATUS(pOUIType);
+ CHECK_NULL_RETURN_STATUS(pCipherSuite);
+
+ if(RT_SEC_LVL_NONE == secLevl)
+ {
+ *pCipherSuite = RT_ENC_ALG_NO_CIPHER;
+ }
+ else if(RT_SEC_LVL_WPA == secLevl)
+ {
+ if(eqOUI(pOUI, WPA_OUI))
+ {
+ switch(*pOUIType)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case WPA_CIPHER_SUITE_OUI_TYPE_NONE:
+ *pCipherSuite = RT_ENC_ALG_NO_CIPHER;;
+ break;
+
+ case WPA_CIPHER_SUITE_OUI_TYPE_WEP40:
+ *pCipherSuite = RT_ENC_ALG_WEP40;;
+ break;
+
+ case WPA_CIPHER_SUITE_OUI_TYPE_TKIP:
+ *pCipherSuite = RT_ENC_ALG_TKIP;;
+ break;
+
+ case WPA_CIPHER_SUITE_OUI_TYPE_CCMP:
+ *pCipherSuite = RT_ENC_ALG_AESCCMP;;
+ break;
+
+ case WPA_CIPHER_SUITE_OUI_TYPE_WEP104:
+ *pCipherSuite = RT_ENC_ALG_WEP104;;
+ break;
+ }
+ }
+ else
+ {
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ }
+ }
+ else if(RT_SEC_LVL_WPA2 == secLevl)
+ {
+ if(eqOUI(pOUI, RSN_OUI))
+ {
+ switch(*pOUIType)
+ {
+ default:
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_USE_GROUP_CIPHER:
+ *pCipherSuite = RT_ENC_ALG_USE_GROUP;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_WEP40:
+ *pCipherSuite = RT_ENC_ALG_WEP40;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_TKIP:
+ *pCipherSuite = RT_ENC_ALG_TKIP;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_CCMP:
+ *pCipherSuite = RT_ENC_ALG_AESCCMP;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_WEP104:
+ *pCipherSuite = RT_ENC_ALG_WEP104;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_BIP:
+ *pCipherSuite = RT_ENC_ALG_BIP;;
+ break;
+
+ case RSN_CIPHER_SUITE_OUI_TYPE_GRP_ADDR_DISALLOWED:
+ *pCipherSuite = RT_ENC_ALG_GROUP_ADDR_TRAFFIC_DISALLOWED;;
+ break;
+ }
+ }
+ else
+ {
+ rtStatus = RT_STATUS_NOT_RECOGNIZED;
+ }
+ }
+
+ return RT_STATUS_NOT_SUPPORT;
+}
+
+//
+// Description:
+// Get the old (deprecated) cipher suite from current RT_ENC_ALGs.
+// This function is used to translate the old definition such as FW.
+// Arguments:
+// [IN] newCipherSuite -
+// The new cipher suite defined in RT_ENC_ALG.
+// Return:
+// The cipher suite defined in RT_ENC_ALG_DEP.
+//
+RT_ENC_ALG_DEP
+Sec_MapNewCipherToDepCipherAlg(
+ IN RT_ENC_ALG newCipherSuite
+ )
+{
+ RT_ENC_ALG_DEP depCipher = NO_Encryption;
+ switch(newCipherSuite)
+ {
+ default:
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Unknown newCipherSuite(0x%08X) to map\n", newCipherSuite));
+ }
+ break;
+
+ case RT_ENC_ALG_NO_CIPHER:
+ depCipher = NO_Encryption;
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ depCipher = TKIP_Encryption;
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ depCipher = AESCCMP_Encryption;
+ break;
+
+ case RT_ENC_ALG_WEP40:
+ depCipher = WEP40_Encryption;
+ break;
+
+ case RT_ENC_ALG_WEP104:
+ depCipher = WEP104_Encryption;
+ break;
+
+ case RT_ENC_ALG_WEP:
+ depCipher = WEP_Encryption;
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ depCipher = SMS4_Encryption;
+ break;
+ }
+
+ return depCipher;
+}
+
+
+RT_ENC_ALG
+SecGetEncryptionOverhead(
+ PADAPTER Adapter,
+ UNALIGNED pu2Byte pMPDUHead,
+ UNALIGNED pu2Byte pMPDUTail,
+ UNALIGNED pu2Byte pMSDUHead,
+ UNALIGNED pu2Byte pMSDUTail,
+ BOOLEAN bByPacket,
+ BOOLEAN bIsBroadcastPkt
+ )
+{
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ RT_ENC_ALG ulSwitchCondition = (bByPacket&&bIsBroadcastPkt)? \
+ pMgntInfo->SecurityInfo.GroupEncAlgorithm:pMgntInfo->SecurityInfo.PairwiseEncAlgorithm;
+
+ // Decide EncryptionOverhead according to Encryption algorithm
+ switch( ulSwitchCondition )
+ {
+ case RT_ENC_ALG_NO_CIPHER:
+ if(pMPDUHead){ *pMPDUHead=0; }
+ if(pMPDUTail){ *pMPDUTail=0; }
+ if(pMSDUHead){ *pMSDUHead=0; }
+ if(pMSDUTail){ *pMSDUTail=0; }
+ break;
+
+ case RT_ENC_ALG_WEP40:
+ case RT_ENC_ALG_WEP104:
+ // CKIP should also go into this case.
+ if(pMPDUHead){ *pMPDUHead=4; }
+ if(pMPDUTail){ *pMPDUTail=4; }
+ if(pMSDUHead){ *pMSDUHead=0; }
+ if(pMSDUTail){ *pMSDUTail=0; }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ if(pMPDUHead){ *pMPDUHead=8; }
+ if(pMPDUTail){ *pMPDUTail=4; }
+ if(pMSDUHead){ *pMSDUHead=0; }
+ if(pMSDUTail){ *pMSDUTail=8; }
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ if(pMPDUHead){ *pMPDUHead=8; }
+ if(pMPDUTail){ *pMPDUTail=8; }
+ if(pMSDUHead){ *pMSDUHead=0; }
+ if(pMSDUTail){ *pMSDUTail=0; }
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ if(pMPDUHead){ *pMPDUHead=18; }
+ if(pMPDUTail){ *pMPDUTail=16; }
+ if(pMSDUHead){ *pMSDUHead=0; }
+ if(pMSDUTail){ *pMSDUTail=0; }
+ break;
+
+ default:
+ break;
+ }
+
+ return ulSwitchCondition;
+
+}
+
+VOID
+SecGetGroupCipherFromBeacon(
+ PADAPTER Adapter,
+ PRT_WLAN_BSS pbssDesc)
+{
+ PRT_SECURITY_T pSecInfo = &(Adapter->MgntInfo.SecurityInfo);
+
+ pSecInfo->GroupEncAlgorithm = pbssDesc->GroupCipherSuite;
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecGetGroupCipherFromBeacon(): GroupEncAlgorithm = %d\n", pSecInfo->GroupEncAlgorithm) );
+
+ SecConstructRSNIE(Adapter);
+}
+
+VOID
+SecConstructRSNIE(
+ PADAPTER Adapter
+ )
+{
+//kcwu: NOTICE===>
+//The frame format of WPA/WPA2 are different
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &Adapter->MgntInfo.SecurityInfo;
+ BOOLEAN bCCX8021xenable = FALSE;
+ BOOLEAN bAPSuportCCKM = FALSE;
+ pu1Byte pIeHead = Adapter->MgntInfo.SecurityInfo.RSNIEBuf;
+ u2Byte IeLen = 0;
+ u1Byte tmpOUI[SIZE_OUI] = {0};
+ u1Byte tmpOUIType = 0;
+ u2Byte AddSize;
+ AKM_SUITE_TYPE selAKM = AKM_SUITE_NONE;
+
+ Adapter->MgntInfo.SecurityInfo.RSNIE.Length = 0;
+
+ // Select the AKM
+ Sec_SelAkmFromAuthMode(
+ Adapter,
+ pSecInfo->AuthMode,
+ CONTENT_PKT_TYPE_AP,
+ NULL,
+ 0,
+ &selAKM);
+
+ if(pSecInfo->SecLvl == RT_SEC_LVL_WPA)
+ {
+ // WPA OUI and Type
+ SET_WPA_IE_OUI_AND_TYPE(pIeHead);
+ IeLen += 4;
+
+ // WPA Version
+ SET_WPA_IE_VERSION(pIeHead, WPA_VER1);
+ IeLen += 2;
+
+ //
+ // 2. Group Cipher Suite.
+ //
+ Sec_MapCipherSuiteToOUIType(pSecInfo->GroupEncAlgorithm, RT_SEC_LVL_WPA, tmpOUI, &tmpOUIType);
+ SET_WPA_IE_GROUP_CIPHER_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+ // Pairwise cipher suite OUI/Type
+ Sec_MapCipherSuiteToOUIType(pSecInfo->PairwiseEncAlgorithm, RT_SEC_LVL_WPA, tmpOUI, &tmpOUIType);
+
+ // Initialize Pairwise Suite count
+ SET_WPA_IE_PAIRWISE_CIPHER_SUITE_CNT(pIeHead, 0);
+ IeLen += 2;
+
+ // Pairwise cipher suite. We may add more pairwise cipher suites here for AP mode.
+ ADD_WPA_IE_PAIRWISE_CIPHER_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+ // Intialize AKM suite count
+ SET_WPA_IE_AKM_SUITE_CNT(pIeHead, 0);
+ IeLen += 2;
+
+ // AKM suite list
+ Sec_MapAKMSuiteToOUIType(selAKM, tmpOUI, &tmpOUIType);
+ ADD_WPA_IE_AKM_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+ // Capabilities
+ SET_WPA_IE_CAP_PTKSA_REPLAY_COUNTER(pIeHead, 0);
+ SET_WPA_IE_CAP_GTKSA_REPLAY_COUNTER(pIeHead, 0);
+ IeLen += 2;
+ }
+ else
+ { // Default: WPA2. Changed from WPA by Annie, 2006-04-26.
+ SET_RSN_IE_VERSION(pIeHead, RSN_VER1);
+ IeLen += 2;
+
+ // Group cipher suite OUI/Type
+ Sec_MapCipherSuiteToOUIType(pSecInfo->GroupEncAlgorithm, RT_SEC_LVL_WPA2, tmpOUI, &tmpOUIType);
+ SET_RSN_IE_GROUP_CIPHER_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+ // Pairwise cipher suite OUI/Type
+ Sec_MapCipherSuiteToOUIType(pSecInfo->PairwiseEncAlgorithm, RT_SEC_LVL_WPA2, tmpOUI, &tmpOUIType);
+
+ // RT_TRACE_F(COMP_SEC, DBG_LOUD, ("PairwiseEncAlgorithm = 0x%08X, OUI = %02X-%02X-%02X-%02X\n", pSecInfo->PairwiseEncAlgorithm, tmpOUI[0], tmpOUI[1], tmpOUI[2], tmpOUIType));
+
+ // Intialize pairwise count
+ SET_RSN_IE_PAIRWISE_CIPHER_SUITE_CNT(pIeHead, 0);
+ IeLen += 2;
+
+ // We may add more pairwise cipher suites here for AP mode.
+ ADD_RSN_IE_PAIRWISE_CIPHER_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+ // Intialize AKM suite count
+ SET_RSN_IE_AKM_SUITE_CNT(pIeHead, 0);
+ IeLen += 2;
+
+ Sec_MapAKMSuiteToOUIType(selAKM, tmpOUI, &tmpOUIType);
+ ADD_RSN_IE_AKM_SUITE_OUI_W_TYPE(pIeHead, tmpOUI, tmpOUIType);
+ IeLen += 4;
+
+
+ //
+ //3 // RSN Capabilities.
+ //
+
+ // (1) Pre-Authentication (bit0)
+ // WPA: Reserver.
+ // WPA2: "A non-AP STA sets the Pre-authentication subfield to zero", in 802.11iD10.0, 7.3.2.25.3 RSN Capabilities, page34. Added by Annie, 2006-05-08.
+ SET_RSN_IE_CAP_PREAUTH(pIeHead, 0);
+
+ // (2) PairwiseAsDefaultKey (bit1)
+ //No Pairwise = false
+ SET_RSN_IE_CAP_NO_PAIRWISE(pIeHead, 0);
+
+ //Replay Counter
+ //kcwu?: Should we implement multiple replay counters?
+ // (3) NumOfPTKSAReplayCounter (bit2,3)
+ SET_RSN_IE_CAP_PTKSA_REPLAY_COUNTER(pIeHead, 0);
+ // (4) NumOfGTKSAReplayCounter (bit4,5)
+ SET_RSN_IE_CAP_GTKSA_REPLAY_COUNTER(pIeHead, 0);
+
+ IeLen += 2;
+ }
+
+ Adapter->MgntInfo.SecurityInfo.RSNIE.Length = IeLen;
+
+ RT_PRINT_DATA( COMP_SEC, DBG_LOUD, ("SecConstructRSNIE(): RSNIE:\n"), pSecInfo->RSNIE.Octet, pSecInfo->RSNIE.Length);
+}
+
+//
+// Description:
+// Append security IEs to this authentication packet.
+// Arguments:
+// [in] pAdapter -
+// The location of target adapter.
+// [in] contentType -
+// The type of content to append this WPA IE. This field also indicates which type of posOutContent.
+// CONTENT_PKT_TYPE_xxx -
+// [in] pInfoBuf -
+// This field is determined by contentType and shall be casted to the corresponding type.
+// pInfoBuf is PRT_WLAN_BSS if contentType is CONTENT_PKT_TYPE_CLIENT.
+// [in] InfoBufLen -
+// Length in byte of pInfoBuf.
+// [in] maxBufLen -
+// The max length of posOutContent buffer in byte.
+// [out] posOutContent -
+// The OCTECT_STRING structure for the content buffer and length.
+// posOutContent is a 802.11 packet if contentType is CONTENT_PKT_TYPE_802_11.
+// Return:
+// RT_STATUS_SUCCESS, if the content is appended withour error.
+// RT_STATUS_BUFFER_TOO_SHORT, if the max length of buffer is not long enough.
+// RT_STATUS_INVALID_STATE, if the security parameter is mismatched.
+// Remark:
+// To determine the RSN content to append to the output content, the pTargetBss, contentType, and posOutContent
+// shall be filled when calling this function. If RSN IE will be appended to an association request frame in posOutContent,
+// the 802.11 packet type and MAC header shall be filled in posOutContent before calling this function.
+// By Bruce, 2015-09-22.
+//
+RT_STATUS
+Sec_AppendWPAIE(
+ IN PADAPTER pAdapter,
+ IN CONTENT_PKT_TYPE contentType,
+ IN PVOID pInfoBuf,
+ IN u4Byte InfoBufLen,
+ IN u4Byte maxBufLen,
+ OUT POCTET_STRING posOutContent
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &pAdapter->MgntInfo.SecurityInfo;
+ u1Byte rsnBuf[MAX_IE_LEN - SIZE_EID_AND_LEN] = {0};
+ OCTET_STRING osRsn;
+ u1Byte pktType = 0xFF;
+ AKM_SUITE_TYPE akmSuite = AKM_SUITE_NONE;
+ u1Byte tmpOUI[SIZE_OUI] = {0};
+ u1Byte tmpOUIType = 0;
+ PRT_WLAN_BSS pBssDesc = NULL;
+ AKM_SUITE_TYPE selAKM = AKM_SUITE_NONE;
+
+ FillOctetString(osRsn, rsnBuf, 0);
+
+ do
+ {
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT | CONTENT_PKT_TYPE_AP | CONTENT_PKT_TYPE_IBSS))
+ {
+ if(RT_SEC_LVL_WPA != pSecInfo->SecLvl)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("SecLvl (%d) != RT_SEC_LVL_WPA\n", pSecInfo->SecLvl));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_802_11))
+ {
+ pktType = PacketGetType(*posOutContent);
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ if(NULL == pInfoBuf || InfoBufLen < sizeof(RT_WLAN_BSS))
+ {
+ // Prefast warning C6328: Size mismatch ignore
+#pragma warning (disable: 6328)
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("pInfoBuf (%p) = NULL or InfoBufLen < required of sizeof(RT_WLAN_BSS) = %d\n", pInfoBuf, sizeof(RT_WLAN_BSS)));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+ pBssDesc = (PRT_WLAN_BSS)pInfoBuf;
+
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_SelAkmFromAuthMode(
+ pAdapter,
+ pSecInfo->AuthMode,
+ CONTENT_PKT_TYPE_CLIENT,
+ pBssDesc,
+ sizeof(RT_WLAN_BSS),
+ &selAKM)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Failed (0x%08X) from Sec_SelAkmFromAuthMode(), pSecInfo->AuthMode = %d, pBssDesc->AKMsuit = 0x%08X\n",
+ rtStatus, pSecInfo->AuthMode, pBssDesc->AKMsuit));
+ break;
+
+ }
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("selAKM = 0x%08X\n", selAKM));
+
+ // Do not append RSN IE in default.
+ rtStatus = RT_STATUS_INVALID_DATA;
+ switch(pktType)
+ {
+ default:
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+
+ case Type_Asoc_Req:
+ case Type_Reasoc_Req:
+ rtStatus = RT_STATUS_SUCCESS;
+ break;
+ }
+
+ if(RT_STATUS_SUCCESS != rtStatus)
+ {
+ // No need to append RSN IE
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("pktType = 0x%02X, no need to append RSN IE\n", pktType));
+ break;
+ }
+ }
+
+ // OUI + type
+ SET_WPA_IE_OUI_AND_TYPE(osRsn.Octet);
+ osRsn.Length += 4;
+
+ // WPA version
+ SET_WPA_IE_VERSION(osRsn.Octet, WPA_VER1);
+ osRsn.Length += 2;
+
+ // Group cipher suite
+ if(RT_STATUS_SUCCESS != (
+ rtStatus = Sec_MapCipherSuiteToOUIType(pSecInfo->GroupEncAlgorithm, RT_SEC_LVL_WPA, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Fail (0x%08X) to get OUI/Type from group EncAlg(0x%08X)\n", rtStatus, pSecInfo->GroupEncAlgorithm));
+ break;
+ }
+ SET_WPA_IE_GROUP_CIPHER_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+
+ // Pairwise cipher suite OUI/Type
+ if(RT_STATUS_SUCCESS !=
+ (rtStatus = Sec_MapCipherSuiteToOUIType(pSecInfo->PairwiseEncAlgorithm, RT_SEC_LVL_WPA, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Fail (0x%08X) to get OUI/Type from pairwise EncAlg(0x%08X)\n", rtStatus, pSecInfo->PairwiseEncAlgorithm));
+ break;
+
+ }
+
+ // Initialize Pairwise Suite count
+ SET_WPA_IE_PAIRWISE_CIPHER_SUITE_CNT(osRsn.Octet, 0);
+ osRsn.Length += 2;
+
+ // Pairwise cipher suite. We may add more pairwise cipher suites here for AP mode.
+ ADD_WPA_IE_PAIRWISE_CIPHER_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+
+ // Intialize AKM suite count
+ SET_WPA_IE_AKM_SUITE_CNT(osRsn.Octet, 0);
+ osRsn.Length += 2;
+
+ // AKM suite list
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ if(RT_STATUS_SUCCESS != (rtStatus = Sec_MapAKMSuiteToOUIType(selAKM, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Failed (0x%08X) from Sec_MapAKMSuiteToOUIType() for selAKM = 0x%08X, AuthMode = %d, targetAKMSuite = 0x%08X\n",
+ rtStatus, selAKM, pSecInfo->AuthMode, pMgntInfo->targetAKMSuite));
+ break;
+ }
+ ADD_WPA_IE_AKM_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+ }
+ else
+ {
+ // ToDo
+ rtStatus = RT_STATUS_NOT_SUPPORT;
+ break;
+ }
+
+ // Capabilities
+ SET_WPA_IE_CAP_PTKSA_REPLAY_COUNTER(osRsn.Octet, 0);
+ SET_WPA_IE_CAP_GTKSA_REPLAY_COUNTER(osRsn.Octet, 0);
+ osRsn.Length += 2;
+ }while(FALSE);
+
+ if(RT_STATUS_SUCCESS == rtStatus)
+ {
+ if((maxBufLen - posOutContent->Length) < osRsn.Length)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING,
+ ("maxBufLen (%d) - posOutContent.Length (%d) < osRsn.Length(%d)\n", maxBufLen, posOutContent->Length, osRsn.Length));
+ rtStatus = RT_STATUS_BUFFER_TOO_SHORT;
+ }
+ else
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "Append IE data:\n", osRsn.Octet, osRsn.Length);
+ PacketMakeElement(posOutContent, EID_Vendor, osRsn);
+ }
+ }
+
+ return rtStatus;
+}
+
+//
+// Description:
+// Append RSN IE to this packet or content.
+// Arguments:
+// [in] pAdapter -
+// The location of target adapter.
+// [in] contentType -
+// The type of content to append this RSN IE. This field also indicates which type of posOutContent.
+// CONTENT_PKT_TYPE_xxx -
+// [in] pInfoBuf -
+// This field is determined by contentType and shall be casted to the corresponding type.
+// pInfoBuf is PRT_WLAN_BSS if contentType is CONTENT_PKT_TYPE_CLIENT.
+// [in] InfoBufLen -
+// Length in byte of pInfoBuf.
+// [in] maxBufLen -
+// The max length of posOutContent buffer in byte.
+// [out] posOutContent -
+// The OCTECT_STRING structure for the content buffer and length.
+// posOutContent is a 802.11 packet if contentType is CONTENT_PKT_TYPE_802_11.
+// Return:
+// RT_STATUS_SUCCESS, if the content is appended withour error.
+// RT_STATUS_BUFFER_TOO_SHORT, if the max length of buffer is not long enough.
+// RT_STATUS_INVALID_STATE, if the security parameter is mismatched.
+// Remark:
+// To determine the RSN content to append to the output content, the pTargetBss, contentType, and posOutContent
+// shall be filled when calling this function. If RSN IE will be appended to an association request frame in posOutContent,
+// the 802.11 packet type and MAC header shall be filled in posOutContent before calling this function.
+// By Bruce, 2015-09-22.
+//
+RT_STATUS
+Sec_AppendRSNIE(
+ IN PADAPTER pAdapter,
+ IN CONTENT_PKT_TYPE contentType,
+ IN PVOID pInfoBuf,
+ IN u4Byte InfoBufLen,
+ IN u4Byte maxBufLen,
+ OUT POCTET_STRING posOutContent
+ )
+{
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &pAdapter->MgntInfo.SecurityInfo;
+ u1Byte rsnBuf[MAX_IE_LEN - SIZE_EID_AND_LEN] = {0};
+ OCTET_STRING osRsn;
+ u1Byte pktType = 0xFF;
+ AKM_SUITE_TYPE akmSuite = AKM_SUITE_NONE;
+ u1Byte tmpOUI[SIZE_OUI] = {0};
+ u1Byte tmpOUIType = 0;
+ PRT_WLAN_BSS pBssDesc = NULL;
+ AKM_SUITE_TYPE selAKM = AKM_SUITE_NONE;
+ PFT_INFO_ENTRY pFtEntry = NULL;
+
+ CHECK_NULL_RETURN_STATUS(posOutContent);
+
+ FillOctetString(osRsn, rsnBuf, 0);
+
+ do
+ {
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT | CONTENT_PKT_TYPE_AP | CONTENT_PKT_TYPE_IBSS))
+ {
+ if(RT_SEC_LVL_WPA2 != pSecInfo->SecLvl)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("SecLvl (%d) != RT_SEC_LVL_WPA2\n", pSecInfo->SecLvl));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_802_11))
+ {
+ pktType = PacketGetType(*posOutContent);
+ }
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ BOOLEAN bFtIeFromEntry = FALSE;
+ if(NULL == pInfoBuf || InfoBufLen < sizeof(RT_WLAN_BSS))
+ {
+ // Prefast warning C6328: Size mismatch ignore
+#pragma warning (disable: 6328)
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("pInfoBuf (%p) = NULL or InfoBufLen < required of sizeof(RT_WLAN_BSS) = %d\n", pInfoBuf, sizeof(RT_WLAN_BSS)));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+ pBssDesc = (PRT_WLAN_BSS)pInfoBuf;
+
+ if(RT_STATUS_SUCCESS != (rtStatus =
+ Sec_SelAkmFromAuthMode(
+ pAdapter,
+ pSecInfo->AuthMode,
+ CONTENT_PKT_TYPE_CLIENT,
+ pBssDesc,
+ sizeof(RT_WLAN_BSS),
+ &selAKM)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Failed (0x%08X) from Sec_SelAkmFromAuthMode(), pSecInfo->AuthMode = %d, pBssDesc->AKMsuit = 0x%08X\n",
+ rtStatus, pSecInfo->AuthMode, pBssDesc->AKMsuit));
+ break;
+
+ }
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("selAKM = 0x%08X\n", selAKM));
+
+ // Check if the entry has PMKID
+ if(AKM_FT_1X == selAKM || AKM_FT_PSK == selAKM)
+ {
+ pFtEntry = FtGetEntry(pAdapter, pBssDesc->bdBssIdBuf);
+ }
+
+ // Do not append RSN IE in default.
+ rtStatus = RT_STATUS_INVALID_DATA;
+ switch(pktType)
+ {
+ default:
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+
+ case Type_Auth:
+ {
+ if(FtIsFtAuthReady(pAdapter, pBssDesc->bdBssIdBuf))
+ {
+ rtStatus = RT_STATUS_SUCCESS;
+ }
+ }
+ break;
+
+ case Type_Asoc_Req:
+ case Type_Reasoc_Req:
+ {
+ if(FtIsFtAssocReqReady(pAdapter, pBssDesc->bdBssIdBuf))
+ {
+ // Prefast warning C6011: Dereferencing NULL pointer 'pFtEntry'.
+ if(pFtEntry != NULL && pFtEntry->RSNELen > SIZE_EID_AND_LEN)
+ {
+ FillOctetString(osRsn, pFtEntry->RSNE + SIZE_EID_AND_LEN, (pFtEntry->RSNELen - SIZE_EID_AND_LEN));
+ bFtIeFromEntry = TRUE;
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("RSN IE content from FT entry\n"));
+ }
+
+ }
+ rtStatus = RT_STATUS_SUCCESS;
+ }
+ break;
+ }
+
+ if(RT_STATUS_SUCCESS != rtStatus)
+ {
+ // No need to append RSN IE
+ RT_TRACE_F(COMP_SEC, DBG_TRACE, ("pktType = 0x%02X, no need to append RSN IE\n", pktType));
+ break;
+ }
+
+ // The content has been filled.
+ if(bFtIeFromEntry)
+ break;
+ }
+
+ SET_RSN_IE_VERSION(osRsn.Octet, RSN_VER1);
+ osRsn.Length += 2;
+
+ // Group cipher suite OUI/Type
+ if(RT_STATUS_SUCCESS !=
+ (rtStatus = Sec_MapCipherSuiteToOUIType(pSecInfo->GroupEncAlgorithm, RT_SEC_LVL_WPA2, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Fail (0x%08X) to get OUI/Type from group EncAlg(0x%08X)\n", rtStatus, pSecInfo->GroupEncAlgorithm));
+ break;
+
+ }
+ SET_RSN_IE_GROUP_CIPHER_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+
+ // Pairwise cipher suite OUI/Type
+ if(RT_STATUS_SUCCESS !=
+ (rtStatus = Sec_MapCipherSuiteToOUIType(pSecInfo->PairwiseEncAlgorithm, RT_SEC_LVL_WPA2, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Fail (0x%08X) to get OUI/Type from pairwise EncAlg(0x%08X)\n", rtStatus, pSecInfo->PairwiseEncAlgorithm));
+ break;
+
+ }
+
+ // RT_TRACE_F(COMP_SEC, DBG_LOUD, ("PairwiseEncAlgorithm = 0x%08X, OUI = %02X-%02X-%02X-%02X\n", pSecInfo->PairwiseEncAlgorithm, tmpOUI[0], tmpOUI[1], tmpOUI[2], tmpOUIType));
+
+ // Intialize pairwise count
+ SET_RSN_IE_PAIRWISE_CIPHER_SUITE_CNT(osRsn.Octet, 0);
+ osRsn.Length += 2;
+
+ // We may add more pairwise cipher suites here for AP mode.
+ ADD_RSN_IE_PAIRWISE_CIPHER_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+
+ // Intialize AKM suite count
+ SET_RSN_IE_AKM_SUITE_CNT(osRsn.Octet, 0);
+ osRsn.Length += 2;
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ if(RT_STATUS_SUCCESS != (rtStatus = Sec_MapAKMSuiteToOUIType(selAKM, tmpOUI, &tmpOUIType)))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("Failed (0x%08X) from Sec_MapAKMSuiteToOUIType() for selAKM = 0x%08X, AuthMode = %d, targetAKMSuite = 0x%08X\n",
+ rtStatus, selAKM, pSecInfo->AuthMode, pMgntInfo->targetAKMSuite));
+ break;
+ }
+ ADD_RSN_IE_AKM_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+ }
+ else
+ {
+ // ToDo
+ rtStatus = RT_STATUS_NOT_SUPPORT;
+ break;
+ }
+
+
+ //
+ //3 // RSN Capabilities.
+ //
+
+ // (1) Pre-Authentication (bit0)
+ // WPA: Reserver.
+ // WPA2: "A non-AP STA sets the Pre-authentication subfield to zero", in 802.11iD10.0, 7.3.2.25.3 RSN Capabilities, page34. Added by Annie, 2006-05-08.
+ SET_RSN_IE_CAP_PREAUTH(osRsn.Octet, 0);
+
+ // (2) PairwiseAsDefaultKey (bit1)
+ //No Pairwise = false
+ SET_RSN_IE_CAP_NO_PAIRWISE(osRsn.Octet, 0);
+
+ //Replay Counter
+ //kcwu?: Should we implement multiple replay counters?
+ // (3) NumOfPTKSAReplayCounter (bit2,3)
+ SET_RSN_IE_CAP_PTKSA_REPLAY_COUNTER(osRsn.Octet, 0);
+ // (4) NumOfGTKSAReplayCounter (bit4,5)
+ SET_RSN_IE_CAP_GTKSA_REPLAY_COUNTER(osRsn.Octet, 0);
+
+ osRsn.Length += 2;
+
+ if(TEST_FLAG(contentType, CONTENT_PKT_TYPE_CLIENT))
+ {
+ pu1Byte pPmkIdBuf = NULL;
+ int pmkIdx = -1;
+ BOOLEAN bGroupMgntCipher = FALSE;
+
+ // Append PMKID
+ if(pFtEntry)
+ { // FT PMKID
+ if(pFtEntry->PMKR0NameLen > 0)
+ {
+ pPmkIdBuf = pFtEntry->PMKR0Name;
+ }
+ }
+ else if((pmkIdx = SecIsInPMKIDList(pAdapter, pBssDesc->bdBssIdBuf)) >= 0)
+ {
+ pPmkIdBuf = pSecInfo->PMKIDList[pmkIdx].PMKID;
+ }
+
+ // Group Management Cipher Suite (Protected Management Frame Protocol)
+ if(pBssDesc->bMFPC && pMgntInfo->bInBIPMFPMode)
+ {
+ SET_RSN_IE_CAP_MFP_CAPABLE(osRsn.Octet, 1);
+ if(RT_STATUS_SUCCESS == Sec_MapCipherSuiteToOUIType(RT_ENC_ALG_BIP, RT_SEC_LVL_WPA2, tmpOUI, &tmpOUIType))
+ {
+ bGroupMgntCipher = TRUE;
+ }
+ }
+
+ // Intialize PMKID count if there is any more content to avoid IOT issue
+ if(pPmkIdBuf || bGroupMgntCipher)
+ {
+ SET_RSN_IE_PMKID_CNT(osRsn.Octet, 0);
+ osRsn.Length += 2;
+ }
+
+ if(pPmkIdBuf)
+ {
+ ADD_RSN_IE_PMKID(osRsn.Octet, pPmkIdBuf);
+ osRsn.Length += PMKID_LEN;
+ }
+
+ if(bGroupMgntCipher)
+ {
+ SET_RSN_IE_GROUP_MGNT_CIPHER_SUITE_OUI_W_TYPE(osRsn.Octet, tmpOUI, tmpOUIType);
+ osRsn.Length += 4;
+ }
+ }
+ }while(FALSE);
+
+ if(RT_STATUS_SUCCESS == rtStatus)
+ {
+ if((maxBufLen - posOutContent->Length) < osRsn.Length)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING,
+ ("maxBufLen (%d) - posOutContent.Length (%d) < osRsn.Length(%d)\n", maxBufLen, posOutContent->Length, osRsn.Length));
+ rtStatus = RT_STATUS_BUFFER_TOO_SHORT;
+ }
+ else
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "Append IE data:\n", osRsn.Octet, osRsn.Length);
+ PacketMakeElement(posOutContent, EID_WPA2, osRsn);
+ }
+ }
+
+ return rtStatus;
+}
+
+
+u1Byte
+SecGetTxKeyIdx(
+ PADAPTER Adapter,
+ pu1Byte pMacAddr // Not used now...
+ )
+{
+ //pairwise keyidx in our driver is 0 (in WPA-PSK or WPA2-PSK.)
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ u1Byte keyidx = PAIRWISE_KEYIDX;
+
+ //2004/06/29, kcwu,
+ //check if pairwise key exists
+ if(pSec->KeyLen[keyidx] == 0)
+ {
+ if(Adapter->MgntInfo.mIbss)
+ { // Ad Hoc Mode.
+ return (pSec->KeyLen[pSec->GroupTransmitKeyIdx]==0)?5:pSec->GroupTransmitKeyIdx;
+ }
+ else
+ { // Infrastructure Mode.
+ return 5;
+ }
+ }
+ else
+ {
+ return keyidx;
+ }
+
+}
+
+
+VOID
+SecCalculateMIC(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSec = &(pMgntInfo->SecurityInfo);
+
+ switch(pSec->PairwiseEncAlgorithm)
+ {
+ case RT_ENC_ALG_WEP40:
+ case RT_ENC_ALG_WEP104:
+ if( pSec->pCkipPara->bIsMIC )
+ { // CKIP MIC case.
+ SecCalculateCKIPMIC(Adapter, pTcb);
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ SecCalculateTKIPMIC(Adapter, pTcb);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+//
+// Descriptin:
+// Append TKIP MIC of given tx packet to send.
+//
+// Note:
+// 1. TKIP MIC input: DA(6) + SA(6) + Priority(1) + Zero(3) + Data(n)
+// where Data field shall conform 802.2 LLC and 802.1 bridging.
+// For example, Data is begined with LLC/SNAP.
+//
+// Assumption:
+// 1. The tx packet repsented by RT_TCB here is an 802.11 MPDU
+// translated from an MSDU before doing fragmentation.
+//
+// Revision History:
+// 061028, rcnjko:
+// Generalize the way to retrive MSDU payload.
+//
+VOID
+SecCalculateTKIPMIC(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSec = &(pMgntInfo->SecurityInfo);
+ u4Byte idx = 0;
+ u1Byte keyidx = SecGetTxKeyIdx(Adapter, pTcb->DestinationAddress);
+ MicData micdata;
+ u1Byte Qos[4];
+ PRT_WLAN_STA pEntry = NULL;
+
+ pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress;
+ u4Byte FrameHdrLng = sMacHdrLng + pSec->EncryptionHeadOverhead;
+ u4Byte OffsetToByPass = 0;
+
+
+ //
+ // MIC Key.
+ //
+ if(ACTING_AS_AP(Adapter))
+ {
+ if(MacAddr_isMulticast(pTcb->DestinationAddress))
+ {
+ //Check if set GTK was completed
+ if(pMgntInfo->globalKeyInfo.GTK[0] == 0)
+ return;
+
+ //Set Tx Group Key
+ SecMICSetKey(&micdata, &pMgntInfo->globalKeyInfo.GTK[16]);
+ }
+ else
+ {
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ if(pEntry == NULL)
+ return;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.TxMICKey == NULL)
+ return;
+
+ //Set Tx Pairwise Key by destination Address
+ SecMICSetKey(&micdata, pEntry->perSTAKeyInfo.TxMICKey);
+ }
+ }
+ else if(pTcb->bTDLPacket)
+ {
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ if(pEntry == NULL)
+ return;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.TxMICKey == NULL)
+ return;
+
+ //Set Tx Pairwise Key by destination Address
+ SecMICSetKey(&micdata, pEntry->perSTAKeyInfo.TxMICKey);
+ }
+ else
+ {
+ if(pSec->PairwiseEncAlgorithm != RT_ENC_ALG_TKIP) {
+ RT_TRACE(COMP_SEC, DBG_LOUD, ("PairwiseEncAlg=%d\n", pSec->PairwiseEncAlgorithm) );
+ return;
+ }
+
+ if(pMgntInfo->mAssoc)
+ {
+ SecMICSetKey(&micdata, pSec->KeyBuf[keyidx]+TKIP_MICKEYRX_POS);
+ }
+ else
+ {
+ SecMICSetKey(&micdata, pSec->KeyBuf[keyidx]+TKIP_MICKEYTX_POS);
+ }
+
+ }
+
+ //
+ // DA, SA.
+ //
+ SecMICAppend(&micdata, pTcb->DestinationAddress, ETHERNET_ADDRESS_LENGTH);
+ SecMICAppend(&micdata, pTcb->SourceAddress, ETHERNET_ADDRESS_LENGTH);
+
+ //
+ // Qos
+ //
+ PlatformZeroMemory(Qos, 4);
+
+ if(IsQoSDataFrame(pHeader))
+ Qos[0] = pTcb->priority; // Added by Annie, 2005-12-21.
+
+
+ SecMICAppend(&micdata, Qos, 4);
+
+ if(IsQoSDataFrame(pHeader))
+ FrameHdrLng += sQoSCtlLng;
+
+ //
+ // Data.
+ //
+ OffsetToByPass = FrameHdrLng;
+ for(idx = 0;idx < pTcb->BufferCount; idx++)
+ {
+ if(pTcb->BufferList[idx].Length <= OffsetToByPass)
+ {
+ OffsetToByPass -= pTcb->BufferList[idx].Length;
+ continue;
+ }
+ else
+ {
+ SecMICAppend(
+ &micdata,
+ pTcb->BufferList[idx].VirtualAddress + OffsetToByPass,
+ pTcb->BufferList[idx].Length - OffsetToByPass);
+ }
+ }
+
+ //
+ // Append MIC to tail.
+ //
+ SecMICGetMIC(&micdata, pTcb->Tailer.VirtualAddress);
+ pTcb->Tailer.Length = TKIP_MIC_LEN;
+
+ pTcb->BufferList[pTcb->BufferCount] = pTcb->Tailer;
+ pTcb->BufferCount++;
+ pTcb->PacketLength += TKIP_MIC_LEN;
+
+ //PRINT_DATA("TX_MIC======>", pTcb->Tailer.VirtualAddress, 8);
+}
+
+
+
+//
+// Calculate CKIP MIC.
+// Ported from CKIP code, Annie, 2006-08-11.
+//
+VOID
+SecCalculateCKIPMIC(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ u1Byte keyidx = pSec->DefaultTransmitKeyIdx;
+ u4Byte idx = 0;
+ pu1Byte pucMIC;
+// u1Byte MICdata[2000] = {0};
+ pu1Byte MICdata;
+ int datalen = 0;
+ PRT_GEN_TEMP_BUFFER pGenBufMICdata;
+
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("==> SecCalculateCKIPMIC()\n") );
+
+ if( !pSec->pCkipPara->bIsMIC) // if not support MIC retun , added by CCW
+ return;
+
+ pGenBufMICdata = GetGenTempBuffer (Adapter, 2000);
+ MICdata = (pu1Byte)pGenBufMICdata->Buffer.Ptr;
+
+ //ckip_miccalc(Adapter, key, pDA, pSA, dcr, dcrlen, calcmic, mickeyid);
+ // key = wep key , dcr = payload ( | LLC | SNAP |MIC |SEQ |eth-payload |)
+ for(idx=1;idx<pTcb->BufferCount;idx++){ // Only check first nonzero buffer
+ if(pTcb->BufferList[idx].Length==0)
+ continue;
+
+ PlatformMoveMemory(
+ MICdata + datalen,
+ pTcb->BufferList[idx].VirtualAddress,
+ pTcb->BufferList[idx].Length );
+
+ datalen += pTcb->BufferList[idx].Length;
+ }
+
+ pucMIC = pTcb->BufferList[1].VirtualAddress + 8 ; // Set MIC file point
+
+
+ ckip_miccalc( Adapter , pSec->pCkipPara->CKIPKeyBuf[keyidx] , pTcb->DestinationAddress ,pTcb->SourceAddress
+ , MICdata ,datalen , pucMIC , keyidx );
+
+ ReturnGenTempBuffer (Adapter, pGenBufMICdata);
+
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("<== SecCalculateCKIPMIC()\n") );
+}
+
+VOID
+SecSoftwareEncryption(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ RT_ENC_ALG SelectEncAlgorithm;
+ PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
+
+ if(pMgntInfo->SafeModeEnabled)
+ {
+ RT_TRACE_F(COMP_SEND, DBG_LOUD, ("Do not use software encrypt when safemode enable\n"));
+ return;
+ }
+
+ if( pTcb->bBTTxPacket )
+ {
+ if(pTcb->EncInfo.IsEncByHW)
+ {
+ RT_TRACE( COMP_SEC , DBG_LOUD , (" ===> BT used HW encrypt !!No enter Sw encrypt !!\n") );
+ return;
+ }
+ else
+ SelectEncAlgorithm = RT_ENC_ALG_AESCCMP;
+ }
+ else
+ SelectEncAlgorithm = Adapter->MgntInfo.SecurityInfo.PairwiseEncAlgorithm;
+
+ switch(SelectEncAlgorithm)
+ {
+ case RT_ENC_ALG_WEP40:
+ case RT_ENC_ALG_WEP104:
+ if( !Adapter->MgntInfo.SecurityInfo.pCkipPara->bIsKP )
+ { // WEP case.
+ SecSWWEPEncryption(Adapter, pTcb);
+ }
+ else
+ { // CKIP case.
+ SecSWCKIPEncryption(Adapter, pTcb);
+ }
+ break;
+ case RT_ENC_ALG_TKIP:
+ SecSWTKIPEncryption(Adapter, pTcb);
+ break;
+ case RT_ENC_ALG_AESCCMP:
+ SecSWAESEncryption(Adapter, pTcb);
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ WAPI_SecFuncHandler(WAPI_SECSWSMS4ENCRYPTION, Adapter, (PVOID)pTcb, WAPI_END);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+// From kcwu 2004/09/24.
+VOID
+SecSWTKIPEncryption(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ u4Byte FragIndex = 0;
+ u4Byte BufferIndex = 0;
+ u2Byte FragBufferCount = 0;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ //u1Byte SecBuffer[2000];
+ u4Byte SpecificHeadOverhead = 0;
+ u4Byte SecBufLen = 0;
+ u4Byte SecBytesCopied = 0;
+ u4Byte SecBufIndex = 0;
+ u4Byte FragBufferIndexStart = 0;
+ pu1Byte SecPtr = 0;
+ u4Byte SecLenForCopy = 0;
+ pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress;
+ u1Byte key[16];
+ u2Byte u2IV16;
+ u4Byte u4IV32;
+ PMGNT_INFO pMgntInfo=&Adapter->MgntInfo;
+ PRT_WLAN_STA pEntry = NULL;// = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte DataOffset; // Added by Annie, 2005-12-23.
+
+ SpecificHeadOverhead = Adapter->TXPacketShiftBytes;
+
+ pHeader += SpecificHeadOverhead;
+
+
+ // AP mode: get key.
+ if(ACTING_AS_AP(Adapter))
+ { // AP mode.
+ if(MacAddr_isMulticast(pTcb->DestinationAddress))
+ {
+ // [AnnieNote] Current GTK is 12345678...12345678, so it's OK.
+ // It's better to modify it by GTK length if we use PRF-X to generate GTK later. 2005-12-23.
+ //
+
+ //Check if set GTK was completed
+ if(Adapter->MgntInfo.globalKeyInfo.GTK[0] == 0)
+ return;
+ }
+ else
+ {
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ if(pEntry == NULL)
+ return;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.TempEncKey == NULL)
+ return;
+ }
+ }
+
+
+ // Get offset. Annie, 2005-12-23.
+ if( IsQoSDataFrame(pHeader) )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ DataOffset = IVOffset + EXT_IV_LEN;
+
+
+ // Get u2IV16 and u4IV32.
+ u2IV16 = ((u2Byte)(*(pHeader+IVOffset + 0)) << 8) + \
+ ((u2Byte)(*(pHeader+IVOffset + 2)) << 0);
+
+ u4IV32 = ((u4Byte) (*(pHeader+IVOffset + 4)) << 0) + \
+ ((u4Byte) (*(pHeader+IVOffset + 5)) << 8) + \
+ ((u4Byte) (*(pHeader+IVOffset + 6)) << 16) + \
+ ((u4Byte) (*(pHeader+IVOffset + 7)) << 24);
+
+
+ if(ACTING_AS_AP(Adapter))
+ { // AP mode.
+ if(MacAddr_isMulticast(pTcb->DestinationAddress))
+ {
+ TKIPGenerateKey(key, u4IV32, u2IV16, pMgntInfo->Bssid, &Adapter->MgntInfo.globalKeyInfo.GTK[0]);
+ }
+ else
+ {
+ if(pEntry != NULL)
+ TKIPGenerateKey(key, u4IV32, u2IV16, pMgntInfo->Bssid, pEntry->perSTAKeyInfo.TempEncKey);
+ }
+ }
+ else
+ { // STA mode.
+ TKIPGenerateKey(key, u4IV32, u2IV16, pTcb->SourceAddress, pSec->KeyBuf[SecGetTxKeyIdx(Adapter, pTcb->DestinationAddress)]);
+ }
+ //TKIP_TSC_DECIMAL2ARRAY(pSec->SWTKIPu2IV16, pSec->SWTKIPu4IV32, ulKeyIndex, pucIV);
+
+ for(FragIndex = 0; FragIndex < pTcb->FragCount; FragIndex++)
+ {
+ FragBufferIndexStart = BufferIndex;
+ SecBufLen = 0;
+
+ //2004/09/14, kcwu, clear the Security Coalesce Buffer
+ PlatformZeroMemory(pSec->SecBuffer, SW_ENCRYPT_BUF_SIZE);
+
+ //2004/09/14, kcwu, to show how many buffers are there used by this fragment
+ FragBufferCount = pTcb->FragBufCount[FragIndex];
+
+ //2004/09/14, kcwu, data to be encrypted start at the second buffer
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ BufferIndex = FragBufferIndexStart+1;
+ FragBufferCount--; // 2005.11.04, by rcnjko.
+ }
+
+ // Concatenate buffers to be encrypted into the buffer, SecBuffer.
+ // SecBuffer for TKIP does not include 802.11 header and IV.
+ while(FragBufferCount-- > 0)
+ {
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ if(pTcb->BufferList[BufferIndex].Length > (SpecificHeadOverhead+DataOffset))
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress + (SpecificHeadOverhead+DataOffset);
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length - (SpecificHeadOverhead+DataOffset);
+ }
+ }
+ else
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress;
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length;
+ }
+
+ // 20110819 Joseph: Prevent from buffer overflow.
+ if((SecBufLen + SecLenForCopy)>SW_ENCRYPT_BUF_SIZE)
+ {
+ SecLenForCopy = SW_ENCRYPT_BUF_SIZE - SecBufLen;
+ FragBufferCount = 0;
+ RT_TRACE( COMP_SEC, DBG_SERIOUS, ("SecSWTKIPEncryption(): Packet is too large. Truncate!!\n") );
+ }
+
+ PlatformMoveMemory(
+ pSec->SecBuffer + SecBufLen, // 2005.11.04, by rcnjko.
+ SecPtr,
+ SecLenForCopy);
+
+ SecBufLen += SecLenForCopy;
+
+ BufferIndex++;
+ //DbgPrint("FragBufferCount = %d, SecBufLen = %d, BufferIndex = %d\n",
+ // FragBufferCount, SecBufLen, BufferIndex);
+
+ }
+
+ if(SecBufLen <= 0)
+ {
+ continue;
+ }
+ //PRINT_DATA("SecSWWEPEncryption_before_encrypted==>", SecBuffer, SecBufLen);
+
+ EncodeWEP(key,
+ 16,
+ pSec->SecBuffer,
+ SecBufLen,
+ pSec->SecBuffer);
+ //PRINT_DATA("SecSWWEPEncryption_after_encrypted==>", SecBuffer, SecBufLen+4);
+
+ // For WEP ICV.
+ SecBufLen += 4;
+
+ SecBytesCopied = 0;
+
+ // 2005.11.04, by rcnjko.
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ SecBufIndex = FragBufferIndexStart+1;
+ FragBufferCount = 1;
+ }
+ else
+ {
+ SecBufIndex = FragBufferIndexStart;
+ FragBufferCount = 0;
+ }
+ //
+
+ //2004/09/14, then copy SecBuffer back to the buffer
+
+ // 2005.11.04, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress+(SpecificHeadOverhead+DataOffset),
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset)
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset);
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+ //
+
+ while(FragBufferCount < pTcb->FragBufCount[FragIndex]){
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress,
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length;
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+
+ // Copy WEP ICV.
+ // 2005.11.04, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER) || pTcb->FragCount == 1)
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex-1].VirtualAddress+pTcb->BufferList[SecBufIndex-1].Length,
+ pSec->SecBuffer+SecBytesCopied,
+ pSec->EncryptionTailOverhead
+ );
+ pTcb->BufferList[SecBufIndex-1].Length += pSec->EncryptionTailOverhead; //4; //Fix MPE SUT System Hang,120715, by YJ.
+ SecBytesCopied += pSec->EncryptionTailOverhead;
+ pTcb->FragLength[FragIndex] += pSec->EncryptionTailOverhead;
+ pTcb->PacketLength += pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // TODO: non-coalesce and fragmneted case.
+ }
+ }
+}
+
+// From kcwu 2004/09/24.
+VOID
+SecSWWEPEncryption(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ u4Byte FragIndex = 0;
+ u4Byte BufferIndex = 0;
+ u2Byte FragBufferCount = 0;
+ u1Byte key[16];
+ u4Byte wepIV=0;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ //u1Byte SecBuffer[2000]; // 3000 -> 2000 to prevent stack overflow problem in Win98, 2005.03.15, by rcnjko.
+ u4Byte SpecificHeadOverhead = 0;
+ u4Byte SecBufLen = 0;
+ u4Byte SecBytesCopied = 0;
+ u4Byte SecBufIndex = 0;
+ u4Byte FragBufferIndexStart = 0;
+ pu1Byte SecPtr = 0;
+ u4Byte SecLenForCopy = 0;
+ pu1Byte pHeader;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte DataOffset; // Added by Annie, 2005-12-23.
+
+ pHeader = pTcb->BufferList[FragBufferIndexStart].VirtualAddress;
+
+ SpecificHeadOverhead = Adapter->TXPacketShiftBytes;
+
+ pHeader += SpecificHeadOverhead;
+
+
+ // Get offset. Annie, 2005-12-23.
+ if( IsQoSDataFrame(pHeader) )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ DataOffset = IVOffset + WEP_IV_LEN;
+
+
+ //2004/09/14, kcwu, the IV has been calculate, just get from current IV
+ //wepIV.ul = (u4Byte) ((pSec->TxIV == 0)?0x00fffffe:((pSec->TxIV-1)&0x00ffffff));
+ SET_WEP_IV_INITVECTOR(&wepIV, *(UNALIGNED pu4Byte)(pHeader+IVOffset));
+
+ SET_WEP_IV_KEYID(& wepIV, pSec->DefaultTransmitKeyIdx);
+
+
+ //PRINT_DATA("SecSWWEPEncryption==>", (pu1Byte)&wepIV, 4);
+
+ PlatformMoveMemory(key, (pHeader+IVOffset), 3);
+ PlatformMoveMemory(key+3, pSec->KeyBuf[pSec->DefaultTransmitKeyIdx],
+ (pSec->PairwiseEncAlgorithm==RT_ENC_ALG_WEP104)?13:5);
+
+ for(FragIndex = 0; FragIndex < pTcb->FragCount; FragIndex++)
+ {
+ FragBufferIndexStart = BufferIndex;
+ SecBufLen = 0;
+
+ //2004/09/14, kcwu, clear the Security Coalesce Buffer
+ PlatformZeroMemory(pSec->SecBuffer, SW_ENCRYPT_BUF_SIZE); // 3000 -> 2000 to prevent stack overflow problem in Win98, 2005.03.15, by rcnjko.
+
+ //2004/09/14, kcwu, to show how many buffers are there used by this fragment
+ FragBufferCount = pTcb->FragBufCount[FragIndex];
+
+ // For non-coalesce case, data to be encrypted start at the second buffer.
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ BufferIndex = FragBufferIndexStart+1;
+ FragBufferCount--; // 2005.11.07, by rcnjko.
+ }
+
+ // Concatenate buffers to be encrypted into the buffer, SecBuffer.
+ // SecBuffer for WEP does not include 802.11 header and IV.
+ while(FragBufferCount-- > 0)
+ {
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ if(pTcb->BufferList[BufferIndex].Length > (SpecificHeadOverhead+DataOffset))
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress + (SpecificHeadOverhead+DataOffset);
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length - (SpecificHeadOverhead+DataOffset);
+ }
+ }
+ else
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress;
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length;
+ }
+
+ // 20110819 Joseph: Prevent from buffer overflow.
+ if((SecBufLen + SecLenForCopy)>SW_ENCRYPT_BUF_SIZE)
+ {
+ SecLenForCopy = SW_ENCRYPT_BUF_SIZE - SecBufLen;
+ FragBufferCount = 0;
+ RT_TRACE( COMP_SEC, DBG_SERIOUS, ("SecSWWEPEncryption(): Packet is too large. Truncate!!\n") );
+ }
+
+ PlatformMoveMemory(
+ pSec->SecBuffer + SecBufLen, // 2005.11.07, by rcnjko.
+ SecPtr,
+ SecLenForCopy);
+
+ SecBufLen += SecLenForCopy;
+
+ BufferIndex++;
+ //DbgPrint("FragBufferCount = %d, SecBufLen = %d, BufferIndex = %d\n",
+ // FragBufferCount, SecBufLen, BufferIndex);
+ }
+
+ if(SecBufLen <= 0)
+ {
+ continue;
+ }
+
+ //PRINT_DATA("SecSWWEPEncryption_before_encrypted==>", pSec->SecBuffer, SecBufLen);
+ EncodeWEP(key,
+ (pSec->PairwiseEncAlgorithm==RT_ENC_ALG_WEP104)?16:8,
+ pSec->SecBuffer,
+ SecBufLen,
+ pSec->SecBuffer);
+ //PRINT_DATA("SecSWWEPEncryption_after_encrypted==>", pSec->SecBuffer, SecBufLen+4);
+
+ // For WEP ICV.
+ SecBufLen += 4;
+
+ SecBytesCopied = 0;
+
+ // 2005.11.07, by rcnjko.
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ SecBufIndex = FragBufferIndexStart+1;
+ FragBufferCount = 1;
+ }
+ else
+ {
+ SecBufIndex = FragBufferIndexStart;
+ FragBufferCount = 0;
+ }
+ //
+
+ //2004/09/14, then copy SecBuffer back to the buffer
+ // 2005.11.04, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress+(SpecificHeadOverhead+DataOffset),
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset)
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset);
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+ //
+
+ while(FragBufferCount < pTcb->FragBufCount[FragIndex])
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress,
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length;
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+
+ // Copy WEP ICV.
+ // 2005.11.07, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex-1].VirtualAddress+pTcb->BufferList[SecBufIndex-1].Length,
+ pSec->SecBuffer+SecBytesCopied,
+ pSec->EncryptionTailOverhead
+ );
+ pTcb->BufferList[SecBufIndex-1].Length += pSec->EncryptionTailOverhead; // 4; //Fix MPE SUT System Hang,120715, by YJ.
+ SecBytesCopied += pSec->EncryptionTailOverhead;
+ pTcb->FragLength[FragIndex] += pSec->EncryptionTailOverhead;
+ pTcb->PacketLength += pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // For non-coalesce case, the WEP ICV cannot append to last buffer of the fragment directly,
+ // because the buffer might belong to upper layer and we are NOT allow to change its length.
+ if(pTcb->FragCount == 1)
+ {
+ PlatformMoveMemory(
+ pTcb->Tailer.VirtualAddress,
+ pSec->SecBuffer+SecBytesCopied,
+ pSec->EncryptionTailOverhead
+ );
+ pTcb->Tailer.Length = pSec->EncryptionTailOverhead;
+
+ pTcb->BufferList[pTcb->BufferCount] = pTcb->Tailer;
+ pTcb->BufferCount++;
+
+ pTcb->FragLength[FragIndex] += pSec->EncryptionTailOverhead;
+ pTcb->FragBufCount[FragIndex]++;
+ pTcb->PacketLength += pSec->EncryptionTailOverhead;
+
+ SecBytesCopied += pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // TODO: non-coalesce and fragmneted case.
+ }
+ }
+ //
+ }
+}
+
+VOID
+SecSWAESEncryption(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ u4Byte keyidx=0;
+ u4Byte FragIndex = 0;
+ u4Byte BufferIndex = 0;
+ u2Byte FragBufferCount = 0;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ //u1Byte SecBuffer[2000];
+ u4Byte SpecificHeadOverhead = 0;
+ u4Byte SecBufLen = 0;
+ u4Byte SecBytesCopied = 0;
+ u4Byte SecBufIndex = 0;
+ u4Byte FragBufferIndexStart = 0;
+ pu1Byte SecPtr = 0;
+ u4Byte SecLenForCopy = 0;
+ pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte DataOffset; // Added by Annie, 2005-12-23.
+ PRT_WLAN_STA pEntry;
+ PMGNT_INFO pMgntInfo=&Adapter->MgntInfo;
+ OCTET_STRING frame;
+
+ SpecificHeadOverhead = Adapter->TXPacketShiftBytes;
+
+ pHeader += SpecificHeadOverhead;
+
+ FillOctetString(frame, pHeader, (u2Byte)pTcb->PacketLength);
+
+ // Get offset. Annie, 2005-12-23.
+ if( IsQoSDataFrame(pHeader) )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+
+ // check address 4
+ if( Frame_ValidAddr4(frame) )
+ {
+ RT_TRACE( COMP_SEC , DBG_LOUD , ("====>ccw BT data SecSWAESEncryption \n") );
+ IVOffset += ETHERNET_ADDRESS_LENGTH;
+ }
+
+ DataOffset = IVOffset + EXT_IV_LEN;
+
+
+ if(ACTING_AS_AP(Adapter))
+ {
+ if(MacAddr_isMulticast(pTcb->DestinationAddress))
+ {
+ // TODO:
+ //keyidx =
+ }
+ else
+ {
+ // TODO:
+ //keyidx =
+ }
+ }
+ else
+ {
+ keyidx = SecGetTxKeyIdx(Adapter, pTcb->DestinationAddress);
+ }
+
+ for(FragIndex = 0; FragIndex < pTcb->FragCount; FragIndex++)
+ {
+ FragBufferIndexStart = BufferIndex;
+ SecBufLen = 0;
+
+ //2004/09/14, kcwu, clear the Security Coalesce Buffer
+ PlatformZeroMemory(pSec->SecBuffer, SW_ENCRYPT_BUF_SIZE);
+
+ //2004/09/14, kcwu, to show how many buffers are there used by this fragment
+ FragBufferCount = pTcb->FragBufCount[FragIndex];
+
+ // Concatenate buffers to be encrypted into the buffer, SecBuffer.
+ // SecBuffer for AES contains 802.11 header and IV information to encrypt data.
+ while(FragBufferCount-- > 0)
+ {
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ if(pTcb->BufferList[BufferIndex].Length > SpecificHeadOverhead)
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress + SpecificHeadOverhead;
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length - SpecificHeadOverhead;
+ }
+ }
+ else
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress;
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length;
+ }
+
+ // 20110819 Joseph: Prevent from buffer overflow.
+ if((SecBufLen + SecLenForCopy)>SW_ENCRYPT_BUF_SIZE)
+ {
+ SecLenForCopy = SW_ENCRYPT_BUF_SIZE - SecBufLen;
+ FragBufferCount = 0;
+ RT_TRACE( COMP_SEC, DBG_SERIOUS, ("SecSWAESEncryption(): Packet is too large. Truncate!!\n") );
+ }
+
+ PlatformMoveMemory(
+ pSec->SecBuffer + SecBufLen, // 2005.11.07, by rcnjko.
+ SecPtr,
+ SecLenForCopy);
+
+ SecBufLen += SecLenForCopy;
+
+ BufferIndex++;
+ //DbgPrint("FragBufferCount = %d, SecBufLen = %d, BufferIndex = %d\n",
+ // FragBufferCount, SecBufLen, BufferIndex);
+ }
+
+ if(SecBufLen <= 0)
+ {
+ continue;
+ }
+
+#ifdef SW_TXENCRYPTION_DBG
+ RT_TRACE(COMP_SEC, DBG_LOUD, ("\n\nKeyIndex = %d\n", SecGetTxKeyIdx(Adapter, pTcb->DestinationAddress)));
+ PRINT_DATA("AESKeyBuf===>", pSec->AESKeyBuf[SecGetTxKeyIdx(Adapter, pTcb->DestinationAddress)], 16);
+ PRINT_DATA("SecBuffer_before ====>", pSec->SecBuffer, SecBufLen);
+#endif
+ if(pTcb->bTDLPacket)
+ {
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ if(pEntry == NULL)
+ return;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.AESKeyBuf[0] == 0)
+ return;
+
+ SecRSNAEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pEntry->perSTAKeyInfo.AESKeyBuf,
+ 0,
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ }
+ else if( !Adapter->MgntInfo.bRSNAPSKMode && !ACTING_AS_AP(Adapter) )
+ { // NO RSNA-PSK and AP-mode
+ if(pTcb->EncInfo.bMFPPacket && pMgntInfo->bInBIPMFPMode)
+ {
+ SecMFPEncodeAESCCM_1W(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)Adapter->MgntInfo.SecurityInfo.AESKeyBuf[0],
+ keyidx,
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ //RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "BIP AES EncData:\n", pHeader, pTcb->PacketLength);
+ }
+ else
+ {
+ SecEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)Adapter->MgntInfo.SecurityInfo.AESKeyBuf[keyidx],
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ }
+ }
+ //AP WPA AES, CCW
+ else if( ACTING_AS_AP(Adapter) )
+ { // AP mode
+
+
+ if(MacAddr_isMulticast(pTcb->DestinationAddress))
+ {// Multicase packet , used AESGTK
+ //RT_TRACE(COMP_WPAAES, DBG_LOUD, ("<===== AP WPA AES Multicase\n"));
+ //Check if set GTK was completed
+ if(Adapter->MgntInfo.globalKeyInfo.AESGTK[0] == 0)
+ return;
+ SecRSNAEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)Adapter->MgntInfo.globalKeyInfo.AESGTK,
+ pSec->GroupTransmitKeyIdx,
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ //RT_TRACE(COMP_WPAAES, DBG_LOUD, ("=====> AP WPA AES Multicase\n"));
+ }
+ else
+ { // unitcase packet , used Entry Pairwise key
+ //RT_TRACE(COMP_WPAAES, DBG_LOUD, ("<===== AP WPA AES unitcase\n"));
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ if(pEntry == NULL)
+ return;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.AESKeyBuf[0] == 0)
+ return;
+
+ SecRSNAEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pEntry->perSTAKeyInfo.AESKeyBuf,
+ 0,
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ //RT_TRACE(COMP_WPAAES, DBG_LOUD, ("=====> AP WPA AES unitcase\n"));
+ }
+ }
+ else
+ { // RSNA-PSK mode
+ OCTET_STRING pduOS;
+ pu1Byte pRA;
+ pu1Byte pTA;
+ u4Byte index;
+
+ FillOctetString(pduOS, pHeader, IVOffset);
+ pRA = Frame_Addr1(pduOS);
+ pTA = Frame_Addr2(pduOS);
+
+ RT_TRACE(COMP_RSNA, DBG_LOUD,( "=====>RSNA IBSS Send Encrypt packet \n"));
+ RT_PRINT_ADDR(COMP_RSNA, DBG_LOUD, "RSNA RA : ", pRA);
+ RT_PRINT_ADDR(COMP_RSNA, DBG_LOUD, "RSNA TA : ", pTA);
+ if(MacAddr_isMulticast(pRA))
+ {
+ PPER_STA_DEFAULT_KEY_ENTRY pDefKey; // Add by CCW
+
+ //
+ // TODO: remvoe our group key from PerStaDefKeyTable[]
+ //
+
+ //Multicast packet
+ //Find out Default KEY Entry
+ pDefKey = pSec->PerStaDefKeyTable;
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY ; index++, pDefKey++)
+ {
+ if( pDefKey->Valid && (PlatformCompareMemory(pDefKey->MACAdrss , pTA, 6)==0))
+ break;
+ }
+
+ if(index != MAX_NUM_PER_STA_KEY)
+ {
+ RT_TRACE(COMP_RSNA, DBG_LOUD, ("DefaultTransmitKeyIdx: %d\n", pSec->DefaultTransmitKeyIdx));
+ RT_PRINT_DATA(COMP_RSNA, DBG_LOUD, " Multicase Default key : ", pDefKey->DefKeyBuf[pSec->DefaultTransmitKeyIdx], 16);
+ SecRSNAEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pDefKey->DefKeyBuf[pSec->DefaultTransmitKeyIdx],
+ pSec->DefaultTransmitKeyIdx,
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ }
+ else
+ { // no key found!
+ RT_PRINT_ADDR(COMP_RSNA, DBG_WARNING, ("SecSWAESEncryption(): No group key found for pTA: \n"), pTA);
+ }
+ }
+ else
+ {
+ PPER_STA_MPAKEY_ENTRY pMAPkey; // Add by CCW
+
+ //unicast packet
+ //Find out MAPPING Key Entry.
+ pMAPkey = pSec->MAPKEYTable;
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY ; index++, pMAPkey++)
+ {
+ if( pMAPkey->Valid && (PlatformCompareMemory(pMAPkey->MACAdrss , pRA, 6)==0))
+ break;
+ }
+
+ if(index != MAX_NUM_PER_STA_KEY)
+ {
+ RT_PRINT_DATA(COMP_RSNA, DBG_LOUD, " Unicase Key Mapping key : ", pMAPkey->MapKeyBuf , 16);
+ SecRSNAEncodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pMAPkey->MapKeyBuf,
+ 0, // default = 0.
+ pSec->SecBuffer,
+ IVOffset,
+ SecBufLen
+ );
+ }
+ else
+ { // no key found!
+ RT_PRINT_ADDR(COMP_RSNA, DBG_WARNING, ("SecSWAESEncryption(): No pairwse key found for pRA: \n"), pRA);
+ }
+ }
+ }
+ // For AES MIC.
+ SecBufLen += 8;
+
+#ifdef SW_TXENCRYPTION_DBG
+ PRINT_DATA("SecBuffer_after ====>", pSec->SecBuffer, SecBufLen);
+ if(SecBufLen == 147)
+ {
+ RT_TRACE(COMP_SEC, DBG_LOUD, ("SecSWAESEncryption:SecBufLen = %d\n", SecBufLen));
+ }
+#endif
+
+ SecBytesCopied = 0;
+
+ // 2005.11.07, by rcnjko.
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ SecBufIndex = FragBufferIndexStart+1;
+ FragBufferCount = 1;
+ }
+ else
+ {
+ SecBufIndex = FragBufferIndexStart;
+ FragBufferCount = 0;
+ }
+ //
+
+ //2004/09/14, then copy SecBuffer back to the buffer
+ // 2005.11.07, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress + (SpecificHeadOverhead+DataOffset),
+ pSec->SecBuffer+DataOffset+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length - (SpecificHeadOverhead+DataOffset)
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length - (SpecificHeadOverhead+DataOffset);
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+ //
+
+ while(FragBufferCount < pTcb->FragBufCount[FragIndex])
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress,
+ pSec->SecBuffer+DataOffset+SecBytesCopied, // 2005.11.07, by rcnjko.
+ pTcb->BufferList[SecBufIndex].Length
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length;
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+
+ // Copy AES MIC.
+ // 2005.11.07, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex-1].VirtualAddress+pTcb->BufferList[SecBufIndex-1].Length,
+ pSec->SecBuffer+DataOffset+SecBytesCopied,
+ 8//pSec->EncryptionTailOverhead
+ );
+ pTcb->BufferList[SecBufIndex-1].Length += 8;//pSec->EncryptionTailOverhead;
+ SecBytesCopied += 8;//pSec->EncryptionTailOverhead;
+ pTcb->FragLength[FragIndex] += 8;//pSec->EncryptionTailOverhead;
+ pTcb->PacketLength += 8;//pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // For non-coalesce case, the AES MIC cannot append to last buffer of the fragment directly,
+ // because the buffer might belong to upper layer and we are NOT allow to change its length.
+ if(pTcb->FragCount == 1)
+ {
+ PlatformMoveMemory(
+ pTcb->Tailer.VirtualAddress,
+ pSec->SecBuffer+DataOffset+SecBytesCopied,
+ 8//pSec->EncryptionTailOverhead
+ );
+ pTcb->Tailer.Length = 8;//pSec->EncryptionTailOverhead;
+
+ pTcb->BufferList[pTcb->BufferCount] = pTcb->Tailer;
+ pTcb->BufferCount++;
+
+ pTcb->FragLength[FragIndex] += 8;//pSec->EncryptionTailOverhead;
+ pTcb->FragBufCount[FragIndex]++;
+ pTcb->PacketLength += 8;//pSec->EncryptionTailOverhead;
+
+ SecBytesCopied += 8;//pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // TODO: non-coalesce and fragmneted case.
+ }
+ }
+ //
+ }
+}
+
+
+//
+// Software encryption for CKIP.
+// Ported from CKIP code, Annie, 2006-08-11. [AnnieTODO]
+//
+VOID
+SecSWCKIPEncryption(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ u4Byte FragIndex = 0;
+ u4Byte BufferIndex = 0;
+ u2Byte FragBufferCount = 0;
+ u4Byte FragBufferIndexStart = 0;
+ u4Byte SecBufLen = 0;
+ u4Byte SecBufIndex = 0;
+ pu1Byte SecPtr = 0;
+ u4Byte SecLenForCopy = 0;
+ pu1Byte pucIV =0;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ ULONG keyidx = pSec->DefaultTransmitKeyIdx;
+ //UCHAR key[16] = {0};
+ pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress;
+ //u1Byte SecBuffer[2000] = {0};
+ u4Byte SpecificHeadOverhead = 0;
+ u1Byte IVOffset;
+ u1Byte DataOffset;
+ u4Byte SecBytesCopied = 0;
+
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("==> SecSWCKIPEncryption()\n") );
+
+ SpecificHeadOverhead = Adapter->TXPacketShiftBytes;
+
+ pHeader += SpecificHeadOverhead;
+
+
+ if( !pSec->pCkipPara->bIsKP )
+ { //Pure WEP
+ RT_TRACE( COMP_CKIP, DBG_LOUD, ("SecSWCKIPEncryption(): Use pure WEP encryption.\n") );
+ SecSWWEPEncryption(Adapter,pTcb);
+ }
+ else
+ { // Do Key Permutation
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("SecSWCKIPEncryption(): CKIP case: Do Key Permutation.\n") );
+ for(FragIndex = 0; FragIndex < pTcb->FragCount; FragIndex++)
+ {
+ FragBufferIndexStart = BufferIndex;
+ SecBufLen = 0;
+
+ if( IsQoSDataFrame(pHeader) )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ DataOffset = IVOffset + WEP_IV_LEN;
+
+ PlatformZeroMemory(pSec->SecBuffer, SW_ENCRYPT_BUF_SIZE);
+
+ FragBufferCount = pTcb->FragBufCount[FragIndex];
+
+ //2004/09/14, kcwu, data to be encrypted start at the second buffer
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ BufferIndex = FragBufferIndexStart+1;
+ FragBufferCount--; // 2005.11.04, by rcnjko.
+ }
+
+ // Concatenate buffers to be encrypted into the buffer, SecBuffer.
+ // SecBuffer for TKIP does not include 802.11 header and IV.
+ while(FragBufferCount-- > 0)
+ {
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ if(pTcb->BufferList[BufferIndex].Length > (SpecificHeadOverhead+DataOffset))
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress + (SpecificHeadOverhead+DataOffset);
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length - (SpecificHeadOverhead+DataOffset);
+ // to get IV , by CCW
+ pucIV = pTcb->BufferList[BufferIndex].VirtualAddress + (SpecificHeadOverhead+IVOffset);
+ }
+ }
+ else
+ {
+ SecPtr = pTcb->BufferList[BufferIndex].VirtualAddress;
+ SecLenForCopy = pTcb->BufferList[BufferIndex].Length;
+ }
+
+ // 20110819 Joseph: Prevent from buffer overflow.
+ if((SecBufLen + SecLenForCopy)>SW_ENCRYPT_BUF_SIZE)
+ {
+ SecLenForCopy = SW_ENCRYPT_BUF_SIZE - SecBufLen;
+ FragBufferCount = 0;
+ RT_TRACE( COMP_SEC, DBG_SERIOUS, ("SecSWCKIPEncryption(): Packet is too large. Truncate!!\n") );
+ }
+
+ PlatformMoveMemory(
+ pSec->SecBuffer + SecBufLen, // 2005.11.04, by rcnjko.
+ SecPtr,
+ SecLenForCopy);
+
+ SecBufLen += SecLenForCopy;
+
+ BufferIndex++;
+ //DbgPrint("FragBufferCount = %d, SecBufLen = %d, BufferIndex = %d\n",
+ // FragBufferCount, SecBufLen, BufferIndex);
+
+ }
+
+ if(SecBufLen <= 0)
+ {
+ continue;
+ }
+
+ ckip_encrypt( pSec->pCkipPara->CKIPKeyBuf[keyidx] , pucIV , pSec->SecBuffer , SecBufLen );
+
+ // For CKIP ICV.
+ SecBufLen += 4;
+ SecBytesCopied = 0;
+
+
+ // 2005.11.04, by rcnjko.
+ if(!TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ SecBufIndex = FragBufferIndexStart+1;
+ FragBufferCount = 1;
+ }
+ else
+ {
+ SecBufIndex = FragBufferIndexStart;
+ FragBufferCount = 0;
+ }
+ //
+
+ //2004/09/14, then copy SecBuffer back to the buffer
+
+ // 2005.11.04, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress+(SpecificHeadOverhead+DataOffset),
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset)
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length-(SpecificHeadOverhead+DataOffset);
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+ //
+
+ while(FragBufferCount < pTcb->FragBufCount[FragIndex]){
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex].VirtualAddress,
+ pSec->SecBuffer+SecBytesCopied,
+ pTcb->BufferList[SecBufIndex].Length
+ );
+ SecBytesCopied += pTcb->BufferList[SecBufIndex].Length;
+ SecBufIndex++;
+ FragBufferCount++;
+ }
+
+
+ // Copy WEP ICV.
+ // 2005.11.07, by rcnjko.
+ if(TEST_FLAG(pTcb->tcbFlags, RT_TCB_FLAG_USE_COALESCE_BUFFER))
+ {
+ PlatformMoveMemory(
+ pTcb->BufferList[SecBufIndex-1].VirtualAddress+pTcb->BufferList[SecBufIndex-1].Length,
+ pSec->SecBuffer+SecBytesCopied,
+ pSec->EncryptionTailOverhead
+ );
+ pTcb->BufferList[SecBufIndex-1].Length += 4;
+ SecBytesCopied += pSec->EncryptionTailOverhead;
+ pTcb->FragLength[FragIndex] += pSec->EncryptionTailOverhead;
+ pTcb->PacketLength += pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // For non-coalesce case, the WEP ICV cannot append to last buffer of the fragment directly,
+ // because the buffer might belong to upper layer and we are NOT allow to change its length.
+ if(pTcb->FragCount == 1)
+ {
+ PlatformMoveMemory(
+ pTcb->Tailer.VirtualAddress,
+ pSec->SecBuffer+SecBytesCopied,
+ pSec->EncryptionTailOverhead
+ );
+ pTcb->Tailer.Length = pSec->EncryptionTailOverhead;
+
+ pTcb->BufferList[pTcb->BufferCount] = pTcb->Tailer;
+ pTcb->BufferCount++;
+
+ pTcb->FragLength[FragIndex] += pSec->EncryptionTailOverhead;
+ pTcb->FragBufCount[FragIndex]++;
+ pTcb->PacketLength += pSec->EncryptionTailOverhead;
+
+ SecBytesCopied += pSec->EncryptionTailOverhead;
+ }
+ else
+ {
+ // TODO: non-coalesce and fragmneted case.
+ }
+ }
+ }
+
+ }
+
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("<== SecSWCKIPEncryption()\n") );
+}
+
+
+//
+// Check IV increase
+//
+// In Encrypt mode , IV is not increase ,and return FALSE.
+//
+RT_SEC_STATUS
+SecRxCheckIV(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd
+ )
+{
+ RT_ENC_ALG DecryptAlgorithm;
+ RT_SEC_STATUS secStatus = RT_SEC_STATUS_SUCCESS;
+ pu1Byte DestAddr;
+ OCTET_STRING Mpdu;
+ BOOLEAN bMulticastDest;
+ u2Byte EncryptionMPDUHeadOverhead, EncryptionMPDUTailOverhead;
+ u2Byte EncryptionMSDUHeadOverhead, EncryptionMSDUTailOverhead;
+ u2Byte MinEncPktSize;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+
+
+ FillOctetString(Mpdu, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ DestAddr = Frame_pDaddr(Mpdu);
+ bMulticastDest = MacAddr_isMulticast(DestAddr);
+
+ if(!Frame_WEP(Mpdu))
+ { // Skip the non-encrypted frame, 2005.06.28, by rcnjko.
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ if(ACTING_AS_AP(Adapter))
+ return RT_SEC_STATUS_SUCCESS;
+
+ SecGetEncryptionOverhead(
+ Adapter,
+ &EncryptionMPDUHeadOverhead,
+ &EncryptionMPDUTailOverhead,
+ &EncryptionMSDUHeadOverhead,
+ &EncryptionMSDUTailOverhead,
+ TRUE,
+ bMulticastDest);
+ MinEncPktSize = Frame_FrameHdrLng(Mpdu) +
+ EncryptionMPDUHeadOverhead + EncryptionMSDUHeadOverhead +
+ EncryptionMSDUTailOverhead + EncryptionMPDUTailOverhead;
+ if(Mpdu.Length < MinEncPktSize)
+ { // 061214, rcnjo: Discard invalid length frame to prevent memory access violation.
+ return RT_SEC_STATUS_INVALID_PKT_LEN;
+ }
+
+
+ if(bMulticastDest)
+ {
+ DecryptAlgorithm = Adapter->MgntInfo.SecurityInfo.GroupEncAlgorithm;
+ }
+ else
+ {
+ DecryptAlgorithm = Adapter->MgntInfo.SecurityInfo.PairwiseEncAlgorithm;
+ }
+
+ // Get offset. Annie, 2005-12-23.
+ if( pRfd->Status.bIsQosData )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+
+ if(pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+
+ switch(DecryptAlgorithm)
+ {
+ case RT_ENC_ALG_WEP104:
+ case RT_ENC_ALG_WEP40:
+ {
+ u4Byte TempIV = 0;
+
+ // Get IV
+ TempIV = (((u4Byte)( Mpdu.Octet[IVOffset] )) << 16 ) +
+ (((u4Byte)( Mpdu.Octet[IVOffset+1] )) << 8 ) +
+ (((u4Byte)( Mpdu.Octet[IVOffset+2] )) << 0 );
+
+ // Check IV
+ // The 2 situations are not IV replay: (1) current IV of Pkt is greater than the rx IV (2) the current pkt is retry and IV is the same
+ if(TempIV > pSec->RXUntiIV || (Frame_Retry(Mpdu) && pSec->RXUntiIV == TempIV))
+ pSec->RXUntiIV = TempIV;
+ else
+ secStatus = RT_SEC_STATUS_DATA_UNICAST_IV_REPLAY;
+
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ case RT_ENC_ALG_AESCCMP:
+ {
+ u2Byte u2IV16;
+ u4Byte u4IV32;
+ u8Byte TempIV;
+
+ // Get u2IV16 and u4IV32.
+ u2IV16 = ((u2Byte)(*(Mpdu.Octet+IVOffset + 0)) << 8)+ \
+ ((u2Byte)(*(Mpdu.Octet+IVOffset + 2)) << 0);
+
+ u4IV32 = ((u4Byte) (*(Mpdu.Octet+IVOffset + 4)) << 0)+ \
+ ((u4Byte) (*(Mpdu.Octet+IVOffset + 5)) << 8)+ \
+ ((u4Byte) (*(Mpdu.Octet+IVOffset + 6)) << 16)+ \
+ ((u4Byte) (*(Mpdu.Octet+IVOffset + 7)) << 24);
+
+ // Get IV
+ TempIV = u2IV16 + ((u8Byte)u4IV32 << 16 );
+
+ if( bMulticastDest )
+ {
+ // The 2 situations are not IV replay: (1) current IV of Pkt is greater than the rx IV (2) the current pkt is retry and IV is the same
+ if( TempIV > pSec->RXMutiIV || (Frame_Retry(Mpdu) && pSec->RXMutiIV == TempIV))
+ pSec->RXMutiIV = TempIV;
+ else
+ secStatus = RT_SEC_STATUS_DATA_MULTICAST_IV_REPLAY;
+ }
+ else
+ {
+ // The 2 situations are not IV replay: (1) current IV of Pkt is greater than the rx IV (2) the current pkt is retry and IV is the same
+ if( TempIV > pSec->RXUntiIV || (Frame_Retry(Mpdu) && pSec->RXUntiIV == TempIV))
+ pSec->RXUntiIV = TempIV;
+ else
+ secStatus = RT_SEC_STATUS_DATA_UNICAST_IV_REPLAY;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if(secStatus != RT_SEC_STATUS_SUCCESS)
+ { // Count Relay statistics
+ if(IsDataFrame(Mpdu.Octet))
+ {
+ switch(DecryptAlgorithm)
+ {
+ case RT_ENC_ALG_TKIP:
+ CountRxTKIPRelpayStatistics(Adapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ CountRxCCMPRelpayStatistics(Adapter, pRfd);
+ break;
+
+ default: //for MacOSX Compiler warning.
+ break;
+ }
+ }
+ else if(IsMgntFrame(Mpdu.Octet))
+ {
+ secStatus = RT_SEC_STATUS_MGNT_IV_REPLAY;
+ switch(DecryptAlgorithm)
+ {
+ case RT_ENC_ALG_TKIP:
+ CountRxMgntTKIPRelpayStatistics(Adapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ CountRxMgntCCMPRelpayStatistics(Adapter, pRfd);
+ break;
+
+ default: //for MacOSX Compiler warning.
+ break;
+ }
+ }
+ }
+
+ return secStatus;
+}
+
+
+RT_SEC_STATUS
+SecSoftwareDecryption(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ RT_ENC_ALG DecryptAlgorithm;
+ RT_SEC_STATUS secStatus = RT_SEC_STATUS_SUCCESS;
+ BOOLEAN bResult= TRUE;
+ pu1Byte DestAddr;
+ OCTET_STRING Mpdu;
+ BOOLEAN bMulticastDest;
+ u2Byte EncryptionMPDUHeadOverhead, EncryptionMPDUTailOverhead;
+ u2Byte EncryptionMSDUHeadOverhead, EncryptionMSDUTailOverhead;
+ u2Byte MinEncPktSize;
+
+ FillOctetString(Mpdu, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ DestAddr = Frame_pDaddr(Mpdu);
+ bMulticastDest = MacAddr_isMulticast(DestAddr);
+
+ do
+ {
+ if(!Frame_WEP(Mpdu))
+ { // Skip the non-encrypted frame, 2005.06.28, by rcnjko.
+ secStatus = RT_SEC_STATUS_SUCCESS;
+ break;
+ }
+
+ if(!pRfd->bRxBTdata)
+ {
+ if(!eqMacAddr(Frame_pBssid(Mpdu), Adapter->MgntInfo.Bssid))
+ {
+ // RT_PRINT_ADDR(COMP_SEC, DBG_WARNING, "Mismatched BSSID (RT_SEC_STATUS_UNKNOWN_TA):\nFrame_pBssid: ", Frame_pBssid(Mpdu));
+ // RT_PRINT_ADDR(COMP_SEC, DBG_WARNING, "MgntInfo.Bssid: ", Adapter->MgntInfo.Bssid);
+ secStatus = RT_SEC_STATUS_UNKNOWN_TA;
+ break;
+ }
+ }
+
+ SecGetEncryptionOverhead(
+ Adapter,
+ &EncryptionMPDUHeadOverhead,
+ &EncryptionMPDUTailOverhead,
+ &EncryptionMSDUHeadOverhead,
+ &EncryptionMSDUTailOverhead,
+ TRUE,
+ bMulticastDest);
+ MinEncPktSize = Frame_FrameHdrLng(Mpdu) +
+ EncryptionMPDUHeadOverhead + EncryptionMSDUHeadOverhead +
+ EncryptionMSDUTailOverhead + EncryptionMPDUTailOverhead;
+ if(Mpdu.Length < MinEncPktSize)
+ { // 061214, rcnjo: Discard invalid length frame to prevent memory access violation.
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("RT_SEC_STATUS_INVALID_PKT_LEN, mpduLength(%d) < MinEncPktSize(%d)\n", Mpdu.Length, MinEncPktSize));
+ secStatus = RT_SEC_STATUS_INVALID_PKT_LEN;
+ break;
+ }
+
+ if(bMulticastDest)
+ {
+ DecryptAlgorithm = Adapter->MgntInfo.SecurityInfo.GroupEncAlgorithm;
+ }
+ else
+ {
+ DecryptAlgorithm = Adapter->MgntInfo.SecurityInfo.PairwiseEncAlgorithm;
+ }
+
+ if(pRfd->bRxBTdata)
+ {
+ DecryptAlgorithm = RT_ENC_ALG_AESCCMP;
+ }
+
+ switch(DecryptAlgorithm)
+ {
+ case RT_ENC_ALG_WEP104:
+ case RT_ENC_ALG_WEP40:
+ if( !Adapter->MgntInfo.SecurityInfo.pCkipPara->bIsKP )
+ { // WEP decryption
+ bResult = SecSWWEPDecryption(Adapter, pRfd);
+ }
+ else
+ { // CKIP decryption
+ bResult = SecSWCKIPDecryption(Adapter, pRfd);
+ }
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ bResult = SecSWTKIPDecryption(Adapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ bResult = SecSWAESDecryption(Adapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_SMS4:
+ if(RT_STATUS_SUCCESS == WAPI_SecFuncHandler(WAPI_SECSWSMS4DECRYPTION, Adapter, (PVOID)pRfd, WAPI_END))
+ bResult = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ if(!bResult)
+ {
+ secStatus = RT_SEC_STATUS_ICV_ERROR;
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "SecSoftwareDecryption:() RT_SEC_STATUS_ICV_ERROR:\n", Mpdu.Octet, Mpdu.Length);
+ if(Adapter->MgntInfo.uLastDecryptedErrorSeqNum == Frame_SeqNum(Mpdu))
+ {
+ break;
+ }
+
+ RT_TRACE(COMP_RECV, DBG_TRACE, ("SecSoftwareDecryption:() CountRxDecryptErrorStatistics\n"));
+
+ CountRxDecryptErrorStatistics(Adapter, pRfd);
+
+ switch(DecryptAlgorithm)
+ {
+ case RT_ENC_ALG_WEP104:
+ case RT_ENC_ALG_WEP40:
+ if( !Adapter->MgntInfo.SecurityInfo.pCkipPara->bIsKP )
+ { // WEP decryption
+ CountWEPUndecryptableStatistics(Adapter, pRfd);
+ CountWEPICVErrorStatistics(Adapter, pRfd);
+ }
+
+ break;
+
+ case RT_ENC_ALG_TKIP:
+ CountTKIPICVErrorStatistics(Adapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ CountRxCCMPDecryptErrorsStatistics(Adapter, pRfd);
+ break;
+
+ default:
+ break;
+ }
+
+ Adapter->MgntInfo.uLastDecryptedErrorSeqNum = Frame_SeqNum(Mpdu);
+
+ break;
+ }
+ else
+ CountRxDecryptSuccessStatistics(Adapter, pRfd);
+
+ if(RT_SEC_STATUS_SUCCESS != secStatus)
+ break;
+
+ //3 // Check IV Replay
+ //
+ // In fact, we should discard this packet because of IV replay.
+ // However, some packets may still be transmitted in disorder because the IV counter is filled by
+ // driver but not HW. So these packets are indicated to the upper layer.
+ // By Bruce, 2009-10-14.
+ //
+
+ secStatus = SecRxCheckIV(Adapter, pRfd);
+
+ switch(secStatus)
+ {
+ case RT_SEC_STATUS_MGNT_IV_REPLAY:
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "RT_SEC_STATUS_MGNT_IV_REPLAY:\n", Mpdu.Octet, Mpdu.Length);
+ }
+ break;
+
+ default:
+ // Skip normal case no matter if it is data IV replay.
+ secStatus = RT_SEC_STATUS_SUCCESS;
+ break;
+ }
+ }while(FALSE);
+
+ return secStatus;
+}
+
+BOOLEAN
+SecSWAESDecryption(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ u1Byte keyidx;
+ u4Byte micOK;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte IVKeyIdOffset; // Added by Annie, 2005-12-23.
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo; // Add by CCW
+ PRT_WLAN_STA pEntry;
+ PMGNT_INFO pMgntInfo=&Adapter->MgntInfo;
+ OCTET_STRING frame;
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ IVOffset = sMacHdrLng;
+ if( pRfd->Status.bIsQosData )
+ {
+ IVOffset += sQoSCtlLng;
+ }
+ if( pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+
+ // check address 4
+ if( Frame_ValidAddr4(frame) )
+ {
+ IVOffset += ETHERNET_ADDRESS_LENGTH;
+ }
+
+ IVKeyIdOffset = IVOffset + 3;
+
+ keyidx = SecGetRxKeyIdx(
+ Adapter,
+ pRfd->Buffer.VirtualAddress+4,
+ ((pRfd->Buffer.VirtualAddress[IVKeyIdOffset]>>6)&0x03)
+ );
+
+ if(pRfd->bTDLPacket)
+ {
+ pu1Byte pTA;
+ OCTET_STRING pduOS;
+
+ FillOctetString(pduOS, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ pTA = Frame_Addr2(pduOS);
+
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTA);
+ if(pEntry == NULL)
+ return FALSE;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.AESKeyBuf[0] == 0)
+ return FALSE;
+
+ micOK = SecDecodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pEntry->perSTAKeyInfo.AESKeyBuf,
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ }
+ else if( !Adapter->MgntInfo.bRSNAPSKMode && !ACTING_AS_AP(Adapter))
+ {
+ if ( pMgntInfo->bInBIPMFPMode && pRfd->Status.bRxMFPPacket )
+ {
+ //RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Decrypt Rx Mgnt Frame\n"));
+ micOK = SecMFPDecodeAESCCM_1W(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)Adapter->MgntInfo.SecurityInfo.AESKeyBuf[0], // 802.11 MFP used Pawise key to encrypt !!
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ if(!micOK)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("[WARNING] Decryption failed, keyIdx = %d\n", keyidx));
+ }
+ }
+ else
+ {
+ micOK = SecDecodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)Adapter->MgntInfo.SecurityInfo.AESKeyBuf[keyidx],
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ }
+
+
+ }
+ else if( ACTING_AS_AP(Adapter) )
+ {
+ pu1Byte pTA;
+ OCTET_STRING pduOS;
+
+ FillOctetString(pduOS, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ pTA = Frame_Addr2(pduOS);
+
+ pEntry = AsocEntry_GetEntry(pMgntInfo, pTA);
+ if(pEntry == NULL)
+ return FALSE;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.AESKeyBuf[0] == 0)
+ return FALSE;
+
+ micOK = SecDecodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pEntry->perSTAKeyInfo.AESKeyBuf,
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ }
+ else
+ {
+ OCTET_STRING pduOS;
+ pu1Byte pRA;
+ pu1Byte pTA;
+ u4Byte index;
+
+ FillOctetString(pduOS, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ pRA = Frame_Addr1(pduOS);
+ pTA = Frame_Addr2(pduOS);
+
+ RT_TRACE(COMP_RSNA , DBG_LOUD , (" =====> RSNA IBSS Recive Encrypt Packet\n"));
+ keyidx = ((pRfd->Buffer.VirtualAddress[IVKeyIdOffset]>>6)&0x03);
+ RT_PRINT_ADDR(COMP_RSNA, DBG_LOUD, "RSNA RA : ", pRA);
+ RT_PRINT_ADDR(COMP_RSNA, DBG_LOUD, "RSNA TA : ", pTA);
+ RT_TRACE(COMP_RSNA , DBG_LOUD , (" KEY ID : %02x \n" ,keyidx ));
+ if(MacAddr_isMulticast(pRA))
+ {
+ PPER_STA_DEFAULT_KEY_ENTRY pDefKey; // Add by CCW
+
+ //Multicast packet
+ //Find out Default KEY Entry
+ pDefKey = pSec->PerStaDefKeyTable;
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY ; index++, pDefKey++)
+ {
+ if( pDefKey->Valid && (PlatformCompareMemory(pDefKey->MACAdrss , pTA, 6)==0))
+ break;
+ }
+ if(index == MAX_NUM_PER_STA_KEY)
+ { // no key found!
+ RT_PRINT_ADDR(COMP_RSNA, DBG_WARNING, ("SecSWAESDecryption(): No group key found for pTA: \n"), pTA);
+ return FALSE;
+ }
+
+ RT_PRINT_DATA(COMP_RSNA, DBG_LOUD, "Multicase Per-station key : ", pDefKey->DefKeyBuf[keyidx], 16);
+ RT_TRACE(COMP_RSNA , DBG_LOUD , (" KEY Valid : %x \n" ,pDefKey->Valid ));
+ micOK = SecDecodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pDefKey->DefKeyBuf[keyidx],
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ //micOK = TRUE;
+ }
+ else
+ {
+ PPER_STA_MPAKEY_ENTRY pMAPkey; // Add by CCW
+
+ //unicast packet
+ //Find out MAPPING Key Entry.
+ pMAPkey = pSec->MAPKEYTable;
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY; index++, pMAPkey++)
+ {
+ if( pMAPkey->Valid && (PlatformCompareMemory(pMAPkey->MACAdrss , pTA, 6)==0))
+ break;
+ }
+
+ if(index != MAX_NUM_PER_STA_KEY)
+ {
+ RT_PRINT_DATA(COMP_RSNA, DBG_LOUD, "Unicase Key-Mapping key : ", pMAPkey->MapKeyBuf, 16);
+
+ micOK = SecDecodeAESCCM(
+ &Adapter->MgntInfo.SecurityInfo,
+ (u4Byte *)pMAPkey->MapKeyBuf,
+ pRfd->Buffer.VirtualAddress,
+ IVOffset,
+ pRfd->PacketLength
+ );
+ }
+ else
+ { // no key found!
+ RT_PRINT_ADDR(COMP_RSNA, DBG_WARNING, ("SecSWAESDecryption(): No pairwise key found for pTA: \n"), pTA);
+ return FALSE;
+ }
+
+
+ }
+ RT_TRACE(COMP_RSNA, DBG_LOUD, (" micOK : %x\n", micOK));
+ }
+
+ return micOK?TRUE:FALSE;
+}
+
+
+BOOLEAN
+SecSWTKIPDecryption(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ u1Byte keyidx;
+ u1Byte SrcAddr[6];
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ u2Byte u2IV16 = (u2Byte)((pSec->TxIV-1)& UINT64_C(0x000000000000ffff));
+ u4Byte u4IV32 = (u4Byte)((((pSec->TxIV-1)& UINT64_C(0x0000ffffffff0000)) >> 16)& UINT64_C(0x00000000ffffffff));
+ u1Byte key[16];
+ pu1Byte data;
+ u4Byte datalen;
+ PMGNT_INFO pMgntInfo=&Adapter->MgntInfo;
+ PRT_WLAN_STA pEntry = NULL;// = AsocEntry_GetEntry(pMgntInfo, pTcb->DestinationAddress);
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ u1Byte IVKeyIdOffset;
+ pu1Byte pHeader = pRfd->Buffer.VirtualAddress;
+
+ // Get offset. Annie, 2005-12-23.
+ if( pRfd->Status.bIsQosData )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ if(pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+ IVKeyIdOffset = IVOffset + KEYID_POS_IN_IV;
+
+ // Get Key Index.
+ keyidx = SecGetRxKeyIdx(Adapter, pHeader+4, ((pHeader[IVKeyIdOffset]>>6)&0x03) );
+
+ PlatformMoveMemory(SrcAddr, pHeader+10, ETHERNET_ADDRESS_LENGTH);
+
+ if(ACTING_AS_AP(Adapter))
+ {
+ if(MacAddr_isMulticast(SrcAddr))
+ {
+ // [AnnieNote] Current GTK is 12345678...12345678, so it's OK.
+ // It's better to modify it by GTK length if we use PRF-X to generate GTK later. 2005-12-23.
+ //
+
+ //Check if set GTK was completed
+ if(Adapter->MgntInfo.globalKeyInfo.GTK[0] == 0)
+ {
+ //RT_TRACE( COMP_AP, DBG_LOUD, ("SecSWTKIPDecryption(): GTK[0] == 0\n") );
+ return FALSE;
+ }
+ }
+ else
+ {
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, SrcAddr);
+ if(pEntry == NULL)
+ return FALSE;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.TempEncKey == NULL)
+ return FALSE;
+ }
+ }
+ else if(pRfd->bTDLPacket)
+ {
+ //Check if STA within associated lsit table
+ pEntry = AsocEntry_GetEntry(pMgntInfo, SrcAddr);
+ if(pEntry == NULL)
+ return FALSE;
+
+ //Check if set PTK was completed
+ if(pEntry->perSTAKeyInfo.TempEncKey == NULL)
+ return FALSE;
+ }
+
+
+ // Get u2IV16 and u4IV32.
+ u2IV16 = ((u2Byte)(*(pHeader+IVOffset + 0)) << 8)+ \
+ ((u2Byte)(*(pHeader+IVOffset + 2)) << 0);
+
+ u4IV32 = ((u4Byte) (*(pHeader+IVOffset + 4)) << 0)+ \
+ ((u4Byte) (*(pHeader+IVOffset + 5)) << 8)+ \
+ ((u4Byte) (*(pHeader+IVOffset + 6)) << 16)+ \
+ ((u4Byte) (*(pHeader+IVOffset + 7)) << 24);
+
+#if 1 //Added by Jay 0712 for security IV
+ if( ACTING_AS_AP(Adapter) ) // Added by Annie. We should not enter here when STA mode. 2005-07-21.
+ {
+ u8Byte tempIV = 0;
+
+ tempIV |= ((u8Byte)u4IV32) << 16;
+ tempIV |= (u8Byte)u2IV16;
+
+ // Prefast warning C6011: Dereferencing NULL pointer 'pEntry'
+ if(pEntry != NULL &&
+ (tempIV - pEntry->perSTAKeyInfo.RxIV) >= 1000000)
+ {
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("Error: tempIV = 0x%16"i64fmt"x\n", tempIV));
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("Error: pEntry->perSTAKeyInfo.RxIV = 0x%16"i64fmt"x\n", pEntry->perSTAKeyInfo.RxIV));
+
+ //Process IV Error...
+ }
+ else
+ {
+ // Prefast warning C6011: Dereferencing NULL pointer 'pEntry'.
+ if (pEntry != NULL)
+ {
+ if (tempIV - pEntry->perSTAKeyInfo.RxIV != 1)
+ {
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("minor issue: tempIV = 0x%16"i64fmt"x\n", tempIV));
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("minor issue: pEntry->perSTAKeyInfo.RxIV = 0x%16"i64fmt"x\n", pEntry->perSTAKeyInfo.RxIV));
+ }
+
+ pEntry->perSTAKeyInfo.RxIV = tempIV;
+ pEntry->perSTAKeyInfo.RxIV &= UINT64_C(0x0000ffffffffffff);
+ }
+ }
+ }
+ else if(pRfd->bTDLPacket)
+ {
+ u8Byte tempIV = 0;
+
+ tempIV |= ((u8Byte)u4IV32) << 16;
+ tempIV |= (u8Byte)u2IV16;
+
+ // Prefast warning C6011: Dereferencing NULL pointer 'pEntry'.
+ if (pEntry != NULL)
+ {
+ if (tempIV - pEntry->perSTAKeyInfo.RxIV >= 1000000)
+ {
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("Error: tempIV = 0x%16"i64fmt"x\n", tempIV));
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("Error: pEntry->perSTAKeyInfo.RxIV = 0x%16"i64fmt"x\n", pEntry->perSTAKeyInfo.RxIV));
+
+ //Process IV Error...
+ }
+ else
+ {
+ if (tempIV - pEntry->perSTAKeyInfo.RxIV != 1)
+ {
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("minor issue: tempIV = 0x%16"i64fmt"x\n", tempIV));
+ //RT_TRACE(COMP_SEC, DBG_LOUD, ("minor issue: pEntry->perSTAKeyInfo.RxIV = 0x%16"i64fmt"x\n", pEntry->perSTAKeyInfo.RxIV));
+ }
+
+ pEntry->perSTAKeyInfo.RxIV = tempIV;
+ pEntry->perSTAKeyInfo.RxIV &= UINT64_C(0x0000ffffffffffff);
+ }
+ }
+ }
+#endif
+
+
+ if(ACTING_AS_AP(Adapter))
+ { // AP Mode.
+ if(MacAddr_isMulticast(SrcAddr))
+ {
+ TKIPGenerateKey(key, u4IV32, u2IV16, SrcAddr, &Adapter->MgntInfo.globalKeyInfo.GTK[0]);
+ }
+ else
+ {
+ if(pEntry != NULL)
+ TKIPGenerateKey(key, u4IV32, u2IV16, SrcAddr, pEntry->perSTAKeyInfo.TempEncKey);
+ }
+ }
+ else if(pRfd->bTDLPacket)
+ {
+ // Prefast warning C6011: Dereferencing NULL pointer 'pEntry'
+ if(pEntry != NULL)
+ TKIPGenerateKey(key, u4IV32, u2IV16, SrcAddr, pEntry->perSTAKeyInfo.TempEncKey);
+ }
+ else
+ { // STA Mode.
+ TKIPGenerateKey(key,u4IV32,u2IV16,SrcAddr,pSec->KeyBuf[keyidx]);
+ }
+
+
+ data = pHeader + IVOffset + pSec->EncryptionHeadOverhead;
+ datalen = pRfd->PacketLength - (IVOffset + pSec->EncryptionHeadOverhead);
+ //PRINT_DATA((const void*)"Decode: Cichpertext==>", data, datalen);
+ if(!DecodeWEP(key,16,data,datalen,data))
+ {
+// PRINT_DATA((const void*)"Decode: plaintext==>", data, datalen);
+ RT_TRACE(COMP_SEC, DBG_LOUD,("Rx:TKIP Error\n"));
+
+ if( ACTING_AS_AP(Adapter) )
+ {
+ if (pEntry != NULL)
+ {
+ pEntry->perSTAKeyInfo.WEPErrorCnt++;
+ RT_TRACE(COMP_AUTHENTICATOR, DBG_LOUD, ("Rx:TKIP Error: %d\n", pEntry->perSTAKeyInfo.WEPErrorCnt));
+ }
+ }
+ else if(pRfd->bTDLPacket)
+ {
+ if (pEntry != NULL)
+ {
+ pEntry->perSTAKeyInfo.WEPErrorCnt++;
+ RT_TRACE(COMP_AUTHENTICATOR, DBG_LOUD, ("Rx:TKIP Error: %d\n", pEntry->perSTAKeyInfo.WEPErrorCnt));
+ }
+ }
+
+ return FALSE;
+ }
+ RT_TRACE(COMP_SEC, DBG_LOUD,("Rx:TKIP OK\n"));
+ return TRUE;
+
+}
+BOOLEAN
+SecSWWEPDecryption(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+ u1Byte keyidx;
+ u1Byte key[16];
+ s4Byte keysize;
+ pu1Byte data;
+ u4Byte datalen;
+ u1Byte IVOffset; // Added by Annie, 2005-12-23.
+ pu1Byte pHeader = pRfd->Buffer.VirtualAddress;
+
+ //Fix SW WEP descryption multicase fail. 2009,12,08
+
+ u2Byte EncryptionMPDUHeadOverhead, EncryptionMPDUTailOverhead;
+ u2Byte EncryptionMSDUHeadOverhead, EncryptionMSDUTailOverhead;
+
+ pu1Byte DestAddr;
+ OCTET_STRING Mpdu;
+ BOOLEAN bMulticastDest;
+ RT_ENC_ALG TempALg;
+
+ FillOctetString(Mpdu, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+ DestAddr = Frame_pDaddr(Mpdu);
+ bMulticastDest = MacAddr_isMulticast(DestAddr);
+
+ if( pSec->SecLvl == RT_SEC_LVL_NONE )
+ bMulticastDest = FALSE;
+
+ SecGetEncryptionOverhead(
+ Adapter,
+ &EncryptionMPDUHeadOverhead,
+ &EncryptionMPDUTailOverhead,
+ &EncryptionMSDUHeadOverhead,
+ &EncryptionMSDUTailOverhead,
+ TRUE,
+ bMulticastDest
+ );
+
+ if( !bMulticastDest )
+ TempALg = pSec->PairwiseEncAlgorithm;
+ else
+ TempALg = pSec->GroupEncAlgorithm;
+
+ // Get offset. Annie, 2005-12-23.
+ if( pRfd->Status.bIsQosData )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ if(pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+
+
+ // Get IV. (Because 802.11 and key both are little endian)
+ PlatformMoveMemory(key, pHeader+IVOffset , 3);
+
+ // Prepare Key.
+ keyidx = GET_WEP_IV_KEYID(pHeader+IVOffset);
+ keysize = (TempALg==RT_ENC_ALG_WEP104) ? 16 : 8;
+ PlatformMoveMemory(key+3, pSec->KeyBuf[keyidx], keysize-3);
+
+ // Set up input data.
+ data = pHeader + IVOffset + 4;//pSec->EncryptionHeadOverhead;
+ datalen = pRfd->PacketLength - (IVOffset +4);// pSec->EncryptionHeadOverhead);
+
+ //RT_PRINT_DATA( COMP_SEC, DBG_LOUD, "Decode: Ciphertext==>", data, datalen);
+ if( !DecodeWEP( key, keysize, data, datalen, data ) )
+ {
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecSWWEPDecryption(): WEP software decrypted Fail!!! (datalen=%d)\n", datalen) );
+ RT_PRINT_DATA( COMP_SEC, DBG_TRACE, "WEP decoded packet", data, datalen );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//
+// Software decryption for CKIP.
+// Ported from CKIP code, Annie, 2006-08-11. [AnnieTODO]
+//
+BOOLEAN
+SecSWCKIPDecryption(
+ PADAPTER Adapter,
+ PRT_RFD pRfd
+ )
+{
+ pu1Byte pHeader = pRfd->Buffer.VirtualAddress;
+ u1Byte keyidx;
+ u1Byte IVOffset;
+ int DEcok = 0;
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+
+ // Get offset. Annie, 2005-12-23.
+ if( pRfd->Status.bIsQosData )
+ {
+ IVOffset = sMacHdrLng + sQoSCtlLng;
+ }
+ else
+ {
+ IVOffset = sMacHdrLng;
+ }
+ if(pRfd->Status.bContainHTC)
+ IVOffset += sHTCLng;
+
+ //Get IV
+ keyidx= GET_WEP_IV_KEYID( pHeader+IVOffset);
+
+ DEcok = DecodeCKIP( Adapter , (UCHAR *)pHeader , pRfd->PacketLength , pSec->pCkipPara->CKIPKeyBuf[keyidx] , keyidx );
+ RT_TRACE( COMP_CKIP, DBG_LOUD, ("SecSWCKIPDecryption(): DEcok=0x%X\n", DEcok) );
+
+ return ( (DEcok==1)? TRUE : FALSE );
+}
+
+
+//
+// Desription:
+// Used for deny link to MIC failure AP in 60 seconds.
+// 2004.10.06, by rcnjo.
+//
+BOOLEAN
+SecInsertDenyBssidList (
+ PRT_SECURITY_T pSec,
+ u1Byte BssidToDeny[6],
+ u8Byte DenyStartTime
+)
+{
+ PRT_DENY_BSSID pBssidToDeny = NULL;
+ u8Byte EarlyestStartTime = PlatformGetCurrentTime();
+ int EarlyestIdx = 0;
+ int i;
+
+ for(i = 0; i < MAX_DENY_BSSID_LIST_CNT; i++)
+ {
+ if(pSec->DenyBssidList[i].bUsed)
+ {
+ if(pSec->DenyBssidList[i].StartTime < EarlyestStartTime)
+ {
+ EarlyestStartTime = pSec->DenyBssidList[i].StartTime;
+ EarlyestIdx = i;
+ }
+ }
+ else
+ {
+ pBssidToDeny = pSec->DenyBssidList + i;
+ break;
+ }
+ }
+
+ if(pBssidToDeny == NULL)
+ {
+ // Use the oldest one.
+ pBssidToDeny = pSec->DenyBssidList + EarlyestIdx;
+ }
+
+ PlatformMoveMemory(pBssidToDeny->Bssid, BssidToDeny, 6);
+ pBssidToDeny->StartTime = DenyStartTime;
+ pBssidToDeny->bUsed = TRUE;
+
+ return TRUE;
+}
+
+//
+// Desription:
+// Used for deny link to MIC failure AP in 60 seconds.
+// 2004.10.06, by rcnjo.
+//
+BOOLEAN
+SecIsInDenyBssidList (
+ PRT_SECURITY_T pSec,
+ u1Byte BssidToCheck[6]
+)
+{
+ BOOLEAN bToDeny = FALSE;
+ PRT_DENY_BSSID pBssidToDeny;
+ u8Byte CurrTime = PlatformGetCurrentTime();
+ int i;
+
+ for(i = 0; i < MAX_DENY_BSSID_LIST_CNT; i++)
+ {
+ pBssidToDeny = pSec->DenyBssidList + i;
+ if(pBssidToDeny->bUsed)
+ {
+ // Check StartTime.
+ if((CurrTime - pBssidToDeny->StartTime) < MIC_CHECK_TIME) // Diff < 60 seconds.
+ {
+ // Check BSSID.
+ if( PlatformCompareMemory(pBssidToDeny->Bssid, BssidToCheck, 6) == 0 )
+ { // The same BSSID.
+ bToDeny = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ // Clear the entry if it is overdue.
+ pBssidToDeny->bUsed = FALSE;
+ continue;
+ }
+ }
+ }
+
+ return bToDeny;
+}
+
+//
+// Desription:
+// Fill up WEP bit and IV of each fragment in the TCB if necessary.
+// Output:
+// 1. Return TRUE if this packet has to be encrypted.
+// 2. Set up pTcb->EncInfo.
+// 2005.06.27, by rcnjo.
+//
+BOOLEAN
+SecFillHeader(
+ PADAPTER Adapter,
+ PRT_TCB pTcb)
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ int i;
+ int FragIndex = 0;
+ int FragBufferIndex = 0;
+ BOOLEAN bEncrypt;
+ PSTA_ENC_INFO_T pEncInfo = &pTcb->EncInfo;
+
+ bEncrypt = MgntGetEncryptionInfo( Adapter, pTcb, pEncInfo,TRUE);
+
+ if(WAPI_QuerySetVariable(Adapter, WAPI_QUERY, WAPI_VAR_NOTSETENCMACHEADER, 0))
+ return FALSE;
+
+ if(!bEncrypt)
+ {
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("SecFillHeader(): !bEncrypt => return FALSE!\n"));
+ return FALSE;
+ }
+
+ for(i = 0;i < pTcb->BufferCount; i++)
+ {
+ // Fill WEP bit, IV.
+ if(FragBufferIndex == 0)
+ {
+ pu1Byte pFrame;
+
+ pFrame = (pu1Byte)&pTcb->BufferList[i].VirtualAddress[Adapter->TXPacketShiftBytes];
+
+ // WEP bit.
+ SET_80211_HDR_WEP(pFrame, 1);
+
+ // IV.
+ SecHeaderFillIV(Adapter, pFrame);
+ }
+
+ FragBufferIndex++;
+ if(FragBufferIndex == pTcb->FragBufCount[FragIndex])
+ {
+ FragIndex++;
+ FragBufferIndex = 0;
+ }
+ }
+
+ RT_TRACE( COMP_CKIP, DBG_TRACE, ("SecFillHeader(): retrun TRUE\n"));
+ return TRUE;
+}
+
+
+
+//
+// Return: Is the content of pPduOS an EAPOL frame or not. (88-8e)
+// Added by Annie, 2005-12-25.
+//
+BOOLEAN
+SecIsEAPOLPacket(
+ IN PADAPTER Adapter,
+ IN POCTET_STRING pPduOS
+ )
+{
+ BOOLEAN IsEAPOLPkt = FALSE;
+ u1Byte Offset_TypeEAPOL = sMacHdrLng + LLC_HEADER_SIZE; // 30
+
+ if( IsQoSDataFrame(pPduOS->Octet) )
+ {
+ Offset_TypeEAPOL += sQoSCtlLng; // +2
+ }
+
+ if( Frame_WEP(*pPduOS))
+ {
+ Offset_TypeEAPOL += Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead; // 4 or 8
+ }
+
+ // Length Check
+ if( pPduOS->Length < (Offset_TypeEAPOL+1) )
+ {
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("SecIsEAPOLPacket(): invalid length(%d)\n", pPduOS->Length ) );
+ return FALSE;
+ }
+
+ // 888e?
+ if( (pPduOS->Octet[Offset_TypeEAPOL]==0x88) && (pPduOS->Octet[Offset_TypeEAPOL+1]==0x8e) )
+ {
+ IsEAPOLPkt = TRUE;
+ }
+
+ //RT_TRACE( COMP_SEC, DBG_LOUD, ("SecIsEAPOLPacket(): Recvd EAPOL frame. IsEAPOLPkt(%d)\n", IsEAPOLPkt ));
+ return IsEAPOLPkt;
+}
+
+//
+// Return: Is the content of pPduOS an EAPOL frame or not. (88-8e)
+// Added by Annie, 2005-12-25.
+//
+BOOLEAN
+SecIsEAPOLKEYPacket(
+ IN PADAPTER Adapter,
+ IN POCTET_STRING pPduOS
+ )
+{
+ BOOLEAN IsEAPOLKeyPkt = FALSE;
+ u1Byte Offset_TypeEAPOL = sMacHdrLng + LLC_HEADER_SIZE; // 30
+
+ if( IsQoSDataFrame(pPduOS->Octet) )
+ {
+ Offset_TypeEAPOL += sQoSCtlLng; // +2
+ }
+
+ if( Frame_WEP(*pPduOS))
+ {
+ Offset_TypeEAPOL += Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead; // 4 or 8
+ }
+
+ // Length Check
+ if( pPduOS->Length < (Offset_TypeEAPOL+1) )
+ {
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("SecIsEAPOLKEYPacket(): invalid length(%d)\n", pPduOS->Length ) );
+ return FALSE;
+ }
+
+ // 888e && Type is Key
+ if( (pPduOS->Octet[Offset_TypeEAPOL]==0x88) && (pPduOS->Octet[Offset_TypeEAPOL+1]==0x8e)
+ && (pPduOS->Octet[Offset_TypeEAPOL+3]==0x03) )
+ {
+ IsEAPOLKeyPkt = TRUE;
+ }
+
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("SecIsEAPOLKEYPacket(): Recvd EAPOL frame. IsEAPOLPkt(%d)\n", IsEAPOLKeyPkt ));
+ //Here is for Verify 2008/03/20
+ //RT_TRACE( COMP_SEC, DBG_LOUD, ("==m==>SecIsEAPOLKEYPacket(): Recvd EAPOL frame. IsEAPOLPkt(%d)<==m==\n", IsEAPOLKeyPkt ));
+ return IsEAPOLKeyPkt;
+}
+
+
+//
+// Ported from 8185: WMacSetPMKID().
+// Added by Annie, 2006-05-07.
+//
+VOID
+SecSetPMKID(
+ IN PADAPTER Adapter,
+ IN PN5_802_11_PMKID pPMKid
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ PN5_BSSID_INFO pBssidInfo = (PN5_BSSID_INFO)(pPMKid->BSSIDInfo);
+ u4Byte ulIndex, i, j;
+ BOOLEAN blInserted = FALSE;
+ u1Byte NullMacadress[6] = {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
+
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecSetPMKID(): Number Of PMKID on list = %d\n", pPMKid->BSSIDInfoCount) );
+
+
+ //
+ // Clear all entry , when PMK-count = 1 and MAC address all zero !!
+ //
+ if( (pPMKid->BSSIDInfoCount == 1 )&&
+ (PlatformCompareMemory(pBssidInfo->BSSID , NullMacadress , 6 )==0))
+ {
+ for( ulIndex=0; ulIndex<NUM_PMKID_CACHE; ulIndex++ )
+ { // Clear all PMK cash !!
+ pSecInfo->PMKIDList[ulIndex].bUsed = FALSE;
+ PlatformZeroMemory(pSecInfo->PMKIDList[ulIndex].Bssid, sizeof(pSecInfo->PMKIDList[ulIndex].Bssid));
+ pSecInfo->PMKIDList[ulIndex].Ssid.Length = 0;
+
+ }
+ return;
+ }
+
+ //
+ // Clear the entry with different SSID from the AP we are associating with.
+ //
+ for( ulIndex=0; ulIndex<NUM_PMKID_CACHE; ulIndex++ )
+ {
+ if( !eqNByte(pMgntInfo->Ssid.Octet, pSecInfo->PMKIDList[ulIndex].SsidBuf, pMgntInfo->Ssid.Length) ||
+ (pMgntInfo->Ssid.Length != pSecInfo->PMKIDList[ulIndex].Ssid.Length) )
+ { // SSID is not matched => Clear the entry!
+ pSecInfo->PMKIDList[ulIndex].bUsed = FALSE;
+ PlatformZeroMemory(pSecInfo->PMKIDList[ulIndex].Bssid, sizeof(pSecInfo->PMKIDList[ulIndex].Bssid));
+ pSecInfo->PMKIDList[ulIndex].Ssid.Length = 0;
+ }
+ }
+
+
+ //
+ // Insert or cover with new PMKID.
+ //
+ for( i=0; i<pPMKid->BSSIDInfoCount; i++ )
+ {
+ if( i >= NUM_PMKID_CACHE )
+ {
+ RT_TRACE( COMP_SEC, DBG_WARNING, ("SecSetPMKID(): BSSIDInfoCount is more than NUM_PMKID_CACHE!%d\n", pPMKid->BSSIDInfoCount) );
+ break;
+ }
+
+ blInserted = FALSE;
+ for(j=0 ; j<NUM_PMKID_CACHE; j++)
+ {
+ if( pSecInfo->PMKIDList[j].bUsed && eqMacAddr(pSecInfo->PMKIDList[j].Bssid, pBssidInfo->BSSID) )
+ { // BSSID is matched, the same AP => rewrite with new PMKID.
+ CopyMem(pSecInfo->PMKIDList[j].PMKID, pBssidInfo->PMKID, sizeof(pBssidInfo->PMKID));
+ blInserted = TRUE;
+ break;
+ }
+ }
+
+ if(blInserted)
+ {
+ pBssidInfo ++; // pointer to next BSSID_INFO.
+ continue;
+ }
+ else
+ {
+ // Find a new entry
+ for( j=0 ; j<NUM_PMKID_CACHE; j++ )
+ {
+ if(pSecInfo->PMKIDList[j].bUsed == FALSE)
+ {
+ pSecInfo->PMKIDList[j].bUsed = TRUE;
+ CopyMem(pSecInfo->PMKIDList[j].Bssid, pBssidInfo->BSSID, 6);
+ CopyMem(pSecInfo->PMKIDList[j].PMKID, pBssidInfo->PMKID, PMKID_LEN);
+ CopySsid(pSecInfo->PMKIDList[j].SsidBuf, pSecInfo->PMKIDList[j].Ssid.Length, pMgntInfo->SsidBuf, pMgntInfo->Ssid.Length);
+
+ break;
+ }
+ }
+ }
+
+ pBssidInfo ++; // pointer to next BSSID_INFO.
+ }
+
+
+ //
+ // For debug purpose: Check current PMKID list.
+ //
+ for( ulIndex=0; ulIndex<NUM_PMKID_CACHE ; ulIndex++ )
+ {
+ if(pSecInfo->PMKIDList[ulIndex].bUsed)
+ {
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("------------------------------------------\n") );
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("[PMKID %d]\n", ulIndex ) );
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("------------------------------------------\n") );
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecSetPMKID(): PMKIDList[%d].bUsed is TRUE\n", ulIndex) );
+ RT_PRINT_STR( COMP_SEC, DBG_LOUD, "SSID", pSecInfo->PMKIDList[ulIndex].Ssid.Octet, pSecInfo->PMKIDList[ulIndex].Ssid.Length);
+ RT_PRINT_DATA( COMP_SEC, DBG_LOUD, "BSSID", pSecInfo->PMKIDList[ulIndex].Bssid, 6);
+ RT_PRINT_DATA( COMP_SEC, DBG_LOUD, "PMKID", pSecInfo->PMKIDList[ulIndex].PMKID, sizeof(pBssidInfo->PMKID));
+ }
+ }
+}
+
+
+
+//
+// Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
+// Added by Annie, 2006-05-07.
+//
+// Search by BSSID,
+// Return Value:
+// -1 :if there is no pre-auth key in the table
+// >=0 :if there is pre-auth key, and return the entry id
+//
+int
+SecIsInPMKIDList(
+ IN PADAPTER Adapter,
+ IN pu1Byte bssid
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ int i;
+
+ for( i=0; i<NUM_PMKID_CACHE; i++ )
+ {
+ if( pSecInfo->PMKIDList[i].bUsed && eqMacAddr(pSecInfo->PMKIDList[i].Bssid, bssid) )
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if( i == NUM_PMKID_CACHE )
+ { // Could not find.
+ i = -1;
+ }
+ else
+ { // There is one Pre-Authentication Key for the specific BSSID.
+ }
+
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecIsInPMKIDList(): i=%d\n", i) );
+ return i;
+}
+
+
+//
+// Ported from 8185: WMacCatPMKID().
+// Added by Annie, 2006-05-07.
+//
+VOID
+SecCatPMKID(
+ IN PADAPTER Adapter,
+ IN pu1Byte CurAPbssid,
+ IN PRT_WLAN_BSS pBssDesc
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ pu1Byte pIECurrent = NULL;
+ int iEntry = 0;
+ BOOLEAN bCCX8021xenable = FALSE;
+ BOOLEAN bAPSuportCCKM = FALSE;
+
+ u1Byte BIPOui[4] = {0x00, 0x0f , 0xac , 0x06};
+
+ // Note: PMKID can only be included in (Re)Association.
+ if( ACTING_AS_AP(Adapter) || pMgntInfo->mIbss )
+ {
+ return;
+ }
+
+ // Note: PMKID fileds are defined in WPA2.
+ if( pSecInfo->SecLvl < RT_SEC_LVL_WPA2 )
+ return;
+
+ if(WAPI_QuerySetVariable(Adapter, WAPI_QUERY, WAPI_VAR_WAPISUPPORT, 0) && pSecInfo->SecLvl == RT_SEC_LVL_WAPI)
+ return;
+
+ //
+ // CCKM mode return.
+ // Note:
+ // Putting PMKID and CCKM together in the reassociation request must confuse the AP and
+ // make it no response after reassociation request packet.
+ //
+ CCX_QueryCCKMSupport(Adapter, &bCCX8021xenable, &bAPSuportCCKM);
+
+ if( bCCX8021xenable && bAPSuportCCKM)
+ {
+ return;
+ }
+
+ //
+ // 1. Search PMKID list (pSecInfo->PMKIDList[i]) by BSSID.
+ //
+ iEntry = SecIsInPMKIDList( Adapter, CurAPbssid );
+ if( iEntry < 0 )
+ {
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecCatPMKID(): AP is not in current PMKID List => do nothing.\n") );
+
+ // Check Need to add MFP IE or not !!
+ if( pBssDesc->bMFPC && pMgntInfo->bInBIPMFPMode)
+ {
+ pIECurrent = pSecInfo->RSNIE.Octet + pSecInfo->RSNIE.Length - 2; // Point to RSN Capablite
+ SET_RSN_CAP_MFP_CAPABLE(pIECurrent , 1 );
+
+ if( pBssDesc->bMFPR )
+ {
+ // Removed by Bruce, 2014-12-08.
+ // From MSDN:
+ // Management Frame Protection Required (MFPR) enforcement on Windows 8 is not supported. Hence miniport drivers should never set
+ // this bit in the RSN capabilities of RSN IE during an association request. For policy, the access point may advertise MFPR which will
+ // allow MFP-capable STA to associate. Access points not supporting MFP capability will fail association. If MFPR is set by an access point
+ // and STA is not MFP capable, Windows 8 will treat the network as mismatched in capability and not send an association request to the
+ // miniport. http://msdn.microsoft.com/en-us/library/windows/hardware/ff547688(v=vs.85).aspx
+ //
+ // SET_RSN_IE_CAP_MFP_REQUIRED(pIECurrent, 1);
+ }
+ pIECurrent += 2;
+
+ if( pBssDesc->bMFPBIP )
+ {
+ // Add PMKID counter = 0x00 0x00
+ PlatformZeroMemory( pIECurrent , 2 );
+ pIECurrent += 2;
+
+ // Add BIP oui
+ PlatformMoveMemory( pIECurrent ,BIPOui , 4 );
+
+ pSecInfo->RSNIE.Length += 6;
+ }
+ }
+
+ return;
+ }
+
+ //
+ // 2. Cat PMKID to RSNIE.
+ //
+ pIECurrent = pSecInfo->RSNIE.Octet + pSecInfo->RSNIE.Length;
+ ((PDOT11_RSN_IE_PMKID)pIECurrent)->SuiteCount = NUM_CAT_PMKID; // NUM_CAT_PMKID=1
+ CopyMem( ((PDOT11_RSN_IE_PMKID)pIECurrent)->PMKList,
+ pSecInfo->PMKIDList[iEntry].PMKID,
+ sizeof(pSecInfo->PMKIDList[iEntry].PMKID)
+ );
+ pSecInfo->RSNIE.Length += ( sizeof( ((PDOT11_RSN_IE_PMKID)pIECurrent)->SuiteCount ) + // 2 bytes for PMKID count.
+ PMKID_LEN*NUM_CAT_PMKID ); // 16*s bytes for PMKID List.
+
+ //
+ // Note : 802.11w sample RSN PMK and BIP support at same time !!
+ //
+
+ // Check Need to add MFP IE or not !!
+ if( pBssDesc->bMFPC && pMgntInfo->bInBIPMFPMode )
+ {
+ pIECurrent = pIECurrent - 2; // Point to RSN Capablite
+ SET_RSN_IE_CAP_MFP_CAPABLE(pIECurrent , 1 );
+
+ if( pBssDesc->bMFPR )
+ {
+ SET_RSN_CAP_MFP_REQUIRED(pIECurrent, 1);
+ }
+
+ pIECurrent = pSecInfo->RSNIE.Octet + pSecInfo->RSNIE.Length;
+
+ if( pBssDesc->bMFPBIP )
+ {
+ // Add BIP oui
+ PlatformMoveMemory( pIECurrent ,BIPOui , 4 );
+
+ pSecInfo->RSNIE.Length += 4;
+ }
+ }
+
+ RT_PRINT_DATA( COMP_SEC, DBG_LOUD, "SecCatPMKID(): New RSNIE", pSecInfo->RSNIE.Octet, pSecInfo->RSNIE.Length );
+}
+
+
+//
+// If there is no key when security enabled, drop data frames.
+// Added by Annie, 2006-08-15.
+//
+BOOLEAN
+SecDropForKeyAbsent(
+ PADAPTER Adapter,
+ PRT_TCB pTcb
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ BOOLEAN bDrop = FALSE;
+ pu1Byte pRa = NULL;
+ BOOLEAN bFindMatchPeer = FALSE;
+
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("==> SecDropForKeyAbsent()\n") );
+
+ GetTcbDestaddr(Adapter, pTcb, &pRa);
+
+ //<TODO: How about in AP mode>
+ if(ACTING_AS_AP(Adapter))
+ {
+ return bDrop;
+ }
+
+ if ( pSecInfo->SecLvl == RT_SEC_LVL_WAPI)
+ {
+ if(RT_STATUS_SUCCESS == WAPI_SecFuncHandler(WAPI_DROPFORSECKEYABSENT,Adapter, (PVOID)pRa, WAPI_END))
+ bDrop = TRUE;
+ }
+ else
+ {
+ if(pMgntInfo->SafeModeEnabled || pMgntInfo->mIbss)
+ {
+ return bDrop;
+ }
+
+ if( pTcb->EncInfo.SecProtInfo == RT_SEC_NORMAL_DATA )
+ {
+ // Data frame, not EAPOL packet.
+ if(RT_STATUS_SUCCESS == WAPI_SecFuncHandler(WAPI_DROPFORSECKEYABSENT,Adapter, (PVOID)pRa, WAPI_END))
+ bDrop = TRUE;
+
+ if( pSecInfo->SecLvl > RT_SEC_LVL_NONE )
+ { // WPA or WPA2.
+ if( MacAddr_isMulticast(pRa) )
+ { // Need group key.
+ if(pSecInfo->KeyLen[pSecInfo->GroupTransmitKeyIdx]==0)
+ {
+ bDrop = TRUE;
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecDropForKeyAbsent(): Tx Data Without Group Key %d\n", pSecInfo->GroupTransmitKeyIdx ) );
+ }
+ }
+ else
+ { // Need pairwise key.
+ if(pSecInfo->KeyLen[PAIRWISE_KEYIDX]==0)
+ {
+ bDrop = TRUE;
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecDropForKeyAbsent(): Tx Data Without Pairwise Key!\n") );
+ }
+ }
+ }
+ else
+ { // Check WEP
+ if( pSecInfo->EncryptionStatus==RT802_11Encryption1Enabled ) // Is this OK?? Annie, 2006-05-04.
+ {
+ if(pSecInfo->KeyLen[pSecInfo->DefaultTransmitKeyIdx]==0)
+ {
+ bDrop = TRUE;
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("SecDropForKeyAbsent(): Tx Data Without WEP Key %d\n", pSecInfo->DefaultTransmitKeyIdx ) );
+ }
+ }
+ }
+ }
+ }
+ if(bDrop)
+ {
+ RT_TRACE( COMP_SEC, DBG_WARNING, ("SecDropForKeyAbsent(): Not to send data frame since there is no key!\n") );
+ RT_PRINT_DATA(COMP_SEC, DBG_TRACE, "Discarded Packet", pTcb->BufferList[0].VirtualAddress, pTcb->BufferList[0].Length);
+ }
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("<== SecDropForKeyAbsent(), bDrop=%d\n", bDrop) );
+
+ return bDrop;
+}
+
+VOID
+SecSetSwEncryptionDecryption(
+ PADAPTER Adapter,
+ BOOLEAN bSWTxEncrypt,
+ BOOLEAN bSWRxDecrypt
+ )
+{
+ PRT_SECURITY_T pSec = &Adapter->MgntInfo.SecurityInfo;
+
+ // Tx Sw Encryption.
+ if ( (pSec->RegSWTxEncryptFlag == EncryptionDecryptionMechanism_Auto) ||
+ (pSec->RegSWTxEncryptFlag >= EncryptionDecryptionMechanism_Undefined) )
+ {
+ pSec->SWTxEncryptFlag = bSWTxEncrypt;
+ }
+ else if ( pSec->RegSWTxEncryptFlag == EncryptionDecryptionMechanism_Hw )
+ {
+ pSec->SWTxEncryptFlag = FALSE;
+ }
+ else if ( pSec->RegSWTxEncryptFlag == EncryptionDecryptionMechanism_Sw )
+ {
+ pSec->SWTxEncryptFlag = TRUE;
+ }
+
+ // If the encryption mechanism differs between driver determined and registry determined.
+ // Print an warning message.
+ if (pSec->RegSWTxEncryptFlag != bSWTxEncrypt)
+ {
+ RT_TRACE(COMP_SEC, DBG_WARNING,
+ ("SecSetSwEncryptionDecryption(): Warning! User and driver determined encryption mechanism mismatch.\n"));
+ RT_TRACE(COMP_SEC, DBG_WARNING,
+ ("SecSetSwEncryptionDecryption(): RegSWTxEncryptFlag = %d, bSWTxEncrypt = %d\n",
+ pSec->RegSWTxEncryptFlag, bSWTxEncrypt));
+ }
+
+ // Rx Sw Decryption.
+ if ( (pSec->RegSWRxDecryptFlag == EncryptionDecryptionMechanism_Auto) ||
+ (pSec->RegSWRxDecryptFlag == EncryptionDecryptionMechanism_Undefined) )
+ {
+ pSec->SWRxDecryptFlag = bSWRxDecrypt;
+ }
+ else if ( pSec->RegSWRxDecryptFlag == EncryptionDecryptionMechanism_Hw )
+ {
+ pSec->SWRxDecryptFlag = FALSE;
+ }
+ else if ( pSec->RegSWRxDecryptFlag == EncryptionDecryptionMechanism_Sw)
+ {
+ pSec->SWRxDecryptFlag = TRUE;
+ }
+
+ // If the decryption mechanism differs between driver determined and registry determined.
+ // Print an warning message.
+ if (pSec->RegSWRxDecryptFlag != bSWRxDecrypt)
+ {
+ RT_TRACE(COMP_SEC, DBG_WARNING,
+ ("SecSetSwEncryptionDecryption(): Warning! User and driver determined decryption mechanism mismatch.\n"));
+ RT_TRACE(COMP_SEC, DBG_WARNING,
+ ("SecSetSwEncryptionDecryption(): RegSWRxDecryptFlag = %d, bSWRxDecrypt = %d\n",
+ pSec->RegSWRxDecryptFlag, bSWRxDecrypt));
+ }
+
+}
+
+//
+// Description:
+// Determine if the specifed key is available for RA
+//
+BOOLEAN
+SecIsTxKeyInstalled(
+ IN PADAPTER pAdapter,
+ IN pu1Byte pRA
+ )
+{
+ PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+
+ if (ACTING_AS_AP(pAdapter) && MgntActQuery_ApType(pAdapter) == RT_AP_TYPE_LINUX )
+ {// AP mode
+ if(!MacAddr_isMulticast(pRA))
+ {
+ PRT_WLAN_STA pEntry;
+ pEntry = AsocEntry_GetEntry(pMgntInfo,pRA);
+ if(pEntry == NULL)
+ return FALSE;
+ else if(pEntry->keyindex != 0)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ if( !pMgntInfo->bRSNAPSKMode )
+ {
+ if( pSecInfo->KeyLen[0] == 0 &&
+ pSecInfo->KeyLen[1] == 0 &&
+ pSecInfo->KeyLen[2] == 0 &&
+ pSecInfo->KeyLen[3] == 0 &&
+ pSecInfo->KeyLen[4] == 0
+ && 0 == WAPI_QuerySetVariable(pAdapter, WAPI_QUERY, WAPI_VAR_ISCAMUSED, 0)
+ )
+ {
+ return FALSE;
+ }
+ else
+ {
+ // Check Pawise Key only !!
+ if(!ACTING_AS_AP(pAdapter) && pSecInfo->SecLvl > RT_SEC_LVL_NONE )
+ {
+ //
+ // Check Tx key
+ // Note:
+ // This is special case for WPA-2 (RSN).
+ // When the CCX service (supplicant) receives the ANoce packet in the 1st packet of 4-way,
+ // the supplicant set the Group Key to driver and thus the driver then sends the SNonce packet "encrypted"
+ // to AP by an empty PTK just because the driver determine that the Keys has been installed
+ // from the procedure SecIsTxKeyInstalled().
+ // We find this behavior of CCX service in the CCX SDK version 1.1.13.
+ // Advised from CCW, and edited by Bruce, 2009-09-04.
+ //
+ if( pSecInfo->KeyLen[0] == 0
+ && 0 == WAPI_QuerySetVariable(pAdapter, WAPI_QUERY, WAPI_VAR_ISCAMUSED, 0)
+ )
+ {
+ RT_TRACE(COMP_SEC, DBG_LOUD, ("SecIsTxKeyInstalled(): pSecInfo->KeyLen[0] == 0, Tx Key is not installed!\n"));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+ }
+ else
+ { // RSNA IBSS mode.
+ u4Byte index;
+
+ if(!MacAddr_isMulticast(pRA))
+ {
+ PPER_STA_MPAKEY_ENTRY pMapKey;
+
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY ; index++)
+ {
+ pMapKey = &(pSecInfo->MAPKEYTable[index]);
+
+ if( pMapKey->Valid && eqMacAddr(pMapKey->MACAdrss , pRA) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+ else
+ {
+ PPER_STA_DEFAULT_KEY_ENTRY pDefKey;
+
+ //
+ // TODO: remvoe our group key from PerStaDefKeyTable[]
+ //
+ for( index = 0 ; index < MAX_NUM_PER_STA_KEY ; index++)
+ {
+ pDefKey = &(pSecInfo->PerStaDefKeyTable[index]);
+
+ if( pDefKey->Valid && eqMacAddr(pDefKey->MACAdrss, pAdapter->CurrentAddress) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+ }
+}
+
+//
+// Description:
+// Descrypt the mgnt frame by SW and check if this packet is valid.
+// Arguments:
+// [in] Adapter -
+// The NIC context.
+// [in] pRfd -
+// The Rx buffer and information.
+// Return:
+// RT_SEC_STATUS_SUCCESS if this packet is descrypted successfully, and otherwise if any error(this packet should be dropped).
+// Assumption:
+// Before calling this function, be sure these conditions are correct,
+// (1) This packet is mgnt frame.
+// (2) MFP is enabled.
+// By Bruce, 2009-10-08.
+//
+RT_SEC_STATUS
+SecSWMFPDecryption(
+ IN PADAPTER pAdapter,
+ IN PRT_RFD pRfd
+ )
+{
+ PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo);
+ PRT_SECURITY_T pSec = &(pMgntInfo->SecurityInfo);
+ RT_SEC_STATUS secStatus = RT_SEC_STATUS_SUCCESS;
+
+ if(RT_SEC_STATUS_SUCCESS != (secStatus = SecSoftwareDecryption(pAdapter, pRfd)))
+ {
+ switch(pSec->PairwiseEncAlgorithm)
+ {
+ case RT_ENC_ALG_TKIP:
+ CountRxMgntTKIPDecryptErrorsStatistics(pAdapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ CountRxMgntCCMPDecryptErrorsStatistics(pAdapter, pRfd);
+ break;
+
+ default: //for MacOSX Compiler warning.
+ break;
+ }
+
+ RT_TRACE(COMP_SEC , DBG_WARNING , ("SecSWMFPDecryption(): Fail (0x%08X) MFP packe decrypt !!\n", secStatus) );
+ return secStatus;
+ }
+ else if( pMgntInfo->bInBIPMFPMode)
+ { // 802.11 MFP
+ OCTET_STRING frame;
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ // Remove IV, but we haven't remove MIC
+ if(frame.Length > (sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead))
+ {
+ PlatformMoveMemory((frame.Octet+ sMacHdrLng),
+ (frame.Octet + sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead),
+ (frame.Length - (sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead)));
+
+ // Clear the WEP bit because we have removed the IV field.
+ SET_80211_HDR_WEP(pRfd->Buffer.VirtualAddress, 0);
+ }
+ else
+ {
+ RT_TRACE(COMP_SEC , DBG_WARNING , ("SecSWMFPDecryption(): Check Packet Length failed!!\n") );
+ return RT_SEC_STATUS_INVALID_PKT_LEN;
+ }
+ }
+
+ else
+ {
+ OCTET_STRING frame;
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ // Check MHDR IE for TKIP...
+ if(pSec->PairwiseEncAlgorithm == RT_ENC_ALG_TKIP)
+ {
+ // Remove the ICV so that we can caculate the MIC.
+ MAKE_RFD_OFFSET_AT_BACK(pRfd, pMgntInfo->SecurityInfo.EncryptionTailOverhead);
+
+ // Check the length is valid including MHDRIE and MIC
+ if(frame.Length < (sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead + 2 + CCX_MFP_TKIP_MHDR_IE_LEN + TKIP_MIC_LEN)) // MHDRIE (2 + 12) + MIC (8)
+ return RT_SEC_STATUS_INVALID_PKT_LEN;
+
+ if(!CCX_VerifyRxMFP_MHDRIE(pAdapter, pRfd))
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_WARNING, " Verify MFP MHDRIE Error, content:\n", frame.Octet, frame.Length);
+ CountRxMgntMFPTKIPMHDRStatistics(pAdapter, pRfd);
+ return RT_SEC_STATUS_MFP_MGNT_MHDR_FAILURE;
+ }
+
+ RT_PRINT_DATA(COMP_CCX, DBG_LOUD, " Content:\n", pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ // GET_80211_HDR_MORE_FRAG(frame.Octet) may need to chech more frg bit not set !!
+ if(!SecCheckMIC( pAdapter , pRfd ))
+ {
+ return RT_SEC_STATUS_MGNT_MIC_FAILURE;
+ }
+ }
+
+ // Remove IV, but we haven't remove MIC and MHDR IE
+ if(frame.Length > (sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead))
+ {
+ PlatformMoveMemory((frame.Octet+ sMacHdrLng),
+ (frame.Octet + sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead),
+ (frame.Length - (sMacHdrLng + pMgntInfo->SecurityInfo.EncryptionHeadOverhead)));
+
+ // Clear the WEP bit because we have removed the IV field.
+ SET_80211_HDR_WEP(pRfd->Buffer.VirtualAddress, 0);
+
+ }
+ else
+ {
+ RT_TRACE(COMP_SEC , DBG_WARNING , ("SecSWMFPDecryption(): Check Packet Length failed!!\n") );
+ return RT_SEC_STATUS_INVALID_PKT_LEN;
+ }
+ }
+ RT_TRACE(COMP_SEC, DBG_LOUD , ("SecSWMFPDecryption(): SW Descryption OK!\n") );
+ return RT_SEC_STATUS_SUCCESS;
+}
+
+
+//
+// Description:
+// Handle 802.11w BIP MIC .
+// Arguments:
+// [in] Adapter -
+// The NIC context.
+// [in] pRfd -
+// The Rx buffer and information.
+// Return:
+// RT_SEC_STATUS_SUCCESS if MIC and MMIE are OK , and otherwise if any error(this packet should be dropped and Do nothing !!).
+//
+
+RT_SEC_STATUS
+SecCheckMMIE(
+ IN PADAPTER pAdapter,
+ IN PRT_RFD pRfd
+ )
+{
+ OCTET_STRING frame;
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ PRT_SECURITY_T pSec = &(pMgntInfo->SecurityInfo);
+ u1Byte Micdata[256] = {0};
+ u4Byte MACTextLength = 8;
+ u1Byte PlantData[256] = {0};
+ pu1Byte pCurrent = PlantData;
+ u1Byte PlantDataLen = 0;
+ u1Byte MMIE[2] = { 0x4c , 0x10 }; // ID and Len
+ PMMIE_STRUC pMMIE = NULL;
+ u1Byte index = 0;
+
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ if( frame.Length > 256 || frame.Length < 18 )
+ return RT_SEC_STATUS_MFP_MGNT_LEN_FAILURE;
+
+ if( pSec->BIPKeyBuffer[0] == 0 )
+ {
+ RT_TRACE( COMP_SEC , DBG_TRACE , ("===> BIP key no install !!\n"));
+ return RT_SEC_STATUS_SUCCESS;
+ }
+ //Check MMIE exit !!
+ if( PlatformCompareMemory( MMIE , frame.Octet + frame.Length - 18, 2 ))
+ {
+ return RT_SEC_STATUS_MFP_MGNT_MMIE_FAILURE;
+ }
+
+ // Get MMIE
+ pMMIE = (PMMIE_STRUC)( frame.Octet + frame.Length - 18 );
+
+
+ if(0 == PlatformCompareMemory(pMMIE->IPN, pSec->IPN, 6))
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_WARNING, "[WARNING] Skip this frame because we received the same IPN = \n", pMMIE->IPN, 6);
+ return RT_SEC_STATUS_MGNT_IV_REPLAY;
+ }
+ // Check PN
+ for( index = 0 ; index < 6 ; index++ )
+ {
+ if(pMMIE->IPN[5 - index] > pSec->IPN[5- index])
+ break;
+ else if(pMMIE->IPN[5 - index] < pSec->IPN[5- index])
+ {
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "MMIE PN Data:", pMMIE->IPN, 6);
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "My PN Data:", pSec->IPN, 6);
+ return RT_SEC_STATUS_MFP_MGNT_MMIE_FAILURE; // PN error !!
+ }
+ else
+ continue;
+ }
+
+ // Constr ADD | frame body
+ PlatformZeroMemory( PlantData , 256 );
+ PlatformMoveMemory( pCurrent , frame.Octet , 2 ); // FC
+ // Reset Retry , PW_MGN and MORE bit
+ SET_80211_HDR_RETRY(PlantData, 0);
+ SET_80211_HDR_PWR_MGNT(PlantData, 0);
+ SET_80211_HDR_MORE_DATA(PlantData, 0);
+ pCurrent += 2;
+
+ // A1 , A2 and A3
+ PlatformMoveMemory( pCurrent , frame.Octet + 4 , 18 );
+ pCurrent += 18;
+
+ // Frame body
+ PlatformMoveMemory( pCurrent , frame.Octet + 24 , frame.Length - 24 );
+
+ // PlantData length = AAD + PacketLen - Hardlen
+ PlantDataLen = 20 + frame.Length - 24 ;
+
+ // Clear MIC Fild
+ PlatformZeroMemory( (PlantData + PlantDataLen - 8 ) , 8);
+
+ RT_PRINT_DATA(COMP_SEC , DBG_LOUD , " PlantData :\n" , PlantData , PlantDataLen);
+
+ // Calculate MIC
+ AES_CMAC_1W( PlantData , PlantDataLen , pSec->BIPKeyBuffer , 16 , Micdata , &MACTextLength);
+
+ // Compare MIC
+ if(!PlatformCompareMemory( Micdata , pMMIE->MIC , 8 ) )
+ {
+ PlatformMoveMemory(pSec->IPN, pMMIE->IPN, 6);
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ RT_PRINT_DATA(COMP_SEC, DBG_WARNING, "[WARNING] Mismatched MIC for MMIE=\n", pMMIE->MIC, 8);
+ RT_PRINT_DATA(COMP_SEC, DBG_WARNING, "[WARNING] Mismatched MIC for Mine=\n", Micdata, MACTextLength);
+
+ return RT_SEC_STATUS_MFP_MGNT_MMIE_MIC_FAILURE;
+}
+
+
+//
+// Description:
+// Handle Rx Packet encryption status and descrypt it if need.
+// Arguments:
+// [in] Adapter -
+// The NIC context.
+// [in] pRfd -
+// The Rx buffer and information.
+// Return:
+// RT_SEC_STATUS_SUCCESS if this packet is descrypted successfully, and otherwise if any error(this packet should be dropped).
+// By Bruce, 2009-10-15.
+//
+RT_SEC_STATUS
+SecRxDescryption(
+ IN PADAPTER pAdapter,
+ IN PRT_RFD pRfd
+ )
+{
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ PRT_SECURITY_T pSec = &(pMgntInfo->SecurityInfo);
+ OCTET_STRING frame;
+ RT_SEC_STATUS secStatus = RT_SEC_STATUS_SUCCESS;
+
+ // Default mark this packet isn't MFP packet.
+ pRfd->Status.bRxMFPPacket = FALSE;
+
+ FillOctetString(frame, pRfd->Buffer.VirtualAddress, pRfd->PacketLength);
+
+ //3 // Check Frame WEP bit
+ // This packet should not be descrypted.
+ if(!Frame_WEP(frame))
+ {
+ if(!eqMacAddr(pMgntInfo->Bssid, Frame_Addr3(frame)))
+ return RT_SEC_STATUS_SUCCESS;
+
+ if(!((IsMgntDeauth(frame.Octet) || IsMgntDisasoc(frame.Octet)))) // Just check Deauth/Disassoc
+ return RT_SEC_STATUS_SUCCESS;
+
+ if(ACTING_AS_AP(pAdapter) || ACTING_AS_IBSS(pAdapter)) // Don't support in AP mode
+ return RT_SEC_STATUS_SUCCESS;
+
+ if(MacAddr_isMulticast(Frame_Addr1(frame)))
+ {
+ if(CCX_IS_MFP_ENABLED(pAdapter)) // CCX MFP does NOT support multicast
+ return RT_SEC_STATUS_SUCCESS;
+ else if(pMgntInfo->bInBIPMFPMode)
+ {
+ if(RT_SEC_STATUS_SUCCESS == (secStatus = SecCheckMMIE( pAdapter , pRfd )))
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Check MMIE OK!\n"));
+ pRfd->Status.bRxMFPPacket = TRUE;
+ return RT_SEC_STATUS_SUCCESS;
+ }
+ else
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Failed (0x%08X) from SecCheckMMIE()\n", secStatus));
+ return secStatus;
+ }
+ }
+ else
+ {
+ return RT_SEC_STATUS_SUCCESS;
+ }
+ }
+ else // Unicast
+ {
+ if(CCX_IS_MFP_ENABLED(pAdapter))
+ {
+ // Do nothing.
+ }
+ else if(pMgntInfo->bInBIPMFPMode)
+ {
+ if(((IsMgntDeauth(frame.Octet) && class3_err == Frame_DeauthReasonCode(frame))
+ || (IsMgntDisasoc(frame.Octet) && class3_err == Frame_DeassocReasonCode(frame))) &&
+ RT_SA_QUERY_STATE_UNINITIALIZED == pSec->pmfSaState)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Received deauth/disassoc frame wit reason = 7 in PMF mode, start SA query process\n"));
+ pSec->pmfSaState = RT_SA_QUERY_STATE_SA_DETECTED;
+ PlatformSetTimer(pAdapter, &(pSec->SAQueryTimer), 100);
+ }
+ }
+ else
+ {
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ if(!SecIsTxKeyInstalled(pAdapter, pMgntInfo->Bssid))
+ return RT_SEC_STATUS_SUCCESS;
+
+ if(IsMgntDisasoc(frame.Octet) || IsMgntDeauth(frame.Octet) || (IsMgntAction(frame.Octet) && !CCX_IS_MFP_ENABLED(pAdapter)))
+ {
+ // CCXv5 S67 MFP enabled, these packets should be encrypted, if not, count the statistic.
+ switch(pSec->PairwiseEncAlgorithm)
+ {
+ case RT_ENC_ALG_TKIP:
+ CountRxMgntTKIPNoEncryptStatistics(pAdapter, pRfd);
+ break;
+
+ case RT_ENC_ALG_AESCCMP:
+ CountRxMgntCCMPNoEncryptStatistics(pAdapter, pRfd);
+ break;
+
+ default: //for MacOSX Compiler warning.
+ break;
+ }
+ RT_PRINT_DATA(COMP_SEC, DBG_WARNING, "[WARNING] Received mgnt frame without protection bit\n", frame.Octet, frame.Length);
+ return RT_SEC_STATUS_MGNT_FRAME_UNENCRYPT;
+ }
+ }
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+
+ //3 // Descryption for Mgnt Frame.
+ if(IsMgntFrame(frame.Octet))
+ {
+ // Open Share Key mode, we do not handle this condition here.
+ if( IsMgntAuth(frame.Octet) &&
+ (pSec->PairwiseEncAlgorithm == RT_ENC_ALG_WEP40 || pSec->PairwiseEncAlgorithm == RT_ENC_ALG_WEP104))
+ {
+ return SecSoftwareDecryption(pAdapter, pRfd);
+ }
+
+ if(!eqMacAddr(pMgntInfo->Bssid, Frame_Addr3(frame)))
+ return RT_SEC_STATUS_SUCCESS;
+
+ //
+ // 802.11 MFP AES
+ //
+ if(pMgntInfo->bInBIPMFPMode || CCX_IS_MFP_ENABLED(pAdapter))
+ {
+ // Mark this packet as MFP Packet to make sure the Descryption process fills the correct values in the fields.
+ pRfd->Status.bRxMFPPacket = TRUE;
+ RT_PRINT_DATA(COMP_SEC , DBG_LOUD, "SecRxDescryption(): Received Unicast Mgnt Frame with protection:\n" , frame.Octet, frame.Length );
+
+ secStatus = SecSWMFPDecryption(pAdapter, pRfd);
+
+ return secStatus;
+ }
+ else
+ {
+ RT_TRACE(COMP_SEC, DBG_WARNING, ("SecRxDescryption(): Error!!! Receive Mgnt Frame with WEP bit (Not support)!"));
+ return RT_SEC_STATUS_PKT_TYPE_NOT_SUPPORT;
+ }
+
+ return secStatus;
+ }
+
+ //3 // Data packet.
+ if(IsDataFrame(frame.Octet))
+ {
+ if(pSec->SWRxDecryptFlag)
+ {
+ if(pMgntInfo->SafeModeEnabled)
+ {
+ RT_TRACE_F(COMP_RECV, DBG_LOUD, ("Do not use SecSoftwareDecryption when SafeModeEnabled\n"));
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ if(RT_SEC_STATUS_SUCCESS != (secStatus = SecSoftwareDecryption(pAdapter, pRfd)))
+ {
+ RT_TRACE(COMP_SEC , DBG_LOUD , ("SecRxDescryption(): SW Descrypt Fail(0x%08X) for data packet\n", secStatus) );
+ return secStatus;
+ }
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ // Win7 SW Descryption Special Case
+ if( pMgntInfo->NdisVersion >= RT_NDIS_VERSION_6_20 ||
+ pMgntInfo->bConcurrentMode ||
+ pMgntInfo->bBTMode )
+ {
+ BOOLEAN bSWSec = FALSE;
+
+ if( ( MacAddr_isBcst(Frame_pDaddr(frame)) ||
+ MacAddr_isMulticast(Frame_pDaddr(frame)) ) &&
+ MgntActQuery_ApType(pAdapter) == RT_AP_TYPE_NONE)
+ bSWSec = TRUE;
+ else if( pSec->PairwiseEncAlgorithm == RT_ENC_ALG_WEP104 ||
+ pSec->PairwiseEncAlgorithm == RT_ENC_ALG_WEP40)
+ bSWSec = TRUE;
+ else if( pMgntInfo->Regdot11networktype == RT_JOIN_NETWORKTYPE_ADHOC &&
+ MgntActQuery_ApType(pAdapter) == RT_AP_TYPE_NONE)
+ bSWSec = TRUE;
+ else if(!pMgntInfo->SecurityInfo.SWRxDecryptFlag && Frame_WEP(frame) && pRfd->Status.Decrypted == 0)
+ bSWSec = TRUE;
+ else
+ bSWSec = FALSE;
+
+ //for win7 FPGA Verification, Adhoc TP test
+ if(pMgntInfo->bRegAdhocUseHWSec && pMgntInfo->Regdot11networktype == RT_JOIN_NETWORKTYPE_ADHOC)
+ bSWSec = FALSE;
+
+ if(bSWSec)
+ {
+ if(RT_SEC_STATUS_SUCCESS != (secStatus = SecSoftwareDecryption(pAdapter, pRfd)))
+ {
+ {
+ RT_TRACE(COMP_SEC , DBG_TRACE , ("===>Fail Win7 SW decrypt\n") );
+ return RT_SEC_STATUS_FAILURE;
+ }
+ }
+ }
+ }
+
+ // Normal Case with HW Descryption
+ return RT_SEC_STATUS_SUCCESS;
+ }
+
+ RT_TRACE(COMP_SEC, DBG_WARNING, ("SecRxDescryption(): Error!!! Receive Frame(Type = 0x%02X) with WEP bit (Not support)!", frame.Octet[0]));
+ return RT_SEC_STATUS_PKT_TYPE_NOT_SUPPORT;
+}
+
+
+//
+// Description:
+// Append 802.11w MFP MMIE , just for AP mode !!
+// Input :
+// posFrame : Action or mgnt frame , DA is broadcast !!
+//
+void
+SecAppenMMIE(
+ IN PADAPTER pAdapter,
+ OUT POCTET_STRING posFrame
+ )
+{
+ if( !(ACTING_AS_AP(pAdapter) ))
+ return;
+
+ // TO DO !!
+ RT_TRACE(COMP_SEC, DBG_LOUD , ( " ===> AP mode support MFP ??\n" ));
+ return;
+}
+
+
+BOOLEAN
+SecStaGetANoseForS5(
+ IN PADAPTER Adapter,
+ IN POCTET_STRING pPduOS
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ u1Byte Offset_TypeEAPOL = sMacHdrLng + LLC_HEADER_SIZE; // 30
+ OCTET_STRING EapMessage;
+ OCTET_STRING EapKeyMessage;
+ OCTET_STRING ANonce;
+
+ if( IsQoSDataFrame(pPduOS->Octet) )
+ {
+ Offset_TypeEAPOL += sQoSCtlLng; // +2
+ }
+
+ if( Frame_WEP(*pPduOS))
+ {
+ Offset_TypeEAPOL += Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead; // 4 or 8
+ }
+
+ // Length Check
+ if( pPduOS->Length < (Offset_TypeEAPOL+1) )
+ {
+ RT_TRACE( COMP_SEC, DBG_TRACE, ("SecGetANoseForS5(): invalid length(%d)\n", pPduOS->Length ) );
+ return FALSE;
+ }
+
+ // 888e?
+ if( (pPduOS->Octet[Offset_TypeEAPOL]==0x88) && (pPduOS->Octet[Offset_TypeEAPOL+1]==0x8e) )
+ {
+ //TYPE_LENGTH_FIELD_SIZE
+ EapMessage.Octet = pPduOS->Octet+(Offset_TypeEAPOL+TYPE_LENGTH_FIELD_SIZE);
+ EapMessage.Length = pPduOS->Length - (Offset_TypeEAPOL+TYPE_LENGTH_FIELD_SIZE);
+ //RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "===> SecStaGetANoseForS5 \n", EapMessage.Octet, EapMessage.Length);
+
+ if( (u1Byte)( *(EapMessage.Octet+1) ) == LIB1X_EAPOL_KEY )
+ {
+ FillOctetString(EapKeyMessage, EapMessage.Octet+LIB1X_EAPOL_HDRLEN, EapMessage.Length-LIB1X_EAPOL_HDRLEN );
+
+ if( Message_KeyType(EapKeyMessage) == type_Pairwise &&
+ Message_KeyMIC(EapKeyMessage) == FALSE) // 1st message of 4-Way
+ {
+ ANonce = Message_KeyNonce(EapKeyMessage);
+ PlatformMoveMemory(pMgntInfo->mbS5ANose,ANonce.Octet,KEY_NONCE_LEN);
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "===> SecStaGetANoseForS5 \n", pMgntInfo->mbS5ANose,KEY_NONCE_LEN);
+ }
+
+ }
+
+ }
+
+ return FALSE;
+
+}
+
+BOOLEAN
+SecStaGenPMKForS5(
+ IN PADAPTER Adapter
+ )
+{
+
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+
+ PasswordHash(pMgntInfo->mbPassphrase,pMgntInfo->mPasspharseLen, pMgntInfo->Ssid.Octet, pMgntInfo->Ssid.Length, pMgntInfo->mbS5PMK);
+
+ // Calcut PTK
+ CalcPTK(pMgntInfo->Bssid , Adapter->CurrentAddress,
+ pMgntInfo->mbS5ANose, pMgntInfo->mbS5SNose,
+ pMgntInfo->mbS5PMK, PMK_LEN, pMgntInfo->mbS5PTK, PTK_LEN_TKIP);
+
+ PlatformMoveMemory(pMgntInfo->PMDot11RSNRekeyPara.KCK , pMgntInfo->mbS5PTK , PTK_LEN_EAPOLMIC); //
+ PlatformMoveMemory(pMgntInfo->PMDot11RSNRekeyPara.KEK , pMgntInfo->mbS5PTK+PTK_LEN_EAPOLMIC , PTK_LEN_EAPOLENC);
+
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "===>SecStaGenPMKForS5 PMK : \n", pMgntInfo->mbS5PMK, PMK_LEN);
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "===>SecStaGenPMKForS5 PTK : \n", pMgntInfo->mbS5PTK, PTK_LEN_TKIP);
+
+ return TRUE;
+}
+
+//
+// Description:
+// Received the SA query packet from the STA.
+//
+RT_STATUS
+OnSAQueryReq(
+ IN PADAPTER pAdapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING posMpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "OnSAQueryReq(): Content:\n", posMpdu->Octet, posMpdu->Length);
+
+ do
+ {
+ if(!pRfd->Status.bRxMFPPacket)
+ {
+ if(pMgntInfo->bInBIPMFPMode)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("[WARNING] Received an unproteced SA query frame in PMF mode\n"));
+ }
+ rtStatus = RT_STATUS_PKT_DROP;
+ break;
+ }
+
+ if(posMpdu->Length < MIN_ACTION_SA_QUERY_FRAME_LEN)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("[WARNING] Received Length (%d) of SA Query Req < %d, skip this frame\n", posMpdu->Length, MIN_ACTION_SA_QUERY_FRAME_LEN));
+ rtStatus = RT_STATUS_INVALID_LENGTH;
+ }
+
+ SendSAQueryRsp(pAdapter, Frame_Addr2(*posMpdu), GET_ACTFRAME_SA_QUERY_ID(posMpdu->Octet));
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Send SA Query Rsp with Identifier = 0x%04X\n", GET_ACTFRAME_SA_QUERY_ID(posMpdu->Octet)));
+ }while(FALSE);
+
+
+ return RT_STATUS_SUCCESS;
+}
+
+//
+// Description:
+// Received the SA query response packet from the STA.
+//
+RT_STATUS
+OnSAQueryRsp(
+ IN PADAPTER pAdapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING posMpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &pAdapter->MgntInfo;
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
+ RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "OnSAQueryRsp(): Content:\n", posMpdu->Octet, posMpdu->Length);
+
+ do
+ {
+ if(!pRfd->Status.bRxMFPPacket)
+ {
+ if(pMgntInfo->bInBIPMFPMode)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("[WARNING] Received an unproteced SA query frame in PMF mode\n"));
+ }
+ rtStatus = RT_STATUS_PKT_DROP;
+ break;
+ }
+
+ if(posMpdu->Length < MIN_ACTION_SA_QUERY_FRAME_LEN)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_WARNING, ("[WARNING] Received Length (%d) of SA Query Req < %d, skip this frame\n", posMpdu->Length, MIN_ACTION_SA_QUERY_FRAME_LEN));
+ rtStatus = RT_STATUS_INVALID_LENGTH;
+ }
+
+ if(!pMgntInfo->mAssoc)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Received SA query response without association, skip it\n"));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ if(RT_SA_QUERY_STATE_SA_REQ_IN_PROGRESS != pSecInfo->pmfSaState)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Received SA query response mismaching my pmfState (%d), skip it\n", pSecInfo->pmfSaState));
+ rtStatus = RT_STATUS_INVALID_STATE;
+ break;
+ }
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Idendifier = 0x%04X, my Identifier = 0x%04X\n", GET_ACTFRAME_SA_QUERY_ID(posMpdu->Octet), pSecInfo->SAReqIdentifier));
+
+ if(GET_ACTFRAME_SA_QUERY_ID(posMpdu->Octet) != pSecInfo->SAReqIdentifier)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Received mismatched Idendifier = 0x%04X, my Identifier = 0x%04X, skip it\n", GET_ACTFRAME_SA_QUERY_ID(posMpdu->Octet), pSecInfo->SAReqIdentifier));
+ rtStatus = RT_STATUS_INVALID_DATA;
+ break;
+ }
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("SA Query process OK, cancel timer\n"));
+ pSecInfo->pmfSaState = RT_SA_QUERY_STATE_UNINITIALIZED;
+ PlatformCancelTimer(pAdapter, &(pSecInfo->SAQueryTimer));
+ }while(FALSE);
+
+
+ return RT_STATUS_SUCCESS;
+}
+
+
+//
+// Description:
+// Fill and move IV and offset if this tx management frame shall be proteced.
+// Arguments:
+// [in] Adapter -
+// The NIC context.
+// [in] pTcb -
+// The context of tx frame.
+// Return:
+// TRUE if this frame is filled and reserved with security content.
+// FALSE if this frame is returned without any change.
+// Remark:
+// This function checks the association condition and determine if the current frame
+// needs to be proteced. If yes, this frame is filled with WEP bit set in the header.
+// By Bruce-2014-12-26.
+//
+BOOLEAN
+SecFillProtectTxMgntFrameHeader(
+ IN PADAPTER pAdapter,
+ IN PRT_TCB pTcb
+ )
+{
+ PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo);
+ PRT_SECURITY_T pSecInfo = &(pMgntInfo->SecurityInfo);
+ OCTET_STRING osMpdu;
+ BOOLEAN bProtected = FALSE;
+
+ FillOctetString(osMpdu, GET_FRAME_OF_FIRST_FRAG(pAdapter, pTcb), (u2Byte)pTcb->BufferList[0].Length);
+
+ do
+ {
+ // Currently, we only checks the action frame because some mgnt frames like deauth/disassociation are filled
+ // with IV and WEP bit in the construction function, but others mgnt frames excluding deauth/disassociation/action
+ // frame shall be sent without protection.
+ // By Bruce, 2014-12-26.
+ if(!IsMgntAction(osMpdu.Octet))
+ {
+ break;
+ }
+
+ if(!pMgntInfo->bInBIPMFPMode)
+ {
+ break;
+ }
+
+ // We only support AES in PMF.
+ if(RT_ENC_ALG_AESCCMP != pSecInfo->PairwiseEncAlgorithm)
+ {
+ break;
+ }
+
+ // We don't support PMF in AP mode.
+ if(MacAddr_isMulticast(Frame_Addr1(osMpdu)))
+ {
+ break;
+ }
+
+ if(0 == pSecInfo->EncryptionHeadOverhead)
+ break;
+
+ bProtected = TRUE;
+ }while(FALSE);
+
+ if(bProtected)
+ {
+ //3 // Determine different kind of frames before fill the IV
+ // ToDo
+
+ //RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "SecFillProtectTxMgntFrameHeader(): Before extend IV content:\n", osMpdu.Octet, osMpdu.Length);
+ // Set WEP bit !!
+ SET_80211_HDR_WEP(osMpdu.Octet, 1);
+
+ PlatformMoveMemory(pSecInfo->SecBuffer, (osMpdu.Octet + sMacHdrLng), (osMpdu.Length - sMacHdrLng));
+
+ PlatformMoveMemory((osMpdu.Octet+ sMacHdrLng + pSecInfo->EncryptionHeadOverhead),
+ pSecInfo->SecBuffer,
+ (osMpdu.Length - sMacHdrLng));
+ PlatformZeroMemory(osMpdu.Octet + sMacHdrLng , pSecInfo->EncryptionHeadOverhead);
+ osMpdu.Length += pSecInfo->EncryptionHeadOverhead;
+ pTcb->BufferList[0].Length += pSecInfo->EncryptionHeadOverhead;
+ pTcb->PacketLength += pSecInfo->EncryptionHeadOverhead;
+ //RT_PRINT_DATA(COMP_SEC, DBG_LOUD, "SecFillProtectTxMgntFrameHeader(): After extend IV content:\n", osMpdu.Octet, osMpdu.Length);
+ }
+
+ return bProtected;
+}
+
+// Description:
+// Timer callback function to handle SA query mechanism.
+VOID
+SAQueryTimerCallback(
+ IN PRT_TIMER pTimer
+ )
+{
+ PADAPTER pAdapter = (PADAPTER)pTimer->Adapter;
+ PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo);
+ PRT_SECURITY_T pSec = &pAdapter->MgntInfo.SecurityInfo;
+
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("pmfSaState = %d\n", pSec->pmfSaState));
+ if(!pMgntInfo->mAssoc)
+ {
+ pSec->pmfSaState = RT_SA_QUERY_STATE_UNINITIALIZED;
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("State is not associated, skip SA query\n"));
+ return;
+ }
+
+ if(RT_SA_QUERY_STATE_SA_DETECTED == pSec->pmfSaState)
+ {
+ pSec->SAReqIdentifier = (pSec->SAReqIdentifier + 1) % 0xFFFFFFFF;
+ pSec->pmfSaState = RT_SA_QUERY_STATE_SA_REQ_IN_PROGRESS;
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Send SA query request with ID = %04X to AP\n", pSec->SAReqIdentifier));
+ SendSAQueryReq(pAdapter, pMgntInfo->Bssid, pSec->SAReqIdentifier);
+ PlatformSetTimer(pAdapter, &(pSec->SAQueryTimer), 1000);
+ }
+ else if(RT_SA_QUERY_STATE_SA_REQ_IN_PROGRESS == pSec->pmfSaState)
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("Disconnect from the AP\n"));
+ MgntDisconnectAP(pAdapter, unspec_reason);
+ pSec->pmfSaState = RT_SA_QUERY_STATE_UNINITIALIZED;
+ }
+ else
+ {
+ RT_TRACE_F(COMP_SEC, DBG_LOUD, ("[WARNING] Unknown pmfstate = %d\n", pSec->pmfSaState));
+ }
+}
+
+
+//
+// 2011/03/04 MH Move all new CAN search metho to here forcommon binary .
+// We need to reorganize the locaton in he future.
+// ---------------------------------------------------------------
+//
+#if (HW_EN_DE_CRYPTION_FOR_NEW_CAM_SEARCH_FLOW == 1)
+
+VOID
+SEC_AsocEntry_ResetEntry(
+ IN PADAPTER Adapter,
+ IN PRT_WLAN_STA pEntry
+ )
+{
+ u1Byte i;
+
+ for( i = 4 ; i < Adapter->TotalCamEntry ; i++)
+ {
+ if( (Adapter->MgntInfo.SWCamTable[i].bUsed)
+ &&(PlatformCompareMemory(pEntry->MacAddr, Adapter->MgntInfo.SWCamTable[i].macAddress, 6)==0))
+ {
+ CamDeleteOneEntry( Adapter , pEntry->MacAddr, i);
+ PlatformZeroMemory( & Adapter->MgntInfo.SWCamTable[i] , sizeof(SW_CAM_TABLE) );
+ }
+ }
+}
+
+#endif // #if (HW_EN_DE_CRYPTION_FOR_NEW_CAM_SEARCH_FLOW == 1)
+
+VOID
+SecUpdateSWGroupKeyInfo(
+ IN PADAPTER Adapter,
+ IN u4Byte KeyIndex,
+ IN u4Byte KeyLength,
+ IN pu1Byte KeyMaterial
+)
+{
+ PRT_SECURITY_T pSecInfo = &Adapter->MgntInfo.SecurityInfo;
+ RT_ENC_ALG EncAlgorithm;
+
+ EncAlgorithm = pSecInfo->GroupEncAlgorithm;
+ RT_TRACE( COMP_INIT, DBG_LOUD, ("SecUpdateSWGroupKeyInfo(): SecLvl>0, Group EncAlgorithm=0x%08X, Pairwise EncAlgo=0x%08X\n",
+ EncAlgorithm, pSecInfo->PairwiseEncAlgorithm) );
+
+ SecClearGroupKeyByIdx(Adapter, (u1Byte)KeyIndex);
+ CopyMem(pSecInfo->KeyBuf[KeyIndex], KeyMaterial, KeyLength );
+ pSecInfo->KeyLen[KeyIndex]= (u1Byte)KeyLength;
+
+ if(EncAlgorithm == RT_ENC_ALG_TKIP)
+ {
+ if((KeyIndex & ADD_KEY_IDX_AS)){//kcwu: Key is set by an Authenticator, exchange Tx/Rx MIC
+ u1Byte tmpbuf[TKIP_MIC_KEY_LEN];
+ PlatformMoveMemory(tmpbuf, KeyMaterial+TKIP_ENC_KEY_LEN, TKIP_MIC_KEY_LEN);
+ PlatformMoveMemory(KeyMaterial+TKIP_ENC_KEY_LEN,
+ KeyMaterial+TKIP_ENC_KEY_LEN+TKIP_MIC_KEY_LEN, TKIP_MIC_KEY_LEN);
+ PlatformMoveMemory(KeyMaterial+TKIP_ENC_KEY_LEN+TKIP_MIC_KEY_LEN, tmpbuf, TKIP_MIC_KEY_LEN);
+ }
+ PlatformMoveMemory(pSecInfo->RxMICKey, KeyMaterial+TKIP_MICKEYRX_POS, TKIP_MIC_KEY_LEN);
+ PlatformMoveMemory(pSecInfo->TxMICKey, KeyMaterial+TKIP_MICKEYTX_POS, TKIP_MIC_KEY_LEN);
+ }
+ else if(EncAlgorithm == RT_ENC_ALG_AESCCMP)
+ {
+ //2004/09/07, kcwu, AES Key Initialize
+ AESCCMP_BLOCK blockKey;
+ PlatformMoveMemory(blockKey.x, pSecInfo->KeyBuf[KeyIndex],16);
+ AES_SetKey(blockKey.x,
+ AESCCMP_BLK_SIZE*8,
+ (u4Byte *)pSecInfo->AESKeyBuf[KeyIndex]); // run the key schedule
+ }
+ else if(EncAlgorithm==RT_ENC_ALG_WEP40 || EncAlgorithm==RT_ENC_ALG_WEP104)
+ {
+ RT_TRACE( COMP_SEC, DBG_LOUD, ("MgntActSet_802_11_ADD_KEY(): SecLvl>0, EncAlgorithm=%d\n", EncAlgorithm) );
+ }
+}
+
+//
+// ---------------------------------------------------------------
+// 2011/03/04 MH Move all new CAN search metho to here forcommon binary .
+// We need to reorganize the locaton in he future.
+//