3232#include "vendor.h"
3333#include "bus.h"
3434#include "common.h"
35+ #include "feature.h"
3536#include "fwvid.h"
37+ #include "xtlv.h"
3638
3739#define BRCMF_SCAN_IE_LEN_MAX 2048
3840
@@ -125,6 +127,13 @@ struct cca_msrmnt_query {
125127 u32 time_req ;
126128};
127129
130+ /* algo bit vector */
131+ #define KEY_ALGO_MASK (_algo ) (1 << (_algo))
132+
133+ /* start enum value for BSS properties */
134+ #define WL_WSEC_INFO_BSS_BASE 0x0100
135+ #define WL_WSEC_INFO_BSS_ALGOS (WL_WSEC_INFO_BSS_BASE + 6)
136+
128137static bool check_vif_up (struct brcmf_cfg80211_vif * vif )
129138{
130139 if (!test_bit (BRCMF_VIF_STATUS_READY , & vif -> sme_state )) {
@@ -237,16 +246,22 @@ static const struct ieee80211_regdomain brcmf_regdom = {
237246/* Note: brcmf_cipher_suites is an array of int defining which cipher suites
238247 * are supported. A pointer to this array and the number of entries is passed
239248 * on to upper layers. AES_CMAC defines whether or not the driver supports MFP.
240- * So the cipher suite AES_CMAC has to be the last one in the array, and when
241- * device does not support MFP then the number of suites will be decreased by 1
249+ * MFP support includes a few other suites, so if MFP is not supported,
250+ * then the number of suites will be decreased by 4
242251 */
243252static const u32 brcmf_cipher_suites [] = {
244253 WLAN_CIPHER_SUITE_WEP40 ,
245254 WLAN_CIPHER_SUITE_WEP104 ,
246255 WLAN_CIPHER_SUITE_TKIP ,
247256 WLAN_CIPHER_SUITE_CCMP ,
248- /* Keep as last entry: */
249- WLAN_CIPHER_SUITE_AES_CMAC
257+ WLAN_CIPHER_SUITE_CCMP_256 ,
258+ WLAN_CIPHER_SUITE_GCMP ,
259+ WLAN_CIPHER_SUITE_GCMP_256 ,
260+ /* Keep as last 4 entries: */
261+ WLAN_CIPHER_SUITE_AES_CMAC ,
262+ WLAN_CIPHER_SUITE_BIP_CMAC_256 ,
263+ WLAN_CIPHER_SUITE_BIP_GMAC_128 ,
264+ WLAN_CIPHER_SUITE_BIP_GMAC_256
250265};
251266
252267/* Vendor specific ie. id = 221, oui and type defines exact ie */
@@ -2010,6 +2025,48 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
20102025 return err ;
20112026}
20122027
2028+ static s32 brcmf_set_wsec_info_algos (struct brcmf_if * ifp , u32 algos , u32 mask )
2029+ {
2030+ struct brcmf_pub * drvr = ifp -> drvr ;
2031+ s32 err = 0 ;
2032+ struct brcmf_wsec_info * wsec_info ;
2033+ struct brcmf_xtlv * wsec_info_tlv ;
2034+ u16 tlv_data_len ;
2035+ u8 tlv_data [8 ];
2036+ u32 param_len ;
2037+ u8 * buf ;
2038+
2039+ brcmf_dbg (TRACE , "Enter\n" );
2040+
2041+ buf = kzalloc (sizeof (struct brcmf_wsec_info ) + sizeof (tlv_data ),
2042+ GFP_KERNEL );
2043+ if (!buf ) {
2044+ bphy_err (drvr , "unable to allocate.\n" );
2045+ return - ENOMEM ;
2046+ }
2047+ wsec_info = (struct brcmf_wsec_info * )buf ;
2048+ wsec_info -> version = BRCMF_WSEC_INFO_VER ;
2049+ wsec_info_tlv =
2050+ (struct brcmf_xtlv * )(buf +
2051+ offsetof(struct brcmf_wsec_info , tlvs ));
2052+ wsec_info -> num_tlvs ++ ;
2053+ tlv_data_len = sizeof (tlv_data );
2054+ memcpy (tlv_data , & algos , sizeof (algos ));
2055+ memcpy (tlv_data + sizeof (algos ), & mask , sizeof (mask ));
2056+ brcmf_xtlv_pack_header (wsec_info_tlv , WL_WSEC_INFO_BSS_ALGOS ,
2057+ tlv_data_len , tlv_data , 0 );
2058+
2059+ param_len = offsetof(struct brcmf_wsec_info , tlvs ) +
2060+ offsetof(struct brcmf_wsec_info_tlv , data ) + tlv_data_len ;
2061+
2062+ err = brcmf_fil_bsscfg_data_set (ifp , "wsec_info" , buf , param_len );
2063+ if (err )
2064+ brcmf_err ("set wsec_info_error:%d\n" , err );
2065+
2066+ kfree (buf );
2067+ return err ;
2068+ }
2069+
20132070static s32
20142071brcmf_set_wsec_mode (struct net_device * ndev ,
20152072 struct cfg80211_connect_params * sme )
@@ -2022,6 +2079,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20222079 s32 gval = 0 ;
20232080 s32 wsec ;
20242081 s32 err = 0 ;
2082+ u32 algos = 0 ;
2083+ u32 mask = 0 ;
20252084
20262085 if (sme -> crypto .n_ciphers_pairwise ) {
20272086 switch (sme -> crypto .ciphers_pairwise [0 ]) {
@@ -2038,6 +2097,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20382097 case WLAN_CIPHER_SUITE_AES_CMAC :
20392098 pval = AES_ENABLED ;
20402099 break ;
2100+ case WLAN_CIPHER_SUITE_GCMP_256 :
2101+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2102+ brcmf_err ("This chip does not support GCMP\n" );
2103+ return - EOPNOTSUPP ;
2104+ }
2105+ pval = AES_ENABLED ;
2106+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2107+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2108+ break ;
20412109 default :
20422110 bphy_err (drvr , "invalid cipher pairwise (%d)\n" ,
20432111 sme -> crypto .ciphers_pairwise [0 ]);
@@ -2059,6 +2127,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20592127 case WLAN_CIPHER_SUITE_AES_CMAC :
20602128 gval = AES_ENABLED ;
20612129 break ;
2130+ case WLAN_CIPHER_SUITE_GCMP_256 :
2131+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2132+ brcmf_err ("This chip does not support GCMP\n" );
2133+ return - EOPNOTSUPP ;
2134+ }
2135+ gval = AES_ENABLED ;
2136+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2137+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2138+ break ;
20622139 default :
20632140 bphy_err (drvr , "invalid cipher group (%d)\n" ,
20642141 sme -> crypto .cipher_group );
@@ -2067,6 +2144,7 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20672144 }
20682145
20692146 brcmf_dbg (CONN , "pval (%d) gval (%d)\n" , pval , gval );
2147+ brcmf_dbg (CONN , "algos (0x%x) mask (0x%x)\n" , algos , mask );
20702148 /* In case of privacy, but no security and WPS then simulate */
20712149 /* setting AES. WPS-2.0 allows no security */
20722150 if (brcmf_find_wpsie (sme -> ie , sme -> ie_len ) && !pval && !gval &&
@@ -2079,6 +2157,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20792157 bphy_err (drvr , "error (%d)\n" , err );
20802158 return err ;
20812159 }
2160+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2161+ brcmf_dbg (CONN , "set_wsec_info algos (0x%x) mask (0x%x)\n" ,
2162+ algos , mask );
2163+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
2164+ if (err ) {
2165+ brcmf_err ("set wsec_info error (%d)\n" , err );
2166+ return err ;
2167+ }
2168+ }
20822169
20832170 sec = & profile -> sec ;
20842171 sec -> cipher_pairwise = sme -> crypto .ciphers_pairwise [0 ];
@@ -2792,6 +2879,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
27922879 s32 val ;
27932880 s32 wsec ;
27942881 s32 err ;
2882+ u32 algos = 0 ;
2883+ u32 mask = 0 ;
27952884 u8 keybuf [8 ];
27962885 bool ext_key ;
27972886
@@ -2875,6 +2964,30 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28752964 val = AES_ENABLED ;
28762965 brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_CCMP\n" );
28772966 break ;
2967+ case WLAN_CIPHER_SUITE_GCMP_256 :
2968+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2969+ brcmf_err ("the low layer not support GCMP\n" );
2970+ err = - EOPNOTSUPP ;
2971+ goto done ;
2972+ }
2973+ key -> algo = CRYPTO_ALGO_AES_GCM256 ;
2974+ val = AES_ENABLED ;
2975+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_GCMP_256\n" );
2976+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2977+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2978+ break ;
2979+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
2980+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2981+ brcmf_err ("the low layer not support GCMP\n" );
2982+ err = - EOPNOTSUPP ;
2983+ goto done ;
2984+ }
2985+ key -> algo = CRYPTO_ALGO_BIP_GMAC256 ;
2986+ val = AES_ENABLED ;
2987+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_BIP_GMAC256 );
2988+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2989+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_BIP_GMAC_256\n" );
2990+ break ;
28782991 default :
28792992 bphy_err (drvr , "Invalid cipher (0x%x)\n" , params -> cipher );
28802993 err = - EINVAL ;
@@ -2896,6 +3009,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28963009 bphy_err (drvr , "set wsec error (%d)\n" , err );
28973010 goto done ;
28983011 }
3012+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
3013+ brcmf_dbg (CONN ,
3014+ "set_wsdec_info algos (0x%x) mask (0x%x)\n" ,
3015+ algos , mask );
3016+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
3017+ if (err ) {
3018+ brcmf_err ("set wsec_info error (%d)\n" , err );
3019+ return err ;
3020+ }
3021+ }
3022+
28993023
29003024done :
29013025 brcmf_dbg (TRACE , "Exit\n" );
0 commit comments