Skip to content

Commit 778e562

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 fd3c448 commit 778e562

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)
@@ -1860,6 +1862,10 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
18601862
if (drvr->bus_if->fwvid == BRCMF_FWVENDOR_CYW &&
18611863
sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
18621864
val = WPA3_AUTH_SAE_PSK;
1865+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
1866+
val = WPA3_AUTH_SAE_PSK;
1867+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE)
1868+
val = WPA3_AUTH_OWE;
18631869
else
18641870
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
18651871
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
@@ -2081,9 +2087,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20812087
u16 rsn_cap;
20822088
u32 mfp;
20832089
u16 count;
2090+
s32 okc_enable;
2091+
u16 pmkid_count;
2092+
const u8 *group_mgmt_cs = NULL;
20842093

20852094
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
20862095
profile->is_ft = false;
2096+
profile->is_okc = false;
20872097

20882098
if (!sme->crypto.n_akm_suites)
20892099
return 0;
@@ -2100,13 +2110,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21002110
val = WPA_AUTH_UNSPECIFIED;
21012111
if (sme->want_1x)
21022112
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2113+
else
2114+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21032115
break;
21042116
case WLAN_AKM_SUITE_PSK:
21052117
val = WPA_AUTH_PSK;
21062118
break;
21072119
default:
2108-
bphy_err(drvr, "invalid akm suite (%d)\n",
2109-
sme->crypto.akm_suites[0]);
2120+
bphy_err(drvr, "invalid cipher group (%d)\n",
2121+
sme->crypto.cipher_group);
21102122
return -EINVAL;
21112123
}
21122124
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -2115,11 +2127,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21152127
val = WPA2_AUTH_UNSPECIFIED;
21162128
if (sme->want_1x)
21172129
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2130+
else
2131+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21182132
break;
21192133
case WLAN_AKM_SUITE_8021X_SHA256:
21202134
val = WPA2_AUTH_1X_SHA256;
21212135
if (sme->want_1x)
21222136
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2137+
else
2138+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21232139
break;
21242140
case WLAN_AKM_SUITE_PSK_SHA256:
21252141
val = WPA2_AUTH_PSK_SHA256;
@@ -2132,14 +2148,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21322148
profile->is_ft = true;
21332149
if (sme->want_1x)
21342150
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2151+
else
2152+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21352153
break;
21362154
case WLAN_AKM_SUITE_FT_PSK:
21372155
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
21382156
profile->is_ft = true;
2157+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP))
2158+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
2159+
else
2160+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2161+
break;
2162+
case WLAN_AKM_SUITE_DPP:
2163+
val = WFA_AUTH_DPP;
2164+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
2165+
break;
2166+
case WLAN_AKM_SUITE_OWE:
2167+
val = WPA3_AUTH_OWE;
2168+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2169+
break;
2170+
case WLAN_AKM_SUITE_8021X_SUITE_B_192:
2171+
val = WPA3_AUTH_1X_SUITE_B_SHA384;
2172+
if (sme->want_1x)
2173+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2174+
else
2175+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
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
} else if (val & WPA3_AUTH_SAE_PSK) {
@@ -2152,17 +2189,38 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21522189
profile->is_ft = true;
21532190
break;
21542191
default:
2155-
bphy_err(drvr, "invalid akm suite (%d)\n",
2156-
sme->crypto.akm_suites[0]);
2192+
bphy_err(drvr, "invalid cipher group (%d)\n",
2193+
sme->crypto.cipher_group);
21572194
return -EINVAL;
21582195
}
21592196
if (sme->crypto.sae_pwd) {
21602197
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
21612198
}
21622199
}
2163-
2164-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
2200+
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) ||
2201+
(profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM)) {
21652202
brcmf_dbg(INFO, "using 1X offload\n");
2203+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2204+
&okc_enable);
2205+
if (err) {
2206+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2207+
} else {
2208+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2209+
profile->is_okc = okc_enable;
2210+
}
2211+
} else if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE &&
2212+
(val == WPA3_AUTH_SAE_PSK)) {
2213+
brcmf_dbg(INFO, "not using SAE offload\n");
2214+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2215+
&okc_enable);
2216+
if (err) {
2217+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2218+
} else {
2219+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2220+
profile->is_okc = okc_enable;
2221+
}
2222+
}
2223+
21662224
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_SAE)
21672225
brcmf_dbg(INFO, "using SAE offload\n");
21682226

