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: Alexander Wetzel <alexander@wetzel-home.de> [use NLA_POLICY_RANGE() for NL80211_KEY_MODE] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:

committed by
Johannes Berg

parent
092c4098f2
commit
6cdd3979a2
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -430,12 +430,6 @@ DECLARE_EVENT_CLASS(key_handle,
|
||||
BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(key_handle, 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)
|
||||
);
|
||||
|
||||
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),
|
||||
@@ -448,6 +442,33 @@ DEFINE_EVENT(key_handle, rdev_del_key,
|
||||
TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_add_key,
|
||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
|
||||
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,
|
||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
|
||||
bool unicast, bool multicast),
|
||||
|
@@ -237,14 +237,23 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
||||
case WLAN_CIPHER_SUITE_CCMP_256:
|
||||
case WLAN_CIPHER_SUITE_GCMP:
|
||||
case WLAN_CIPHER_SUITE_GCMP_256:
|
||||
/* Disallow pairwise keys with non-zero index unless it's WEP
|
||||
* or a vendor specific cipher (because current deployments use
|
||||
* pairwise WEP keys with non-zero indices and for vendor
|
||||
* specific ciphers this should be validated in the driver or
|
||||
* hardware level - but 802.11i clearly specifies to use zero)
|
||||
/* IEEE802.11-2016 allows only 0 and - when using Extended Key
|
||||
* ID - 1 as index for pairwise keys.
|
||||
* @NL80211_KEY_NO_TX is only allowed for pairwise keys when
|
||||
* the driver supports Extended Key ID.
|
||||
* @NL80211_KEY_SET_TX can't be set when installing and
|
||||
* validating a key.
|
||||
*/
|
||||
if (pairwise && key_idx)
|
||||
if (params->mode == NL80211_KEY_NO_TX) {
|
||||
if (!wiphy_ext_feature_isset(&rdev->wiphy,
|
||||
NL80211_EXT_FEATURE_EXT_KEY_ID))
|
||||
return -EINVAL;
|
||||
else if (!pairwise || key_idx < 0 || key_idx > 1)
|
||||
return -EINVAL;
|
||||
} else if ((pairwise && key_idx) ||
|
||||
params->mode == NL80211_KEY_SET_TX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_AES_CMAC:
|
||||
case WLAN_CIPHER_SUITE_BIP_CMAC_256:
|
||||
|
Reference in New Issue
Block a user