| From: Felix Fietkau <nbd@nbd.name> |
| Date: Wed, 22 Mar 2023 10:17:49 +0100 |
| Subject: [PATCH] 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: Felix Fietkau <nbd@nbd.name> |
| --- |
| |
| --- a/mt7603/main.c |
| +++ b/mt7603/main.c |
| @@ -512,15 +512,15 @@ mt7603_set_key(struct ieee80211_hw *hw, |
| !(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); |
| --- a/mt7615/mac.c |
| +++ b/mt7615/mac.c |
| @@ -1193,8 +1193,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtsc |
| 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,27 +1202,18 @@ mt7615_mac_wtbl_update_key(struct mt7615 |
| 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); |
| - memcpy(data + 16, key->key + 24, 8); |
| - memcpy(data + 24, key->key + 16, 8); |
| - } else { |
| - if (cipher_mask == BIT(cipher)) |
| - memcpy(data, key->key, key->keylen); |
| - else if (cipher != MT_CIPHER_BIP_CMAC_128) |
| - memcpy(data, key->key, 16); |
| - if (cipher == MT_CIPHER_BIP_CMAC_128) |
| - memcpy(data + 16, key->key, 16); |
| - } |
| + if (cipher == MT_CIPHER_TKIP) { |
| + /* Rx/Tx MIC keys are swapped */ |
| + memcpy(data, key->key, 16); |
| + memcpy(data + 16, key->key + 24, 8); |
| + memcpy(data + 24, key->key + 16, 8); |
| } else { |
| + if (cipher_mask == BIT(cipher)) |
| + memcpy(data, key->key, key->keylen); |
| + else if (cipher != MT_CIPHER_BIP_CMAC_128) |
| + memcpy(data, key->key, 16); |
| 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)); |
| + memcpy(data + 16, key->key, 16); |
| } |
| |
| mt76_wr_copy(dev, addr, data, sizeof(data)); |
| @@ -1234,7 +1224,7 @@ mt7615_mac_wtbl_update_key(struct mt7615 |
| 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_ |
| 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_ |
| |
| 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 mt7 |
| |
| 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 mt7 |
| 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); |
| + cipher_mask |= BIT(cipher); |
| + 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 mt7 |
| |
| 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; |
| --- a/mt7615/main.c |
| +++ b/mt7615/main.c |
| @@ -391,18 +391,17 @@ static int mt7615_set_key(struct ieee802 |
| |
| if (cmd == SET_KEY) |
| *wcid_keyidx = idx; |
| - else if (idx == *wcid_keyidx) |
| - *wcid_keyidx = -1; |
| - else |
| + else { |
| + if (idx == *wcid_keyidx) |
| + *wcid_keyidx = -1; |
| 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); |
| --- a/mt7615/mt7615.h |
| +++ b/mt7615/mt7615.h |
| @@ -491,11 +491,9 @@ int mt7615_mac_write_txwi(struct mt7615_ |
| 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); |
| |
| --- a/mt76x02_util.c |
| +++ b/mt76x02_util.c |
| @@ -454,20 +454,20 @@ int mt76x02_set_key(struct ieee80211_hw |
| 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); |
| |
| --- a/mt7915/main.c |
| +++ b/mt7915/main.c |
| @@ -410,16 +410,15 @@ static int mt7915_set_key(struct ieee802 |
| mt7915_mcu_add_bss_info(phy, vif, true); |
| } |
| |
| - if (cmd == SET_KEY) |
| + if (cmd == SET_KEY) { |
| *wcid_keyidx = idx; |
| - else if (idx == *wcid_keyidx) |
| - *wcid_keyidx = -1; |
| - else |
| + } else { |
| + if (idx == *wcid_keyidx) |
| + *wcid_keyidx = -1; |
| goto out; |
| + } |
| |
| - mt76_wcid_key_setup(&dev->mt76, wcid, |
| - cmd == SET_KEY ? key : NULL); |
| - |
| + mt76_wcid_key_setup(&dev->mt76, wcid, key); |
| err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, |
| key, MCU_EXT_CMD(STA_REC_UPDATE), |
| &msta->wcid, cmd); |
| --- a/mt7921/main.c |
| +++ b/mt7921/main.c |
| @@ -569,16 +569,15 @@ static int mt7921_set_key(struct ieee802 |
| |
| mt7921_mutex_acquire(dev); |
| |
| - if (cmd == SET_KEY) |
| + if (cmd == SET_KEY) { |
| *wcid_keyidx = idx; |
| - else if (idx == *wcid_keyidx) |
| - *wcid_keyidx = -1; |
| - else |
| + } else { |
| + if (idx == *wcid_keyidx) |
| + *wcid_keyidx = -1; |
| goto out; |
| + } |
| |
| - mt76_wcid_key_setup(&dev->mt76, wcid, |
| - cmd == SET_KEY ? key : NULL); |
| - |
| + mt76_wcid_key_setup(&dev->mt76, wcid, key); |
| err = mt76_connac_mcu_add_key(&dev->mt76, vif, &msta->bip, |
| key, MCU_UNI_CMD(STA_REC_UPDATE), |
| &msta->wcid, cmd); |
| --- a/mt7996/main.c |
| +++ b/mt7996/main.c |
| @@ -351,16 +351,15 @@ static int mt7996_set_key(struct ieee802 |
| mt7996_mcu_add_bss_info(phy, vif, true); |
| } |
| |
| - if (cmd == SET_KEY) |
| + if (cmd == SET_KEY) { |
| *wcid_keyidx = idx; |
| - else if (idx == *wcid_keyidx) |
| - *wcid_keyidx = -1; |
| - else |
| + } else { |
| + if (idx == *wcid_keyidx) |
| + *wcid_keyidx = -1; |
| goto out; |
| + } |
| |
| - mt76_wcid_key_setup(&dev->mt76, wcid, |
| - cmd == SET_KEY ? key : NULL); |
| - |
| + mt76_wcid_key_setup(&dev->mt76, wcid, key); |
| err = mt7996_mcu_add_key(&dev->mt76, vif, &msta->bip, |
| key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), |
| &msta->wcid, cmd); |