Skip to content

Commit 10e89ea

Browse files
dberlinmarcan
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 8a38012 commit 10e89ea

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,6 +32,8 @@
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+
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 */
@@ -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+
20182075
static s32
20192076
brcmf_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

29063030
done:
29073031
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
@@ -43,6 +43,7 @@ static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
4343
{ BRCMF_FEAT_DOT11H, "802.11h" },
4444
{ BRCMF_FEAT_SAE, "sae" },
4545
{ BRCMF_FEAT_FWAUTH, "idauth" },
46+
{ BRCMF_FEAT_GCMP, "gcmp"}
4647
};
4748

4849
#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)