summaryrefslogtreecommitdiff
path: root/net/wireless/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c137
1 files changed, 106 insertions, 31 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index cff5a1bd95cc..3e584d0ca3e2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -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,40 +258,94 @@ 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 (WARN_ON(!wdev))
+ return false;
- if (key_idx < 0 || key_idx > max_key_idx)
+ if (key_idx < 0)
return false;
- return true;
+ /*
+ * 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,
+ struct wireless_dev *wdev,
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) {
@@ -344,6 +396,15 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
break;
}
+ /*
+ * Per Wi-Fi Aware v4.0 section 7.1.2, NAN Data interfaces
+ * shall only use CCMP-128 or GCMP-256.
+ */
+ if (wdev->iftype == NL80211_IFTYPE_NAN_DATA &&
+ params->cipher != WLAN_CIPHER_SUITE_CCMP &&
+ params->cipher != WLAN_CIPHER_SUITE_GCMP_256)
+ return -EINVAL;
+
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
if (params->key_len != WLAN_KEY_LEN_WEP40)
@@ -424,6 +485,21 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))
return -EINVAL;
+ if (params->ltf_keyseed) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_SECURE_LTF) ||
+ !wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_SET_KEY_LTF_SEED))
+ return -EOPNOTSUPP;
+
+ /*
+ * LTF key seed is pairwise key material and must only be
+ * used with a pairwise key
+ */
+ if (!pairwise)
+ return -EINVAL;
+ }
+
return 0;
}
@@ -1201,7 +1277,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
/* cannot change into P2P device or NAN */
if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
- ntype == NL80211_IFTYPE_NAN)
+ ntype == NL80211_IFTYPE_NAN ||
+ ntype == NL80211_IFTYPE_PD)
return -EOPNOTSUPP;
if (!rdev->ops->change_virtual_intf ||
@@ -1266,6 +1343,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_NAN:
+ case NL80211_IFTYPE_PD:
WARN_ON(1);
break;
}
@@ -2277,9 +2355,6 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
case NL80211_CHAN_WIDTH_80P80:
vht_opclass = 130;
break;
- case NL80211_CHAN_WIDTH_10:
- case NL80211_CHAN_WIDTH_5:
- return false; /* unsupported for now */
default:
vht_opclass = 0;
break;