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
21892277skip_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+
63396494static s32
63406495brcmf_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 ;
0 commit comments