Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 17e22b53 authored by Yu Wang's avatar Yu Wang
Browse files

qcacmn: enhance crypto api to install key synchronously

Add parameter 'bool sync' for wlan_cfg80211_crypto_add_key()
to indicate whether or not to add key synchronously.
If it's set to true, wait until install key complete event
is received.

Change-Id: I9a69d486665fb3f65a5720ccfbfb638c09329418
CRs-Fixed: 2865832
parent 0ba7a588
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -416,6 +416,16 @@ static QDF_STATUS dispatcher_deinit_crypto(void)
{
	return wlan_crypto_deinit();
}

static QDF_STATUS dispatcher_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
	return wlan_crypto_psoc_enable(psoc);
}

static QDF_STATUS dispatcher_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
	return wlan_crypto_psoc_disable(psoc);
}
#else
static QDF_STATUS dispatcher_init_crypto(void)
{
@@ -426,6 +436,16 @@ static QDF_STATUS dispatcher_deinit_crypto(void)
{
	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS dispatcher_crypto_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS dispatcher_crypto_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
	return QDF_STATUS_SUCCESS;
}
#endif /* END of WLAN_CONV_CRYPTO_SUPPORTED */

#ifdef WIFI_POS_CONVERGED
@@ -1055,12 +1075,17 @@ QDF_STATUS dispatcher_psoc_enable(struct wlan_objmgr_psoc *psoc)
	if (QDF_STATUS_SUCCESS != dispatcher_dbr_psoc_enable(psoc))
		goto dbr_psoc_enable_fail;

	if (QDF_STATUS_SUCCESS != dispatcher_crypto_psoc_enable(psoc))
		goto crypto_psoc_enable_fail;

	if (QDF_STATUS_SUCCESS != wlan_mlme_psoc_enable(psoc))
		goto mlme_psoc_enable_fail;

	return QDF_STATUS_SUCCESS;

mlme_psoc_enable_fail:
	dispatcher_crypto_psoc_disable(psoc);
crypto_psoc_enable_fail:
	dispatcher_dbr_psoc_disable(psoc);
dbr_psoc_enable_fail:
	fd_psoc_disable(psoc);
@@ -1087,6 +1112,8 @@ QDF_STATUS dispatcher_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
	QDF_BUG(QDF_STATUS_SUCCESS == wlan_mlme_psoc_disable(psoc));

	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_crypto_psoc_disable(psoc));

	QDF_BUG(QDF_STATUS_SUCCESS == dispatcher_dbr_psoc_disable(psoc));

	QDF_BUG(QDF_STATUS_SUCCESS == fd_psoc_disable(psoc));
+4 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2019,2021 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
@@ -65,10 +65,12 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev,
 * @vdev: vdev object
 * @key_type: denotes if the add key request is for pairwise or group key
 * @key_index: Index of the key that needs to be added
 * @sync: flag to indicate whether or not to add key synchronously.
 *  DO NOT set to true if it's in scheduler context.
 *
 * Return: Zero on Success, negative value on failure
 */
int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev,
				 enum wlan_crypto_key_type key_type,
				 uint8_t key_index);
				 uint8_t key_index, bool sync);
#endif
+72 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
@@ -23,10 +23,15 @@
#include <wlan_crypto_global_api.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_crypto_main_i.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include <wlan_crypto_def_i.h>
#include <wlan_crypto_obj_mgr_i.h>
#include <net/cfg80211.h>
#include <wlan_nl_to_crypto_params.h>
#include "wlan_cfg80211_crypto.h"
#include <wlan_cfg80211.h>
#include <wlan_osif_request_manager.h>

