| /** @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; |
| } |