blob: e364e73a21303ccdd352a5bbe67e0a8532252794 [file] [log] [blame]
/*
* Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
* This file limUtils.cc contains the utility functions
* LIM uses.
* Author: Chandra Modumudi
* Date: 02/13/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
*/
#include "aniGlobal.h"
#include "wniApi.h"
#include "sirCommon.h"
#include "wniCfg.h"
#include "cfgApi.h"
#include "utilsApi.h"
#include "limUtils.h"
#include "limSecurityUtils.h"
#include "limSession.h"
#define LIM_SEED_LENGTH 16
/**
*preauth node timeout value in interval of 10msec
*/
#define LIM_OPENAUTH_TIMEOUT 500
/**
* limIsAuthAlgoSupported()
*
*FUNCTION:
* This function is called in various places within LIM code
* to determine whether passed authentication algorithm is enabled
* or not
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param authType Indicates MAC based authentication type
* (eSIR_OPEN_SYSTEM or eSIR_SHARED_KEY)
* If Shared Key authentication to be used,
* 'Privacy Option Implemented' flag is also
* checked.
*
* @return true if passed authType is enabled else false
*/
tANI_U8
limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession psessionEntry)
{
tANI_U32 algoEnable, privacyOptImp;
if (authType == eSIR_OPEN_SYSTEM)
{
if(psessionEntry->limSystemRole == eLIM_AP_ROLE)
{
if((psessionEntry->authType == eSIR_OPEN_SYSTEM) || (psessionEntry->authType == eSIR_AUTO_SWITCH))
return true;
else
return false;
}
if (wlan_cfgGetInt(pMac, WNI_CFG_OPEN_SYSTEM_AUTH_ENABLE,
&algoEnable) != eSIR_SUCCESS)
{
/**
* Could not get AuthAlgo1 Enable value
* from CFG. Log error.
*/
limLog(pMac, LOGE,
FL("could not retrieve AuthAlgo1 Enable value"));
return false;
}
else
return ( (algoEnable > 0 ? true : false) );
}
else
{
if(psessionEntry->limSystemRole == eLIM_AP_ROLE)
{
if((psessionEntry->authType == eSIR_SHARED_KEY) || (psessionEntry->authType == eSIR_AUTO_SWITCH))
algoEnable = true;
else
algoEnable = false;
}
else
if (wlan_cfgGetInt(pMac, WNI_CFG_SHARED_KEY_AUTH_ENABLE,
&algoEnable) != eSIR_SUCCESS)
{
/**
* Could not get AuthAlgo2 Enable value
* from CFG. Log error.
*/
limLog(pMac, LOGE,
FL("could not retrieve AuthAlgo2 Enable value"));
return false;
}
if(psessionEntry->limSystemRole == eLIM_AP_ROLE)
{
privacyOptImp = psessionEntry->privacy;
}
else
if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED,
&privacyOptImp) != eSIR_SUCCESS)
{
/**
* Could not get PrivacyOptionImplemented value
* from CFG. Log error.
*/
limLog(pMac, LOGE,
FL("could not retrieve PrivacyOptImplemented value"));
return false;
}
return (algoEnable && privacyOptImp);
}
} /****** end limIsAuthAlgoSupported() ******/
/**
* limInitPreAuthList
*
*FUNCTION:
* This function is called while starting a BSS at AP
* to initialize MAC authenticated STA list. This may also be called
* while joining/starting an IBSS if MAC authentication is allowed
* in IBSS mode.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @return None
*/
void
limInitPreAuthList(tpAniSirGlobal pMac)
{
pMac->lim.pLimPreAuthList = NULL;
} /*** end limInitPreAuthList() ***/
/**
* limDeletePreAuthList
*
*FUNCTION:
* This function is called cleanup Pre-auth list either on
* AP or on STA when moving from one persona to other.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @return None
*/
void
limDeletePreAuthList(tpAniSirGlobal pMac)
{
struct tLimPreAuthNode *pCurrNode, *pTempNode;
pCurrNode = pTempNode = pMac->lim.pLimPreAuthList;
while (pCurrNode != NULL)
{
pTempNode = pCurrNode->next;
limLog(pMac, LOG1, FL("=====> limDeletePreAuthList "));
limReleasePreAuthNode(pMac, pCurrNode);
pCurrNode = pTempNode;
}
pMac->lim.pLimPreAuthList = NULL;
} /*** end limDeletePreAuthList() ***/
/**
* limSearchPreAuthList
*
*FUNCTION:
* This function is called when Authentication frame is received
* by AP (or at a STA in IBSS supporting MAC based authentication)
* to search if a STA is in the middle of MAC Authentication
* transaction sequence.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param macAddr - MAC address of the STA that sent
* Authentication frame.
*
* @return Pointer to pre-auth node if found, else NULL
*/
struct tLimPreAuthNode *
limSearchPreAuthList(tpAniSirGlobal pMac, tSirMacAddr macAddr)
{
struct tLimPreAuthNode *pTempNode = pMac->lim.pLimPreAuthList;
while (pTempNode != NULL)
{
if (vos_mem_compare( (tANI_U8 *) macAddr,
(tANI_U8 *) &pTempNode->peerMacAddr,
sizeof(tSirMacAddr)) )
break;
pTempNode = pTempNode->next;
}
return pTempNode;
} /*** end limSearchPreAuthList() ***/
/**
* limDeleteOpenAuthPreAuthNode
*
*FUNCTION:
* This function is called to delete any stale preauth nodes on
* receiving authentication frame and existing preauth nodes
* reached the maximum allowed limit.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
*
* @return true if any preauthnode deleted else false
*/
tANI_U8
limDeleteOpenAuthPreAuthNode(tpAniSirGlobal pMac)
{
struct tLimPreAuthNode *pPrevNode, *pTempNode, *pFoundNode;
tANI_U8 authNodeFreed = false;
pTempNode = pPrevNode = pMac->lim.pLimPreAuthList;
if (pTempNode == NULL)
return authNodeFreed;
while (pTempNode != NULL)
{
if (pTempNode->mlmState == eLIM_MLM_AUTHENTICATED_STATE &&
pTempNode->authType == eSIR_OPEN_SYSTEM &&
(vos_timer_get_system_ticks() >
(LIM_OPENAUTH_TIMEOUT + pTempNode->timestamp) ||
vos_timer_get_system_ticks() < pTempNode->timestamp))
{
// Found node to be deleted
authNodeFreed = true;
pFoundNode = pTempNode;
if (pMac->lim.pLimPreAuthList == pTempNode)
{
pPrevNode = pMac->lim.pLimPreAuthList = pTempNode =
pFoundNode->next;
}
else
{
pPrevNode->next = pTempNode->next;
pTempNode = pPrevNode->next;
}
limReleasePreAuthNode(pMac, pFoundNode);
}
else
{
pPrevNode = pTempNode;
pTempNode = pPrevNode->next;
}
}
return authNodeFreed;
}
/**
* limAddPreAuthNode
*
*FUNCTION:
* This function is called at AP while sending Authentication
* frame2.
* This may also be called on a STA in IBSS if MAC authentication is
* allowed in IBSS mode.
*
*LOGIC:
* Node is always added to the front of the list
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pAuthNode - Pointer to pre-auth node to be added to the list.
*
* @return None
*/
void
limAddPreAuthNode(tpAniSirGlobal pMac, struct tLimPreAuthNode *pAuthNode)
{
pMac->lim.gLimNumPreAuthContexts++;
pAuthNode->next = pMac->lim.pLimPreAuthList;
pMac->lim.pLimPreAuthList = pAuthNode;
} /*** end limAddPreAuthNode() ***/
/**
* limReleasePreAuthNode
*
*FUNCTION:
* This function is called to realease the accquired
* pre auth node from list.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param pAuthNode - Pointer to Pre Auth node to be released
* @return None
*/
void
limReleasePreAuthNode(tpAniSirGlobal pMac, tpLimPreAuthNode pAuthNode)
{
pAuthNode->fFree = 1;
MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_PRE_AUTH_CLEANUP_TIMER));
tx_timer_deactivate(&pAuthNode->timer);
pMac->lim.gLimNumPreAuthContexts--;
} /*** end limReleasePreAuthNode() ***/
/**
* limDeletePreAuthNode
*
*FUNCTION:
* This function is called at AP when a pre-authenticated STA is
* Associated/Reassociated or when AuthFrame4 is received after
* Auth Response timeout.
* This may also be called on a STA in IBSS if MAC authentication and
* Association/Reassociation is allowed in IBSS mode.
*
*LOGIC:
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param peerMacAddr - MAC address of the STA that need to be deleted
* from pre-auth node list.
*
* @return None
*/
void
limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr)
{
struct tLimPreAuthNode *pPrevNode, *pTempNode;
pTempNode = pPrevNode = pMac->lim.pLimPreAuthList;
if (pTempNode == NULL)
return;
if (vos_mem_compare( (tANI_U8 *) macAddr,
(tANI_U8 *) &pTempNode->peerMacAddr,
sizeof(tSirMacAddr)) )
{
// First node to be deleted
pMac->lim.pLimPreAuthList = pTempNode->next;
limLog(pMac, LOG1, FL(" first node to delete"));
limLog(pMac, LOG1,
FL(" Release data entry:%pK idx %d peer: " MAC_ADDRESS_STR),
pTempNode, pTempNode->authNodeIdx,
MAC_ADDR_ARRAY(macAddr));
limReleasePreAuthNode(pMac, pTempNode);
return;
}
pTempNode = pTempNode->next;
while (pTempNode != NULL)
{
if (vos_mem_compare( (tANI_U8 *) macAddr,
(tANI_U8 *) &pTempNode->peerMacAddr,
sizeof(tSirMacAddr)) )
{
// Found node to be deleted
pPrevNode->next = pTempNode->next;
limLog(pMac, LOG1, FL(" subsequent node to delete"));
limLog(pMac, LOG1,
FL("Release data entry: %pK id %d peer: "MAC_ADDRESS_STR),
pTempNode, pTempNode->authNodeIdx, MAC_ADDR_ARRAY(macAddr));
limReleasePreAuthNode(pMac, pTempNode);
return;
}
pPrevNode = pTempNode;
pTempNode = pTempNode->next;
}
// Should not be here
// Log error
limLog(pMac, LOGP, FL("peer not found in pre-auth list, addr= "));
limPrintMacAddr(pMac, macAddr, LOGP);
} /*** end limDeletePreAuthNode() ***/
/**
* limRestoreFromPreAuthState
*
*FUNCTION:
* This function is called on STA whenever an Authentication
* sequence is complete and state prior to auth need to be
* restored.
*
*LOGIC:
* MLM_AUTH_CNF is prepared and sent to SME state machine.
* In case of restoring from pre-auth:
* - Channel Id is programmed at LO/RF synthesizer
* - BSSID is programmed at RHP
*
*ASSUMPTIONS:
*
*NOTE:
*
* @param pMac - Pointer to Global MAC structure
* @param resultCode - result of authentication attempt
* @return None
*/
void
limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 protStatusCode,tpPESession sessionEntry)
{
tSirMacAddr currentBssId;
tLimMlmAuthCnf mlmAuthCnf;
vos_mem_copy( (tANI_U8 *) &mlmAuthCnf.peerMacAddr,
(tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr,
sizeof(tSirMacAddr));
mlmAuthCnf.authType = pMac->lim.gpLimMlmAuthReq->authType;
mlmAuthCnf.resultCode = resultCode;
mlmAuthCnf.protStatusCode = protStatusCode;
/* Update PE session ID*/
mlmAuthCnf.sessionId = sessionEntry->peSessionId;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState));
/* Set the authAckStatus status flag as sucess as
* host have received the auth rsp and no longer auth
* retry is needed also cancel the auth rety timer
*/
pMac->authAckStatus = LIM_AUTH_ACK_RCD_SUCCESS;
/* Auth retry and AUth failure timers are not started for SAE
* Change' timer for future activations
*/
if (tx_timer_running(&pMac->lim.limTimers.gLimPeriodicAuthRetryTimer))
limDeactivateAndChangeTimer(pMac, eLIM_AUTH_RETRY_TIMER);
/* Change' timer for future activations */
if (tx_timer_running(&pMac->lim.limTimers.gLimAuthFailureTimer))
limDeactivateAndChangeTimer(pMac, eLIM_AUTH_FAIL_TIMER);
#if 0
if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, currentBssId, &cfg) != eSIR_SUCCESS)
{
/// Could not get BSSID from CFG. Log error.
limLog(pMac, LOGP, FL("could not retrieve BSSID"));
}
#endif //TO SUPPORT BT-AMP
sirCopyMacAddr(currentBssId,sessionEntry->bssId);
if (sessionEntry->limSmeState == eLIM_SME_WT_PRE_AUTH_STATE)
{
pMac->lim.gLimPreAuthChannelNumber = 0;
}
if ((protStatusCode == eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS)
&& (sessionEntry->sta_auth_retries_for_code17 <
pMac->sta_auth_retries_for_code17)) {
limLog(pMac, LOG1, FL("Retry Auth "));
limDoSendAuthMgmtFrame(pMac, sessionEntry);
sessionEntry->sta_auth_retries_for_code17++;
} else {
/// Free up buffer allocated
/// for pMac->lim.gLimMlmAuthReq
vos_mem_free(pMac->lim.gpLimMlmAuthReq);
pMac->lim.gpLimMlmAuthReq = NULL;
sessionEntry->limMlmState = sessionEntry->limPrevMlmState;
limPostSmeMessage(pMac,
LIM_MLM_AUTH_CNF,
(tANI_U32 *) &mlmAuthCnf);
sessionEntry->sta_auth_retries_for_code17 = 0;
}
} /*** end limRestoreFromAuthState() ***/
/**
* limLookUpKeyMappings()
*
*FUNCTION:
* This function is called in limProcessAuthFrame() function
* to determine if there exists a Key Mapping key for a given
* MAC address.
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param macAddr MAC address of the peer STA for which existence
* of Key Mapping key is to be determined
*
* @return pKeyMapEntry - Pointer to the keyMapEntry returned by CFG
*/
tCfgWepKeyEntry *
limLookUpKeyMappings(tSirMacAddr macAddr)
{
return NULL;
} /****** end limLookUpKeyMappings() ******/
/**
* limEncryptAuthFrame()
*
*FUNCTION:
* This function is called in limProcessAuthFrame() function
* to encrypt Authentication frame3 body.
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param keyId key id to used
* @param pKey Pointer to the key to be used for encryption
* @param pPlainText Pointer to the body to be encrypted
* @param pEncrBody Pointer to the encrypted auth frame body
* @param keyLength 8 (WEP40) or 16 (WEP104)
* @return None
*/
void
limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 *pPlainText,
tANI_U8 *pEncrBody, tANI_U32 keyLength)
{
tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
tANI_U16 frame_len;
frame_len = ((tpSirMacAuthFrameBody)pPlainText)->length +
SIR_MAC_AUTH_FRAME_INFO_LEN + SIR_MAC_CHALLENGE_ID_LEN;
keyLength += 3;
// Bytes 0-2 of seed is IV
// Read TSF timestamp into seed to get random IV - 1st 3 bytes
halGetTxTSFtimer(pMac, (tSirMacTimeStamp *) &seed);
// Bytes 3-7 of seed is key
vos_mem_copy((tANI_U8 *) &seed[3], pKey, keyLength - 3);
// Compute CRC-32 and place them in last 4 bytes of plain text
limComputeCrc32(icv, pPlainText, frame_len);
vos_mem_copy( pPlainText + frame_len,
icv, SIR_MAC_WEP_ICV_LENGTH);
// Run RC4 on plain text with the seed
limRC4(pEncrBody + SIR_MAC_WEP_IV_LENGTH,
(tANI_U8 *) pPlainText, seed, keyLength,
frame_len + SIR_MAC_WEP_ICV_LENGTH);
// Prepare IV
pEncrBody[0] = seed[0];
pEncrBody[1] = seed[1];
pEncrBody[2] = seed[2];
pEncrBody[3] = keyId << 6;
} /****** end limEncryptAuthFrame() ******/
/**
* limComputeCrc32()
*
*FUNCTION:
* This function is called to compute CRC-32 on a given source.
* Used while encrypting/decrypting Authentication frame 3.
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pDest Destination location for computed CRC
* @param pSrc Source location to be CRC computed
* @param len Length over which CRC to be computed
* @return None
*/
void
limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U16 len)
{
tANI_U32 crc;
int i;
crc = 0;
crc = ~crc;
while(len-- > 0)
crc = limCrcUpdate(crc, *pSrc++);
crc = ~crc;
for (i=0; i < SIR_MAC_WEP_IV_LENGTH; i++)
{
pDest[i] = (tANI_U8)crc;
crc >>= 8;
}
} /****** end limComputeCrc32() ******/
/**
* limRC4()
*
*FUNCTION:
* This function is called to run RC4 algorithm. Called while
* encrypting/decrypting Authentication frame 3.
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pDest Destination location for encrypted text
* @param pSrc Source location to be encrypted
* @param seed Contains seed (IV + key) for PRNG
* @param keyLength 8 (WEP40) or 16 (WEP104)
* @param frameLen Length of the frame
*
* @return None
*/
void
limRC4(tANI_U8 *pDest, tANI_U8 *pSrc, tANI_U8 *seed, tANI_U32 keyLength, tANI_U16 frameLen)
{
typedef struct
{
tANI_U8 i, j;
tANI_U8 sbox[256];
} tRC4Context;
tRC4Context ctx;
{
tANI_U16 i, j, k;
//
// Initialize sbox using seed
//
ctx.i = ctx.j = 0;
for (i=0; i<256; i++)
ctx.sbox[i] = (tANI_U8)i;
j = 0;
k = 0;
for (i=0; i<256; i++)
{
tANI_U8 temp;
if ( k < LIM_SEED_LENGTH )
j = (tANI_U8)(j + ctx.sbox[i] + seed[k]);
temp = ctx.sbox[i];
ctx.sbox[i] = ctx.sbox[j];
ctx.sbox[j] = temp;
if (++k >= keyLength)
k = 0;
}
}
{
tANI_U8 i = ctx.i;
tANI_U8 j = ctx.j;
tANI_U16 len = frameLen;
while (len-- > 0)
{
tANI_U8 temp1, temp2;
i = (tANI_U8)(i+1);
temp1 = ctx.sbox[i];
j = (tANI_U8)(j + temp1);
ctx.sbox[i] = temp2 = ctx.sbox[j];
ctx.sbox[j] = temp1;
temp1 = (tANI_U8)(temp1 + temp2);
temp1 = ctx.sbox[temp1];
temp2 = (tANI_U8)(pSrc ? *pSrc++ : 0);
*pDest++ = (tANI_U8)(temp1 ^ temp2);
}
ctx.i = i;
ctx.j = j;
}
} /****** end limRC4() ******/
/**
* limDecryptAuthFrame()
*
*FUNCTION:
* This function is called in limProcessAuthFrame() function
* to decrypt received Authentication frame3 body.
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param pKey Pointer to the key to be used for decryption
* @param pEncrBody Pointer to the body to be decrypted
* @param pPlainBody Pointer to the decrypted body
* @param keyLength 8 (WEP40) or 16 (WEP104)
*
* @return Decrypt result - eSIR_SUCCESS for success and
* LIM_DECRYPT_ICV_FAIL for ICV mismatch.
* If decryption is a success, pBody will
* have decrypted auth frame body.
*/
tANI_U8
limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody,
tANI_U8 *pPlainBody, tANI_U32 keyLength, tANI_U16 frameLen)
{
tANI_U8 seed[LIM_SEED_LENGTH], icv[SIR_MAC_WEP_ICV_LENGTH];
int i;
keyLength += 3;
// Bytes 0-2 of seed is received IV
vos_mem_copy((tANI_U8 *) seed, pEncrBody, SIR_MAC_WEP_IV_LENGTH - 1);
// Bytes 3-7 of seed is key
vos_mem_copy((tANI_U8 *) &seed[3], pKey, keyLength - 3);
// Run RC4 on encrypted text with the seed
limRC4(pPlainBody,
pEncrBody + SIR_MAC_WEP_IV_LENGTH,
seed,
keyLength,
frameLen);
PELOG4(limLog(pMac, LOG4, FL("plainbody is "));
sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);)
// Compute CRC-32 and place them in last 4 bytes of encrypted body
limComputeCrc32(icv,
(tANI_U8 *) pPlainBody,
(frameLen - SIR_MAC_WEP_ICV_LENGTH));
// Compare RX_ICV with computed ICV
for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++)
{
PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"),
i, icv[i], i, pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);)
if (icv[i] != pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i])
return LIM_DECRYPT_ICV_FAIL;
}
return eSIR_SUCCESS;
} /****** end limDecryptAuthFrame() ******/
/**
* limPostSmeSetKeysCnf
*
* A utility API to send MLM_SETKEYS_CNF to SME
*/
void limPostSmeSetKeysCnf( tpAniSirGlobal pMac,
tLimMlmSetKeysReq *pMlmSetKeysReq,
tLimMlmSetKeysCnf *mlmSetKeysCnf)
{
// Prepare and Send LIM_MLM_SETKEYS_CNF
vos_mem_copy( (tANI_U8 *) &mlmSetKeysCnf->peerMacAddr,
(tANI_U8 *) pMlmSetKeysReq->peerMacAddr,
sizeof(tSirMacAddr));
vos_mem_copy( (tANI_U8 *) &mlmSetKeysCnf->peerMacAddr,
(tANI_U8 *) pMlmSetKeysReq->peerMacAddr,
sizeof(tSirMacAddr));
/// Free up buffer allocated for mlmSetKeysReq
vos_mem_zero(pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq));
vos_mem_free( pMlmSetKeysReq );
pMac->lim.gpLimMlmSetKeysReq = NULL;
limPostSmeMessage( pMac,
LIM_MLM_SETKEYS_CNF,
(tANI_U32 *) mlmSetKeysCnf );
}
/**
* limPostSmeRemoveKeysCnf
*
* A utility API to send MLM_REMOVEKEY_CNF to SME
*/
void limPostSmeRemoveKeyCnf( tpAniSirGlobal pMac,
tpPESession psessionEntry,
tLimMlmRemoveKeyReq *pMlmRemoveKeyReq,
tLimMlmRemoveKeyCnf *mlmRemoveKeyCnf)
{
// Prepare and Send LIM_MLM_REMOVEKEYS_CNF
vos_mem_copy( (tANI_U8 *) &mlmRemoveKeyCnf->peerMacAddr,
(tANI_U8 *) pMlmRemoveKeyReq->peerMacAddr,
sizeof(tSirMacAddr));
/// Free up buffer allocated for mlmRemoveKeysReq
vos_mem_free( pMlmRemoveKeyReq );
pMac->lim.gpLimMlmRemoveKeyReq = NULL;
psessionEntry->limMlmState = psessionEntry->limPrevMlmState; //Restore the state.
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState));
limPostSmeMessage( pMac,
LIM_MLM_REMOVEKEY_CNF,
(tANI_U32 *) mlmRemoveKeyCnf );
}
/**
* limSendSetBssKeyReq()
*
*FUNCTION:
* This function is called from limProcessMlmSetKeysReq(),
* when PE is trying to setup the Group Keys related
* to a specified encryption type
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
* @return none
*/
void limSendSetBssKeyReq( tpAniSirGlobal pMac,
tLimMlmSetKeysReq *pMlmSetKeysReq,
tpPESession psessionEntry)
{
tSirMsgQ msgQ;
tpSetBssKeyParams pSetBssKeyParams = NULL;
tLimMlmSetKeysCnf mlmSetKeysCnf;
tSirRetStatus retCode;
tANI_U32 val = 0;
if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS)
{
limLog( pMac, LOG1,
FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS" ), pMlmSetKeysReq->numKeys);
// Respond to SME with error code
mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
goto end;
}
// Package WDA_SET_BSSKEY_REQ message parameters
pSetBssKeyParams = vos_mem_malloc(sizeof( tSetBssKeyParams ));
if ( NULL == pSetBssKeyParams )
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory during SET_BSSKEY" ));
// Respond to SME with error code
mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
goto end;
}
else
vos_mem_set( (void *) pSetBssKeyParams,
sizeof( tSetBssKeyParams ), 0);
// Update the WDA_SET_BSSKEY_REQ parameters
pSetBssKeyParams->bssIdx = psessionEntry->bssIdx;
pSetBssKeyParams->encType = pMlmSetKeysReq->edType;
if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val))
{
limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" ));
}
pSetBssKeyParams->singleTidRc = (tANI_U8)val;
/* Update PE session Id*/
pSetBssKeyParams->sessionId = psessionEntry ->peSessionId;
if(pMlmSetKeysReq->key[0].keyId &&
((pMlmSetKeysReq->edType == eSIR_ED_WEP40) ||
(pMlmSetKeysReq->edType == eSIR_ED_WEP104))
)
{
/* IF the key id is non-zero and encryption type is WEP, Send all the 4
* keys to HAL with filling the key at right index in pSetBssKeyParams->key. */
pSetBssKeyParams->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
vos_mem_copy( (tANI_U8 *) &pSetBssKeyParams->key[pMlmSetKeysReq->key[0].keyId],
(tANI_U8 *) &pMlmSetKeysReq->key[0], sizeof(pMlmSetKeysReq->key[0]));
}
else
{
pSetBssKeyParams->numKeys = pMlmSetKeysReq->numKeys;
vos_mem_copy( (tANI_U8 *) &pSetBssKeyParams->key,
(tANI_U8 *) &pMlmSetKeysReq->key,
sizeof( tSirKeys ) * pMlmSetKeysReq->numKeys );
}
SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
msgQ.type = WDA_SET_BSSKEY_REQ;
//
// FIXME_GEN4
// A global counter (dialog token) is required to keep track of
// all PE <-> HAL communication(s)
//
msgQ.reserved = 0;
msgQ.bodyptr = pSetBssKeyParams;
msgQ.bodyval = 0;
limLog( pMac, LOGW,
FL( "Sending WDA_SET_BSSKEY_REQ..." ));
MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type));
if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ )))
{
limLog( pMac, LOGE,
FL("Posting SET_BSSKEY to HAL failed, reason=%X"),
retCode );
// Respond to SME with LIM_MLM_SETKEYS_CNF
mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
}
else
return; // Continue after WDA_SET_BSSKEY_RSP...
end:
limPostSmeSetKeysCnf( pMac,
pMlmSetKeysReq,
&mlmSetKeysCnf );
}
/**
* @function : limSendSetStaKeyReq()
*
* @brief : This function is called from limProcessMlmSetKeysReq(),
* when PE is trying to setup the Unicast Keys related
* to a specified STA with specified encryption type
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param pMlmSetKeysReq Pointer to MLM_SETKEYS_REQ buffer
* @param staIdx STA index for which the keys are being set
* @param defWEPIdx The default WEP key index [0..3]
* @return none
*/
void limSendSetStaKeyReq( tpAniSirGlobal pMac,
tLimMlmSetKeysReq *pMlmSetKeysReq,
tANI_U16 staIdx,
tANI_U8 defWEPIdx,
tpPESession sessionEntry)
{
tSirMsgQ msgQ;
tpSetStaKeyParams pSetStaKeyParams = NULL;
tLimMlmSetKeysCnf mlmSetKeysCnf;
tSirRetStatus retCode;
tANI_U32 val = 0;
// Package WDA_SET_STAKEY_REQ message parameters
pSetStaKeyParams = vos_mem_malloc(sizeof( tSetStaKeyParams ));
if ( NULL == pSetStaKeyParams )
{
limLog( pMac, LOGP, FL( "Unable to allocate memory during SET_BSSKEY" ));
return;
}
else
vos_mem_set( (void *) pSetStaKeyParams, sizeof( tSetStaKeyParams ), 0);
// Update the WDA_SET_STAKEY_REQ parameters
pSetStaKeyParams->staIdx = staIdx;
pSetStaKeyParams->encType = pMlmSetKeysReq->edType;
if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val))
{
limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" ));
}
pSetStaKeyParams->singleTidRc = (tANI_U8)val;
/* Update PE session ID*/
pSetStaKeyParams->sessionId = sessionEntry->peSessionId;
/**
* For WEP - defWEPIdx indicates the default WEP
* Key to be used for TX
* For all others, there's just one key that can
* be used and hence it is assumed that
* defWEPIdx = 0 (from the caller)
*/
pSetStaKeyParams->defWEPIdx = defWEPIdx;
/** Store the Previous MlmState*/
sessionEntry->limPrevMlmState = sessionEntry->limMlmState;
SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
if(sessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE && !pMlmSetKeysReq->key[0].unicast) {
sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_BCASTKEY_STATE;
msgQ.type = WDA_SET_STA_BCASTKEY_REQ;
}else {
sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_KEY_STATE;
msgQ.type = WDA_SET_STAKEY_REQ;
}
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState));
/**
* In the Case of WEP_DYNAMIC, ED_TKIP and ED_CCMP
* the Key[0] contains the KEY, so just copy that alone,
* for the case of WEP_STATIC the hal gets the key from cfg
*/
switch( pMlmSetKeysReq->edType ) {
case eSIR_ED_WEP40:
case eSIR_ED_WEP104:
// FIXME! Is this OK?
if( 0 == pMlmSetKeysReq->numKeys ) {
tANI_U32 i;
for(i=0; i < SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS ;i++)
{
vos_mem_copy( (tANI_U8 *) &pSetStaKeyParams->key[i],
(tANI_U8 *) &pMlmSetKeysReq->key[i], sizeof( tSirKeys ));
}
pSetStaKeyParams->wepType = eSIR_WEP_STATIC;
sessionEntry->limMlmState = eLIM_MLM_WT_SET_STA_KEY_STATE;
MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, sessionEntry->peSessionId, sessionEntry->limMlmState));
}else {
/*This case the keys are coming from upper layer so need to fill the
* key at the default wep key index and send to the HAL */
if (defWEPIdx >= SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS)
{
limLog( pMac, LOGE, FL("WEPIdx length %d more than "
"the Max limit, reset to Max"),defWEPIdx);
vos_mem_free (pSetStaKeyParams);
return;
}
vos_mem_copy((tANI_U8 *) &pSetStaKeyParams->key[defWEPIdx],
(tANI_U8 *) &pMlmSetKeysReq->key[0],
sizeof( pMlmSetKeysReq->key[0] ));
pMlmSetKeysReq->numKeys = SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS;
}
break;
case eSIR_ED_TKIP:
case eSIR_ED_CCMP:
#ifdef FEATURE_WLAN_WAPI
case eSIR_ED_WPI:
#endif
{
vos_mem_copy( (tANI_U8 *) &pSetStaKeyParams->key,
(tANI_U8 *) &pMlmSetKeysReq->key[0], sizeof( tSirKeys ));
}
break;
default:
break;
}
//
// FIXME_GEN4
// A global counter (dialog token) is required to keep track of
// all PE <-> HAL communication(s)
//
msgQ.reserved = 0;
msgQ.bodyptr = pSetStaKeyParams;
msgQ.bodyval = 0;
limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ..." ));
MTRACE(macTraceMsgTx(pMac, sessionEntry->peSessionId, msgQ.type));
if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) {
limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X"), retCode );
// Respond to SME with LIM_MLM_SETKEYS_CNF
mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
}else
return; // Continue after WDA_SET_STAKEY_RSP...
limPostSmeSetKeysCnf( pMac, pMlmSetKeysReq, &mlmSetKeysCnf );
}
/**
* limSendRemoveBssKeyReq()
*
*FUNCTION:
* This function is called from limProcessMlmRemoveReq(),
* when PE is trying to Remove a Group Key related
* to a specified encryption type
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param pMlmRemoveKeyReq Pointer to MLM_REMOVEKEY_REQ buffer
* @return none
*/
void limSendRemoveBssKeyReq( tpAniSirGlobal pMac,
tLimMlmRemoveKeyReq *pMlmRemoveKeyReq,
tpPESession psessionEntry)
{
tSirMsgQ msgQ;
tpRemoveBssKeyParams pRemoveBssKeyParams = NULL;
tLimMlmRemoveKeyCnf mlmRemoveKeysCnf;
tSirRetStatus retCode;
// Package WDA_REMOVE_BSSKEY_REQ message parameters
pRemoveBssKeyParams = vos_mem_malloc(sizeof( tRemoveBssKeyParams ));
if ( NULL == pRemoveBssKeyParams )
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory during REMOVE_BSSKEY" ));
// Respond to SME with error code
mlmRemoveKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
goto end;
}
else
vos_mem_set( (void *) pRemoveBssKeyParams,
sizeof( tRemoveBssKeyParams ), 0);
// Update the WDA_REMOVE_BSSKEY_REQ parameters
pRemoveBssKeyParams->bssIdx = psessionEntry->bssIdx;
pRemoveBssKeyParams->encType = pMlmRemoveKeyReq->edType;
pRemoveBssKeyParams->keyId = pMlmRemoveKeyReq->keyId;
pRemoveBssKeyParams->wepType = pMlmRemoveKeyReq->wepType;
/* Update PE session Id*/
pRemoveBssKeyParams->sessionId = psessionEntry->peSessionId;
msgQ.type = WDA_REMOVE_BSSKEY_REQ;
//
// FIXME_GEN4
// A global counter (dialog token) is required to keep track of
// all PE <-> HAL communication(s)
//
msgQ.reserved = 0;
msgQ.bodyptr = pRemoveBssKeyParams;
msgQ.bodyval = 0;
limLog( pMac, LOGW,
FL( "Sending WDA_REMOVE_BSSKEY_REQ..." ));
MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type));
if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ )))
{
limLog( pMac, LOGE,
FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X"),
retCode );
// Respond to SME with LIM_MLM_REMOVEKEYS_CNF
mlmRemoveKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
}
else
return;
end:
limPostSmeRemoveKeyCnf( pMac,
psessionEntry,
pMlmRemoveKeyReq,
&mlmRemoveKeysCnf );
}
/**
* limSendRemoveStaKeyReq()
*
*FUNCTION:
* This function is called from limProcessMlmRemoveKeysReq(),
* when PE is trying to setup the Unicast Keys related
* to a specified STA with specified encryption type
*
*LOGIC:
*
*ASSUMPTIONS:
* NA
*
*NOTE:
* NA
*
* @param pMac Pointer to Global MAC structure
* @param pMlmRemoveKeysReq Pointer to MLM_REMOVEKEYS_REQ buffer
* @param staIdx STA index for which the keys are being set
* @return none
*/
void limSendRemoveStaKeyReq( tpAniSirGlobal pMac,
tLimMlmRemoveKeyReq *pMlmRemoveKeyReq,
tANI_U16 staIdx,
tpPESession psessionEntry)
{
tSirMsgQ msgQ;
tpRemoveStaKeyParams pRemoveStaKeyParams = NULL;
tLimMlmRemoveKeyCnf mlmRemoveKeyCnf;
tSirRetStatus retCode;
pRemoveStaKeyParams = vos_mem_malloc(sizeof( tRemoveStaKeyParams ));
if ( NULL == pRemoveStaKeyParams )
{
limLog( pMac, LOGE,
FL( "Unable to allocate memory during REMOVE_STAKEY" ));
// Respond to SME with error code
mlmRemoveKeyCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
goto end;
}
else
vos_mem_set( (void *) pRemoveStaKeyParams,
sizeof( tRemoveStaKeyParams ), 0);
if( (pMlmRemoveKeyReq->edType == eSIR_ED_WEP104 || pMlmRemoveKeyReq->edType == eSIR_ED_WEP40) &&
pMlmRemoveKeyReq->wepType == eSIR_WEP_STATIC )
{
PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface"));)
mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS;
goto end;
}
// Update the WDA_REMOVEKEY_REQ parameters
pRemoveStaKeyParams->staIdx = staIdx;
pRemoveStaKeyParams->encType = pMlmRemoveKeyReq->edType;
pRemoveStaKeyParams->keyId = pMlmRemoveKeyReq->keyId;
pRemoveStaKeyParams->unicast = pMlmRemoveKeyReq->unicast;
/* Update PE session ID*/
pRemoveStaKeyParams->sessionId = psessionEntry->peSessionId;
SET_LIM_PROCESS_DEFD_MESGS(pMac, false);
msgQ.type = WDA_REMOVE_STAKEY_REQ;
//
// FIXME_GEN4
// A global counter (dialog token) is required to keep track of
// all PE <-> HAL communication(s)
//
msgQ.reserved = 0;
msgQ.bodyptr = pRemoveStaKeyParams;
msgQ.bodyval = 0;
limLog( pMac, LOGW,
FL( "Sending WDA_REMOVE_STAKEY_REQ..." ));
MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type));
retCode = wdaPostCtrlMsg( pMac, &msgQ );
if (eSIR_SUCCESS != retCode)
{
limLog( pMac, LOGE,
FL("Posting REMOVE_STAKEY to HAL failed, reason=%X"),
retCode );
vos_mem_free(pRemoveStaKeyParams);
pRemoveStaKeyParams = NULL;
// Respond to SME with LIM_MLM_REMOVEKEY_CNF
mlmRemoveKeyCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL;
}
else
return;
end:
if (pRemoveStaKeyParams)
{
vos_mem_free(pRemoveStaKeyParams);
}
limPostSmeRemoveKeyCnf( pMac,
psessionEntry,
pMlmRemoveKeyReq,
&mlmRemoveKeyCnf );
}