Commit 0065199f authored by Chih-Kang Chang's avatar Chih-Kang Chang Committed by Ping-Ke Shih

wifi: rtw89: wow: append security header offset for different cipher

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: default avatarChih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20240620055825.17592-2-pkshih@realtek.com
parent 6c3b5970
......@@ -13,22 +13,20 @@
#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);
......
......@@ -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)
{
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment