[PATCH] wpa_supplicant: support Marvell roaming offload

Amitkumar Karwar akarwar at marvell.com
Fri Jul 8 03:11:02 PDT 2016


From: lihz <lihz at marvell.com>

This patch adds function to download pmk/pmk_r0/pmk_r0_name for roaming
offload and Marvell OUI vendor event handler.

Signed-off-by: Huazeng Li <lihz at marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar at marvell.com>
---
 src/common/mrvl-vendor.h           | 28 ++++++++++++++++++
 src/drivers/driver_nl80211.c       | 54 ++++++++++++++++++++++++++++++++++
 src/drivers/driver_nl80211_event.c | 60 ++++++++++++++++++++++++++++++++++++++
 src/drivers/drivers.mak            |  3 ++
 src/drivers/drivers.mk             |  3 ++
 src/rsn_supp/wpa_ft.c              | 16 ++++++++++
 wpa_supplicant/defconfig           |  3 ++
 7 files changed, 167 insertions(+)
 create mode 100644 src/common/mrvl-vendor.h

diff --git a/src/common/mrvl-vendor.h b/src/common/mrvl-vendor.h
new file mode 100644
index 0000000..df5426f
--- /dev/null
+++ b/src/common/mrvl-vendor.h
@@ -0,0 +1,28 @@
+/*
+ * Marvell OUI and vendor specific assignments
+ */
+#ifndef MRVL_VENDOR_H
+#define MRVL_VENDOR_H
+
+#define OUI_MRVL 0x005043
+#define MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY 0x2
+
+#define MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_OFFLOAD 0x10001
+#define MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH 0x10002
+
+enum mrvl_wlan_vendor_attr_roam_auth {
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
+	/* keep last */
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST,
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX =
+	MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
+};
+#endif /* MRVL_VENDOR_H */
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index b2b27a7..f9de8de 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -27,6 +27,7 @@
 #include "eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/mrvl-vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "l2_packet/l2_packet.h"
@@ -2641,6 +2642,35 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv,
 }
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+static int issue_key_mgmt_set_pmk_mrvl(struct wpa_driver_nl80211_data *drv,
+				       const u8 *key, size_t key_len)
+{
+	struct nl_msg *msg;
+	int ret;
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD))
+		return 0;
+
+	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
+	if (!msg || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MRVL) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY) ||
+	    nla_put(msg, NL80211_ATTR_VENDOR_DATA, key_len, key)) {
+		nl80211_nlmsg_clear(msg);
+		nlmsg_free(msg);
+		return -1;
+	}
+	ret = send_and_recv_msgs(drv, msg, NULL, (void *)-1);
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Key management set key failed: ret=%d (%s)",
+			   ret, strerror(-ret));
+	}
+
+	return ret;
+}
+#endif /* CONFIG_DRIVER_NL80211_MRVL */
 
 static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 				      enum wpa_alg alg, const u8 *addr,
@@ -2680,6 +2710,18 @@ static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
 	}
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+	if (alg == WPA_ALG_PMK &&
+	    (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
+		wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
+			   __func__);
+		ret = issue_key_mgmt_set_pmk_mrvl(drv, key, key_len);
+		return ret;
+	}
+#endif /* CONFIG_DRIVER_NL80211_MRVL */
+#endif /* CONFIG_IEEE80211R */
+
 	if (alg == WPA_ALG_NONE) {
 		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
 		if (!msg)
@@ -4938,6 +4980,18 @@ static int wpa_driver_nl80211_try_connect(
 	}
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+	if (params->req_key_mgmt_offload && params->psk &&
+	    (params->key_mgmt_suite == WPA_KEY_MGMT_PSK ||
+	     params->key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 ||
+	     params->key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) {
+		wpa_printf(MSG_DEBUG, "nl80211: Key management set PMK");
+		ret = issue_key_mgmt_set_pmk_mrvl(drv, params->psk, 32);
+		if (ret)
+			return ret;
+	}
+#endif /* CONFIG_DRIVER_NL80211_MRVL */
+
 	wpa_printf(MSG_DEBUG, "nl80211: Connect (ifindex=%d)", drv->ifindex);
 	msg = nl80211_drv_msg(drv, 0, NL80211_CMD_CONNECT);
 	if (!msg)
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 762e3ac..3d3ab6b 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -15,6 +15,7 @@
 #include "utils/eloop.h"
 #include "common/qca-vendor.h"
 #include "common/qca-vendor-attr.h"
+#include "common/mrvl-vendor.h"
 #include "common/ieee802_11_defs.h"
 #include "common/ieee802_11_common.h"
 #include "driver_nl80211.h"
@@ -1946,6 +1947,62 @@ static void nl80211_vendor_event_qca(struct wpa_driver_nl80211_data *drv,
 	}
 }
 
+static void mrvl_nl80211_key_mgmt_auth(struct wpa_driver_nl80211_data *drv,
+				       const u8 *data, size_t len)
+{
+	struct nlattr *tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX + 1];
+	u8 *bssid;
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Key management roam+auth vendor event received");
+
+	if (nla_parse(tb, MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX,
+		      (struct nlattr *)data, len, NULL) ||
+	    !tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID] ||
+	    nla_len(tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]) != ETH_ALEN ||
+	    !tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE] ||
+	    !tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED])
+		return;
+
+	bssid = nla_data(tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID]);
+	wpa_printf(MSG_DEBUG, "  * roam BSSID " MACSTR, MAC2STR(bssid));
+
+	mlme_event_connect(drv, NL80211_CMD_ROAM, NULL,
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE],
+			   NULL,
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK],
+			   tb[MRVL_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS]);
+}
+
+static void nl80211_vendor_event_mrvl(struct wpa_driver_nl80211_data *drv,
+				      u32 subcmd, u8 *data, size_t len)
+{
+	switch (subcmd) {
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+	case MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_OFFLOAD:
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Received MRVL vendor event %u", subcmd);
+		if (*data)
+			drv->capa.flags |= WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD;
+		else
+			drv->capa.flags &= ~WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD;
+		break;
+	case MRVL_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH:
+		mrvl_nl80211_key_mgmt_auth(drv, data, len);
+		break;
+#endif
+	default:
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Ignore unsupported MRVL vendor event %u",
+			   subcmd);
+		break;
+	}
+}
 
 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr **tb)
