2017-02-21 12:38:02

by Johannes Berg

[permalink] [raw]
Subject: [RFC v2 1/2] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK

From: Eliad Peller <[email protected]>

Let drivers advertise support for station-mode 4-way handshake
offloading with a new NL80211_EXT_FEATURE_4WAY_HANDSHAKE_OFFLOAD_STA
flag.

Add a new NL80211_ATTR_PMK attribute that might be passed as part
of NL80211_CMD_CONNECT command, and contain the PSK (which is the
PMK, hence the name.)

The driver/device is assumed to handle the 4-way handshake by
itself in this case (including key derivations, etc.), instead
of relying on the supplicant.

This patch is somewhat based on this one (by Vladimir Kondratiev):
https://patchwork.kernel.org/patch/1309561/.

Signed-off-by: Vladimir Kondratiev <[email protected]>
Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/linux/ieee80211.h | 1 +
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 9 +++++++++
net/wireless/nl80211.c | 8 ++++++++
4 files changed, 20 insertions(+)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 6ea381c98aae..2049e983a994 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2357,6 +2357,7 @@ enum ieee80211_sa_query_action {
#define WLAN_MAX_KEY_LEN 32

#define WLAN_PMKID_LEN 16
+#define WLAN_PMK_LEN 32

#define WLAN_OUI_WFA 0x506f9a
#define WLAN_OUI_TYPE_WFA_P2P 9
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 86c12f85fb53..4ca968927d60 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -643,6 +643,7 @@ struct survey_info {
* @wep_keys: static WEP keys, if not NULL points to an array of
* CFG80211_MAX_WEP_KEYS WEP keys
* @wep_tx_key: key index (0..3) of the default TX static WEP key
+ * @psk: PSK (for devices supporting 4-way-handshake offload)
*/
struct cfg80211_crypto_settings {
u32 wpa_versions;
@@ -656,6 +657,7 @@ struct cfg80211_crypto_settings {
bool control_port_no_encrypt;
struct key_params *wep_keys;
int wep_tx_key;
+ const u8 *psk;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9a499b15cfbc..bb5e1904a107 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2012,6 +2012,9 @@ enum nl80211_commands {
* u32 attribute with an &enum nl80211_timeout_reason value. This is used,
* e.g., with %NL80211_CMD_CONNECT event.
*
+ * @NL80211_ATTR_PMK: PSK for offloaded 4-Way Handshake. Relevant only
+ * with %NL80211_CMD_CONNECT (for WPA/WPA2-PSK networks).
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2423,6 +2426,8 @@ enum nl80211_attrs {

NL80211_ATTR_TIMEOUT_REASON,

+ NL80211_ATTR_PMK,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -4759,6 +4764,9 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_CQM_RSSI_LIST: With this driver the
* %NL80211_ATTR_CQM_RSSI_THOLD attribute accepts a list of zero or more
* RSSI threshold values to monitor rather than exactly one threshold.
+ * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device supports doing 4-way
+ * handshake with PSK in station mode (PSK is passed as part of the connect
+ * and associate commands).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4778,6 +4786,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED,
NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
NL80211_EXT_FEATURE_CQM_RSSI_LIST,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d516527fcb8e..494b50b3eb71 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -410,6 +410,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.len = sizeof(struct nl80211_bss_select_rssi_adjust)
},
[NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 },
+ [NL80211_ATTR_PMK] = { .len = WLAN_PMK_LEN },
};

/* policy for the key attributes */
@@ -8039,6 +8040,13 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
memcpy(settings->akm_suites, data, len);
}

+ if (info->attrs[NL80211_ATTR_PMK]) {
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
+ return -EINVAL;
+ settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
+ }
+
return 0;
}

--
2.9.3


2017-02-24 08:08:20

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X



On 21-2-2017 13:37, Johannes Berg wrote:
> From: Avraham Stern <[email protected]>
>
> Add API for setting the PMK to the driver. For FT support, allow
> setting also the PMK-R0 Name.
>
> This can be used by drivers that support 4-Way handshake offload
> while IEEE802.1X authentication is managed by upper layers.
>
> Signed-off-by: Avraham Stern <[email protected]>
> Signed-off-by: Johannes Berg <[email protected]>
> ---
> include/linux/ieee80211.h | 3 ++
> include/net/cfg80211.h | 27 ++++++++++++
> include/uapi/linux/nl80211.h | 24 ++++++++++-
> net/wireless/core.c | 5 +++
> net/wireless/nl80211.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
> net/wireless/rdev-ops.h | 25 +++++++++++
> net/wireless/trace.h | 60 +++++++++++++++++++++++++++
> 7 files changed, 241 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> index 2049e983a994..fb1f533e75b3 100644
> --- a/include/linux/ieee80211.h
> +++ b/include/linux/ieee80211.h
> @@ -2356,8 +2356,11 @@ enum ieee80211_sa_query_action {
>
> #define WLAN_MAX_KEY_LEN 32
>
> +#define WLAN_PMK_NAME_LEN 16
> #define WLAN_PMKID_LEN 16
> +#define WLAN_PMK_LEN_EAP_LEAP 16
> #define WLAN_PMK_LEN 32
> +#define WLAN_PMK_LEN_SUITE_B_192 48
>
> #define WLAN_OUI_WFA 0x506f9a
> #define WLAN_OUI_TYPE_WFA_P2P 9
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 4ca968927d60..a68c6db6ac55 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -2507,6 +2507,23 @@ struct cfg80211_nan_func {
> };
>
> /**
> + * struct cfg80211_pmk_conf - PMK configuration
> + *
> + * @aa: authenticator address
> + * @pmk_len: PMK length in bytes.
> + * @pmk: the PMK material
> + * @pmk_r0_name: PMK-R0 Name. NULL if not applicable (i.e., the PMK
> + * is not PMK-R0). When pmk_r0_name is not NULL, the pmk field
> + * holds PMK-R0.
> + */
> +struct cfg80211_pmk_conf {
> + const u8 *aa;
> + u8 pmk_len;
> + const u8 *pmk;
> + const u8 *pmk_r0_name;
> +};
> +
> +/**
> * struct cfg80211_ops - backend description for wireless configuration
> *
> * This struct is registered by fullmac card drivers and/or wireless stacks
> @@ -2823,6 +2840,11 @@ struct cfg80211_nan_func {
> * All other parameters must be ignored.
> *
> * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
> + *
> + * @set_pmk: configure the PMK to be used for offloaded 4-Way handshake.
> + * (invoked with the wireless_dev mutex held)
> + * @del_pmk: delete the previously configured PMK for the given authenticator.
> + * (invoked with the wireless_dev mutex held)
> */
> struct cfg80211_ops {
> int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
> @@ -3111,6 +3133,11 @@ struct cfg80211_ops {
> int (*set_multicast_to_unicast)(struct wiphy *wiphy,
> struct net_device *dev,
> const bool enabled);
> +
> + int (*set_pmk)(struct wiphy *wiphy, struct net_device *dev,
> + const struct cfg80211_pmk_conf *conf);
> + int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
> + const u8 *aa);

Minor nit, but prefer clr_pmk to clear the pmk.

> };
>
> /*
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index bb5e1904a107..89295fc2336b 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -901,6 +901,14 @@
> * does not result in a change for the current association. Currently,
> * only the %NL80211_ATTR_IE data is used and updated with this command.
> *
> + * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
> + * for the given authenticator address (specified with &NL80211_ATTR_MAC).
> + * When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
> + * PMK-R0, otherwise it specifies the PMK.
> + * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
> + * configured PMK for the authenticator address identified by
> + * &NL80211_ATTR_MAC.

Maybe better to indicate it is for 802.1X. Here also preference for
NL80211_CMD_CLR_PMK.

> + *
> * @NL80211_CMD_MAX: highest used command number
> * @__NL80211_CMD_AFTER_LAST: internal use
> */
> @@ -1100,6 +1108,9 @@ enum nl80211_commands {
>
> NL80211_CMD_UPDATE_CONNECT_PARAMS,
>
> + NL80211_CMD_SET_PMK,
> + NL80211_CMD_DEL_PMK,
> +
> /* add new commands above here */
>
> /* used to define NL80211_CMD_MAX below */
> @@ -2012,8 +2023,12 @@ enum nl80211_commands {
> * u32 attribute with an &enum nl80211_timeout_reason value. This is used,
> * e.g., with %NL80211_CMD_CONNECT event.
> *
> - * @NL80211_ATTR_PMK: PSK for offloaded 4-Way Handshake. Relevant only
> - * with %NL80211_CMD_CONNECT (for WPA/WPA2-PSK networks).
> + * @NL80211_ATTR_PMK: PMK for offloaded 4-Way Handshake. Relevant with
> + * %NL80211_CMD_CONNECT (for WPA/WPA2-PSK networks) when PSK is used, or
> + * with %NL80211_CMD_SET_PMK when 802.1X authentication is used.
> + * When &NL80211_ATTR_PMKR0_NAME is specified, this attribute specifies
> + * the PMK-R0.
> + * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
> *
> * @NUM_NL80211_ATTR: total number of nl80211_attrs available
> * @NL80211_ATTR_MAX: highest attribute number currently defined
> @@ -2427,6 +2442,7 @@ enum nl80211_attrs {
> NL80211_ATTR_TIMEOUT_REASON,
>
> NL80211_ATTR_PMK,
> + NL80211_ATTR_PMKR0_NAME,
>
> /* add attributes here, update the policy in nl80211.c */
>
> @@ -4767,6 +4783,9 @@ enum nl80211_feature_flags {
> * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device supports doing 4-way
> * handshake with PSK in station mode (PSK is passed as part of the connect
> * and associate commands).
> + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X: Device supports doing 4-way
> + * handshake with 802.1X in station mode (needs to pass EAP frames to
> + * the host and accept the set_pmk/del_pmk commands).
> *
> * @NUM_NL80211_EXT_FEATURES: number of extended features.
> * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
> @@ -4787,6 +4806,7 @@ enum nl80211_ext_feature_index {
> NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
> NL80211_EXT_FEATURE_CQM_RSSI_LIST,
> NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
> + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,

So do we need this flag. Is the fact that the driver implements the
set_pmk and del_pmk (or clr_pmk) callbacks not sufficient provided they
are listed in the "supported commands" message of wiphy dump (not in
this patch). Which reminds me, is "supported commands" no longer
preferred because that list does not seem complete?

Regards,
Arend

2017-02-21 12:38:02

by Johannes Berg

[permalink] [raw]
Subject: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X

From: Avraham Stern <[email protected]>

Add API for setting the PMK to the driver. For FT support, allow
setting also the PMK-R0 Name.

This can be used by drivers that support 4-Way handshake offload
while IEEE802.1X authentication is managed by upper layers.

Signed-off-by: Avraham Stern <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/linux/ieee80211.h | 3 ++
include/net/cfg80211.h | 27 ++++++++++++
include/uapi/linux/nl80211.h | 24 ++++++++++-
net/wireless/core.c | 5 +++
net/wireless/nl80211.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 25 +++++++++++
net/wireless/trace.h | 60 +++++++++++++++++++++++++++
7 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 2049e983a994..fb1f533e75b3 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2356,8 +2356,11 @@ enum ieee80211_sa_query_action {

#define WLAN_MAX_KEY_LEN 32

+#define WLAN_PMK_NAME_LEN 16
#define WLAN_PMKID_LEN 16
+#define WLAN_PMK_LEN_EAP_LEAP 16
#define WLAN_PMK_LEN 32
+#define WLAN_PMK_LEN_SUITE_B_192 48

#define WLAN_OUI_WFA 0x506f9a
#define WLAN_OUI_TYPE_WFA_P2P 9
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4ca968927d60..a68c6db6ac55 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2507,6 +2507,23 @@ struct cfg80211_nan_func {
};

/**
+ * struct cfg80211_pmk_conf - PMK configuration
+ *
+ * @aa: authenticator address
+ * @pmk_len: PMK length in bytes.
+ * @pmk: the PMK material
+ * @pmk_r0_name: PMK-R0 Name. NULL if not applicable (i.e., the PMK
+ * is not PMK-R0). When pmk_r0_name is not NULL, the pmk field
+ * holds PMK-R0.
+ */
+struct cfg80211_pmk_conf {
+ const u8 *aa;
+ u8 pmk_len;
+ const u8 *pmk;
+ const u8 *pmk_r0_name;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2823,6 +2840,11 @@ struct cfg80211_nan_func {
* All other parameters must be ignored.
*
* @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
+ *
+ * @set_pmk: configure the PMK to be used for offloaded 4-Way handshake.
+ * (invoked with the wireless_dev mutex held)
+ * @del_pmk: delete the previously configured PMK for the given authenticator.
+ * (invoked with the wireless_dev mutex held)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3111,6 +3133,11 @@ struct cfg80211_ops {
int (*set_multicast_to_unicast)(struct wiphy *wiphy,
struct net_device *dev,
const bool enabled);
+
+ int (*set_pmk)(struct wiphy *wiphy, struct net_device *dev,
+ const struct cfg80211_pmk_conf *conf);
+ int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *aa);
};

/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index bb5e1904a107..89295fc2336b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -901,6 +901,14 @@
* does not result in a change for the current association. Currently,
* only the %NL80211_ATTR_IE data is used and updated with this command.
*
+ * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
+ * for the given authenticator address (specified with &NL80211_ATTR_MAC).
+ * When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
+ * PMK-R0, otherwise it specifies the PMK.
+ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
+ * configured PMK for the authenticator address identified by
+ * &NL80211_ATTR_MAC.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1100,6 +1108,9 @@ enum nl80211_commands {

NL80211_CMD_UPDATE_CONNECT_PARAMS,

+ NL80211_CMD_SET_PMK,
+ NL80211_CMD_DEL_PMK,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -2012,8 +2023,12 @@ enum nl80211_commands {
* u32 attribute with an &enum nl80211_timeout_reason value. This is used,
* e.g., with %NL80211_CMD_CONNECT event.
*
- * @NL80211_ATTR_PMK: PSK for offloaded 4-Way Handshake. Relevant only
- * with %NL80211_CMD_CONNECT (for WPA/WPA2-PSK networks).
+ * @NL80211_ATTR_PMK: PMK for offloaded 4-Way Handshake. Relevant with
+ * %NL80211_CMD_CONNECT (for WPA/WPA2-PSK networks) when PSK is used, or
+ * with %NL80211_CMD_SET_PMK when 802.1X authentication is used.
+ * When &NL80211_ATTR_PMKR0_NAME is specified, this attribute specifies
+ * the PMK-R0.
+ * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2427,6 +2442,7 @@ enum nl80211_attrs {
NL80211_ATTR_TIMEOUT_REASON,

NL80211_ATTR_PMK,
+ NL80211_ATTR_PMKR0_NAME,

/* add attributes here, update the policy in nl80211.c */

@@ -4767,6 +4783,9 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK: Device supports doing 4-way
* handshake with PSK in station mode (PSK is passed as part of the connect
* and associate commands).
+ * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X: Device supports doing 4-way
+ * handshake with 802.1X in station mode (needs to pass EAP frames to
+ * the host and accept the set_pmk/del_pmk commands).
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4787,6 +4806,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI,
NL80211_EXT_FEATURE_CQM_RSSI_LIST,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 76e664144c8e..65f4b4d4a805 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -691,6 +691,11 @@ int wiphy_register(struct wiphy *wiphy)
(wiphy->bss_select_support & ~(BIT(__NL80211_BSS_SELECT_ATTR_AFTER_LAST) - 2))))
return -EINVAL;

+ if (WARN_ON(wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X) &&
+ (!rdev->ops->set_pmk || !rdev->ops->del_pmk)))
+ return -EINVAL;
+
if (wiphy->addresses)
memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 494b50b3eb71..f67098559c3b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -12075,6 +12075,90 @@ static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
return rdev_set_multicast_to_unicast(rdev, dev, enabled);
}

+static int nl80211_set_pmk(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_pmk_conf pmk_conf = {};
+ int ret;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION &&
+ wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+ return -EOPNOTSUPP;
+
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_MAC] || !info->attrs[NL80211_ATTR_PMK])
+ return -EINVAL;
+
+ wdev_lock(wdev);
+ if (!wdev->current_bss) {
+ ret = -ENOTCONN;
+ goto out;
+ }
+
+ pmk_conf.aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ if (memcmp(pmk_conf.aa, wdev->current_bss->pub.bssid, ETH_ALEN)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pmk_conf.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]);
+ pmk_conf.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]);
+ if (pmk_conf.pmk_len != WLAN_PMK_LEN &&
+ pmk_conf.pmk_len != WLAN_PMK_LEN_SUITE_B_192) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (info->attrs[NL80211_ATTR_PMKR0_NAME]) {
+ int r0_name_len = nla_len(info->attrs[NL80211_ATTR_PMKR0_NAME]);
+
+ if (r0_name_len != WLAN_PMK_NAME_LEN) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pmk_conf.pmk_r0_name =
+ nla_data(info->attrs[NL80211_ATTR_PMKR0_NAME]);
+ }
+
+ ret = rdev_set_pmk(rdev, dev, &pmk_conf);
+out:
+ wdev_unlock(wdev);
+ return ret;
+}
+
+static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ const u8 *aa;
+ int ret;
+
+ if (wdev->iftype != NL80211_IFTYPE_STATION &&
+ wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+ return -EOPNOTSUPP;
+
+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X))
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_MAC])
+ return -EINVAL;
+
+ wdev_lock(wdev);
+ aa = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ ret = rdev_del_pmk(rdev, dev, aa);
+ wdev_unlock(wdev);
+
+ return ret;
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -12950,6 +13034,21 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_SET_PMK,
+ .doit = nl80211_set_pmk,
+ .policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_DEL_PMK,
+ .doit = nl80211_del_pmk,
+ .policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+
};

