wifi: nl80211: Extend del pmksa support for SAE and OWE security
authorVinayak Yadawad <vinayak.yadawad@broadcom.com>
Wed, 29 Nov 2023 12:50:43 +0000 (18:20 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 12 Dec 2023 09:36:59 +0000 (10:36 +0100)
Current handling of del pmksa with SSID is limited to FILS
security. In the current change the del pmksa support is extended
to SAE/OWE security offloads as well. For OWE/SAE offloads, the
PMK is generated and cached at driver/FW, so user app needs the
capability to request cache deletion based on SSID for drivers
supporting SAE/OWE offload.

Signed-off-by: Vinayak Yadawad <vinayak.yadawad@broadcom.com>
Link: https://msgid.link/ecdae726459e0944c377a6a6f6cb2c34d2e057d0.1701262123.git.vinayak.yadawad@broadcom.com
[drop whitespace-damaged rdev_ops pointer completely, enabling tracing]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/uapi/linux/nl80211.h
net/wireless/nl80211.c

index 0cd1da2c2902a993df7e45c95e4c8856ac410e5b..8f42d598e285395b281f69139d665e92601d247b 100644 (file)
  * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC
  *     (for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID,
  *     %NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS
- *     authentication.
+ *     authentication. Additionally in case of SAE offload and OWE offloads
+ *     PMKSA entry can be deleted using %NL80211_ATTR_SSID.
  * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries.
  *
  * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
index 403a4a38966a3e19bdd6a45b8529ff9d7df1047c..d6a20c21f094c2620ca642f272bf20588223a41a 100644 (file)
@@ -12174,16 +12174,18 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
        return err;
 }
 
-static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
+static int nl80211_set_pmksa(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
-                       struct cfg80211_pmksa *pmksa) = NULL;
        struct net_device *dev = info->user_ptr[1];
        struct cfg80211_pmksa pmksa;
+       bool ap_pmksa_caching_support = false;
 
        memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
 
+       ap_pmksa_caching_support = wiphy_ext_feature_isset(&rdev->wiphy,
+               NL80211_EXT_FEATURE_AP_PMKSA_CACHING);
+
        if (!info->attrs[NL80211_ATTR_PMKID])
                return -EINVAL;
 
@@ -12192,16 +12194,15 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
        if (info->attrs[NL80211_ATTR_MAC]) {
                pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
        } else if (info->attrs[NL80211_ATTR_SSID] &&
-                  info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
-                  (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA ||
-                   info->attrs[NL80211_ATTR_PMK])) {
+                  info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
+                  info->attrs[NL80211_ATTR_PMK]) {
                pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
                pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
-               pmksa.cache_id =
-                       nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
+               pmksa.cache_id = nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
        } else {
                return -EINVAL;
        }
+
        if (info->attrs[NL80211_ATTR_PMK]) {
                pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
                pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
@@ -12213,32 +12214,71 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
 
        if (info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD])
                pmksa.pmk_reauth_threshold =
-                       nla_get_u8(
-                               info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
+                       nla_get_u8(info->attrs[NL80211_ATTR_PMK_REAUTH_THRESHOLD]);
 
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
-           !(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP &&
-             wiphy_ext_feature_isset(&rdev->wiphy,
-                                     NL80211_EXT_FEATURE_AP_PMKSA_CACHING)))
+           !((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+              dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
+              ap_pmksa_caching_support))
                return -EOPNOTSUPP;
 
-       switch (info->genlhdr->cmd) {
-       case NL80211_CMD_SET_PMKSA:
-               rdev_ops = rdev->ops->set_pmksa;
-               break;
-       case NL80211_CMD_DEL_PMKSA:
-               rdev_ops = rdev->ops->del_pmksa;
-               break;
-       default:
-               WARN_ON(1);
-               break;
+       if (!rdev->ops->set_pmksa)
+               return -EOPNOTSUPP;
+
+       return rdev_set_pmksa(rdev, dev, &pmksa);
+}
+
+static int nl80211_del_pmksa(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct net_device *dev = info->user_ptr[1];
+       struct cfg80211_pmksa pmksa;
+       bool sae_offload_support = false;
+       bool owe_offload_support = false;
+       bool ap_pmksa_caching_support = false;
+
+       memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
+
+       sae_offload_support = wiphy_ext_feature_isset(&rdev->wiphy,
+               NL80211_EXT_FEATURE_SAE_OFFLOAD);
+       owe_offload_support = wiphy_ext_feature_isset(&rdev->wiphy,
+               NL80211_EXT_FEATURE_OWE_OFFLOAD);
+       ap_pmksa_caching_support = wiphy_ext_feature_isset(&rdev->wiphy,
+               NL80211_EXT_FEATURE_AP_PMKSA_CACHING);
+
+       if (info->attrs[NL80211_ATTR_PMKID])
+               pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
+
+       if (info->attrs[NL80211_ATTR_MAC]) {
+               pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+       } else if (info->attrs[NL80211_ATTR_SSID]) {
+               /* SSID based pmksa flush suppported only for FILS,
+                * OWE/SAE OFFLOAD cases
+                */
+               if (info->attrs[NL80211_ATTR_FILS_CACHE_ID] &&
+                   info->attrs[NL80211_ATTR_PMK]) {
+                       pmksa.cache_id = nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]);
+               } else if (!sae_offload_support && !owe_offload_support) {
+                       return -EINVAL;
+               }
+               pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+               pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+       } else {
+               return -EINVAL;
        }
 
-       if (!rdev_ops)
+       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT &&
+           !((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+              dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
+              ap_pmksa_caching_support))
+               return -EOPNOTSUPP;
+
+       if (!rdev->ops->del_pmksa)
                return -EOPNOTSUPP;
 
-       return rdev_ops(&rdev->wiphy, dev, &pmksa);
+       return rdev_del_pmksa(rdev, dev, &pmksa);
 }
 
 static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
@@ -16912,7 +16952,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
        {
                .cmd = NL80211_CMD_SET_PMKSA,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-               .doit = nl80211_setdel_pmksa,
+               .doit = nl80211_set_pmksa,
                .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
                                         NL80211_FLAG_CLEAR_SKB),
@@ -16920,7 +16960,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
        {
                .cmd = NL80211_CMD_DEL_PMKSA,
                .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-               .doit = nl80211_setdel_pmksa,
+               .doit = nl80211_del_pmksa,
                .flags = GENL_UNS_ADMIN_PERM,
                .internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
        },