Commit e6db67fa authored by Felix Fietkau's avatar Felix Fietkau Committed by Kalle Valo
Browse files

wifi: mt76: ignore key disable commands



This helps avoid cleartext leakage of already queued or powersave buffered
packets, when a reassoc triggers the key deletion.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230330091259.61378-1-nbd@nbd.name
parent cf5fa3ca
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
		return -EOPNOTSUPP;

	if (cmd == SET_KEY) {
		key->hw_key_idx = wcid->idx;
		wcid->hw_key_idx = idx;
	} else {
	if (cmd != SET_KEY) {
		if (idx == wcid->hw_key_idx)
			wcid->hw_key_idx = -1;

		key = NULL;
		return 0;
	}

	key->hw_key_idx = wcid->idx;
	wcid->hw_key_idx = idx;
	mt76_wcid_key_setup(&dev->mt76, wcid, key);

	return mt7603_wtbl_set_key(dev, wcid->idx, key);
+21 −49
Original line number Diff line number Diff line
@@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);
static int
mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			   struct ieee80211_key_conf *key,
			   enum mt76_cipher_type cipher, u16 cipher_mask,
			   enum set_key_cmd cmd)
			   enum mt76_cipher_type cipher, u16 cipher_mask)
{
	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;
	u8 data[32] = {};
@@ -1203,7 +1202,6 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
		return -EINVAL;

	mt76_rr_copy(dev, addr, data, sizeof(data));
	if (cmd == SET_KEY) {
	if (cipher == MT_CIPHER_TKIP) {
		/* Rx/Tx MIC keys are swapped */
		memcpy(data, key->key, 16);
@@ -1217,14 +1215,6 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
		if (cipher == MT_CIPHER_BIP_CMAC_128)
			memcpy(data + 16, key->key, 16);
	}
	} else {
		if (cipher == MT_CIPHER_BIP_CMAC_128)
			memset(data + 16, 0, 16);
		else if (cipher_mask)
			memset(data, 0, 16);
		if (!cipher_mask)
			memset(data, 0, sizeof(data));
	}

	mt76_wr_copy(dev, addr, data, sizeof(data));

@@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
static int
mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			  enum mt76_cipher_type cipher, u16 cipher_mask,
			  int keyidx, enum set_key_cmd cmd)
			  int keyidx)
{
	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;

@@ -1253,9 +1243,7 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,
	else
		w0 &= ~MT_WTBL_W0_RX_IK_VALID;

	if (cmd == SET_KEY &&
	    (cipher != MT_CIPHER_BIP_CMAC_128 ||
	     cipher_mask == BIT(cipher))) {
	if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {
		w0 &= ~MT_WTBL_W0_KEY_IDX;
		w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);
	}
@@ -1272,19 +1260,10 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,

static void
mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			      enum mt76_cipher_type cipher, u16 cipher_mask,
			      enum set_key_cmd cmd)
			      enum mt76_cipher_type cipher, u16 cipher_mask)
{
	u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);

	if (!cipher_mask) {
		mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE);
		return;
	}

	if (cmd != SET_KEY)
		return;

	if (cipher == MT_CIPHER_BIP_CMAC_128 &&
	    cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))
		return;
@@ -1295,8 +1274,7 @@ mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,

int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			      struct mt76_wcid *wcid,
			      struct ieee80211_key_conf *key,
			      enum set_key_cmd cmd)
			      struct ieee80211_key_conf *key)
{
	enum mt76_cipher_type cipher;
	u16 cipher_mask = wcid->cipher;
@@ -1306,19 +1284,14 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
	if (cipher == MT_CIPHER_NONE)
		return -EOPNOTSUPP;

	if (cmd == SET_KEY)
	cipher_mask |= BIT(cipher);
	else
		cipher_mask &= ~BIT(cipher);

	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd);
	err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask,
					 cmd);
	mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);
	err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);
	if (err < 0)
		return err;

	err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,
					key->keyidx, cmd);
					key->keyidx);
	if (err < 0)
		return err;

@@ -1329,13 +1302,12 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,

int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			    struct mt76_wcid *wcid,
			    struct ieee80211_key_conf *key,
			    enum set_key_cmd cmd)
			    struct ieee80211_key_conf *key)
{
	int err;

	spin_lock_bh(&dev->mt76.lock);
	err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
	err = __mt7615_mac_wtbl_set_key(dev, wcid, key);
	spin_unlock_bh(&dev->mt76.lock);

	return err;
+7 −8
Original line number Diff line number Diff line
@@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,

	if (cmd == SET_KEY)
		*wcid_keyidx = idx;
	else if (idx == *wcid_keyidx)
	else {
		if (idx == *wcid_keyidx)
			*wcid_keyidx = -1;
	else
		goto out;
	}

	mt76_wcid_key_setup(&dev->mt76, wcid,
			    cmd == SET_KEY ? key : NULL);

	mt76_wcid_key_setup(&dev->mt76, wcid, key);
	if (mt76_is_mmio(&dev->mt76))
		err = mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
		err = mt7615_mac_wtbl_set_key(dev, wcid, key);
	else
		err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd);
		err = __mt7615_mac_wtbl_set_key(dev, wcid, key);

out:
	mt7615_mutex_release(dev);
+2 −4
Original line number Diff line number Diff line
@@ -490,11 +490,9 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,
void mt7615_mac_set_timing(struct mt7615_phy *phy);
int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,
			      struct mt76_wcid *wcid,
			      struct ieee80211_key_conf *key,
			      enum set_key_cmd cmd);
			      struct ieee80211_key_conf *key);
int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,
			    struct ieee80211_key_conf *key,
			    enum set_key_cmd cmd);
			    struct ieee80211_key_conf *key);
void mt7615_mac_reset_work(struct work_struct *work);
u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid);

+9 −9
Original line number Diff line number Diff line
@@ -454,20 +454,20 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
	msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
	wcid = msta ? &msta->wcid : &mvif->group_wcid;

	if (cmd == SET_KEY) {
		key->hw_key_idx = wcid->idx;
		wcid->hw_key_idx = idx;
		if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
			key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
			wcid->sw_iv = true;
		}
	} else {
	if (cmd != SET_KEY) {
		if (idx == wcid->hw_key_idx) {
			wcid->hw_key_idx = -1;
			wcid->sw_iv = false;
		}

		key = NULL;
		return 0;
	}

	key->hw_key_idx = wcid->idx;
	wcid->hw_key_idx = idx;
	if (key->flags & IEEE80211_KEY_FLAG_RX_MGMT) {
		key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
		wcid->sw_iv = true;
	}
	mt76_wcid_key_setup(&dev->mt76, wcid, key);

Loading