From 29d5267f428e8d14720dbe67980990df89728a4f Mon Sep 17 00:00:00 2001 From: Carter Chen Date: Wed, 12 Oct 2022 21:19:47 -0500 Subject: [PATCH 124/296] brcmfmac: ext_owe supporting parsing the AKM setting of OWE. parsing the ie in the cfg80211_connect_params, to find the owe extension ie we need to set to firmware. Fixes: SWLINUX-2956 Signed-off-by: Carter Chen --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 154 +++++++++++++++++- .../broadcom/brcm80211/include/brcmu_wifi.h | 2 +- 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 09770656b12f..e08d6b3f9d38 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -146,7 +146,6 @@ struct cca_msrmnt_query { /* start enum value for BSS properties */ #define WL_WSEC_INFO_BSS_BASE 0x0100 #define WL_WSEC_INFO_BSS_ALGOS (WL_WSEC_INFO_BSS_BASE + 6) - #define WL_HE_CMD_BSSCOLOR 5 static bool check_vif_up(struct brcmf_cfg80211_vif *vif) @@ -332,6 +331,32 @@ struct parsed_vndr_ies { struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; }; +struct brcmf_ext_tlv { + u8 id; + u8 len; + u8 ext_id; +}; + +struct parsed_ext_ie_info { + u8 *ie_ptr; + u32 ie_len; /* total length including id & length field */ + struct brcmf_ext_tlv ie_data; +}; + +struct parsed_extension_ies { + u32 count; + struct parsed_ext_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; +}; + +struct dot11_assoc_resp { + u16 capability; /* capability information */ + u16 status; /* status code */ + u16 aid; /* association ID */ +}; + +#define WLC_E_IF_ROLE_STA 0 /* Infra STA */ +#define WLC_E_IF_ROLE_AP 1 /* Access Point */ + #define WL_INTERFACE_CREATE_VER_1 1 #define WL_INTERFACE_CREATE_VER_2 2 #define WL_INTERFACE_CREATE_VER_3 3 @@ -2165,6 +2190,8 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) { if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE) val = WPA3_AUTH_SAE_PSK; + else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE) + val = WPA3_AUTH_OWE; else val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; } else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) { @@ -2418,6 +2445,10 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) val = WFA_AUTH_DPP; profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE; break; + case WLAN_AKM_SUITE_OWE: + val = WPA3_AUTH_OWE; + profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM; + break; case WLAN_AKM_SUITE_8021X_SUITE_B_192: val = WPA3_AUTH_1X_SUITE_B_SHA384; if (sme->want_1x) @@ -5306,6 +5337,58 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) return ie_len + VNDR_IE_HDR_SIZE; } +static s32 +brcmf_parse_extension_ies(const u8 *extension_ie_buf, u32 extension_ie_len, + struct parsed_extension_ies *extension_ies) +{ + struct brcmf_ext_tlv *ext_ie; + struct brcmf_tlv *ie; + struct parsed_ext_ie_info *parsed_info; + s32 remaining_len; + + remaining_len = (s32)extension_ie_len; + memset(extension_ies, 0, sizeof(*extension_ies)); + + ie = (struct brcmf_tlv *)extension_ie_buf; + while (ie) { + if (ie->id != WLAN_EID_EXTENSION) + goto next; + ext_ie = (struct brcmf_ext_tlv *)ie; + + /* len should be bigger than ext_id + one data */ + if (ext_ie->len < 2) { + brcmf_err("invalid ext_ie ie. length is too small %d\n", + ext_ie->len); + goto next; + } + + parsed_info = &extension_ies->ie_info[extension_ies->count]; + + parsed_info->ie_ptr = (char *)ext_ie; + parsed_info->ie_len = ext_ie->len + TLV_HDR_LEN; + memcpy(&parsed_info->ie_data, ext_ie, sizeof(*ext_ie)); + + extension_ies->count++; + + brcmf_dbg(TRACE, "** EXT_IE %d, len 0x%02x EXT_ID: %d\n", + parsed_info->ie_data.id, + parsed_info->ie_data.len, + parsed_info->ie_data.ext_id); + + /* temperory parsing at most 5 EXT_ID, will review it.*/ + if (extension_ies->count >= VNDR_IE_PARSE_LIMIT) + break; +next: + remaining_len -= (ie->len + TLV_HDR_LEN); + if (remaining_len <= TLV_HDR_LEN) + ie = NULL; + else + ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len + + TLV_HDR_LEN); + } + return 0; +} + s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len) { @@ -5327,6 +5410,9 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, s32 i; u8 *ptr; int remained_buf_len; + struct parsed_extension_ies new_ext_ies; + struct parsed_extension_ies old_ext_ies; + struct parsed_ext_ie_info *extie_info; if (!vif) return -ENODEV; @@ -5388,6 +5474,13 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, vndrie_info->ie_len); parsed_ie_buf_len += vndrie_info->ie_len; } + brcmf_parse_extension_ies(vndr_ie_buf, vndr_ie_len, &new_ext_ies); + for (i = 0; i < new_ext_ies.count; i++) { + extie_info = &new_ext_ies.ie_info[i]; + memcpy(ptr + parsed_ie_buf_len, extie_info->ie_ptr, + extie_info->ie_len); + parsed_ie_buf_len += extie_info->ie_len; + } } if (mgmt_ie_buf && *mgmt_ie_len) { @@ -5400,6 +5493,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, /* parse old vndr_ie */ brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies); + /* parse old ext_ie */ + brcmf_parse_extension_ies(mgmt_ie_buf, *mgmt_ie_len, &old_ext_ies); /* make a command to delete old ie */ for (i = 0; i < old_vndr_ies.count; i++) { @@ -5417,6 +5512,23 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, curr_ie_buf += del_add_ie_buf_len; total_ie_buf_len += del_add_ie_buf_len; } + /* make a command to delete old extension ie */ + for (i = 0; i < old_ext_ies.count; i++) { + extie_info = &old_ext_ies.ie_info[i]; + + brcmf_dbg(TRACE, "DEL EXT_IE : %d, Len: %d , ext_id:%d\n", + extie_info->ie_data.id, + extie_info->ie_data.len, + extie_info->ie_data.ext_id); + + del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, + pktflag | BRCMF_VNDR_IE_CUSTOM_FLAG, + extie_info->ie_ptr, + extie_info->ie_len, + "del"); + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; + } } *mgmt_ie_len = 0; @@ -5455,6 +5567,39 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, vndrie_info->ie_len); *mgmt_ie_len += vndrie_info->ie_len; + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; + } + /* make a command to add new EXT ie */ + for (i = 0; i < new_ext_ies.count; i++) { + extie_info = &new_ext_ies.ie_info[i]; + + /* verify remained buf size before copy data */ + if (remained_buf_len < (extie_info->ie_data.len + + VNDR_IE_VSIE_OFFSET)) { + bphy_err(drvr, "no space in mgmt_ie_buf: len left %d", + remained_buf_len); + break; + } + remained_buf_len -= (extie_info->ie_len + + VNDR_IE_VSIE_OFFSET); + + brcmf_dbg(TRACE, "ADDED EXT ID : %d, Len: %d, OUI:%d\n", + extie_info->ie_data.id, + extie_info->ie_data.len, + extie_info->ie_data.ext_id); + + del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, + pktflag | BRCMF_VNDR_IE_CUSTOM_FLAG, + extie_info->ie_ptr, + extie_info->ie_len, + "add"); + + /* save the parsed IE in wl struct */ + memcpy(ptr + (*mgmt_ie_len), extie_info->ie_ptr, + extie_info->ie_len); + *mgmt_ie_len += extie_info->ie_len; + curr_ie_buf += del_add_ie_buf_len; total_ie_buf_len += del_add_ie_buf_len; } @@ -7151,6 +7296,11 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, conn_info->req_ie_len = 0; conn_info->req_ie = NULL; } + + /* resp_len is the total length of assoc resp + * which includes 6 bytes of aid/status code/capabilities. + * the assoc_resp_ie length should minus the 6 bytes which starts from rate_ie. + */ if (resp_len) { err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies", cfg->extra_buf, @@ -7159,7 +7309,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, bphy_err(drvr, "could not get assoc resp (%d)\n", err); return err; } - conn_info->resp_ie_len = resp_len; + conn_info->resp_ie_len = resp_len - sizeof(struct dot11_assoc_resp); conn_info->resp_ie = kmemdup(cfg->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h index 04bf1c0b3b06..de5b585b91a8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h @@ -240,7 +240,7 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec) #define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */ #define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */ - +#define WPA3_AUTH_OWE 0x100000 /* OWE */ #define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */ #define WPA3_AUTH_1X_SUITE_B_SHA384 0x400000 /* Suite B-192 SHA384 */ -- 2.25.1