1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2022 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 STA */
28 	if (vif->type == NL80211_IFTYPE_AP &&
29 	    !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
30 		return BIT(link_info->mcast_sta.sta_id);
31 
32 	/* for client mode use the AP STA also for group keys */
33 	if (!sta && vif->type == NL80211_IFTYPE_STATION)
34 		sta = mvmvif->ap_sta;
35 
36 	/* During remove the STA was removed and the group keys come later
37 	 * (which sounds like a bad sequence, but remember that to mac80211 the
38 	 * group keys have no sta pointer), so we don't have a STA now.
39 	 * Since this happens for group keys only, just use the link_info as
40 	 * the group keys are per link; make sure that is the case by checking
41 	 * we do have a link_id or are not doing MLO.
42 	 * Of course the same can be done during add as well, but we must do
43 	 * it during remove, since we don't have the mvmvif->ap_sta pointer.
44 	 */
45 	if (!sta && (keyconf->link_id >= 0 || !vif->valid_links))
46 		return BIT(link_info->ap_sta_id);
47 
48 	/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
49 
50 	/* pass link_id to filter by it if not -1 (GTK on client) */
51 	return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
52 }
53 
54 u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
55 			  struct ieee80211_vif *vif,
56 			  struct ieee80211_sta *sta,
57 			  struct ieee80211_key_conf *keyconf)
58 {
59 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
60 	u32 flags = 0;
61 
62 	lockdep_assert_held(&mvm->mutex);
63 
64 	if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
65 		flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
66 
67 	switch (keyconf->cipher) {
68 	case WLAN_CIPHER_SUITE_WEP104:
69 		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
70 		fallthrough;
71 	case WLAN_CIPHER_SUITE_WEP40:
72 		flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP;
73 		break;
74 	case WLAN_CIPHER_SUITE_TKIP:
75 		flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP;
76 		break;
77 	case WLAN_CIPHER_SUITE_AES_CMAC:
78 	case WLAN_CIPHER_SUITE_CCMP:
79 		flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP;
80 		break;
81 	case WLAN_CIPHER_SUITE_GCMP_256:
82 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
83 		flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
84 		fallthrough;
85 	case WLAN_CIPHER_SUITE_GCMP:
86 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
87 		flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP;
88 		break;
89 	}
90 
91 	if (!sta && vif->type == NL80211_IFTYPE_STATION)
92 		sta = mvmvif->ap_sta;
93 
94 	if (!IS_ERR_OR_NULL(sta) && sta->mfp)
95 		flags |= IWL_SEC_KEY_FLAG_MFP;
96 
97 	return flags;
98 }
99 
100 struct iwl_mvm_sta_key_update_data {
101 	struct ieee80211_sta *sta;
102 	u32 old_sta_mask;
103 	u32 new_sta_mask;
104 	int err;
105 };
106 
107 static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw,
108 				       struct ieee80211_vif *vif,
109 				       struct ieee80211_sta *sta,
110 				       struct ieee80211_key_conf *key,
111 				       void *_data)
112 {
113 	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
114 	struct iwl_mvm_sta_key_update_data *data = _data;
115 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
116 	struct iwl_sec_key_cmd cmd = {
117 		.action = cpu_to_le32(FW_CTXT_ACTION_MODIFY),
118 		.u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask),
119 		.u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask),
120 		.u.modify.key_id = cpu_to_le32(key->keyidx),
121 		.u.modify.key_flags =
122 			cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)),
123 	};
124 	int err;
125 
126 	/* only need to do this for pairwise keys (link_id == -1) */
127 	if (sta != data->sta || key->link_id >= 0)
128 		return;
129 
130 	err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd);
131 
132 	if (err)
133 		data->err = err;
134 }
135 
136 int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm,
137 				struct ieee80211_vif *vif,
138 				struct ieee80211_sta *sta,
139 				u32 old_sta_mask,
140 				u32 new_sta_mask)
141 {
142 	struct iwl_mvm_sta_key_update_data data = {
143 		.sta = sta,
144 		.old_sta_mask = old_sta_mask,
145 		.new_sta_mask = new_sta_mask,
146 	};
147 
148 	ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key,
149 				&data);
150 	return data.err;
151 }
152 
153 static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask,
154 				 u32 key_flags, u32 keyidx, u32 flags)
155 {
156 	u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
157 	struct iwl_sec_key_cmd cmd = {
158 		.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE),
159 		.u.remove.sta_mask = cpu_to_le32(sta_mask),
160 		.u.remove.key_id = cpu_to_le32(keyidx),
161 		.u.remove.key_flags = cpu_to_le32(key_flags),
162 	};
163 
164 	return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd);
165 }
166 
167 int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags,
168 			 struct ieee80211_key_conf *keyconf)
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_ADD),
173 		.u.add.sta_mask = cpu_to_le32(sta_mask),
174 		.u.add.key_id = cpu_to_le32(keyconf->keyidx),
175 		.u.add.key_flags = cpu_to_le32(key_flags),
176 		.u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)),
177 	};
178 	int ret;
179 
180 	if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key)))
181 		return -EINVAL;
182 
183 	if (WARN_ON(!sta_mask))
184 		return -EINVAL;
185 
186 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
187 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
188 		memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key,
189 		       keyconf->keylen);
190 	else
191 		memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen);
192 
193 	if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) {
194 		memcpy(cmd.u.add.tkip_mic_rx_key,
195 		       keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
196 		       8);
197 		memcpy(cmd.u.add.tkip_mic_tx_key,
198 		       keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY,
199 		       8);
200 	}
201 
202 	ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
203 	if (ret)
204 		return ret;
205 
206 	/*
207 	 * For WEP, the same key is used for multicast and unicast so need to
208 	 * upload it again. If this fails, remove the original as well.
209 	 */
210 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
211 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
212 		cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY);
213 		ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd);
214 		if (ret)
215 			__iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
216 					      keyconf->keyidx, 0);
217 	}
218 
219 	return ret;
220 }
221 
222 int iwl_mvm_sec_key_add(struct iwl_mvm *mvm,
223 			struct ieee80211_vif *vif,
224 			struct ieee80211_sta *sta,
225 			struct ieee80211_key_conf *keyconf)
226 {
227 	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
228 	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
229 
230 	return iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf);
231 }
232 
233 static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
234 				struct ieee80211_vif *vif,
235 				struct ieee80211_sta *sta,
236 				struct ieee80211_key_conf *keyconf,
237 				u32 flags)
238 {
239 	u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf);
240 	u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf);
241 	int ret;
242 
243 	if (WARN_ON(!sta_mask))
244 		return -EINVAL;
245 
246 	ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
247 				    flags);
248 	if (ret)
249 		return ret;
250 
251 	/* For WEP, delete the key again as unicast */
252 	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
253 	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
254 		key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY;
255 		ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
256 					    keyconf->keyidx, flags);
257 	}
258 
259 	return ret;
260 }
261 
262 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm,
263 			struct ieee80211_vif *vif,
264 			struct ieee80211_sta *sta,
265 			struct ieee80211_key_conf *keyconf)
266 {
267 	return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0);
268 }
269 
270 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw,
271 					   struct ieee80211_vif *vif,
272 					   struct ieee80211_sta *sta,
273 					   struct ieee80211_key_conf *key,
274 					   void *data)
275 {
276 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
277 	unsigned int link_id = (uintptr_t)data;
278 
279 	if (key->hw_key_idx == STA_KEY_IDX_INVALID)
280 		return;
281 
282 	if (sta)
283 		return;
284 
285 	if (key->link_id >= 0 && key->link_id != link_id)
286 		return;
287 
288 	_iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC);
289 	key->hw_key_idx = STA_KEY_IDX_INVALID;
290 }
291 
292 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm,
293 			       struct ieee80211_vif *vif,
294 			       struct iwl_mvm_vif_link_info *link,
295 			       unsigned int link_id)
296 {
297 	u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD);
298 	u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0);
299 
300 	if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION ||
301 			 link->ap_sta_id == IWL_MVM_INVALID_STA))
302 		return;
303 
304 	if (!sec_key_ver)
305 		return;
306 
307 	ieee80211_iter_keys_rcu(mvm->hw, vif,
308 				iwl_mvm_sec_key_remove_ap_iter,
309 				(void *)(uintptr_t)link_id);
310 }
311