diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 5242c10a038d..94cb53f7bf07 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -1244,25 +1244,6 @@ QDF_STATUS ucfg_mlme_get_roam_bmiss_final_bcnt(struct wlan_objmgr_psoc *psoc, uint8_t *val); -#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) -/** - * ucfg_mlme_update_sae_single_pmk_info() - Update sae_single_pmk_info - * @vdev: pointer to VDEV common object - * @pmk_info: Pointer mlme pmkid info - * - * Return: None - */ -void -ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, - struct mlme_pmk_info *pmk_info); -#else -static inline void -ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, - struct mlme_pmk_info *pmk_info) -{ -} -#endif - /** * ucfg_mlme_get_roam_bmiss_first_bcnt() - Get roam bmiss final count * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c index 1e003bfb583b..476989a420d6 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c @@ -980,14 +980,6 @@ ucfg_mlme_get_delay_before_vdev_stop(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } -#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) -void ucfg_mlme_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, - struct mlme_pmk_info *sae_single_pmk) -{ - wlan_mlme_update_sae_single_pmk(vdev, sae_single_pmk); -} -#endif - QDF_STATUS ucfg_mlme_get_roam_bmiss_final_bcnt(struct wlan_objmgr_psoc *psoc, uint8_t *val) diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index ad926b9097d5..ed17bfeb32cb 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -5957,7 +5957,7 @@ static int __wlan_hdd_cfg80211_keymgmt_set_key(struct wiphy *wiphy, qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE); qdf_mem_copy(local_pmk, data, data_len); sme_roam_set_psk_pmk(mac_handle, hdd_adapter->vdev_id, - local_pmk, data_len); + local_pmk, data_len, true); qdf_mem_zero(&local_pmk, SIR_ROAM_SCAN_PSK_SIZE); return 0; } @@ -21618,39 +21618,6 @@ static int wlan_hdd_cfg80211_add_station(struct wiphy *wiphy, return errno; } -#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) -/** - * wlan_update_sae_single_pmk_info() - Update a separate pmk information - * structure to support sae roaming using same pmk - * @vdev: vdev common object - * @pmk_cache: Pointer to pmk cache info - * - * Return: None - */ -static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, - tPmkidCacheInfo *pmk_cache) -{ - struct mlme_pmk_info *pmk_info; - - pmk_info = qdf_mem_malloc(sizeof(*pmk_info)); - if (!pmk_info) - return; - - qdf_mem_copy(pmk_info->pmk, pmk_cache->pmk, pmk_cache->pmk_len); - pmk_info->pmk_len = pmk_cache->pmk_len; - - ucfg_mlme_update_sae_single_pmk_info(vdev, pmk_info); - - qdf_mem_zero(pmk_info, sizeof(*pmk_info)); - qdf_mem_free(pmk_info); - -} -#else -static void wlan_update_sae_single_pmk_info(struct wlan_objmgr_vdev *vdev, - tPmkidCacheInfo *pmk_cache) -{ -} -#endif static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter, tPmkidCacheInfo *pmk_cache) { @@ -21698,12 +21665,10 @@ static QDF_STATUS wlan_hdd_set_pmksa_cache(struct hdd_adapter *adapter, qdf_mem_free(pmksa); } - wlan_update_sae_single_pmk_info(vdev, pmk_cache); - 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); - + pmk_cache->pmk, pmk_cache->pmk_len, + false); hdd_objmgr_put_vdev(vdev); return result; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index e8480df8675c..5531dd6558c9 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -600,7 +600,8 @@ void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id, tPmkidCacheInfo *pmk_cache); QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId, - uint8_t *pPSK_PMK, size_t pmk_len); + uint8_t *psk_pmk, size_t pmk_len, + bool update_to_fw); #else static inline void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id, @@ -623,7 +624,8 @@ sme_set_roam_scan_ch_event_cb(mac_handle_t mac_handle, static inline QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId, - uint8_t *pPSK_PMK, size_t pmk_len) + uint8_t *psk_pmk, size_t pmk_len, + bool update_to_fw) { return QDF_STATUS_SUCCESS; } diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 36c3c9c2de5b..ebae4064b48b 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -3199,19 +3199,23 @@ void sme_get_pmk_info(mac_handle_t mac_handle, uint8_t session_id, #ifdef WLAN_FEATURE_ROAM_OFFLOAD /* - * \fn sme_roam_set_psk_pmk - * \brief a wrapper function to request CSR to save PSK/PMK - * This is a synchronous call. - * \param mac_handle - Global structure - * \param sessionId - SME sessionId - * \param pPSK_PMK - pointer to an array of Psk[]/Pmk - * \param pmk_len - Length could be only 16 bytes in case if LEAP - * connections. Need to pass this information to - * firmware. - * \return QDF_STATUS -status whether PSK/PMK is set or not + * sme_roam_set_psk_pmk() - a wrapper function to request CSR to save PSK/PMK + * This is a synchronous call. + * @mac_handle: Global structure + * @sessionId: SME sessionId + * @pPSK_PMK: pointer to an array of Psk[]/Pmk + * @pmk_len: Length could be only 16 bytes in case if LEAP + * connections. Need to pass this information to + * firmware. + * @update_to_fw: True - send RSO update to firmware after updating + * session->psk_pmk. + * False - Copy the pmk to session->psk_pmk and return + * + * Return: QDF_STATUS -status whether PSK/PMK is set or not */ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId, - uint8_t *pPSK_PMK, size_t pmk_len) + uint8_t *psk_pmk, size_t pmk_len, + bool update_to_fw) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct mac_context *mac = MAC_CONTEXT(mac_handle); @@ -3219,8 +3223,8 @@ QDF_STATUS sme_roam_set_psk_pmk(mac_handle_t mac_handle, uint8_t sessionId, status = sme_acquire_global_lock(&mac->sme); if (QDF_IS_STATUS_SUCCESS(status)) { if (CSR_IS_SESSION_VALID(mac, sessionId)) - status = csr_roam_set_psk_pmk(mac, sessionId, pPSK_PMK, - pmk_len); + status = csr_roam_set_psk_pmk(mac, sessionId, psk_pmk, + pmk_len, update_to_fw); else status = QDF_STATUS_E_INVAL; sme_release_global_lock(&mac->sme); diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 2f14f15f755c..6ccfa331231f 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -9568,6 +9568,68 @@ bool is_disconnect_pending(struct mac_context *pmac, uint8_t vdev_id) return disconnect_cmd_exist; } +#if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) +static void +csr_clear_other_bss_sae_single_pmk_entry(struct mac_context *mac, + struct bss_description *bss_desc, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + + if (!bss_desc->is_single_pmk) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id, + WLAN_LEGACY_SME_ID); + if (!vdev) { + sme_err("vdev is NULL"); + return; + } + + wlan_crypto_selective_clear_sae_single_pmk_entries(vdev, + (struct qdf_mac_addr *)bss_desc->bssId); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); +} + +static void +csr_delete_current_bss_sae_single_pmk_entry(struct mac_context *mac, + struct bss_description *bss_desc, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct wlan_crypto_pmksa pmksa; + + if (!bss_desc->is_single_pmk) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id, + WLAN_LEGACY_SME_ID); + if (!vdev) { + sme_err("vdev is NULL"); + return; + } + + qdf_copy_macaddr(&pmksa.bssid, + (struct qdf_mac_addr *)bss_desc->bssId); + wlan_crypto_set_del_pmksa(vdev, &pmksa, false); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); +} +#else +static inline void +csr_clear_other_bss_sae_single_pmk_entry(struct mac_context *mac, + struct bss_description *bss_desc, + uint8_t vdev_id) +{} + +static inline void +csr_delete_current_bss_sae_single_pmk_entry(struct mac_context *mac, + struct bss_description *bss_desc, + uint8_t vdev_id) +{} +#endif + static void csr_roam_join_rsp_processor(struct mac_context *mac, struct join_rsp *pSmeJoinRsp) { @@ -9643,6 +9705,16 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, * the response to upper layers */ session_ptr->join_bssid_count = 0; + + /* + * On successful connection to sae single pmk AP, + * clear all the single pmk AP. + */ + if (pCommand && pCommand->u.roamCmd.pLastRoamBss) + csr_clear_other_bss_sae_single_pmk_entry(mac, + pCommand->u.roamCmd.pLastRoamBss, + pSmeJoinRsp->vdev_id); + csr_roam_complete(mac, eCsrJoinSuccess, (void *)pSmeJoinRsp, pSmeJoinRsp->vdev_id); @@ -9663,6 +9735,14 @@ static void csr_roam_join_rsp_processor(struct mac_context *mac, pSmeJoinRsp->status_code, pSmeJoinRsp->status_code, reason_code); + /* + * If connection fails with Single PMK bssid, clear this pmk + * entry. + */ + if (pCommand && pCommand->u.roamCmd.pLastRoamBss) + csr_delete_current_bss_sae_single_pmk_entry( + mac, pCommand->u.roamCmd.pLastRoamBss, + pSmeJoinRsp->vdev_id); /* * Delete the PMKID of the BSSID for which the assoc reject is * received from the AP due to invalid PMKID reason. @@ -14715,7 +14795,8 @@ void csr_get_pmk_info(struct mac_context *mac_ctx, uint8_t session_id, } QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId, - uint8_t *pPSK_PMK, size_t pmk_len) + uint8_t *psk_pmk, size_t pmk_len, + bool update_to_fw) { struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId); @@ -14723,7 +14804,7 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId, sme_err("session %d not found", sessionId); return QDF_STATUS_E_FAILURE; } - qdf_mem_copy(pSession->psk_pmk, pPSK_PMK, sizeof(pSession->psk_pmk)); + qdf_mem_copy(pSession->psk_pmk, psk_pmk, sizeof(pSession->psk_pmk)); pSession->pmk_len = pmk_len; if (csr_is_auth_type_ese(mac->roam.roamSession[sessionId]. @@ -14732,7 +14813,9 @@ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId, return QDF_STATUS_SUCCESS; } - csr_roam_update_cfg(mac, sessionId, REASON_ROAM_PSK_PMK_CHANGED); + if (update_to_fw) + csr_roam_update_cfg(mac, sessionId, + REASON_ROAM_PSK_PMK_CHANGED); return QDF_STATUS_SUCCESS; } @@ -14779,6 +14862,50 @@ void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc, } wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); } + +void +csr_store_sae_single_pmk_to_global_cache(struct mac_context *mac, + struct csr_roam_session *session, + uint8_t vdev_id) +{ + struct wlan_objmgr_vdev *vdev; + struct mlme_pmk_info *pmk_info; + + if (!session->pConnectBssDesc) + return; + + if (!session->pConnectBssDesc->is_single_pmk) + return; + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id, + WLAN_LEGACY_SME_ID); + if (!vdev) { + sme_err("vdev is NULL"); + return; + } + + /* + * Mark the AP as single PMK capable in Crypto Table + */ + wlan_crypto_set_sae_single_pmk_bss_cap(vdev, + (struct qdf_mac_addr *)session->pConnectBssDesc->bssId, + true); + + pmk_info = qdf_mem_malloc(sizeof(*pmk_info)); + if (!pmk_info) { + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + return; + } + + qdf_mem_copy(pmk_info->pmk, session->psk_pmk, session->pmk_len); + pmk_info->pmk_len = session->pmk_len; + + wlan_mlme_update_sae_single_pmk(vdev, pmk_info); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); + qdf_mem_zero(pmk_info, sizeof(*pmk_info)); + qdf_mem_free(pmk_info); +} #endif QDF_STATUS csr_roam_del_pmkid_from_cache(struct mac_context *mac, @@ -21418,9 +21545,11 @@ csr_check_and_set_sae_single_pmk_cap(struct mac_context *mac_ctx, struct csr_roam_session *session, uint8_t vdev_id) { - bool val; struct wlan_objmgr_vdev *vdev; - uint32_t keymgmt; + struct mlme_pmk_info *pmk_info; + tPmkidCacheInfo *pmkid_cache; + uint32_t keymgmt, pmkid_index; + bool val, lookup_success; vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, vdev_id, WLAN_LEGACY_SME_ID); @@ -21435,7 +21564,49 @@ csr_check_and_set_sae_single_pmk_cap(struct mac_context *mac_ctx, val = csr_is_sae_single_pmk_vsie_ap(session->pConnectBssDesc); wlan_mlme_set_sae_single_pmk_bss_cap(mac_ctx->psoc, vdev_id, val); + if (!val) + goto end; + + wlan_crypto_set_sae_single_pmk_bss_cap(vdev, + (struct qdf_mac_addr *)session->pConnectBssDesc->bssId, + true); + + pmkid_cache = qdf_mem_malloc(sizeof(*pmkid_cache)); + if (!pmkid_cache) + goto end; + + qdf_copy_macaddr(&pmkid_cache->BSSID, + &session->connectedProfile.bssid); + /* + * In SAE single pmk roaming case, there will + * be no PMK entry found for the AP in pmk cache. + * So if the lookup is successful, then we have done + * a FULL sae here. In that case, clear all other + * single pmk entries. + */ + lookup_success = csr_lookup_pmkid_using_bssid(mac_ctx, session, + pmkid_cache, + &pmkid_index); + qdf_mem_free(pmkid_cache); + if (lookup_success) { + wlan_crypto_selective_clear_sae_single_pmk_entries(vdev, + &session->connectedProfile.bssid); + + pmk_info = qdf_mem_malloc(sizeof(*pmk_info)); + if (!pmk_info) + goto end; + + qdf_mem_copy(pmk_info->pmk, session->psk_pmk, + session->pmk_len); + pmk_info->pmk_len = session->pmk_len; + wlan_mlme_update_sae_single_pmk(vdev, pmk_info); + + qdf_mem_zero(pmk_info, sizeof(*pmk_info)); + qdf_mem_free(pmk_info); + } } + +end: wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID); } #else @@ -21587,6 +21758,7 @@ static QDF_STATUS csr_process_roam_sync_callback(struct mac_context *mac_ctx, mac_ctx->psoc); mac_ctx->sme.set_connection_info_cb(false); session->roam_synch_in_progress = false; + csr_check_and_set_sae_single_pmk_cap(mac_ctx, session, session_id); diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index b47b5ddeece7..a64e25c6683a 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -761,16 +761,19 @@ void csr_get_pmk_info(struct mac_context *mac_ctx, uint8_t session_id, tPmkidCacheInfo *pmk_cache); /* - * csr_roam_set_psk_pmk() - - * store PSK/PMK - * mac - pointer to global structure for MAC - * sessionId - Sme session id - * pPSK_PMK - pointer to an array of Psk/Pmk + * csr_roam_set_psk_pmk() - store PSK/PMK in CSR session + * + * @mac - pointer to global structure for MAC + * @sessionId - Sme session id + * @psk_pmk - pointer to an array of PSK/PMK + * @update_to_fw - Send RSO update config command to firmware to update + * PMK + * * Return QDF_STATUS - usually it succeed unless sessionId is not found - * Note: */ QDF_STATUS csr_roam_set_psk_pmk(struct mac_context *mac, uint32_t sessionId, - uint8_t *pPSK_PMK, size_t pmk_len); + uint8_t *psk_pmk, size_t pmk_len, + bool update_to_fw); QDF_STATUS csr_roam_set_key_mgmt_offload(struct mac_context *mac_ctx, uint32_t session_id, @@ -947,12 +950,21 @@ QDF_STATUS csr_roam_del_pmkid_from_cache(struct mac_context *mac, void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, tPmkidCacheInfo *pmksa); +void csr_store_sae_single_pmk_to_global_cache(struct mac_context *mac, + struct csr_roam_session *session, + uint8_t vdev_id); #else static inline void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, tPmkidCacheInfo *pmksa) { } + +static inline +void csr_store_sae_single_pmk_to_global_cache(struct mac_context *mac, + struct csr_roam_session *session, + uint8_t vdev_id) +{} #endif QDF_STATUS csr_send_ext_change_channel(struct mac_context *mac_ctx, diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 6d23794efbe6..b800f30cc074 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -856,6 +856,14 @@ static void csr_neighbor_roam_info_ctx_init(struct mac_context *mac, } if (csr_roam_is_roam_offload_scan_enabled(mac)) { + /* + * Store the current PMK info of the AP + * to the single pmk global cache if the BSS allows + * single pmk roaming capable. + */ + csr_store_sae_single_pmk_to_global_cache(mac, session, + session_id); + /* * If this is not a INFRA type BSS, then do not send the command * down to firmware.Do not send the START command for