]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: iwlwifi: mld: set correct key mask for NAN
authorJohannes Berg <johannes.berg@intel.com>
Wed, 13 May 2026 05:44:02 +0000 (08:44 +0300)
committerMiri Korenblit <miriam.rachel.korenblit@intel.com>
Tue, 26 May 2026 12:17:12 +0000 (15:17 +0300)
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>
drivers/net/wireless/intel/iwlwifi/mld/iface.c
drivers/net/wireless/intel/iwlwifi/mld/iface.h
drivers/net/wireless/intel/iwlwifi/mld/key.c
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
drivers/net/wireless/intel/iwlwifi/mld/sta.c

index 399efeb469f6e7f3e6dd0fc75b80fd87fdd911d6..2b837c6fa5fee88ae373c14128e00e7ba113c6c6 100644 (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 &&
index c6a7588df1fa57b109fbf2e0d1c7da9195e24d26..bc6f45ff76f888dd6c410528063653b613c45900 100644 (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;
index 151e35b851f7de8af8052e5fa9998be9ce5358a7..a6454d90d0e31f0a22ead4d3236b88d0a7fd2d87 100644 (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);
index b6df09812daefde5dc94632f78ea824c17a30cf8..9736b43155d681584eabdec2016fca8ce3067a04 100644 (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);
index cd13238ed613d7977aed7fd7398e389535e79bec..77eeeed66116be88fb8d9d289186e410fc08f0c7 100644 (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) {