static struct genl_family nl80211_fam __ro_after_init = {
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index f2baf5921091..06698552f1f2 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1165,4 +1165,29 @@ rdev_set_coalesce(struct cfg80211_registered_device *rdev,
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
+
+static inline int rdev_set_pmk(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_pmk_conf *pmk_conf)
+{
+ int ret = -EOPNOTSUPP;
+
+ trace_rdev_set_pmk(&rdev->wiphy, dev, pmk_conf);
+ if (rdev->ops->set_pmk)
+ ret = rdev->ops->set_pmk(&rdev->wiphy, dev, pmk_conf);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
+ struct net_device *dev, const u8 *aa)
+{
+ int ret = -EOPNOTSUPP;
+
+ trace_rdev_del_pmk(&rdev->wiphy, dev, aa);
+ if (rdev->ops->del_pmk)
+ ret = rdev->ops->del_pmk(&rdev->wiphy, dev, aa);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index fd55786f0462..47a5e8d4b113 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2252,6 +2252,66 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
);

+TRACE_EVENT(rdev_set_pmk,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_pmk_conf *pmk_conf),
+
+ TP_ARGS(wiphy, netdev, pmk_conf),
+
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(aa)
+ __field(u8, pmk_len)
+ __field(u8, pmk_r0_name_len)
+ __dynamic_array(u8, pmk, pmk_conf->pmk_len)
+ __dynamic_array(u8, pmk_r0_name, WLAN_PMK_NAME_LEN)
+ ),
+
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(aa, pmk_conf->aa);
+ __entry->pmk_len = pmk_conf->pmk_len;
+ __entry->pmk_r0_name_len =
+ pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0;
+ memcpy(__get_dynamic_array(pmk), pmk_conf->pmk,
+ pmk_conf->pmk_len);
+ memcpy(__get_dynamic_array(pmk_r0_name), pmk_conf->pmk_r0_name,
+ pmk_conf->pmk_r0_name ? WLAN_PMK_NAME_LEN : 0);
+ ),
+
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
+ "pmk_len=%u, pmk: %s pmk_r0_name: %s", WIPHY_PR_ARG,
+ NETDEV_PR_ARG, MAC_PR_ARG(aa), __entry->pmk_len,
+ __print_array(__get_dynamic_array(pmk),
+ __get_dynamic_array_len(pmk), 1),
+ __entry->pmk_r0_name_len ?
+ __print_array(__get_dynamic_array(pmk_r0_name),
+ __get_dynamic_array_len(pmk_r0_name), 1) : "")
+);
+
+TRACE_EVENT(rdev_del_pmk,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *aa),
+
+ TP_ARGS(wiphy, netdev, aa),
+
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(aa)
+ ),
+
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(aa, aa);
+ ),
+
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa))
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
--
2.9.3

