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

Commit 6cdd3979 authored by Alexander Wetzel's avatar Alexander Wetzel Committed by Johannes Berg
Browse files

nl80211/cfg80211: Extended Key ID support



Add support for IEEE 802.11-2016 "Extended Key ID for Individually
Addressed Frames".

Extend cfg80211 and nl80211 to allow pairwise keys to be installed for
Rx only, enable Tx separately and allow Key ID 1 for pairwise keys.

Signed-off-by: default avatarAlexander Wetzel <alexander@wetzel-home.de>
[use NLA_POLICY_RANGE() for NL80211_KEY_MODE]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 092c4098
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -485,6 +485,7 @@ struct vif_params {
 *	with the get_key() callback, must be in little endian,
 *	length given by @seq_len.
 * @seq_len: length of @seq.
 * @mode: key install mode (RX_TX, NO_TX or SET_TX)
 */
struct key_params {
	const u8 *key;
@@ -492,6 +493,7 @@ struct key_params {
	int key_len;
	int seq_len;
	u32 cipher;
	enum nl80211_key_mode mode;
};

/**
+28 −0
Original line number Diff line number Diff line
@@ -4152,6 +4152,27 @@ enum nl80211_channel_type {
	NL80211_CHAN_HT40PLUS
};

/**
 * enum nl80211_key_mode - Key mode
 *
 * @NL80211_KEY_RX_TX: (Default)
 *	Key can be used for Rx and Tx immediately
 *
 * The following modes can only be selected for unicast keys and when the
 * driver supports @NL80211_EXT_FEATURE_EXT_KEY_ID:
 *
 * @NL80211_KEY_NO_TX: Only allowed in combination with @NL80211_CMD_NEW_KEY:
 *	Unicast key can only be used for Rx, Tx not allowed, yet
 * @NL80211_KEY_SET_TX: Only allowed in combination with @NL80211_CMD_SET_KEY:
 *	The unicast key identified by idx and mac is cleared for Tx and becomes
 *	the preferred Tx key for the station.
 */
enum nl80211_key_mode {
	NL80211_KEY_RX_TX,
	NL80211_KEY_NO_TX,
	NL80211_KEY_SET_TX
};

/**
 * enum nl80211_chan_width - channel width definitions
 *
@@ -4395,6 +4416,9 @@ enum nl80211_key_default_types {
 * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags
 *	attributes, specifying what a key should be set as default as.
 *	See &enum nl80211_key_default_types.
 * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode.
 *	Defaults to @NL80211_KEY_RX_TX.
 *
 * @__NL80211_KEY_AFTER_LAST: internal
 * @NL80211_KEY_MAX: highest key attribute
 */
@@ -4408,6 +4432,7 @@ enum nl80211_key_attributes {
	NL80211_KEY_DEFAULT_MGMT,
	NL80211_KEY_TYPE,
	NL80211_KEY_DEFAULT_TYPES,
	NL80211_KEY_MODE,

	/* keep last */
	__NL80211_KEY_AFTER_LAST,
@@ -5353,6 +5378,8 @@ enum nl80211_feature_flags {
 *      able to rekey an in-use key correctly. Userspace must not rekey PTK keys
 *      if this flag is not set. Ignoring this can leak clear text packets and/or
 *      freeze the connection.
 * @NL80211_EXT_FEATURE_EXT_KEY_ID: Driver supports "Extended Key ID for
 *      Individually Addressed Frames" from IEEE802.11-2016.
 *
 * @NL80211_EXT_FEATURE_AIRTIME_FAIRNESS: Driver supports getting airtime
 *	fairness for transmitted packets and has enabled airtime fairness
@@ -5406,6 +5433,7 @@ enum nl80211_ext_feature_index {
	NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
	NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
	NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
	NL80211_EXT_FEATURE_EXT_KEY_ID,

	/* add new features before the definition below */
	NUM_NL80211_EXT_FEATURES,
+28 −4
Original line number Diff line number Diff line
@@ -553,6 +553,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = {
	[NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
	[NL80211_KEY_TYPE] = NLA_POLICY_MAX(NLA_U32, NUM_NL80211_KEYTYPES - 1),
	[NL80211_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
	[NL80211_KEY_MODE] = NLA_POLICY_RANGE(NLA_U8, 0, NL80211_KEY_SET_TX),
};

/* policy for the key default flags */
@@ -967,6 +968,9 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
		k->def_multi = kdt[NL80211_KEY_DEFAULT_TYPE_MULTICAST];
	}

	if (tb[NL80211_KEY_MODE])
		k->p.mode = nla_get_u8(tb[NL80211_KEY_MODE]);

	return 0;
}

@@ -3643,8 +3647,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
	if (key.idx < 0)
		return -EINVAL;

	/* only support setting default key */
	if (!key.def && !key.defmgmt)
	/* Only support setting default key and
	 * Extended Key ID action NL80211_KEY_SET_TX.
	 */
	if (!key.def && !key.defmgmt &&
	    !(key.p.mode == NL80211_KEY_SET_TX))
		return -EINVAL;

	wdev_lock(dev->ieee80211_ptr);
@@ -3668,7 +3675,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
		dev->ieee80211_ptr->wext.default_key = key.idx;
#endif
	} else {
	} else if (key.defmgmt) {
		if (key.def_uni || !key.def_multi) {
			err = -EINVAL;
			goto out;
@@ -3690,8 +3697,25 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
		dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
#endif
	} else if (key.p.mode == NL80211_KEY_SET_TX &&
		   wiphy_ext_feature_isset(&rdev->wiphy,
					   NL80211_EXT_FEATURE_EXT_KEY_ID)) {
		u8 *mac_addr = NULL;

		if (info->attrs[NL80211_ATTR_MAC])
			mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);

		if (!mac_addr || key.idx < 0 || key.idx > 1) {
			err = -EINVAL;
			goto out;
		}

		err = rdev_add_key(rdev, dev, key.idx,
				   NL80211_KEYTYPE_PAIRWISE,
				   mac_addr, &key.p);
	} else {
		err = -EINVAL;
	}
 out:
	wdev_unlock(dev->ieee80211_ptr);

+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
			       struct key_params *params)
{
	int ret;
	trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
	trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise,
			   mac_addr, params->mode);
	ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
				  mac_addr, params);
	trace_rdev_return_int(&rdev->wiphy, ret);
+26 −5
Original line number Diff line number Diff line
@@ -430,22 +430,43 @@ DECLARE_EVENT_CLASS(key_handle,
		  BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
);

DEFINE_EVENT(key_handle, rdev_add_key,
DEFINE_EVENT(key_handle, rdev_get_key,
	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
		 bool pairwise, const u8 *mac_addr),
	TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);

DEFINE_EVENT(key_handle, rdev_get_key,
DEFINE_EVENT(key_handle, rdev_del_key,
	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
		 bool pairwise, const u8 *mac_addr),
	TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
);

DEFINE_EVENT(key_handle, rdev_del_key,
TRACE_EVENT(rdev_add_key,
	TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
		 bool pairwise, const u8 *mac_addr),
	TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
		 bool pairwise, const u8 *mac_addr, u8 mode),
	TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr, mode),
	TP_STRUCT__entry(
		WIPHY_ENTRY
		NETDEV_ENTRY
		MAC_ENTRY(mac_addr)
		__field(u8, key_index)
		__field(bool, pairwise)
		__field(u8, mode)
	),
	TP_fast_assign(
		WIPHY_ASSIGN;
		NETDEV_ASSIGN;
		MAC_ASSIGN(mac_addr, mac_addr);
		__entry->key_index = key_index;
		__entry->pairwise = pairwise;
		__entry->mode = mode;
	),
	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, "
		  "mode: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
		  WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
		  __entry->mode, BOOL_TO_STR(__entry->pairwise),
		  MAC_PR_ARG(mac_addr))
);

TRACE_EVENT(rdev_set_default_key,
Loading