Skip to content

Commit a349ce5

Browse files
committed
[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 <[email protected]>
1 parent 9a9d12e commit a349ce5

4 files changed

Lines changed: 196 additions & 28 deletions

File tree

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

Lines changed: 185 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
#define RSN_CAP_MFPR_MASK BIT(6)
6666
#define RSN_CAP_MFPC_MASK BIT(7)
6767
#define RSN_PMKID_COUNT_LEN 2
68+
#define DPP_AKM_SUITE_TYPE 2
69+
#define WLAN_AKM_SUITE_DPP SUITE(WLAN_OUI_WFA, DPP_AKM_SUITE_TYPE)
6870

6971
#define VNDR_IE_CMD_LEN 4 /* length of the set command
7072
* string :"add", "del" (+ NUL)
@@ -1841,15 +1843,20 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev,
18411843
struct brcmf_cfg80211_security *sec;
18421844
s32 val = 0;
18431845
s32 err = 0;
1844-
1845-
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1846+
if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) {
18461847
val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1847-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1848-
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1849-
else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
1848+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) {
1849+
if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
1850+
val = WPA3_AUTH_SAE_PSK;
1851+
else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_OWE)
1852+
val = WPA3_AUTH_OWE;
1853+
else
1854+
val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1855+
} else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3) {
18501856
val = WPA3_AUTH_SAE_PSK;
1851-
else
1857+
} else {
18521858
val = WPA_AUTH_DISABLED;
1859+
}
18531860
brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val);
18541861
err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", val);
18551862
if (err) {
@@ -2064,9 +2071,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
20642071
u16 rsn_cap;
20652072
u32 mfp;
20662073
u16 count;
2074+
s32 okc_enable;
2075+
u16 pmkid_count;
2076+
const u8 *group_mgmt_cs = NULL;
20672077

20682078
profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
20692079
profile->is_ft = false;
2080+
profile->is_okc = false;
20702081

20712082
if (!sme->crypto.n_akm_suites)
20722083
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) {
@@ -2141,16 +2179,35 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
21412179
profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
21422180
}
21432181
break;
2144-
default:
2145-
bphy_err(drvr, "invalid akm suite (%d)\n",
2146-
sme->crypto.akm_suites[0]);
2182+
default:
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,
@@ -2454,7 +2556,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
24542556
goto done;
24552557
}
24562558
err = brcmf_set_sae_password(ifp, params->crypto.sae_pwd,
2457-
params->crypto.sae_pwd_len);
2559+
params->crypto.sae_pwd_len);
24582560
if (!err && params->crypto.psk)
24592561
err = brcmf_set_pmk(ifp, params->crypto.psk,
24602562
BRCMF_WSEC_MAX_PSK_LEN);
@@ -5870,17 +5972,29 @@ static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
58705972
const struct cfg80211_pmk_conf *conf)
58715973
{
58725974
struct brcmf_if *ifp;
5873-
5975+
struct brcmf_pub *drvr;
5976+
int ret;
58745977
brcmf_dbg(TRACE, "enter\n");
58755978

58765979
/* expect using firmware supplicant for 1X */
58775980
ifp = netdev_priv(dev);
5878-
if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
5981+
drvr = ifp->drvr;
5982+
if (WARN_ON((ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X) &&
5983+
(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_ROAM) &&
5984+
(ifp->vif->profile.is_ft != true) &&
5985+
(ifp->vif->profile.is_okc != true)))
58795986
return -EINVAL;
58805987

58815988
if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
58825989
return -ERANGE;
58835990

5991+
if (ifp->vif->profile.is_okc) {
5992+
ret = brcmf_fil_iovar_data_set(ifp, "okc_info_pmk", conf->pmk,
5993+
conf->pmk_len);
5994+
if (ret < 0)
5995+
bphy_err(drvr, "okc_info_pmk iovar failed: ret=%d\n",
5996+
ret);
5997+
}
58845998
return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
58855999
}
58866000

@@ -6317,6 +6431,46 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
63176431
return err;
63186432
}
63196433

6434+
static bool brcmf_has_pmkid(const u8 *parse, u32 len)
6435+
{
6436+
const struct brcmf_tlv *rsn_ie;
6437+
const u8 *ie;
6438+
u32 ie_len;
6439+
u32 offset;
6440+
u16 count;
6441+
6442+
rsn_ie = brcmf_parse_tlvs(parse, len, WLAN_EID_RSN);
6443+
if (!rsn_ie)
6444+
goto done;
6445+
ie = (const u8 *)rsn_ie;
6446+
ie_len = rsn_ie->len + TLV_HDR_LEN;
6447+
/* Skip group data cipher suite */
6448+
offset = TLV_HDR_LEN + WPA_IE_VERSION_LEN + WPA_IE_MIN_OUI_LEN;
6449+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6450+
goto done;
6451+
/* Skip pairwise cipher suite(s) */
6452+
count = ie[offset] + (ie[offset + 1] << 8);
6453+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6454+
if (offset + WPA_IE_SUITE_COUNT_LEN >= ie_len)
6455+
goto done;
6456+
/* Skip auth key management suite(s) */
6457+
count = ie[offset] + (ie[offset + 1] << 8);
6458+
offset += WPA_IE_SUITE_COUNT_LEN + (count * WPA_IE_MIN_OUI_LEN);
6459+
if (offset + RSN_CAP_LEN >= ie_len)
6460+
goto done;
6461+
/* Skip rsn capabilities */
6462+
offset += RSN_CAP_LEN;
6463+
if (offset + RSN_PMKID_COUNT_LEN > ie_len)
6464+
goto done;
6465+
/* Extract PMKID count */
6466+
count = ie[offset] + (ie[offset + 1] << 8);
6467+
if (count)
6468+
return true;
6469+
6470+
done:
6471+
return false;
6472+
}
6473+
63206474
static s32
63216475
brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63226476
struct net_device *ndev,
@@ -6387,11 +6541,16 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
63876541
cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
63886542
brcmf_dbg(CONN, "Report roaming result\n");
63896543

6390-
if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X && profile->is_ft) {
6391-
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0, GFP_KERNEL);
6544+
if (((profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X ||
6545+
profile->use_fwsup == BRCMF_PROFILE_FWSUP_ROAM) &&
6546+
(brcmf_has_pmkid(roam_info.req_ie, roam_info.req_ie_len) ||
6547+
profile->is_ft || profile->is_okc))) {
6548+
cfg80211_port_authorized(ndev, profile->bssid, NULL, 0,
6549+
GFP_KERNEL);
63926550
brcmf_dbg(CONN, "Report port authorized\n");
63936551
}
63946552

6553+
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
63956554
set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
63966555
brcmf_dbg(TRACE, "Exit\n");
63976556
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
@@ -58,7 +58,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
5858
{ BRCMF_FEAT_DOT11H, "802.11h" },
5959
{ BRCMF_FEAT_SAE, "sae" },
6060
{ BRCMF_FEAT_FWAUTH, "idauth" },
61-
{ BRCMF_FEAT_GCMP, "gcmp"}
61+
{ BRCMF_FEAT_GCMP, "gcmp" }
6262
};
6363

6464
#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)