Browse Source

qcacld-3.0: Add support for cross-SAE AKM roam

Pass the akm explicitly in the external auth
request to the userspace since there are many
SAE AKM suites.

Change-Id: Ifef8657f7ef75b402aa670813eba6adc5ab9853a
CRs-Fixed: 3355395
Surya Prakash Sivaraj 2 years ago
parent
commit
ae712fa3de

+ 2 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h

@@ -2325,11 +2325,13 @@ struct roam_stats_event {
  * @vdev_id: vdev id
  * @ap_bssid: SAE authentication offload AP MAC Address
  * @ta: SAE authentication offload Tx MAC Address
+ * @akm: SAE AKM type
  */
 struct auth_offload_event {
 	uint8_t vdev_id;
 	struct qdf_mac_addr ap_bssid;
 	struct qdf_mac_addr ta;
+	uint32_t akm;
 };
 
 /*

+ 3 - 2
components/wmi/src/wmi_unified_roam_tlv.c

@@ -3314,6 +3314,7 @@ extract_auth_offload_event_tlv(wmi_unified_t wmi_handle,
 	}
 
 	auth_event->vdev_id = rso_auth_start_ev->vdev_id;
+	auth_event->akm = rso_auth_start_ev->akm_suite_type;
 
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->candidate_ap_bssid,
 				   auth_event->ap_bssid.bytes);
@@ -3327,10 +3328,10 @@ extract_auth_offload_event_tlv(wmi_unified_t wmi_handle,
 	}
 
 	wmi_debug("Received Roam auth offload event for bss:"
-		  QDF_MAC_ADDR_FMT " ta:" QDF_MAC_ADDR_FMT " vdev_id: %d",
+		  QDF_MAC_ADDR_FMT " ta:" QDF_MAC_ADDR_FMT " vdev_id: %d akm: %d",
 		  QDF_MAC_ADDR_REF(auth_event->ap_bssid.bytes),
 		  QDF_MAC_ADDR_REF(auth_event->ta.bytes),
-		  auth_event->vdev_id);
+		  auth_event->vdev_id, auth_event->akm);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 30 - 4
core/hdd/src/wlan_hdd_assoc.c

@@ -261,6 +261,34 @@ void wlan_hdd_sae_copy_ta_addr(struct cfg80211_external_auth_params *params,
 {
 }
 #endif
+
+/**
+ * wlan_hdd_get_keymgmt_for_sae_akm() - Get the keymgmt OUI
+ * corresponding to the SAE AKM type
+ * @akm: AKM type
+ *
+ * This API is used to get the keymgmt OUI for the SAE AKM type.
+ * Return: keymgmt OUI
+ */
+static uint32_t
+wlan_hdd_get_keymgmt_for_sae_akm(uint32_t akm)
+{
+	if (akm == WLAN_AKM_SAE)
+		return WLAN_AKM_SUITE_SAE;
+	else if (akm == WLAN_AKM_FT_SAE)
+		return WLAN_AKM_SUITE_FT_OVER_SAE;
+	else if (akm == WLAN_AKM_SAE_EXT_KEY)
+		return WLAN_AKM_SUITE_SAE_EXT_KEY;
+	/**
+	 * Legacy FW doesn't support SAE-EXK-KEY or
+	 * Cross-SAE_AKM roaming. In such cases, send
+	 * SAE for both SAE and FT-SAE AKMs. The supplicant
+	 * has backward compatibility to handle this case.
+	 */
+	else
+		return WLAN_AKM_SUITE_SAE;
+}
+
 /**
  * wlan_hdd_sae_callback() - Sends SAE info to supplicant
  * @adapter: pointer adapter context
@@ -288,10 +316,8 @@ static void wlan_hdd_sae_callback(struct hdd_adapter *adapter,
 
 	flags = cds_get_gfp_flags();
 
-	params.key_mgmt_suite = 0x00;
-	params.key_mgmt_suite |= 0x0F << 8;
-	params.key_mgmt_suite |= 0xAC << 16;
-	params.key_mgmt_suite |= 0x8 << 24;
+	params.key_mgmt_suite =
+		wlan_hdd_get_keymgmt_for_sae_akm(sae_info->akm);
 
 	params.action = NL80211_EXTERNAL_AUTH_START;
 	qdf_mem_copy(params.bssid, sae_info->peer_mac_addr.bytes,

+ 1 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -527,6 +527,7 @@ static const u32 hdd_sta_akm_suites[] = {
 	RSN_AUTH_KEY_MGMT_OSEN,
 	WAPI_PSK_AKM_SUITE,
 	WAPI_CERT_AKM_SUITE,
+	WLAN_AKM_SUITE_SAE_EXT_KEY,
 };
 
 /*akm suits supported by AP*/

+ 4 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -188,6 +188,10 @@ extern const struct nla_policy wlan_hdd_wisa_cmd_policy[
 #define WLAN_AKM_SUITE_FT_EAP_SHA_384 0x000FAC0D
 #endif
 
+#ifndef WLAN_AKM_SUITE_SAE_EXT_KEY
+#define WLAN_AKM_SUITE_SAE_EXT_KEY 0x000FAC18
+#endif
+
 #ifdef FEATURE_WLAN_TDLS
 #define WLAN_IS_TDLS_SETUP_ACTION(action) \
 	((TDLS_SETUP_REQUEST <= action) && \

+ 4 - 1
core/mac/inc/sir_api.h

@@ -651,7 +651,8 @@ struct sme_ready_req {
 	uint16_t length;
 	QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac,
 						    uint8_t vdev_id,
-						    struct qdf_mac_addr bssid);
+						    struct qdf_mac_addr bssid,
+						    uint32_t akm);
 	pe_roam_synch_fn_t pe_roam_synch_cb;
 	stop_roaming_fn_t stop_roaming_cb;
 	QDF_STATUS (*sme_msg_cb)(struct mac_context *mac,
@@ -5157,6 +5158,7 @@ struct sir_roam_scan_stats {
  * @vdev_id: vdev id
  * @peer_mac_addr: peer MAC address
  * @ssid: SSID
+ * @akm: key mgmt suite used
  */
 struct sir_sae_info {
 	uint16_t msg_type;
@@ -5164,6 +5166,7 @@ struct sir_sae_info {
 	uint32_t vdev_id;
 	struct qdf_mac_addr peer_mac_addr;
 	tSirMacSSid ssid;
+	uint32_t akm;
 };
 
 /**

+ 22 - 2
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -590,6 +590,21 @@ static bool lim_is_preauth_ctx_exists(struct mac_context *mac_ctx,
 }
 
 #ifdef WLAN_FEATURE_SAE
+static inline
+uint32_t lim_get_sae_keymgmt_suite(uint32_t keymgmt)
+{
+	/* Select the best SAE AKM suite supported */
+	if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
+		return WLAN_AKM_SAE_EXT_KEY;
+	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_FT_SAE))
+		return WLAN_AKM_FT_SAE;
+	else if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE))
+		return WLAN_AKM_SAE;
+
+	pe_err("Invalid SAE Keymgmt suite %d", keymgmt);
+	return WLAN_AKM_SAE;
+}
+
 QDF_STATUS lim_trigger_auth_req_sae(struct mac_context *mac_ctx,
 				    struct pe_session *session,
 				    struct qdf_mac_addr *peer_bssid)
