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;