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
22032291skip_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+
63826537static s32
63836538brcmf_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 ;
0 commit comments