Skip to content

Commit ffc4dd8

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 a700451 commit ffc4dd8

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 */
@@ -2014,6 +2029,48 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
20142029
return err;
20152030
}
20162031

2032+
static s32 brcmf_set_wsec_info_algos(struct brcmf_if *ifp, u32 algos, u32 mask)
2033+
{
2034+
struct brcmf_pub *drvr = ifp->drvr;
2035+
s32 err = 0;
2036+
struct brcmf_wsec_info *wsec_info;
2037+
struct brcmf_xtlv *wsec_info_tlv;
2038+
u16 tlv_data_len;
2039+
u8 tlv_data[8];
2040+
u32 param_len;
2041+
u8 *buf;
2042+
2043+
brcmf_dbg(TRACE, "Enter\n");
2044+
2045+
buf = kzalloc(sizeof(struct brcmf_wsec_info) + sizeof(tlv_data),
2046+
GFP_KERNEL);
2047+
if (!buf) {
2048+
bphy_err(drvr, "unable to allocate.\n");
2049+
return -ENOMEM;
2050+
}
2051+
wsec_info = (struct brcmf_wsec_info *)buf;
2052+
wsec_info->version = BRCMF_WSEC_INFO_VER;
2053+
wsec_info_tlv =
2054+
(struct brcmf_xtlv *)(buf +
2055+
offsetof(struct brcmf_wsec_info, tlvs));
2056+
wsec_info->num_tlvs++;
2057+
tlv_data_len = sizeof(tlv_data);
2058+
memcpy(tlv_data, &algos, sizeof(algos));
2059+
memcpy(tlv_data + sizeof(algos), &mask, sizeof(mask));
2060+
brcmf_xtlv_pack_header(wsec_info_tlv, WL_WSEC_INFO_BSS_ALGOS,
2061+
tlv_data_len, tlv_data, 0);
2062+
2063+
param_len = offsetof(struct brcmf_wsec_info, tlvs) +
2064+
offsetof(struct brcmf_wsec_info_tlv, data) + tlv_data_len;
2065+
2066+
err = brcmf_fil_bsscfg_data_set(ifp, "wsec_info", buf, param_len);
2067+
if (err)
2068+
brcmf_err("set wsec_info_error:%d\n", err);
2069+
2070+
kfree(buf);
2071+
return err;
2072+
}
2073+
20172074
static s32
20182075
brcmf_set_wsec_mode(struct net_device *ndev,
20192076
struct cfg80211_connect_params *sme)
@@ -2026,6 +2083,8 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20262083
s32 gval = 0;
20272084
s32 wsec;
20282085
s32 err = 0;
2086+
u32 algos = 0;
2087+
u32 mask = 0;
20292088

20302089
if (sme->crypto.n_ciphers_pairwise) {
20312090
switch (sme->crypto.ciphers_pairwise[0]) {
@@ -2042,6 +2101,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20422101
case WLAN_CIPHER_SUITE_AES_CMAC:
20432102
pval = AES_ENABLED;
20442103
break;
2104+
case WLAN_CIPHER_SUITE_GCMP_256:
2105+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2106+
brcmf_err("This chip does not support GCMP\n");
2107+
return -EOPNOTSUPP;
2108+
}
2109+
pval = AES_ENABLED;
2110+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256);
2111+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2112+
break;
20452113
default:
20462114
bphy_err(drvr, "invalid cipher pairwise (%d)\n",
20472115
sme->crypto.ciphers_pairwise[0]);
@@ -2063,6 +2131,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20632131
case WLAN_CIPHER_SUITE_AES_CMAC:
20642132
gval = AES_ENABLED;
20652133
break;
2134+
case WLAN_CIPHER_SUITE_GCMP_256:
2135+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2136+
brcmf_err("This chip does not support GCMP\n");
2137+
return -EOPNOTSUPP;
2138+
}
2139+
gval = AES_ENABLED;
2140+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256);
2141+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2142+
break;
20662143
default:
20672144
bphy_err(drvr, "invalid cipher group (%d)\n",
20682145
sme->crypto.cipher_group);
@@ -2071,6 +2148,7 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20712148
}
20722149

20732150
brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
2151+
brcmf_dbg(CONN, "algos (0x%x) mask (0x%x)\n", algos, mask);
20742152
/* In case of privacy, but no security and WPS then simulate */
20752153
/* setting AES. WPS-2.0 allows no security */
20762154
if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&
@@ -2083,6 +2161,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20832161
bphy_err(drvr, "error (%d)\n", err);
20842162
return err;
20852163
}
2164+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2165+
brcmf_dbg(CONN, "set_wsec_info algos (0x%x) mask (0x%x)\n",
2166+
algos, mask);
2167+
err = brcmf_set_wsec_info_algos(ifp, algos, mask);
2168+
if (err) {
2169+
brcmf_err("set wsec_info error (%d)\n", err);
2170+
return err;
2171+
}
2172+
}
20862173

20872174
sec = &profile->sec;
20882175
sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
@@ -2797,6 +2884,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
27972884
s32 val;
27982885
s32 wsec;
27992886
s32 err;
2887+
u32 algos = 0;
2888+
u32 mask = 0;
28002889
u8 keybuf[8];
28012890
bool ext_key;
28022891

@@ -2880,6 +2969,30 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
28802969
val = AES_ENABLED;
28812970
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
28822971
break;
2972+
case WLAN_CIPHER_SUITE_GCMP_256:
2973+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2974+
brcmf_err("the low layer not support GCMP\n");
2975+
err = -EOPNOTSUPP;
2976+
goto done;
2977+
}
2978+
key->algo = CRYPTO_ALGO_AES_GCM256;
2979+
val = AES_ENABLED;
2980+
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_GCMP_256\n");
2981+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256);
2982+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2983+
break;
2984+
case WLAN_CIPHER_SUITE_BIP_GMAC_256:
2985+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2986+
brcmf_err("the low layer not support GCMP\n");
2987+
err = -EOPNOTSUPP;
2988+
goto done;
2989+
}
2990+
key->algo = CRYPTO_ALGO_BIP_GMAC256;
2991+
val = AES_ENABLED;
2992+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_BIP_GMAC256);
2993+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2994+
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_BIP_GMAC_256\n");
2995+
break;
28832996
default:
28842997
bphy_err(drvr, "Invalid cipher (0x%x)\n", params->cipher);
28852998
err = -EINVAL;
@@ -2901,6 +3014,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
29013014
bphy_err(drvr, "set wsec error (%d)\n", err);
29023015
goto done;
29033016
}
3017+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
3018+
brcmf_dbg(CONN,
3019+
"set_wsdec_info algos (0x%x) mask (0x%x)\n",
3020+
algos, mask);
3021+
err = brcmf_set_wsec_info_algos(ifp, algos, mask);
3022+
if (err) {
3023+
brcmf_err("set wsec_info error (%d)\n", err);
3024+
return err;
3025+
}
3026+
}
3027+
29043028

29053029
done:
29063030
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)