All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jerome Pouiller <Jerome.Pouiller@silabs.com>
To: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	Kalle Valo <kvalo@codeaurora.org>
Cc: devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"David S . Miller" <davem@davemloft.net>,
	devicetree@vger.kernel.org, "Rob Herring" <robh+dt@kernel.org>,
	linux-mmc@vger.kernel.org, "Pali Rohár" <pali@kernel.org>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Jérôme Pouiller" <jerome.pouiller@silabs.com>
Subject: [PATCH v9 14/24] wfx: add key.c/key.h
Date: Tue, 11 Jan 2022 18:14:14 +0100	[thread overview]
Message-ID: <20220111171424.862764-15-Jerome.Pouiller@silabs.com> (raw)
In-Reply-To: <20220111171424.862764-1-Jerome.Pouiller@silabs.com>

From: Jérôme Pouiller <jerome.pouiller@silabs.com>

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
---
 drivers/net/wireless/silabs/wfx/key.c | 227 ++++++++++++++++++++++++++
 drivers/net/wireless/silabs/wfx/key.h |  19 +++
 2 files changed, 246 insertions(+)
 create mode 100644 drivers/net/wireless/silabs/wfx/key.c
 create mode 100644 drivers/net/wireless/silabs/wfx/key.h

diff --git a/drivers/net/wireless/silabs/wfx/key.c b/drivers/net/wireless/silabs/wfx/key.c
new file mode 100644
index 000000000000..8f23e8d42bd4
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/key.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Key management related functions.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "key.h"
+#include "wfx.h"
+#include "hif_tx_mib.h"
+
+static int wfx_alloc_key(struct wfx_dev *wdev)
+{
+	int idx;
+
+	idx = ffs(~wdev->key_map) - 1;
+	if (idx < 0 || idx >= MAX_KEY_ENTRIES)
+		return -1;
+
+	wdev->key_map |= BIT(idx);
+	return idx;
+}
+
+static void wfx_free_key(struct wfx_dev *wdev, int idx)
+{
+	WARN(!(wdev->key_map & BIT(idx)), "inconsistent key allocation");
+	wdev->key_map &= ~BIT(idx);
+}
+
+static u8 fill_wep_pair(struct wfx_hif_wep_pairwise_key *msg,
+			struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+	WARN(key->keylen > sizeof(msg->key_data), "inconsistent data");
+	msg->key_length = key->keylen;
+	memcpy(msg->key_data, key->key, key->keylen);
+	ether_addr_copy(msg->peer_address, peer_addr);
+	return HIF_KEY_TYPE_WEP_PAIRWISE;
+}
+
+static u8 fill_wep_group(struct wfx_hif_wep_group_key *msg,
+			 struct ieee80211_key_conf *key)
+{
+	WARN(key->keylen > sizeof(msg->key_data), "inconsistent data");
+	msg->key_id = key->keyidx;
+	msg->key_length = key->keylen;
+	memcpy(msg->key_data, key->key, key->keylen);
+	return HIF_KEY_TYPE_WEP_DEFAULT;
+}
+
+static u8 fill_tkip_pair(struct wfx_hif_tkip_pairwise_key *msg,
+			 struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+	u8 *keybuf = key->key;
+
+	WARN(key->keylen != sizeof(msg->tkip_key_data) + sizeof(msg->tx_mic_key) +
+			    sizeof(msg->rx_mic_key), "inconsistent data");
+	memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data));
+	keybuf += sizeof(msg->tkip_key_data);
+	memcpy(msg->tx_mic_key, keybuf, sizeof(msg->tx_mic_key));
+	keybuf += sizeof(msg->tx_mic_key);
+	memcpy(msg->rx_mic_key, keybuf, sizeof(msg->rx_mic_key));
+	ether_addr_copy(msg->peer_address, peer_addr);
+	return HIF_KEY_TYPE_TKIP_PAIRWISE;
+}
+
+static u8 fill_tkip_group(struct wfx_hif_tkip_group_key *msg, struct ieee80211_key_conf *key,
+			  struct ieee80211_key_seq *seq, enum nl80211_iftype iftype)
+{
+	u8 *keybuf = key->key;
+
+	WARN(key->keylen != sizeof(msg->tkip_key_data) + 2 * sizeof(msg->rx_mic_key),
+	     "inconsistent data");
+	msg->key_id = key->keyidx;
+	memcpy(msg->rx_sequence_counter, &seq->tkip.iv16, sizeof(seq->tkip.iv16));
+	memcpy(msg->rx_sequence_counter + sizeof(u16), &seq->tkip.iv32, sizeof(seq->tkip.iv32));
+	memcpy(msg->tkip_key_data, keybuf, sizeof(msg->tkip_key_data));
+	keybuf += sizeof(msg->tkip_key_data);
+	if (iftype == NL80211_IFTYPE_AP)
+		/* Use Tx MIC Key */
+		memcpy(msg->rx_mic_key, keybuf + 0, sizeof(msg->rx_mic_key));
+	else
+		/* Use Rx MIC Key */
+		memcpy(msg->rx_mic_key, keybuf + 8, sizeof(msg->rx_mic_key));
+	return HIF_KEY_TYPE_TKIP_GROUP;
+}
+
+static u8 fill_ccmp_pair(struct wfx_hif_aes_pairwise_key *msg,
+			 struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+	WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data");
+	ether_addr_copy(msg->peer_address, peer_addr);
+	memcpy(msg->aes_key_data, key->key, key->keylen);
+	return HIF_KEY_TYPE_AES_PAIRWISE;
+}
+
+static u8 fill_ccmp_group(struct wfx_hif_aes_group_key *msg,
+			  struct ieee80211_key_conf *key, struct ieee80211_key_seq *seq)
+{
+	WARN(key->keylen != sizeof(msg->aes_key_data), "inconsistent data");
+	memcpy(msg->aes_key_data, key->key, key->keylen);
+	memcpy(msg->rx_sequence_counter, seq->ccmp.pn, sizeof(seq->ccmp.pn));
+	memreverse(msg->rx_sequence_counter, sizeof(seq->ccmp.pn));
+	msg->key_id = key->keyidx;
+	return HIF_KEY_TYPE_AES_GROUP;
+}
+
+static u8 fill_sms4_pair(struct wfx_hif_wapi_pairwise_key *msg,
+			 struct ieee80211_key_conf *key, u8 *peer_addr)
+{
+	u8 *keybuf = key->key;
+
+	WARN(key->keylen != sizeof(msg->wapi_key_data) + sizeof(msg->mic_key_data),
+	     "inconsistent data");
+	ether_addr_copy(msg->peer_address, peer_addr);
+	memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data));
+	keybuf += sizeof(msg->wapi_key_data);
+	memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data));
+	msg->key_id = key->keyidx;
+	return HIF_KEY_TYPE_WAPI_PAIRWISE;
+}
+
+static u8 fill_sms4_group(struct wfx_hif_wapi_group_key *msg,
+			  struct ieee80211_key_conf *key)
+{
+	u8 *keybuf = key->key;
+
+	WARN(key->keylen != sizeof(msg->wapi_key_data) + sizeof(msg->mic_key_data),
+	     "inconsistent data");
+	memcpy(msg->wapi_key_data, keybuf, sizeof(msg->wapi_key_data));
+	keybuf += sizeof(msg->wapi_key_data);
+	memcpy(msg->mic_key_data, keybuf, sizeof(msg->mic_key_data));
+	msg->key_id = key->keyidx;
+	return HIF_KEY_TYPE_WAPI_GROUP;
+}
+
+static u8 fill_aes_cmac_group(struct wfx_hif_igtk_group_key *msg,
+			      struct ieee80211_key_conf *key, struct ieee80211_key_seq *seq)
+{
+	WARN(key->keylen != sizeof(msg->igtk_key_data), "inconsistent data");
+	memcpy(msg->igtk_key_data, key->key, key->keylen);
+	memcpy(msg->ipn, seq->aes_cmac.pn, sizeof(seq->aes_cmac.pn));
+	memreverse(msg->ipn, sizeof(seq->aes_cmac.pn));
+	msg->key_id = key->keyidx;
+	return HIF_KEY_TYPE_IGTK_GROUP;
+}
+
+static int wfx_add_key(struct wfx_vif *wvif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key)
+{
+	int ret;
+	struct wfx_hif_req_add_key k = { };
+	struct ieee80211_key_seq seq;
+	struct wfx_dev *wdev = wvif->wdev;
+	int idx = wfx_alloc_key(wvif->wdev);
+	bool pairwise = key->flags & IEEE80211_KEY_FLAG_PAIRWISE;
+
+	WARN(key->flags & IEEE80211_KEY_FLAG_PAIRWISE && !sta, "inconsistent data");
+	ieee80211_get_key_rx_seq(key, 0, &seq);
+	if (idx < 0)
+		return -EINVAL;
+	k.int_id = wvif->id;
+	k.entry_index = idx;
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	    key->cipher == WLAN_CIPHER_SUITE_WEP104) {
+		if (pairwise)
+			k.type = fill_wep_pair(&k.key.wep_pairwise_key, key, sta->addr);
+		else
+			k.type = fill_wep_group(&k.key.wep_group_key, key);
+	} else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+		if (pairwise)
+			k.type = fill_tkip_pair(&k.key.tkip_pairwise_key, key, sta->addr);
+		else
+			k.type = fill_tkip_group(&k.key.tkip_group_key, key, &seq,
+						 wvif->vif->type);
+	} else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) {
+		if (pairwise)
+			k.type = fill_ccmp_pair(&k.key.aes_pairwise_key, key, sta->addr);
+		else
+			k.type = fill_ccmp_group(&k.key.aes_group_key, key, &seq);
+	} else if (key->cipher == WLAN_CIPHER_SUITE_SMS4) {
+		if (pairwise)
+			k.type = fill_sms4_pair(&k.key.wapi_pairwise_key, key, sta->addr);
+		else
+			k.type = fill_sms4_group(&k.key.wapi_group_key, key);
+	} else if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
+		k.type = fill_aes_cmac_group(&k.key.igtk_group_key, key, &seq);
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
+	} else {
+		dev_warn(wdev->dev, "unsupported key type %d\n", key->cipher);
+		wfx_free_key(wdev, idx);
+		return -EOPNOTSUPP;
+	}
+	ret = wfx_hif_add_key(wdev, &k);
+	if (ret) {
+		wfx_free_key(wdev, idx);
+		return -EOPNOTSUPP;
+	}
+	key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE | IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
+	key->hw_key_idx = idx;
+	return 0;
+}
+
+static int wfx_remove_key(struct wfx_vif *wvif, struct ieee80211_key_conf *key)
+{
+	WARN(key->hw_key_idx >= MAX_KEY_ENTRIES, "corrupted hw_key_idx");
+	wfx_free_key(wvif->wdev, key->hw_key_idx);
+	return wfx_hif_remove_key(wvif->wdev, key->hw_key_idx);
+}
+
+int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif,
+		struct ieee80211_sta *sta, struct ieee80211_key_conf *key)
+{
+	int ret = -EOPNOTSUPP;
+	struct wfx_vif *wvif = (struct wfx_vif *)vif->drv_priv;
+
+	mutex_lock(&wvif->wdev->conf_mutex);
+	if (cmd == SET_KEY)
+		ret = wfx_add_key(wvif, sta, key);
+	if (cmd == DISABLE_KEY)
+		ret = wfx_remove_key(wvif, key);
+	mutex_unlock(&wvif->wdev->conf_mutex);
+	return ret;
+}
+
diff --git a/drivers/net/wireless/silabs/wfx/key.h b/drivers/net/wireless/silabs/wfx/key.h
new file mode 100644
index 000000000000..2234e36dbbcd
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/key.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Key management related functions.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#ifndef WFX_KEY_H
+#define WFX_KEY_H
+
+#include <net/mac80211.h>
+
+struct wfx_dev;
+struct wfx_vif;
+
+int wfx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif,
+		struct ieee80211_sta *sta, struct ieee80211_key_conf *key);
+
+#endif
-- 
2.34.1


  parent reply	other threads:[~2022-01-11 17:17 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-11 17:14 [PATCH v9 00/24] wfx: get out from the staging area Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 01/24] mmc: sdio: add SDIO IDs for Silabs WF200 chip Jerome Pouiller
