mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
wifi: mt76: mt7996: fix setting beacon protection keys
Include beacon key information in the STA_REC_UPDATE call. Remove mt7996_mcu_get_pn - when installing a new key, we should not reuse any existing PN value. Signed-off-by: Allen Ye <allen.ye@mediatek.com> Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com> Link: https://patch.msgid.link/20250915075910.47558-4-nbd@nbd.name Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
@@ -262,13 +262,6 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key);
|
||||
|
||||
if (key->keyidx == 6 || key->keyidx == 7) {
|
||||
err = mt7996_mcu_bcn_prot_enable(dev, link,
|
||||
msta_link, key);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mt7996_mcu_add_key(&dev->mt76, vif, key,
|
||||
MCU_WMWA_UNI_CMD(STA_REC_UPDATE),
|
||||
&msta_link->wcid, cmd);
|
||||
|
||||
@@ -2545,41 +2545,58 @@ mt7996_mcu_sta_key_tlv(struct mt76_wcid *wcid,
|
||||
enum set_key_cmd cmd)
|
||||
{
|
||||
struct sta_rec_sec_uni *sec;
|
||||
struct sec_key_uni *sec_key;
|
||||
struct tlv *tlv;
|
||||
u8 cipher;
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
|
||||
sec = (struct sta_rec_sec_uni *)tlv;
|
||||
sec->add = cmd;
|
||||
sec->add = 0;
|
||||
sec->n_cipher = 1;
|
||||
sec_key = &sec->key[0];
|
||||
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
|
||||
sec_key->key_id = key->keyidx;
|
||||
|
||||
if (cmd == SET_KEY) {
|
||||
struct sec_key_uni *sec_key;
|
||||
u8 cipher;
|
||||
if (cmd != SET_KEY)
|
||||
return 0;
|
||||
|
||||
cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
if (cipher == MCU_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
cipher = mt76_connac_mcu_get_cipher(key->cipher);
|
||||
if (cipher == MCU_CIPHER_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
sec_key = &sec->key[0];
|
||||
sec_key->wlan_idx = cpu_to_le16(wcid->idx);
|
||||
sec_key->mgmt_prot = 0;
|
||||
sec_key->cipher_id = cipher;
|
||||
sec_key->cipher_len = sizeof(*sec_key);
|
||||
sec_key->key_id = key->keyidx;
|
||||
sec_key->key_len = key->keylen;
|
||||
sec_key->need_resp = 0;
|
||||
memcpy(sec_key->key, key->key, key->keylen);
|
||||
sec_key->mgmt_prot = 0;
|
||||
sec_key->cipher_id = cipher;
|
||||
sec_key->cipher_len = sizeof(*sec_key);
|
||||
sec_key->key_len = key->keylen;
|
||||
sec_key->need_resp = 0;
|
||||
memcpy(sec_key->key, key->key, key->keylen);
|
||||
|
||||
if (cipher == MCU_CIPHER_TKIP) {
|
||||
/* Rx/Tx MIC keys are swapped */
|
||||
memcpy(sec_key->key + 16, key->key + 24, 8);
|
||||
memcpy(sec_key->key + 24, key->key + 16, 8);
|
||||
}
|
||||
|
||||
sec->n_cipher = 1;
|
||||
} else {
|
||||
sec->n_cipher = 0;
|
||||
if (cipher == MCU_CIPHER_TKIP) {
|
||||
/* Rx/Tx MIC keys are swapped */
|
||||
memcpy(sec_key->key + 16, key->key + 24, 8);
|
||||
memcpy(sec_key->key + 24, key->key + 16, 8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sec_key->key_id != 6 && sec_key->key_id != 7)
|
||||
return 0;
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
sec_key->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
sec_key->bcn_mode = BP_SW_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2603,95 +2620,6 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,
|
||||
return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);
|
||||
}
|
||||
|
||||
static int mt7996_mcu_get_pn(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link, u8 *pn)
|
||||
{
|
||||
#define TSC_TYPE_BIGTK_PN 2
|
||||
struct sta_rec_pn_info *pn_info;
|
||||
struct sk_buff *skb, *rskb;
|
||||
struct tlv *tlv;
|
||||
int ret;
|
||||
|
||||
skb = mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
|
||||
&msta_link->wcid);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PN_INFO, sizeof(*pn_info));
|
||||
pn_info = (struct sta_rec_pn_info *)tlv;
|
||||
|
||||
pn_info->tsc_type = TSC_TYPE_BIGTK_PN;
|
||||
ret = mt76_mcu_skb_send_and_get_msg(&dev->mt76, skb,
|
||||
MCU_WM_UNI_CMD_QUERY(STA_REC_UPDATE),
|
||||
true, &rskb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
skb_pull(rskb, 4);
|
||||
|
||||
pn_info = (struct sta_rec_pn_info *)rskb->data;
|
||||
if (le16_to_cpu(pn_info->tag) == STA_REC_PN_INFO)
|
||||
memcpy(pn, pn_info->pn, 6);
|
||||
|
||||
dev_kfree_skb(rskb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,
|
||||
struct mt7996_vif_link *link,
|
||||
struct mt7996_sta_link *msta_link,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct mt7996_mcu_bcn_prot_tlv *bcn_prot;
|
||||
struct sk_buff *skb;
|
||||
struct tlv *tlv;
|
||||
u8 pn[6] = {};
|
||||
int len = sizeof(struct bss_req_hdr) +
|
||||
sizeof(struct mt7996_mcu_bcn_prot_tlv);
|
||||
int ret;
|
||||
|
||||
skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &link->mt76, len);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BCN_PROT, sizeof(*bcn_prot));
|
||||
|
||||
bcn_prot = (struct mt7996_mcu_bcn_prot_tlv *)tlv;
|
||||
|
||||
ret = mt7996_mcu_get_pn(dev, link, msta_link, pn);
|
||||
if (ret) {
|
||||
dev_kfree_skb(skb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (key->cipher) {
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_CMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_128:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_128;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
|
||||
bcn_prot->cipher_id = MCU_CIPHER_BCN_PROT_GMAC_256;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Not supported Bigtk Cipher\n");
|
||||
dev_kfree_skb(skb);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
pn[0]++;
|
||||
memcpy(bcn_prot->pn, pn, 6);
|
||||
bcn_prot->enable = BP_SW_MODE;
|
||||
memcpy(bcn_prot->key, key->key, WLAN_MAX_KEY_LEN);
|
||||
bcn_prot->key_id = key->keyidx;
|
||||
|
||||
return mt76_mcu_skb_send_msg(&dev->mt76, skb,
|
||||
MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
|
||||
}
|
||||
|
||||
int mt7996_mcu_add_dev_info(struct mt7996_phy *phy, struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *link_conf,
|
||||
struct mt76_vif_link *mlink, bool enable)
|
||||
|
||||
@@ -351,17 +351,6 @@ enum {
|
||||
BP_HW_MODE,
|
||||
};
|
||||
|
||||
struct mt7996_mcu_bcn_prot_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
u8 pn[6];
|
||||
u8 enable;
|
||||
u8 cipher_id;
|
||||
u8 key[WLAN_MAX_KEY_LEN];
|
||||
u8 key_id;
|
||||
u8 __rsv[3];
|
||||
} __packed;
|
||||
|
||||
struct bss_ra_tlv {
|
||||
__le16 tag;
|
||||
__le16 len;
|
||||
@@ -531,6 +520,9 @@ struct sec_key_uni {
|
||||
u8 key_len;
|
||||
u8 need_resp;
|
||||
u8 key[32];
|
||||
u8 pn[6];
|
||||
u8 bcn_mode;
|
||||
u8 _rsv;
|
||||
} __packed;
|
||||
|
||||
struct sta_rec_sec_uni {
|
||||
|
||||
Reference in New Issue
Block a user