@@ -597,6 +612,7 @@ QDF_STATUS lim_trigger_auth_req_sae(struct mac_context *mac_ctx,
 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
 	struct sir_sae_info *sae_info;
 	struct scheduler_msg msg = {0};
+	uint32_t keymgmt;
 
 	sae_info = qdf_mem_malloc(sizeof(*sae_info));
 	if (!sae_info)
@@ -607,16 +623,20 @@ QDF_STATUS lim_trigger_auth_req_sae(struct mac_context *mac_ctx,
 	sae_info->vdev_id = session->smeSessionId;
 
 	qdf_copy_macaddr(&sae_info->peer_mac_addr, peer_bssid);
+	keymgmt = wlan_crypto_get_param(session->vdev,
+					WLAN_CRYPTO_PARAM_KEY_MGMT);
+	sae_info->akm = lim_get_sae_keymgmt_suite(keymgmt);
 
 	sae_info->ssid.length = session->ssId.length;
 	qdf_mem_copy(sae_info->ssid.ssId,
 		session->ssId.ssId,
 		session->ssId.length);
 
-	pe_debug("vdev_id %d ssid " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT,
+	pe_debug("vdev_id %d ssid " QDF_SSID_FMT " " QDF_MAC_ADDR_FMT "akm %d",
 		 sae_info->vdev_id,
 		 QDF_SSID_REF(sae_info->ssid.length, sae_info->ssid.ssId),
-		 QDF_MAC_ADDR_REF(sae_info->peer_mac_addr.bytes));
+		 QDF_MAC_ADDR_REF(sae_info->peer_mac_addr.bytes),
+		 sae_info->akm);
 
 	msg.type = eWNI_SME_TRIGGER_SAE;
 	msg.bodyptr = sae_info;

+ 5 - 2
core/sme/inc/csr_internal.h

@@ -597,16 +597,19 @@ bool csr_is_mcc_channel(struct mac_context *mac_ctx, uint32_t chan_freq);
  * @mac_ctx: Global mac context pointer
  * @vdev_id: Vdev id
  * @bssid: candidate AP bssid
+ * @akm: candidate AKM
  */
 QDF_STATUS
 csr_roam_auth_offload_callback(struct mac_context *mac_ctx,
 			       uint8_t vdev_id,
-			       struct qdf_mac_addr bssid);
+			       struct qdf_mac_addr bssid,
+			       uint32_t akm);
 #else
 static inline QDF_STATUS
 csr_roam_auth_offload_callback(struct mac_context *mac_ctx,
 			       uint8_t vdev_id,
-			       struct qdf_mac_addr bssid)
+			       struct qdf_mac_addr bssid,
+			       uint32_t akm)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }

+ 10 - 5
core/sme/src/csr/csr_api_roam.c

