3232#include "vendor.h"
3333#include "bus.h"
3434#include "common.h"
35+ #include "feature.h"
36+ #include "xtlv.h"
3537
3638#define BRCMF_SCAN_IE_LEN_MAX 2048
3739
@@ -124,6 +126,13 @@ struct cca_msrmnt_query {
124126 u32 time_req ;
125127};
126128
129+ /* algo bit vector */
130+ #define KEY_ALGO_MASK (_algo ) (1 << (_algo))
131+
132+ /* start enum value for BSS properties */
133+ #define WL_WSEC_INFO_BSS_BASE 0x0100
134+ #define WL_WSEC_INFO_BSS_ALGOS (WL_WSEC_INFO_BSS_BASE + 6)
135+
127136static bool check_vif_up (struct brcmf_cfg80211_vif * vif )
128137{
129138 if (!test_bit (BRCMF_VIF_STATUS_READY , & vif -> sme_state )) {
@@ -236,16 +245,22 @@ static const struct ieee80211_regdomain brcmf_regdom = {
236245/* Note: brcmf_cipher_suites is an array of int defining which cipher suites
237246 * are supported. A pointer to this array and the number of entries is passed
238247 * on to upper layers. AES_CMAC defines whether or not the driver supports MFP.
239- * So the cipher suite AES_CMAC has to be the last one in the array, and when
240- * device does not support MFP then the number of suites will be decreased by 1
248+ * MFP support includes a few other suites, so if MFP is not supported,
249+ * then the number of suites will be decreased by 4
241250 */
242251static const u32 brcmf_cipher_suites [] = {
243252 WLAN_CIPHER_SUITE_WEP40 ,
244253 WLAN_CIPHER_SUITE_WEP104 ,
245254 WLAN_CIPHER_SUITE_TKIP ,
246255 WLAN_CIPHER_SUITE_CCMP ,
247- /* Keep as last entry: */
248- WLAN_CIPHER_SUITE_AES_CMAC
256+ WLAN_CIPHER_SUITE_CCMP_256 ,
257+ WLAN_CIPHER_SUITE_GCMP ,
258+ WLAN_CIPHER_SUITE_GCMP_256 ,
259+ /* Keep as last 4 entries: */
260+ WLAN_CIPHER_SUITE_AES_CMAC ,
261+ WLAN_CIPHER_SUITE_BIP_CMAC_256 ,
262+ WLAN_CIPHER_SUITE_BIP_GMAC_128 ,
263+ WLAN_CIPHER_SUITE_BIP_GMAC_256
249264};
250265
251266/* Vendor specific ie. id = 221, oui and type defines exact ie */
@@ -2015,6 +2030,48 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
20152030 return err ;
20162031}
20172032
2033+ static s32 brcmf_set_wsec_info_algos (struct brcmf_if * ifp , u32 algos , u32 mask )
2034+ {
2035+ struct brcmf_pub * drvr = ifp -> drvr ;
2036+ s32 err = 0 ;
2037+ struct brcmf_wsec_info * wsec_info ;
2038+ struct brcmf_xtlv * wsec_info_tlv ;
2039+ u16 tlv_data_len ;
2040+ u8 tlv_data [8 ];
2041+ u32 param_len ;
2042+ u8 * buf ;
2043+
2044+ brcmf_dbg (TRACE , "Enter\n" );
2045+
2046+ buf = kzalloc (sizeof (struct brcmf_wsec_info ) + sizeof (tlv_data ),
2047+ GFP_KERNEL );
2048+ if (!buf ) {
2049+ bphy_err (drvr , "unable to allocate.\n" );
2050+ return - ENOMEM ;
2051+ }
2052+ wsec_info = (struct brcmf_wsec_info * )buf ;
2053+ wsec_info -> version = BRCMF_WSEC_INFO_VER ;
2054+ wsec_info_tlv =
2055+ (struct brcmf_xtlv * )(buf +
2056+ offsetof(struct brcmf_wsec_info , tlvs ));
2057+ wsec_info -> num_tlvs ++ ;
2058+ tlv_data_len = sizeof (tlv_data );
2059+ memcpy (tlv_data , & algos , sizeof (algos ));
2060+ memcpy (tlv_data + sizeof (algos ), & mask , sizeof (mask ));
2061+ brcmf_xtlv_pack_header (wsec_info_tlv , WL_WSEC_INFO_BSS_ALGOS ,
2062+ tlv_data_len , tlv_data , 0 );
2063+
2064+ param_len = offsetof(struct brcmf_wsec_info , tlvs ) +
2065+ offsetof(struct brcmf_wsec_info_tlv , data ) + tlv_data_len ;
2066+
2067+ err = brcmf_fil_bsscfg_data_set (ifp , "wsec_info" , buf , param_len );
2068+ if (err )
2069+ brcmf_err ("set wsec_info_error:%d\n" , err );
2070+
2071+ kfree (buf );
2072+ return err ;
2073+ }
2074+
20182075static s32
20192076brcmf_set_wsec_mode (struct net_device * ndev ,
20202077 struct cfg80211_connect_params * sme )
@@ -2027,6 +2084,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20272084 s32 gval = 0 ;
20282085 s32 wsec ;
20292086 s32 err = 0 ;
2087+ u32 algos = 0 ;
2088+ u32 mask = 0 ;
20302089
20312090 if (sme -> crypto .n_ciphers_pairwise ) {
20322091 switch (sme -> crypto .ciphers_pairwise [0 ]) {
@@ -2043,6 +2102,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20432102 case WLAN_CIPHER_SUITE_AES_CMAC :
20442103 pval = AES_ENABLED ;
20452104 break ;
2105+ case WLAN_CIPHER_SUITE_GCMP_256 :
2106+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2107+ brcmf_err ("This chip does not support GCMP\n" );
2108+ return - EOPNOTSUPP ;
2109+ }
2110+ pval = AES_ENABLED ;
2111+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2112+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2113+ break ;
20462114 default :
20472115 bphy_err (drvr , "invalid cipher pairwise (%d)\n" ,
20482116 sme -> crypto .ciphers_pairwise [0 ]);
@@ -2064,6 +2132,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20642132 case WLAN_CIPHER_SUITE_AES_CMAC :
20652133 gval = AES_ENABLED ;
20662134 break ;
2135+ case WLAN_CIPHER_SUITE_GCMP_256 :
2136+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2137+ brcmf_err ("This chip does not support GCMP\n" );
2138+ return - EOPNOTSUPP ;
2139+ }
2140+ gval = AES_ENABLED ;
2141+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2142+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2143+ break ;
20672144 default :
20682145 bphy_err (drvr , "invalid cipher group (%d)\n" ,
20692146 sme -> crypto .cipher_group );
@@ -2072,6 +2149,7 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20722149 }
20732150
20742151 brcmf_dbg (CONN , "pval (%d) gval (%d)\n" , pval , gval );
2152+ brcmf_dbg (CONN , "algos (0x%x) mask (0x%x)\n" , algos , mask );
20752153 /* In case of privacy, but no security and WPS then simulate */
20762154 /* setting AES. WPS-2.0 allows no security */
20772155 if (brcmf_find_wpsie (sme -> ie , sme -> ie_len ) && !pval && !gval &&
@@ -2084,6 +2162,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20842162 bphy_err (drvr , "error (%d)\n" , err );
20852163 return err ;
20862164 }
2165+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2166+ brcmf_dbg (CONN , "set_wsec_info algos (0x%x) mask (0x%x)\n" ,
2167+ algos , mask );
2168+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
2169+ if (err ) {
2170+ brcmf_err ("set wsec_info error (%d)\n" , err );
2171+ return err ;
2172+ }
2173+ }
20872174
20882175 sec = & profile -> sec ;
20892176 sec -> cipher_pairwise = sme -> crypto .ciphers_pairwise [0 ];
@@ -2798,6 +2885,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
27982885 s32 val ;
27992886 s32 wsec ;
28002887 s32 err ;
2888+ u32 algos = 0 ;
2889+ u32 mask = 0 ;
28012890 u8 keybuf [8 ];
28022891 bool ext_key ;
28032892
@@ -2881,6 +2970,30 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28812970 val = AES_ENABLED ;
28822971 brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_CCMP\n" );
28832972 break ;
2973+ case WLAN_CIPHER_SUITE_GCMP_256 :
2974+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2975+ brcmf_err ("the low layer not support GCMP\n" );
2976+ err = - EOPNOTSUPP ;
2977+ goto done ;
2978+ }
2979+ key -> algo = CRYPTO_ALGO_AES_GCM256 ;
2980+ val = AES_ENABLED ;
2981+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_GCMP_256\n" );
2982+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2983+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2984+ break ;
2985+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
2986+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2987+ brcmf_err ("the low layer not support GCMP\n" );
2988+ err = - EOPNOTSUPP ;
2989+ goto done ;
2990+ }
2991+ key -> algo = CRYPTO_ALGO_BIP_GMAC256 ;
2992+ val = AES_ENABLED ;
2993+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_BIP_GMAC256 );
2994+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2995+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_BIP_GMAC_256\n" );
2996+ break ;
28842997 default :
28852998 bphy_err (drvr , "Invalid cipher (0x%x)\n" , params -> cipher );
28862999 err = - EINVAL ;
@@ -2902,6 +3015,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
29023015 bphy_err (drvr , "set wsec error (%d)\n" , err );
29033016 goto done ;
29043017 }
3018+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
3019+ brcmf_dbg (CONN ,
3020+ "set_wsdec_info algos (0x%x) mask (0x%x)\n" ,
3021+ algos , mask );
3022+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
3023+ if (err ) {
3024+ brcmf_err ("set wsec_info error (%d)\n" , err );
3025+ return err ;
3026+ }
3027+ }
3028+
29053029
29063030done :
29073031 brcmf_dbg (TRACE , "Exit\n" );
0 commit comments