2017-02-21 14:51:57

by Jouni Malinen

[permalink] [raw]
Subject: Re: [RFC v2 1/2] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK

On Tue, Feb 21, 2017 at 01:37:57PM +0100, Johannes Berg wrote:
> Add a new NL80211_ATTR_PMK attribute that might be passed as part
> of NL80211_CMD_CONNECT command, and contain the PSK (which is the
> PMK, hence the name.)

> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> +#define WLAN_PMK_LEN 32

> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> struct cfg80211_crypto_settings {
> + const u8 *psk;

> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> + [NL80211_ATTR_PMK] = { .len = WLAN_PMK_LEN },

While the existing WPA2-PSK cases all use 32 octet PMK, there are also
48 octet PMKs in use with EAP (Suite B 192-bit level and FILS with
SHA384). Patch 2/2 seemed to look at the PMK length as well.. Should the
same be done already with 1/2 so that the PSK case is separately
validating exact match with 32 octets in length for PMK = PSK while the
other cases allow longer PMK as well?

I never remember how the attr policy .len works, so that may already be
the implicit behavior here, but it would be clearer to be more explicit
about the possible lengths of the WLAN_ATTR_PMK and not assume that
WLAN_PMK_LEN definition is the only possible option.

--
Jouni Malinen PGP id EFC895FA

2017-02-21 14:47:30

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v2 1/2] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK


