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 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 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 if (keyconf->flags & IEEE80211_KEY_FLAG_SPP_AMSDU) 112 flags |= IWL_SEC_KEY_FLAG_SPP_AMSDU; 113 114 return flags; 115 } 116 117 struct iwl_mvm_sta_key_update_data { 118 struct ieee80211_sta *sta; 119 u32 old_sta_mask; 120 u32 new_sta_mask; 121 int err; 122 }; 123 124 static void iwl_mvm_mld_update_sta_key(struct ieee80211_hw *hw, 125 struct ieee80211_vif *vif, 126 struct ieee80211_sta *sta, 127 struct ieee80211_key_conf *key, 128 void *_data) 129 { 130 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 131 struct iwl_mvm_sta_key_update_data *data = _data; 132 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 133 struct iwl_sec_key_cmd cmd = { 134 .action = cpu_to_le32(FW_CTXT_ACTION_MODIFY), 135 .u.modify.old_sta_mask = cpu_to_le32(data->old_sta_mask), 136 .u.modify.new_sta_mask = cpu_to_le32(data->new_sta_mask), 137 .u.modify.key_id = cpu_to_le32(key->keyidx), 138 .u.modify.key_flags = 139 cpu_to_le32(iwl_mvm_get_sec_flags(mvm, vif, sta, key)), 140 }; 141 int err; 142 143 /* only need to do this for pairwise keys (link_id == -1) */ 144 if (sta != data->sta || key->link_id >= 0) 145 return; 146 147 err = iwl_mvm_send_cmd_pdu(mvm, cmd_id, CMD_ASYNC, sizeof(cmd), &cmd); 148 149 if (err) 150 data->err = err; 151 } 152 153 int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm, 154 struct ieee80211_vif *vif, 155 struct ieee80211_sta *sta, 156 u32 old_sta_mask, 157 u32 new_sta_mask) 158 { 159 struct iwl_mvm_sta_key_update_data data = { 160 .sta = sta, 161 .old_sta_mask = old_sta_mask, 162 .new_sta_mask = new_sta_mask, 163 }; 164 165 ieee80211_iter_keys_rcu(mvm->hw, vif, iwl_mvm_mld_update_sta_key, 166 &data); 167 return data.err; 168 } 169 170 static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask, 171 u32 key_flags, u32 keyidx, u32 flags) 172 { 173 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 174 struct iwl_sec_key_cmd cmd = { 175 .action = cpu_to_le32(FW_CTXT_ACTION_REMOVE), 176 .u.remove.sta_mask = cpu_to_le32(sta_mask), 177 .u.remove.key_id = cpu_to_le32(keyidx), 178 .u.remove.key_flags = cpu_to_le32(key_flags), 179 }; 180 181 return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd); 182 } 183 184 int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, 185 struct ieee80211_key_conf *keyconf) 186 { 187 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 188 struct iwl_sec_key_cmd cmd = { 189 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 190 .u.add.sta_mask = cpu_to_le32(sta_mask), 191 .u.add.key_id = cpu_to_le32(keyconf->keyidx), 192 .u.add.key_flags = cpu_to_le32(key_flags), 193 .u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)), 194 }; 195 int max_key_len = sizeof(cmd.u.add.key); 196 int ret; 197 198 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 199 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) 200 max_key_len -= IWL_SEC_WEP_KEY_OFFSET; 201 202 if (WARN_ON(keyconf->keylen > max_key_len)) 203 return -EINVAL; 204 205 if (WARN_ON(!sta_mask)) 206 return -EINVAL; 207 208 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 209 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) 210 memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key, 211 keyconf->keylen); 212 else 213 memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen); 214 215 if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) { 216 memcpy(cmd.u.add.tkip_mic_rx_key, 217 keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, 218 8); 219 memcpy(cmd.u.add.tkip_mic_tx_key, 220 keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 221 8); 222 } 223 224 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 225 if (ret) 226 return ret; 227 228 /* 229 * For WEP, the same key is used for multicast and unicast so need to 230 * upload it again. If this fails, remove the original as well. 231 */ 232 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 233 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 234 cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY); 235 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 236 if (ret) 237 __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 238 keyconf->keyidx, 0); 239 } 240 241 return ret; 242 } 243 244 int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, 245 struct ieee80211_vif *vif, 246 struct ieee80211_sta *sta, 247 struct ieee80211_key_conf *keyconf) 248 { 249 u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); 250 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); 251 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 252 struct iwl_mvm_vif_link_info *mvm_link = NULL; 253 int ret; 254 255 if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { 256 unsigned int link_id = 0; 257 258 /* set to -1 for non-MLO right now */ 259 if (keyconf->link_id >= 0) 260 link_id = keyconf->link_id; 261 262 mvm_link = mvmvif->link[link_id]; 263 if (WARN_ON(!mvm_link)) 264 return -EINVAL; 265 266 if (mvm_link->igtk) { 267 IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n", 268 mvm_link->igtk->keyidx); 269 ret = iwl_mvm_sec_key_del(mvm, vif, sta, 270 mvm_link->igtk); 271 if (ret) 272 IWL_ERR(mvm, 273 "failed to remove old IGTK (ret=%d)\n", 274 ret); 275 } 276 277 WARN_ON(mvm_link->igtk); 278 } 279 280 ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); 281 if (ret) 282 return ret; 283 284 if (mvm_link) 285 mvm_link->igtk = keyconf; 286 287 /* We don't really need this, but need it to be not invalid, 288 * and if we switch links multiple times it might go to be 289 * invalid when removed. 290 */ 291 keyconf->hw_key_idx = 0; 292 293 return 0; 294 } 295 296 static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 297 struct ieee80211_vif *vif, 298 struct ieee80211_sta *sta, 299 struct ieee80211_key_conf *keyconf, 300 u32 flags) 301 { 302 u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); 303 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); 304 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 305 int ret; 306 307 if (WARN_ON(!sta_mask)) 308 return -EINVAL; 309 310 if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { 311 struct iwl_mvm_vif_link_info *mvm_link; 312 unsigned int link_id = 0; 313 314 /* set to -1 for non-MLO right now */ 315 if (keyconf->link_id >= 0) 316 link_id = keyconf->link_id; 317 318 mvm_link = mvmvif->link[link_id]; 319 if (WARN_ON(!mvm_link)) 320 return -EINVAL; 321 322 if (mvm_link->igtk == keyconf) { 323 /* no longer in HW - mark for later */ 324 mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; 325 mvm_link->igtk = NULL; 326 } 327 } 328 329 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, 330 flags); 331 if (ret) 332 return ret; 333 334 /* For WEP, delete the key again as unicast */ 335 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 336 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 337 key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY; 338 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 339 keyconf->keyidx, flags); 340 } 341 342 return ret; 343 } 344 345 int iwl_mvm_sec_key_del_pasn(struct iwl_mvm *mvm, 346 struct ieee80211_vif *vif, 347 u32 sta_mask, 348 struct ieee80211_key_conf *keyconf) 349 { 350 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) | 351 IWL_SEC_KEY_FLAG_MFP; 352 353 if (WARN_ON(!sta_mask)) 354 return -EINVAL; 355 356 return __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, 357 0); 358 } 359 360 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 361 struct ieee80211_vif *vif, 362 struct ieee80211_sta *sta, 363 struct ieee80211_key_conf *keyconf) 364 { 365 return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0); 366 } 367 368 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw, 369 struct ieee80211_vif *vif, 370 struct ieee80211_sta *sta, 371 struct ieee80211_key_conf *key, 372 void *data) 373 { 374 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 375 unsigned int link_id = (uintptr_t)data; 376 377 if (key->hw_key_idx == STA_KEY_IDX_INVALID) 378 return; 379 380 if (sta) 381 return; 382 383 if (key->link_id >= 0 && key->link_id != link_id) 384 return; 385 386 _iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC); 387 key->hw_key_idx = STA_KEY_IDX_INVALID; 388 } 389 390 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, 391 struct ieee80211_vif *vif, 392 struct iwl_mvm_vif_link_info *link, 393 unsigned int link_id) 394 { 395 u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 396 u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); 397 398 if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION || 399 link->ap_sta_id == IWL_MVM_INVALID_STA)) 400 return; 401 402 if (!sec_key_ver) 403 return; 404 405 ieee80211_iter_keys_rcu(mvm->hw, vif, 406 iwl_mvm_sec_key_remove_ap_iter, 407 (void *)(uintptr_t)link_id); 408 } 409