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 return flags; 112 } 113 114 struct 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 121 static 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, 0, sizeof(cmd), &cmd); 145 146 if (err) 147 data->err = err; 148 } 149 150 int 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(mvm->hw, vif, iwl_mvm_mld_update_sta_key, 163 &data); 164 return data.err; 165 } 166 167 static 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 181 int 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 241 int 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 293 static 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 342 int 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 350 static 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 372 void 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(mvm->hw, vif, 388 iwl_mvm_sec_key_remove_ap_iter, 389 (void *)(uintptr_t)link_id); 390 } 391