@@ -1985,6 +2042,9 @@ static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 	case OUI_QCA:
 		nl80211_vendor_event_qca(drv, subcmd, data, len);
 		break;
+	case OUI_MRVL:
+		nl80211_vendor_event_mrvl(drv, subcmd, data, len);
+		break;
 	default:
 		wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
 		break;
diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
index c6d3f81..4a4f3e2 100644
--- a/src/drivers/drivers.mak
+++ b/src/drivers/drivers.mak
@@ -32,6 +32,9 @@ DRV_OBJS += ../src/drivers/driver_nl80211_scan.o
 ifdef CONFIG_DRIVER_NL80211_QCA
 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_QCA
 endif
+ifdef CONFIG_DRIVER_NL80211_MRVL
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_MRVL
+endif
 NEED_SME=y
 NEED_AP_MLME=y
 NEED_NETLINK=y
diff --git a/src/drivers/drivers.mk b/src/drivers/drivers.mk
index c6fe4c2..d84dee7 100644
--- a/src/drivers/drivers.mk
+++ b/src/drivers/drivers.mk
@@ -28,6 +28,9 @@ DRV_OBJS += src/drivers/driver_nl80211_scan.c
 ifdef CONFIG_DRIVER_NL80211_QCA
 DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_QCA
 endif
+ifdef CONFIG_DRIVER_NL80211_MRVL
+DRV_CFLAGS += -DCONFIG_DRIVER_NL80211_MRVL
+endif
 NEED_SME=y
 NEED_AP_MLME=y
 NEED_NETLINK=y
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 205793e..5a6fb1d 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -23,6 +23,9 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 {
 	u8 ptk_name[WPA_PMK_NAME_LEN];
 	const u8 *anonce = key->key_nonce;
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+	u8 pmkr0_pmkr0name[48] = { 0 };
+#endif /* CONFIG_DRIVER_NL80211_MRVL */
 
 	if (sm->xxkey_len == 0) {
 		wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
@@ -37,6 +40,19 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, PMK_LEN);
 	wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name",
 		    sm->pmk_r0_name, WPA_PMK_NAME_LEN);
+#ifdef CONFIG_DRIVER_NL80211_MRVL
+	os_memcpy(pmkr0_pmkr0name, (u8 *)sm->pmk_r0, PMK_LEN);
+	os_memcpy(pmkr0_pmkr0name + PMK_LEN, (u8 *)sm->pmk_r0_name,
+		  WPA_PMK_NAME_LEN);
+	if (wpa_sm_set_key(sm, WPA_ALG_PMK, NULL, 0, 1, NULL,
+			   0, pmkr0_pmkr0name,
+			   (PMK_LEN + WPA_PMK_NAME_LEN)) < 0) {
+		wpa_printf(MSG_WARNING, "FT: Failed to set
+			   PMKR0/PMKR0NAME to the driver");
+		return -1;
+	}
+#endif /* CONFIG_DRIVER_NL80211_MRVL */
+
 	wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_name, sm->r1kh_id,
 			  sm->own_addr, sm->pmk_r1, sm->pmk_r1_name);
 	wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, PMK_LEN);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 1d05198..e2179e5 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -34,6 +34,9 @@ CONFIG_DRIVER_NL80211=y
 # QCA vendor extensions to nl80211
 #CONFIG_DRIVER_NL80211_QCA=y
 
+# MRVL vendor extensions to nl80211
+#CONFIG_DRIVER_NL80211_MRVL=y
+
 # driver_nl80211.c requires libnl. If you are compiling it yourself
 # you may need to point hostapd to your version of libnl.
 #
-- 
1.9.1




More information about the Hostap mailing list