Skip to content

Commit 8ff047b

Browse files
committed
wifi: cfg80211: clarify and tighten key checks
Currently, we accept per-STA GTK for any interface type if the IBSS_RSN flag is set, which doesn't make sense, and also accept various key indices that aren't really (meant to be) supported, such as IGTK/BIGTK on IBSS or AP_VLAN etc. For MESH and NAN_DATA interface types, per-STA GTKs are required, so their support shouldn't depend on IBSS_RSN. Conversely a driver setting IBSS_RSN doesn't really say it also accepts per-STA GTK for other interface types. Move more checks into cfg80211_valid_key_idx() and make them more precise: - allow IGTK and, if supported, BIGTK for NAN - allow per-STA (RX) GTK only for - NAN_DATA - IBSS if IBSS_RSN is supported - MESH - allow B/I/GTK for station/P2P-client without mac_addr for RX with the current AP (historic API quirk), subject to support - allow TX GTK for AP/P2P-GO/AP_VLAN - allow TX IGTK/BIGTK for AP/P2P-GO subject to support Other settings are rejected, clearing up corner cases and disallowing unexpected settings. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260715212403.725e6b63e890.I24684374112bb94d0633d61ef76ecb8a1517f7f1@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 3002812 commit 8ff047b

4 files changed

Lines changed: 86 additions & 38 deletions

File tree

net/wireless/core.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,9 @@ void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
443443

444444
/* internal helpers */
445445
bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
446-
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
447-
int key_idx, bool pairwise);
446+
bool cfg80211_valid_key_idx(struct wireless_dev *wdev,
447+
int key_idx, bool pairwise,
448+
const u8 *mac_addr);
448449
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
449450
struct wireless_dev *wdev,
450451
struct key_params *params, int key_idx,

net/wireless/nl80211.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5409,7 +5409,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
54095409
if (!rdev->ops->get_key)
54105410
return -EOPNOTSUPP;
54115411

5412-
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
5412+
if (!cfg80211_valid_key_idx(wdev, key_idx, pairwise, mac_addr))
54135413
return -ENOENT;
54145414

54155415
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
@@ -5663,19 +5663,16 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
56635663
key.type != NL80211_KEYTYPE_GROUP)
56645664
return -EINVAL;
56655665

5666-
if (!cfg80211_valid_key_idx(rdev, key.idx,
5667-
key.type == NL80211_KEYTYPE_PAIRWISE))
5666+
if (!cfg80211_valid_key_idx(wdev, key.idx,
5667+
key.type == NL80211_KEYTYPE_PAIRWISE,
5668+
mac_addr))
56685669
return -EINVAL;
56695670

56705671
if (!rdev->ops->del_key)
56715672
return -EOPNOTSUPP;
56725673

56735674
err = nl80211_key_allowed(wdev);
56745675

5675-
if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
5676-
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
5677-
err = -ENOENT;
5678-
56795676
if (!err)
56805677
err = nl80211_validate_key_link_id(info, wdev, link_id,
56815678
key.type == NL80211_KEYTYPE_PAIRWISE);

net/wireless/util.c

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,8 @@ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
241241
return false;
242242
}
243243

244-
static bool
245-
cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev)
244+
static bool cfg80211_igtk_cipher_supported(struct wiphy *wiphy)
246245
{
247-
struct wiphy *wiphy = &rdev->wiphy;
248246
int i;
249247

250248
for (i = 0; i < wiphy->n_cipher_suites; i++) {
@@ -260,41 +258,94 @@ cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev)
260258
return false;
261259
}
262260