> The .len verifies that it's at least that long. We're thus ignoring
> additional bytes in the PSK case if they're present, which I suppose
> we should fix by checking the exact length in the code separately.
>
IOW, I'll add this:

--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8044,6 +8044,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
if (!wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
return -EINVAL;
+ if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
+ return -EINVAL;
settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
}


johannes

2017-02-23 10:26:08

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 1/2] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK



On 21-2-2017 15:47, Johannes Berg wrote:
>
>> The .len verifies that it's at least that long. We're thus ignoring
>> additional bytes in the PSK case if they're present, which I suppose
>> we should fix by checking the exact length in the code separately.
>>

libnl seems to have the notion of min_len and max_len in its policy
definition, but the kernel does not so .len is actually min_len indeed.

> IOW, I'll add this:
>
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -8044,6 +8044,8 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
> if (!wiphy_ext_feature_isset(&rdev->wiphy,
> NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK))
> return -EINVAL;
> + if (nla_len(info->attrs[NL80211_ATTR_PMK]) != WLAN_PMK_LEN)
> + return -EINVAL;

Makes sense.

Regards,
Arend

> settings->psk = nla_data(info->attrs[NL80211_ATTR_PMK]);
> }
>
>
> johannes
>

2017-02-21 14:46:13

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v2 1/2] cfg80211: support 4-way handshake offloading for WPA/WPA2-PSK


