/** @file keyMgmtSta.c
|
*
|
* @brief This file defines key management API for sta
|
* Copyright (C) 2014-2017, 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) {
|
//Not install same iGtk
|
if (!memcmp(&priv->util_fns,
|
pKeyMgmtInfoSta->IGtk.Key,
|
(UINT8 *)(((IGtkKde_t *)pKde->data)->IGtk),
|
MIN(sizeof(pKeyMgmtInfoSta->IGtk.Key),
|
(pKde->length - 12)))) {
|
return TRUE;
|
} else {
|
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;
|
KeyData_t GRKey;
|
|
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, &GRKey);
|
/* Not install same GTK */
|
if (!memcmp
|
(util_fns, pKeyMgmtInfoSta->GRKey.Key, GRKey.Key,
|
TK_SIZE)) {
|
priv->gtk_installed = 1;
|
} else {
|
memcpy(util_fns, &pKeyMgmtInfoSta->GRKey, &GRKey,
|
sizeof(KeyData_t));
|
pKeyMgmtInfoSta->GRKey.TxIV16 = GRKey.TxIV16;
|
pKeyMgmtInfoSta->GRKey.TxIV32 = 0xFFFFFFFF;
|
priv->gtk_installed = 0;
|
}
|
|
if (keyMgmtProcessMsgExt(priv, pKeyMgmtInfoSta, pKeyMsg) ==
|
FALSE) {
|
return NULL;
|
}
|
} else {
|
/* WPA or Dynamic WEP */
|
if (!memcmp
|
(util_fns, pKeyMgmtInfoSta->GRKey.Key, pKeyMsg->key_data,
|
pKeyMsg->key_material_len)) {
|
priv->gtk_installed = 1;
|
} else {
|
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;
|
UINT8 intf_hr_len =
|
pm_fns->Hostsa_get_intf_hr_len(pm_fns->pmlan_private);
|
|
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_hr_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;
|
UINT8 intf_hr_len =
|
pm_fns->Hostsa_get_intf_hr_len(pm_fns->pmlan_private);
|
|
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_hr_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);
|
}
|
#if 0
|
}
|
#endif
|
|
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;
|
UINT8 intf_hr_len =
|
pm_fns->Hostsa_get_intf_hr_len(pm_fns->pmlan_private);
|
|
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_hr_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 = NULL;
|
|
if (!psapriv)
|
return;
|
|
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;
|
psapriv->gtk_installed = 0;
|
}
|
}
|
|
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 || 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 || 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 = NULL;
|
|
if (!psapriv || psapriv->suppData == NULL) {
|
return;
|
}
|
|
util_fns = &psapriv->util_fns;
|
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 (priv->gtk_installed)
|
return;
|
/*
|
** 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 (!priv->suppData->keyMgmtInfoSta.pwkHandshakeComplete) {
|
/*
|
** 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)
|
{
|
if (!priv->suppData->keyMgmtInfoSta.pwkHandshakeComplete) {
|
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;
|
}
|