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 @@ ...@@ -13,22 +13,20 @@
#include "ps.h" #include "ps.h"
#include "reg.h" #include "reg.h"
#include "util.h" #include "util.h"
#include "wow.h"
struct rtw89_eapol_2_of_2 { struct rtw89_eapol_2_of_2 {
struct ieee80211_hdr_3addr hdr;
u8 gtkbody[14]; u8 gtkbody[14];
u8 key_des_ver; u8 key_des_ver;
u8 rsvd[92]; u8 rsvd[92];
} __packed __aligned(2); } __packed;
struct rtw89_sa_query { struct rtw89_sa_query {
struct ieee80211_hdr_3addr hdr;
u8 category; u8 category;
u8 action; u8 action;
} __packed __aligned(2); } __packed;
struct rtw89_arp_rsp { struct rtw89_arp_rsp {
struct ieee80211_hdr_3addr addr;
u8 llc_hdr[sizeof(rfc1042_header)]; u8 llc_hdr[sizeof(rfc1042_header)];
__be16 llc_type; __be16 llc_type;
struct arphdr arp_hdr; struct arphdr arp_hdr;
...@@ -36,7 +34,7 @@ struct rtw89_arp_rsp { ...@@ -36,7 +34,7 @@ struct rtw89_arp_rsp {
__be32 sender_ip; __be32 sender_ip;
u8 target_hw[ETH_ALEN]; u8 target_hw[ETH_ALEN];
__be32 target_ip; __be32 target_ip;
} __packed __aligned(2); } __packed;
static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; 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, ...@@ -2197,8 +2195,10 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03}; 0x8E, 0x01, 0x03, 0x00, 0x5F, 0x02, 0x03};
struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 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_wow_param *rtw_wow = &rtwdev->wow;
struct rtw89_eapol_2_of_2 *eapol_pkt; struct rtw89_eapol_2_of_2 *eapol_pkt;
struct ieee80211_hdr_3addr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
u8 key_des_ver; u8 key_des_ver;
...@@ -2211,17 +2211,21 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev, ...@@ -2211,17 +2211,21 @@ static struct sk_buff *rtw89_eapol_get(struct rtw89_dev *rtwdev,
else else
key_des_ver = 0; 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) if (!skb)
return NULL; 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 = 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)); memcpy(eapol_pkt->gtkbody, gtkbody, sizeof(gtkbody));
eapol_pkt->key_des_ver = key_des_ver; eapol_pkt->key_des_ver = key_des_ver;
...@@ -2233,20 +2237,26 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, ...@@ -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_vif *vif = rtwvif_to_vif(rtwvif);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 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 rtw89_sa_query *sa_query;
struct sk_buff *skb; 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) if (!skb)
return NULL; 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 = 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->category = WLAN_CATEGORY_SA_QUERY;
sa_query->action = WLAN_ACTION_SA_QUERY_RESPONSE; sa_query->action = WLAN_ACTION_SA_QUERY_RESPONSE;
...@@ -2256,17 +2266,19 @@ static struct sk_buff *rtw89_sa_query_get(struct rtw89_dev *rtwdev, ...@@ -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, static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
struct rtw89_vif *rtwvif) struct rtw89_vif *rtwvif)
{ {
u8 sec_hdr_len = rtw89_wow_get_sec_hdr_len(rtwdev);
struct rtw89_wow_param *rtw_wow = &rtwdev->wow; struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
struct ieee80211_hdr_3addr *hdr;
struct rtw89_arp_rsp *arp_skb; struct rtw89_arp_rsp *arp_skb;
struct arphdr *arp_hdr; struct arphdr *arp_hdr;
struct sk_buff *skb; struct sk_buff *skb;
__le16 fc; __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) if (!skb)
return NULL; return NULL;
arp_skb = skb_put_zero(skb, sizeof(*arp_skb)); hdr = skb_put_zero(skb, sizeof(*hdr));
if (rtw_wow->ptk_alg) if (rtw_wow->ptk_alg)
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS | 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, ...@@ -2274,11 +2286,14 @@ static struct sk_buff *rtw89_arp_response_get(struct rtw89_dev *rtwdev,
else else
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS); fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS);
arp_skb->addr.frame_control = fc; hdr->frame_control = fc;
ether_addr_copy(arp_skb->addr.addr1, rtwvif->bssid); ether_addr_copy(hdr->addr1, rtwvif->bssid);
ether_addr_copy(arp_skb->addr.addr2, rtwvif->mac_addr); ether_addr_copy(hdr->addr2, rtwvif->mac_addr);
ether_addr_copy(arp_skb->addr.addr3, rtwvif->bssid); 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)); memcpy(arp_skb->llc_hdr, rfc1042_header, sizeof(rfc1042_header));
arp_skb->llc_type = htons(ETH_P_ARP); 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) ...@@ -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; 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[] = { static const struct rtw89_cipher_info rtw89_cipher_info_defs[] = {
{WLAN_CIPHER_SUITE_WEP40, .fw_alg = 1, .len = WLAN_KEY_LEN_WEP40,}, RTW89_CIPHER_INFO_DEF(WEP40),
{WLAN_CIPHER_SUITE_WEP104, .fw_alg = 2, .len = WLAN_KEY_LEN_WEP104,}, RTW89_CIPHER_INFO_DEF(WEP104),
{WLAN_CIPHER_SUITE_TKIP, .fw_alg = 3, .len = WLAN_KEY_LEN_TKIP,}, RTW89_CIPHER_INFO_DEF(TKIP),
{WLAN_CIPHER_SUITE_CCMP, .fw_alg = 6, .len = WLAN_KEY_LEN_CCMP,}, RTW89_CIPHER_INFO_DEF(CCMP),
{WLAN_CIPHER_SUITE_GCMP, .fw_alg = 8, .len = WLAN_KEY_LEN_GCMP,}, RTW89_CIPHER_INFO_DEF(GCMP),
{WLAN_CIPHER_SUITE_CCMP_256, .fw_alg = 7, .len = WLAN_KEY_LEN_CCMP_256,}, RTW89_CIPHER_INFO_DEF(CCMP_256),
{WLAN_CIPHER_SUITE_GCMP_256, .fw_alg = 23, .len = WLAN_KEY_LEN_GCMP_256,}, RTW89_CIPHER_INFO_DEF(GCMP_256),
{WLAN_CIPHER_SUITE_AES_CMAC, .fw_alg = 32, .len = WLAN_KEY_LEN_AES_CMAC,}, RTW89_CIPHER_INFO_DEF(AES_CMAC),
}; };
#undef RTW89_CIPHER_INFO_DEF
static const static const
struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher) struct rtw89_cipher_info *rtw89_cipher_alg_recognize(u32 cipher)
{ {
......
...@@ -35,6 +35,17 @@ enum rtw89_wake_reason { ...@@ -35,6 +35,17 @@ enum rtw89_wake_reason {
RTW89_WOW_RSN_RX_NLO = 0x55, 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 { struct rtw89_cipher_suite {
u8 oui[3]; u8 oui[3];
u8 type; u8 type;
...@@ -64,6 +75,25 @@ struct rtw89_set_key_info_iter_data { ...@@ -64,6 +75,25 @@ struct rtw89_set_key_info_iter_data {
bool error; 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 #ifdef CONFIG_PM
int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan); int rtw89_wow_suspend(struct rtw89_dev *rtwdev, struct cfg80211_wowlan *wowlan);
int rtw89_wow_resume(struct rtw89_dev *rtwdev); 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