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 static 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_sec_key_add(struct iwl_mvm *mvm, 168 struct ieee80211_vif *vif, 169 struct ieee80211_sta *sta, 170 struct ieee80211_key_conf *keyconf) 171 { 172 u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); 173 u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); 174 u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 175 struct iwl_sec_key_cmd cmd = { 176 .action = cpu_to_le32(FW_CTXT_ACTION_ADD), 177 .u.add.sta_mask = cpu_to_le32(sta_mask), 178 .u.add.key_id = cpu_to_le32(keyconf->keyidx), 179 .u.add.key_flags = cpu_to_le32(key_flags), 180 .u.add.tx_seq = cpu_to_le64(atomic64_read(&keyconf->tx_pn)), 181 }; 182 int ret; 183 184 if (WARN_ON(keyconf->keylen > sizeof(cmd.u.add.key))) 185 return -EINVAL; 186 187 if (WARN_ON(!sta_mask)) 188 return -EINVAL; 189 190 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 191 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) 192 memcpy(cmd.u.add.key + IWL_SEC_WEP_KEY_OFFSET, keyconf->key, 193 keyconf->keylen); 194 else 195 memcpy(cmd.u.add.key, keyconf->key, keyconf->keylen); 196 197 if (keyconf->cipher == WLAN_CIPHER_SUITE_TKIP) { 198 memcpy(cmd.u.add.tkip_mic_rx_key, 199 keyconf->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY, 200 8); 201 memcpy(cmd.u.add.tkip_mic_tx_key, 202 keyconf->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 203 8); 204 } 205 206 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 207 if (ret) 208 return ret; 209 210 /* 211 * For WEP, the same key is used for multicast and unicast so need to 212 * upload it again. If this fails, remove the original as well. 213 */ 214 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 215 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 216 cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY); 217 ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); 218 if (ret) 219 __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 220 keyconf->keyidx, 0); 221 } 222 223 return ret; 224 } 225 226 static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 227 struct ieee80211_vif *vif, 228 struct ieee80211_sta *sta, 229 struct ieee80211_key_conf *keyconf, 230 u32 flags) 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 int ret; 235 236 if (WARN_ON(!sta_mask)) 237 return -EINVAL; 238 239 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx, 240 flags); 241 if (ret) 242 return ret; 243 244 /* For WEP, delete the key again as unicast */ 245 if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 || 246 keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) { 247 key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY; 248 ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, 249 keyconf->keyidx, flags); 250 } 251 252 return ret; 253 } 254 255 int iwl_mvm_sec_key_del(struct iwl_mvm *mvm, 256 struct ieee80211_vif *vif, 257 struct ieee80211_sta *sta, 258 struct ieee80211_key_conf *keyconf) 259 { 260 return _iwl_mvm_sec_key_del(mvm, vif, sta, keyconf, 0); 261 } 262 263 static void iwl_mvm_sec_key_remove_ap_iter(struct ieee80211_hw *hw, 264 struct ieee80211_vif *vif, 265 struct ieee80211_sta *sta, 266 struct ieee80211_key_conf *key, 267 void *data) 268 { 269 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 270 unsigned int link_id = (uintptr_t)data; 271 272 if (key->hw_key_idx == STA_KEY_IDX_INVALID) 273 return; 274 275 if (sta) 276 return; 277 278 if (key->link_id >= 0 && key->link_id != link_id) 279 return; 280 281 _iwl_mvm_sec_key_del(mvm, vif, NULL, key, CMD_ASYNC); 282 key->hw_key_idx = STA_KEY_IDX_INVALID; 283 } 284 285 void iwl_mvm_sec_key_remove_ap(struct iwl_mvm *mvm, 286 struct ieee80211_vif *vif, 287 struct iwl_mvm_vif_link_info *link, 288 unsigned int link_id) 289 { 290 u32 sec_key_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); 291 u8 sec_key_ver = iwl_fw_lookup_cmd_ver(mvm->fw, sec_key_id, 0); 292 293 if (WARN_ON_ONCE(vif->type != NL80211_IFTYPE_STATION || 294 link->ap_sta_id == IWL_MVM_INVALID_STA)) 295 return; 296 297 if (!sec_key_ver) 298 return; 299 300 ieee80211_iter_keys_rcu(mvm->hw, vif, 301 iwl_mvm_sec_key_remove_ap_iter, 302 (void *)(uintptr_t)link_id); 303 } 304