OSDN Git Service

cfg80211/nl80211: Offload OWE processing to user space in AP mode
authorSunil Dutt <usdutt@codeaurora.org>
Tue, 9 Apr 2019 07:39:28 +0000 (13:09 +0530)
committerMin Liu <minliu@codeaurora.org>
Mon, 22 Apr 2019 10:56:46 +0000 (18:56 +0800)
This interface allows the host driver to offload OWE processing
to user space. This intends to support OWE (Opportunistic Wireless
Encryption) AKM by the drivers that implement SME but rely on the
user space for the cryptographic/OWE processing in AP mode. Such
drivers are not capable of processing/deriving the DH IE.

A new NL80211 command - NL80211_CMD_UPDATE_OWE_INFO is introduced
to send the request/event between the host driver and user space.

Driver shall provide the OWE info (MAC address and DH IE) of
the peer to user space for cryptographic processing of the DH IE
through the event. Accordingly, the user space shall update the
OWE info/DH IE to the driver.

Following is the sequence in AP mode for OWE authentication.

Driver passes the OWE info obtained from the peer in the
Association Request to the user space through the event
cfg80211_update_owe_info_event. User space shall process the
OWE info received and generate new OWE info. This OWE info is
passed to the driver through NL80211_CMD_UPDATE_OWE_INFO
request. Driver eventually uses this OWE info to send the
Association Response to the peer.

This OWE info in the command interface carries the IEs that include
PMKID of the peer if the PMKSA is still valid or an updated DH IE
for generating a new PMKSA with the peer.

Signed-off-by: Liangwei Dong <liangwei@codeaurora.org>
Signed-off-by: Sunil Dutt <usdutt@codeaurora.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Git-commit: cb74e9775871f8c82a1297cf76209f10ab5bbe3d
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
Change-Id: I3b0391cd6da1ff033f4d8383013deb4ad5ecbe64
CRs-Fixed: 2414077
Signed-off-by: Srinivas Dasari <dasaris@codeaurora.org>
Signed-off-by: Min Liu <minliu@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 33ea21e..5f79280 100644 (file)
@@ -2447,6 +2447,32 @@ struct cfg80211_external_auth_params {
 };
 
 /**
+ * struct cfg80211_update_owe_info - OWE Information
+ *
+ * This structure provides information needed for the drivers to offload OWE
+ * (Opportunistic Wireless Encryption) processing to the user space.
+ *
+ * Commonly used across update_owe_info request and event interfaces.
+ *
+ * @peer: MAC address of the peer device for 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 request command interface (user space to driver).
+ * @ie: IEs obtained from the peer or constructed by the user space. These are
+ *     the IEs of the remote peer in the event from the host driver and
+ *     the constructed IEs by the user space in the request interface.
+ * @ie_len: Length of IEs in octets.
+ */
+struct cfg80211_update_owe_info {
+       u8 peer[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
@@ -2744,6 +2770,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 OWE processing to the user space will get the updated
+ *     DH IE through this interface.
  */
 struct cfg80211_ops {
        int     (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3015,6 +3045,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);
 };
 
 /*
@@ -5899,4 +5931,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..7877fac 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 AKM by the host drivers that implement SME but rely
+ *     on the user space for the cryptographic/DH IE processing in AP mode.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1210,6 +1215,8 @@ 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..9336f6e 100644 (file)
@@ -11216,6 +11216,31 @@ 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_MAC])
+               return -EINVAL;
+
+       memset(&owe_info, 0, sizeof(owe_info));
+       owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+       nla_memcpy(owe_info.peer, 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 +12083,13 @@ 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,
+               .flags = GENL_ADMIN_PERM,
+               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+                                 NL80211_FLAG_NEED_RTNL,
+       },
 };
 
 /* notification functions */
@@ -14052,6 +14084,46 @@ 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);
+
+       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->peer))
+               goto nla_put_failure;
+
+       if (!owe_info->ie_len ||
+           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:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_update_owe_info_event);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
index aef08a0..c20e37a 100644 (file)
@@ -1054,4 +1054,17 @@ 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 = -EOPNOTSUPP;
+
+       trace_rdev_update_owe_info(&rdev->wiphy, dev, oweinfo);
+       if (rdev->ops->update_owe_info)
+               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..77eb73d 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(peer)
+                            __field(u16, status)
+                            __dynamic_array(u8, ie, owe_info->ie_len)),
+           TP_fast_assign(WIPHY_ASSIGN;
+                          NETDEV_ASSIGN;
+                          MAC_ASSIGN(peer, owe_info->peer);
+                          __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(peer),
+                 __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(peer)
+                            __dynamic_array(u8, ie, owe_info->ie_len)),
+           TP_fast_assign(WIPHY_ASSIGN;
+                          NETDEV_ASSIGN;
+                          MAC_ASSIGN(peer, owe_info->peer);
+                          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(peer))
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH