Browse Source

qcacmn: For Adaptive 11R connection , choose the first AKM in RSNIE

Supplicant compares AKM(s) in RSN IE of Beacon/Probe response and
AKM on third EAPOL frame received by AP. In the case of multi AKM,
previously Host converts all adaptive 11r AKM(s), if any, present
in RSN IE of Beacon/Probe response to corresponding FT AKM but the
AP(s) which support adaptive 11r (ADAPTIVE_11R_OUI: 0x964000) only
converts first AKM to corresponding FT AKM and sends third EAPOL
frame to DUT. This results in failure in a 4-way handshake in
supplicant due to RSN IE miss-match between RSNIE sent by host
and RSNIE present in third EAPOL frame. Now like AP, the host is
converting only the first AKM to corresponding FT AKM to avoid
RSNIE mismatch in supplicant.

Change-Id: I522c6e313df50c1ef2952ec2e464a107ae739dad
CRs-Fixed: 3230622
abhinav kumar 3 năm trước cách đây
mục cha
commit
93eb9ca13a

+ 15 - 0
umac/cmn_services/crypto/inc/wlan_crypto_global_def.h

@@ -315,6 +315,17 @@ struct wlan_crypto_pmksa {
 	struct mobility_domain_params mdid;
 };
 
+#ifdef WLAN_ADAPTIVE_11R
+/**
+ * struct wlan_crypto_pmksa - structure to store AKM(s) present in RSN IE of
+ * Beacon/Probe response
+ * @key_mgmt: AKM(s) present in RSN IE of Beacon/Probe response
+ */
+struct key_mgmt_list {
+	uint32_t key_mgmt;
+};
+#endif
+
 /**
  * struct wlan_crypto_params - holds crypto params
  * @authmodeset:        authentication mode
@@ -325,6 +336,7 @@ struct wlan_crypto_pmksa {
  * @key_mgmt:           key mgmt
  * @pmksa:              pmksa
  * @rsn_caps:           rsn_capability
+ * @akm_list:           order of AKM present in RSN IE of Beacon/Probe response
  *
  * This structure holds crypto params for peer or vdev
  */
