[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