Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 721bdf6a authored by Srikanth Marepalli's avatar Srikanth Marepalli Committed by Madan Koyyalamudi
Browse files

qcacld-3.0: Invalid pmkid in the FT-EAP disconnection case

During FT-EAP roaming after session timeout if the FTIE received
in the EAPOL of full EAP is improper, the supplicant would
disconnect the AP with the reason FTIE mismatch.
During this disconnection supplicant flushes all the existing PMK
cache entries and eventually the framework would add these cache
entries again (apparently, the current entry would be with the
older PMK). On this addition to the driver, there is no connected
profile and thus no MDID is associated to this PMKSA entry(AP1-PMK1).
Further, on the fresh (Full EAP) connection to the AP2 with the
same MDID, a new cache entry gets added and thus MDID from the
connected profile gets associated with the PMKSA cache entry. At
this point of time, there are two PMKSA cache entries (AP1-PMK1
without MDID and AP2-PMK2 with MDID).
Adding further, if the incorrect PMK (without MDID / stale entry)
i.e. PMK1 is given to the firmware on the RSO command for the
specific BSSID (here AP1) during roam, further roams shall be
calculated with this PMK1 and result in to the invalid pmkid
issue.
Thus, avoid this situation by removing that stale PMKSA entry in
the driver and this entry can be deleted only when it is associated
with the MDID. Driver on the new pmksa addition shall check for the
matching pmksa cache entry with the MDID and delete the earlier ones.
To associate the MDID, this commit checks for the same from the scan
entry of the BSSID, if there is no connected profile for the same
(this happened when the framework has added the cache entry when in
the disconnected state).

Change-Id: If81d66059173dda8d7a2940ca10dc96ef16e125c
CRs-Fixed: 2972115
parent e0d55a65
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -22247,10 +22247,12 @@ static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter,
		qdf_mem_free(pmksa);
	}
	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len)
	if (result == QDF_STATUS_SUCCESS && pmk_cache->pmk_len) {
		sme_roam_set_psk_pmk(mac_handle, adapter->vdev_id,
				     pmk_cache->pmk, pmk_cache->pmk_len,
				     false);
		sme_set_pmk_cache_ft(mac_handle, adapter->vdev_id, pmk_cache);
	}
	hdd_objmgr_put_vdev(vdev);
	return result;
+19 −0
Original line number Diff line number Diff line
@@ -634,6 +634,18 @@ void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id,
QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
				uint8_t *psk_pmk, size_t pmk_len,
				bool update_to_fw);

/**
 * sme_set_pmk_cache_ft() - a wrapper function to request CSR to save MDID
 * This is a synchronous call.
 * @mac_handle:  Global structure
 * @session_id:   SME session id
 * @pmk_cache:    pointer to pmk cache structure tPmkidCacheInfo
 *
 * Return: QDF_STATUS -status whether MDID is set or not
 */
QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
				tPmkidCacheInfo *pmk_cache);
#else
static inline
void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id,
@@ -661,6 +673,13 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
{
	return QDF_STATUS_SUCCESS;
}

static inline
QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
				tPmkidCacheInfo *pmk_cache)
{
	return QDF_STATUS_SUCCESS;
}
#endif