static void wlan_cfg80211_translate_key(struct wlan_objmgr_vdev *vdev,
					uint8_t key_index,
@@ -134,19 +139,83 @@ int wlan_cfg80211_store_key(struct wlan_objmgr_vdev *vdev,
	return 0;
}

#define WLAN_WAIT_TIME_ADD_KEY 100

static void
wlan_cfg80211_crypto_add_key_cb(void *context,
				struct crypto_add_key_result *result)
{
	struct osif_request *request;
	struct crypto_add_key_result *priv;

	request = osif_request_get(context);
	if (!request) {
		osif_err("Obsolete request");
		return;
	}

	priv = osif_request_priv(request);
	qdf_mem_copy(priv, result, sizeof(*priv));
	osif_request_complete(request);
	osif_request_put(request);
}

int wlan_cfg80211_crypto_add_key(struct wlan_objmgr_vdev *vdev,
				 enum wlan_crypto_key_type key_type,
				 uint8_t key_index)
				 uint8_t key_index, bool sync)
{
	struct wlan_crypto_key *crypto_key;
	QDF_STATUS status;
	struct osif_request *request;
	struct crypto_add_key_result *result;
	struct wlan_crypto_comp_priv *priv;
	int ret;
	static const struct osif_request_params params = {
		.priv_size = sizeof(*result),
		.timeout_ms = WLAN_WAIT_TIME_ADD_KEY,
	};

	crypto_key = wlan_crypto_get_key(vdev, key_index);
	if (!crypto_key) {
		osif_err("Crypto KEY is NULL");
		return -EINVAL;
	}

	if (sync) {
		priv = wlan_get_vdev_crypto_obj(vdev);
		if (!priv) {
			osif_err("Invalid crypto_priv");
			return -EINVAL;
		}

		request = osif_request_alloc(&params);
		if (!request) {
			osif_err("Request allocation failure");
			return -ENOMEM;
		}

		priv->add_key_ctx = osif_request_cookie(request);;
		priv->add_key_cb = wlan_cfg80211_crypto_add_key_cb;

		status  = ucfg_crypto_set_key_req(vdev, crypto_key, key_type);
		if (QDF_IS_STATUS_SUCCESS(status)) {
			ret = osif_request_wait_for_response(request);
			if (ret) {
				osif_err("Target response timed out");
			} else {
				result = osif_request_priv(request);
				osif_debug("complete, vdev_id %u, ix: %u, flags: %u, status: %u",
					   result->vdev_id, result->key_ix,
					   result->key_flags, result->status);
			}
		}

		priv->add_key_ctx = NULL;
		priv->add_key_cb = NULL;
		osif_request_put(request);
	} else {
		status  = ucfg_crypto_set_key_req(vdev, crypto_key, key_type);
	}

	return qdf_status_to_os_return(status);
}
+128 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
@@ -36,6 +36,10 @@
#include <wmi_unified_api.h>
#include <wmi_unified_crypto_api.h>
#include <cdp_txrx_peer_ops.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include "wlan_crypto_def_i.h"
#include "wlan_crypto_obj_mgr_i.h"

#ifdef FEATURE_WLAN_WAPI
#ifdef FEATURE_WAPI_BIG_ENDIAN
@@ -261,9 +265,129 @@ QDF_STATUS target_if_crypto_set_key(struct wlan_objmgr_vdev *vdev,

	/* Zero-out local key variables */
	qdf_mem_zero(&params, sizeof(struct set_key_params));

	return status;
}

/**
 * target_if_crypto_install_key_comp_evt_handler() - install key complete
 *   handler
 * @handle: wma handle
 * @event: event data
 * @len: data length
 *
 * This event is sent by fw once WPA/WPA2 keys are installed in fw.
 *
 * Return: 0 for success or error code
 */
