Skip to content

Commit fa8c9b3

Browse files
dberlinjannau
authored andcommitted
[brcmfmac] Support GCMP cipher suite, used by WPA3.
This patch adds support for using GCMP/etc during offload where supported by the firmware. Signed-off-by: Daniel Berlin <dberlin@dberlin.org>
1 parent 3687c18 commit fa8c9b3

5 files changed

Lines changed: 160 additions & 4 deletions

File tree

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c

Lines changed: 128 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
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+
127136
static 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
*/
242251
static 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+
20372094
static s32
20382095
brcmf_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

29233047
done:
29243048
brcmf_dbg(TRACE, "Exit\n");

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
4545
{ BRCMF_FEAT_SAE, "sae " },
4646
{ BRCMF_FEAT_FWAUTH, "idauth" },
4747
{ BRCMF_FEAT_SAE_EXT, "sae_ext" },
48+
{ BRCMF_FEAT_GCMP, "gcmp"}
4849
};
4950

5051
#ifdef DEBUG

drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
3333
* SCAN_V2: Version 2 scan params
3434
* SAE_EXT: SAE authentication handled by user-space supplicant
35+
* SCAN_v3: Version 3 scan params
36+
* PMKID_V2: Version 2 PMKID
37+
* PMKID_V3: Version 3 PMKID
38+
* JOIN_V1: Version 1 join struct
39+
* GCMP: GCMP Cipher suite support
3540
*/
3641
#define BRCMF_FEAT_LIST \
3742
BRCMF_FEAT_DEF(MBSS) \
@@ -62,6 +67,7 @@
6267
BRCMF_FEAT_DEF(PMKID_V3) \
6368
BRCMF_FEAT_DEF(SAE_EXT) \
6469
BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \
70+
BRCMF_FEAT_DEF(GCMP)
6571

6672
/*
6773
* Quirks:

drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,4 +1309,22 @@ struct brcmf_eventmsgs_ext_le {
13091309
u8 mask[];
13101310
};
13111311

1312+
/* version of the brcmf_wl_wsec_info structure */
1313+
#define BRCMF_WSEC_INFO_VER 1
1314+
1315+
/* tlv used to return wl_wsec_info properties */
1316+
struct brcmf_wsec_info_tlv {
1317+
u16 type;
1318+
u16 len; /* data length */
1319+
u8 data[1]; /* data follows */
1320+
};
1321+
1322+
/* input/output data type for wsec_info iovar */
1323+
struct brcmf_wsec_info {
1324+
u8 version; /* structure version */
1325+
u8 pad[2];
1326+
u8 num_tlvs;
1327+
struct brcmf_wsec_info_tlv tlvs[1]; /* tlv data follows */
1328+
};
1329+
13121330
#endif /* FWIL_TYPES_H_ */

drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,13 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
215215
#define CRYPTO_ALGO_AES_RESERVED1 5
216216
#define CRYPTO_ALGO_AES_RESERVED2 6
217217
#define CRYPTO_ALGO_NALG 7
218+
#define CRYPTO_ALGO_AES_GCM 14 /* 128 bit GCM */
219+
#define CRYPTO_ALGO_AES_CCM256 15 /* 256 bit CCM */
220+
#define CRYPTO_ALGO_AES_GCM256 16 /* 256 bit GCM */
221+
#define CRYPTO_ALGO_BIP_CMAC256 17 /* 256 bit BIP CMAC */
222+
#define CRYPTO_ALGO_BIP_GMAC 18 /* 128 bit BIP GMAC */
223+
#define CRYPTO_ALGO_BIP_GMAC256 19 /* 256 bit BIP GMAC */
224+
218225

219226
/* wireless security bitvec */
220227

0 commit comments

Comments
 (0)