diff --git a/mt7996/main.c b/mt7996/main.c index 6d922d7a3..2d4a40b30 100644 --- a/mt7996/main.c +++ b/mt7996/main.c @@ -258,7 +258,7 @@ mt7996_set_hw_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt76_wcid_key_setup(&dev->mt76, &msta_link->wcid, key); - err = mt7996_mcu_add_key(&dev->mt76, link, key, + err = mt7996_mcu_add_key(&dev->mt76, link, &msta_link->bip, key, MCU_WMWA_UNI_CMD(STA_REC_UPDATE), &msta_link->wcid, cmd); diff --git a/mt7996/mcu.c b/mt7996/mcu.c index 3dcbfed0b..7fb9f64f4 100644 --- a/mt7996/mcu.c +++ b/mt7996/mcu.c @@ -2862,6 +2862,7 @@ void mt7996_mcu_update_sta_rec_bw(void *data, struct ieee80211_sta *sta) static int mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid, struct sk_buff *skb, + struct mt76_connac_sta_key_conf *sta_key_conf, struct ieee80211_key_conf *key, enum set_key_cmd cmd) { @@ -2888,6 +2889,34 @@ mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid, if (cipher == MCU_CIPHER_NONE) return -EOPNOTSUPP; + if (cipher == MCU_CIPHER_BIP_CMAC_128) { + /* BIP batch mode: install CCMP + BIP as two keys, matching + * the approach used by mt76_connac_mcu_sta_key_tlv() for + * mt7915. This is required for FT-SAE (802.11r with WPA3) + * to work correctly, as the management frame protection + * keys must be installed alongside the pairwise key. + */ + sec_key->mgmt_prot = 0; + sec_key->cipher_id = MCU_CIPHER_AES_CCMP; + sec_key->cipher_len = sizeof(*sec_key); + sec_key->key_id = sta_key_conf->keyidx; + sec_key->key_len = 16; + sec_key->need_resp = 0; + memcpy(sec_key->key, sta_key_conf->key, 16); + + sec_key = &sec->key[1]; + sec_key->wlan_idx = cpu_to_le16(wcid->idx); + sec_key->mgmt_prot = 1; + sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128; + sec_key->cipher_len = sizeof(*sec_key); + sec_key->key_id = key->keyidx; + sec_key->key_len = 16; + sec_key->need_resp = 0; + memcpy(sec_key->key, key->key, 16); + sec->n_cipher = 2; + return 0; + } + sec_key->mgmt_prot = 0; sec_key->cipher_id = cipher; sec_key->cipher_len = sizeof(*sec_key); @@ -2902,6 +2931,12 @@ mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid, return 0; } + /* store key_conf for BIP batch update */ + if (cipher == MCU_CIPHER_AES_CCMP) { + memcpy(sta_key_conf->key, key->key, key->keylen); + sta_key_conf->keyidx = key->keyidx; + } + if (sec_key->key_id != 6 && sec_key->key_id != 7) return 0; @@ -2930,6 +2965,7 @@ mt7996_mcu_sta_key_tlv(struct mt76_dev *dev, struct mt76_wcid *wcid, } int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link, + struct mt76_connac_sta_key_conf *sta_key_conf, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd) { @@ -2941,7 +2977,7 @@ int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link, if (IS_ERR(skb)) return PTR_ERR(skb); - ret = mt7996_mcu_sta_key_tlv(dev, wcid, skb, key, cmd); + ret = mt7996_mcu_sta_key_tlv(dev, wcid, skb, sta_key_conf, key, cmd); if (ret) { dev_kfree_skb(skb); return ret; diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h index 0dc4198fc..4f73ddf5d 100644 --- a/mt7996/mt7996.h +++ b/mt7996/mt7996.h @@ -914,6 +914,7 @@ int mt7996_init_debugfs(struct mt7996_dev *dev); void mt7996_debugfs_rx_fw_monitor(struct mt7996_dev *dev, const void *data, int len); bool mt7996_debugfs_rx_log(struct mt7996_dev *dev, const void *data, int len); int mt7996_mcu_add_key(struct mt76_dev *dev, struct mt7996_vif_link *link, + struct mt76_connac_sta_key_conf *sta_key_conf, struct ieee80211_key_conf *key, int mcu_cmd, struct mt76_wcid *wcid, enum set_key_cmd cmd); int mt7996_mcu_bcn_prot_enable(struct mt7996_dev *dev,