]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: wow: append security header offset for different cipher
authorChih-Kang Chang <gary.chang@realtek.com>
Thu, 20 Jun 2024 05:58:19 +0000 (13:58 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 27 Jun 2024 01:20:40 +0000 (09:20 +0800)
When creating EAPOL_KEY, SA_QUERY and ARP_RSP packet offload, we need
to append security header offset for different cipher as required by
the firmware. Only 8852A, 8852B, 8852BT and 8851B need it.

Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240620055825.17592-2-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/wow.c
drivers/net/wireless/realtek/rtw89/wow.h

index 23204b2706c93f2a21d181094f7a5f546a2b9d4b..3c666fd0f8eda16000f999b41ab3325325aaa034 100644 (file)
 #include "ps.h"
 #include "reg.h"
 #include "util.h"
+#include "wow.h"
 
 struct rtw89_eapol_2_of_2 {
-       struct ieee80211_hdr_3addr hdr;
        u8 gtkbody[14];
        u8 key_des_ver;
        u8 rsvd[92];
-} __packed __aligned(2);
+} __packed;
 
 struct rtw89_sa_query {
-       struct ieee80211_hdr_3addr hdr;
        u8 category;
        u8 action;
-} __packed __aligned(2);
+} __packed;
 
 struct rtw89_arp_rsp {
-       struct ieee80211_hdr_3addr addr;
        u8 llc_hdr[sizeof(rfc1042_header)];
        __be16 llc_type;
        struct arphdr arp_hdr;
@@ -36,7 +34,7 @@ struct rtw89_arp_rsp {
        __be32 sender_ip;
        u8 target_hw[ETH_ALEN];
        __be32 target_ip;
-} __packed __aligned(2);
+} __packed;
 
 static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
 
@@ -2197,8 +2195,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
                                     0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03};
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
        struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
        struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
        struct rtw89_eapol_2_of_2 *eapol_pkt;
+       struct ieee80211_hdr_3addr *hdr;
        struct sk_buff *skb;
        u8 key_des_ver;
 
@@ -2211,17 +2211,21 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
        else
                key_des_ver = 0;
 
-       skb = dev_alloc_skb(sizeof(*eapol_pkt));
+       skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*eapol_pkt));
        if (!skb)
                return NULL;
 
+       hdr = skb_put_zero(skb, sizeof(*hdr));
+       hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+                                        IEEE80211_FCTL_TODS |
+                                        IEEE80211_FCTL_PROTECTED);
+       ether_addr_copy(hdr->addr1, bss_conf->bssid);
+       ether_addr_copy(hdr->addr2, vif->addr);
+       ether_addr_copy(hdr->addr3, bss_conf->bssid);
+
+       skb_put_zero(skb, sec_hdr_len);
+
        eapol_pkt = skb_put_zero(skb, sizeof(*eapol_pkt));
-       eapol_pkt->hdr.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
-                                                  IEEE80211_FCTL_TODS |
-                                                  IEEE80211_FCTL_PROTECTED);
-       ether_addr_copy(eapol_pkt->hdr.addr1, bss_conf->bssid);
-       ether_addr_copy(eapol_pkt->hdr.addr2, vif->addr);
-       ether_addr_copy(eapol_pkt->hdr.addr3, bss_conf->bssid);
        memcpy(eapol_pkt->gtkbody, gtkbody, sizeof(gtkbody));
        eapol_pkt->key_des_ver = key_des_ver;
 
@@ -2233,20 +2237,26 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
 {
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
        struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+       u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
+       struct ieee80211_hdr_3addr *hdr;
        struct rtw89_sa_query *sa_query;
        struct sk_buff *skb;
 
-       skb = dev_alloc_skb(sizeof(*sa_query));
+       skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*sa_query));
        if (!skb)
                return NULL;
 
+       hdr = skb_put_zero(skb, sizeof(*hdr));
+       hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                        IEEE80211_STYPE_ACTION |
+                                        IEEE80211_FCTL_PROTECTED);
+       ether_addr_copy(hdr->addr1, bss_conf->bssid);
+       ether_addr_copy(hdr->addr2, vif->addr);
+       ether_addr_copy(hdr->addr3, bss_conf->bssid);
+
+       skb_put_zero(skb, sec_hdr_len);
+
        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;
 
@@ -2256,17 +2266,19 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev,
 static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
                                              struct rtw89_vif *rtwvif)
 {
+       u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
        struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
+       struct ieee80211_hdr_3addr *hdr;
        struct rtw89_arp_rsp *arp_skb;
        struct arphdr *arp_hdr;
        struct sk_buff *skb;
        __le16 fc;
 
-       skb = dev_alloc_skb(sizeof(struct rtw89_arp_rsp));
+       skb = dev_alloc_skb(sizeof(*hdr) + sec_hdr_len + sizeof(*arp_skb));
        if (!skb)
                return NULL;
 
-       arp_skb = skb_put_zero(skb, sizeof(*arp_skb));
+       hdr = skb_put_zero(skb, sizeof(*hdr));
 
        if (rtw_wow->ptk_alg)
                fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS |
@@ -2274,11 +2286,14 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
        else
                fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS);
 
