Skip to content

Commit 3b1c053

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 587c169 commit 3b1c053

3 files changed

Lines changed: 187 additions & 18 deletions

File tree

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

Lines changed: 177 additions & 17 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)
@@ -1846,6 +1848,10 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
18461848
if (drvr->bus_if->fwvid == BRCMF_FWVENDOR_CYW &&
18471849
sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
18481850
val = WPA3_AUTH_SAE_PSK;
1851+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
1852+
val = WPA3_AUTH_SAE_PSK;
1853+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE)
1854+
val = WPA3_AUTH_OWE;
18491855
else
18501856
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
18511857
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
@@ -2067,9 +2073,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20672073
u16 rsn_cap;
20682074
u32 mfp;
20692075
u16 count;
2076+
s32 okc_enable;
2077+
u16 pmkid_count;
2078+
const u8 *group_mgmt_cs = NULL;
20702079

20712080
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
20722081
profile->is_ft = false;
2082+
profile->is_okc = false;
20732083

20742084
if (!sme->crypto.n_akm_suites)
20752085
return 0;
@@ -2086,13 +2096,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20862096
val = WPA_AUTH_UNSPECIFIED;
20872097
if (sme->want_1x)
20882098
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2099+
else
2100+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20892101
break;
20902102
case WLAN_AKM_SUITE_PSK:
20912103
val = WPA_AUTH_PSK;
20922104
break;
20932105
default:
2094-
bphy_err(drvr, "invalid akm suite (%d)\n",
2095-
sme->crypto.akm_suites[0]);
2106+
bphy_err(drvr, "invalid cipher group (%d)\n",
2107+
sme->crypto.cipher_group);
20962108
return -EINVAL;
20972109
}
20982110
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -2101,11 +2113,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21012113
val = WPA2_AUTH_UNSPECIFIED;
21022114
if (sme->want_1x)
21032115
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2116+
else
2117+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21042118
break;
21052119
case WLAN_AKM_SUITE_8021X_SHA256:
21062120
val = WPA2_AUTH_1X_SHA256;
21072121
if (sme->want_1x)
21082122
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2123+
else
2124+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21092125
break;
21102126
case WLAN_AKM_SUITE_PSK_SHA256:
21112127
val = WPA2_AUTH_PSK_SHA256;
@@ -2118,14 +2134,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21182134
profile->is_ft = true;
21192135
if (sme->want_1x)
21202136
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2137+
else
2138+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21212139
break;
21222140
case WLAN_AKM_SUITE_FT_PSK:
21232141
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
21242142
profile->is_ft = true;
2143+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP))
2144+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
2145+
else
2146+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2147+
break;
2148+
case WLAN_AKM_SUITE_DPP:
2149+
val = WFA_AUTH_DPP;
2150+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
2151+
break;
2152+
case WLAN_AKM_SUITE_OWE:
2153+
val = WPA3_AUTH_OWE;
2154+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2155+
break;
2156+
case WLAN_AKM_SUITE_8021X_SUITE_B_192:
2157+
val = WPA3_AUTH_1X_SUITE_B_SHA384;
2158+
if (sme->want_1x)
2159+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2160+
else
2161+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21252162
break;
21262163
default:
2127-
bphy_err(drvr, "invalid akm suite (%d)\n",
2128-
sme->crypto.akm_suites[0]);
2164+
bphy_err(drvr, "invalid cipher group (%d)\n",
2165+
sme->crypto.cipher_group);
21292166
return -EINVAL;
21302167
}
21312168
} else if (val & WPA3_AUTH_SAE_PSK) {
@@ -2138,17 +2175,38 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21382175
profile->is_ft = true;
21392176
break;
21402177
default:
2141-
bphy_err(drvr, "invalid akm suite (%d)\n",
2142-
sme->crypto.akm_suites[0]);
2178+
bphy_err(drvr, "invalid cipher group (%d)\n",
2179+
sme->crypto.cipher_group);
21432180
return -EINVAL;
21442181
}
21452182
if (sme->crypto.sae_pwd) {
21462183
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
21472184
}
21482185
}
2149-
2150-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
2186+
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) ||
2187+
(profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM)) {
21512188
brcmf_dbg(INFO, "using 1X offload\n");
2189+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2190+
&okc_enable);
2191+
if (err) {
2192+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2193+
} else {
2194+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2195+
profile->is_okc = okc_enable;
2196+
}
2197+
} else if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE &&
2198+
(val == WPA3_AUTH_SAE_PSK)) {
2199+
brcmf_dbg(INFO, "not using SAE offload\n");
2200+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2201+
&okc_enable);
2202+
if (err) {
2203+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2204+
} else {
2205+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2206+
profile->is_okc = okc_enable;
2207+
}
2208+
}
2209+
21522210
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE)
21532211
brcmf_dbg(INFO, "using SAE offload\n");
21542212