2022-01-12 10:58   ` Ulf Hansson
2022-01-12 12:45     ` Kalle Valo
2022-01-11 17:14 ` [PATCH v9 02/24] dt-bindings: introduce silabs,wfx.yaml Jerome Pouiller
2022-01-11 20:49   ` Rob Herring
2022-01-11 22:19   ` Rob Herring
2022-01-12  9:51     ` Jérôme Pouiller
2022-01-11 17:14 ` [PATCH v9 03/24] wfx: add Makefile/Kconfig Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 04/24] wfx: add wfx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 05/24] wfx: add main.c/main.h Jerome Pouiller
2022-01-26  8:20   ` Jérôme Pouiller
2022-02-10 14:20     ` Kalle Valo
2022-02-10 14:41       ` Jérôme Pouiller
2022-02-10 14:51         ` Kalle Valo
2022-02-10 15:13           ` Jérôme Pouiller
2022-02-10 16:25             ` Kalle Valo
2022-02-10 16:37               ` Jérôme Pouiller
2022-02-11  7:08                 ` Kalle Valo
2022-02-10 14:23   ` Pali Rohár
2022-01-11 17:14 ` [PATCH v9 06/24] wfx: add bus.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 07/24] wfx: add bus_spi.c Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 08/24] wfx: add bus_sdio.c Jerome Pouiller
2022-01-12 10:51   ` Ulf Hansson
2022-01-12 10:58   ` Pali Rohár
2022-01-12 11:18     ` Jérôme Pouiller
2022-01-12 11:43       ` Pali Rohár
2022-01-12 12:06         ` Greg Kroah-Hartman
2022-01-12 12:14           ` Pali Rohár
2022-01-12 15:03         ` Ulf Hansson
2022-01-12 16:45         ` Jérôme Pouiller
2022-01-12 17:48           ` Pali Rohár
2022-01-12 18:23             ` Jérôme Pouiller
2022-01-13 12:07               ` Ulf Hansson
2022-01-11 17:14 ` [PATCH v9 09/24] wfx: add hwio.c/hwio.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 10/24] wfx: add fwio.c/fwio.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 11/24] wfx: add bh.c/bh.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 12/24] wfx: add hif_api_*.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 13/24] wfx: add hif_tx*.c/hif_tx*.h Jerome Pouiller
2022-01-11 17:14 ` Jerome Pouiller [this message]
2022-01-11 17:14 ` [PATCH v9 15/24] wfx: add hif_rx.c/hif_rx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 16/24] wfx: add data_rx.c/data_rx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 17/24] wfx: add queue.c/queue.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 18/24] wfx: add data_tx.c/data_tx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 19/24] wfx: add sta.c/sta.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 20/24] wfx: add scan.c/scan.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 21/24] wfx: add debug.c/debug.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 22/24] wfx: add traces.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 23/24] wfx: remove from the staging area Jerome Pouiller
2022-01-12  7:49   ` Kalle Valo
2022-01-12  9:32     ` Jérôme Pouiller
2022-01-12 12:46       ` Kalle Valo
2022-01-11 17:14 ` [PATCH v9 24/24] wfx: get out " Jerome Pouiller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220111171424.862764-15-Jerome.Pouiller@silabs.com \
    --to=jerome.pouiller@silabs.com \
    --cc=davem@davemloft.net \
    --cc=devel@driverdev.osuosl.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kvalo@codeaurora.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pali@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.