Skip to content

Commit d6e6827

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 6d2ed99 commit d6e6827

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

@@ -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+
128137
static 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
*/
243252
static 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+
20132070
static s32
20142071
brcmf_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

29003024
done:
29013025
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
@@ -44,6 +44,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
4444
{ BRCMF_FEAT_DOT11H, "802.11h" },
4545
{ BRCMF_FEAT_SAE, "sae" },
4646
{ BRCMF_FEAT_FWAUTH, "idauth" },
47+
{ BRCMF_FEAT_GCMP, "gcmp"}
4748
};
4849

4950
#ifdef DEBUG

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
* FWAUTH: Firmware authenticator
3232
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
3333
* SCAN_V2: Version 2 scan params
34+
* SCAN_v3: Version 3 scan params
35+
* PMKID_V2: Version 2 PMKID
36+
* PMKID_V3: Version 3 PMKID
37+
* JOIN_V1: Version 1 join struct
38+
* GCMP: GCMP Cipher suite support
3439
*/
3540
#define BRCMF_FEAT_LIST \
3641
BRCMF_FEAT_DEF(MBSS) \
@@ -60,6 +65,7 @@
6065
BRCMF_FEAT_DEF(PMKID_V2) \
6166
BRCMF_FEAT_DEF(PMKID_V3) \
6267
BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \
68+
BRCMF_FEAT_DEF(GCMP)
6369

6470
/*
6571
* 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)