if (keyconf->link_id >= 0) {
link_info = mvmvif->link[keyconf->link_id]; if (!link_info) return 0;
}
/* AP group keys are per link and should be on the mcast/bcast STA */ if (vif->type == NL80211_IFTYPE_AP &&
!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { /* IGTK/BIGTK to bcast STA */ if (keyconf->keyidx >= 4) return BIT(link_info->bcast_sta.sta_id); /* GTK for data to mcast STA */ return BIT(link_info->mcast_sta.sta_id);
}
/* for client mode use the AP STA also for group keys */ if (!sta && vif->type == NL80211_IFTYPE_STATION)
sta = mvmvif->ap_sta;
/* During remove the STA was removed and the group keys come later * (which sounds like a bad sequence, but remember that to mac80211 the * group keys have no sta pointer), so we don't have a STA now. * Since this happens for group keys only, just use the link_info as * the group keys are per link; make sure that is the case by checking * we do have a link_id or are not doing MLO. * Of course the same can be done during add as well, but we must do * it during remove, since we don't have the mvmvif->ap_sta pointer.
*/ if (!sta && (keyconf->link_id >= 0 || !ieee80211_vif_is_mld(vif))) return BIT(link_info->ap_sta_id);
/* STA should be non-NULL now, but iwl_mvm_sta_fw_id_mask() checks */
/* pass link_id to filter by it if not -1 (GTK on client) */ return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id);
}
if (!pairwise)
flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
switch (keyconf->cipher) { case WLAN_CIPHER_SUITE_WEP104:
flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
fallthrough; case WLAN_CIPHER_SUITE_WEP40:
flags |= IWL_SEC_KEY_FLAG_CIPHER_WEP; break; case WLAN_CIPHER_SUITE_TKIP:
flags |= IWL_SEC_KEY_FLAG_CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_AES_CMAC: case WLAN_CIPHER_SUITE_CCMP:
flags |= IWL_SEC_KEY_FLAG_CIPHER_CCMP; break; case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_BIP_GMAC_256:
flags |= IWL_SEC_KEY_FLAG_KEY_SIZE;
fallthrough; case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_BIP_GMAC_128:
flags |= IWL_SEC_KEY_FLAG_CIPHER_GCMP; break;
}
if (!sta && vif->type == NL80211_IFTYPE_STATION)
sta = mvmvif->ap_sta;
/* * If we are installing an iGTK (in AP or STA mode), we need to tell * the firmware this key will en/decrypt MGMT frames. * Same goes if we are installing a pairwise key for an MFP station. * In case we're installing a groupwise key (which is not an iGTK), * then, we will not use this key for MGMT frames.
*/ if ((!IS_ERR_OR_NULL(sta) && sta->mfp && pairwise) || igtk)
flags |= IWL_SEC_KEY_FLAG_MFP;
if (keyconf->flags & IEEE80211_KEY_FLAG_SPP_AMSDU)
flags |= IWL_SEC_KEY_FLAG_SPP_AMSDU;
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); if (ret) return ret;
/* * For WEP, the same key is used for multicast and unicast so need to * upload it again. If this fails, remove the original as well.
*/ if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
cmd.u.add.key_flags ^= cpu_to_le32(IWL_SEC_KEY_FLAG_MCAST_KEY);
ret = iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, sizeof(cmd), &cmd); if (ret)
__iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
keyconf->keyidx, 0);
}
/* set to -1 for non-MLO right now */ if (keyconf->link_id >= 0)
link_id = keyconf->link_id;
mvm_link = mvmvif->link[link_id]; if (WARN_ON(!mvm_link)) return -EINVAL;
if (mvm_link->igtk) {
IWL_DEBUG_MAC80211(mvm, "remove old IGTK %d\n",
mvm_link->igtk->keyidx);
ret = iwl_mvm_sec_key_del(mvm, vif, sta,
mvm_link->igtk); if (ret)
IWL_ERR(mvm, "failed to remove old IGTK (ret=%d)\n",
ret);
}
WARN_ON(mvm_link->igtk);
}
ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); if (ret) return ret;
if (mvm_link)
mvm_link->igtk = keyconf;
/* We don't really need this, but need it to be not invalid, * and if we switch links multiple times it might go to be * invalid when removed.
*/
keyconf->hw_key_idx = 0;
/* set to -1 for non-MLO right now */ if (keyconf->link_id >= 0)
link_id = keyconf->link_id;
mvm_link = mvmvif->link[link_id]; if (WARN_ON(!mvm_link)) return -EINVAL;
if (mvm_link->igtk == keyconf) { /* no longer in HW - mark for later */
mvm_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
mvm_link->igtk = NULL;
}
}
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags, keyconf->keyidx,
flags); if (ret) return ret;
/* For WEP, delete the key again as unicast */ if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
key_flags ^= IWL_SEC_KEY_FLAG_MCAST_KEY;
ret = __iwl_mvm_sec_key_del(mvm, sta_mask, key_flags,
keyconf->keyidx, flags);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.