mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
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>
This commit is contained in:
parent
3002812cbe
commit
8ff047b9c7
|
|
@ -443,8 +443,9 @@ void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
|
|||
|
||||
/* internal helpers */
|
||||
bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
|
||||
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
|
||||
int key_idx, bool pairwise);
|
||||
bool cfg80211_valid_key_idx(struct wireless_dev *wdev,
|
||||
int key_idx, bool pairwise,
|
||||
const u8 *mac_addr);
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
struct key_params *params, int key_idx,
|
||||
|
|
|
|||
|
|
@ -5409,7 +5409,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!rdev->ops->get_key)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
if (!cfg80211_valid_key_idx(wdev, key_idx, pairwise, mac_addr))
|
||||
return -ENOENT;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
|
|
@ -5663,8 +5663,9 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
|||
key.type != NL80211_KEYTYPE_GROUP)
|
||||
return -EINVAL;
|
||||
|
||||
if (!cfg80211_valid_key_idx(rdev, key.idx,
|
||||
key.type == NL80211_KEYTYPE_PAIRWISE))
|
||||
if (!cfg80211_valid_key_idx(wdev, key.idx,
|
||||
key.type == NL80211_KEYTYPE_PAIRWISE,
|
||||
mac_addr))
|
||||
return -EINVAL;
|
||||
|
||||
if (!rdev->ops->del_key)
|
||||
|
|
@ -5672,10 +5673,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
err = nl80211_key_allowed(wdev);
|
||||
|
||||
if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
err = -ENOENT;
|
||||
|
||||
if (!err)
|
||||
err = nl80211_validate_key_link_id(info, wdev, link_id,
|
||||
key.type == NL80211_KEYTYPE_PAIRWISE);
|
||||
|
|
|
|||
|
|
@ -241,10 +241,8 @@ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev)
|
||||
static bool cfg80211_igtk_cipher_supported(struct wiphy *wiphy)
|
||||
{
|
||||
struct wiphy *wiphy = &rdev->wiphy;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < wiphy->n_cipher_suites; i++) {
|
||||
|
|
@ -260,27 +258,86 @@ cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev,
|
||||
int key_idx, bool pairwise)
|
||||
bool cfg80211_valid_key_idx(struct wireless_dev *wdev,
|
||||
int key_idx, bool pairwise,
|
||||
const u8 *mac_addr)
|
||||
{
|
||||
int max_key_idx;
|
||||
|
||||
if (pairwise)
|
||||
max_key_idx = 3;
|
||||
else if (wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION) ||
|
||||
wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
|
||||
max_key_idx = 7;
|
||||
else if (cfg80211_igtk_cipher_supported(rdev))
|
||||
max_key_idx = 5;
|
||||
else
|
||||
max_key_idx = 3;
|
||||
|
||||
if (key_idx < 0 || key_idx > max_key_idx)
|
||||
if (WARN_ON(!wdev))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
if (key_idx < 0)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Can't differentiate ciphers here so allow 0..3.
|
||||
* Pairwise keys must be for a station (MAC address given).
|
||||
*/
|
||||
if (pairwise) {
|
||||
if (!mac_addr)
|
||||
return false;
|
||||
|
||||
return key_idx < 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* For group keys, mac_addr==NULL means setting a group key
|
||||
* for TX, which is only supported on some interface types,
|
||||
* except for STATION/P2P_CLIENT, where it's setting the RX
|
||||
* key with the current AP (for legacy reasons.)
|
||||
*
|
||||
* Apart from that exception, a non-NULL mac_addr means RX
|
||||
* key being set.
|
||||
*/
|
||||
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
if (!(wdev->wiphy->flags & WIPHY_FLAG_IBSS_RSN))
|
||||
return false;
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
/* no support for IGTK/BIGTK (yet?) */
|
||||
return key_idx < 4;
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* these always need to support per-STA GTK */
|
||||
return key_idx < 4;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
/* no data */
|
||||
if (key_idx < 4)
|
||||
return false;
|
||||
/* NAN reused this flag */
|
||||
if (wiphy_ext_feature_isset(wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION))
|
||||
return key_idx <= 7;
|
||||
return key_idx <= 5;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
/* see note about exception above */
|
||||
if (mac_addr)
|
||||
return false;
|
||||
/* BIGTK support implies IGTK support */
|
||||
if (wiphy_ext_feature_isset(wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
|
||||
return key_idx <= 7;
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
/* no RX with [B]IGTK */
|
||||
if (mac_addr)
|
||||
return false;
|
||||
if (wiphy_ext_feature_isset(wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_BEACON_PROTECTION))
|
||||
return key_idx <= 7;
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
/* no RX with GTK */
|
||||
if (mac_addr)
|
||||
return false;
|
||||
if (cfg80211_igtk_cipher_supported(wdev->wiphy))
|
||||
return key_idx <= 5;
|
||||
return key_idx <= 3;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
|
|
@ -288,13 +345,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
|||
struct key_params *params, int key_idx,
|
||||
bool pairwise, const u8 *mac_addr)
|
||||
{
|
||||
if (!cfg80211_valid_key_idx(rdev, key_idx, pairwise))
|
||||
return -EINVAL;
|
||||
|
||||
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
return -EINVAL;
|
||||
|
||||
if (pairwise && !mac_addr)
|
||||
if (!cfg80211_valid_key_idx(wdev, key_idx, pairwise, mac_addr))
|
||||
return -EINVAL;
|
||||
|
||||
switch (params->cipher) {
|
||||
|
|
|
|||
|
|
@ -454,8 +454,7 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
rejoin = true;
|
||||
}
|
||||
|
||||
if (!pairwise && addr &&
|
||||
!(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
if (!cfg80211_valid_key_idx(wdev, idx, pairwise, addr))
|
||||
err = -ENOENT;
|
||||
else
|
||||
err = rdev_del_key(rdev, wdev, -1, idx, pairwise,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user