@@ -337,6 +349,9 @@ struct wlan_crypto_params {
 	uint32_t key_mgmt;
 	struct   wlan_crypto_pmksa *pmksa[WLAN_CRYPTO_MAX_PMKID];
 	uint16_t rsn_caps;
+#ifdef WLAN_ADAPTIVE_11R
+	struct key_mgmt_list akm_list[WLAN_CRYPTO_KEY_MGMT_MAX];
+#endif
 };
 
 /**

+ 36 - 3
umac/cmn_services/crypto/src/wlan_crypto_global_api.c

@@ -2833,12 +2833,40 @@ QDF_STATUS wlan_crypto_wpaie_check(struct wlan_crypto_params *crypto_params,
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_ADAPTIVE_11R
+/**
+ * wlan_crypto_akm_list_in_order - store AMK list in order
+ * @crypto_params: crypto param structure
+ * @key_mgmt: key management
+ * @akm_index: place at which AMK present in RSN IE of Beacon/Probe response
+ *
+ * Return: none
+ */
+static void
+wlan_crypto_store_akm_list_in_order(struct wlan_crypto_params *crypto_params,
+				    int32_t key_mgmt, int akm_index)
+{
+	if (akm_index >= WLAN_CRYPTO_KEY_MGMT_MAX) {
+		crypto_debug("Invalid AKM Index");
+		return;
+	}
+
+	crypto_params->akm_list[akm_index].key_mgmt = key_mgmt;
+}
+#else
+static inline void
+wlan_crypto_store_akm_list_in_order(struct wlan_crypto_params *crypto_params,
+				    int32_t key_mgmt, int akm_index)
+{
+}
+#endif
+
 QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
 				   const uint8_t *frm)
 {
 	uint8_t len = frm[1];
 	int32_t w;
-	int n;
+	int n, akm_index;
 
 	/* Check the length once for fixed parts: OUI, type & version */
 	if (len < 2)
@@ -2928,11 +2956,16 @@ QDF_STATUS wlan_crypto_rsnie_check(struct wlan_crypto_params *crypto_params,
 	if (n) {
 		if (len < n * 4)
 			return QDF_STATUS_E_INVAL;
-
+		akm_index = 0;
 		for (; n > 0; n--) {
 			w = wlan_crypto_rsn_suite_to_keymgmt(frm);
-			if (w >= 0)
+			if (w >= 0) {
 				SET_KEY_MGMT(crypto_params, w);
+				wlan_crypto_store_akm_list_in_order(
+						crypto_params, w, akm_index);
+				akm_index++;
+			}
+
 			frm += 4, len -= 4;
 		}
 	} else {

+ 71 - 22
umac/scan/core/src/wlan_scan_filter.c

@@ -214,6 +214,73 @@ static bool scm_chk_crypto_params(struct scan_filter *filter,
 	return true;
 }
 
+#ifdef WLAN_ADAPTIVE_11R
+/**
+ * scm_check_and_update_adaptive_11r_key_mgmt_support() -  check and update
+ * first rsn security which is present in RSN IE of Beacon/Probe response to
+ * corresponding FT AKM.
+ * @ap_crypto: crypto param structure
+ *
+ * Return: none
+ */
+static void scm_check_and_update_adaptive_11r_key_mgmt_support(
+					struct wlan_crypto_params *ap_crypto)
+{
+	uint32_t i, first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_MAX;
+
+	/*
+	 * Supplicant compares AKM(s) in RSN IE of Beacon/Probe response and
+	 * AKM on EAPOL M3 frame received by AP.  In the case of multi AKM,
+	 * previously Host converts all adaptive 11r AKM(s), if any, present
+	 * in RSN IE of Beacon/Probe response to corresponding FT AKM but the
+	 * AP(s) which support adaptive 11r (ADAPTIVE_11R_OUI: 0x964000) only
+	 * converts first AKM to corresponding FT AKM and sends EAPOL M3 frame
+	 * to DUT. This results in failure in a 4-way handshake in supplicant
+	 * due to RSN IE miss-match between RSNIE sent by host and RSNIE
+	 * present in EAPOL M3 frame. Now like AP, the host is converting only
+	 * the first AKM to corresponding FT AKM to avoid RSNIE mismatch in
+	 * supplicant.
+	 */
+	for (i = 0; i < WLAN_CRYPTO_KEY_MGMT_MAX; i++) {
+		if (ap_crypto->akm_list[i].key_mgmt ==
+		    WLAN_CRYPTO_KEY_MGMT_IEEE8021X ||
+		    ap_crypto->akm_list[i].key_mgmt ==
+		    WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256) {
+			first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_IEEE8021X;
+			break;
+		}
+
+		if (ap_crypto->akm_list[i].key_mgmt ==
+		    WLAN_CRYPTO_KEY_MGMT_PSK ||
+		    ap_crypto->akm_list[i].key_mgmt ==
+		    WLAN_CRYPTO_KEY_MGMT_PSK_SHA256) {
+			first_key_mgmt = WLAN_CRYPTO_KEY_MGMT_PSK;
+			break;
+		}
+	}
+
+	if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_MAX) {
+		scm_debug("No adaptive 11r's AKM present in RSN IE");
+		return;
+	}
+
+	scm_debug("First AKM:%d present in RSN IE of bcn/Probe rsp at index:%d",
+		  first_key_mgmt, i);
+
+	if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_IEEE8021X)
+		QDF_SET_PARAM(ap_crypto->key_mgmt,
+			      WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
+
+	if (first_key_mgmt == WLAN_CRYPTO_KEY_MGMT_PSK)
+		QDF_SET_PARAM(ap_crypto->key_mgmt, WLAN_CRYPTO_KEY_MGMT_FT_PSK);
+}
+#else
+static inline void scm_check_and_update_adaptive_11r_key_mgmt_support(
+					struct wlan_crypto_params *ap_crypto)
+{
+}
+#endif
+
 /**
  * scm_check_rsn() - Check if scan entry support RSN security
  * @filter: scan filter
@@ -253,29 +320,11 @@ static bool scm_check_rsn(struct scan_filter *filter,
 				filter->enable_adaptive_11r;
 
 	/* If adaptive 11r is enabled set the FT AKM for AP */
-	if (is_adaptive_11r) {
-		if (QDF_HAS_PARAM(ap_crypto->key_mgmt,
-				  WLAN_CRYPTO_KEY_MGMT_IEEE8021X)) {
-			QDF_SET_PARAM(ap_crypto->key_mgmt,
-				      WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
-		}
-		if (QDF_HAS_PARAM(ap_crypto->key_mgmt,
-				  WLAN_CRYPTO_KEY_MGMT_PSK)) {
-			QDF_SET_PARAM(ap_crypto->key_mgmt,
-				      WLAN_CRYPTO_KEY_MGMT_FT_PSK);
-		}
-		if (QDF_HAS_PARAM(ap_crypto->key_mgmt,
-				  WLAN_CRYPTO_KEY_MGMT_PSK_SHA256)) {
-			QDF_SET_PARAM(ap_crypto->key_mgmt,
-				      WLAN_CRYPTO_KEY_MGMT_FT_PSK);
-		}
-		if (QDF_HAS_PARAM(ap_crypto->key_mgmt,
-				  WLAN_CRYPTO_KEY_MGMT_IEEE8021X_SHA256)) {
-			QDF_SET_PARAM(ap_crypto->key_mgmt,
-				      WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X);
-		}
-	}
+	if (is_adaptive_11r)
+		scm_check_and_update_adaptive_11r_key_mgmt_support(ap_crypto);
 
+	scm_debug("ap_crypto->key_mgmt:%d, filter->key_mgmt:%d",
+		  ap_crypto->key_mgmt, filter->key_mgmt);
 	match = scm_chk_crypto_params(filter, ap_crypto, is_adaptive_11r,
 				      db_entry, security);
 	qdf_mem_free(ap_crypto);