Преглед изворни кода

qcacld-3.0: Add support for FILS pmksa caching without ERP keys

For FILS pmksa caching, the STA can use the PMKSA cached as
part of the full 802.1x connection. When FILS PMKSA caching
is used, the supplicant might not send the ERP keys in the
connect request. So add support to allow connection when
ERP keys are not received in connect request but FILS
PMK is present in the cache.
If the PMK cache lookup is successful for the bssid,
use pmksa caching to associate, else fallback to full 802.1x
to associate to the BSS.

Change-Id: I9fa67ee5978b7199da1cb638f7f321baed6e5913
CRs-Fixed: 2710402
Pragaspathi Thilagaraj пре 4 година
родитељ
комит
df22e92942

+ 9 - 4
core/hdd/src/wlan_hdd_cfg80211.c

@@ -18654,15 +18654,15 @@ static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
 		  req->fils_erp_next_seq_num, req->auth_type,
 		  req->fils_erp_username_len, req->fils_erp_rrk_len,
 		  req->fils_erp_realm_len);
-	if (!req->fils_erp_rrk_len || !req->fils_erp_realm_len ||
-	    !req->fils_erp_username_len ||
+	if (req->fils_erp_rrk_len || req->fils_erp_realm_len ||
+	    req->fils_erp_username_len ||
 	    req->fils_erp_rrk_len > FILS_MAX_RRK_LENGTH ||
 	    req->fils_erp_realm_len > FILS_MAX_REALM_LEN ||
 	    req->fils_erp_username_len > FILS_MAX_KEYNAME_NAI_LENGTH) {
 		hdd_err("length incorrect, user=%zu rrk=%zu realm=%zu",
 			req->fils_erp_username_len, req->fils_erp_rrk_len,
 			req->fils_erp_realm_len);
-		return false;
+		return true;
 	}
 
 	if (!req->fils_erp_rrk || !req->fils_erp_realm ||
@@ -18670,7 +18670,6 @@ static bool wlan_hdd_fils_data_in_limits(struct cfg80211_connect_params *req)
 		hdd_err("buffer incorrect, user=%pK rrk=%pK realm=%pK",
 			req->fils_erp_username, req->fils_erp_rrk,
 			req->fils_erp_realm);
-		return false;
 	}
 
 	return true;
@@ -18765,6 +18764,12 @@ static int wlan_hdd_cfg80211_set_fils_config(struct hdd_adapter *adapter,
 			roam_profile->fils_con_info->key_nai_length);
 		goto fils_conn_fail;
 	}
+
+	if (!req->fils_erp_username_len) {
+		hdd_err("FILS_PMKSA: No ERP username, return success");
+		return 0;
+	}
+
 	buf = roam_profile->fils_con_info->keyname_nai;
 	qdf_mem_copy(buf, req->fils_erp_username, req->fils_erp_username_len);
 	buf += req->fils_erp_username_len;

+ 33 - 15
core/mac/src/pe/lim/lim_process_fils.c

@@ -976,6 +976,11 @@ static int lim_create_fils_wrapper_data(struct pe_fils_session *fils_info)
 	if (!fils_info)
 		return 0;
 
+	if (!fils_info->keyname_nai_length || !fils_info->fils_rrk_len) {
+		pe_debug("FILS_PMKSA: NO keyname nai/RRK configured. Use PMKSA caching");
+		return 0;
+	}
+
 	buf_len =
 		/* code + identifier */
 		sizeof(uint8_t) * 2 +
@@ -1168,6 +1173,12 @@ void lim_add_fils_data_to_auth_frame(struct pe_session *session,
 	lim_fils_data_dump("Fils Session",
 		fils_info->fils_session, SIR_FILS_SESSION_LENGTH);
 
+	if (!fils_info->fils_erp_reauth_pkt ||
+	    !fils_info->fils_erp_reauth_pkt_len) {
+		pe_debug("FILS: No ERP data. Dont add auth wrapped data");
+		return;
+	}
+
 	/*  ERP Packet  */
 	/* Add element id */
 	*body = SIR_MAX_ELEMENT_ID;
@@ -1520,24 +1531,31 @@ void lim_update_fils_config(struct mac_context *mac_ctx,
 		       FILS_MAX_KEYNAME_NAI_LENGTH);
 		fils_config_info->key_nai_length = FILS_MAX_KEYNAME_NAI_LENGTH;
 	}
