diff options
author | Chih-Kang Chang <gary.chang@realtek.com> | 2024-05-02 04:25:03 +0200 |
---|---|---|
committer | Ping-Ke Shih <pkshih@realtek.com> | 2024-05-04 02:05:15 +0200 |
commit | 940cd99625de8c75209b1169e6cd5698075c0a37 (patch) | |
tree | ef8cc2fd0254e307bec5e53ba6ea772e79d4fdc8 /drivers/net/wireless/realtek/rtw89/fw.c | |
parent | wifi: rtw89: wow: update latest PTK GTK info to mac80211 after resume (diff) | |
download | linux-940cd99625de8c75209b1169e6cd5698075c0a37.tar.xz linux-940cd99625de8c75209b1169e6cd5698075c0a37.zip |
wifi: rtw89: wow: support 802.11w PMF IGTK rekey
Once we connect to AP with 802.11w enabled, IGTK rekey happen during GTK
happen. We get IGTK IPN from mac80211 and set to firmware, and get latest
IGTK IPN from AOAC report then update to mac80211 after resume. When rekey
happen, also update new IGTK key info to mac80211. Furthermore, We
construct SA query reply packet to firmware. If firmware received SA query
request from AP can transmit reply back when suspend.
Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://msgid.link/20240502022505.28966-11-pkshih@realtek.com
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/fw.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/fw.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index 50df25e6484d..444badc3eede 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -20,6 +20,12 @@ struct rtw89_eapol_2_of_2 { u8 rsvd[92]; } __packed __aligned(2); +struct rtw89_sa_query { + struct ieee80211_hdr_3addr hdr; + u8 category; + u8 action; +} __packed __aligned(2); + static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; union rtw89_fw_element_arg { @@ -2192,6 +2198,31 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, return skb; } +static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; + struct rtw89_sa_query *sa_query; + struct sk_buff *skb; + + skb = dev_alloc_skb(sizeof(*sa_query)); + if (!skb) + return NULL; + + sa_query = skb_put_zero(skb, sizeof(*sa_query)); + sa_query->hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | + IEEE80211_STYPE_ACTION | + IEEE80211_FCTL_PROTECTED); + ether_addr_copy(sa_query->hdr.addr1, bss_conf->bssid); + ether_addr_copy(sa_query->hdr.addr2, vif->addr); + ether_addr_copy(sa_query->hdr.addr3, bss_conf->bssid); + sa_query->category = WLAN_CATEGORY_SA_QUERY; + sa_query->action = WLAN_ACTION_SA_QUERY_RESPONSE; + + return skb; +} + static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, enum rtw89_fw_pkt_ofld_type type, @@ -2222,6 +2253,9 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev, case RTW89_PKT_OFLD_TYPE_EAPOL_KEY: skb = rtw89_eapol_get(rtwdev, rtwvif); break; + case RTW89_PKT_OFLD_TYPE_SA_QUERY: + skb = rtw89_sa_query_get(rtwdev, rtwvif); + break; default: goto err; } @@ -6556,6 +6590,7 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, struct rtw89_h2c_wow_gtk_ofld *h2c; u8 macid = rtwvif->mac_id; u32 len = sizeof(*h2c); + u8 pkt_id_sa_query = 0; struct sk_buff *skb; u8 pkt_id_eapol = 0; int ret; @@ -6583,13 +6618,24 @@ int rtw89_fw_h2c_wow_gtk_ofld(struct rtw89_dev *rtwdev, if (ret) goto fail; - /* not support TKIP and IEEE80211W yet */ + if (gtk_info->igtk_keyid) { + ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif, + RTW89_PKT_OFLD_TYPE_SA_QUERY, + &pkt_id_sa_query); + if (ret) + goto fail; + } + + /* not support TKIP yet */ h2c->w0 = le32_encode_bits(enable, RTW89_H2C_WOW_GTK_OFLD_W0_EN) | le32_encode_bits(0, RTW89_H2C_WOW_GTK_OFLD_W0_TKIP_EN) | - le32_encode_bits(0, RTW89_H2C_WOW_GTK_OFLD_W0_IEEE80211W_EN) | + le32_encode_bits(gtk_info->igtk_keyid ? 1 : 0, + RTW89_H2C_WOW_GTK_OFLD_W0_IEEE80211W_EN) | le32_encode_bits(macid, RTW89_H2C_WOW_GTK_OFLD_W0_MAC_ID) | le32_encode_bits(pkt_id_eapol, RTW89_H2C_WOW_GTK_OFLD_W0_GTK_RSP_ID); - h2c->w1 = le32_encode_bits(rtw_wow->akm, RTW89_H2C_WOW_GTK_OFLD_W1_ALGO_AKM_SUIT); + h2c->w1 = le32_encode_bits(gtk_info->igtk_keyid ? pkt_id_sa_query : 0, + RTW89_H2C_WOW_GTK_OFLD_W1_PMF_SA_QUERY_ID) | + le32_encode_bits(rtw_wow->akm, RTW89_H2C_WOW_GTK_OFLD_W1_ALGO_AKM_SUIT); h2c->gtk_info = rtw_wow->gtk_info; hdr: |