@@ -2184,14 +2242,47 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21842242
mfp = BRCMF_MFP_REQUIRED;
21852243
else if (rsn_cap & RSN_CAP_MFPC_MASK)
21862244
mfp = BRCMF_MFP_CAPABLE;
2245+
/* In case of dpp, very low tput is observed if MFPC is set in
2246+
* firmmare. Firmware needs to ensure that MFPC is not set when
2247+
* MFPR was requested from fmac. However since this change being
2248+
* specific to DPP, fmac needs to set wpa_auth prior to mfp, so
2249+
* that firmware can use this info to prevent MFPC being set in
2250+
* case of dpp.
2251+
*/
2252+
if (val == WFA_AUTH_DPP) {
2253+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2254+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2255+
val);
2256+
if (err) {
2257+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2258+
return err;
2259+
}
2260+
}
2261+
21872262
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
2263+
offset += RSN_CAP_LEN;
2264+
if (mfp && (ie_len - offset >= RSN_PMKID_COUNT_LEN)) {
2265+
pmkid_count = ie[offset] + (ie[offset + 1] << 8);
2266+
offset += RSN_PMKID_COUNT_LEN + (pmkid_count * WLAN_PMKID_LEN);
2267+
if (ie_len - offset >= WPA_IE_MIN_OUI_LEN) {
2268+
group_mgmt_cs = &ie[offset];
2269+
if (memcmp(group_mgmt_cs, RSN_OUI, TLV_OUI_LEN) == 0) {
2270+
brcmf_fil_bsscfg_data_set(ifp, "bip",
2271+
(void *)group_mgmt_cs,
2272+
WPA_IE_MIN_OUI_LEN);
2273+
}
2274+
}
2275+
}
21882276

21892277
skip_mfp_config:
2190-
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2191-
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
2192-
if (err) {
2193-
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2194-
return err;
2278+
if (val != WFA_AUTH_DPP) {
2279+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2280+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2281+
val);
2282+
if (err) {
2283+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2284+
return err;
2285+
}
21952286
}
21962287

21972288
return err;
@@ -2442,6 +2533,18 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24422533
}
24432534
}
24442535

2536+
if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
2537+
/* enable firmware supplicant for this interface */
2538+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
2539+
if (err < 0) {
2540+
bphy_err(drvr,
2541+
"failed to enable fw supplicant\n");
2542+
goto done;
2543+
}
2544+
} else {
2545+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
2546+
}
2547+
24452548
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) &&
24462549
params->crypto.psk)
24472550
err = brcmf_set_pmk(ifp, params->crypto.psk,
@@ -5888,17 +5991,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
58885991
const struct cfg80211_pmk_conf *conf)
58895992
{
58905993
struct brcmf_if *ifp;
5891-
5994+
struct brcmf_pub *drvr;
5995+
int ret;
58925996
brcmf_dbg(TRACE, "enter\n");
58935997

58945998
/* expect using firmware supplicant for 1X */
58955999
ifp = netdev_priv(dev);
5896-
if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
6000+
drvr = ifp->drvr;
6001+
if (WARN_ON((ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X) &&
6002+
(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_ROAM) &&
6003+
(ifp->vif->profile.is_ft != true) &&
6004+
(ifp->vif->profile.is_okc != true)))
58976005
return -EINVAL;
58986006

58996007
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
59006008
return -ERANGE;
59016009

6010+
if (ifp->vif->profile.is_okc) {
6011+
ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", conf->pmk,
6012+
conf->pmk_len);
6013+
if (ret < 0)
6014+
bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n",
6015+
ret);
6016+
}
59026017
return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
59036018
}
59046019

@@ -6336,6 +6451,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63366451
return err;
63376452
}
63386453

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

6409-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
6410-
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
6564+
if (((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X ||
6565+
profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) &&
6566+
(brcmf_has_pmkid(roam_info.req_ie, roam_info.req_ie_len) ||
6567+
profile->is_ft || profile->is_okc))) {
6568+
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0,
6569+
GFP_KERNEL);
64116570
brcmf_dbg(CONN, "Report port authorized\n");
64126571
}
64136572

6573+
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
64146574
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
64156575
brcmf_dbg(TRACE, "Exit\n");
64166576
return err;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ enum brcmf_profile_fwsup {
128128
BRCMF_PROFILE_FWSUP_NONE,
129129
BRCMF_PROFILE_FWSUP_PSK,
130130
BRCMF_PROFILE_FWSUP_1X,
131-
BRCMF_PROFILE_FWSUP_SAE
131+
BRCMF_PROFILE_FWSUP_SAE,
132+
BRCMF_PROFILE_FWSUP_ROAM
132133
};
133134

134135
/**
@@ -173,6 +174,7 @@ struct brcmf_cfg80211_profile {
173174
enum brcmf_profile_fwsup use_fwsup;
174175
u16 use_fwauth;
175176
bool is_ft;
177+
bool is_okc;
176178
};
177179

178180
/**

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)