@@ -2198,14 +2256,47 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21982256
mfp = BRCMF_MFP_REQUIRED;
21992257
else if (rsn_cap & RSN_CAP_MFPC_MASK)
22002258
mfp = BRCMF_MFP_CAPABLE;
2259+
/* In case of dpp, very low tput is observed if MFPC is set in
2260+
* firmmare. Firmware needs to ensure that MFPC is not set when
2261+
* MFPR was requested from fmac. However since this change being
2262+
* specific to DPP, fmac needs to set wpa_auth prior to mfp, so
2263+
* that firmware can use this info to prevent MFPC being set in
2264+
* case of dpp.
2265+
*/
2266+
if (val == WFA_AUTH_DPP) {
2267+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2268+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2269+
val);
2270+
if (err) {
2271+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2272+
return err;
2273+
}
2274+
}
2275+
22012276
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
2277+
offset += RSN_CAP_LEN;
2278+
if (mfp && (ie_len - offset >= RSN_PMKID_COUNT_LEN)) {
2279+
pmkid_count = ie[offset] + (ie[offset + 1] << 8);
2280+
offset += RSN_PMKID_COUNT_LEN + (pmkid_count * WLAN_PMKID_LEN);
2281+
if (ie_len - offset >= WPA_IE_MIN_OUI_LEN) {
2282+
group_mgmt_cs = &ie[offset];
2283+
if (memcmp(group_mgmt_cs, RSN_OUI, TLV_OUI_LEN) == 0) {
2284+
brcmf_fil_bsscfg_data_set(ifp, "bip",
2285+
(void *)group_mgmt_cs,
2286+
WPA_IE_MIN_OUI_LEN);
2287+
}
2288+
}
2289+
}
22022290

22032291
skip_mfp_config:
2204-
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2205-
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
2206-
if (err) {
2207-
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2208-
return err;
2292+
if (val != WFA_AUTH_DPP) {
2293+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2294+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2295+
val);
2296+
if (err) {
2297+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2298+
return err;
2299+
}
22092300
}
22102301

22112302
return err;
@@ -2456,6 +2547,18 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24562547
}
24572548
}
24582549

2550+
if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
2551+
/* enable firmware supplicant for this interface */
2552+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
2553+
if (err < 0) {
2554+
bphy_err(drvr,
2555+
"failed to enable fw supplicant\n");
2556+
goto done;
2557+
}
2558+
} else {
2559+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
2560+
}
2561+
24592562
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) &&
24602563
params->crypto.psk)
24612564
err = brcmf_set_pmk(ifp, params->crypto.psk,
@@ -5910,17 +6013,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
59106013
const struct cfg80211_pmk_conf *conf)
59116014
{
59126015
struct brcmf_if *ifp;
5913-
6016+
struct brcmf_pub *drvr;
6017+
int ret;
59146018
brcmf_dbg(TRACE, "enter\n");
59156019

59166020
/* expect using firmware supplicant for 1X */
59176021
ifp = netdev_priv(dev);
5918-
if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
6022+
drvr = ifp->drvr;
6023+
if (WARN_ON((ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X) &&
6024+
(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_ROAM) &&
6025+
(ifp->vif->profile.is_ft != true) &&
6026+
(ifp->vif->profile.is_okc != true)))
59196027
return -EINVAL;
59206028

59216029
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
59226030
return -ERANGE;
59236031

6032+
if (ifp->vif->profile.is_okc) {
6033+
ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", conf->pmk,
6034+
conf->pmk_len);
6035+
if (ret < 0)
6036+
bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n",
6037+
ret);
6038+
}
59246039
return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
59256040
}
59266041

@@ -6379,6 +6494,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63796494
return err;
63806495
}
63816496

6497+
static bool brcmf_has_pmkid(const u8 *parse, u32 len)
6498+
{
6499+
const struct brcmf_tlv *rsn_ie;
6500+
const u8 *ie;
6501+
u32 ie_len;
6502+
u32 offset;
6503+
u16 count;
6504+
6505+
rsn_ie = brcmf_parse_tlvs(parse, len, WLAN_EID_RSN);
6506+
if (!rsn_ie)
6507+
goto done;
6508+
ie = (const u8 *)rsn_ie;
6509+
ie_len = rsn_ie->len + TLV_HDR_LEN;
6510+
/* Skip group data cipher suite */
6511+
offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
6512+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6513+
goto done;
6514+
/* Skip pairwise cipher suite(s) */
6515+
count = ie[offset] + (ie[offset + 1] << 8);
6516+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6517+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6518+
goto done;
6519+
/* Skip auth key management suite(s) */
6520+
count = ie[offset] + (ie[offset + 1] << 8);
6521+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6522+
if (offset + RSN_CAP_LEN >= ie_len)
6523+
goto done;
6524+
/* Skip rsn capabilities */
6525+
offset += RSN_CAP_LEN;
6526+
if (offset + RSN_PMKID_COUNT_LEN > ie_len)
6527+
goto done;
6528+
/* Extract PMKID count */
6529+
count = ie[offset] + (ie[offset + 1] << 8);
6530+
if (count)
6531+
return true;
6532+
6533+
done:
6534+
return false;
6535+
}
6536+
63826537
static s32
63836538
brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63846539
struct net_device *ndev,
@@ -6449,11 +6604,16 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
64496604
cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
64506605
brcmf_dbg(CONN, "Report roaming result\n");
64516606

6452-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
6453-
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
6607+
if (((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X ||
6608+
profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) &&
6609+
(brcmf_has_pmkid(roam_info.req_ie, roam_info.req_ie_len) ||
6610+
profile->is_ft || profile->is_okc))) {
6611+
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0,
6612+
GFP_KERNEL);
64546613
brcmf_dbg(CONN, "Report port authorized\n");
64556614
}
64566615

6616+
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
64576617
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
64586618
brcmf_dbg(TRACE, "Exit\n");
64596619
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)