-       arp_skb->addr.frame_control = fc;
-       ether_addr_copy(arp_skb->addr.addr1, rtwvif->bssid);
-       ether_addr_copy(arp_skb->addr.addr2, rtwvif->mac_addr);
-       ether_addr_copy(arp_skb->addr.addr3, rtwvif->bssid);
+       hdr->frame_control = fc;
+       ether_addr_copy(hdr->addr1, rtwvif->bssid);
+       ether_addr_copy(hdr->addr2, rtwvif->mac_addr);
+       ether_addr_copy(hdr->addr3, rtwvif->bssid);
+
+       skb_put_zero(skb, sec_hdr_len);
 
+       arp_skb = skb_put_zero(skb, sizeof(*arp_skb));
        memcpy(arp_skb->llc_hdr, rfc1042_header, sizeof(rfc1042_header));
        arp_skb->llc_type = htons(ETH_P_ARP);
 
index fa61484c38395f3a6b42bd50a6d09c947dc14e4d..df22a53b8f41219d76e95a424b409c3f8f246bd6 100644 (file)
@@ -27,17 +27,23 @@ void rtw89_wow_parse_akm(struct rtw89_dev *rtwdev, struct sk_buff *skb)
        rtw_wow->akm = rsn_ie->akm_cipher_suite.type;
 }
 
+#define RTW89_CIPHER_INFO_DEF(cipher) \
+       {WLAN_CIPHER_SUITE_ ## cipher, .fw_alg = RTW89_WOW_FW_ALG_ ## cipher, \
+        .len = WLAN_KEY_LEN_ ## cipher}
+
 static const struct rtw89_cipher_info rtw89_cipher_info_defs[] = {
-       {WLAN_CIPHER_SUITE_WEP40,       .fw_alg = 1,    .len = WLAN_KEY_LEN_WEP40,},
-       {WLAN_CIPHER_SUITE_WEP104,      .fw_alg = 2,    .len = WLAN_KEY_LEN_WEP104,},
-       {WLAN_CIPHER_SUITE_TKIP,        .fw_alg = 3,    .len = WLAN_KEY_LEN_TKIP,},
-       {WLAN_CIPHER_SUITE_CCMP,        .fw_alg = 6,    .len = WLAN_KEY_LEN_CCMP,},
-       {WLAN_CIPHER_SUITE_GCMP,        .fw_alg = 8,    .len = WLAN_KEY_LEN_GCMP,},
-       {WLAN_CIPHER_SUITE_CCMP_256,    .fw_alg = 7,    .len = WLAN_KEY_LEN_CCMP_256,},
-       {WLAN_CIPHER_SUITE_GCMP_256,    .fw_alg = 23,   .len = WLAN_KEY_LEN_GCMP_256,},
-       {WLAN_CIPHER_SUITE_AES_CMAC,    .fw_alg = 32,   .len = WLAN_KEY_LEN_AES_CMAC,},
+       RTW89_CIPHER_INFO_DEF(WEP40),
+       RTW89_CIPHER_INFO_DEF(WEP104),
+       RTW89_CIPHER_INFO_DEF(TKIP),
+       RTW89_CIPHER_INFO_DEF(CCMP),
+       RTW89_CIPHER_INFO_DEF(GCMP),
+       RTW89_CIPHER_INFO_DEF(CCMP_256),
+       RTW89_CIPHER_INFO_DEF(GCMP_256),
+       RTW89_CIPHER_INFO_DEF(AES_CMAC),
 };
 
+#undef RTW89_CIPHER_INFO_DEF
+
 static const
 struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher)
 {
index e595aee0196d7b63abffdcfb49cb45bca5e22fc7..0d90add0e88d998a3d7209f32d05c60c1f23740d 100644 (file)
@@ -35,6 +35,17 @@ enum rtw89_wake_reason {
        RTW89_WOW_RSN_RX_NLO = 0x55,
 };
 
+enum rtw89_fw_alg {
+       RTW89_WOW_FW_ALG_WEP40 = 0x1,
+       RTW89_WOW_FW_ALG_WEP104 = 0x2,
+       RTW89_WOW_FW_ALG_TKIP = 0x3,
+       RTW89_WOW_FW_ALG_CCMP = 0x6,
+       RTW89_WOW_FW_ALG_CCMP_256 = 0x7,
+       RTW89_WOW_FW_ALG_GCMP = 0x8,
+       RTW89_WOW_FW_ALG_GCMP_256 = 0x9,
+       RTW89_WOW_FW_ALG_AES_CMAC = 0xa,
+};
+
 struct rtw89_cipher_suite {
        u8 oui[3];
        u8 type;
@@ -64,6 +75,25 @@ struct rtw89_set_key_info_iter_data {
        bool error;
 };
 
+static inline int rtw89_wow_get_sec_hdr_len(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
+
+       if (!(rtwdev->chip->chip_id == RTL8852A || rtw89_is_rtl885xb(rtwdev)))
+               return 0;
+
+       switch (rtw_wow->ptk_alg) {
+       case RTW89_WOW_FW_ALG_WEP40:
+               return 4;
+       case RTW89_WOW_FW_ALG_TKIP:
+       case RTW89_WOW_FW_ALG_CCMP:
+       case RTW89_WOW_FW_ALG_GCMP_256:
+               return 8;
+       default:
+               return 0;
+       }
+}
+
 #ifdef CONFIG_PM
 int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan);
 int rtw89_wow_resume(struct rtw89_dev *rtwdev);