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_pasn(struct iwl_mvm *mvm, 339 struct ieee80211_vif *vif, 340 u32 sta_mask, 341 struct ieee80211_key_conf *keyconf) 342 { 343 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) | 344 IWL_SEC_KEY_FLAG_MFP; 345 346 if (WARN_ON(!sta_mask)) 347 return -EINVAL; 348 349 return __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, 350 0); 351 } 352 353 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 354 struct ieee80211_vif *vif, 355 struct ieee80211_sta *sta, 356 struct ieee80211_key_conf *keyconf) 357 { 358 return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0); 359 } 360 361 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw, 362 struct ieee80211_vif *vif, 363 struct ieee80211_sta *sta, 364 struct ieee80211_key_conf *key, 365 void *data) 366 { 367 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 368 unsigned int link_id = (uintptr_t)data; 369 370 if (key->hw_key_idx == STA_KEY_IDX_INVALID) 371 return; 372 373 if (sta) 374 return; 375 376 if (key->link_id >= 0 && key->link_id != link_id) 377 return; 378 379 _iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC); 380 key->hw_key_idx = STA_KEY_IDX_INVALID; 381 } 382 383 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, 384 struct ieee80211_vif *vif, 385 struct iwl_mvm_vif_link_info *link, 386 unsigned int link_id) 387 { 388 u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 389 u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); 390 391 if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION || 392 link->ap_sta_id == IWL_MVM_INVALID_STA)) 393 return; 394 395 if (!sec_key_ver) 396 return; 397 398 ieee80211_iter_keys_rcu(mvm->hw, vif, 399 iwl_mvm_sec_key_remove_ap_iter, 400 (void *)(uintptr_t)link_id); 401 } 402