Jelajahi Sumber

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
Naveen Rawat 9 tahun lalu
induk
melakukan
83622ef789

+ 25 - 1
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,

+ 23 - 10
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 {

+ 2 - 0
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;

+ 25 - 0
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;

+ 27 - 3
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);