Selaa lähdekoodia

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
Srikanth Marepalli 4 vuotta sitten
vanhempi
sitoutus
4ded73bfcf

+ 14 - 0
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

+ 13 - 0
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;
 };
 
 /**

+ 89 - 0
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;
@@ -2993,6 +3075,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 */