@@ -7626,6 +7626,7 @@ fail:
  * @mac_ctx: Global mac context pointer
  * @vdev_id: vdev id
  * @roam_bssid: Candidate BSSID to roam
+ * @akm: Candidate AKM
  *
  * This function calls the hdd_sme_roam_callback with reason
  * eCSR_ROAM_SAE_COMPUTE to trigger SAE auth to supplicant.
@@ -7633,7 +7634,8 @@ fail:
 static QDF_STATUS
 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
 				   uint8_t vdev_id,
-				   struct qdf_mac_addr roam_bssid)
+				   struct qdf_mac_addr roam_bssid,
+				   uint32_t akm)
 {
 	struct csr_roam_info *roam_info;
 	struct sir_sae_info sae_info;
@@ -7651,6 +7653,7 @@ csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
 
 	sae_info.msg_len = sizeof(sae_info);
 	sae_info.vdev_id = vdev_id;
+	sae_info.akm = akm;
 	wlan_cm_get_roam_offload_ssid(mac_ctx->psoc, vdev_id,
 				      sae_info.ssid.ssId,
 				      &sae_info.ssid.length);
@@ -7670,15 +7673,16 @@ csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
 static inline QDF_STATUS
 csr_process_roam_auth_sae_callback(struct mac_context *mac_ctx,
 				   uint8_t vdev_id,
-				   struct qdf_mac_addr roam_bssid)
+				   struct qdf_mac_addr roam_bssid,
+				   uint32_t akm)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }
 #endif
 
 QDF_STATUS
-csr_roam_auth_offload_callback(struct mac_context *mac_ctx,
-			       uint8_t vdev_id, struct qdf_mac_addr bssid)
+csr_roam_auth_offload_callback(struct mac_context *mac_ctx, uint8_t vdev_id,
+			       struct qdf_mac_addr bssid, uint32_t akm)
 {
 	QDF_STATUS status;
 
@@ -7686,7 +7690,8 @@ csr_roam_auth_offload_callback(struct mac_context *mac_ctx,
 	if (!QDF_IS_STATUS_SUCCESS(status))
 		return status;
 
-	status = csr_process_roam_auth_sae_callback(mac_ctx, vdev_id, bssid);
+	status = csr_process_roam_auth_sae_callback(mac_ctx, vdev_id,
+						    bssid, akm);
 
 	sme_release_global_lock(&mac_ctx->sme);
 

+ 2 - 1
core/wma/inc/wma.h

@@ -999,7 +999,8 @@ typedef struct {
 
 	QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac,
 						    uint8_t vdev_id,
-						    struct qdf_mac_addr bssid);
+						    struct qdf_mac_addr bssid,
+						    uint32_t akm);
 	QDF_STATUS (*pe_roam_synch_cb)(struct mac_context *mac,
 		uint8_t vdev_id,
 		struct roam_offload_synch_ind *roam_synch_data,

+ 4 - 2
core/wma/inc/wma_types.h

@@ -731,7 +731,8 @@ QDF_STATUS wma_register_roaming_callbacks(
 		QDF_STATUS (*csr_roam_auth_event_handle_cb)(
 			struct mac_context *mac,
 			uint8_t vdev_id,
-			struct qdf_mac_addr bssid),
+			struct qdf_mac_addr bssid,
+			uint32_t akm),
 		pe_roam_synch_fn_t pe_roam_synch_cb,
 		QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac,
 			uint8_t vdev_id,
@@ -743,7 +744,8 @@ static inline QDF_STATUS wma_register_roaming_callbacks(
 		QDF_STATUS (*csr_roam_auth_event_handle_cb)(
 			struct mac_context *mac,
 			uint8_t vdev_id,
-			struct qdf_mac_addr bssid),
+			struct qdf_mac_addr bssid,
+			uint32_t akm),
 		pe_roam_synch_fn_t pe_roam_synch_cb,
 		QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac,
 			uint8_t vdev_id,

+ 2 - 1
core/wma/src/wma_mgmt.c

@@ -3984,7 +3984,8 @@ QDF_STATUS wma_de_register_mgmt_frm_client(void)
 QDF_STATUS wma_register_roaming_callbacks(
 	QDF_STATUS (*csr_roam_auth_event_handle_cb)(struct mac_context *mac,
 						    uint8_t vdev_id,
-						    struct qdf_mac_addr bssid),
+						    struct qdf_mac_addr bssid,
+						    uint32_t akm),
 	pe_roam_synch_fn_t pe_roam_synch_cb,
 	QDF_STATUS (*pe_disconnect_cb) (struct mac_context *mac,
 					uint8_t vdev_id,

+ 2 - 1
core/wma/src/wma_scan_roam.c

@@ -296,7 +296,8 @@ cm_handle_auth_offload(struct auth_offload_event *auth_event)
 				auth_event->vdev_id,
 				auth_event->ta);
 	status = wma->csr_roam_auth_event_handle_cb(mac_ctx, auth_event->vdev_id,
-						    auth_event->ap_bssid);
+						    auth_event->ap_bssid,
+						    auth_event->akm);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		wma_err_rl("Trigger pre-auth failed");
 		return QDF_STATUS_E_FAILURE;