> While the existing WPA2-PSK cases all use 32 octet PMK, there are
> also
> 48 octet PMKs in use with EAP (Suite B 192-bit level and FILS with
> SHA384). Patch 2/2 seemed to look at the PMK length as well.. Should
> the same be done already with 1/2 so that the PSK case is separately
> validating exact match with 32 octets in length for PMK = PSK while
> the other cases allow longer PMK as well?
>
> I never remember how the attr policy .len works, so that may already
> be the implicit behavior here, but it would be clearer to be more
> explicit about the possible lengths of the WLAN_ATTR_PMK and not
> assume that WLAN_PMK_LEN definition is the only possible option.

The .len verifies that it's at least that long. We're thus ignoring
additional bytes in the PSK case if they're present, which I suppose we
should fix by checking the exact length in the code separately.

johannes

2017-03-02 09:00:02

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X


> > + int (*del_pmk)(struct wiphy *wiphy, struct
> > net_device *dev,
> > +    const u8 *aa);
>
> Minor nit, but prefer clr_pmk to clear the pmk.

Why? You don't have "the PMK" that you can clear, you have "a PMK" (for
the network) and after deleting it you don't have it anymore. You don't
have a "cleared PMK" afterwards, you just don't have any. I think the
delete makes more sense?

> > + * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the
> > previously
> > + * configured PMK for the authenticator address identified
> > by
> > + * &NL80211_ATTR_MAC.
>
> Maybe better to indicate it is for 802.1X.

