Skip to content

Commit 3ed0592

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 716455d commit 3ed0592

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 */
@@ -2018,6 +2033,48 @@ static s32 brcmf_set_auth_type(struct net_device *ndev,
20182033
return err;
20192034
}
20202035

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

20342093
if (sme->crypto.n_ciphers_pairwise) {
20352094
switch (sme->crypto.ciphers_pairwise[0]) {
@@ -2046,6 +2105,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20462105
case WLAN_CIPHER_SUITE_AES_CMAC:
20472106
pval = AES_ENABLED;
20482107
break;
2108+
case WLAN_CIPHER_SUITE_GCMP_256:
2109+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2110+
brcmf_err("This chip does not support GCMP\n");
2111+
return -EOPNOTSUPP;
2112+
}
2113+
pval = AES_ENABLED;
2114+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256);
2115+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2116+
break;
20492117
default:
20502118
bphy_err(drvr, "invalid cipher pairwise (%d)\n",
20512119
sme->crypto.ciphers_pairwise[0]);
@@ -2067,6 +2135,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20672135
case WLAN_CIPHER_SUITE_AES_CMAC:
20682136
gval = AES_ENABLED;
20692137
break;
2138+
case WLAN_CIPHER_SUITE_GCMP_256:
2139+
if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2140+
brcmf_err("This chip does not support GCMP\n");
2141+
return -EOPNOTSUPP;
2142+
}
2143+
gval = AES_ENABLED;
2144+
algos = KEY_ALGO_MASK(CRYPTO_ALGO_AES_GCM256);
2145+
mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
2146+
break;
20702147
default:
20712148
bphy_err(drvr, "invalid cipher group (%d)\n",
20722149
sme->crypto.cipher_group);
@@ -2075,6 +2152,7 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20752152
}
20762153

20772154
brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval);
2155+
brcmf_dbg(CONN, "algos (0x%x) mask (0x%x)\n", algos, mask);
20782156
/* In case of privacy, but no security and WPS then simulate */
20792157
/* setting AES. WPS-2.0 allows no security */
20802158
if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval &&
@@ -2087,6 +2165,15 @@ brcmf_set_wsec_mode(struct net_device *ndev,
20872165
bphy_err(drvr, "error (%d)\n", err);
20882166
return err;
20892167
}
2168+
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_GCMP)) {
2169+
brcmf_dbg(CONN, "set_wsec_info algos (0x%x) mask (0x%x)\n",
2170+
algos, mask);
2171+
err = brcmf_set_wsec_info_algos(ifp, algos, mask);
2172+
if (err) {
2173+
brcmf_err("set wsec_info error (%d)\n", err);
2174+
return err;
2175+
}
2176+
}
20902177

20912178
sec = &profile->sec;
20922179
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
@@ -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)