/**
+14 −0
Original line number Diff line number Diff line
@@ -3904,6 +3904,20 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId,
	}
	return status;
}

QDF_STATUS sme_set_pmk_cache_ft(mac_handle_t mac_handle, uint8_t session_id,
				tPmkidCacheInfo *pmk_cache)
{
	QDF_STATUS status = QDF_STATUS_E_FAILURE;
	struct mac_context *mac = MAC_CONTEXT(mac_handle);

	status = sme_acquire_global_lock(&mac->sme);
	if (QDF_IS_STATUS_SUCCESS(status)) {
		status = csr_set_pmk_cache_ft(mac, session_id, pmk_cache);
		sme_release_global_lock(&mac->sme);
	}
	return status;
}
#endif

QDF_STATUS sme_roam_get_wpa_rsn_req_ie(mac_handle_t mac_handle,
+68 −27
Original line number Diff line number Diff line
@@ -7061,8 +7061,8 @@ static void csr_roam_process_join_res(struct mac_context *mac_ctx,
				session->connectedProfile.mdid.mdie_present;
			if (akm_type == eCSR_AUTH_TYPE_FT_SAE && mdie_present) {
				sme_debug("Update the MDID in PMK cache for FT-SAE case");
				csr_update_pmk_cache_ft(mac_ctx,
							session_id, session);
				csr_update_pmk_cache_ft(mac_ctx, session_id,
							NULL, NULL);
			}
			len = join_rsp->assocReqLength +
@@ -13867,7 +13867,6 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId,
				bool update_to_fw)
{
	struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId);
	enum csr_akm_type akm_type;
	if (!pSession) {
		sme_err("session %d not found", sessionId);
@@ -13882,20 +13881,51 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId,
		return QDF_STATUS_SUCCESS;
	}
	akm_type = pSession->connectedProfile.AuthType;
	if (update_to_fw)
		csr_roam_update_cfg(mac, sessionId,
				    REASON_ROAM_PSK_PMK_CHANGED);
	return QDF_STATUS_SUCCESS;
}
QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint32_t session_id,
				tPmkidCacheInfo *pmk_cache)
{
	struct csr_roam_session *session = CSR_GET_SESSION(mac, session_id);
	enum csr_akm_type akm_type;
	if (!CSR_IS_SESSION_VALID(mac, session_id)) {
		sme_err("session %d not found", session_id);
		return QDF_STATUS_E_INVAL;
	}
	akm_type = session->connectedProfile.AuthType;
	if ((akm_type == eCSR_AUTH_TYPE_FT_RSN ||
	     akm_type == eCSR_AUTH_TYPE_FT_FILS_SHA256 ||
	     akm_type == eCSR_AUTH_TYPE_FT_FILS_SHA384 ||
	     akm_type == eCSR_AUTH_TYPE_FT_SUITEB_EAP_SHA384) &&
	    pSession->connectedProfile.mdid.mdie_present) {
	    session->connectedProfile.mdid.mdie_present) {
		sme_debug("Auth type: %d update the MDID in cache", akm_type);
		csr_update_pmk_cache_ft(mac, sessionId, pSession);
	}
		csr_update_pmk_cache_ft(mac, session_id, pmk_cache, NULL);
	} else {
		tCsrScanResultInfo *scan_res;
		QDF_STATUS status = QDF_STATUS_E_FAILURE;
	if (update_to_fw)
		csr_roam_update_cfg(mac, sessionId,
				    REASON_ROAM_PSK_PMK_CHANGED);
		scan_res = qdf_mem_malloc(sizeof(tCsrScanResultInfo));
		if (!scan_res)
			return QDF_STATUS_E_NOMEM;
		status = csr_scan_get_result_for_bssid(mac, &pmk_cache->BSSID,
						       scan_res);
		if (QDF_IS_STATUS_SUCCESS(status) &&
		    scan_res->BssDescriptor.mdiePresent) {
			sme_debug("Update MDID in cache from scan_res");
			csr_update_pmk_cache_ft(mac, session_id,
						pmk_cache, scan_res);
		}
		qdf_mem_free(scan_res);
		scan_res = NULL;
	}
	return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_ROAM_OFFLOAD */
@@ -14015,12 +14045,14 @@ csr_store_sae_single_pmk_to_global_cache(struct mac_context *mac,
#endif
void csr_update_pmk_cache_ft(struct mac_context *mac, uint32_t vdev_id,
			     struct csr_roam_session *session)
			     tPmkidCacheInfo *pmk_cache,
			     tCsrScanResultInfo *scan_res)
{
	QDF_STATUS status = QDF_STATUS_E_INVAL;
	struct wlan_objmgr_vdev *vdev;
	struct wlan_crypto_pmksa pmksa;
	enum QDF_OPMODE vdev_mode;
	struct csr_roam_session *session = CSR_GET_SESSION(mac, vdev_id);
	if (!session) {
		sme_err("session not found");
@@ -14043,23 +14075,19 @@ void csr_update_pmk_cache_ft(struct mac_context *mac, uint32_t vdev_id,
	}
	/*
	 * In FT connection fetch the MDID from Session and send it to crypto
	 * so that it will update the crypto PMKSA table with the MDID for the
	 * matching BSSID or SSID PMKSA entry. And delete the old/stale PMK
	 * cache entries for the same mobility domain as of the newly added
	 * entry to avoid multiple PMK cache entries for the same MDID.
	 */
	qdf_copy_macaddr(&pmksa.bssid, &session->connectedProfile.bssid);
	sme_debug("copied the BSSID from session to PMKSA");
	if (session->connectedProfile.SSID.length) {
		qdf_mem_copy(&pmksa.ssid, &session->connectedProfile.SSID.ssId,
			     session->connectedProfile.SSID.length);
		qdf_mem_copy(
			&pmksa.cache_id,
			&session->pConnectBssDesc->fils_info_element.cache_id,
			CACHE_ID_LEN);
		pmksa.ssid_len = session->connectedProfile.SSID.length;
		sme_debug("copied the SSID from session to PMKSA");
	 * In FT connection fetch the MDID from Session or scan result whichever
	 * is available and send it to crypto so that it will update the crypto
	 * PMKSA table with the MDID for the matching BSSID or SSID PMKSA entry.
	 * And delete the old/stale PMK cache entries for the same mobility
	 * domain as of the newly added entry to avoid multiple PMK cache
	 * entries for the same MDID.
	 */
	if (pmk_cache && pmk_cache->ssid_len) {
		pmksa.ssid_len = pmk_cache->ssid_len;
		qdf_mem_copy(&pmksa.ssid, &pmk_cache->ssid, pmksa.ssid_len);
		qdf_mem_copy(&pmksa.cache_id,
			     &pmk_cache->cache_id, CACHE_ID_LEN);
		sme_debug("copied the SSID from pmk_cache to PMKSA");
	}
	if (session->connectedProfile.mdid.mdie_present) {
@@ -14067,6 +14095,19 @@ void csr_update_pmk_cache_ft(struct mac_context *mac, uint32_t vdev_id,
		pmksa.mdid.mobility_domain =
				session->connectedProfile.mdid.mobility_domain;
		sme_debug("copied the MDID from session to PMKSA");
		qdf_copy_macaddr(&pmksa.bssid,
				 &session->connectedProfile.bssid);
		status = wlan_crypto_update_pmk_cache_ft(vdev, &pmksa);
		if (status == QDF_STATUS_SUCCESS)
			sme_debug("Updated the crypto cache table");
	} else if (scan_res && scan_res->BssDescriptor.mdiePresent) {
		pmksa.mdid.mdie_present = 1;
		pmksa.mdid.mobility_domain =
			(scan_res->BssDescriptor.mdie[0] |
			 (scan_res->BssDescriptor.mdie[1] << 8));
		sme_debug("copied the MDID from scan_res to PMKSA");
		qdf_copy_macaddr(&pmksa.bssid, &pmk_cache->BSSID);
		status = wlan_crypto_update_pmk_cache_ft(vdev, &pmksa);
		if (status == QDF_STATUS_SUCCESS)
+19 −4
Original line number Diff line number Diff line
@@ -729,6 +729,18 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId,
				uint8_t *psk_pmk, size_t pmk_len,
				bool update_to_fw);

/**
 * csr_set_pmk_cache_ft() - store MDID in PMK cache
 *
 * @mac  - pointer to global structure for MAC
 * @session_id - Sme session id
 * @pmk_cache: pointer to a structure of PMK
 *
 * Return QDF_STATUS - usually it succeed unless session_id is not found
 */
QDF_STATUS csr_set_pmk_cache_ft(struct mac_context *mac, uint32_t session_id,
				tPmkidCacheInfo *pmk_cache);

QDF_STATUS csr_roam_set_key_mgmt_offload(struct mac_context *mac_ctx,
					 uint32_t session_id,
					 struct pmkid_mode_bits *pmkid_modes);
@@ -880,13 +892,16 @@ QDF_STATUS csr_roam_del_pmkid_from_cache(struct mac_context *mac,

/**
 * csr_update_pmk_cache_ft - API to update MDID in PMKSA cache entry
 * @session_id: session ID
 * @session: sme session pointer
 * @mac: Pointer to global structure for MAC
 * @vdev_id: session ID
 * @pmk_cache: pointer to pmk cache
 * @scan_res: pointer to tCsrScanResultInfo
 *
 * Return: None
 */
void csr_update_pmk_cache_ft(struct mac_context *mac, uint32_t session_id,
			     struct csr_roam_session *session);
void csr_update_pmk_cache_ft(struct mac_context *mac, uint32_t vdev_id,
			     tPmkidCacheInfo *pmk_cache,
			     tCsrScanResultInfo *scan_res);

#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
/**