I guess that makes sense.

> > + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
>
> So do we need this flag. Is the fact that the driver implements the
> set_pmk and del_pmk (or clr_pmk) callbacks not sufficient provided
> they are listed in the "supported commands" message of wiphy dump
> (not in this patch). Which reminds me, is "supported commands" no
> longer preferred because that list does not seem complete?

It's complicated... We've kinda naturally gravitated towards extended
feature flags because they're so easy to handle now (only need to
define the bit) - and with mac80211 in the picture, relying on the
handlers only often didn't work, so it requires extra code in the CMD()
advertising - and anyway it already requires extra code there unlike
the feature flags...

So overall - while this isn't stated policy (yet?) - I think we prefer
the feature bits.

johannes

2017-03-31 12:39:48

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X



On 31-3-2017 13:50, Johannes Berg wrote:
> On Tue, 2017-03-28 at 12:50 +0200, Arend Van Spriel wrote:
>>
>> So looking at wpa_supplicant RFC patches I see that it now diverts
>> driver_nl80211_set_key() for ALG_PMK case to the new api. So why not
>> extending CMD_NEW_KEY to support ALG_PMK?
>
> I don't really care what the supplicant does, but IMHO having
> completely different types of keys in the same API isn't a good idea.
> We'd have to invent (a) cipher suite(s), or new attributes, to even
> encapsulate that in netlink - and the usage is completely different
> etc.

