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 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 || !ieee80211_vif_is_mld(vif))) 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 max_key_len = sizeof(cmd.u.add.key); 179 int ret; 180 181 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 182 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) 183 max_key_len -= IWL_SEC_WEP_KEY_OFFSET; 184 185 if (WARN_ON(keyconf->keylen > max_key_len)) 186 return -EINVAL; 187 188 if (WARN_ON(!sta_mask)) 189 return -EINVAL; 190 191 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 192 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) 193 memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key, 194 keyconf->keylen); 195 else 196 memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen); 197 198 if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) { 199 memcpy(cmd.u.add.tkip_mic_rx_key, 200 keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, 201 8); 202 memcpy(cmd.u.add.tkip_mic_tx_key, 203 keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 204 8); 205 } 206 207 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 208 if (ret) 209 return ret; 210 211 /* 212 * For WEP, the same key is used for multicast and unicast so need to 213 * upload it again. If this fails, remove the original as well. 214 */ 215 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 216 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 217 cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY); 218 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 219 if (ret) 220 __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 221 keyconf->keyidx, 0); 222 } 223 224 return ret; 225 } 226 227 int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, 228 struct ieee80211_vif *vif, 229 struct ieee80211_sta *sta, 230 struct ieee80211_key_conf *keyconf) 231 { 232 u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); 233 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); 234 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 235 struct iwl_mvm_vif_link_info *mvm_link = NULL; 236 int ret; 237 238 if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { 239 unsigned int link_id = 0; 240 241 /* set to -1 for non-MLO right now */ 242 if (keyconf->link_id >= 0) 243 link_id = keyconf->link_id; 244 245 mvm_link = mvmvif->link[link_id]; 246 if (WARN_ON(!mvm_link)) 247 return -EINVAL; 248 249 if (mvm_link->igtk) { 250 IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n", 251 mvm_link->igtk->keyidx); 252 ret = iwl_mvm_sec_key_del(mvm, vif, sta, 253 mvm_link->igtk); 254 if (ret) 255 IWL_ERR(mvm, 256 "failed to remove old IGTK (ret=%d)\n", 257 ret); 258 } 259 260 WARN_ON(mvm_link->igtk); 261 } 262 263 ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); 264 if (ret) 265 return ret; 266 267 if (mvm_link) 268 mvm_link->igtk = keyconf; 269 270 /* We don't really need this, but need it to be not invalid, 271 * and if we switch links multiple times it might go to be 272 * invalid when removed. 273 */ 274 keyconf->hw_key_idx = 0; 275 276 return 0; 277 } 278 279 static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 280 struct ieee80211_vif *vif, 281 struct ieee80211_sta *sta, 282 struct ieee80211_key_conf *keyconf, 283 u32 flags) 284 { 285 u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); 286 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); 287 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 288 int ret; 289 290 if (WARN_ON(!sta_mask)) 291 return -EINVAL; 292 293 if (keyconf->keyidx == 4 || keyconf->keyidx == 5) { 294 struct iwl_mvm_vif_link_info *mvm_link; 295 unsigned int link_id = 0; 296 297 /* set to -1 for non-MLO right now */ 298 if (keyconf->link_id >= 0) 299 link_id = keyconf->link_id; 300 301 mvm_link = mvmvif->link[link_id]; 302 if (WARN_ON(!mvm_link)) 303 return -EINVAL; 304 305 if (mvm_link->igtk == keyconf) { 306 /* no longer in HW - mark for later */ 307 mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID; 308 mvm_link->igtk = NULL; 309 } 310 } 311 312 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, 313 flags); 314 if (ret) 315 return ret; 316 317 /* For WEP, delete the key again as unicast */ 318 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 319 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 320 key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY; 321 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 322 keyconf->keyidx, flags); 323 } 324 325 return ret; 326 } 327 328 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 329 struct ieee80211_vif *vif, 330 struct ieee80211_sta *sta, 331 struct ieee80211_key_conf *keyconf) 332 { 333 return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0); 334 } 335 336 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw, 337 struct ieee80211_vif *vif, 338 struct ieee80211_sta *sta, 339 struct ieee80211_key_conf *key, 340 void *data) 341 { 342 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 343 unsigned int link_id = (uintptr_t)data; 344 345 if (key->hw_key_idx == STA_KEY_IDX_INVALID) 346 return; 347 348 if (sta) 349 return; 350 351 if (key->link_id >= 0 && key->link_id != link_id) 352 return; 353 354 _iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC); 355 key->hw_key_idx = STA_KEY_IDX_INVALID; 356 } 357 358 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, 359 struct ieee80211_vif *vif, 360 struct iwl_mvm_vif_link_info *link, 361 unsigned int link_id) 362 { 363 u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 364 u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); 365 366 if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION || 367 link->ap_sta_id == IWL_MVM_INVALID_STA)) 368 return; 369 370 if (!sec_key_ver) 371 return; 372 373 ieee80211_iter_keys_rcu(mvm->hw, vif, 374 iwl_mvm_sec_key_remove_ap_iter, 375 (void *)(uintptr_t)link_id); 376 } 377