263-
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
264-
int key_idx, bool pairwise)
261+
bool cfg80211_valid_key_idx(struct wireless_dev *wdev,
262+
int key_idx, bool pairwise,
263+
const u8 *mac_addr)
265264
{
266-
int max_key_idx;
267-
268-
if (pairwise)
269-
max_key_idx = 3;
270-
else if (wiphy_ext_feature_isset(&rdev->wiphy,
271-
NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
272-
wiphy_ext_feature_isset(&rdev->wiphy,
273-
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
274-
max_key_idx = 7;
275-
else if (cfg80211_igtk_cipher_supported(rdev))
276-
max_key_idx = 5;
277-
else
278-
max_key_idx = 3;
265+
if (WARN_ON(!wdev))
266+
return false;
279267

280-
if (key_idx < 0 || key_idx > max_key_idx)
268+
if (key_idx < 0)
281269
return false;
282270

283-
return true;
271+
/*
272+
* Can't differentiate ciphers here so allow 0..3.
273+
* Pairwise keys must be for a station (MAC address given).
274+
*/
275+
if (pairwise) {
276+
if (!mac_addr)
277+
return false;
278+
279+
return key_idx < 4;
280+
}
281+
282+
/*
283+
* For group keys, mac_addr==NULL means setting a group key
284+
* for TX, which is only supported on some interface types,
285+
* except for STATION/P2P_CLIENT, where it's setting the RX
286+
* key with the current AP (for legacy reasons.)
287+
*
288+
* Apart from that exception, a non-NULL mac_addr means RX
289+
* key being set.
290+
*/
291+
292+
switch (wdev->iftype) {
293+
case NL80211_IFTYPE_ADHOC:
294+
if (!(wdev->wiphy->flags & WIPHY_FLAG_IBSS_RSN))
295+
return false;
296+
fallthrough;
297+
case NL80211_IFTYPE_MESH_POINT:
298+
/* no support for IGTK/BIGTK (yet?) */
299+
return key_idx < 4;
300+
case NL80211_IFTYPE_NAN_DATA:
301+
/* these always need to support per-STA GTK */
302+
return key_idx < 4;
303+
case NL80211_IFTYPE_NAN:
304+
/* no data */
305+
if (key_idx < 4)
306+
return false;
307+
/* NAN reused this flag */
308+
if (wiphy_ext_feature_isset(wdev->wiphy,
309+
NL80211_EXT_FEATURE_BEACON_PROTECTION))
310+
return key_idx <= 7;
311+
return key_idx <= 5;
312+
case NL80211_IFTYPE_STATION:
313+
case NL80211_IFTYPE_P2P_CLIENT:
314+
/* see note about exception above */
315+
if (mac_addr)
316+
return false;
317+
/* BIGTK support implies IGTK support */
318+
if (wiphy_ext_feature_isset(wdev->wiphy,
319+
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
320+
return key_idx <= 7;
321+
fallthrough;
322+
case NL80211_IFTYPE_AP:
323+
case NL80211_IFTYPE_P2P_GO:
324+
/* no RX with [B]IGTK */
325+
if (mac_addr)
326+
return false;
327+
if (wiphy_ext_feature_isset(wdev->wiphy,
328+
NL80211_EXT_FEATURE_BEACON_PROTECTION))
329+
return key_idx <= 7;
330+
fallthrough;
331+
case NL80211_IFTYPE_AP_VLAN:
332+
/* no RX with GTK */
333+
if (mac_addr)
334+
return false;
335+
if (cfg80211_igtk_cipher_supported(wdev->wiphy))
336+
return key_idx <= 5;
337+
return key_idx <= 3;
338+
default:
339+
return false;
340+
}
284341
}
285342

286343
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
287344
struct wireless_dev *wdev,
288345
struct key_params *params, int key_idx,
289346
bool pairwise, const u8 *mac_addr)
290347
{
291-
if (!cfg80211_valid_key_idx(rdev, key_idx, pairwise))
292-
return -EINVAL;
293-
294-
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
295-
return -EINVAL;
296-
297-
if (pairwise && !mac_addr)
348+
if (!cfg80211_valid_key_idx(wdev, key_idx, pairwise, mac_addr))
298349
return -EINVAL;
299350

300351
switch (params->cipher) {

net/wireless/wext-compat.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,7 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
454454
rejoin = true;
455455
}
456456

457-
if (!pairwise && addr &&
458-
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
457+
if (!cfg80211_valid_key_idx(wdev, idx, pairwise, addr))
459458
err = -ENOENT;
460459
else
461460
err = rdev_del_key(rdev, wdev, -1, idx, pairwise,

0 commit comments

Comments
 (0)