-	pe_fils_info->keyname_nai_data =
-		qdf_mem_malloc(fils_config_info->key_nai_length);
-	if (!pe_fils_info->keyname_nai_data)
-		return;
 
-	qdf_mem_copy(pe_fils_info->keyname_nai_data,
-		     fils_config_info->keyname_nai,
-		     fils_config_info->key_nai_length);
-	pe_fils_info->fils_rrk =
-		qdf_mem_malloc(fils_config_info->r_rk_length);
-	if (!pe_fils_info->fils_rrk) {
-		qdf_mem_free(pe_fils_info->keyname_nai_data);
-		return;
+	if (fils_config_info->key_nai_length) {
+		pe_fils_info->keyname_nai_data =
+			qdf_mem_malloc(fils_config_info->key_nai_length);
+		if (!pe_fils_info->keyname_nai_data)
+			return;
+
+		qdf_mem_copy(pe_fils_info->keyname_nai_data,
+			     fils_config_info->keyname_nai,
+			     fils_config_info->key_nai_length);
 	}
 
-	if (fils_config_info->r_rk_length <= FILS_MAX_RRK_LENGTH)
-		qdf_mem_copy(pe_fils_info->fils_rrk, fils_config_info->r_rk,
-			     fils_config_info->r_rk_length);
+	if (fils_config_info->r_rk_length) {
+		pe_fils_info->fils_rrk =
+			qdf_mem_malloc(fils_config_info->r_rk_length);
+		if (!pe_fils_info->fils_rrk) {
+			qdf_mem_free(pe_fils_info->keyname_nai_data);
+			return;
+		}
+
+		if (fils_config_info->r_rk_length <= FILS_MAX_RRK_LENGTH)
+			qdf_mem_copy(pe_fils_info->fils_rrk,
+				     fils_config_info->r_rk,
+				     fils_config_info->r_rk_length);
+	}
 
 	qdf_mem_copy(pe_fils_info->fils_pmkid, fils_config_info->pmkid,
 		     PMKID_LEN);

+ 48 - 12
core/sme/src/csr/csr_api_roam.c

@@ -14495,30 +14495,59 @@ static QDF_STATUS csr_set_ldpc_exception(struct mac_context *mac_ctx,
 
 #ifdef WLAN_FEATURE_FILS_SK
 /*
- * csr_update_fils_connection_info: Copy fils connection info to join request
+ * csr_validate_and_update_fils_info: Copy fils connection info to join request
  * @profile: pointer to profile
  * @csr_join_req: csr join request
  *
  * Return: None
  */
-static void csr_update_fils_connection_info(struct csr_roam_profile *profile,
-					    struct join_req *csr_join_req)
+static QDF_STATUS
+csr_validate_and_update_fils_info(struct mac_context *mac,
+				  struct csr_roam_profile *profile,
+				  struct bss_description *bss_desc,
+				  struct join_req *csr_join_req,
+				  uint8_t vdev_id)
 {
+	uint8_t cache_id[CACHE_ID_LEN] = {0};
+
 	if (!profile->fils_con_info)
-		return;
+		return QDF_STATUS_SUCCESS;
 
-	if (profile->fils_con_info->is_fils_connection) {
-		qdf_mem_copy(&csr_join_req->fils_con_info,
-			     profile->fils_con_info,
-			     sizeof(struct cds_fils_connection_info));
-	} else {
+	if (!profile->fils_con_info->is_fils_connection) {
+		sme_debug("FILS_PMKSA: Not a FILS connection");
 		qdf_mem_zero(&csr_join_req->fils_con_info,
 			     sizeof(struct cds_fils_connection_info));
+		return QDF_STATUS_SUCCESS;
 	}
+
+	if (bss_desc->fils_info_element.is_cache_id_present) {
+		qdf_mem_copy(cache_id, bss_desc->fils_info_element.cache_id,
+			     CACHE_ID_LEN);
+		sme_debug("FILS_PMKSA: cache_id[0]:%d, cache_id[1]:%d",
+			  cache_id[0], cache_id[1]);
+	}
+
+	if ((!profile->fils_con_info->r_rk_length ||
+	     !profile->fils_con_info->key_nai_length) &&
+	    !bss_desc->fils_info_element.is_cache_id_present &&
+	    !csr_lookup_fils_pmkid(mac, vdev_id, cache_id,
+				   csr_join_req->ssId.ssId,
+				   csr_join_req->ssId.length))
+		return QDF_STATUS_E_FAILURE;
+
+	qdf_mem_copy(&csr_join_req->fils_con_info,
+		     profile->fils_con_info,
+		     sizeof(struct cds_fils_connection_info));
+
+	return QDF_STATUS_SUCCESS;
 }
 #else
-static void csr_update_fils_connection_info(struct csr_roam_profile *profile,
-					    struct join_req *csr_join_req)
+static QDF_STATUS
+csr_validate_and_update_fils_info(struct mac_context *mac,
+				  struct csr_roam_profile *profile,
+				  struct bss_description *bss_desc,
+				  struct join_req *csr_join_req,
+				  uint8_t vdev_id)
 { }
 #endif
 
@@ -15692,7 +15721,14 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId,
 		qdf_mem_copy(&csr_join_req->bssDescription, pBssDescription,
 				pBssDescription->length +
 				sizeof(pBssDescription->length));
-		csr_update_fils_connection_info(pProfile, csr_join_req);
+
+		status = csr_validate_and_update_fils_info(mac, pProfile,
+							   pBssDescription,
+							   csr_join_req,
+							   sessionId);
+		if (QDF_IS_STATUS_ERROR(status))
+			return status;
+
 		csr_update_sae_config(csr_join_req, mac, pSession);
 		/*
 		 * conc_custom_rule1:

+ 13 - 0
core/sme/src/csr/csr_inside_api.h

@@ -1075,6 +1075,19 @@ bool csr_lookup_pmkid_using_bssid(struct mac_context *mac,
 					struct csr_roam_session *session,
 					tPmkidCacheInfo *pmk_cache);
 
+/**
+ * csr_lookup_fils_pmkid  - Lookup FILS PMKID using ssid and cache id
+ * @mac:       Pointer to mac context
+ * @vdev_id:   vdev id
+ * @cache_id:  FILS cache id
+ * @ssid:      SSID pointer
+ * @ssid_len:  SSID length
+ *
+ * Return: True if lookup is successful
+ */
+bool csr_lookup_fils_pmkid(struct mac_context *mac, uint8_t vdev_id,
+			   uint8_t *cache_id, uint8_t *ssid,
+			   uint8_t ssid_len);
 /**
  * csr_is_pmkid_found_for_peer() - check if pmkid sent by peer is present
 				   in PMK cache. Used in SAP mode.

+ 25 - 0
core/sme/src/csr/csr_util.c

@@ -2693,6 +2693,31 @@ bool csr_lookup_pmkid_using_bssid(struct mac_context *mac,
 	return true;
 }
 
+bool csr_lookup_fils_pmkid(struct mac_context *mac,
+			   uint8_t vdev_id, uint8_t *cache_id,
+			   uint8_t *ssid, uint8_t ssid_len)
+{
+	struct wlan_crypto_pmksa *pmksa;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
+						    WLAN_LEGACY_SME_ID);
+	if (!vdev) {
+		sme_err("Invalid vdev");
+		return false;
+	}
+
+	pmksa = wlan_crypto_get_fils_pmksa(vdev, cache_id, ssid, ssid_len);
+	if (!pmksa) {
+		sme_err("FILS_PMKSA: Lookup failed");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
+		return false;
+	}
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
+
+	return true;
+}
+
 /**
  * csr_update_session_pmk() - Update the pmk len and pmk in the roam session
  * @session: pointer to the CSR Roam session