OSDN Git Service

cfg80211/nl80211: Offload OWE processing to user space
authorSunil Dutt <usdutt@codeaurora.org>
Wed, 9 Jan 2019 16:42:29 +0000 (22:12 +0530)
committerLiangwei Dong <liangwei@codeaurora.org>
Tue, 12 Mar 2019 06:04:11 +0000 (02:04 -0400)
This interface allows the host driver to offload OWE processing to
user space. This intends to support OWE/Enhanced Open AKM by the host
drivers that implement SME but rely on the user space for
the crypotographic/OWE processing.Such drivers are not capable of
processing/deriving the DH IE's.

This interface acts as both the event from the driver to userspace
and a command from userspace to the driver.

Host driver shall use the event to notify the OWE info of the peer
to the userspace for the cryptographic processing of the DH ie's.
Accordingly, the userspace shall update the OWE info/DH ie's to
the host driver corresponding to the peer.

Above sequence aims for the AP mode where the event carries the
OWE info of the peer(STA) obtained in the Assoc Request.
The request interface from the userspace shall update the OWE
info to the host driver, which is used to send the Assoc response
to the peer.

This OWE info in the command interface shall contain the ie's which
either include the pmkid of the peer if the PMKSA is still valid or
an updated DH ie's for generating a new PMKSA with the peer.

Change-Id: Id5a2e800bdae1ea31a20a062d012cc33e5a3c6a3
CRs-Fixed: 2414077
Signed-off-by: Liangwei Dong <liangwei@codeaurora.org>
Signed-off-by: Sunil Dutt <usdutt@codeaurora.org>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/trace.h

index 18aff0c..78ad3fe 100644 (file)
@@ -2444,6 +2444,31 @@ struct cfg80211_external_auth_params {
 };
 
 /**
+ * struct cfg80211_update_owe_info - OWE Information
+ *
+ * This structure provides information needed for the drivers to offload OWE
+ * (Oppurtunistic Wireless Encryption) processing to the user space.
+ *
+ * Commonly used across update_owe request and event interfaces.
+ *
+ * @bssid: BSSID of the peer from which the OWE processing has to be done.
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful OWE info
+ *         processing, use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space
+ *         cannot give you the real status code for failures. Used only for
+ *         OWE update response command interface (user space to driver).
+ * @ie: IE's obtained from the peer or constructed by the user space. These are
+ *         the IE's of the remote peer in the event from the host driver and
+ *         the constructed IE's by the user space in the request interface.
+ * @ie_len: Length of IE's in octets.
+ */
+struct cfg80211_update_owe_info {
+       u8 bssid[ETH_ALEN] __aligned(2);
+       u16 status;
+       const u8 *ie;
+       size_t ie_len;
+};
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2741,6 +2766,10 @@ struct cfg80211_external_auth_params {
  *
  * @external_auth: indicates result of offloaded authentication processing from
  *     user space
+ *
+ * @update_owe_info: Provide updated OWE info to driver. Driver implementing SME
+ *     but offloading the OWE processing to the user space will get the updated
+ *     DH IE's (from the IE's) obtained through this interface.
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3012,6 +3041,8 @@ struct cfg80211_ops {
                                              const u8 *addr);
        int     (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
                                 struct cfg80211_external_auth_params *params);
+       int     (*update_owe_info)(struct wiphy *wiphy, struct net_device *dev,
+                                  struct cfg80211_update_owe_info *owe_info);
 };
 
 /*
@@ -5896,4 +5927,14 @@ int cfg80211_external_auth_request(struct net_device *netdev,
 #define wiphy_WARN(wiphy, format, args...)                     \
        WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
 
+/**
+ * cfg80211_update_owe_info_event - Notify the peer's OWE info to user space
+ * @netdev: network device
+ * @owe_info: peer's owe info
+ * @gfp: allocation flags
+ */
+void cfg80211_update_owe_info_event(struct net_device *netdev,
+                                   struct cfg80211_update_owe_info *owe_info,
+                                   gfp_t gfp);
+
 #endif /* __NET_CFG80211_H */
index 0527b77..9ac3946 100644 (file)
  *     indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes
  *     determining the width and type.
  *
+ * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to
+ *     offload OWE processing to user space. This intends to support
+ *     OWE/Enhanced Open AKM by the host drivers that implemnt SME but rely
+ *     on the user space for the crypotographic/DH IE processing.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1210,6 +1215,7 @@ enum nl80211_commands {
 
        NL80211_CMD_NOTIFY_RADAR,
 
+       NL80211_CMD_UPDATE_OWE_INFO,
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
index dfce235..a22e64f 100644 (file)
@@ -11216,6 +11216,34 @@ static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
        return rdev_external_auth(rdev, dev, &params);
 }
 
