瀏覽代碼

qcacld-3.0: Add support for PASN cfg80211 ops

Add support for PASN cfg80211 ops:
1. set_ltf_keyseed
2. pasn_auth

Change-Id: Icfda1664a9d5e9a14c54066c4c2344fec368bec6
CRs-Fixed: 3159890
Pragaspathi Thilagaraj 3 年之前
父節點
當前提交
129b265449
共有 3 個文件被更改,包括 431 次插入7 次删除
  1. 1 0
      Kbuild
  2. 394 7
      core/hdd/src/wlan_hdd_cfg80211.c
  3. 36 0
      core/hdd/src/wlan_hdd_hostapd.c

+ 1 - 0
Kbuild

@@ -2342,6 +2342,7 @@ WIFI_POS_OBJS := $(WIFI_POS_CORE_DIR)/wifi_pos_api.o \
 		 $(WIFI_POS_CORE_DIR)/wifi_pos_ucfg.o \
 		 $(WIFI_POS_CORE_DIR)/wifi_pos_utils.o \
 		 $(WIFI_POS_OS_IF_DIR)/os_if_wifi_pos.o \
+		 $(WIFI_POS_OS_IF_DIR)/os_if_wifi_pos_utils.o \
 		 $(WIFI_POS_OS_IF_DIR)/wlan_cfg80211_wifi_pos.o \
 		 $(WIFI_POS_TGT_DIR)/target_if_wifi_pos.o \
 		 $(WIFI_POS_TGT_DIR)/target_if_wifi_pos_rx_ops.o \

+ 394 - 7
core/hdd/src/wlan_hdd_cfg80211.c

@@ -132,6 +132,7 @@
 #include "cfg_ucfg_api.h"
 
 #include "wlan_crypto_def_i.h"
+#include "wifi_pos_ucfg_i.h"
 #include "wlan_crypto_global_api.h"
 #include "wlan_nl_to_crypto_params.h"
 #include "wlan_crypto_global_def.h"
@@ -176,6 +177,8 @@
 #include "qdf_util.h"
 #include "wlan_hdd_mdns_offload.h"
 #include "wlan_pkt_capture_ucfg_api.h"
+#include "wifi_pos_public_struct.h"
+#include "wifi_pos_pasn_api.h"
 #include "os_if_pkt_capture.h"
 #include "wlan_hdd_son.h"
 #include "wlan_hdd_mcc_quota.h"