static int
target_if_crypto_install_key_comp_evt_handler(void *handle, uint8_t *event,
					      uint32_t len)
{
	struct wlan_crypto_comp_priv *priv_obj;
	struct wlan_objmgr_psoc *psoc;
	struct wlan_objmgr_vdev *vdev;
	struct wmi_install_key_comp_event params;
	QDF_STATUS status;
	wmi_unified_t wmi_handle;
	struct crypto_add_key_result result;

	if (!event || !handle) {
		target_if_err("invalid param");
		return -EINVAL;
	}

	psoc = target_if_get_psoc_from_scn_hdl(handle);
	if (!psoc) {
		target_if_err("psoc is null");
		return -EINVAL;
	}

	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
	if (!wmi_handle) {
		target_if_err("invalid wmi handle");
		return -EINVAL;
	}

	status = wmi_extract_install_key_comp_event(wmi_handle, event,
						    len, &params);
	if (QDF_IS_STATUS_ERROR(status)) {
		target_if_err("received invalid buf from target");
		return -EINVAL;
	}

	target_if_debug("vdev %d mac " QDF_MAC_ADDR_FMT " ix %x flags %x status %d",
			params.vdev_id,
			QDF_MAC_ADDR_REF(params.peer_macaddr),
			params.key_ix, params.key_flags, params.status);

	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, params.vdev_id,
						    WLAN_CRYPTO_ID);
	if (!vdev) {
		target_if_err("vdev %d is null", params.vdev_id);
		return -EINVAL;
	}

	priv_obj = wlan_get_vdev_crypto_obj(vdev);
	if (!priv_obj) {
		target_if_err("priv_obj is null");
		wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);
		return -EINVAL;
	}

	result.vdev_id = params.vdev_id;
	result.key_ix = params.key_ix;
	result.key_flags = params.key_flags;
	result.status = params.status;
	qdf_mem_copy(result.peer_macaddr, params.peer_macaddr,
		     QDF_MAC_ADDR_SIZE);

	if (priv_obj->add_key_cb)
		priv_obj->add_key_cb(priv_obj->add_key_ctx, &result);

	wlan_objmgr_vdev_release_ref(vdev, WLAN_CRYPTO_ID);

	return 0;
}

static QDF_STATUS
target_if_crypto_register_events(struct wlan_objmgr_psoc *psoc)
{
	QDF_STATUS status;

	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
		target_if_err("psoc or psoc->tgt_if_handle is null");
		return QDF_STATUS_E_INVAL;
	}

	status = wmi_unified_register_event_handler(
			get_wmi_unified_hdl_from_psoc(psoc),
			wmi_vdev_install_key_complete_event_id,
			target_if_crypto_install_key_comp_evt_handler,
			WMI_RX_WORK_CTX);
	if (QDF_IS_STATUS_ERROR(status)) {
		target_if_err("register_event_handler failed: err %d", status);
		return status;
	}

	return QDF_STATUS_SUCCESS;
}

static QDF_STATUS
target_if_crypto_deregister_events(struct wlan_objmgr_psoc *psoc)
{
	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
		target_if_err("psoc or psoc->tgt_if_handle is null");
		return QDF_STATUS_E_INVAL;
	}

	wmi_unified_unregister_event_handler(
			get_wmi_unified_hdl_from_psoc(psoc),
			wmi_vdev_install_key_complete_event_id);

	return QDF_STATUS_SUCCESS;
}

QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
{
	struct wlan_lmac_if_crypto_tx_ops *crypto;
@@ -275,6 +399,8 @@ QDF_STATUS target_if_crypto_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
	crypto = &tx_ops->crypto_tx_ops;

	crypto->set_key = target_if_crypto_set_key;
	crypto->register_events = target_if_crypto_register_events;
	crypto->deregister_events = target_if_crypto_deregister_events;

	return QDF_STATUS_SUCCESS;
}
+4 −0
Original line number Diff line number Diff line
@@ -361,6 +361,8 @@ struct wlan_crypto_req_key {
 * @defaultkey: function pointer to set default key
 * @set_key: converged function pointer to set key in hw
 * @getpn: function pointer to get current pn value of peer
 * @register_events: function pointer to register wmi event handler
 * @deregister_events: function pointer to deregister wmi event handler
 */

struct wlan_lmac_if_crypto_tx_ops {
@@ -380,6 +382,8 @@ struct wlan_lmac_if_crypto_tx_ops {
			      enum wlan_crypto_key_type key_type);
	QDF_STATUS(*getpn)(struct wlan_objmgr_vdev *vdev,
			   uint8_t *macaddr, uint32_t key_type);
	QDF_STATUS (*register_events)(struct wlan_objmgr_psoc *psoc);
	QDF_STATUS (*deregister_events)(struct wlan_objmgr_psoc *psoc);
};

/**
Loading