+static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
+{
+       struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct cfg80211_update_owe_info owe_info;
+       struct net_device *dev = info->user_ptr[1];
+
+       if (!rdev->ops->update_owe_info)
+               return -EOPNOTSUPP;
+
+       if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
+           (info->attrs[NL80211_ATTR_IE] &&
+            !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])))
+               return -EINVAL;
+
+       memset(&owe_info, 0, sizeof(owe_info));
+       owe_info.status =
+                       nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+       if (info->attrs[NL80211_ATTR_MAC])
+               nla_memcpy(owe_info.bssid, info->attrs[NL80211_ATTR_MAC],
+                          ETH_ALEN);
+       if (info->attrs[NL80211_ATTR_IE]) {
+               owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+       }
+
+       return rdev_update_owe_info(rdev, dev, &owe_info);
+}
+
 #define NL80211_FLAG_NEED_WIPHY                0x01
 #define NL80211_FLAG_NEED_NETDEV       0x02
 #define NL80211_FLAG_NEED_RTNL         0x04
@@ -12058,6 +12086,14 @@ static const struct genl_ops nl80211_ops[] = {
                .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
                                  NL80211_FLAG_NEED_RTNL,
        },
+       {
+               .cmd = NL80211_CMD_UPDATE_OWE_INFO,
+               .doit = nl80211_update_owe_info,
+               .policy = nl80211_policy,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
 };
 
 /* notification functions */
@@ -14052,6 +14088,49 @@ int cfg80211_external_auth_request(struct net_device *dev,
 }
 EXPORT_SYMBOL(cfg80211_external_auth_request);
 
+void cfg80211_update_owe_info_event(struct net_device *netdev,
+                                   struct cfg80211_update_owe_info *owe_info,
+                                   gfp_t gfp)
+{
+       struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+       struct sk_buff *msg;
+       void *hdr;
+
+       trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
+
+       if (!owe_info)
+               return;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
+       if (!hdr)
+               goto nla_put_failure;
+
+       if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+           nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+           nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->bssid))
+               goto nla_put_failure;
+
+       if (nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
+               goto nla_put_failure;
+
+       genlmsg_end(msg, hdr);
+
+       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+                               NL80211_MCGRP_MLME, gfp);
+       return;
+
+nla_put_failure:
+       if (hdr)
+               genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_update_owe_info_event);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
index aef08a0..5cfd263 100644 (file)
@@ -1054,4 +1054,16 @@ rdev_external_auth(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static inline int rdev_update_owe_info(struct cfg80211_registered_device *rdev,
+                                      struct net_device *dev,
+                                      struct cfg80211_update_owe_info *oweinfo)
+{
+       int ret;
+
+       trace_rdev_update_owe_info(&rdev->wiphy, dev, oweinfo);
+       ret = rdev->ops->update_owe_info(&rdev->wiphy, dev, oweinfo);
+       trace_rdev_return_int(&rdev->wiphy, ret);
+       return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
index 03a76e8..bf43da7 100644 (file)
@@ -2866,6 +2866,43 @@ TRACE_EVENT(cfg80211_stop_iface,
                  WIPHY_PR_ARG, WDEV_PR_ARG)
 );
 
+TRACE_EVENT(rdev_update_owe_info,
+           TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                    struct cfg80211_update_owe_info *owe_info),
+           TP_ARGS(wiphy, netdev, owe_info),
+           TP_STRUCT__entry(WIPHY_ENTRY
+                            NETDEV_ENTRY
+                            MAC_ENTRY(bssid)
+                            __field(u16, status)
+                            __dynamic_array(u8, ie, owe_info->ie_len)),
+           TP_fast_assign(WIPHY_ASSIGN;
+                          NETDEV_ASSIGN;
+                          MAC_ASSIGN(bssid, owe_info->bssid);
+                          __entry->status = owe_info->status;
+                          memcpy(__get_dynamic_array(ie),
+                                 owe_info->ie, owe_info->ie_len);),
+           TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT
+                 " status %d", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid),
+                 __entry->status)
+);
+
+TRACE_EVENT(cfg80211_update_owe_info_event,
+           TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+                    struct cfg80211_update_owe_info *owe_info),
+           TP_ARGS(wiphy, netdev, owe_info),
+           TP_STRUCT__entry(WIPHY_ENTRY
+                            NETDEV_ENTRY
+                            MAC_ENTRY(bssid)
+                            __dynamic_array(u8, ie, owe_info->ie_len)),
+           TP_fast_assign(WIPHY_ASSIGN;
+                          NETDEV_ASSIGN;
+                          MAC_ASSIGN(bssid, owe_info->bssid);
+                          memcpy(__get_dynamic_array(ie), owe_info->ie,
+                                 owe_info->ie_len);),
+           TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+                     WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid))
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH