Skip to content

Commit 962a807

Browse files
dberlinjannau
authored andcommitted
[brcmfmac] Add support for more auth suites in roaming offload
This adds support for more authentication types during roaming offload, enabling the firmware to handle roaming for ~all authentication types. Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1 parent 66d9e5b commit 962a807

4 files changed

Lines changed: 194 additions & 26 deletions

File tree

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 183 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666
#define RSN_CAP_MFPR_MASK BIT(6)
6767
#define RSN_CAP_MFPC_MASK BIT(7)
6868
#define RSN_PMKID_COUNT_LEN 2
69+
#define DPP_AKM_SUITE_TYPE 2
70+
#define WLAN_AKM_SUITE_DPP SUITE(WLAN_OUI_WFA, DPP_AKM_SUITE_TYPE)
6971

7072
#define VNDR_IE_CMD_LEN 4 /* length of the set command
7173
* string :"add", "del" (+ NUL)
@@ -1840,15 +1842,20 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
18401842
struct brcmf_cfg80211_security *sec;
18411843
s32 val = 0;
18421844
s32 err = 0;
1843-
1844-
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1845+
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
18451846
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1846-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1847-
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1848-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
1847+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
1848+
if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
1849+
val = WPA3_AUTH_SAE_PSK;
1850+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE)
1851+
val = WPA3_AUTH_OWE;
1852+
else
1853+
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1854+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
18491855
val = WPA3_AUTH_SAE_PSK;
1850-
else
1856+
} else {
18511857
val = WPA_AUTH_DISABLED;
1858+
}
18521859
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
18531860
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
18541861
if (err) {
@@ -2063,9 +2070,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20632070
u16 rsn_cap;
20642071
u32 mfp;
20652072
u16 count;
2073+
s32 okc_enable;
2074+
u16 pmkid_count;
2075+
const u8 *group_mgmt_cs = NULL;
20662076

20672077
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
20682078
profile->is_ft = false;
2079+
profile->is_okc = false;
20692080

20702081
if (!sme->crypto.n_akm_suites)
20712082
return 0;
@@ -2082,13 +2093,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20822093
val = WPA_AUTH_UNSPECIFIED;
20832094
if (sme->want_1x)
20842095
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2096+
else
2097+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20852098
break;
20862099
case WLAN_AKM_SUITE_PSK:
20872100
val = WPA_AUTH_PSK;
20882101
break;
20892102
default:
2090-
bphy_err(drvr, "invalid akm suite (%d)\n",
2091-
sme->crypto.akm_suites[0]);
2103+
bphy_err(drvr, "invalid cipher group (%d)\n",
2104+
sme->crypto.cipher_group);
20922105
return -EINVAL;
20932106
}
20942107
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -2097,11 +2110,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20972110
val = WPA2_AUTH_UNSPECIFIED;
20982111
if (sme->want_1x)
20992112
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2113+
else
2114+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21002115
break;
21012116
case WLAN_AKM_SUITE_8021X_SHA256:
21022117
val = WPA2_AUTH_1X_SHA256;
21032118
if (sme->want_1x)
21042119
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2120+
else
2121+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21052122
break;
21062123
case WLAN_AKM_SUITE_PSK_SHA256:
21072124
val = WPA2_AUTH_PSK_SHA256;
@@ -2114,14 +2131,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21142131
profile->is_ft = true;
21152132
if (sme->want_1x)
21162133
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2134+
else
2135+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21172136
break;
21182137
case WLAN_AKM_SUITE_FT_PSK:
21192138
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
21202139
profile->is_ft = true;
2140+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP))
2141+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
2142+
else
2143+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2144+
break;
2145+
case WLAN_AKM_SUITE_DPP:
2146+
val = WFA_AUTH_DPP;
2147+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
2148+
break;
2149+
case WLAN_AKM_SUITE_OWE:
2150+
val = WPA3_AUTH_OWE;
2151+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2152+
break;
2153+
case WLAN_AKM_SUITE_8021X_SUITE_B_192:
2154+
val = WPA3_AUTH_1X_SUITE_B_SHA384;
2155+
if (sme->want_1x)
2156+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2157+
else
2158+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21212159
break;
21222160
default:
2123-
bphy_err(drvr, "invalid akm suite (%d)\n",
2124-
sme->crypto.akm_suites[0]);
2161+
bphy_err(drvr, "invalid cipher group (%d)\n",
2162+
sme->crypto.cipher_group);
21252163
return -EINVAL;
21262164
}
21272165
} else if (val & WPA3_AUTH_SAE_PSK) {
@@ -2142,15 +2180,34 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21422180
}
21432181
break;
21442182
default:
2145-
bphy_err(drvr, "invalid akm suite (%d)\n",
2146-
sme->crypto.akm_suites[0]);
2183+
bphy_err(drvr, "invalid cipher group (%d)\n",
2184+
sme->crypto.cipher_group);
21472185
return -EINVAL;
21482186
}
21492187
}
2150-
2151-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
2188+
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) ||
2189+
(profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM)) {
21522190
brcmf_dbg(INFO, "using 1X offload\n");
2153-
2191+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2192+
&okc_enable);
2193+
if (err) {
2194+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2195+
} else {
2196+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2197+
profile->is_okc = okc_enable;
2198+
}
2199+
} else if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE &&
2200+
(val == WPA3_AUTH_SAE_PSK)) {
2201+
brcmf_dbg(INFO, "not using SAE offload\n");
2202+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2203+
&okc_enable);
2204+
if (err) {
2205+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2206+
} else {
2207+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2208+
profile->is_okc = okc_enable;
2209+
}
2210+
}
21542211
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
21552212
goto skip_mfp_config;
21562213
/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
@@ -2183,14 +2240,47 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21832240
mfp = BRCMF_MFP_REQUIRED;
21842241
else if (rsn_cap & RSN_CAP_MFPC_MASK)
21852242
mfp = BRCMF_MFP_CAPABLE;
2243+
/* In case of dpp, very low tput is observed if MFPC is set in
2244+
* firmmare. Firmware needs to ensure that MFPC is not set when
2245+
* MFPR was requested from fmac. However since this change being
2246+
* specific to DPP, fmac needs to set wpa_auth prior to mfp, so
2247+
* that firmware can use this info to prevent MFPC being set in
2248+
* case of dpp.
2249+
*/
2250+
if (val == WFA_AUTH_DPP) {
2251+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2252+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2253+
val);
2254+
if (err) {
2255+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2256+
return err;
2257+
}
2258+
}
2259+
21862260
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
2261+
offset += RSN_CAP_LEN;
2262+
if (mfp && (ie_len - offset >= RSN_PMKID_COUNT_LEN)) {
2263+
pmkid_count = ie[offset] + (ie[offset + 1] << 8);
2264+
offset += RSN_PMKID_COUNT_LEN + (pmkid_count * WLAN_PMKID_LEN);
2265+
if (ie_len - offset >= WPA_IE_MIN_OUI_LEN) {
2266+
group_mgmt_cs = &ie[offset];
2267+
if (memcmp(group_mgmt_cs, RSN_OUI, TLV_OUI_LEN) == 0) {
2268+
brcmf_fil_bsscfg_data_set(ifp, "bip",
2269+
(void *)group_mgmt_cs,
2270+
WPA_IE_MIN_OUI_LEN);
2271+
}
2272+
}
2273+
}
21872274

21882275
skip_mfp_config:
2189-
brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
2190-
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
2191-
if (err) {
2192-
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2193-
return err;
2276+
if (val != WFA_AUTH_DPP) {
2277+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2278+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2279+
val);
2280+
if (err) {
2281+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2282+
return err;
2283+
}
21942284
}
21952285

21962286
return err;
@@ -2441,6 +2531,18 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24412531
}
24422532
}
24432533

2534+
if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
2535+
/* enable firmware supplicant for this interface */
2536+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
2537+
if (err < 0) {
2538+
bphy_err(drvr,
2539+
"failed to enable fw supplicant\n");
2540+
goto done;
2541+
}
2542+
} else {
2543+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
2544+
}
2545+
24442546
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) &&
24452547
params->crypto.psk)
24462548
err = brcmf_set_pmk(ifp, params->crypto.psk,
@@ -5886,17 +5988,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
58865988
const struct cfg80211_pmk_conf *conf)
58875989
{
58885990
struct brcmf_if *ifp;
5889-
5991+
struct brcmf_pub *drvr;
5992+
int ret;
58905993
brcmf_dbg(TRACE, "enter\n");
58915994

58925995
/* expect using firmware supplicant for 1X */
58935996
ifp = netdev_priv(dev);
5894-
if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
5997+
drvr = ifp->drvr;
5998+
if (WARN_ON((ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X) &&
5999+
(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_ROAM) &&
6000+
(ifp->vif->profile.is_ft != true) &&
6001+
(ifp->vif->profile.is_okc != true)))
58956002
return -EINVAL;
58966003

58976004
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
58986005
return -ERANGE;
58996006

6007+
if (ifp->vif->profile.is_okc) {
6008+
ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", conf->pmk,
6009+
conf->pmk_len);
6010+
if (ret < 0)
6011+
bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n",
6012+
ret);
6013+
}
59006014
return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
59016015
}
59026016

