Skip to content

Commit 354b6e8

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 ae686cb commit 354b6e8

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)
@@ -1836,15 +1838,20 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
18361838
struct brcmf_cfg80211_security *sec;
18371839
s32 val = 0;
18381840
s32 err = 0;
1839-
1840-
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1841+
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
18411842
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1842-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1843-
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1844-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
1843+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
1844+
if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
1845+
val = WPA3_AUTH_SAE_PSK;
1846+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE)
1847+
val = WPA3_AUTH_OWE;
1848+
else
1849+
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1850+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
18451851
val = WPA3_AUTH_SAE_PSK;
1846-
else
1852+
} else {
18471853
val = WPA_AUTH_DISABLED;
1854+
}
18481855
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
18491856
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
18501857
if (err) {
@@ -2059,9 +2066,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20592066
u16 rsn_cap;
20602067
u32 mfp;
20612068
u16 count;
2069+
s32 okc_enable;
2070+
u16 pmkid_count;
2071+
const u8 *group_mgmt_cs = NULL;
20622072

20632073
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
20642074
profile->is_ft = false;
2075+
profile->is_okc = false;
20652076

20662077
if (!sme->crypto.n_akm_suites)
20672078
return 0;
@@ -2077,13 +2088,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20772088
val = WPA_AUTH_UNSPECIFIED;
20782089
if (sme->want_1x)
20792090
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2091+
else
2092+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20802093
break;
20812094
case WLAN_AKM_SUITE_PSK:
20822095
val = WPA_AUTH_PSK;
20832096
break;
20842097
default:
2085-
bphy_err(drvr, "invalid akm suite (%d)\n",
2086-
sme->crypto.akm_suites[0]);
2098+
bphy_err(drvr, "invalid cipher group (%d)\n",
2099+
sme->crypto.cipher_group);
20872100
return -EINVAL;
20882101
}
20892102
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -2092,11 +2105,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20922105
val = WPA2_AUTH_UNSPECIFIED;
20932106
if (sme->want_1x)
20942107
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2108+
else
2109+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20952110
break;
20962111
case WLAN_AKM_SUITE_8021X_SHA256:
20972112
val = WPA2_AUTH_1X_SHA256;
20982113
if (sme->want_1x)
20992114
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2115+
else
2116+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21002117
break;
21012118
case WLAN_AKM_SUITE_PSK_SHA256:
21022119
val = WPA2_AUTH_PSK_SHA256;
@@ -2109,14 +2126,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21092126
profile->is_ft = true;
21102127
if (sme->want_1x)
21112128
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2129+
else
2130+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21122131
break;
21132132
case WLAN_AKM_SUITE_FT_PSK:
21142133
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
21152134
profile->is_ft = true;
2135+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP))
2136+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
2137+
else
2138+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2139+
break;
2140+
case WLAN_AKM_SUITE_DPP:
2141+
val = WFA_AUTH_DPP;
2142+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
2143+
break;
2144+
case WLAN_AKM_SUITE_OWE:
2145+
val = WPA3_AUTH_OWE;
2146+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2147+
break;
2148+
case WLAN_AKM_SUITE_8021X_SUITE_B_192:
2149+
val = WPA3_AUTH_1X_SUITE_B_SHA384;
2150+
if (sme->want_1x)
2151+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2152+
else
2153+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21162154
break;
21172155
default:
2118-
bphy_err(drvr, "invalid akm suite (%d)\n",
2119-
sme->crypto.akm_suites[0]);
2156+
bphy_err(drvr, "invalid cipher group (%d)\n",
2157+
sme->crypto.cipher_group);
21202158
return -EINVAL;
21212159
}
21222160
} else if (val & WPA3_AUTH_SAE_PSK) {
@@ -2137,15 +2175,34 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21372175
}
21382176
break;
21392177
default:
2140-
bphy_err(drvr, "invalid akm suite (%d)\n",
2141-
sme->crypto.akm_suites[0]);
2178+
bphy_err(drvr, "invalid cipher group (%d)\n",
2179+
sme->crypto.cipher_group);
21422180
return -EINVAL;
21432181
}
21442182
}
2145-
2146-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
2183+
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) ||
2184+
(profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM)) {
21472185
brcmf_dbg(INFO, "using 1X offload\n");
2148-
2186+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2187+
&okc_enable);
2188+
if (err) {
2189+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2190+
} else {
2191+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2192+
profile->is_okc = okc_enable;
2193+
}
2194+
} else if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE &&
2195+
(val == WPA3_AUTH_SAE_PSK)) {
2196+
brcmf_dbg(INFO, "not using SAE offload\n");
2197+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2198+
&okc_enable);
2199+
if (err) {
2200+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2201+
} else {
2202+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2203+
profile->is_okc = okc_enable;
2204+
}
2205+
}
21492206
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
21502207
goto skip_mfp_config;
21512208
/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
@@ -2178,14 +2235,47 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21782235
mfp = BRCMF_MFP_REQUIRED;
21792236
else if (rsn_cap & RSN_CAP_MFPC_MASK)
21802237
mfp = BRCMF_MFP_CAPABLE;
2238+
/* In case of dpp, very low tput is observed if MFPC is set in
2239+
* firmmare. Firmware needs to ensure that MFPC is not set when
2240+
* MFPR was requested from fmac. However since this change being
2241+
* specific to DPP, fmac needs to set wpa_auth prior to mfp, so
2242+
* that firmware can use this info to prevent MFPC being set in
2243+
* case of dpp.
2244+
*/
2245+
if (val == WFA_AUTH_DPP) {
2246+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2247+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2248+
val);
2249+
if (err) {
2250+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2251+
return err;
2252+
}
2253+
}
2254+
21812255
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
2256+
offset += RSN_CAP_LEN;
2257+
if (mfp && (ie_len - offset >= RSN_PMKID_COUNT_LEN)) {
2258+
pmkid_count = ie[offset] + (ie[offset + 1] << 8);
2259+
offset += RSN_PMKID_COUNT_LEN + (pmkid_count * WLAN_PMKID_LEN);
2260+
if (ie_len - offset >= WPA_IE_MIN_OUI_LEN) {
2261+
group_mgmt_cs = &ie[offset];
2262+
if (memcmp(group_mgmt_cs, RSN_OUI, TLV_OUI_LEN) == 0) {
2263+
brcmf_fil_bsscfg_data_set(ifp, "bip",
2264+
(void *)group_mgmt_cs,
2265+
WPA_IE_MIN_OUI_LEN);
2266+
}
2267+
}
2268+
}
21822269

