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
@@ -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 */
@@ -2034,6 +2049,48 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
20342049 return err ;
20352050}
20362051
2052+ static s32 brcmf_set_wsec_info_algos (struct brcmf_if * ifp , u32 algos , u32 mask )
2053+ {
2054+ struct brcmf_pub * drvr = ifp -> drvr ;
2055+ s32 err = 0 ;
2056+ struct brcmf_wsec_info * wsec_info ;
2057+ struct brcmf_xtlv * wsec_info_tlv ;
2058+ u16 tlv_data_len ;
2059+ u8 tlv_data [8 ];
2060+ u32 param_len ;
2061+ u8 * buf ;
2062+
2063+ brcmf_dbg (TRACE , "Enter\n" );
2064+
2065+ buf = kzalloc (sizeof (struct brcmf_wsec_info ) + sizeof (tlv_data ),
2066+ GFP_KERNEL );
2067+ if (!buf ) {
2068+ bphy_err (drvr , "unable to allocate.\n" );
2069+ return - ENOMEM ;
2070+ }
2071+ wsec_info = (struct brcmf_wsec_info * )buf ;
2072+ wsec_info -> version = BRCMF_WSEC_INFO_VER ;
2073+ wsec_info_tlv =
2074+ (struct brcmf_xtlv * )(buf +
2075+ offsetof(struct brcmf_wsec_info , tlvs ));
2076+ wsec_info -> num_tlvs ++ ;
2077+ tlv_data_len = sizeof (tlv_data );
2078+ memcpy (tlv_data , & algos , sizeof (algos ));
2079+ memcpy (tlv_data + sizeof (algos ), & mask , sizeof (mask ));
2080+ brcmf_xtlv_pack_header (wsec_info_tlv , WL_WSEC_INFO_BSS_ALGOS ,
2081+ tlv_data_len , tlv_data , 0 );
2082+
2083+ param_len = offsetof(struct brcmf_wsec_info , tlvs ) +
2084+ offsetof(struct brcmf_wsec_info_tlv , data ) + tlv_data_len ;
2085+
2086+ err = brcmf_fil_bsscfg_data_set (ifp , "wsec_info" , buf , param_len );
2087+ if (err )
2088+ brcmf_err ("set wsec_info_error:%d\n" , err );
2089+
2090+ kfree (buf );
2091+ return err ;
2092+ }
2093+
20372094static s32
20382095brcmf_set_wsec_mode (struct net_device * ndev ,
20392096 struct cfg80211_connect_params * sme )
@@ -2046,6 +2103,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20462103 s32 gval = 0 ;
20472104 s32 wsec ;
20482105 s32 err = 0 ;
2106+ u32 algos = 0 ;
2107+ u32 mask = 0 ;
20492108
20502109 if (sme -> crypto .n_ciphers_pairwise ) {
20512110 switch (sme -> crypto .ciphers_pairwise [0 ]) {
@@ -2062,6 +2121,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20622121 case WLAN_CIPHER_SUITE_AES_CMAC :
20632122 pval = AES_ENABLED ;
20642123 break ;
2124+ case WLAN_CIPHER_SUITE_GCMP_256 :
2125+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2126+ brcmf_err ("This chip does not support GCMP\n" );
2127+ return - EOPNOTSUPP ;
2128+ }
2129+ pval = AES_ENABLED ;
2130+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2131+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2132+ break ;
20652133 default :
20662134 bphy_err (drvr , "invalid cipher pairwise (%d)\n" ,
20672135 sme -> crypto .ciphers_pairwise [0 ]);
@@ -2083,6 +2151,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20832151 case WLAN_CIPHER_SUITE_AES_CMAC :
20842152 gval = AES_ENABLED ;
20852153 break ;
2154+ case WLAN_CIPHER_SUITE_GCMP_256 :
2155+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2156+ brcmf_err ("This chip does not support GCMP\n" );
2157+ return - EOPNOTSUPP ;
2158+ }
2159+ gval = AES_ENABLED ;
2160+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
2161+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
2162+ break ;
20862163 default :
20872164 bphy_err (drvr , "invalid cipher group (%d)\n" ,
20882165 sme -> crypto .cipher_group );
@@ -2091,6 +2168,7 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20912168 }
20922169
20932170 brcmf_dbg (CONN , "pval (%d) gval (%d)\n" , pval , gval );
2171+ brcmf_dbg (CONN , "algos (0x%x) mask (0x%x)\n" , algos , mask );
20942172 /* In case of privacy, but no security and WPS then simulate */
20952173 /* setting AES. WPS-2.0 allows no security */
20962174 if (brcmf_find_wpsie (sme -> ie , sme -> ie_len ) && !pval && !gval &&
@@ -2103,6 +2181,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
21032181 bphy_err (drvr , "error (%d)\n" , err );
21042182 return err ;
21052183 }
2184+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2185+ brcmf_dbg (CONN , "set_wsec_info algos (0x%x) mask (0x%x)\n" ,
2186+ algos , mask );
2187+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
2188+ if (err ) {
2189+ brcmf_err ("set wsec_info error (%d)\n" , err );
2190+ return err ;
2191+ }
2192+ }
21062193
21072194 sec = & profile -> sec ;
21082195 sec -> cipher_pairwise = sme -> crypto .ciphers_pairwise [0 ];
@@ -2815,6 +2902,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28152902 s32 val ;
28162903 s32 wsec ;
28172904 s32 err ;
2905+ u32 algos = 0 ;
2906+ u32 mask = 0 ;
28182907 u8 keybuf [8 ];
28192908 bool ext_key ;
28202909
@@ -2898,6 +2987,30 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28982987 val = AES_ENABLED ;
28992988 brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_CCMP\n" );
29002989 break ;
2990+ case WLAN_CIPHER_SUITE_GCMP_256 :
2991+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
2992+ brcmf_err ("the low layer not support GCMP\n" );
2993+ err = - EOPNOTSUPP ;
2994+ goto done ;
2995+ }
2996+ key -> algo = CRYPTO_ALGO_AES_GCM256 ;
2997+ val = AES_ENABLED ;
2998+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_GCMP_256\n" );
2999+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_AES_GCM256 );
3000+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
3001+ break ;
3002+ case WLAN_CIPHER_SUITE_BIP_GMAC_256 :
3003+ if (!brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
3004+ brcmf_err ("the low layer not support GCMP\n" );
3005+ err = - EOPNOTSUPP ;
3006+ goto done ;
3007+ }
3008+ key -> algo = CRYPTO_ALGO_BIP_GMAC256 ;
3009+ val = AES_ENABLED ;
3010+ algos = KEY_ALGO_MASK (CRYPTO_ALGO_BIP_GMAC256 );
3011+ mask = algos | KEY_ALGO_MASK (CRYPTO_ALGO_AES_CCM );
3012+ brcmf_dbg (CONN , "WLAN_CIPHER_SUITE_BIP_GMAC_256\n" );
3013+ break ;
29013014 default :
29023015 bphy_err (drvr , "Invalid cipher (0x%x)\n" , params -> cipher );
29033016 err = - EINVAL ;
@@ -2919,6 +3032,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
29193032 bphy_err (drvr , "set wsec error (%d)\n" , err );
29203033 goto done ;
29213034 }
3035+ if (brcmf_feat_is_enabled (ifp , BRCMF_FEAT_GCMP )) {
3036+ brcmf_dbg (CONN ,
3037+ "set_wsdec_info algos (0x%x) mask (0x%x)\n" ,
3038+ algos , mask );
3039+ err = brcmf_set_wsec_info_algos (ifp , algos , mask );
3040+ if (err ) {
3041+ brcmf_err ("set wsec_info error (%d)\n" , err );
3042+ return err ;
3043+ }
3044+ }
3045+
29223046
29233047done :
29243048 brcmf_dbg (TRACE , "Exit\n" );
0 commit comments