Ok. Just wondering. I am ok with the proposal with the addition of
authorized flag in connect event. So do you expect these to come as
non-rfc patches any time soon?

Regards,
Arend

2017-03-02 10:59:41

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X



On 2-3-2017 9:59, Johannes Berg wrote:
>
>>> + int (*del_pmk)(struct wiphy *wiphy, struct
>>> net_device *dev,
>>> + const u8 *aa);
>>
>> Minor nit, but prefer clr_pmk to clear the pmk.
>
> Why? You don't have "the PMK" that you can clear, you have "a PMK" (for
> the network) and after deleting it you don't have it anymore. You don't
> have a "cleared PMK" afterwards, you just don't have any. I think the
> delete makes more sense?

Ah. I just looked at set_pmk and felt its counter-part should therefor
be clr_pmk. Following your logic should it be add_pmk iso set_pmk?

>>> + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X,
>>
>> So do we need this flag. Is the fact that the driver implements the
>> set_pmk and del_pmk (or clr_pmk) callbacks not sufficient provided
>> they are listed in the "supported commands" message of wiphy dump
>> (not in this patch). Which reminds me, is "supported commands" no
>> longer preferred because that list does not seem complete?
>
> It's complicated... We've kinda naturally gravitated towards extended
> feature flags because they're so easy to handle now (only need to
> define the bit) - and with mac80211 in the picture, relying on the
> handlers only often didn't work, so it requires extra code in the CMD()
> advertising - and anyway it already requires extra code there unlike
> the feature flags...
>
> So overall - while this isn't stated policy (yet?) - I think we prefer
> the feature bits.

I see. Glad they worked out that way ;-)

Regards,
Arend

2017-03-31 12:42:23

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X

On Fri, 2017-03-31 at 14:39 +0200, Arend Van Spriel wrote:
>
> Ok. Just wondering. I am ok with the proposal with the addition of
> authorized flag in connect event. So do you expect these to come as
> non-rfc patches any time soon?
>

Hmm. I need to find time to look at it, but I'll be travelling next
week for netconf/netdev.

If you wanted to pick up anything here I won't stop you :)

johannes

2017-03-31 18:40:29

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X



On 31-3-2017 14:42, Johannes Berg wrote:
> On Fri, 2017-03-31 at 14:39 +0200, Arend Van Spriel wrote:
>>
>> Ok. Just wondering. I am ok with the proposal with the addition of
>> authorized flag in connect event. So do you expect these to come as
>> non-rfc patches any time soon?
>>
>
> Hmm. I need to find time to look at it, but I'll be travelling next
> week for netconf/netdev.

ok.

> If you wanted to pick up anything here I won't stop you :)

I am tempted, but it is weekend so I will see how I feel on monday :-p

Regards,
Arend

2017-03-31 11:50:04

by Johannes Berg

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X

On Tue, 2017-03-28 at 12:50 +0200, Arend Van Spriel wrote:
>
> So looking at wpa_supplicant RFC patches I see that it now diverts
> driver_nl80211_set_key() for ALG_PMK case to the new api. So why not
> extending CMD_NEW_KEY to support ALG_PMK?

I don't really care what the supplicant does, but IMHO having
completely different types of keys in the same API isn't a good idea.
We'd have to invent (a) cipher suite(s), or new attributes, to even
encapsulate that in netlink - and the usage is completely different
etc.

johannes

2017-03-28 10:51:14

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [RFC v2 2/2] cfg80211: support 4-way handshake offloading for 802.1X



On 21-2-2017 13:37, Johannes Berg wrote:
> From: Avraham Stern <[email protected]>
>
> Add API for setting the PMK to the driver. For FT support, allow
> setting also the PMK-R0 Name.
>
> This can be used by drivers that support 4-Way handshake offload
> while IEEE802.1X authentication is managed by upper layers.

So looking at wpa_supplicant RFC patches I see that it now diverts
driver_nl80211_set_key() for ALG_PMK case to the new api. So why not
extending CMD_NEW_KEY to support ALG_PMK?

Regards,
Arend