@@ -20357,6 +20360,129 @@ static int wlan_hdd_add_key_sta(struct wlan_objmgr_pdev *pdev,
 	return errno;
 }
 
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+static int wlan_cfg80211_set_pasn_key(struct wlan_objmgr_psoc *psoc,
+				      struct wlan_objmgr_vdev *vdev,
+				      struct key_params *params,
+				      const u8 *mac_addr,
+				      const u8 *src_addr,
+				      enum wlan_crypto_key_type key_type,
+				      int key_index)
+{
+	struct wlan_crypto_key *crypto_key;
+	struct wlan_objmgr_peer *peer;
+	struct wlan_pasn_auth_status *pasn_status;
+	enum wlan_crypto_cipher_type cipher;
+	int cipher_len, ret = 0;
+	bool is_ltf_keyseed_required;
+	QDF_STATUS status;
+
+	if (!params) {
+		osif_err("Key params is NULL");
+		return -EINVAL;
+	}
+
+	crypto_key = qdf_mem_malloc(sizeof(*crypto_key));
+	if (!crypto_key)
+		return -ENOMEM;
+
+	cipher_len = osif_nl_to_crypto_cipher_len(params->cipher);
+	if (cipher_len < 0 || params->key_len < cipher_len) {
+		osif_err("cipher length %d less than reqd len %d",
+			 params->key_len, cipher_len);
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	cipher = osif_nl_to_crypto_cipher_type(params->cipher);
+	if (!IS_WEP_CIPHER(cipher) &&
+	    key_type == WLAN_CRYPTO_KEY_TYPE_UNICAST && !mac_addr) {
+		osif_err("mac_addr is NULL for pairwise Key");
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	status = wlan_crypto_validate_key_params(cipher, key_index,
+						 params->key_len,
+						 params->seq_len);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("Invalid key params");
+		qdf_mem_free(crypto_key);
+		return -EINVAL;
+	}
+
+	wlan_cfg80211_translate_key(vdev, key_index, key_type, mac_addr,
+				    params, crypto_key);
+
+	hdd_debug("Set PASN unicast key");
+	status = ucfg_crypto_set_key_req(vdev, crypto_key, key_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		osif_err("PASN set_key failed");
+		qdf_mem_free(crypto_key);
+		return -EFAULT;
+	}
+
+	qdf_mem_free(crypto_key);
+
+	peer = wlan_objmgr_get_peer_by_mac(psoc, (uint8_t *)mac_addr,
+					   WLAN_WIFI_POS_CORE_ID);
+	if (!peer) {
+		osif_err("PASN peer is not found");
+		return -EFAULT;
+	}
+
+	/*
+	 * If LTF key seed is not required for the peer, then update
+	 * the source mac address for that peer by sending PASN auth
+	 * status command.
+	 * If LTF keyseed is required, then PASN Auth status command
+	 * will be sent after LTF keyseed command.
+	 */
+	is_ltf_keyseed_required =
+			ucfg_wifi_pos_is_ltf_keyseed_required_for_peer(peer);
+	wlan_objmgr_peer_release_ref(peer, WLAN_WIFI_POS_CORE_ID);
+	if (is_ltf_keyseed_required)
+		return 0;
+
+	pasn_status = qdf_mem_malloc(sizeof(*pasn_status));
+	if (!pasn_status)
+		return -ENOMEM;
+
+	pasn_status->vdev_id = vdev->vdev_objmgr.vdev_id;
+	pasn_status->num_peers = 1;
+
+	if (mac_addr)
+		qdf_mem_copy(pasn_status->auth_status[0].peer_mac.bytes,
+			     mac_addr, QDF_MAC_ADDR_SIZE);
+
+	if (src_addr)
+		qdf_mem_copy(pasn_status->auth_status[0].self_mac.bytes,
+			     src_addr, QDF_MAC_ADDR_SIZE);
+
+	status = wifi_pos_send_pasn_auth_status(psoc, pasn_status);
+	if (QDF_IS_STATUS_ERROR(status))
+		osif_err("Send PASN auth status failed");
+
+	ret = qdf_status_to_os_return(status);
+
+	qdf_mem_free(pasn_status);
+
+	return ret;
+}
+#else
+static inline
+int wlan_cfg80211_set_pasn_key(struct wlan_objmgr_psoc *psoc,
+			       struct wlan_objmgr_vdev *vdev,
+			       struct key_params *params,
+			       const u8 *mac_addr,
+			       const u8 *src_addr,
+			       enum wlan_crypto_key_type key_type,
+			       int key_index)
+{
+	return 0;
+}
+#endif
+
 static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 				       struct net_device *ndev,
 				       u8 key_index, bool pairwise,
@@ -20367,7 +20493,8 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 	mac_handle_t mac_handle;
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
 	struct wlan_objmgr_vdev *vdev;
-	bool ft_mode = false;
+	struct wlan_objmgr_peer *peer;
+	bool ft_mode = false, is_peer_type_pasn;
 	enum wlan_crypto_cipher_type cipher;
 	int errno;
 	int32_t cipher_cap, ucast_cipher = 0;
@@ -20395,7 +20522,7 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 	hdd_debug("converged Device_mode %s(%d) index %d, pairwise %d",
 		  qdf_opmode_str(adapter->device_mode),
 		  adapter->device_mode, key_index, pairwise);
-	 mac_handle = hdd_ctx->mac_handle;
+	mac_handle = hdd_ctx->mac_handle;
 
 	if (hdd_is_btk_enc_type(params->cipher))
 		return sme_add_key_btk(mac_handle, adapter->vdev_id,
@@ -20407,6 +20534,7 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 	vdev = hdd_objmgr_get_vdev_by_user(adapter, WLAN_OSIF_ID);
 	if (!vdev)
 		return -EINVAL;
+
 	if (!pairwise && ((adapter->device_mode == QDF_STA_MODE) ||
 	    (adapter->device_mode == QDF_P2P_CLIENT_MODE))) {
 		qdf_mem_copy(mac_address.bytes,
@@ -20417,6 +20545,25 @@ static int __wlan_hdd_cfg80211_add_key(struct wiphy *wiphy,
 			qdf_mem_copy(mac_address.bytes, mac_addr,
 				     QDF_MAC_ADDR_SIZE);
 	}
+
+	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, mac_address.bytes,
+					   WLAN_OSIF_ID);
+	is_peer_type_pasn = peer &&
+			    (wlan_peer_get_peer_type(peer) ==
+			     WLAN_PEER_RTT_PASN);
+	wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
+
+	if (is_peer_type_pasn) {
+		errno = wlan_cfg80211_set_pasn_key(
+				hdd_ctx->psoc,
+				vdev, params, mac_addr, NULL,
+				(pairwise ?
+				 WLAN_CRYPTO_KEY_TYPE_UNICAST : WLAN_CRYPTO_KEY_TYPE_GROUP),
+				 key_index);
+
+		return errno;
+	}
+
 	errno = wlan_cfg80211_store_key(vdev, key_index,
 					(pairwise ?
 					WLAN_CRYPTO_KEY_TYPE_UNICAST :
@@ -20683,7 +20830,9 @@ static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
  * This function is required for cfg80211_ops API.
  * It is used to delete the key information
  * Underlying hardware implementation does not have API to delete the
- * encryption key. It is automatically deleted when the peer is
+ * encryption key for normal peers. Currently delete keys are supported
+ * only for PASN peers.
+ * For other peers, it is automatically deleted when the peer is
  * removed. Hence this function currently does nothing.
  * Future implementation may interprete delete key operation to
  * replacing the key with a random junk value, effectively making it
@@ -20693,12 +20842,58 @@ static int wlan_hdd_cfg80211_get_key(struct wiphy *wiphy,
  */
 
 static int __wlan_hdd_cfg80211_del_key(struct wiphy *wiphy,
-				     struct net_device *ndev,
-				     u8 key_index,
-				     bool pairwise, const u8 *mac_addr)
+				       struct net_device *ndev,
+				       u8 key_index,
+				       bool pairwise, const u8 *mac_addr)
 {
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(ndev);
+	struct wlan_objmgr_peer *peer;
+	struct qdf_mac_addr peer_mac;
+	enum wlan_peer_type peer_type;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	int ret;
+
+	hdd_enter();
+
+	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
+		return -EINVAL;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (!mac_addr) {
+		hdd_err("Peer mac address is NULL");
+		return 0;
+	}
+
+	qdf_mem_copy(peer_mac.bytes, mac_addr, QDF_MAC_ADDR_SIZE);
+	if (qdf_is_macaddr_zero(&peer_mac) ||
+	    qdf_is_macaddr_broadcast(&peer_mac)) {
+		hdd_err("Invalid mac address");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	peer = wlan_objmgr_get_peer_by_mac(hdd_ctx->psoc, peer_mac.bytes,
+					   WLAN_OSIF_ID);
+	if (peer) {
+		peer_type = wlan_peer_get_peer_type(peer);
+		if (peer_type == WLAN_PEER_RTT_PASN) {
+			status = wifi_pos_send_pasn_peer_deauth(hdd_ctx->psoc,
+								&peer_mac);
+			if (QDF_IS_STATUS_ERROR(status))
+				hdd_err("send_pasn_peer_deauth failed");
+
+			ret = qdf_status_to_os_return(status);
+		}
+		wlan_objmgr_peer_release_ref(peer, WLAN_OSIF_ID);
+	}
+err:
 	hdd_exit();
-	return 0;
+
+	return ret;
 }
 
 /**
@@ -23818,6 +24013,194 @@ wlan_hdd_cfg80211_external_auth(struct wiphy *wiphy,
 }
 #endif
 
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+static int
+__wlan_hdd_cfg80211_send_pasn_auth_status(struct wiphy *wiphy,
+					  struct net_device *dev,
+					  struct cfg80211_pasn_params *params)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct wlan_pasn_auth_status *data;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	int ret, i;
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
+		return -EINVAL;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	data = qdf_mem_malloc(sizeof(*data));
+	if (!data)
+		return -ENOMEM;
+
+	data->vdev_id = adapter->vdev_id;
+	data->num_peers = params->num_pasn_peers;
+	if (!data->num_peers) {
+		hdd_err("No peers");
+		qdf_mem_free(data);
+		return -EINVAL;
+	}
+
+	if (data->num_peers > WLAN_MAX_11AZ_PEERS)
+		data->num_peers = WLAN_MAX_11AZ_PEERS;
+
+	for (i = 0; i < data->num_peers; i++) {
+		data->auth_status[i].status = params->peer[i].status;
+		if (params->peer[i].peer_addr)
+			qdf_mem_copy(data->auth_status[i].peer_mac.bytes,
+				     params->peer[i].peer_addr,
+				     QDF_MAC_ADDR_SIZE);
+
+		if (params->peer[i].src_addr)
+			qdf_mem_copy(data->auth_status[i].self_mac.bytes,
+				     params->peer[i].src_addr,
+				     QDF_MAC_ADDR_SIZE);
+	}
+
+	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc, data);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Send pasn auth status failed");
+
+	qdf_mem_free(data);
+	ret = qdf_status_to_os_return(status);
+
+	return ret;
+}
+
+static int
+__wlan_hdd_cfg80211_set_ltf_keyseed(struct wiphy *wiphy, struct net_device *dev,
+				    struct cfg80211_ltf_keyseed_conf *conf)
+{
+	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+	struct wlan_crypto_ltf_keyseed_data *data;
+	struct wlan_pasn_auth_status *pasn_auth_status;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	int ret;
+
+	if (hdd_get_conparam() == QDF_GLOBAL_FTM_MODE) {
+		hdd_err("Command not allowed in FTM mode");
+		return -EPERM;
+	}
+
+	if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
+		return -EINVAL;
+
+	ret = wlan_hdd_validate_context(hdd_ctx);
+	if (ret)
+		return ret;
+
+	if (!conf->bssid) {
+		hdd_err("Null BSSID");
+		return -EINVAL;
+	}
+
+	data = qdf_mem_malloc(sizeof(*data));
+	if (!data)
+		return -ENOMEM;
+
+	data->vdev_id = adapter->vdev_id;
+	qdf_mem_copy(data->peer_mac_addr.bytes, conf->bssid, QDF_MAC_ADDR_SIZE);
+
+	if (conf->src_addr)
+		qdf_mem_copy(data->src_mac_addr.bytes, conf->src_addr,
+			     QDF_MAC_ADDR_SIZE);
+
+	data->key_seed_len = conf->ltf_keyseed_len;
+	if (!data->key_seed_len ||
+	    data->key_seed_len < WLAN_MIN_SECURE_LTF_KEYSEED_LEN) {
+		hdd_err("Invalid key seed length:%d", conf->ltf_keyseed_len);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	qdf_mem_copy(data->key_seed, conf->ltf_keyseed,
+		     data->key_seed_len);
+
+	status = wlan_crypto_set_ltf_keyseed(hdd_ctx->psoc, data);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Set LTF Keyseed failed");
+		ret = qdf_status_to_os_return(status);
+		goto err;
+	}
+
+	/*
+	 * Send PASN Auth status followed by SET LTF keyseed command to
+	 * set the peer as authorized at firmware and firmware will start
+	 * ranging after this.
+	 */
+	pasn_auth_status = qdf_mem_malloc(sizeof(*pasn_auth_status));
+	if (!pasn_auth_status) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	pasn_auth_status->vdev_id = adapter->vdev_id;
+	pasn_auth_status->num_peers = 1;
+	qdf_mem_copy(pasn_auth_status->auth_status[0].peer_mac.bytes,
+		     conf->bssid, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(pasn_auth_status->auth_status[0].self_mac.bytes,
+		     conf->src_addr, QDF_MAC_ADDR_SIZE);
+
+	status = wifi_pos_send_pasn_auth_status(hdd_ctx->psoc,
+						pasn_auth_status);
+	qdf_mem_free(pasn_auth_status);
+	if (QDF_IS_STATUS_ERROR(status))
+		hdd_err("Send PASN auth status failed");
+
+	ret = qdf_status_to_os_return(status);
+err:
+	qdf_mem_free(data);
+
+	return ret;
+}
+
+static int
+wlan_hdd_cfg80211_set_ltf_keyseed(struct wiphy *wiphy, struct net_device *dev,
+				  struct cfg80211_ltf_keyseed_conf *conf)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_set_ltf_keyseed(wiphy, dev, conf);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
+
+static int
+wlan_hdd_cfg80211_send_pasn_auth_status(struct wiphy *wiphy,
+					struct net_device *dev,
+					struct cfg80211_pasn_params *params)
+{
+	int errno;
+	struct osif_vdev_sync *vdev_sync;
+
+	errno = osif_vdev_sync_op_start(dev, &vdev_sync);
+	if (errno)
+		return errno;
+
+	errno = __wlan_hdd_cfg80211_send_pasn_auth_status(wiphy, dev, params);
+
+	osif_vdev_sync_op_stop(vdev_sync);
+
+	return errno;
+}
+#endif
+
 #if defined(WLAN_FEATURE_NAN) && \
 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
 static int
@@ -24797,6 +25180,10 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = {
 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
 	.external_auth = wlan_hdd_cfg80211_external_auth,
 #endif
+#if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
+	.set_ltf_keyseed = wlan_hdd_cfg80211_set_ltf_keyseed,
+	.pasn_auth = wlan_hdd_cfg80211_send_pasn_auth_status,
+#endif
 #if defined(WLAN_FEATURE_NAN) && \
 	   (KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE)
 	.start_nan = wlan_hdd_cfg80211_start_nan,

+ 36 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -5709,6 +5709,36 @@ static QDF_STATUS wlan_hdd_mlo_update(struct hdd_context *hdd_ctx,
 }
 #endif
 
+static void
+hdd_softap_update_pasn_vdev_params(struct hdd_context *hdd_ctx,
+				   uint8_t vdev_id,
+				   struct hdd_beacon_data *beacon,
+				   bool mfp_capable, bool mfp_required)
+{
+	uint32_t pasn_vdev_param = 0;
+	const uint8_t *rsnx_ie, *rsnxe_cap;
+	uint8_t cap_len;
+
+	if (mfp_capable)
+		pasn_vdev_param |= WLAN_CRYPTO_MFPC;
+
+	if (mfp_required)
+		pasn_vdev_param |= WLAN_CRYPTO_MFPR;
+
+	rsnx_ie = wlan_get_ie_ptr_from_eid(WLAN_ELEMID_RSNXE,
+					   beacon->tail, beacon->tail_len);
+	if (!rsnx_ie)
+		return;
+
+	rsnxe_cap = wlan_crypto_parse_rsnxe_ie(rsnx_ie, &cap_len);
+	if (*rsnxe_cap & WLAN_CRYPTO_RSNX_CAP_URNM_MFPR)
+		pasn_vdev_param |= WLAN_CRYPTO_URNM_MFPR;
+
+	wlan_crypto_vdev_set_param(hdd_ctx->psoc, vdev_id,
+				   WMI_VDEV_PARAM_11AZ_SECURITY_CONFIG,
+				   pasn_vdev_param);
+}
+
 /**
  * wlan_hdd_cfg80211_start_bss() - start bss
  * @adapter: Pointer to hostapd adapter
@@ -6048,6 +6078,12 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 					   QDF_TRACE_LEVEL_DEBUG,
 					   config->akm_list.authType,
 					   config->akm_list.numEntries);
+
+			hdd_softap_update_pasn_vdev_params(hdd_ctx,
+							   adapter->vdev_id,
+							   beacon,
+							   mfp_capable,
+							   mfp_required);
 		}
 	}