Commit 69fdb084 authored by Miri Korenblit's avatar Miri Korenblit Committed by Johannes Berg
Browse files

wifi: mac80211: don't require cipher and keylen in gtk rekey



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: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250721214922.3c5c023bfae9.Ie6594ae2b4b6d5b3d536e642b349046ebfce7a5d@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2ed9a9fc
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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;

+9 −2
Original line number Diff line number Diff line
@@ -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;
+5 −2
Original line number Diff line number Diff line
@@ -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)) {
+5 −2
Original line number Diff line number Diff line
@@ -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);

/**
+33 −3
Original line number Diff line number Diff line
@@ -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);