21832270
skip_mfp_config:
2184-
brcmf_dbg(CONN, "setting wpa_auth to %d\n", val);
2185-
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val);
2186-
if (err) {
2187-
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2188-
return err;
2271+
if (val != WFA_AUTH_DPP) {
2272+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2273+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2274+
val);
2275+
if (err) {
2276+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2277+
return err;
2278+
}
21892279
}
21902280

21912281
return err;
@@ -2436,6 +2526,18 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24362526
}
24372527
}
24382528

2529+
if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
2530+
/* enable firmware supplicant for this interface */
2531+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
2532+
if (err < 0) {
2533+
bphy_err(drvr,
2534+
"failed to enable fw supplicant\n");
2535+
goto done;
2536+
}
2537+
} else {
2538+
err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 0);
2539+
}
2540+
24392541
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) &&
24402542
params->crypto.psk)
24412543
err = brcmf_set_pmk(ifp, params->crypto.psk,
@@ -5877,17 +5979,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
58775979
const struct cfg80211_pmk_conf *conf)
58785980
{
58795981
struct brcmf_if *ifp;
5880-
5982+
struct brcmf_pub *drvr;
5983+
int ret;
58815984
brcmf_dbg(TRACE, "enter\n");
58825985

58835986
/* expect using firmware supplicant for 1X */
58845987
ifp = netdev_priv(dev);
5885-
if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
5988+
drvr = ifp->drvr;
5989+
if (WARN_ON((ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X) &&
5990+
(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_ROAM) &&
5991+
(ifp->vif->profile.is_ft != true) &&
5992+
(ifp->vif->profile.is_okc != true)))
58865993
return -EINVAL;
58875994

58885995
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
58895996
return -ERANGE;
58905997

5998+
if (ifp->vif->profile.is_okc) {
5999+
ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", conf->pmk,
6000+
conf->pmk_len);
6001+
if (ret < 0)
6002+
bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n",
6003+
ret);
6004+
}
58916005
return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
58926006
}
58936007

@@ -6324,6 +6438,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63246438
return err;
63256439
}
63266440

6441+
static bool brcmf_has_pmkid(const u8 *parse, u32 len)
6442+
{
6443+
const struct brcmf_tlv *rsn_ie;
6444+
const u8 *ie;
6445+
u32 ie_len;
6446+
u32 offset;
6447+
u16 count;
6448+
6449+
rsn_ie = brcmf_parse_tlvs(parse, len, WLAN_EID_RSN);
6450+
if (!rsn_ie)
6451+
goto done;
6452+
ie = (const u8 *)rsn_ie;
6453+
ie_len = rsn_ie->len + TLV_HDR_LEN;
6454+
/* Skip group data cipher suite */
6455+
offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
6456+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6457+
goto done;
6458+
/* Skip pairwise cipher suite(s) */
6459+
count = ie[offset] + (ie[offset + 1] << 8);
6460+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6461+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6462+
goto done;
6463+
/* Skip auth key management suite(s) */
6464+
count = ie[offset] + (ie[offset + 1] << 8);
6465+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6466+
if (offset + RSN_CAP_LEN >= ie_len)
6467+
goto done;
6468+
/* Skip rsn capabilities */
6469+
offset += RSN_CAP_LEN;
6470+
if (offset + RSN_PMKID_COUNT_LEN > ie_len)
6471+
goto done;
6472+
/* Extract PMKID count */
6473+
count = ie[offset] + (ie[offset + 1] << 8);
6474+
if (count)
6475+
return true;
6476+
6477+
done:
6478+
return false;
6479+
}
6480+
63276481
static s32
63286482
brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63296483
struct net_device *ndev,
@@ -6394,11 +6548,16 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63946548
cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
63956549
brcmf_dbg(CONN, "Report roaming result\n");
63966550

6397-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
6398-
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
6551+
if (((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X ||
6552+
profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) &&
6553+
(brcmf_has_pmkid(roam_info.req_ie, roam_info.req_ie_len) ||
6554+
profile->is_ft || profile->is_okc))) {
6555+
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0,
6556+
GFP_KERNEL);
63996557
brcmf_dbg(CONN, "Report port authorized\n");
64006558
}
64016559

6560+
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
64026561
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
64036562
brcmf_dbg(TRACE, "Exit\n");
64046563
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)