From 83622ef789a274595f414d5994e2c6f31ebc2d5e Mon Sep 17 00:00:00 2001 From: Naveen Rawat Date: Wed, 25 Nov 2015 16:27:41 -0800 Subject: [PATCH] qcacld-3.0: For LFR 3, save reassoc frame sent OTA by firmware In LFR3 reassoc frame is sent by firmware and host or supplicant is not aware of its content. Because of this supplicant does not have complete information to perform EAP exchange with authenticator if fresh EAP exchange is requested. To fix this: 1) Take the reassoc req frame passed by firmware and save that to pe session This frame will then be passed to supplicant through usual path. 2) In case of FT connection, do not pass key replay counter attribute to supplicant. Change-Id: I51dd8004c910b45c7f25e9cd140448e592b096b3 CRs-Fixed: 943711 --- core/hdd/src/wlan_hdd_assoc.c | 26 ++++++++++++++++++++++++- core/hdd/src/wlan_hdd_cfg80211.c | 33 ++++++++++++++++++++++---------- core/mac/inc/sir_api.h | 2 ++ core/mac/src/pe/lim/lim_api.c | 25 ++++++++++++++++++++++++ core/wma/src/wma_scan_roam.c | 30 ++++++++++++++++++++++++++--- 5 files changed, 102 insertions(+), 14 deletions(-) diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index e69f3c725c31..2c09426a1b48 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -1368,6 +1368,7 @@ static void hdd_send_re_assoc_event(struct net_device *dev, unsigned int len = 0; u8 *pFTAssocRsp = NULL; uint8_t *rspRsnIe = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); + uint8_t *assoc_req_ies = kmalloc(IW_GENERIC_IE_MAX, GFP_KERNEL); uint32_t rspRsnLength = 0; struct ieee80211_channel *chan; hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); @@ -1383,6 +1384,10 @@ static void hdd_send_re_assoc_event(struct net_device *dev, return; } + if (!assoc_req_ies) { + hdd_err("Unable to allocate Assoc Req IE"); + return; + } if (pCsrRoamInfo == NULL) { hddLog(LOGE, FL("Invalid CSR roam info")); goto done; @@ -1462,14 +1467,24 @@ static void hdd_send_re_assoc_event(struct net_device *dev, final_req_ie, (ssid_ie_len + reqRsnLength), rspRsnIe, rspRsnLength, GFP_KERNEL); + cdf_mem_copy(assoc_req_ies, + (u8 *)pCsrRoamInfo->pbFrames + pCsrRoamInfo->nBeaconLength, + pCsrRoamInfo->nAssocReqLength); + + hdd_notice("ReAssoc Req IE dump"); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_DEBUG, + assoc_req_ies, pCsrRoamInfo->nAssocReqLength); + wlan_hdd_send_roam_auth_event(pHddCtx, pCsrRoamInfo->bssid.bytes, - reqRsnIe, reqRsnLength, rspRsnIe, rspRsnLength, + assoc_req_ies, pCsrRoamInfo->nAssocReqLength, + rspRsnIe, rspRsnLength, pCsrRoamInfo); done: sme_roam_free_connect_profile(hal_handle, &roam_profile); if (final_req_ie) kfree(final_req_ie); kfree(rspRsnIe); + kfree(assoc_req_ies); } /** @@ -1967,6 +1982,15 @@ defined(FEATURE_WLAN_LFR) "assocReqlen %d assocRsplen %d", assocReqlen, assocRsplen); + + hdd_notice( + "Reassoc Req IE dump"); + CDF_TRACE_HEX_DUMP( + CDF_MODULE_ID_HDD, + CDF_TRACE_LEVEL_DEBUG, + pFTAssocReq, + assocReqlen); + cfg80211_roamed(dev, chan, pRoamInfo-> bssid.bytes, diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index aa2004dc00ee..8d830a3cbc0d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3047,16 +3047,29 @@ int wlan_hdd_send_roam_auth_event(hdd_context_t *hdd_ctx_ptr, uint8_t *bssid, if (roam_info_ptr->synchAuthStatus == CSR_ROAM_AUTH_STATUS_AUTHENTICATED) { hddLog(CDF_TRACE_LEVEL_DEBUG, FL("Include Auth Params TLV's")); - if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, - true) || - nla_put(skb, - QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, - SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr) - || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, - SIR_KCK_KEY_LEN, roam_info_ptr->kck) - || nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, - SIR_KEK_KEY_LEN, roam_info_ptr->kek)) { - hddLog(CDF_TRACE_LEVEL_ERROR, FL("nla put fail")); + if (nla_put_u8(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, true)) { + hdd_err("nla put fail"); + goto nla_put_failure; + } + /* if FT connection: dont send ROAM_AUTH_KEY_REPLAY_CTR */ + if (roam_info_ptr->u.pConnectedProfile->AuthType != + eCSR_AUTH_TYPE_FT_RSN && + roam_info_ptr->u.pConnectedProfile->AuthType != + eCSR_AUTH_TYPE_FT_RSN_PSK && + nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, + SIR_REPLAY_CTR_LEN, roam_info_ptr->replay_ctr)) { + hdd_err("non FT connection."); + hdd_err("failed to send replay counter."); + goto nla_put_failure; + } + if (nla_put(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, + SIR_KCK_KEY_LEN, roam_info_ptr->kck) || + nla_put(skb, + QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, + SIR_KEK_KEY_LEN, roam_info_ptr->kek)) { + hdd_err("nla put fail"); goto nla_put_failure; } } else { diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index d0c794834bf3..d41818245bca 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -3941,6 +3941,8 @@ typedef struct sSirSmeRoamOffloadSynchInd { uint16_t beaconProbeRespLength; uint16_t reassocRespOffset; uint16_t reassocRespLength; + uint16_t reassoc_req_offset; + uint16_t reassoc_req_length; uint8_t isBeacon; uint8_t roamedVdevId; struct cdf_mac_addr bssid; diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 2a2134ad58fd..af61ed339e0e 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2036,6 +2036,31 @@ void lim_roam_offload_synch_ind(tpAniSirGlobal pMac, tpSirMsgQ pMsg) /* Prepare the session right now with as much as possible */ lim_fill_ft_session(pMac, bss_desc_ptr, ft_session_ptr, session_ptr); + + if (ft_session_ptr->assocReqLen) { + /* + * For LFR3 the Assoc Request frame was sent by firmware, hence + * pe session struct does not have corresponding IEs. Firmware + * sends whole ASSOC req frame upto host in Roam Sync Event. + * Copy this frame pe session's buffer, so that it can follow + * LFR2 code path to send them to supplicant. + */ + ft_session_ptr->assocReqLen = + roam_sync_ind_ptr->reassoc_req_length + - SIR_MAC_HDR_LEN_3A - SIR_MAC_REASSOC_SSID_OFFSET; + ft_session_ptr->assocReq = + cdf_mem_malloc(ft_session_ptr->assocReqLen); + if (NULL == ft_session_ptr->assocReq) { + CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR, + "LFR3: Failed to alloc memory for Assoc Req"); + return; + } + cdf_mem_copy(ft_session_ptr->assocReq, + (uint8_t *)roam_sync_ind_ptr + + roam_sync_ind_ptr->reassoc_req_offset + + SIR_MAC_HDR_LEN_3A + SIR_MAC_REASSOC_SSID_OFFSET, + ft_session_ptr->assocReqLen); + } lim_ft_prepare_add_bss_req(pMac, false, ft_session_ptr, bss_desc_ptr); mmh_msg.type = roam_sync_ind_ptr->messageType; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index f170cca1c1a4..d4bb3367ecf2 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -2728,6 +2728,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, wmi_roam_synch_event_fixed_param *synch_event = NULL; uint8_t *bcn_probersp_ptr = NULL; uint8_t *reassoc_rsp_ptr = NULL; + uint8_t *reassoc_req_ptr = NULL; tp_wma_handle wma = (tp_wma_handle) handle; wmi_channel *chan = NULL; wmi_key_material *key = NULL; @@ -2759,7 +2760,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, } wma->interfaces[synch_event->vdev_id].roam_synch_in_progress = true; len = sizeof(roam_offload_synch_ind) + - synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len; + synch_event->bcn_probe_rsp_len + synch_event->reassoc_rsp_len + + synch_event->reassoc_req_len; roam_synch_ind_ptr = (roam_offload_synch_ind *) cdf_mem_malloc(len); if (!roam_synch_ind_ptr) { @@ -2786,6 +2788,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, roam_synch_ind_ptr->isBeacon = synch_event->is_beacon; WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, roam_synch_ind_ptr->bssid.bytes); + /* Beacon/Probe Rsp data */ roam_synch_ind_ptr->beaconProbeRespOffset = sizeof(roam_offload_synch_ind); bcn_probersp_ptr = @@ -2795,6 +2798,8 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, synch_event->bcn_probe_rsp_len; cdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, roam_synch_ind_ptr->beaconProbeRespLength); + + /* ReAssoc Rsp data */ roam_synch_ind_ptr->reassocRespOffset = sizeof(roam_offload_synch_ind) + roam_synch_ind_ptr->beaconProbeRespLength; @@ -2804,18 +2809,37 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, cdf_mem_copy(reassoc_rsp_ptr, param_buf->reassoc_rsp_frame, roam_synch_ind_ptr->reassocRespLength); + + /* ReAssoc Req data */ + roam_synch_ind_ptr->reassoc_req_offset = + sizeof(roam_offload_synch_ind) + + roam_synch_ind_ptr->beaconProbeRespLength + + roam_synch_ind_ptr->reassocRespLength; + roam_synch_ind_ptr->reassoc_req_length = synch_event->reassoc_req_len; + reassoc_req_ptr = (uint8_t *) roam_synch_ind_ptr + + roam_synch_ind_ptr->reassoc_req_offset; + cdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame, + roam_synch_ind_ptr->reassoc_req_length); + chan = (wmi_channel *) param_buf->chan; roam_synch_ind_ptr->chan_freq = chan->mhz; key = (wmi_key_material *) param_buf->key; if (key != NULL) { - CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, - key->replay_counter, SIR_REPLAY_CTR_LEN); cdf_mem_copy(roam_synch_ind_ptr->kck, key->kck, SIR_KCK_KEY_LEN); cdf_mem_copy(roam_synch_ind_ptr->kek, key->kek, SIR_KEK_KEY_LEN); cdf_mem_copy(roam_synch_ind_ptr->replay_ctr, key->replay_counter, SIR_REPLAY_CTR_LEN); + WMA_LOGD("%s: KCK dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->kck, SIR_KCK_KEY_LEN); + WMA_LOGD("%s: KEK dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->kek, SIR_KEK_KEY_LEN); + WMA_LOGD("%s: Key Replay Counter dump", __func__); + CDF_TRACE_HEX_DUMP(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_DEBUG, + key->replay_counter, SIR_REPLAY_CTR_LEN); } wma_send_msg(wma, WMA_ROAM_OFFLOAD_SYNCH_IND, (void *) roam_synch_ind_ptr, 0);