Skip to content

Commit eb29f7c

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 a358ebe commit eb29f7c

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;
@@ -2078,13 +2089,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20782089
val = WPA_AUTH_UNSPECIFIED;
20792090
if (sme->want_1x)
20802091
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2092+
else
2093+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20812094
break;
20822095
case WLAN_AKM_SUITE_PSK:
20832096
val = WPA_AUTH_PSK;
20842097
break;
20852098
default:
2086-
bphy_err(drvr, "invalid akm suite (%d)\n",
2087-
sme->crypto.akm_suites[0]);
2099+
bphy_err(drvr, "invalid cipher group (%d)\n",
2100+
sme->crypto.cipher_group);
20882101
return -EINVAL;
20892102
}
20902103
} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
@@ -2093,11 +2106,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20932106
val = WPA2_AUTH_UNSPECIFIED;
20942107
if (sme->want_1x)
20952108
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2109+
else
2110+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
20962111
break;
20972112
case WLAN_AKM_SUITE_8021X_SHA256:
20982113
val = WPA2_AUTH_1X_SHA256;
20992114
if (sme->want_1x)
21002115
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2116+
else
2117+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21012118
break;
21022119
case WLAN_AKM_SUITE_PSK_SHA256:
21032120
val = WPA2_AUTH_PSK_SHA256;
@@ -2110,14 +2127,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21102127
profile->is_ft = true;
21112128
if (sme->want_1x)
21122129
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2130+
else
2131+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21132132
break;
21142133
case WLAN_AKM_SUITE_FT_PSK:
21152134
val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
21162135
profile->is_ft = true;
2136+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP))
2137+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
2138+
else
2139+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2140+
break;
2141+
case WLAN_AKM_SUITE_DPP:
2142+
val = WFA_AUTH_DPP;
2143+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
2144+
break;
2145+
case WLAN_AKM_SUITE_OWE:
2146+
val = WPA3_AUTH_OWE;
2147+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
2148+
break;
2149+
case WLAN_AKM_SUITE_8021X_SUITE_B_192:
2150+
val = WPA3_AUTH_1X_SUITE_B_SHA384;
2151+
if (sme->want_1x)
2152+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
2153+
else
2154+
profile->use_fwsup = BRCMF_PROFILE_FWSUP_ROAM;
21172155
break;
21182156
default:
2119-
bphy_err(drvr, "invalid akm suite (%d)\n",
2120-
sme->crypto.akm_suites[0]);
2157+
bphy_err(drvr, "invalid cipher group (%d)\n",
2158+
sme->crypto.cipher_group);
21212159
return -EINVAL;
21222160
}
21232161
} else if (val & WPA3_AUTH_SAE_PSK) {
@@ -2138,15 +2176,34 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21382176
}
21392177
break;
21402178
default:
2141-
bphy_err(drvr, "invalid akm suite (%d)\n",
2142-
sme->crypto.akm_suites[0]);
2179+
bphy_err(drvr, "invalid cipher group (%d)\n",
2180+
sme->crypto.cipher_group);
21432181
return -EINVAL;
21442182
}
21452183
}
2146-
2147-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
2184+
if ((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X) ||
2185+
(profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM)) {
21482186
brcmf_dbg(INFO, "using 1X offload\n");
2149-
2187+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2188+
&okc_enable);
2189+
if (err) {
2190+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2191+
} else {
2192+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2193+
profile->is_okc = okc_enable;
2194+
}
2195+
} else if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE &&
2196+
(val == WPA3_AUTH_SAE_PSK)) {
2197+
brcmf_dbg(INFO, "not using SAE offload\n");
2198+
err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), "okc_enable",
2199+
&okc_enable);
2200+
if (err) {
2201+
bphy_err(drvr, "get okc_enable failed (%d)\n", err);
2202+
} else {
2203+
brcmf_dbg(INFO, "get okc_enable (%d)\n", okc_enable);
2204+
profile->is_okc = okc_enable;
2205+
}
2206+
}
21502207
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
21512208
goto skip_mfp_config;
21522209
/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
@@ -2179,14 +2236,47 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21792236
mfp = BRCMF_MFP_REQUIRED;
21802237
else if (rsn_cap & RSN_CAP_MFPC_MASK)
21812238
mfp = BRCMF_MFP_CAPABLE;
2239+
/* In case of dpp, very low tput is observed if MFPC is set in
2240+
* firmmare. Firmware needs to ensure that MFPC is not set when
2241+
* MFPR was requested from fmac. However since this change being
2242+
* specific to DPP, fmac needs to set wpa_auth prior to mfp, so
2243+
* that firmware can use this info to prevent MFPC being set in
2244+
* case of dpp.
2245+
*/
2246+
if (val == WFA_AUTH_DPP) {
2247+
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
2248+
err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth",
2249+
val);
2250+
if (err) {
2251+
bphy_err(drvr, "could not set wpa_auth (%d)\n", err);
2252+
return err;
2253+
}
2254+
}
2255+
21822256
brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "mfp", mfp);
2257+
offset += RSN_CAP_LEN;
2258+
if (mfp && (ie_len - offset >= RSN_PMKID_COUNT_LEN)) {
2259+
pmkid_count = ie[offset] + (ie[offset + 1] << 8);
2260+
offset += RSN_PMKID_COUNT_LEN + (pmkid_count * WLAN_PMKID_LEN);
2261+
if (ie_len - offset >= WPA_IE_MIN_OUI_LEN) {
2262+
group_mgmt_cs = &ie[offset];
2263+
if (memcmp(group_mgmt_cs, RSN_OUI, TLV_OUI_LEN) == 0) {
2264+
brcmf_fil_bsscfg_data_set(ifp, "bip",
2265+
(void *)group_mgmt_cs,
2266+
WPA_IE_MIN_OUI_LEN);
2267+
}
2268+
}
2269+
}
21832270

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

21922282
return err;
@@ -2437,6 +2527,18 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24372527
}
24382528
}
24392529

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

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

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

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

@@ -6325,6 +6439,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63256439
return err;
63266440
}
63276441

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

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

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