@@ -6333,6 +6447,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63336447
return err;
63346448
}
63356449

6450+
static bool brcmf_has_pmkid(const u8 *parse, u32 len)
6451+
{
6452+
const struct brcmf_tlv *rsn_ie;
6453+
const u8 *ie;
6454+
u32 ie_len;
6455+
u32 offset;
6456+
u16 count;
6457+
6458+
rsn_ie = brcmf_parse_tlvs(parse, len, WLAN_EID_RSN);
6459+
if (!rsn_ie)
6460+
goto done;
6461+
ie = (const u8 *)rsn_ie;
6462+
ie_len = rsn_ie->len + TLV_HDR_LEN;
6463+
/* Skip group data cipher suite */
6464+
offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
6465+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6466+
goto done;
6467+
/* Skip pairwise cipher suite(s) */
6468+
count = ie[offset] + (ie[offset + 1] << 8);
6469+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6470+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6471+
goto done;
6472+
/* Skip auth key management suite(s) */
6473+
count = ie[offset] + (ie[offset + 1] << 8);
6474+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6475+
if (offset + RSN_CAP_LEN >= ie_len)
6476+
goto done;
6477+
/* Skip rsn capabilities */
6478+
offset += RSN_CAP_LEN;
6479+
if (offset + RSN_PMKID_COUNT_LEN > ie_len)
6480+
goto done;
6481+
/* Extract PMKID count */
6482+
count = ie[offset] + (ie[offset + 1] << 8);
6483+
if (count)
6484+
return true;
6485+
6486+
done:
6487+
return false;
6488+
}
6489+
63366490
static s32
63376491
brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63386492
struct net_device *ndev,
@@ -6403,11 +6557,16 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
64036557
cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
64046558
brcmf_dbg(CONN, "Report roaming result\n");
64056559

6406-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
6407-
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
6560+
if (((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X ||
6561+
profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) &&
6562+
(brcmf_has_pmkid(roam_info.req_ie, roam_info.req_ie_len) ||
6563+
profile->is_ft || profile->is_okc))) {
6564+
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0,
6565+
GFP_KERNEL);
64086566
brcmf_dbg(CONN, "Report port authorized\n");
64096567
}
64106568

6569+
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
64116570
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
64126571
brcmf_dbg(TRACE, "Exit\n");
64136572
return err;

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ enum brcmf_profile_fwsup {
126126
BRCMF_PROFILE_FWSUP_NONE,
127127
BRCMF_PROFILE_FWSUP_PSK,
128128
BRCMF_PROFILE_FWSUP_1X,
129-
BRCMF_PROFILE_FWSUP_SAE
129+
BRCMF_PROFILE_FWSUP_SAE,
130+
BRCMF_PROFILE_FWSUP_ROAM
130131
};
131132

132133
/**
@@ -156,6 +157,7 @@ struct brcmf_cfg80211_profile {
156157
enum brcmf_profile_fwsup use_fwsup;
157158
u16 use_fwauth;
158159
bool is_ft;
160+
bool is_okc;
159161
};
160162

161163
/**

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
5959
{ BRCMF_FEAT_DOT11H, "802.11h" },
6060
{ BRCMF_FEAT_SAE, "sae" },
6161
{ BRCMF_FEAT_FWAUTH, "idauth" },
62-
{ BRCMF_FEAT_GCMP, "gcmp"}
62+
{ BRCMF_FEAT_GCMP, "gcmp" }
6363
};
6464

6565
#ifdef DEBUG

drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
254254
#define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */
255255

256256
#define WPA3_AUTH_SAE_PSK 0x40000 /* SAE with 4-way handshake */
257+
#define WPA3_AUTH_OWE 0x100000 /* OWE */
258+
#define WFA_AUTH_DPP 0x200000 /* WFA DPP AUTH */
259+
#define WPA3_AUTH_1X_SUITE_B_SHA384 0x400000 /* Suite B-192 SHA384 */
260+
261+
262+
#define WFA_OUI "\x50\x6F\x9A" /* WFA OUI */
263+
#define DPP_VER 0x1A /* WFA DPP v1.0 */
257264

258265
#define DOT11_DEFAULT_RTS_LEN 2347
259266
#define DOT11_DEFAULT_FRAG_LEN 2346

0 commit comments

Comments
 (0)