wifi: iwlwifi: mld: set correct key mask for NAN

For NAN data, the supplicant may derive and install GTKs to
transmit with. As multicast data encryption is supported only
with firmware versions that support adding NAN multicast
data station, allow GTK installation only with such FW
versions. Otherwise, do not install the GTK to the device.

For NAN management, there are no GTKs, but there are IGTKs
and BIGTKs, which need to be installed for the NAN broadcast
and NAN management stations. This is supported only with
firmware versions that allow adding NAN broadcast station
and NAN management station.

Handle both of these cases by adjusting the station mask
appropriately, returning a zero station mask for the GTK
and allowing that to not be an error/warning message.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Co-developed-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Link: https://patch.msgid.link/20260513084215.7e18e0718d22.Icbf4204a9f1190eb4102016ad5f1c5bdab49635b@changeid
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
This commit is contained in:
Johannes Berg 2026-05-13 08:44:02 +03:00 committed by Miri Korenblit
parent b506efbde8
commit 927c7e8473
5 changed files with 59 additions and 5 deletions

View File

@ -66,6 +66,8 @@ void iwl_mld_cleanup_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
iwl_mld_free_internal_sta(mld, &mld_vif->nan.bcast_sta);
if (mld_vif->nan.mgmt_sta.sta_id != IWL_INVALID_STA)
iwl_mld_free_internal_sta(mld, &mld_vif->nan.mgmt_sta);
mld_vif->nan.tx_igtk = NULL;
}
if (vif->type == NL80211_IFTYPE_NAN_DATA &&

View File

@ -160,6 +160,8 @@ struct iwl_mld_emlsr {
* @nan.mgmt_sta: internal station used for NAN management frames, e.g., SDFs
* and NAFs.
* @nan.mcast_data_sta: internal station used for multicast NAN Data frames.
* @nan.tx_igtk: TX IGTK key for NAN, tracked separately since NAN does not
* use the vif links.
*/
struct iwl_mld_vif {
/* Add here fields that need clean up on restart */
@ -189,6 +191,7 @@ struct iwl_mld_vif {
struct iwl_mld_int_sta bcast_sta;
struct iwl_mld_int_sta mgmt_sta;
struct iwl_mld_int_sta mcast_data_sta;
struct ieee80211_key_conf *tx_igtk;
} nan;
struct iwl_mld_emlsr emlsr;

View File

@ -63,6 +63,40 @@ static u32 iwl_mld_get_key_sta_mask(struct iwl_mld *mld,
lockdep_assert_wiphy(mld->wiphy);
if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta) {
/* Older firmware versions do not support transmission of
* multicast data frames.
*/
if (!iwl_mld_nan_use_nan_stations(mld))
return 0;
if (WARN_ON(mld_vif->nan.mcast_data_sta.sta_id ==
IWL_INVALID_STA))
return 0;
return BIT(mld_vif->nan.mcast_data_sta.sta_id);
}
if (vif->type == NL80211_IFTYPE_NAN && !sta) {
/* Older firmware versions do not support installation of
* IGTK/BIGTK keys.
*/
if (!iwl_mld_nan_use_nan_stations(mld))
return 0;
if (WARN_ON(mld_vif->nan.bcast_sta.sta_id == IWL_INVALID_STA ||
mld_vif->nan.mgmt_sta.sta_id == IWL_INVALID_STA))
return 0;
if (key->keyidx >= 4 && key->keyidx <= 5)
return BIT(mld_vif->nan.mgmt_sta.sta_id);
if (key->keyidx >= 6 && key->keyidx <= 7)
return BIT(mld_vif->nan.bcast_sta.sta_id);
return 0;
}
/* AP group keys are per link and should be on the mcast/bcast STA */
if (vif->type == NL80211_IFTYPE_AP &&
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
@ -204,7 +238,7 @@ iwl_mld_get_igtk_ptr(struct ieee80211_vif *vif,
return &mld_sta->deflink.rx_igtk;
}
return &mld_vif->deflink.tx_igtk;
return &mld_vif->nan.tx_igtk;
case NL80211_IFTYPE_AP:
mld_link = iwl_mld_link_dereference_check(mld_vif, link_id);
if (WARN_ON(!mld_link))
@ -254,8 +288,16 @@ int iwl_mld_add_key(struct iwl_mld *mld,
lockdep_assert_wiphy(mld->wiphy);
if (!sta_mask)
if (!sta_mask) {
/* for NAN (GTK) indicate SW-only, it's not used at all */
if (vif->type == NL80211_IFTYPE_NAN_DATA && !sta &&
!iwl_mld_nan_use_nan_stations(mld))
return 1;
/* otherwise that's not valid */
IWL_WARN(mld, "empty STA mask for key %d\n", key->keyidx);
return -EINVAL;
}
igtk_ptr = iwl_mld_get_igtk_ptr(vif, sta, key);
if (igtk_ptr) {
@ -270,8 +312,10 @@ int iwl_mld_add_key(struct iwl_mld *mld,
}
ret = iwl_mld_add_key_to_fw(mld, sta_mask, key_flags, key);
if (ret)
if (ret) {
IWL_WARN(mld, "failed to add key to FW (%d)\n", ret);
return ret;
}
if (igtk_ptr) {
WARN_ON(*igtk_ptr);

View File

@ -2248,7 +2248,6 @@ static int iwl_mld_set_key_add(struct iwl_mld *mld,
ret = iwl_mld_add_key(mld, vif, sta, key);
if (ret) {
IWL_WARN(mld, "set key failed (%d)\n", ret);
if (ptk_pn) {
RCU_INIT_POINTER(mld_sta->ptk_pn[keyidx], NULL);
kfree(ptk_pn);

View File

@ -1089,8 +1089,14 @@ iwl_mld_set_internal_sta_to_fw(struct iwl_mld *mld,
* On the other hand, FW will never check this flag during RX since
* an AP/GO doesn't receive protected broadcast management frames.
* So, we can set it unconditionally.
*
* For NAN stations associated with a NAN Device, the MFP bit must be
* set to 1, as otherwise the FW will assert when a key associated with
* these stations would be added.
*/
if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT)
if (internal_sta->sta_type == STATION_TYPE_BCAST_MGMT ||
internal_sta->sta_type == STATION_TYPE_NAN_BCAST ||
internal_sta->sta_type == STATION_TYPE_NAN_MGMT)
cmd.mfp = cpu_to_le32(1);
if (addr) {