]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: mac80211: don't require cipher and keylen in gtk rekey
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Mon, 21 Jul 2025 18:50:49 +0000 (21:50 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 22 Jul 2025 08:43:19 +0000 (10:43 +0200)
ieee80211_add_gtk_rekey receives a keyconf as an argument, and the
cipher and keylen are taken from there to the new allocated key.
But in rekey, both the cipher and the keylen should be the same as of
the old key, so let ieee80211_add_gtk_rekey find those, so drivers won't
have to fill it in.

Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250721214922.3c5c023bfae9.Ie6594ae2b4b6d5b3d536e642b349046ebfce7a5d@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mld/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/realtek/rtw89/wow.c
include/net/mac80211.h
net/mac80211/key.c

index 26255246a3208993932ccc3ad2bb1b047ef7815d..ed0a0f76f1c51b89c0ecd09b1c7c05455b9e4f9b 100644 (file)
@@ -762,6 +762,7 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif,
                .conf.keyidx = key_data->id,
        };
        int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+       u8 key[WOWLAN_KEY_MAX_SIZE];
 
        BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
        BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
@@ -803,7 +804,11 @@ iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif,
        }
 
        memcpy(conf.conf.key, key_data->key, conf.conf.keylen);
-       key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);
+
+       memcpy(key, key_data->key, sizeof(key_data->key));
+
+       key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key,
+                                            sizeof(key), link_id);
        if (IS_ERR(key_config))
                return;
 
index ef9bab0429026b98b3452833c90c40e3d5724a3b..997cdd76b13cff8041d375ecf87173dfe8809d6d 100644 (file)
@@ -1954,6 +1954,7 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
        DEFINE_RAW_FLEX(struct ieee80211_key_conf, conf, key,
                        WOWLAN_KEY_MAX_SIZE);
        int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+       u8 key_data[WOWLAN_KEY_MAX_SIZE];
 
        conf->cipher = gtk_cipher;
 
@@ -1988,8 +1989,10 @@ static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,
                                 conf->cipher, conf->keyidx);
                memcpy(conf->key, status->gtk[i].key,
                       sizeof(status->gtk[i].key));
+               memcpy(key_data, status->gtk[i].key, sizeof(status->gtk[i].key));
 
-               key = ieee80211_gtk_rekey_add(vif, conf, link_id);
+               key = ieee80211_gtk_rekey_add(vif, status->gtk[i].id, key_data,
+                                             sizeof(key_data), link_id);
                if (IS_ERR(key)) {
                        /* FW may send also the old keys */
                        if (PTR_ERR(key) == -EALREADY)
@@ -2021,6 +2024,7 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
        struct ieee80211_key_conf *key_config;
        struct ieee80211_key_seq seq;
        int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
+       u8 key[WOWLAN_KEY_MAX_SIZE];
        s8 keyidx = key_data->id;
 
        conf->cipher = cipher;
@@ -2050,7 +2054,10 @@ iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,
        BUILD_BUG_ON(WOWLAN_KEY_MAX_SIZE < sizeof(key_data->key));
        memcpy(conf->key, key_data->key, conf->keylen);
 
-       key_config = ieee80211_gtk_rekey_add(vif, conf, link_id);
+       memcpy(key, key_data->key, sizeof(key_data->key));
+
+       key_config = ieee80211_gtk_rekey_add(vif, keyidx, key, sizeof(key),
+                                            link_id);
        if (IS_ERR(key_config)) {
                /* FW may send also the old keys */
                return PTR_ERR(key_config) == -EALREADY;
index 071c7577df52b24354d86c1fbf78e1b5f2a29049..5bb7c1a42f1dec5a2b4a47f6388150aadf95c8cc 100644 (file)
@@ -619,9 +619,12 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
               flex_array_size(rekey_conf, key, cipher_info->len));
 
        if (ieee80211_vif_is_mld(wow_vif))
-               key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, rtwvif_link->link_id);
+               key = ieee80211_gtk_rekey_add(wow_vif, keyidx, gtk,
+                                             cipher_info->len,
+                                             rtwvif_link->link_id);
        else
-               key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1);
+               key = ieee80211_gtk_rekey_add(wow_vif, keyidx, gtk,
+                                             cipher_info->len, -1);
 
        kfree(rekey_conf);
        if (IS_ERR(key)) {
index a0cf976a91177992a33361ded01be84db1849aa0..a45e4bee65d4f651a1fbdf1cffc00ea27069298f 100644 (file)
@@ -6035,7 +6035,10 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
 /**
  * ieee80211_gtk_rekey_add - add a GTK key from rekeying during WoWLAN
  * @vif: the virtual interface to add the key on
- * @keyconf: new key data
+ * @idx: the keyidx of the key
+ * @key_data: the key data
+ * @key_len: the key data. Might be bigger than the actual key length,
+ *     but not smaller (for the driver convinence)
  * @link_id: the link id of the key or -1 for non-MLO
  *
  * When GTK rekeying was done while the system was suspended, (a) new
@@ -6062,7 +6065,7 @@ void ieee80211_set_key_rx_seq(struct ieee80211_key_conf *keyconf,
  */
 struct ieee80211_key_conf *
 ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
-                       struct ieee80211_key_conf *keyconf,
+                       u8 idx, u8 *key_data, u8 key_len,
                        int link_id);
 
 /**
index 9d65013ddac79c11170f55e28eaae9d98facd013..b14e9cd9713ff231774932079d6e48bb5e71baae 100644 (file)
@@ -1356,11 +1356,12 @@ EXPORT_SYMBOL_GPL(ieee80211_set_key_rx_seq);
 
 struct ieee80211_key_conf *
 ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
-                       struct ieee80211_key_conf *keyconf,
+                       u8 idx, u8 *key_data, u8 key_len,
                        int link_id)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_key *prev_key;
        struct ieee80211_key *key;
        int err;
        struct ieee80211_link_data *link_data =
@@ -1376,8 +1377,37 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
        if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
                return ERR_PTR(-EINVAL);
 
-       key = ieee80211_key_alloc(keyconf->cipher, keyconf->keyidx,
-                                 keyconf->keylen, keyconf->key,
+       if (WARN_ON(idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
+                   NUM_DEFAULT_BEACON_KEYS))
+               return ERR_PTR(-EINVAL);
+
+       prev_key = wiphy_dereference(local->hw.wiphy,
+                                    link_data->gtk[idx]);
+       if (!prev_key) {
+               if (idx < NUM_DEFAULT_KEYS) {
+                       for (int i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                               if (i == idx)
+                                       continue;
+                               prev_key = wiphy_dereference(local->hw.wiphy,
+                                                            link_data->gtk[i]);
+                               if (prev_key)
+                                       break;
+                       }
+               } else {
+                       /* For IGTK we have 4 and 5 and for BIGTK - 6 and 7 */
+                       prev_key = wiphy_dereference(local->hw.wiphy,
+                                                    link_data->gtk[idx ^ 1]);
+               }
+       }
+
+       if (WARN_ON(!prev_key))
+               return ERR_PTR(-EINVAL);
+
+       if (WARN_ON(key_len < prev_key->conf.keylen))
+               return ERR_PTR(-EINVAL);
+
+       key = ieee80211_key_alloc(prev_key->conf.cipher, idx,
+                                 prev_key->conf.keylen, key_data,
                                  0, NULL);
        if (IS_ERR(key))
                return ERR_CAST(key);