blob: aa089a4d88eb93af15c1b0b5448ee57d0a97eea0 [file] [log] [blame]
/** @file keyMgmtSta.c
*
* @brief This file defines key management API for sta
* Copyright (C) 2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available by writing to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*/
/******************************************************
Change log:
03/07/2014: Initial version
******************************************************/
#include "wltypes.h"
#include "IEEE_types.h"
#include "hostsa_ext_def.h"
#include "authenticator.h"
#include "wl_macros.h"
#include "keyMgmtSta.h"
#include "pass_phrase.h"
#include "wlpd.h"
#include "KeyApiStaDefs.h"
#include "crypt_new.h"
#include "pmkCache.h"
#include "sha1.h"
#include "md5.h"
#include "rc4.h"
#include "aes_cmac.h"
#include "mrvl_sha256_crypto.h"
#include "keyMgmtSta_rom.h"
#include "tlv.h"
#define DEAUTH_DELAY_TIME_INTERVAL 40000 /* 40 ms */
#define PWK_MSG1_RETRIES 7
/* 10 seconds timeout for completing RSN key handshake */
//#define RSNSECUREDTIMEOUT 10000000
#define RSNSECUREDTIMEOUT MRVDRV_TIMER_10S
//static void SendMICFailReport_sta(cm_ConnectionInfo_t* connPtr,
// keyMgmtInfoSta_t* pKeyMgmtInfoSta,
// BOOLEAN isUnicast);
#if 0
static BufferReturnNotify_t keyMgmtKeyGroupTxDone(phostsa_private priv);
static BufferReturnNotify_t keyMgmtKeyPairwiseTxDone(phostsa_private priv);
static BufferReturnNotify_t keyMgmtKeyPairAndGroupTxDone(phostsa_private priv);
#endif
static void keyMgmtKeyGroupTxDone(phostsa_private priv);
static void keyMgmtKeyPairwiseTxDone(phostsa_private priv);
static void keyMgmtKeyPairAndGroupTxDone(phostsa_private priv);
static supplicantData_t keyMgmt_SuppData[MAX_SUPPLICANT_SESSIONS];
void FillKeyMaterialStruct(phostsa_private priv,
UINT16 key_len, UINT8 isPairwise, KeyData_t *pKey);
void FillGrpKeyMaterialStruct(phostsa_private priv,
UINT16 keyType,
UINT8 *pn,
UINT8 keyIdx, UINT8 keyLen, KeyData_t *pKey);
UINT16 keyMgmtFormatWpaRsnIe(phostsa_private priv,
UINT8 *pos,
IEEEtypes_MacAddr_t *pBssid,
IEEEtypes_MacAddr_t *pStaAddr,
UINT8 *pPmkid, BOOLEAN addPmkid);
t_u8 supplicantIsEnabled(void *priv);
void
allocSupplicantData(void *priv)
{
phostsa_private psapriv = (phostsa_private)priv;
int i = 0;
if (psapriv->suppData) {
return;
}
// if (pm_fns->bss_type == MLAN_BSS_TYPE_STA)
{
// int_sta = os_if_save_EnterCriticalSection();
for (i = 0; i < MAX_SUPPLICANT_SESSIONS; i++) {
if (keyMgmt_SuppData[i].inUse == FALSE) {
keyMgmt_SuppData[i].inUse = TRUE;
supplicantInit((void *)psapriv,
&keyMgmt_SuppData[i]);
psapriv->suppData =
(void *)&keyMgmt_SuppData[i];
break;
}
}
// os_if_save_ExitCriticalSection(int_sta);
// os_ASSERT(connPtr->suppData);
}
}
void
freeSupplicantData(void *priv)
{
phostsa_private psapriv = (phostsa_private)priv;
struct supplicantData *suppData = psapriv->suppData;
if (suppData != NULL) {
suppData->inUse = FALSE;
suppData = NULL;
}
}
mlan_status
initSupplicantTimer(void *priv)
{
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
mlan_status ret = MLAN_STATUS_SUCCESS;
if (util_fns->moal_init_timer(util_fns->pmoal_handle,
&psapriv->suppData->keyMgmtInfoSta.
rsnTimer,
keyMgmtStaRsnSecuredTimeoutHandler,
psapriv) != MLAN_STATUS_SUCCESS) {
ret = MLAN_STATUS_FAILURE;
return ret;
}
return ret;
}
void
freeSupplicantTimer(void *priv)
{
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
if (psapriv->suppData->keyMgmtInfoSta.rsnTimer) {
util_fns->moal_free_timer(util_fns->pmoal_handle,
psapriv->suppData->keyMgmtInfoSta.
rsnTimer);
psapriv->suppData->keyMgmtInfoSta.rsnTimer = NULL;
}
}
//#if defined(PSK_SUPPLICANT) || defined (WPA_NONE)
void
keyMgmtSendDeauth2Peer(phostsa_private priv, UINT16 reason)
{
hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
/* Assumes we are sending to AP */
// keyMgmtSendDeauth((cm_ConnectionInfo_t*)connPtr,
// &((cm_ConnectionInfo_t*)connPtr)->suppData->localBssid,
// reason);
#if 0
ret = wlan_prepare_cmd(priv,
HostCmd_CMD_802_11_DEAUTHENTICATE,
HostCmd_ACT_GEN_SET,
0, NULL, &priv->suppData->localBssid);
if (ret == MLAN_STATUS_SUCCESS)
wlan_recv_event(priv, MLAN_EVENT_ID_DRV_DEFER_HANDLING, MNULL);
#endif
pm_fns->hostsa_StaSendDeauth(pm_fns->pmlan_private,
(t_u8 *)&priv->suppData->localBssid,
reason);
}
BOOLEAN
keyMgmtProcessMsgExt(phostsa_private priv, keyMgmtInfoSta_t *pKeyMgmtInfoSta,
EAPOL_KeyMsg_t *pKeyMsg)
{
if (pKeyMsg->key_info.KeyType && pKeyMsg->key_info.KeyMIC) {
/* PWK Msg #3 processing */
#ifdef DOT11R
if (supplicantAkmWpa2Ft
(priv,
&pKeyMgmtInfoSta->connPtr->suppData->customMIB_RSNConfig.
AKM)) {
if (dot11r_process_pwk_msg3(pKeyMsg) == FALSE) {
return FALSE;
}
}
#endif
#ifdef CCX_MFP
if (ccx_mfp_process_pwk_msg3(pKeyMsg) == FALSE) {
return FALSE;
}
#endif
}
/*
** KDE processing for Msg#3 and for any Group Key rotations
*/
if (pKeyMsg->key_info.EncryptedKeyData) {
#ifdef DOT11W
KDE_t *pKde;
/* Parse IGTK for 11w */
pKde = parseKeyKDE_DataType(priv, pKeyMsg->key_data,
pKeyMsg->key_material_len,
KDE_DATA_TYPE_IGTK);
if (pKde) {
keyMgmtSetIGtk(priv, pKeyMgmtInfoSta,
(IGtkKde_t *)pKde->data, pKde->length);
#if 0
hostEventPrintHex(assocAgent_getConnPtr(),
"SetIGTK", keyMgmtGetIGtk(), 16);
#endif
}
#endif
}
return TRUE;
}
#ifdef WAR_ROM_BUG50312_SIMUL_INFRA_WFD
EAPOL_KeyMsg_t *
patch_ProcessRxEAPOL_GrpMsg1(phostsa_private priv, mlan_buffer *pmbuf,
keyMgmtInfoSta_t *pKeyMgmtInfoSta)
{
hostsa_util_fns *util_fns = &priv->util_fns;
EAPOL_KeyMsg_t *pKeyMsg;
pKeyMsg = GetKeyMsgNonceFromEAPOL(priv, pmbuf, pKeyMgmtInfoSta);
if (!pKeyMsg) {
return NULL;
}
KeyMgmtSta_ApplyKEK(priv, pKeyMsg,
&pKeyMgmtInfoSta->GRKey,
pKeyMgmtInfoSta->EAPOL_Encr_Key);
pKeyMgmtInfoSta->RSNDataTrafficEnabled = 1;
// microTimerStop(pKeyMgmtInfoSta->rsnTimer);
util_fns->moal_stop_timer(util_fns->pmoal_handle,
pKeyMgmtInfoSta->rsnTimer);
// pKeyMgmtInfoSta->rsnTimer = 0;
/* Decrypt the group key */
if (pKeyMsg->desc_type == 2) {
/* WPA2 */
/* handle it according to 802.11i GTK frame format */
parseKeyDataGTK(priv, pKeyMsg->key_data,
pKeyMsg->key_material_len,
&pKeyMgmtInfoSta->GRKey);
if (keyMgmtProcessMsgExt(priv, pKeyMgmtInfoSta, pKeyMsg) ==
FALSE) {
return NULL;
}
} else {
/* WPA or Dynamic WEP */
memcpy(util_fns, pKeyMgmtInfoSta->GRKey.Key,
pKeyMsg->key_data, pKeyMsg->key_material_len);
pKeyMgmtInfoSta->GRKey.KeyIndex = pKeyMsg->key_info.KeyIndex;
}
return pKeyMsg;
}
#endif
#ifdef WAR_ROM_BUG50312_SIMUL_INFRA_WFD
EAPOL_KeyMsg_t *
patch_ProcessRxEAPOL_PwkMsg3(phostsa_private priv, mlan_buffer *pmbuf,
keyMgmtInfoSta_t *pKeyMgmtInfoSta)
{
hostsa_util_fns *util_fns = &priv->util_fns;
EAPOL_KeyMsg_t *pKeyMsg;
pKeyMsg = GetKeyMsgNonceFromEAPOL(priv, pmbuf, pKeyMgmtInfoSta);
if (!pKeyMsg) {
return NULL;
}
pKeyMgmtInfoSta->newPWKey.TxIV16 = 1;
pKeyMgmtInfoSta->newPWKey.TxIV32 = 0;
/* look for group key once the pairwise has been plumbed */
if (pKeyMsg->key_info.EncryptedKeyData) {
/* I think the timer stop should be moved later on in case
ramHook_Process_CCX_MFP_11r returns FALSE */
// microTimerStop(pKeyMgmtInfoSta->rsnTimer);
util_fns->moal_stop_timer(util_fns->pmoal_handle,
pKeyMgmtInfoSta->rsnTimer);
// pKeyMgmtInfoSta->rsnTimer = 0;
KeyMgmtSta_ApplyKEK(priv, pKeyMsg,
&pKeyMgmtInfoSta->GRKey,
pKeyMgmtInfoSta->EAPOL_Encr_Key);
if (keyMgmtProcessMsgExt(priv, pKeyMgmtInfoSta, pKeyMsg) ==
FALSE) {
return NULL;
}
parseKeyDataGTK(priv, pKeyMsg->key_data,
pKeyMsg->key_material_len,
&pKeyMgmtInfoSta->GRKey);
}
return pKeyMsg;
}
#endif
/* This routine must be called after mlmeStaInit_UR
** It assumes that parent session structures are initialized
** (vmacEntry_ur and mlmeStaInfo_URepeater)
*/
void
KeyMgmtInitSta(phostsa_private priv)
{
KeyMgmtSta_InitSession(priv, &priv->suppData->keyMgmtInfoSta);
}
Status_e
GeneratePWKMsg2(phostsa_private priv, mlan_buffer *pmbuf,
UINT8 *pSNonce, UINT8 *pEAPOLMICKey, UINT8 forceKeyDescVersion)
{
hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
EAPOL_KeyMsg_Tx_t *pTxEapol = MNULL;
UINT16 frameLen;
UINT16 packet_len = 0;
BOOLEAN rsnIeAdded = FALSE;
EAPOL_KeyMsg_t *pRxEapol =
(EAPOL_KeyMsg_t *)(pmbuf->pbuf + pmbuf->data_offset +
sizeof(ether_hdr_t));
struct supplicantData *suppData = priv->suppData;
pmlan_buffer newbuf = MNULL;
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
newbuf = pm_fns->hostsa_alloc_mlan_buffer(pm_fns->pmlan_adapter,
MLAN_TX_DATA_BUF_SIZE_2K, 0,
MOAL_MALLOC_BUFFER);
if (newbuf) {
newbuf->bss_index = pmbuf->bss_index;
newbuf->buf_type = pmbuf->buf_type;
newbuf->priority = pmbuf->priority;
newbuf->in_ts_sec = pmbuf->in_ts_sec;
newbuf->in_ts_usec = pmbuf->in_ts_usec;
newbuf->data_offset =
(sizeof(TxPD) + INTF_HEADER_LEN + DMA_ALIGNMENT);
}
if (newbuf == NULL) {
PRINTM(MERROR, "GeneratePWKMsg2 newbuf=NULL\n");
return FAIL;
}
pTxEapol = (EAPOL_KeyMsg_Tx_t *)(newbuf->pbuf + newbuf->data_offset);
KeyMgmtSta_PrepareEAPOLFrame(priv, pTxEapol,
pRxEapol,
(t_u8 *)&suppData->localBssid,
(t_u8 *)&suppData->localStaAddr, pSNonce);
#ifdef DOT11R
if (dot11r_is_ft_akm(&connPtr->suppData->customMIB_RSNConfig.AKM)) {
dot11r_process_pwk_msg2(connPtr, &pTxEapol->keyMsg);
rsnIeAdded = TRUE;
}
#endif
if (!rsnIeAdded && (pTxEapol->keyMsg.desc_type != 1)) {
/* Add the RSN/WPA IE if not dynamic WEP */
pTxEapol->keyMsg.key_material_len
= keyMgmtFormatWpaRsnIe(priv,
(UINT8 *)&pTxEapol->keyMsg.
key_data, &suppData->localBssid,
&suppData->localStaAddr, NULL,
FALSE);
}
#ifdef CCX_MFP
ccx_mfp_process_pwk_msg2(&pTxEapol->keyMsg);
#endif
frameLen = KeyMgmtSta_PopulateEAPOLLengthMic(priv, pTxEapol,
pEAPOLMICKey,
EAPOL_PROTOCOL_V1,
forceKeyDescVersion);
packet_len = frameLen + sizeof(Hdr_8021x_t) + sizeof(ether_hdr_t);
UpdateEAPOLWcbLenAndTransmit(priv, newbuf, packet_len);
PRINTM(MMSG, "LEAVE: %s\n", __FUNCTION__);
return SUCCESS;
}
Status_e
GeneratePWKMsg4(phostsa_private priv, mlan_buffer *pmbuf,
keyMgmtInfoSta_t *pKeyMgmtInfoSta, BOOLEAN groupKeyReceived)
{
hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
struct supplicantData *suppData = priv->suppData;
EAPOL_KeyMsg_Tx_t *pTxEapol;
UINT16 frameLen;
UINT16 packet_len = 0;
EAPOL_KeyMsg_t *pRxEapol =
(EAPOL_KeyMsg_t *)(pmbuf->pbuf + pmbuf->data_offset +
sizeof(ether_hdr_t));
pmlan_buffer newbuf = MNULL;
PRINTM(MMSG, "Enter GeneratePWKMsg4\n");
newbuf = pm_fns->hostsa_alloc_mlan_buffer(pm_fns->pmlan_adapter,
MLAN_TX_DATA_BUF_SIZE_2K, 0,
MOAL_MALLOC_BUFFER);
if (newbuf) {
newbuf->bss_index = pmbuf->bss_index;
newbuf->buf_type = pmbuf->buf_type;
newbuf->priority = pmbuf->priority;
newbuf->in_ts_sec = pmbuf->in_ts_sec;
newbuf->in_ts_usec = pmbuf->in_ts_usec;
newbuf->data_offset =
(sizeof(TxPD) + INTF_HEADER_LEN + DMA_ALIGNMENT);
}
if (newbuf == NULL) {
PRINTM(MERROR, "GeneratePWKMsg4 newbuf=NULL\n");
return FAIL;
}
pTxEapol = (EAPOL_KeyMsg_Tx_t *)(newbuf->pbuf + newbuf->data_offset);
KeyMgmtSta_PrepareEAPOLFrame(priv, pTxEapol,
pRxEapol,
(t_u8 *)&suppData->localBssid,
(t_u8 *)&suppData->localStaAddr, NULL);
frameLen = KeyMgmtSta_PopulateEAPOLLengthMic(priv, pTxEapol,
pKeyMgmtInfoSta->
EAPOL_MIC_Key,
EAPOL_PROTOCOL_V1, 0);
/* Set the BuffDesc free callback so the PSK supplicant can determine
** if the 4th message was successfully received by the AP. Allows
** the supplicant to hold off switching/setting the new key until **
it is sure the AP has acknowledged the handshake completion */
#if 0
if (pKeyMgmtInfoSta->RSNDataTrafficEnabled) {
pBufDesc->isCB = 1;
if (groupKeyReceived) {
pBufDesc->freeCallback = keyMgmtKeyPairAndGroupTxDone;
} else {
pBufDesc->freeCallback = keyMgmtKeyPairwiseTxDone;
}
} else {
#endif
if (groupKeyReceived) {
keyMgmtKeyPairAndGroupTxDone(priv);
} else {
keyMgmtKeyPairwiseTxDone(priv);
}
// }
packet_len =
frameLen + sizeof(Hdr_8021x_t) + sizeof(ether_hdr_t);
UpdateEAPOLWcbLenAndTransmit(priv, newbuf, packet_len);
PRINTM(MMSG, "Leave GeneratePWKMsg4\n");
return SUCCESS;
}
Status_e GenerateGrpMsg2(phostsa_private priv, mlan_buffer *pmbuf,
keyMgmtInfoSta_t *pKeyMgmtInfoSta) {
hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
EAPOL_KeyMsg_t *pRxEapol =
(EAPOL_KeyMsg_t *)(pmbuf->pbuf + pmbuf->data_offset +
sizeof(ether_hdr_t));
EAPOL_KeyMsg_Tx_t *pTxEapol;
UINT16 frameLen;
UINT16 packet_len = 0;
struct supplicantData *suppData = priv->suppData;
pmlan_buffer newbuf = MNULL;
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
newbuf = pm_fns->hostsa_alloc_mlan_buffer(pm_fns->pmlan_adapter,
MLAN_TX_DATA_BUF_SIZE_2K,
0,
MOAL_MALLOC_BUFFER);
if (newbuf) {
newbuf->bss_index = pmbuf->bss_index;
newbuf->buf_type = pmbuf->buf_type;
newbuf->priority = pmbuf->priority;
newbuf->in_ts_sec = pmbuf->in_ts_sec;
newbuf->in_ts_usec = pmbuf->in_ts_usec;
newbuf->data_offset =
(sizeof(TxPD) + INTF_HEADER_LEN +
DMA_ALIGNMENT);
}
if (newbuf == NULL) {
PRINTM(MERROR, "GenerateGrpMsg2 newbuf=NULL\n");
return FAIL;
}
pTxEapol =
(EAPOL_KeyMsg_Tx_t *)(newbuf->pbuf +
newbuf->data_offset);
KeyMgmtSta_PrepareEAPOLFrame(priv, pTxEapol,
pRxEapol,
(t_u8 *)&suppData->localBssid,
(t_u8 *)&suppData->localStaAddr,
NULL);
frameLen = KeyMgmtSta_PopulateEAPOLLengthMic(priv, pTxEapol,
pKeyMgmtInfoSta->
EAPOL_MIC_Key,
EAPOL_PROTOCOL_V1,
0);
// pBufDesc->isCB = 1;
// pBufDesc->freeCallback = keyMgmtKeyGroupTxDone;
keyMgmtKeyGroupTxDone(priv);
packet_len =
frameLen + sizeof(Hdr_8021x_t) + sizeof(ether_hdr_t);
UpdateEAPOLWcbLenAndTransmit(priv, newbuf, packet_len);
PRINTM(MMSG, "LEAVE: %s\n", __FUNCTION__);
return SUCCESS;
}
BOOLEAN KeyMgmtStaHsk_Recvd_PWKMsg1(phostsa_private priv,
mlan_buffer *pmbuf,
IEEEtypes_MacAddr_t *sa,
IEEEtypes_MacAddr_t *da) {
EAPOL_KeyMsg_t *pKeyMsg = NULL;
struct supplicantData *suppData = priv->suppData;
keyMgmtInfoSta_t *pKeyMgmtInfoSta = &suppData->keyMgmtInfoSta;
UINT8 *pPmk;
BOOLEAN msgProcessed;
BOOLEAN genPwkMsg2;
BOOLEAN retval;
UINT32 uMaxRetry = 5; // MAX_SUPPLICANT_INIT_TIMEOUT
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
msgProcessed = FALSE;
genPwkMsg2 = TRUE;
retval = FALSE;
//#ifdef PSK_SUPPLICANT
/* Wait for supplicant data to be initialized, which will
complete after set channel/DPD trainign is complete */
while (uMaxRetry-- && (suppData->suppInitialized != TRUE)) {
// OSATaskSleep(1);
}
//#endif
pKeyMsg = GetKeyMsgNonceFromEAPOL(priv, pmbuf, pKeyMgmtInfoSta);
if (!pKeyMsg) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_PWKMsg1 pKeyMsg is NULL\n");
return FALSE;
}
#ifdef DOT11R
if (!msgProcessed &&
dot11r_is_ft_akm(&connPtr->suppData->customMIB_RSNConfig.
AKM)) {
dot11r_process_pwk_msg1(connPtr, sa, da,
pKeyMgmtInfoSta->SNonce,
pKeyMgmtInfoSta->ANonce);
msgProcessed = TRUE;
retval = TRUE;
}
#endif
#ifdef PSK_SUPPLICANT_CCKM
if (!msgProcessed && ccx_is_cckm_enabled(connPtr)) {
retval = cckm_Recvd_PWKMsg1(connPtr,
sa,
da,
pEAPoLBufDesc,
pKeyMgmtInfoSta->SNonce,
(UINT8 *)connPtr->suppData->
hashSsId.SsId,
connPtr->suppData->hashSsId.
Len);
genPwkMsg2 = FALSE;
msgProcessed = TRUE;
}
#endif
if (!msgProcessed
&& supplicantAkmIsWpaWpa2(priv,
&suppData->customMIB_RSNConfig.
AKM)) {
if (supplicantAkmIsWpaWpa2Psk
(priv, &suppData->customMIB_RSNConfig.AKM)) {
/* Selected AKM Suite is PSK based */
pPmk = pmkCacheFindPSK((void *)priv,
(UINT8 *)suppData->
hashSsId.SsId,
suppData->hashSsId.Len);
} else {
pPmk = pmkCacheFindPMK(priv,
&suppData->localBssid);
}
if (!pPmk) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_PWKMsg1 pPmk is NULL\n");
return FALSE;
}
KeyMgmtSta_DeriveKeys(priv, pPmk,
(UINT8 *)da,
(UINT8 *)sa,
pKeyMgmtInfoSta->ANonce,
pKeyMgmtInfoSta->SNonce,
pKeyMgmtInfoSta->EAPOL_MIC_Key,
pKeyMgmtInfoSta->EAPOL_Encr_Key,
&pKeyMgmtInfoSta->newPWKey,
supplicantAkmUsesKdf(priv,
&suppData->
customMIB_RSNConfig.
AKM));
retval = TRUE;
/* PMKID checking not used by embedded supplicant. **
Commenting out the code in case it needs to be **
readded later. */
#if 0
/* Need to check for PMKID response */
if (pKeyMsg->desc_type == 2) {
if (keyLen) {
KDE_t *pKde;
/* Parse PMKID though it's _not used_
now */
pKde = parseKeyKDE_DataType(pKeyMsg->
key_data,
keyLen,
KDE_DATA_TYPE_PMKID);
if (pKde
&& gcustomMIB_RSNConfig.pmkidValid
&& memcmp(pKde->data,
gcustomMIB_RSNConfig.
PMKID,
sizeof
(gcustomMIB_RSNConfig.
PMKID))) {
/* PMKID could be invalid if
generated based on an ** old
key. A new key should have
been negotiated ** We
should regenerate PMKID and
check it. */
}
}
}
#endif
}
if (genPwkMsg2) {
/* construct Message 2 */
if (GeneratePWKMsg2(priv, pmbuf,
pKeyMgmtInfoSta->SNonce,
pKeyMgmtInfoSta->EAPOL_MIC_Key,
0) != SUCCESS) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_PWKMsg1 GeneratePWKMsg2 Fail\n");
retval = FALSE;
}
}
if (retval == TRUE) {
#ifdef MIB_STATS
INC_MIB_STAT(connPtr, eapolSentFrmFwCnt);
#endif
updateApReplayCounter(priv, pKeyMgmtInfoSta,
(UINT8 *)pKeyMsg->replay_cnt);
pKeyMgmtInfoSta->RSNSecured = FALSE;
}
PRINTM(MMSG, "LEAVE: %s\n", __FUNCTION__);
return retval;
}
EAPOL_KeyMsg_t const *KeyMgmtStaHsk_Recvd_PWKMsg3(phostsa_private priv,
mlan_buffer *pmbuf) {
EAPOL_KeyMsg_t *pKeyMsg;
// cm_ConnectionInfo_t* connPtr = pEAPoLBufDesc->intf.connPtr;
struct supplicantData *suppData = priv->suppData;
keyMgmtInfoSta_t *pKeyMgmtInfoSta = &suppData->keyMgmtInfoSta;
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
#ifdef WAR_ROM_BUG50312_SIMUL_INFRA_WFD
pKeyMsg =
patch_ProcessRxEAPOL_PwkMsg3(pEAPoLBufDesc,
pKeyMgmtInfoSta);
#else
pKeyMsg = ProcessRxEAPOL_PwkMsg3(priv, pmbuf, pKeyMgmtInfoSta);
#endif
if (!pKeyMsg) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_PWKMsg3 pKeyMsg is NULL\n");
return NULL;
}
/* construct Message 4 */
if (GeneratePWKMsg4(priv, pmbuf,
pKeyMgmtInfoSta,
(pKeyMsg->desc_type == 2)) != SUCCESS) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_PWKMsg3 GeneratePWKMsg4 Fail\n");
return pKeyMsg;
}
#ifdef MIB_STATS
INC_MIB_STAT(connPtr, eapolSentFrmFwCnt);
#endif
updateApReplayCounter(priv, pKeyMgmtInfoSta,
(UINT8 *)pKeyMsg->replay_cnt);
PRINTM(MMSG, "LEAVE: %s\n", __FUNCTION__);
return NULL;
}
EAPOL_KeyMsg_t const *KeyMgmtStaHsk_Recvd_GrpMsg1(phostsa_private priv,
mlan_buffer *pmbuf) {
EAPOL_KeyMsg_t *pKeyMsg;
struct supplicantData *suppData = priv->suppData;
keyMgmtInfoSta_t *pKeyMgmtInfoSta = &suppData->keyMgmtInfoSta;
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
#ifdef WAR_ROM_BUG50312_SIMUL_INFRA_WFD
pKeyMsg = patch_ProcessRxEAPOL_GrpMsg1(priv, pKeyMgmtInfoSta);
#else
pKeyMsg = ProcessRxEAPOL_GrpMsg1(priv, pmbuf, pKeyMgmtInfoSta);
#endif
if (!pKeyMsg) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_GrpMsg1 pKeyMsg is NULL\n");
return NULL;
}
/* construct Message Grp Msg2 */
if (GenerateGrpMsg2(priv, pmbuf, pKeyMgmtInfoSta) != SUCCESS) {
PRINTM(MERROR,
"KeyMgmtStaHsk_Recvd_GrpMsg1 GenerateGrpMsg2 Fail\n");
return NULL;
}
#ifdef MIB_STATS
INC_MIB_STAT(connPtr, eapolSentFrmFwCnt);
#endif
updateApReplayCounter(priv, pKeyMgmtInfoSta,
(UINT8 *)pKeyMsg->replay_cnt);
PRINTM(MMSG, "LEAVE: %s\n", __FUNCTION__);
return pKeyMsg;
}
void ProcessKeyMgmtDataSta(phostsa_private priv, mlan_buffer *pmbuf,
IEEEtypes_MacAddr_t *sa,
IEEEtypes_MacAddr_t *da) {
UINT8 retry;
EAPOL_KeyMsg_t *pKeyMsg =
(EAPOL_KeyMsg_t *)(pmbuf->pbuf + pmbuf->data_offset +
sizeof(ether_hdr_t));
retry = 0;
if (pKeyMsg->key_info.KeyType) {
/* PWK */
if (pKeyMsg->key_info.KeyMIC) {
/* 3rd msg in seq */
KeyMgmtStaHsk_Recvd_PWKMsg3(priv, pmbuf);
} else {
while ((KeyMgmtStaHsk_Recvd_PWKMsg1
(priv, pmbuf, sa, da) == FALSE)
&& (retry < PWK_MSG1_RETRIES)) {
/* Delay and retry Msg1 processing in
case failure was ** due to the host
not having time to program a PMK **
yet for 802.1x AKMPs */
// hal_WaitInUs(100);
retry++;
}
// KeyMgmtStaHsk_Recvd_PWKMsg1(priv, pmbuf, sa,
// da);
}
} else {
/* GRP */
if (!KeyMgmtStaHsk_Recvd_GrpMsg1(priv, pmbuf)) {
#if defined(MEF_ENH) && defined(VISTA_802_11_DRIVER_INTERFACE)
hostsleep_initiate_wakeup_with_reason
(WOL_GRP_KEY_REFRESH_ERROR,
WOL_VACUOUS_PATTERN_ID);
#endif
}
}
}
#if 0
/*
** This function send a MIC failure event to the AP
*/
void SendMICFailReport_sta(cm_ConnectionInfo_t * connPtr,
keyMgmtInfoSta_t *pKeyMgmtInfoSta,
BOOLEAN isUnicast) {
EAPOL_KeyMsg_Tx_t *pTxEapol;
UINT16 frameLen;
UINT32 int_sta;
BufferDesc_t *pBufDesc;
if (pKeyMgmtInfoSta->staCounterHi == 0xffffffff
&& pKeyMgmtInfoSta->staCounterLo == 0xffffffff) {
KeyMgmtResetCounter(pKeyMgmtInfoSta);
return;
}
int_sta = os_if_save_EnterCriticalSection();
/* Since there is a MIC failure drop all packets in Tx queue. */
while ((pBufDesc = (BufferDesc_t *) getq(&wlan_data_q)) != NULL) {
/* Do nothing here. We are just dropping the packet **
and releasing the queue. */
mrvl_HandleTxDone(pBufDesc, 0);
}
os_if_save_ExitCriticalSection(int_sta);
pBufDesc = GetTxEAPOLBuffer(connPtr, &pTxEapol, NULL);
if (pBufDesc == NULL) {
return;
}
KeyMgmtSta_PrepareEAPOLMicErrFrame(pTxEapol,
isUnicast,
&connPtr->suppData->
localBssid,
&connPtr->suppData->
localStaAddr,
pKeyMgmtInfoSta);
SetEAPOLKeyDescTypeVersion(pTxEapol,
connPtr->suppData->
customMIB_RSNConfig.wpaType.wpa2,
supplicantAkmUsesKdf(&connPtr->
suppData->
customMIB_RSNConfig.
AKM),
connPtr->suppData->
customMIB_RSNConfig.ucstCipher.ccmp);
if (pKeyMgmtInfoSta->staCounterLo++ == 0) {
pKeyMgmtInfoSta->staCounterHi++;
}
frameLen = KeyMgmtSta_PopulateEAPOLLengthMic(pTxEapol,
pKeyMgmtInfoSta->
EAPOL_MIC_Key,
EAPOL_PROTOCOL_V1,
0);
UpdateEAPOLWcbLenAndTransmit(pBufDesc, frameLen);
}
#endif
#ifdef WAR_ROM_BUG57216_QUIET_TIME_INTERVAL
/* This function assumes that argument state would be either
NO_MIC_FAILURE or FIRST_MIC_FAIL_IN_60_SEC
It must not be called with state othe than these two
*/
#define MIC_ERROR_QUIET_TIME_INTERVAL 60000000 /* 60 sec */
#define MIC_ERROR_CHECK_TIME_INTERVAL 60000000
void KeyMgmtSta_handleMICErr(MIC_Fail_State_e state,
keyMgmtInfoSta_t *pKeyMgmtInfoSta,
MicroTimerCallback_t callback,
UINT8 flags) {
UINT32 expiry;
UINT32 int_save = tx_interrupt_control(TX_INT_DISABLE);
if (state == NO_MIC_FAILURE) {
/* First MIC failure */
pKeyMgmtInfoSta->sta_MIC_Error.status =
FIRST_MIC_FAIL_IN_60_SEC;
expiry = MIC_ERROR_CHECK_TIME_INTERVAL;
} else {
/* Received 2 MIC failures within 60 sec. Do deauth
from AP */
pKeyMgmtInfoSta->sta_MIC_Error.disableStaAsso = 1;
pKeyMgmtInfoSta->sta_MIC_Error.status =
SECOND_MIC_FAIL_IN_60_SEC;
pKeyMgmtInfoSta->apCounterHi = 0;
pKeyMgmtInfoSta->apCounterLo = 0;
expiry = MIC_ERROR_QUIET_TIME_INTERVAL;
}
tx_interrupt_control(int_save);
#if 0
microTimerStop(pKeyMgmtInfoSta->micTimer);
microTimerStart(callback,
(UINT32)pKeyMgmtInfoSta,
expiry, &pKeyMgmtInfoSta->micTimer, flags);
#endif
}
#endif
#if 0
void supplicantMICCounterMeasureInvoke(cm_ConnectionInfo_t * connPtr,
BOOLEAN isUnicast) {
MIC_Fail_State_e state;
keyMgmtInfoSta_t *pKeyMgmtInfoSta =
&connPtr->suppData->keyMgmtInfoSta;
if (pKeyMgmtInfoSta->sta_MIC_Error.MICCounterMeasureEnabled) {
state = pKeyMgmtInfoSta->sta_MIC_Error.status;
/* Watchdog and clear any pending TX packets to ensure
that ** We are able to get a TX buffer */
tx_watchdog_recovery();
SendMICFailReport_sta(connPtr, pKeyMgmtInfoSta,
isUnicast);
switch (state) {
case NO_MIC_FAILURE:
/* Received 1st MIC failure */
/* Noneed to check if timer is active. It will
not be active ** cause this is the first
state */
KeyMgmtSta_handleMICErr(state,
pKeyMgmtInfoSta,
MicErrTimerExp_Sta,
MICRO_TIMER_FLAG_KILL_ON_PS_ENTRY);
connPtr->suppData->customMIB_RSNStats.
TKIPLocalMICFailures++;
break;
case FIRST_MIC_FAIL_IN_60_SEC:
/* Received 2 MIC failures within 60 sec. Do
deauth from AP */
connPtr->suppData->customMIB_RSNStats.
TKIPCounterMeasuresInvoked++;
KeyMgmtSta_handleMICErr(state,
pKeyMgmtInfoSta,
MicErrTimerExp_Sta,
MICRO_TIMER_FLAG_KILL_ON_PS_ENTRY);
/* Is this really needed? */
pKeyMgmtInfoSta->connPtr = connPtr;
KeyMgmtSta_handleMICDeauthTimer(pKeyMgmtInfoSta,
DeauthDelayTimerExp_Sta,
DEAUTH_DELAY_TIME_INTERVAL,
MICRO_TIMER_FLAG_KILL_ON_PS_ENTRY);
break;
case SECOND_MIC_FAIL_IN_60_SEC:
/* No need to do anything. Everything has been
taken care of by ** the above state */
default:
break;
}
}
return;
}
#endif
/*
Start the key Management session
*/
void keyMgmtSta_StartSession(phostsa_private priv,
IEEEtypes_MacAddr_t *pBssid,
IEEEtypes_MacAddr_t *pStaAddr) {
hostsa_util_fns *util_fns = &priv->util_fns;
keyMgmtInfoSta_t *pKeyMgmtInfoSta =
&priv->suppData->keyMgmtInfoSta;
// pKeyMgmtInfoSta->psapriv = priv;
memcpy(util_fns, &priv->suppData->localStaAddr,
pStaAddr, sizeof(priv->suppData->localStaAddr));
memcpy(util_fns, &priv->suppData->localBssid,
pBssid, sizeof(priv->suppData->localBssid));
keyMgmtSta_StartSession_internal(priv, pKeyMgmtInfoSta,
// keyMgmtStaRsnSecuredTimeoutHandler,
RSNSECUREDTIMEOUT, 0); // MICRO_TIMER_FLAG_KILL_ON_PS_ENTRY);
}
void supplicantClrEncryptKey(void *priv) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_mlan_fns *pm_fns = &psapriv->mlan_fns;
pm_fns->hostsa_clr_encrypt_key(psapriv->pmlan_private);
}
UINT32 keyApi_UpdateKeyMaterial(void *priv,
key_MgtMaterial_t *keyMgtData_p) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
hostsa_mlan_fns *pm_fns = &psapriv->mlan_fns;
// UINT8 wepKeyIndex;
mlan_ds_encrypt_key encrypt_key;
t_u8 bcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
memset(util_fns, &encrypt_key, 0, sizeof(mlan_ds_encrypt_key));
PRINTM(MMSG, "keyApi_UpdateKeyMaterial keyType=%x keyLen=%x\n",
keyMgtData_p->keyType, keyMgtData_p->keyLen);
switch (keyMgtData_p->keyType) {
case KEY_TYPE_TKIP:
case KEY_TYPE_AES:
/* The Key Info definition for TKIP and AES is the same
*/
if (keyMgtData_p->keyInfo & KEY_INFO_UNICAST) {
/* Unicast Key */
// SET_KEY_STATE_ENABLED(pwkey,
// (keyMgtData_p->keyInfo
// & KEY_INFO_ENABLED)? TRUE : FALSE);
// pwkey->hdr.keyType = keyMgtData_p->keyType;
// pwkey->hdr.keyDirection =
// KEY_DIRECTION_RXTX;
// pwkey->hdr.keyLen = keyMgtData_p->keyLen;
// if (IS_KEY_STATE_ENABLED(pwkey))
// {
// ramHook_keyApiSta_setConnDataTrafficEnabled(connPtr,
// TRUE);
// ramHook_keyApiSta_setConnCurPktTxEnabled(connPtr,
// TRUE);
// SET_KEY_STATE_FORCE_EAPOL_UNENCRYPTED(pwkey,
// TRUE);
// }
encrypt_key.key_flags |= KEY_FLAG_SET_TX_KEY;
encrypt_key.key_len = keyMgtData_p->keyLen;
memcpy(util_fns, encrypt_key.mac_addr,
psapriv->suppData->localBssid,
MAC_ADDR_SIZE);
/* The Key Material is different */
if (keyMgtData_p->keyLen &&
(keyMgtData_p->keyType == KEY_TYPE_TKIP)) {
/* Update key if included */
memcpy(util_fns,
(void *)encrypt_key.key_material,
(const void *)keyMgtData_p->
keyEncypt.TKIP.key, TK_SIZE);
memcpy(util_fns,
(void *)&encrypt_key.
key_material[TK_SIZE],
(const void *)keyMgtData_p->
keyEncypt.TKIP.txMicKey,
MIC_KEY_SIZE);
memcpy(util_fns,
(void *)&encrypt_key.
key_material[TK_SIZE +
MIC_KEY_SIZE],
(const void *)keyMgtData_p->
keyEncypt.TKIP.rxMicKey,
MIC_KEY_SIZE);
} else if (keyMgtData_p->keyLen &&
(keyMgtData_p->keyType ==
KEY_TYPE_AES)) {
/* Update key if included */
memcpy(util_fns,
(uint8 *)encrypt_key.
key_material,
(uint8 *)keyMgtData_p->keyEncypt.
AES.key, TK_SIZE);
/* duplicate to group key, for adhoc
aes to use. */
// if (!IS_KEY_STATE_ENABLED(gwkey))
// {
/* Multicast Key */
// SET_KEY_STATE_ENABLED(gwkey,
// (keyMgtData_p->keyInfo
// & KEY_INFO_ENABLED) ? TRUE : FALSE);
// gwkey->hdr.keyType =
// keyMgtData_p->keyType;
// gwkey->hdr.keyDirection =
// KEY_DIRECTION_RXTX;
// gwkey->hdr.keyLen =
// keyMgtData_p->keyLen;
// if (IS_KEY_STATE_ENABLED(gwkey))
// {
// gwkey->ckd.tkip_aes.loReplayCounter16
// = 0;
// gwkey->ckd.tkip_aes.hiReplayCounter32
// = 0xffffffff;
// }
// memcpy((uint8*)gwkey->ckd.tkip_aes.key,
// (uint8*)keyMgtData_p->keyEncypt.AES.key,
// TK_SIZE);
// }
}
}
if (keyMgtData_p->keyInfo & KEY_INFO_MULTICAST) {
/* Multicast Key */
// SET_KEY_STATE_ENABLED(gwkey,
// (keyMgtData_p->
// keyInfo & KEY_INFO_ENABLED) ? TRUE :
// FALSE);
// gwkey->hdr.keyType = keyMgtData_p->keyType;
// gwkey->hdr.keyDirection =
// KEY_DIRECTION_RXTX;
// gwkey->hdr.keyLen = keyMgtData_p->keyLen;
// if (IS_KEY_STATE_ENABLED(gwkey))
// {
// gwkey->ckd.tkip_aes.loReplayCounter16 = 0;
// gwkey->ckd.tkip_aes.hiReplayCounter32 =
// 0xffffffff;
// if (!IS_KEY_STATE_ENABLED(pwkey))
// {
// gwkey->ckd.tkip_aes.txIV32 = 0x0;
// gwkey->ckd.tkip_aes.txIV16 = 0x1;
// ramHook_keyApiSta_setConnDataTrafficEnabled(connPtr,
// TRUE);
// ramHook_keyApiSta_setConnCurPktTxEnabled(connPtr,
// TRUE);
// }
// }
encrypt_key.key_flags |= KEY_FLAG_GROUP_KEY;
encrypt_key.key_len = keyMgtData_p->keyLen;
memcpy(util_fns, encrypt_key.mac_addr,
bcast_addr, MAC_ADDR_SIZE);
if (keyMgtData_p->keyLen &&
(keyMgtData_p->keyType == KEY_TYPE_TKIP)) {
/* Update key if included */
memcpy(util_fns,
(void *)encrypt_key.key_material,
(const void *)keyMgtData_p->
keyEncypt.TKIP.key, TK_SIZE);
memcpy(util_fns,
(void *)&encrypt_key.
key_material[TK_SIZE],
(const void *)keyMgtData_p->
keyEncypt.TKIP.txMicKey,
MIC_KEY_SIZE);
memcpy(util_fns,
(void *)&encrypt_key.
key_material[TK_SIZE +
MIC_KEY_SIZE],
(const void *)keyMgtData_p->
keyEncypt.TKIP.rxMicKey,
MIC_KEY_SIZE);
} else if (keyMgtData_p->keyLen &&
(keyMgtData_p->keyType ==
KEY_TYPE_AES)) {
/* Update key if included */
memcpy(util_fns,
(uint8 *)encrypt_key.
key_material,
(uint8 *)keyMgtData_p->keyEncypt.
AES.key, TK_SIZE);
}
}
/**set pn 0*/
memset(util_fns, encrypt_key.pn, 0,
sizeof(encrypt_key.pn));
/**key flag*/
encrypt_key.key_flags |= KEY_FLAG_RX_SEQ_VALID;
// ramHook_keyApi_PalladiumHook1(connPtr);
/**set command to fw update key*/
pm_fns->hostsa_set_encrypt_key((void *)psapriv->
pmlan_private,
&encrypt_key);
break;
#ifndef WAR_ROM_BUG54733_PMF_SUPPORT
case KEY_TYPE_AES_CMAC:
if ( /* NULL != igwkey && */
(keyMgtData_p->
keyInfo & KEY_INFO_MULTICAST_IGTK)) {
/* Multicast Key */
// SET_KEY_STATE_ENABLED(igwkey,
// (keyMgtData_p->keyInfo
// & KEY_INFO_ENABLED) ? TRUE : FALSE);
// igwkey->hdr.keyType = keyMgtData_p->keyType;
// igwkey->hdr.keyDirection =
// KEY_DIRECTION_RXTX;
// igwkey->hdr.keyLen = keyMgtData_p->keyLen;
if (keyMgtData_p->keyLen) {
/* Update IPN if included */
// memcpy((UINT8
// *)&igwkey->ckd.tkip_aes.loReplayCounter16,
// (UINT8
// *)&keyMgtData_p->keyEncypt.iGTK.ipn[0],
// sizeof(igwkey->ckd.tkip_aes.loReplayCounter16));
// memcpy((UINT8
// *)&igwkey->ckd.tkip_aes.hiReplayCounter32,
//
// (UINT8
// *)&keyMgtData_p->keyEncypt.iGTK.ipn[2],
// sizeof(igwkey->ckd.tkip_aes.hiReplayCounter32));
/* Update key if included */
// memcpy((UINT8
// *)igwkey->ckd.tkip_aes.key,
// (UINT8
// *)keyMgtData_p->keyEncypt.iGTK.key,
// CRYPTO_AES_CMAC_KEY_LEN);
memcpy(util_fns,
(uint8 *)encrypt_key.
key_material,
(UINT8 *)keyMgtData_p->keyEncypt.
iGTK.key,
CRYPTO_AES_CMAC_KEY_LEN);
}
/**set pn 0*/
memset(util_fns, encrypt_key.pn, 0,
sizeof(encrypt_key.pn));
/**key flag*/
encrypt_key.key_flags |= KEY_FLAG_RX_SEQ_VALID;
// ramHook_keyApi_PalladiumHook1(connPtr);
/**set command to fw update key*/
pm_fns->hostsa_set_encrypt_key(psapriv->
pmlan_private,
&encrypt_key);
}
break;
#endif
}
return 0;
}
void FillKeyMaterialStruct(phostsa_private priv,
UINT16 key_len,
UINT8 isPairwise, KeyData_t *pKey) {
key_MgtMaterial_t keyMgtData;
#ifdef MIB_STATS
if (isPairwise) {
INC_MIB_STAT(connPtr, PTKSentFrmESUPPCnt);
} else {
INC_MIB_STAT(connPtr, GTKSentFrmESUPPCnt);
}
#endif
FillKeyMaterialStruct_internal(priv, &keyMgtData, key_len,
isPairwise, pKey);
keyApi_UpdateKeyMaterial(priv, &keyMgtData);
}
void FillGrpKeyMaterialStruct(phostsa_private priv,
UINT16 keyType,
UINT8 *pn,
UINT8 keyIdx,
UINT8 keyLen, KeyData_t *pKey) {
hostsa_util_fns *util_fns = &priv->util_fns;
key_MgtMaterial_t keyMgtData;
if (keyType == KDE_DATA_TYPE_IGTK) {
memset(util_fns, (void *)&keyMgtData, 0x00,
sizeof(keyMgtData));
keyMgtData.keyType = KEY_TYPE_AES_CMAC;
keyMgtData.keyInfo =
KEY_INFO_MULTICAST_IGTK | KEY_INFO_ENABLED;
keyMgtData.keyLen = keyLen;
memcpy(util_fns, keyMgtData.keyEncypt.iGTK.ipn, pn,
CRYPTO_AES_CMAC_IPN_LEN);
memcpy(util_fns, keyMgtData.keyEncypt.iGTK.key,
pKey->Key, keyLen);
} else {
FillKeyMaterialStruct_internal(priv, &keyMgtData,
keyLen, FALSE, pKey);
}
keyApi_UpdateKeyMaterial(priv, &keyMgtData);
}
void supplicantInitSession(void *priv,
t_u8 *pSsid,
t_u16 len, t_u8 *pBssid, t_u8 *pStaAddr) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
if (supplicantIsEnabled((void *)psapriv)) {
KeyMgmtInitSta(psapriv);
memcpy(util_fns,
(void *)psapriv->suppData->hashSsId.SsId, pSsid,
len);
psapriv->suppData->hashSsId.Len = len;
keyMgmtSta_StartSession(psapriv,
(IEEEtypes_MacAddr_t *)pBssid,
(IEEEtypes_MacAddr_t *)
pStaAddr);
psapriv->suppData->suppInitialized = TRUE;
}
}
UINT8 supplicantIsCounterMeasuresActive(phostsa_private priv) {
return priv->suppData->keyMgmtInfoSta.sta_MIC_Error.
disableStaAsso;
}
//#endif
void init_customApp_mibs(phostsa_private priv,
supplicantData_t *suppData) {
hostsa_util_fns *util_fns = &priv->util_fns;
memset(util_fns, &suppData->customMIB_RSNStats,
0x00, sizeof(suppData->customMIB_RSNStats));
memset(util_fns, &suppData->customMIB_RSNConfig,
0x00, sizeof(suppData->customMIB_RSNConfig));
/* keep noRsn = 1 as default setting */
suppData->customMIB_RSNConfig.wpaType.noRsn = 1;
}
SecurityMode_t supplicantCurrentSecurityMode(phostsa_private priv) {
return (priv->suppData->customMIB_RSNConfig.wpaType);
}
AkmSuite_t *supplicantCurrentAkmSuite(phostsa_private priv) {
return &priv->suppData->customMIB_RSNConfig.AKM;
}
//#pragma arm section code = ".wlandatapathcode"
t_u8 supplicantIsEnabled(void *priv) {
phostsa_private psapriv = (phostsa_private)priv;
if (psapriv->suppData == NULL) {
return 0;
}
return (psapriv->suppData->customMIB_RSNConfig.RSNEnabled);
}
//#pragma arm section code
void supplicantDisable(void *priv) {
phostsa_private psapriv = (phostsa_private)priv;
if (!supplicantIsEnabled((void *)psapriv)) {
return;
}
psapriv->suppData->customMIB_RSNConfig.RSNEnabled = 0;
init_customApp_mibs(psapriv, psapriv->suppData);
PRINTM(MMSG, "supplicantDisable RSNEnabled=%x\n",
psapriv->suppData->customMIB_RSNConfig.RSNEnabled);
}
void supplicantQueryPassphraseAndEnable(void *priv, t_u8 *pbuf) {
phostsa_private psapriv = (phostsa_private)priv;
pmkElement_t *pPMKElement = MNULL;
mlan_ssid_bssid *ssid_bssid = (mlan_ssid_bssid *)pbuf;
mlan_802_11_ssid *pssid = &ssid_bssid->ssid;
if (psapriv->suppData == NULL)
return;
if (!ssid_bssid)
return;
if (!pssid->ssid_len)
return;
/* extract the PSK from the cache entry */
pPMKElement =
pmkCacheFindPSKElement((void *)psapriv, pssid->ssid,
pssid->ssid_len);
if (pPMKElement)
psapriv->suppData->customMIB_RSNConfig.RSNEnabled = 1;
else
psapriv->suppData->customMIB_RSNConfig.RSNEnabled = 0;
PRINTM(MMSG,
"supplicantQueryPassphraseAndEnable RSNEnabled=%x ssid=%s\n",
psapriv->suppData->customMIB_RSNConfig.RSNEnabled,
pssid->ssid);
}
void supplicantSetAssocRsn(phostsa_private priv,
SecurityMode_t wpaType,
Cipher_t *pMcstCipher,
Cipher_t *pUcstCipher,
AkmSuite_t *pAkm,
IEEEtypes_RSNCapability_t *pRsnCap,
Cipher_t *pGrpMgmtCipher) {
hostsa_util_fns *util_fns = &priv->util_fns;
IEEEtypes_RSNCapability_t rsnCap;
if (pRsnCap == NULL) {
/* It is being added as an IOT workaround for APs that
do not properly handle association requests that omit
* the RSN Capability field in the RSN IE */
memset(util_fns, &rsnCap, 0x00, sizeof(rsnCap));
pRsnCap = &rsnCap;
}
supplicantSetAssocRsn_internal(priv,
&priv->suppData->
customMIB_RSNConfig,
&priv->suppData->currParams,
wpaType, pMcstCipher,
pUcstCipher, pAkm, pRsnCap,
pGrpMgmtCipher);
}
UINT16 keyMgmtFormatWpaRsnIe(phostsa_private priv,
UINT8 *pos,
IEEEtypes_MacAddr_t *pBssid,
IEEEtypes_MacAddr_t *pStaAddr,
UINT8 *pPmkid, BOOLEAN addPmkid) {
struct supplicantData *suppData = priv->suppData;
return keyMgmtFormatWpaRsnIe_internal(priv,
&suppData->
customMIB_RSNConfig, pos,
pBssid, pStaAddr, pPmkid,
addPmkid);
}
static void install_wpa_none_keys(phostsa_private priv,
UINT8 type, UINT8 unicast) {
UINT8 *pPMK;
key_MgtMaterial_t keyMgtData;
pPMK = pmkCacheFindPSK((void *)priv,
(UINT8 *)priv->suppData->hashSsId.SsId,
priv->suppData->hashSsId.Len);
if (pPMK == NULL) {
return;
}
install_wpa_none_keys_internal(priv, &keyMgtData,
pPMK, type, unicast);
keyApi_UpdateKeyMaterial(priv, &keyMgtData);
/* there's no timer or other to initialize */
KeyMgmtInitSta(priv);
priv->suppData->keyMgmtInfoSta.RSNSecured = TRUE;
}
void supplicantInstallWpaNoneKeys(phostsa_private priv) {
if (priv->suppData->customMIB_RSNConfig.RSNEnabled
&& priv->suppData->customMIB_RSNConfig.wpaType.wpaNone) {
install_wpa_none_keys(priv,
priv->suppData->
customMIB_RSNConfig.mcstCipher.
ccmp, 0);
install_wpa_none_keys(priv,
priv->suppData->
customMIB_RSNConfig.mcstCipher.
ccmp, 1);
}
}
void supplicantSetProfile(phostsa_private priv,
SecurityMode_t wpaType,
Cipher_t mcstCipher, Cipher_t ucstCipher) {
priv->suppData->currParams.wpaType = wpaType;
priv->suppData->currParams.mcstCipher = mcstCipher;
priv->suppData->currParams.ucstCipher = ucstCipher;
}
void supplicantGetProfile(phostsa_private priv,
SecurityMode_t *pWpaType,
Cipher_t *pMcstCipher,
Cipher_t *pUcstCipher) {
*pWpaType = priv->suppData->currParams.wpaType;
*pMcstCipher = priv->suppData->currParams.mcstCipher;
*pUcstCipher = priv->suppData->currParams.ucstCipher;
}
void supplicantGetProfileCurrent(phostsa_private priv,
SecurityMode_t *pWpaType,
Cipher_t *pMcstCipher,
Cipher_t *pUcstCipher) {
*pWpaType = priv->suppData->customMIB_RSNConfig.wpaType;
*pMcstCipher = priv->suppData->customMIB_RSNConfig.mcstCipher;
*pUcstCipher = priv->suppData->customMIB_RSNConfig.ucstCipher;
}
void supplicantInit(void *priv, supplicantData_t *suppData) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
init_customApp_mibs(priv, suppData);
memset(util_fns, &suppData->currParams, 0xff,
sizeof(SecurityParams_t));
memset(util_fns, &suppData->keyMgmtInfoSta, 0,
sizeof(keyMgmtInfoSta_t));
suppData->keyMgmtInfoSta.sta_MIC_Error.disableStaAsso = 0;
suppData->keyMgmtInfoSta.sta_MIC_Error.
MICCounterMeasureEnabled = 1;
suppData->keyMgmtInfoSta.sta_MIC_Error.status = NO_MIC_FAILURE;
KeyMgmtResetCounter(&suppData->keyMgmtInfoSta);
}
void supplicantStopSessionTimer(void *priv) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
if (psapriv->suppData == NULL) {
return;
}
if (psapriv->suppData->keyMgmtInfoSta.rsnTimer) {
util_fns->moal_stop_timer(util_fns->pmoal_handle,
psapriv->suppData->
keyMgmtInfoSta.rsnTimer);
// priv->suppData->keyMgmtInfoSta.rsnTimer = 0;
}
}
void supplicantSmeResetNotification(phostsa_private priv) {
supplicantStopSessionTimer(priv);
}
UINT16 keyMgmtGetKeySize(phostsa_private priv, UINT8 isPairwise) {
return keyMgmtGetKeySize_internal(&priv->suppData->
customMIB_RSNConfig,
isPairwise);
}
void keyMgmtSetMICKey(phostsa_private priv, UINT8 *pKey) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, priv->suppData->keyMgmtInfoSta.EAPOL_MIC_Key,
pKey,
sizeof(priv->suppData->keyMgmtInfoSta.EAPOL_MIC_Key));
}
UINT8 *keyMgmtGetMICKey(phostsa_private priv) {
return (priv->suppData->keyMgmtInfoSta.EAPOL_MIC_Key);
}
void keyMgmtSetEAPOLEncrKey(phostsa_private priv, UINT8 *pKey) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, priv->suppData->keyMgmtInfoSta.EAPOL_Encr_Key,
pKey,
sizeof(priv->suppData->keyMgmtInfoSta.EAPOL_Encr_Key));
}
void keyMgmtSetTemporalKeyOnly(phostsa_private priv, UINT8 *pTk) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, &priv->suppData->keyMgmtInfoSta.newPWKey.Key,
pTk,
sizeof(priv->suppData->keyMgmtInfoSta.newPWKey.Key));
}
UINT8 *keyMgmtGetEAPOLEncrKey(phostsa_private priv) {
return (priv->suppData->keyMgmtInfoSta.EAPOL_Encr_Key);
}
void keyMgmtSetPairwiseKey(phostsa_private priv, KeyData_t *pKey) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, &priv->suppData->keyMgmtInfoSta.newPWKey,
pKey, sizeof(priv->suppData->keyMgmtInfoSta.newPWKey));
}
void keyMgmtSetGroupKey(phostsa_private priv, KeyData_t *pKey) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, &priv->suppData->keyMgmtInfoSta.GRKey,
pKey, sizeof(priv->suppData->keyMgmtInfoSta.GRKey));
FillKeyMaterialStruct(priv,
keyMgmtGetKeySize(priv, FALSE), FALSE,
pKey);
}
void keyMgmtSetGtk(phostsa_private priv,
IEEEtypes_GtkElement_t * pGtk, UINT8 *pKek) {
hostsa_util_fns *util_fns = &priv->util_fns;
UINT8 encrKeyLen;
/* Determine the encrypted key field length from the IE length */
encrKeyLen = pGtk->Len - (sizeof(pGtk->KeyInfo) +
sizeof(pGtk->KeyLen) +
sizeof(pGtk->RSC));
MRVL_AesUnWrap(pKek,
2,
encrKeyLen / 8 - 1,
(UINT8 *)pGtk->Key, NULL, (UINT8 *)pGtk->Key);
memcpy(util_fns, &priv->suppData->keyMgmtInfoSta.GRKey.Key,
(UINT8 *)pGtk->Key,
sizeof(priv->suppData->keyMgmtInfoSta.GRKey.Key));
FillGrpKeyMaterialStruct(priv,
KDE_DATA_TYPE_GTK,
pGtk->RSC,
pGtk->KeyInfo.KeyId,
pGtk->KeyLen,
&priv->suppData->keyMgmtInfoSta.GRKey);
}
void keyMgmtSetIGtk(phostsa_private priv,
keyMgmtInfoSta_t *pKeyMgmtInfoSta,
IGtkKde_t *pIGtkKde, UINT8 iGtkKdeLen) {
hostsa_util_fns *util_fns = &priv->util_fns;
UINT8 iGtkLen;
iGtkLen = iGtkKdeLen - 12; /* OUI + dataType + keyId + IPN
= 12 bytes */
memcpy(util_fns, &pKeyMgmtInfoSta->IGtk.Key,
(UINT8 *)pIGtkKde->IGtk,
MIN(sizeof(pKeyMgmtInfoSta->IGtk.Key), iGtkLen));
FillGrpKeyMaterialStruct(priv,
KDE_DATA_TYPE_IGTK,
pIGtkKde->IPN,
pIGtkKde->keyId[0],
iGtkLen, &pKeyMgmtInfoSta->IGtk);
}
UINT8 *keyMgmtGetIGtk(phostsa_private priv) {
return (priv->suppData->keyMgmtInfoSta.IGtk.Key);
}
void keyMgmtPlumbPairwiseKey(phostsa_private priv) {
hostsa_util_fns *util_fns = &priv->util_fns;
memcpy(util_fns, &priv->suppData->keyMgmtInfoSta.PWKey,
&priv->suppData->keyMgmtInfoSta.newPWKey,
sizeof(priv->suppData->keyMgmtInfoSta.PWKey));
FillKeyMaterialStruct(priv,
keyMgmtGetKeySize(priv, TRUE),
TRUE,
&priv->suppData->keyMgmtInfoSta.PWKey);
}
#if 0
#pragma arm section code = ".wlandatapathcode"
void keyMgmtSuccessfulDecryptNotify(cm_ConnectionInfo_t * connPtr,
cipher_key_t *pRxCipherKey) {
if (supplicantIsEnabled(connPtr)) {
connPtr->suppData->keyMgmtInfoSta.pRxDecryptKey =
pRxCipherKey;
if (connPtr->suppData->keyMgmtInfoSta.pRxDecryptKey &&
(!connPtr->suppData->customMIB_RSNConfig.RSNEnabled
|| (connPtr->suppData->customMIB_RSNConfig.
RSNEnabled &&
connPtr->suppData->keyMgmtInfoSta.
pwkHandshakeComplete))) {
SET_KEY_STATE_FORCE_EAPOL_UNENCRYPTED(connPtr->
suppData->
keyMgmtInfoSta.
pRxDecryptKey,
FALSE);
}
} else {
if (pRxCipherKey &&
(!connPtr->cmFlags.RSNEnabled ||
(connPtr->cmFlags.RSNEnabled &&
connPtr->cmFlags.gDataTrafficEnabled))) {
SET_KEY_STATE_FORCE_EAPOL_UNENCRYPTED
(pRxCipherKey, FALSE);
}
}
}
#pragma arm section code
#endif
static void keyMgmtKeyGroupTxDone(phostsa_private priv) {
/*
** if (!pBufDesc || (pBufDesc->rsvd & 0x00FF == 0))
**
** Removed check to verify the 4th message was a success. If we
** miss the ACK from the 4th(WPA2)/2nd(WPA) message, but the AP
** received it, then it won't retry and we will be stuck waiting for
** a session timeout.
**
** Could add back later if we retry the message in case of TX failure.
*/
FillKeyMaterialStruct(priv,
keyMgmtGetKeySize(priv, FALSE),
FALSE,
&priv->suppData->keyMgmtInfoSta.GRKey);
priv->suppData->keyMgmtInfoSta.RSNDataTrafficEnabled = TRUE;
if (priv->suppData->keyMgmtInfoSta.RSNSecured == FALSE) {
priv->suppData->keyMgmtInfoSta.RSNSecured = TRUE;
keyMgmtControlledPortOpen(priv);
}
#ifdef MULTI_CH_SW
chmgr_UnlockCh(connPtr, 0);
#endif
// return NULL;
}
static void keyMgmtKeyPairwiseTxDone(phostsa_private priv) {
/*
** if (!pBufDesc || (pBufDesc->rsvd & 0x00FF == 0))
**
** Removed check to verify the 4th message was a success. If we
** miss the ACK from the 4th(WPA2) message, but the AP
** received it, then it won't retry and we will be stuck waiting for
** a session timeout.
**
** Could add back later if we retry the message in case of TX failure.
*/
keyMgmtPlumbPairwiseKey(priv);
priv->suppData->keyMgmtInfoSta.pwkHandshakeComplete = TRUE;
if (priv->suppData->keyMgmtInfoSta.pRxDecryptKey &&
priv->suppData->keyMgmtInfoSta.pwkHandshakeComplete) {
SET_KEY_STATE_FORCE_EAPOL_UNENCRYPTED(priv->suppData->
keyMgmtInfoSta.
pRxDecryptKey,
FALSE);
}
}
static
void keyMgmtKeyPairAndGroupTxDone(phostsa_private priv) {
keyMgmtKeyPairwiseTxDone(priv);
keyMgmtKeyGroupTxDone(priv);
}
void keyMgmtControlledPortOpen(phostsa_private priv) {
hostsa_mlan_fns *pm_fns = &priv->mlan_fns;
supplicantStopSessionTimer((void *)priv);
pm_fns->Hostsa_StaControlledPortOpen(pm_fns->pmlan_private);
}
#ifdef WAR_ROM_BUG42707_RSN_IE_LEN_CHECK
BOOLEAN patch_supplicantParseRsnIe(phostsa_private priv,
IEEEtypes_RSNElement_t *pRsnIe,
SecurityMode_t *pWpaTypeOut,
Cipher_t *pMcstCipherOut,
Cipher_t *pUcstCipherOut,
AkmSuite_t *pAkmListOut,
UINT8 akmOutMax,
IEEEtypes_RSNCapability_t
*pRsnCapOut,
Cipher_t *pGrpMgmtCipherOut) {
hostsa_util_fns *util_fns = &priv->util_fns;
UINT8 *pIeData;
UINT8 *pIeEnd;
UINT8 *pGrpKeyCipher;
UINT16 pwsKeyCnt;
UINT8 *pPwsKeyCipherList;
UINT16 authKeyCnt;
UINT8 *pAuthKeyList;
IEEEtypes_RSNCapability_t *pRsnCap;
UINT16 *pPMKIDCnt;
UINT8 *pGrpMgmtCipher;
memset(util_fns, pWpaTypeOut, 0x00, sizeof(SecurityMode_t));
pWpaTypeOut->wpa2 = 1;
/* Set the start and end of the IE data */
pIeData = (UINT8 *)&pRsnIe->Ver;
pIeEnd = pIeData + pRsnIe->Len;
/* Skip past the version field */
pIeData += sizeof(pRsnIe->Ver);
/* Parse the group key cipher list */
pGrpKeyCipher = pIeData;
pIeData += sizeof(pRsnIe->GrpKeyCipher);
supplicantParseMcstCipher(priv, pMcstCipherOut, pGrpKeyCipher);
/* Parse the pairwise key cipher list */
memcpy(util_fns, &pwsKeyCnt, pIeData, sizeof(pwsKeyCnt));
pIeData += sizeof(pRsnIe->PwsKeyCnt);
pPwsKeyCipherList = pIeData;
pIeData += pwsKeyCnt * sizeof(pRsnIe->PwsKeyCipherList);
supplicantParseUcstCipher(priv, pUcstCipherOut, pwsKeyCnt,
pPwsKeyCipherList);
/* Parse and return the AKM list */
memcpy(util_fns, &authKeyCnt, pIeData, sizeof(authKeyCnt));
pIeData += sizeof(pRsnIe->AuthKeyCnt);
pAuthKeyList = pIeData;
pIeData += authKeyCnt * sizeof(pRsnIe->AuthKeyList);
memset(util_fns, pAkmListOut, 0x00,
akmOutMax * sizeof(AkmSuite_t));
memcpy(util_fns, pAkmListOut, pAuthKeyList,
MIN(authKeyCnt,
akmOutMax) * sizeof(pRsnIe->AuthKeyList));
/* Check if the RSN Capability is included */
if (pIeData < pIeEnd) {
pRsnCap = (IEEEtypes_RSNCapability_t *)pIeData;
pIeData += sizeof(pRsnIe->RsnCap);
if (pRsnCapOut) {
memcpy(util_fns, pRsnCapOut, pRsnCap,
sizeof(IEEEtypes_RSNCapability_t));
}
}
/* Check if the PMKID count is included */
if (pIeData < pIeEnd) {
pPMKIDCnt = (UINT16 *)pIeData;
pIeData += sizeof(pRsnIe->PMKIDCnt);
/* Check if the PMKID List is included */
if (pIeData < pIeEnd) {
/* pPMKIDList = pIeData; <-- Currently not used
in parsing */
pIeData +=
*pPMKIDCnt * sizeof(pRsnIe->PMKIDList);
}
}
/* Check if the Group Mgmt Cipher is included */
if (pIeData < pIeEnd) {
pGrpMgmtCipher = pIeData;
if (pGrpMgmtCipherOut) {
memcpy(util_fns, pGrpMgmtCipherOut,
pGrpMgmtCipher,
sizeof(pRsnIe->GrpMgmtCipher));
}
}
return TRUE;
}
#endif
//#pragma arm section code = ".init"
void keyMgmtSta_RomInit(void) {
//#if defined(PSK_SUPPLICANT) || defined (WPA_NONE)
// ramHook_keyMgmtProcessMsgExt = keyMgmtProcessMsgExt;
// ramHook_keyMgmtSendDeauth = keyMgmtSendDeauth2Peer;
//#endif
#ifdef WAR_ROM_BUG42707_RSN_IE_LEN_CHECK
supplicantParseRsnIe_hook = patch_supplicantParseRsnIe;
#endif
}
//#pragma arm section code
#if defined(BTAMP)
UINT8 *parseKeyDataField(cm_ConnectionInfo_t * connPtr,
UINT8 *pKey, UINT16 len) {
keyMgmtInfoSta_t *pKeyMgmtInfoSta;
KDE_t *pKde;
pKeyMgmtInfoSta = &connPtr->suppData->keyMgmtInfoSta;
/* parse KDE GTK */
pKde = parseKeyDataGTK(pKey, len, &pKeyMgmtInfoSta->GRKey);
/* Parse PMKID though it's _not used_ now */
pKde = parseKeyKDE_DataType(pKey, len, KDE_DATA_TYPE_PMKID);
if (pKde) {
/* PMKID KDE */
return (UINT8 *)pKde->data;
}
return NULL;
}
/* Add RSN IE to a frame body */
UINT16 btampAddRsnIe(cm_ConnectionInfo_t * connPtr,
IEEEtypes_RSNElement_t *pRsnIe) {
const uint8 wpa2_psk[4] = { 0x00, 0x0f, 0xac, 0x02 }; /* WPA2
PSK */
UINT16 ieSize;
IEEEtypes_RSNCapability_t rsncap;
SecurityMode_t securityMode;
Cipher_t mcstWpa2;
Cipher_t ucstWpa2;
AkmSuite_t *pAkmWpa2;
memset(util_fns, &securityMode, 0x00, sizeof(securityMode));
memset(util_fns, &mcstWpa2, 0x00, sizeof(mcstWpa2));
memset(util_fns, &ucstWpa2, 0x00, sizeof(ucstWpa2));
memset(util_fns, &rsncap, 0, sizeof(rsncap));
mcstWpa2.ccmp = 1;
ucstWpa2.ccmp = 1;
securityMode.wpa2 = 1;
pAkmWpa2 = (AkmSuite_t *)wpa2_psk;
supplicantSetProfile(connPtr, securityMode, mcstWpa2, ucstWpa2);
supplicantSetAssocRsn(connPtr, securityMode, &mcstWpa2,
&ucstWpa2, pAkmWpa2, &rsncap, NULL);
ieSize = keyMgmtFormatWpaRsnIe(connPtr,
(UINT8 *)pRsnIe,
NULL, NULL, NULL, FALSE);
return ieSize;
}
#endif
#if 0
void supplicantParseAndFormatRsnIe(phostsa_private priv,
IEEEtypes_RSNElement_t *pRsnIe,
SecurityMode_t *pWpaTypeOut,
Cipher_t *pMcstCipherOut,
Cipher_t *pUcstCipherOut,
AkmSuite_t *pAkmListOut,
UINT8 akmOutMax,
IEEEtypes_RSNCapability_t
*pRsnCapOut,
Cipher_t *pGrpMgmtCipherOut) {
hostsa_util_fns *util_fns = &priv->util_fns;
UINT8 *pIeData;
UINT8 *pIeEnd;
UINT8 *pGrpKeyCipher;
UINT16 pwsKeyCnt;
UINT8 *pPwsKeyCipherList;
UINT16 authKeyCnt;
UINT8 *pAuthKeyList;
IEEEtypes_RSNCapability_t *pRsnCap;
UINT16 *pPMKIDCnt;
UINT8 *pGrpMgmtCipher;
//longl add
UINT8 *pos = NULL;
UINT8 cp_size = 0;
#if 0
#if !defined(REMOVE_PATCH_HOOKS)
if (supplicantParseRsnIe_hook(pRsnIe,
pWpaTypeOut,
pMcstCipherOut,
pUcstCipherOut,
pAkmListOut,
akmOutMax,
pRsnCapOut, pGrpMgmtCipherOut)) {
return;
}
#endif
#endif
memset(util_fns, pWpaTypeOut, 0x00, sizeof(SecurityMode_t));
memset(util_fns, (UINT8 *)priv->suppData->wpa_rsn_ie, 0x00,
MAX_IE_SIZE);
pos = (UINT8 *)priv->suppData->wpa_rsn_ie;
pWpaTypeOut->wpa2 = 1;
/* Set the start and end of the IE data */
pIeData = (UINT8 *)&pRsnIe->Ver;
pIeEnd = pIeData + pRsnIe->Len;
/* Skip past the version field */
pIeData += sizeof(pRsnIe->Ver);
/* Parse the group key cipher list */
pGrpKeyCipher = pIeData;
pIeData += sizeof(pRsnIe->GrpKeyCipher);
supplicantParseMcstCipher(priv, pMcstCipherOut, pGrpKeyCipher);
cp_size = pIeData - (UINT8 *)pRsnIe;
memcpy(util_fns, pos, (UINT8 *)pRsnIe, cp_size);
pos += cp_size;
/* Parse the pairwise key cipher list */
memcpy(util_fns, &pwsKeyCnt, pIeData, sizeof(pwsKeyCnt));
pIeData += sizeof(pRsnIe->PwsKeyCnt);
if (pwsKeyCnt > 0) {
(*(UINT16 *)pos) = (UINT16)1;
pos += sizeof(UINT16);
}
pPwsKeyCipherList = pIeData;
pIeData += pwsKeyCnt * sizeof(pRsnIe->PwsKeyCipherList);
supplicantParseUcstCipher(priv, pUcstCipherOut, pwsKeyCnt,
pPwsKeyCipherList);
if (pUcstCipherOut->ccmp == 1) {
memcpy(util_fns, pos, wpa2_oui04, sizeof(wpa2_oui04));
pos += sizeof(wpa2_oui04);
} else if (pUcstCipherOut->tkip == 1) {
memcpy(util_fns, pos, wpa2_oui02, sizeof(wpa2_oui02));
pos += sizeof(wpa2_oui02);
}
if ((pUcstCipherOut->ccmp == 1) && (pUcstCipherOut->tkip == 1))
pUcstCipherOut->tkip = 0;
cp_size = pIeEnd - pIeData;
memcpy(util_fns, pos, pIeData, cp_size);
pos += cp_size;
((IEEEtypes_RSNElement_t *)(priv->suppData->wpa_rsn_ie))->Len =
pos - (UINT8 *)priv->suppData->wpa_rsn_ie -
sizeof(IEEEtypes_InfoElementHdr_t);
/* Parse and return the AKM list */
memcpy(util_fns, &authKeyCnt, pIeData, sizeof(authKeyCnt));
pIeData += sizeof(pRsnIe->AuthKeyCnt);
pAuthKeyList = pIeData;
pIeData += authKeyCnt * sizeof(pRsnIe->AuthKeyList);
memset(util_fns, pAkmListOut, 0x00,
akmOutMax * sizeof(AkmSuite_t));
memcpy(util_fns, pAkmListOut, pAuthKeyList,
MIN(authKeyCnt,
akmOutMax) * sizeof(pRsnIe->AuthKeyList));
DBG_HEXDUMP(MCMD_D, " pAuthKeyList",
(t_u8 *)pAuthKeyList, MIN(authKeyCnt,
akmOutMax) *
sizeof(pRsnIe->AuthKeyList));
DBG_HEXDUMP(MCMD_D, " pAuthKeyList", (t_u8 *)pAkmListOut,
MIN(authKeyCnt,
akmOutMax) * sizeof(pRsnIe->AuthKeyList));
/* Check if the RSN Capability is included */
if (pIeData < pIeEnd) {
pRsnCap = (IEEEtypes_RSNCapability_t *)pIeData;
pIeData += sizeof(pRsnIe->RsnCap);
if (pRsnCapOut) {
memcpy(util_fns, pRsnCapOut, pRsnCap,
sizeof(IEEEtypes_RSNCapability_t));
}
}
/* Check if the PMKID count is included */
if (pIeData < pIeEnd) {
pPMKIDCnt = (UINT16 *)pIeData;
pIeData += sizeof(pRsnIe->PMKIDCnt);
/* Check if the PMKID List is included */
if (pIeData < pIeEnd) {
/* pPMKIDList = pIeData; <-- Currently not used
in parsing */
pIeData +=
*pPMKIDCnt * sizeof(pRsnIe->PMKIDList);
}
}
/* Check if the Group Mgmt Cipher is included */
if (pIeData < pIeEnd) {
pGrpMgmtCipher = pIeData;
if (pGrpMgmtCipherOut) {
memcpy(util_fns, pGrpMgmtCipherOut,
pGrpMgmtCipher,
sizeof(pRsnIe->GrpMgmtCipher));
}
}
}
void supplicantParseAndFormatWpaIe(phostsa_private priv,
IEEEtypes_WPAElement_t *pIe,
SecurityMode_t *pWpaType,
Cipher_t *pMcstCipher,
Cipher_t *pUcstCipher,
AkmSuite_t *pAkmList,
UINT8 akmOutMax) {
hostsa_util_fns *util_fns = &priv->util_fns;
IEEEtypes_WPAElement_t *pTemp = pIe;
int count;
int akmCount = akmOutMax;
AkmSuite_t *pAkm = pAkmList;
UINT8 *pos = NULL;
UINT8 cp_size = 0;
UINT8 *pIeEnd =
(UINT8 *)pIe + sizeof(IEEEtypes_InfoElementHdr_t) +
pIe->Len;
PRINTM(MMSG, "ENTER: %s\n", __FUNCTION__);
memset(util_fns, pMcstCipher, 0x00, sizeof(Cipher_t));
memset(util_fns, pUcstCipher, 0x00, sizeof(Cipher_t));
memset(util_fns, pAkmList, 0x00,
akmOutMax * sizeof(AkmSuite_t));
memset(util_fns, pWpaType, 0x00, sizeof(SecurityMode_t));
memset(util_fns, (UINT8 *)priv->suppData->wpa_rsn_ie, 0x00,
MAX_IE_SIZE);
pos = (UINT8 *)priv->suppData->wpa_rsn_ie;
pWpaType->wpa = 1;
/* record the AP's multicast cipher */
if (!memcmp
(util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui02,
sizeof(wpa_oui02))) {
/* WPA TKIP */
pMcstCipher->tkip = 1;
} else if (!memcmp
(util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui04,
sizeof(wpa_oui04))) {
/* WPA AES */
pMcstCipher->ccmp = 1;
} else if (!memcmp
(util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui01,
sizeof(wpa_oui01))) {
/* WPA WEP 40 */
pMcstCipher->wep40 = 1;
} else if (!memcmp
(util_fns, (char *)pTemp->GrpKeyCipher, wpa_oui05,
sizeof(wpa_oui05))) {
/* WPA WEP 104 */
pMcstCipher->wep104 = 1;
}
cp_size = (UINT8 *)(&pTemp->PwsKeyCnt) - (UINT8 *)pIe;
memcpy(util_fns, pos, (UINT8 *)pIe, cp_size);
pos += cp_size;
count = pTemp->PwsKeyCnt;
if (count > 0) {
(*(UINT16 *)pos) = (UINT16)1;
pos += sizeof(UINT16);
}
while (count) {
/* record the AP's unicast cipher */
if (!memcmp(util_fns, (char *)pTemp->PwsKeyCipherList,
wpa_oui02, sizeof(wpa_oui02))) {
/* WPA TKIP */
pUcstCipher->tkip = 1;
} else if (!memcmp
(util_fns, (char *)pTemp->PwsKeyCipherList,
wpa_oui04, sizeof(wpa_oui04))) {
/* WPA AES */
pUcstCipher->ccmp = 1;
}
count--;
if (count) {
pTemp = (IEEEtypes_WPAElement_t *)((UINT8 *)
pTemp +
sizeof
(pTemp->
PwsKeyCipherList));
}
}
if (pUcstCipher->ccmp == 1) {
memcpy(util_fns, pos, wpa_oui04, sizeof(wpa_oui04));
pos += sizeof(wpa_oui04);
} else if (pUcstCipher->tkip == 1) {
memcpy(util_fns, pos, wpa_oui02, sizeof(wpa_oui02));
pos += sizeof(wpa_oui02);
}
if ((pUcstCipher->ccmp == 1) && (pUcstCipher->tkip == 1))
pUcstCipher->tkip = 0;
cp_size = pIeEnd - (UINT8 *)(&pTemp->AuthKeyCnt);
memcpy(util_fns, pos, &pTemp->AuthKeyCnt, cp_size);
pos += cp_size;
((IEEEtypes_RSNElement_t *)(priv->suppData->wpa_rsn_ie))->Len =
pos - (UINT8 *)priv->suppData->wpa_rsn_ie -
sizeof(IEEEtypes_InfoElementHdr_t);
count = pTemp->AuthKeyCnt;
while (count) {
if (akmCount) {
/* Store the AKM */
memcpy(util_fns, pAkm,
(char *)pTemp->AuthKeyList,
sizeof(pTemp->AuthKeyList));
pAkm++;
akmCount--;
}
count--;
if (count) {
pTemp = (IEEEtypes_WPAElement_t *)((UINT8 *)
pTemp +
sizeof
(pTemp->
AuthKeyList));
}
}
if (!memcmp
(util_fns, pAkmList, wpa_oui_none, sizeof(wpa_oui_none))) {
pWpaType->wpaNone = 1;
}
}
#endif
void *processRsnWpaInfo(void *priv, void *prsnwpa_ie) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
Cipher_t mcstCipher;
Cipher_t ucstCipher;
SecurityMode_t wpaType;
AkmSuite_t akmList[AKM_SUITE_MAX];
IEEEtypes_RSNCapability_t rsnCap;
t_u8 type =
((IEEEtypes_InfoElementHdr_t *)prsnwpa_ie)->ElementId;
if (supplicantIsEnabled((void *)psapriv)) {
memset(util_fns, &wpaType, 0x00, sizeof(wpaType));
if (type == ELEM_ID_RSN ||
type == ELEM_ID_VENDOR_SPECIFIC) {
if (type == ELEM_ID_RSN) {
supplicantParseRsnIe(psapriv,
(IEEEtypes_RSNElement_t
*)prsnwpa_ie,
&wpaType,
&mcstCipher,
&ucstCipher,
akmList,
NELEMENTS(akmList),
&rsnCap, NULL);
} else if (type == ELEM_ID_VENDOR_SPECIFIC) {
supplicantParseWpaIe(psapriv,
(IEEEtypes_WPAElement_t
*)prsnwpa_ie,
&wpaType,
&mcstCipher,
&ucstCipher,
akmList,
NELEMENTS
(akmList));
}
if (wpaType.wpa2 || wpaType.wpa) {
memset(util_fns, &rsnCap, 0x00,
sizeof(rsnCap));
supplicantSetProfile(psapriv, wpaType,
mcstCipher,
ucstCipher);
supplicantSetAssocRsn(psapriv,
wpaType,
&mcstCipher,
&ucstCipher,
akmList,
&rsnCap, NULL);
memset(util_fns,
(UINT8 *)psapriv->suppData->
wpa_rsn_ie, 0x00, MAX_IE_SIZE);
if (keyMgmtFormatWpaRsnIe
(psapriv,
(UINT8 *)&psapriv->suppData->
wpa_rsn_ie,
&psapriv->suppData->localBssid,
&psapriv->suppData->localStaAddr,
NULL, FALSE)) ;
return (void *)(psapriv->suppData->
wpa_rsn_ie);
}
}
}
return NULL;
}
t_u8 supplicantFormatRsnWpaTlv(void *priv, void *rsn_wpa_ie,
void *rsn_ie_tlv) {
phostsa_private psapriv = (phostsa_private)priv;
hostsa_util_fns *util_fns = &psapriv->util_fns;
void *supp_rsn_wpa_ie = NULL;
MrvlIEGeneric_t *prsn_ie = (MrvlIEGeneric_t *)rsn_ie_tlv;
t_u8 total_len = 0;
if (rsn_wpa_ie) {
supp_rsn_wpa_ie =
processRsnWpaInfo((void *)psapriv, rsn_wpa_ie);
if (!supp_rsn_wpa_ie)
return total_len;
/* WPA_IE or RSN_IE */
prsn_ie->IEParam.Type =
(t_u16)(((IEEEtypes_InfoElementHdr_t *)
supp_rsn_wpa_ie)->ElementId);
prsn_ie->IEParam.Type = prsn_ie->IEParam.Type & 0x00FF;
prsn_ie->IEParam.Type =
wlan_cpu_to_le16(prsn_ie->IEParam.Type);
prsn_ie->IEParam.Length =
(t_u16)(((IEEEtypes_InfoElementHdr_t *)
supp_rsn_wpa_ie)->Len);
prsn_ie->IEParam.Length =
prsn_ie->IEParam.Length & 0x00FF;
if (prsn_ie->IEParam.Length <= MAX_IE_SIZE) {
memcpy(util_fns,
rsn_ie_tlv + sizeof(prsn_ie->IEParam),
(t_u8 *)supp_rsn_wpa_ie +
sizeof(IEEEtypes_InfoElementHdr_t),
prsn_ie->IEParam.Length);
} else
return total_len;
HEXDUMP("ASSOC_CMD: RSN IE", (t_u8 *)rsn_ie_tlv,
sizeof(prsn_ie->IEParam) +
prsn_ie->IEParam.Length);
total_len +=
sizeof(prsn_ie->IEParam) +
prsn_ie->IEParam.Length;
prsn_ie->IEParam.Length =
wlan_cpu_to_le16(prsn_ie->IEParam.Length);
}
return total_len;
}