Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08177d39 authored by Sunil Dutt's avatar Sunil Dutt Committed by Gerrit - the friendly Code Review server
Browse files

cfg80211/nl80211: Offload OWE processing to user space in AP mode



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: default avatarLiangwei Dong <liangwei@codeaurora.org>
Signed-off-by: default avatarSunil Dutt <usdutt@codeaurora.org>
Signed-off-by: default avatarJohannes 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: default avatarSrinivas Dasari <dasaris@codeaurora.org>
parent b1096dd1
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -2847,6 +2847,32 @@ struct cfg80211_external_auth_params {
	const u8 *pmkid;
};

/**
 * 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
 *
@@ -3179,6 +3205,10 @@ struct cfg80211_external_auth_params {
 *
 * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
 *	tells the driver that the frame should not be encrypted.
 *
 * @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);
@@ -3484,6 +3514,8 @@ struct cfg80211_ops {
				   const u8 *buf, size_t len,
				   const u8 *dest, const __be16 proto,
				   const bool noencrypt);
	int	(*update_owe_info)(struct wiphy *wiphy, struct net_device *dev,
				   struct cfg80211_update_owe_info *owe_info);
};

/*
@@ -6806,4 +6838,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 */
+7 −0
Original line number Diff line number Diff line
@@ -1065,6 +1065,11 @@
 *	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
 */
@@ -1285,6 +1290,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 */
+72 −0
Original line number Diff line number Diff line
@@ -13025,6 +13025,31 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
	return err;
}

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
@@ -13936,6 +13961,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,
	},
};

static struct genl_family nl80211_fam __ro_after_init = {
@@ -16110,6 +16142,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 __init nl80211_init(void)
+13 −0
Original line number Diff line number Diff line
@@ -1232,4 +1232,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 */
+38 −0
Original line number Diff line number Diff line
@@ -3259,6 +3259,44 @@ TRACE_EVENT(rdev_get_txq_stats,
	),
	TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, 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