From 32f21c89bd8a21d4d10072183014e7aa72d718ae Mon Sep 17 00:00:00 2001 From: Vignesh Viswanathan Date: Tue, 11 Sep 2018 17:36:30 +0530 Subject: [PATCH] qcacld-3.0: Update CSR session PMK during Roam Sync Propagation Currently CSR session PMK is updated from the set_key command from supplicant after successful 8 way handshake with the AP. However, in case of roaming to an AP which already has the PMKID cached, the Roam Sync happens with Auth Status Authenticated and set_key from the supplicant does not happen. In this case, the value in the CSR session PMK is incorrect and is the PMK of the previous AP before roaming. After this scenario, if any RSO command is sent to the FW, the incorrect PMK is sent as part of the RSO command updating the FW with incorrect PMK for the current AP. The next time a roaming happens to the same AP, then the 4 way handshake fails and fallback to 8 way handshake happens. Update the PMK in CSR session for the current AP from PMKID cache during Roam Sync propagation, if the Auth Status is authenticated. Change-Id: I3ced7d0fd75379ede01cf9f993f5beefbb20cda1 CRs-Fixed: 2313289 --- core/sme/src/csr/csr_api_roam.c | 36 +++++++++++++++++++++++++++++++++ core/sme/src/csr/csr_util.c | 30 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 2de484d30949..e5ceee65eaf3 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -21836,6 +21836,8 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, sme_QosAssocInfo assoc_info; tpAddBssParams add_bss_params; QDF_STATUS status = QDF_STATUS_SUCCESS; + tPmkidCacheInfo pmkid_cache; + uint32_t pmkid_index; uint16_t len; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH tSirSmeHTProfile *src_profile = NULL; @@ -21986,6 +21988,40 @@ static QDF_STATUS csr_process_roam_sync_callback(tpAniSirGlobal mac_ctx, FL("LFR3:Don't start waitforkey timer")); csr_roam_substate_change(mac_ctx, eCSR_ROAM_SUBSTATE_NONE, session_id); + /* + * If authStatus is AUTHENTICATED, then we have done successful + * 4 way handshake in FW using the cached PMKID. + * However, the session->psk_pmk has the PMK of the older AP + * as set_key is not received from supplicant. + * When any RSO command is sent for the current AP, the older + * AP's PMK is sent to the FW which leads to incorrect PMK and + * leads to 4 way handshake failure when roaming happens to + * this AP again. + * Check if a PMK cache exists for the roamed AP and update + * it into the session pmk. + */ + qdf_mem_zero(&pmkid_cache, sizeof(pmkid_cache)); + qdf_copy_macaddr(&pmkid_cache.BSSID, + &session->connectedProfile.bssid); + sme_debug("Trying to find PMKID for " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(pmkid_cache.BSSID.bytes)); + if (csr_lookup_pmkid_using_bssid(mac_ctx, session, + &pmkid_cache, + &pmkid_index)) { + session->pmk_len = + session->PmkidCacheInfo[pmkid_index].pmk_len; + qdf_mem_zero(session->psk_pmk, + sizeof(session->psk_pmk)); + qdf_mem_copy(session->psk_pmk, + session->PmkidCacheInfo[pmkid_index].pmk, + session->pmk_len); + sme_debug("pmkid found for " QDF_MAC_ADDR_STR " at %d len %d", + QDF_MAC_ADDR_ARRAY(pmkid_cache.BSSID.bytes), + pmkid_index, (uint32_t)session->pmk_len); + } else { + sme_debug("PMKID Not found in cache for " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(pmkid_cache.BSSID.bytes)); + } } else { roam_info->fAuthRequired = true; csr_roam_substate_change(mac_ctx, diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index f94da3d3ebdf..1d384a565e45 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -3876,6 +3876,28 @@ static inline void csr_update_pmksa_to_profile(struct csr_roam_profile *profile, } #endif +/** + * csr_update_session_pmk() - Update the pmk len and pmk in the roam session + * @session: pointer to the CSR Roam session + * @pmkid_cache: pointer to the pmkid cache + * + * Return: None + */ +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +static void csr_update_session_pmk(struct csr_roam_session *session, + tPmkidCacheInfo *pmkid_cache) +{ + session->pmk_len = pmkid_cache->pmk_len; + qdf_mem_zero(session->psk_pmk, sizeof(session->psk_pmk)); + qdf_mem_copy(session->psk_pmk, pmkid_cache->pmk, session->pmk_len); +} +#else +static inline void csr_update_session_pmk(struct csr_roam_session *session, + tPmkidCacheInfo *pmkid_cache) +{ +} +#endif + uint8_t csr_construct_rsn_ie(tpAniSirGlobal pMac, uint32_t sessionId, struct csr_roam_profile *pProfile, tSirBssDescription *pSirBssDesc, @@ -4007,6 +4029,14 @@ uint8_t csr_construct_rsn_ie(tpAniSirGlobal pMac, uint32_t sessionId, qdf_mem_copy(pPMK->PMKIDList[0].PMKID, pmkid_cache.PMKID, CSR_RSN_PMKID_SIZE); + + /* + * If a PMK cache is found for the BSSID, then + * update the PMK in CSR session also as this + * will be sent to the FW during RSO. + */ + csr_update_session_pmk(session, &pmkid_cache); + csr_update_pmksa_to_profile(pProfile, &pmkid_cache); } else { pPMK->cPMKIDs = 0;