xref: /linux/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c (revision f6154d8babbb8a98f0d3ea325aafae2e33bfd8be)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2022 - 2023 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 
11 static 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 
59 u32 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 	u32 flags = 0;
66 
67 	lockdep_assert_held(&mvm->mutex);
68 
69 	if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
70 		flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
71 
72 	switch (keyconf->cipher) {
73 	case WLAN_CIPHER_SUITE_WEP104:
74 		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
75 		fallthrough;
76 	case WLAN_CIPHER_SUITE_WEP40:
77 		flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP;
78 		break;
79 	case WLAN_CIPHER_SUITE_TKIP:
80 		flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP;
81 		break;
82 	case WLAN_CIPHER_SUITE_AES_CMAC:
83 	case WLAN_CIPHER_SUITE_CCMP:
84 		flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP;
85 		break;
86 	case WLAN_CIPHER_SUITE_GCMP_256:
87 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
88 		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
89 		fallthrough;
90 	case WLAN_CIPHER_SUITE_GCMP:
91 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
92 		flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP;
93 		break;
94 	}
95 
96 	if (!sta && vif->type == NL80211_IFTYPE_STATION)
97 		sta = mvmvif->ap_sta;
98 
99 	/* Set the MFP flag also for an AP interface where the key is an IGTK
100 	 * key as in such a case the station would always be NULL
101 	 */
102 	if ((!IS_ERR_OR_NULL(sta) && sta->mfp) ||
103 	    (vif->type == NL80211_IFTYPE_AP &&
104 	     (keyconf->keyidx == 4 || keyconf->keyidx == 5)))
105 		flags |= IWL_SEC_KEY_FLAG_MFP;
106 
107 	return flags;
108 }
109 
110 struct iwl_mvm_sta_key_update_data {
111 	struct ieee80211_sta *sta;
112 	u32 old_sta_mask;
113 	u32 new_sta_mask;
114 	int err;
115 };
116 
117 static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
118 				       struct ieee80211_vif *vif,
119 				       struct ieee80211_sta *sta,
120 				       struct ieee80211_key_conf *key,
121 				       void *_data)
122 {
123 	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
124 	struct iwl_mvm_sta_key_update_data *data = _data;
125 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
126 	struct iwl_sec_key_cmd cmd = {
127 		.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
128 		.u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
129 		.u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
130 		.u.modify.key_id = cpu_to_le32(key->keyidx),
131 		.u.modify.key_flags =
132 			cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
133 	};
134 	int err;
135 
136 	/* only need to do this for pairwise keys (link_id == -1) */
137 	if (sta != data->sta || key->link_id >= 0)
138 		return;
139 
140 	err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
141 
142 	if (err)
143 		data->err = err;
144 }
145 
146 int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
147 				struct ieee80211_vif *vif,
148 				struct ieee80211_sta *sta,
149 				u32 old_sta_mask,
150 				u32 new_sta_mask)
151 {
152 	struct iwl_mvm_sta_key_update_data data = {
153 		.sta = sta,
154 		.old_sta_mask = old_sta_mask,
155 		.new_sta_mask = new_sta_mask,
156 	};
157 
158 	ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
159 				&data);
160 	return data.err;
161 }
162 
163 static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
164 				 u32 key_flags, u32 keyidx, u32 flags)
165 {
166 	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
167 	struct iwl_sec_key_cmd cmd = {
168 		.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
169 		.u.remove.sta_mask = cpu_to_le32(sta_mask),
170 		.u.remove.key_id = cpu_to_le32(keyidx),
171 		.u.remove.key_flags = cpu_to_le32(key_flags),
172 	};
173 
174 	return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
175 }
176 
177 int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
178 			 struct ieee80211_key_conf *keyconf)
179 {
180 	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
181 	struct iwl_sec_key_cmd cmd = {
182 		.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
183 		.u.add.sta_mask = cpu_to_le32(sta_mask),
184 		.u.add.key_id = cpu_to_le32(keyconf->keyidx),
185 		.u.add.key_flags = cpu_to_le32(key_flags),
186 		.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
187 	};
188 	int max_key_len = sizeof(cmd.u.add.key);
189 	int ret;
190 
191 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
192 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
193 		max_key_len -= IWL_SEC_WEP_KEY_OFFSET;
194 
195 	if (WARN_ON(keyconf->keylen > max_key_len))
196 		return -EINVAL;
197 
198 	if (WARN_ON(!sta_mask))
199 		return -EINVAL;
200 
201 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
202 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
203 		memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key,
204 		       keyconf->keylen);
205 	else
206 		memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen);
207 
208 	if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
209 		memcpy(cmd.u.add.tkip_mic_rx_key,
210 		       keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
211 		       8);
212 		memcpy(cmd.u.add.tkip_mic_tx_key,
213 		       keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY,
214 		       8);
215 	}
216 
217 	ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
218 	if (ret)
219 		return ret;
220 
221 	/*
222 	 * For WEP, the same key is used for multicast and unicast so need to
223 	 * upload it again. If this fails, remove the original as well.
224 	 */
225 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
226 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
227 		cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY);
228 		ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
229 		if (ret)
230 			__iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
231 					      keyconf->keyidx, 0);
232 	}
233 
234 	return ret;
235 }
236 
237 int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
238 			struct ieee80211_vif *vif,
239 			struct ieee80211_sta *sta,
240 			struct ieee80211_key_conf *keyconf)
241 {
242 	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
243 	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
244 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
245 	struct iwl_mvm_vif_link_info *mvm_link = NULL;
246 	int ret;
247 
248 	if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
249 		unsigned int link_id = 0;
250 
251 		/* set to -1 for non-MLO right now */
252 		if (keyconf->link_id >= 0)
253 			link_id = keyconf->link_id;
254 
255 		mvm_link = mvmvif->link[link_id];
256 		if (WARN_ON(!mvm_link))
257 			return -EINVAL;
258 
259 		if (mvm_link->igtk) {
260 			IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n",
261 					   mvm_link->igtk->keyidx);
262 			ret = iwl_mvm_sec_key_del(mvm, vif, sta,
263 						  mvm_link->igtk);
264 			if (ret)
265 				IWL_ERR(mvm,
266 					"failed to remove old IGTK (ret=%d)\n",
267 					ret);
268 		}
269 
270 		WARN_ON(mvm_link->igtk);
271 	}
272 
273 	ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
274 	if (ret)
275 		return ret;
276 
277 	if (mvm_link)
278 		mvm_link->igtk = keyconf;
279 
280 	/* We don't really need this, but need it to be not invalid,
281 	 * and if we switch links multiple times it might go to be
282 	 * invalid when removed.
283 	 */
284 	keyconf->hw_key_idx = 0;
285 
286 	return 0;
287 }
288 
289 static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
290 				struct ieee80211_vif *vif,
291 				struct ieee80211_sta *sta,
292 				struct ieee80211_key_conf *keyconf,
293 				u32 flags)
294 {
295 	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
296 	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
297 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
298 	int ret;
299 
300 	if (WARN_ON(!sta_mask))
301 		return -EINVAL;
302 
303 	if (keyconf->keyidx == 4 || keyconf->keyidx == 5) {
304 		struct iwl_mvm_vif_link_info *mvm_link;
305 		unsigned int link_id = 0;
306 
307 		/* set to -1 for non-MLO right now */
308 		if (keyconf->link_id >= 0)
309 			link_id = keyconf->link_id;
310 
311 		mvm_link = mvmvif->link[link_id];
312 		if (WARN_ON(!mvm_link))
313 			return -EINVAL;
314 
315 		if (mvm_link->igtk == keyconf) {
316 			/* no longer in HW - mark for later */
317 			mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
318 			mvm_link->igtk = NULL;
319 		}
320 	}
321 
322 	ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
323 				    flags);
324 	if (ret)
325 		return ret;
326 
327 	/* For WEP, delete the key again as unicast */
328 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
329 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
330 		key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY;
331 		ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
332 					    keyconf->keyidx, flags);
333 	}
334 
335 	return ret;
336 }
337 
338 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
339 			struct ieee80211_vif *vif,
340 			struct ieee80211_sta *sta,
341 			struct ieee80211_key_conf *keyconf)
342 {
343 	return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0);
344 }
345 
346 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
347 					   struct ieee80211_vif *vif,
348 					   struct ieee80211_sta *sta,
349 					   struct ieee80211_key_conf *key,
350 					   void *data)
351 {
352 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
353 	unsigned int link_id = (uintptr_t)data;
354 
355 	if (key->hw_key_idx == STA_KEY_IDX_INVALID)
356 		return;
357 
358 	if (sta)
359 		return;
360 
361 	if (key->link_id >= 0 && key->link_id != link_id)
362 		return;
363 
364 	_iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC);
365 	key->hw_key_idx = STA_KEY_IDX_INVALID;
366 }
367 
368 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
369 			       struct ieee80211_vif *vif,
370 			       struct iwl_mvm_vif_link_info *link,
371 			       unsigned int link_id)
372 {
373 	u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
374 	u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
375 
376 	if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION ||
377 			 link->ap_sta_id == IWL_MVM_INVALID_STA))
378 		return;
379 
380 	if (!sec_key_ver)
381 		return;
382 
383 	ieee80211_iter_keys_rcu(mvm->hw, vif,
384 				iwl_mvm_sec_key_remove_ap_iter,
385 				(void *)(uintptr_t)link_id);
386 }
387