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