1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*
3 * Copyright (C) 2022 - 2024 Intel Corporation
4 */
5#include <linux/kernel.h>
6#include <net/mac80211.h>
7#include "mvm.h"
8#include "fw/api/context.h"
9#include "fw/api/datapath.h"
10
11static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm,
12				    struct ieee80211_vif *vif,
13				    struct ieee80211_sta *sta,
14				    struct ieee80211_key_conf *keyconf)
15{
16	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
17	struct iwl_mvm_vif_link_info *link_info = &mvmvif->deflink;
18
19	lockdep_assert_held(&mvm->mutex);
20
21	if (keyconf->link_id >= 0) {
22		link_info = mvmvif->link[keyconf->link_id];
23		if (!link_info)
24			return 0;
25	}
26
27	/* AP group keys are per link and should be on the mcast/bcast STA */
28	if (vif->type == NL80211_IFTYPE_AP &&
29	    !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
30		/* IGTK/BIGTK to bcast STA */
31		if (keyconf->keyidx >= 4)
32			return BIT(link_info->bcast_sta.sta_id);
33		/* GTK for data to mcast STA */
34		return BIT(link_info->mcast_sta.sta_id);
35	}
36
37	/* for client mode use the AP STA also for group keys */
38	if (!sta && vif->type == NL80211_IFTYPE_STATION)
39		sta = mvmvif->ap_sta;
40
41	/* During remove the STA was removed and the group keys come later
42	 * (which sounds like a bad sequence, but remember that to mac80211 the
43	 * group keys have no sta pointer), so we don't have a STA now.
44	 * Since this happens for group keys only, just use the link_info as
45	 * the group keys are per link; make sure that is the case by checking
46	 * we do have a link_id or are not doing MLO.
47	 * Of course the same can be done during add as well, but we must do
48	 * it during remove, since we don't have the mvmvif->ap_sta pointer.
49	 */
50	if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif)))
51		return BIT(link_info->ap_sta_id);
52
53	/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
54
55	/* pass link_id to filter by it if not -1 (GTK on client) */
56	return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
57}
58
59u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
60			  struct ieee80211_vif *vif,
61			  struct ieee80211_sta *sta,
62			  struct ieee80211_key_conf *keyconf)
63{
64	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
65	bool pairwise = keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE;
66	bool igtk = keyconf->keyidx == 4 || keyconf->keyidx == 5;
67	u32 flags = 0;
68
69	lockdep_assert_held(&mvm->mutex);
70
71	if (!pairwise)
72		flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
73
74	switch (keyconf->cipher) {
75	case WLAN_CIPHER_SUITE_WEP104:
76		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
77		fallthrough;
78	case WLAN_CIPHER_SUITE_WEP40:
79		flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP;
80		break;
81	case WLAN_CIPHER_SUITE_TKIP:
82		flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP;
83		break;
84	case WLAN_CIPHER_SUITE_AES_CMAC:
85	case WLAN_CIPHER_SUITE_CCMP:
86		flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP;
87		break;
88	case WLAN_CIPHER_SUITE_GCMP_256:
89	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
90		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
91		fallthrough;
92	case WLAN_CIPHER_SUITE_GCMP:
93	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
94		flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP;
95		break;
96	}
97
98	if (!sta && vif->type == NL80211_IFTYPE_STATION)
99		sta = mvmvif->ap_sta;
100
101	/*
102	 * If we are installing an iGTK (in AP or STA mode), we need to tell
103	 * the firmware this key will en/decrypt MGMT frames.
104	 * Same goes if we are installing a pairwise key for an MFP station.
105	 * In case we're installing a groupwise key (which is not an iGTK),
106	 * then, we will not use this key for MGMT frames.
107	 */
108	if ((!IS_ERR_OR_NULL(sta) && sta->mfp && pairwise) || igtk)
109		flags |= IWL_SEC_KEY_FLAG_MFP;
110
111	return flags;
112}
113
114struct iwl_mvm_sta_key_update_data {
115	struct ieee80211_sta *sta;
116	u32 old_sta_mask;
117	u32 new_sta_mask;
118	int err;
119};
120
121static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
122				       struct ieee80211_vif *vif,
123				       struct ieee80211_sta *sta,
124				       struct ieee80211_key_conf *key,
125				       void *_data)
126{
127	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
128	struct iwl_mvm_sta_key_update_data *data = _data;
129	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
130	struct iwl_sec_key_cmd cmd = {
131		.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
132		.u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
133		.u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
134		.u.modify.key_id = cpu_to_le32(key->keyidx),
135		.u.modify.key_flags =
136			cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
137	};
138	int err;
139
140	/* only need to do this for pairwise keys (link_id == -1) */
141	if (sta != data->sta || key->link_id >= 0)
142		return;
143
144	err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
145
146	if (err)
147		data->err = err;
148}
149
150int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
151				struct ieee80211_vif *vif,
152				struct ieee80211_sta *sta,
153				u32 old_sta_mask,
154				u32 new_sta_mask)
155{
156	struct iwl_mvm_sta_key_update_data data = {
157		.sta = sta,
158		.old_sta_mask = old_sta_mask,
159		.new_sta_mask = new_sta_mask,
160	};
161
162	ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
163				&data);
164	return data.err;
165}
166
167static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
168				 u32 key_flags, u32 keyidx, u32 flags)
169{
170	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
171	struct iwl_sec_key_cmd cmd = {
172		.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
173		.u.remove.sta_mask = cpu_to_le32(sta_mask),
174		.u.remove.key_id = cpu_to_le32(keyidx),
175		.u.remove.key_flags = cpu_to_le32(key_flags),
176	};
177
178	return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
179}
180
181int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
182			 struct ieee80211_key_conf *keyconf)
183{
184	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
185	struct iwl_sec_key_cmd cmd = {
186		.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
187		.u.add.sta_mask = cpu_to_le32(sta_mask),
188		.u.add.key_id = cpu_to_le32(keyconf->keyidx),
189		.u.add.key_flags = cpu_to_le32(key_flags),
190		.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
191	};
192	int max_key_len = sizeof(cmd.u.add.key);
193	int ret;
194
195	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
196	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
197		max_key_len -= IWL_SEC_WEP_KEY_OFFSET;
198
199	if (WARN_ON(keyconf->keylen > max_key_len))
200		return -EINVAL;
201
202	if (WARN_ON(!sta_mask))
203		return -EINVAL;
204
205	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
206	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
207		memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key,
208		       keyconf->keylen);
209	else
210		memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen);
211
212	if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
213		memcpy(cmd.u.add.tkip_mic_rx_key,
214		       keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
215		       8);
216		memcpy(cmd.u.add.tkip_mic_tx_key,
217		       keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY,
218		       8);
219	}
220
221	ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
222	if (ret)
223		return ret;
224
225	/*
226	 * For WEP, the same key is used for multicast and unicast so need to
227	 * upload it again. If this fails, remove the original as well.
228	 */
229	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
230	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
231		cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY);
232		ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
233		if (ret)
234			__iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
235					      keyconf->keyidx, 0);
236	}
237
238	return ret;
239}
240
241int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
242			struct ieee80211_vif *vif,
243			struct ieee80211_sta *sta,
244			struct ieee80211_key_conf *keyconf)
245{
246	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
247	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
248	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
249	struct iwl_mvm_vif_link_info *mvm_link = NULL;
250	int ret;
251
252	if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
253		unsigned int link_id = 0;
254
255		/* set to -1 for non-MLO right now */
256		if (keyconf->link_id >= 0)
257			link_id = keyconf->link_id;
258
259		mvm_link = mvmvif->link[link_id];
260		if (WARN_ON(!mvm_link))
261			return -EINVAL;
262
263		if (mvm_link->igtk) {
264			IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n",
265					   mvm_link->igtk->keyidx);
266			ret = iwl_mvm_sec_key_del(mvm, vif, sta,
267						  mvm_link->igtk);
268			if (ret)
269				IWL_ERR(mvm,
270					"failed to remove old IGTK (ret=%d)\n",
271					ret);
272		}
273
274		WARN_ON(mvm_link->igtk);
275	}
276
277	ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
278	if (ret)
279		return ret;
280
281	if (mvm_link)
282		mvm_link->igtk = keyconf;
283
284	/* We don't really need this, but need it to be not invalid,
285	 * and if we switch links multiple times it might go to be
286	 * invalid when removed.
287	 */
288	keyconf->hw_key_idx = 0;
289
290	return 0;
291}
292
293static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
294				struct ieee80211_vif *vif,
295				struct ieee80211_sta *sta,
296				struct ieee80211_key_conf *keyconf,
297				u32 flags)
298{
299	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
300	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
301	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
302	int ret;
303
304	if (WARN_ON(!sta_mask))
305		return -EINVAL;
306
307	if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
308		struct iwl_mvm_vif_link_info *mvm_link;
309		unsigned int link_id = 0;
310
311		/* set to -1 for non-MLO right now */
312		if (keyconf->link_id >= 0)
313			link_id = keyconf->link_id;
314
315		mvm_link = mvmvif->link[link_id];
316		if (WARN_ON(!mvm_link))
317			return -EINVAL;
318
319		if (mvm_link->igtk == keyconf) {
320			/* no longer in HW - mark for later */
321			mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
322			mvm_link->igtk = NULL;
323		}
324	}
325
326	ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
327				    flags);
328	if (ret)
329		return ret;
330
331	/* For WEP, delete the key again as unicast */
332	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
333	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
334		key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY;
335		ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
336					    keyconf->keyidx, flags);
337	}
338
339	return ret;
340}
341
342int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
343			struct ieee80211_vif *vif,
344			struct ieee80211_sta *sta,
345			struct ieee80211_key_conf *keyconf)
346{
347	return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0);
348}
349
350static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
351					   struct ieee80211_vif *vif,
352					   struct ieee80211_sta *sta,
353					   struct ieee80211_key_conf *key,
354					   void *data)
355{
356	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
357	unsigned int link_id = (uintptr_t)data;
358
359	if (key->hw_key_idx == STA_KEY_IDX_INVALID)
360		return;
361
362	if (sta)
363		return;
364
365	if (key->link_id >= 0 && key->link_id != link_id)
366		return;
367
368	_iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC);
369	key->hw_key_idx = STA_KEY_IDX_INVALID;
370}
371
372void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
373			       struct ieee80211_vif *vif,
374			       struct iwl_mvm_vif_link_info *link,
375			       unsigned int link_id)
376{
377	u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
378	u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
379
380	if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION ||
381			 link->ap_sta_id == IWL_MVM_INVALID_STA))
382		return;
383
384	if (!sec_key_ver)
385		return;
386
387	ieee80211_iter_keys_rcu(mvm->hw, vif,
388				iwl_mvm_sec_key_remove_ap_iter,
389				(void *)(uintptr_t)link_id);
390}
391