From b5fcfc428157060a9d169169c0bbfc12b6dd09cc Mon Sep 17 00:00:00 2001 From: Srikanth Marepalli Date: Fri, 9 Oct 2020 03:57:07 +0530 Subject: [PATCH] qcacmn: Update the PMK crypto cache based on MDID in FT roam In FT roam when STA connects to AP1 then PMK1 gets cached. And then STA disconnects from AP1 and connects to AP2 then PMK2 gets cached. Now if STA roams to AP1 then FW uses PMK2 from mlme session to create the PMKID. But the corresponding RSO command from driver sends the PMK1 to FW and the same gets updated in mlme session of FW. This results in failure of next roams, as the invalid PMKID gets created using PMK1. This fix helps in deleting the old/stale PMK cache entries for the same mobility domain as of the newly added entry. Also the FT-SuiteB AKM is enabled in crypto using this change. Change-Id: Id147ec40b8e0deacc4c427d396ec973cec483904 CRs-Fixed: 2796105 --- .../crypto/inc/wlan_crypto_global_api.h | 14 +++ .../crypto/inc/wlan_crypto_global_def.h | 13 +++ .../crypto/src/wlan_crypto_global_api.c | 89 +++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h index 7e45dac3b220..0572427007ca 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_api.h @@ -1027,6 +1027,20 @@ QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_pmksa *pmksa, bool set); +/** + * wlan_crypto_update_pmk_cache_ft - Updates the mobility domain information + * for a BSSID in the PMKSA Cache table. + * @vdev: vdev + * @pmksa: pmksa to be updated. + * + * This function gets called from ucfg to update pmksa with mdid. + * And flush the matching mdid entries. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS wlan_crypto_update_pmk_cache_ft(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_pmksa *pmksa); + #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) /** * wlan_crypto_selective_clear_sae_single_pmk_entries - Clear the PMK entries diff --git a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h index 331982ef038f..32872946c3dd 100644 --- a/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h +++ b/umac/cmn_services/crypto/inc/wlan_crypto_global_def.h @@ -243,6 +243,17 @@ enum fils_erp_cryptosuite { HMAC_SHA256_256, }; +/** + * struct mobility_domain_params - structure containing + * mobility domain info + * @mdie_present: mobility domain present or not + * @mobility_domain: mobility domain + */ +struct mobility_domain_params { + uint8_t mdie_present; + uint16_t mobility_domain; +}; + /** * struct wlan_crypto_pmksa - structure of crypto to contain pmkid * @bssid: bssid for which pmkid is saved @@ -253,6 +264,7 @@ enum fils_erp_cryptosuite { * @ssid: ssid information * @cache_id: cache id * @single_pmk_supported: SAE single pmk supported BSS + * @mdid: structure to contain mobility domain parameters */ struct wlan_crypto_pmksa { struct qdf_mac_addr bssid; @@ -265,6 +277,7 @@ struct wlan_crypto_pmksa { #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD) bool single_pmk_supported; #endif + struct mobility_domain_params mdid; }; /** diff --git a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c index 3b236befc255..8e610fca262b 100644 --- a/umac/cmn_services/crypto/src/wlan_crypto_global_api.c +++ b/umac/cmn_services/crypto/src/wlan_crypto_global_api.c @@ -370,6 +370,7 @@ QDF_STATUS wlan_crypto_set_pmksa(struct wlan_crypto_params *crypto_params, return QDF_STATUS_E_INVAL; } crypto_params->pmksa[first_available_slot] = pmksa; + crypto_debug("PMKSA: Added the PMKSA entry at index=%d", i); return QDF_STATUS_SUCCESS; } @@ -407,6 +408,8 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, sizeof(struct wlan_crypto_pmksa)); qdf_mem_free(crypto_params->pmksa[i]); crypto_params->pmksa[i] = NULL; + crypto_debug("PMKSA: Deleted PMKSA entry at index=%d", + i); /* Find and remove the entries matching the pmk */ for (j = 0; j < WLAN_CRYPTO_MAX_PMKID; j++) { @@ -420,6 +423,8 @@ QDF_STATUS wlan_crypto_del_pmksa(struct wlan_crypto_params *crypto_params, sizeof(struct wlan_crypto_pmksa)); qdf_mem_free(crypto_params->pmksa[j]); crypto_params->pmksa[j] = NULL; + crypto_debug("PMKSA: Deleted PMKSA at idx=%d", + j); } } /* reset stored pmk */ @@ -492,6 +497,81 @@ QDF_STATUS wlan_crypto_set_del_pmksa(struct wlan_objmgr_vdev *vdev, return status; } +QDF_STATUS wlan_crypto_update_pmk_cache_ft(struct wlan_objmgr_vdev *vdev, + struct wlan_crypto_pmksa *pmksa) +{ + QDF_STATUS status = QDF_STATUS_E_INVAL; + struct wlan_crypto_pmksa *cached_pmksa; + struct wlan_crypto_comp_priv *crypto_priv; + struct wlan_crypto_params *crypto_params; + uint8_t mdie_present, i; + uint16_t mobility_domain; + + if (!pmksa) { + crypto_err("pmksa is NULL for set operation"); + return status; + } + + crypto_priv = (struct wlan_crypto_comp_priv *) + wlan_get_vdev_crypto_obj(vdev); + if (!crypto_priv) { + crypto_err("crypto_priv NULL"); + return status; + } + + crypto_params = &crypto_priv->crypto_params; + + if (pmksa->mdid.mdie_present) { + for (i = 0; i < WLAN_CRYPTO_MAX_PMKID; i++) { + if (!crypto_params->pmksa[i]) + continue; + cached_pmksa = crypto_params->pmksa[i]; + mdie_present = cached_pmksa->mdid.mdie_present; + mobility_domain = cached_pmksa->mdid.mobility_domain; + + /* In FT connection when STA connects to AP1 then PMK1 + * gets cached. And if STA disconnects from AP1 and + * connects to AP2 then PMK2 gets cached. This will + * result in having multiple PMK cache entries for the + * same MDID. So delete the old/stale PMK cache entries + * for the same mobility domain as of the newly added + * entry. And Update the MDID for the matching BSSID or + * SSID PMKSA entry. + */ + if (qdf_is_macaddr_equal + (&cached_pmksa->bssid, &pmksa->bssid)) { + cached_pmksa->mdid.mdie_present = 1; + cached_pmksa->mdid.mobility_domain = + pmksa->mdid.mobility_domain; + crypto_debug("Updated the MDID at index=%d", i); + status = QDF_STATUS_SUCCESS; + } else if (pmksa->ssid_len && + !qdf_mem_cmp(pmksa->ssid, + cached_pmksa->ssid, + pmksa->ssid_len) && + !qdf_mem_cmp(pmksa->cache_id, + cached_pmksa->cache_id, + WLAN_CACHE_ID_LEN)) { + cached_pmksa->mdid.mdie_present = 1; + cached_pmksa->mdid.mobility_domain = + pmksa->mdid.mobility_domain; + crypto_debug("Updated the MDID at index=%d", i); + status = QDF_STATUS_SUCCESS; + } else if (mdie_present && + (pmksa->mdid.mobility_domain == + mobility_domain)) { + qdf_mem_zero(crypto_params->pmksa[i], + sizeof(struct wlan_crypto_pmksa)); + qdf_mem_free(crypto_params->pmksa[i]); + crypto_params->pmksa[i] = NULL; + crypto_debug("Deleted PMKSA at index=%d", i); + status = QDF_STATUS_SUCCESS; + } + } + } + return status; +} + struct wlan_crypto_pmksa * wlan_crypto_get_peer_pmksa(struct wlan_objmgr_vdev *vdev, struct wlan_crypto_pmksa *pmksa) @@ -2376,6 +2456,8 @@ wlan_crypto_rsn_keymgmt_to_suite(uint32_t keymgmt) return RSN_AUTH_KEY_MGMT_OWE; case WLAN_CRYPTO_KEY_MGMT_DPP: return RSN_AUTH_KEY_MGMT_DPP; + case WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384: + return RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_384; } return status; @@ -2987,6 +3069,13 @@ uint8_t *wlan_crypto_build_rsnie_with_pmksa(struct wlan_objmgr_vdev *vdev, selcnt[0]++; RSN_ADD_KEYMGMT_TO_SUITE(frm, WLAN_CRYPTO_KEY_MGMT_OSEN); } + if (HAS_KEY_MGMT(crypto_params, + WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384)) { + uint32_t kmgmt = WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384; + + selcnt[0]++; + RSN_ADD_KEYMGMT_TO_SUITE(frm, kmgmt); + } add_rsn_caps: WLAN_CRYPTO_ADDSHORT(frm, crypto_params->rsn_caps); /* optional capabilities */