aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Shmidt <dimitrysh@google.com>2013-06-06 11:25:10 -0700
committerDmitry Shmidt <dimitrysh@google.com>2013-06-06 11:25:10 -0700
commit8bae4138a0356709720a96f3e50b4d734e532c12 (patch)
tree469665c7a3dd83523f082389bb33b5c9095d6b30 /src
parentd3e385e428c94340d89ba090e3500a085463e713 (diff)
downloadandroid_external_wpa_supplicant_8-8bae4138a0356709720a96f3e50b4d734e532c12.tar.gz
android_external_wpa_supplicant_8-8bae4138a0356709720a96f3e50b4d734e532c12.tar.bz2
android_external_wpa_supplicant_8-8bae4138a0356709720a96f3e50b4d734e532c12.zip
Accumulative patch from commit 4abc0424ef4bde2ea4fb1ba1c18619c7bc36eb02
4abc042 P2P: Automatic channel selection at re-invocation of persistent GO 8f39528 P2P: Modify wait time in INVITE state based on Tx status of INV-REQ e112764 nl80211: Use NL80211_ATTR_PEER_AID to set TDLS peer AID f8a5fd4 Synchronize with wireless-testing.git include/uapi/linux/nl80211.h 9b1693a WPS: Allow Device Password Id changes between PIN methods 1ba51ec nl80211: Add debug print for set_supp_port operation add9b7a nl80211: Ignore deauth/disassoc event from old AP eb4737f Fix ESS_DISASSOC ctrl_iface command parser b54c9ff FT: Fix TKIP group key configuration in FT protocol e78aaca Stop TKIP countermeasures on FLUSH command 3cb953e Do not set driver MAC ACL unless driver supports this 3c4ca36 hostapd: Support MAC address based access control list Change-Id: I0250e483c2992e6da8b2d1a323b7e3b8a73f9608 Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/ap/ap_drv_ops.h8
-rw-r--r--src/ap/hostapd.c70
-rw-r--r--src/ap/hostapd.h2
-rw-r--r--src/drivers/driver.h22
-rw-r--r--src/drivers/driver_nl80211.c114
-rw-r--r--src/drivers/nl80211_copy.h20
-rw-r--r--src/p2p/p2p_invitation.c6
-rw-r--r--src/rsn_supp/wpa_ft.c7
-rw-r--r--src/wps/wps_enrollee.c18
9 files changed, 255 insertions, 12 deletions
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
index ceb7e68e..70fab553 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -173,6 +173,14 @@ static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd,
return hapd->driver->sta_clear_stats(hapd->drv_priv, addr);
}
+static inline int hostapd_drv_set_acl(struct hostapd_data *hapd,
+ struct hostapd_acl_params *params)
+{
+ if (hapd->driver == NULL || hapd->driver->set_acl == NULL)
+ return 0;
+ return hapd->driver->set_acl(hapd->drv_priv, params);
+}
+
static inline int hostapd_drv_set_ap(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params)
{
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a0ac38c4..780b2e2e 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -837,6 +837,74 @@ static void hostapd_tx_queue_params(struct hostapd_iface *iface)
}
+static int hostapd_set_acl_list(struct hostapd_data *hapd,
+ struct mac_acl_entry *mac_acl,
+ int n_entries, u8 accept_acl)
+{
+ struct hostapd_acl_params *acl_params;
+ int i, err;
+
+ acl_params = os_zalloc(sizeof(*acl_params) +
+ (n_entries * sizeof(acl_params->mac_acl[0])));
+ if (!acl_params)
+ return -ENOMEM;
+
+ for (i = 0; i < n_entries; i++)
+ os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr,
+ ETH_ALEN);
+
+ acl_params->acl_policy = accept_acl;
+ acl_params->num_mac_acl = n_entries;
+
+ err = hostapd_drv_set_acl(hapd, acl_params);
+
+ os_free(acl_params);
+
+ return err;
+}
+
+
+static void hostapd_set_acl(struct hostapd_data *hapd)
+{
+ struct hostapd_config *conf = hapd->iconf;
+ int err;
+ u8 accept_acl;
+
+ if (hapd->iface->drv_max_acl_mac_addrs == 0)
+ return;
+ if (!(conf->bss->num_accept_mac || conf->bss->num_deny_mac))
+ return;
+
+ if (conf->bss->macaddr_acl == DENY_UNLESS_ACCEPTED) {
+ if (conf->bss->num_accept_mac) {
+ accept_acl = 1;
+ err = hostapd_set_acl_list(hapd, conf->bss->accept_mac,
+ conf->bss->num_accept_mac,
+ accept_acl);
+ if (err) {
+ wpa_printf(MSG_DEBUG, "Failed to set accept acl");
+ return;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+ }
+ } else if (conf->bss->macaddr_acl == ACCEPT_UNLESS_DENIED) {
+ if (conf->bss->num_deny_mac) {
+ accept_acl = 0;
+ err = hostapd_set_acl_list(hapd, conf->bss->deny_mac,
+ conf->bss->num_deny_mac,
+ accept_acl);
+ if (err) {
+ wpa_printf(MSG_DEBUG, "Failed to set deny acl");
+ return;
+ }
+ } else {
+ wpa_printf(MSG_DEBUG, "Mismatch between ACL Policy & Accept/deny lists file");
+ }
+ }
+}
+
+
static int setup_interface(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
@@ -962,6 +1030,8 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
ap_list_init(iface);
+ hostapd_set_acl(hapd);
+
if (hostapd_driver_commit(hapd) < 0) {
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
"configuration", __func__);
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 9a3bb686..55f6dd84 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -233,6 +233,8 @@ struct hostapd_iface {
const u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
+ unsigned int drv_max_acl_mac_addrs;
+
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index c27544b9..0f92b189 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -906,6 +906,8 @@ struct wpa_driver_capa {
#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008
unsigned int probe_resp_offloads;
+ unsigned int max_acl_mac_addrs;
+
/**
* extended_capa - extended capabilities in driver/device
*
@@ -966,6 +968,16 @@ struct hostapd_freq_params {
int bandwidth;
};
+struct mac_address {
+ u8 addr[ETH_ALEN];
+};
+
+struct hostapd_acl_params {
+ u8 acl_policy;
+ unsigned int num_mac_acl;
+ struct mac_address mac_acl[0];
+};
+
enum wpa_driver_if_type {
/**
* WPA_IF_STATION - Station mode interface
@@ -1596,6 +1608,16 @@ struct wpa_driver_ops {
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
/**
+ * set_acl - Set ACL in AP mode
+ * @priv: Private driver interface data
+ * @params: Parameters to configure ACL
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is used only for the drivers which support MAC address ACL.
+ */
+ int (*set_acl)(void *priv, struct hostapd_acl_params *params);
+
+ /**
* hapd_init - Initialize driver interface (hostapd only)
* @hapd: Pointer to hostapd context
* @params: Configuration for the driver wrapper
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 3d16330c..cbc80e3b 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -225,7 +225,9 @@ struct wpa_driver_nl80211_data {
struct nl_cb *nl_cb;
u8 auth_bssid[ETH_ALEN];
+ u8 auth_attempt_bssid[ETH_ALEN];
u8 bssid[ETH_ALEN];
+ u8 prev_bssid[ETH_ALEN];
int associated;
u8 ssid[32];
size_t ssid_len;
@@ -376,6 +378,15 @@ static int is_p2p_interface(enum nl80211_iftype nlmode)
}
+static void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
+{
+ if (drv->associated)
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ drv->associated = 0;
+ os_memset(drv->bssid, 0, ETH_ALEN);
+}
+
+
struct nl80211_bss_info_arg {
struct wpa_driver_nl80211_data *drv;
struct wpa_scan_results *res;
@@ -1053,6 +1064,7 @@ static void mlme_event_auth(struct wpa_driver_nl80211_data *drv,
}
os_memcpy(drv->auth_bssid, mgmt->sa, ETH_ALEN);
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
os_memcpy(event.auth.peer, mgmt->sa, ETH_ALEN);
event.auth.auth_type = le_to_host16(mgmt->u.auth.auth_alg);
@@ -1132,6 +1144,7 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
drv->associated = 1;
os_memcpy(drv->bssid, mgmt->sa, ETH_ALEN);
+ os_memcpy(drv->prev_bssid, mgmt->sa, ETH_ALEN);
os_memset(&event, 0, sizeof(event));
if (len > 24 + sizeof(mgmt->u.assoc_resp)) {
@@ -1183,8 +1196,10 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
}
drv->associated = 1;
- if (addr)
+ if (addr) {
os_memcpy(drv->bssid, nla_data(addr), ETH_ALEN);
+ os_memcpy(drv->prev_bssid, drv->bssid, ETH_ALEN);
+ }
if (req_ie) {
event.assoc_info.req_ies = nla_data(req_ie);
@@ -1231,7 +1246,7 @@ static void mlme_event_disconnect(struct wpa_driver_nl80211_data *drv,
}
wpa_printf(MSG_DEBUG, "nl80211: Disconnect event");
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&data, 0, sizeof(data));
if (reason)
data.deauth_info.reason_code = nla_get_u16(reason);
@@ -1400,6 +1415,22 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
if (len >= 24) {
bssid = mgmt->bssid;
+ if ((drv->capa.flags & WPA_DRIVER_FLAGS_SME) &&
+ !drv->associated &&
+ os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->auth_attempt_bssid, ETH_ALEN) != 0 &&
+ os_memcmp(bssid, drv->prev_bssid, ETH_ALEN) == 0) {
+ /*
+ * Avoid issues with some roaming cases where
+ * disconnection event for the old AP may show up after
+ * we have started connection with the new AP.
+ */
+ wpa_printf(MSG_DEBUG, "nl80211: Ignore deauth/disassoc event from old AP " MACSTR " when already authenticating with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
+ return;
+ }
+
if (drv->associated != 0 &&
os_memcmp(bssid, drv->bssid, ETH_ALEN) != 0 &&
os_memcmp(bssid, drv->auth_bssid, ETH_ALEN) != 0) {
@@ -1415,7 +1446,7 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
}
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(&event, 0, sizeof(event));
/* Note: Same offset for Reason Code in both frame subtypes */
@@ -2877,6 +2908,10 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
capa->max_match_sets =
nla_get_u8(tb[NL80211_ATTR_MAX_MATCH_SETS]);
+ if (tb[NL80211_ATTR_MAC_ACL_MAX])
+ capa->max_acl_mac_addrs =
+ nla_get_u8(tb[NL80211_ATTR_MAC_ACL_MAX]);
+
wiphy_info_supported_iftypes(info, tb[NL80211_ATTR_SUPPORTED_IFTYPES]);
wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]);
wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]);
@@ -4841,7 +4876,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
int reason_code)
{
wpa_printf(MSG_DEBUG, "%s(reason_code=%d)", __func__, reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
drv->ignore_next_local_disconnect = 0;
/* Disconnect command doesn't need BSSID - it uses cached value */
return wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
@@ -4857,7 +4892,7 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
return wpa_driver_nl80211_disconnect(drv, reason_code);
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code);
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
if (drv->nlmode == NL80211_IFTYPE_ADHOC)
return nl80211_leave_ibss(drv);
return wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
@@ -4925,8 +4960,12 @@ static int wpa_driver_nl80211_authenticate(
is_retry = drv->retry_auth;
drv->retry_auth = 0;
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
os_memset(drv->auth_bssid, 0, ETH_ALEN);
+ if (params->bssid)
+ os_memcpy(drv->auth_attempt_bssid, params->bssid, ETH_ALEN);
+ else
+ os_memset(drv->auth_attempt_bssid, 0, ETH_ALEN);
/* FIX: IBSS mode */
nlmode = params->p2p ?
NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION;
@@ -5837,6 +5876,60 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble,
}
+static int wpa_driver_nl80211_set_acl(void *priv,
+ struct hostapd_acl_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct nlattr *acl;
+ unsigned int i;
+ int ret = 0;
+
+ if (!(drv->capa.max_acl_mac_addrs))
+ return -ENOTSUP;
+
+ if (params->num_mac_acl > drv->capa.max_acl_mac_addrs)
+ return -ENOTSUP;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ wpa_printf(MSG_DEBUG, "nl80211: Set %s ACL (num_mac_acl=%u)",
+ params->acl_policy ? "Accept" : "Deny", params->num_mac_acl);
+
+ nl80211_cmd(drv, msg, 0, NL80211_CMD_SET_MAC_ACL);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+
+ NLA_PUT_U32(msg, NL80211_ATTR_ACL_POLICY, params->acl_policy ?
+ NL80211_ACL_POLICY_DENY_UNLESS_LISTED :
+ NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED);
+
+ acl = nla_nest_start(msg, NL80211_ATTR_MAC_ADDRS);
+ if (acl == NULL)
+ goto nla_put_failure;
+
+ for (i = 0; i < params->num_mac_acl; i++)
+ NLA_PUT(msg, i + 1, ETH_ALEN, params->mac_acl[i].addr);
+
+ nla_nest_end(msg, acl);
+
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ msg = NULL;
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)",
+ ret, strerror(-ret));
+ }
+
+nla_put_failure:
+ nlmsg_free(msg);
+
+ return ret;
+}
+
+
static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_ap_params *params)
{
@@ -6172,6 +6265,9 @@ static int wpa_driver_nl80211_sta_add(void *priv,
params->listen_interval);
NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
params->listen_interval);
+ } else if (params->aid && (params->flags & WPA_STA_TDLS_PEER)) {
+ wpa_printf(MSG_DEBUG, " * peer_aid=%u", params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_PEER_AID, params->aid);
}
if (params->ht_capabilities) {
wpa_hexdump(MSG_DEBUG, " * ht_capabilities",
@@ -7444,7 +7540,7 @@ static int wpa_driver_nl80211_associate(
return wpa_driver_nl80211_connect(drv, params);
}
- drv->associated = 0;
+ nl80211_mark_disconnected(drv);
msg = nlmsg_alloc();
if (!msg)
@@ -7758,6 +7854,9 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized)
struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
+ wpa_printf(MSG_DEBUG, "nl80211: Set supplicant port %sauthorized for "
+ MACSTR, authorized ? "" : "un", MAC2STR(drv->bssid));
+
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
@@ -9936,6 +10035,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.set_supp_port = wpa_driver_nl80211_set_supp_port,
.set_country = wpa_driver_nl80211_set_country,
.set_ap = wpa_driver_nl80211_set_ap,
+ .set_acl = wpa_driver_nl80211_set_acl,
.if_add = wpa_driver_nl80211_if_add,
.if_remove = driver_nl80211_if_remove,
.send_mlme = driver_nl80211_send_mlme,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index d1e48b5e..32b060ea 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -27,6 +27,8 @@
#include <linux/types.h>
+#define NL80211_GENL_NAME "nl80211"
+
/**
* DOC: Station handling
*
@@ -1429,6 +1431,11 @@ enum nl80211_commands {
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
* the connection should have increased reliability (u16).
*
+ * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
+ * This is similar to @NL80211_ATTR_STA_AID but with a difference of being
+ * allowed to be used with the first @NL80211_CMD_SET_STATION command to
+ * update a TDLS peer STA entry.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1727,6 +1734,8 @@ enum nl80211_attrs {
NL80211_ATTR_CRIT_PROT_ID,
NL80211_ATTR_MAX_CRIT_PROT_DURATION,
+ NL80211_ATTR_PEER_AID,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1991,6 +2000,10 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
* non-peer STA
+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
+ * Contains a nested array of signal strength attributes (u8, dBm)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
* @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute
*/
@@ -2020,6 +2033,8 @@ enum nl80211_sta_info {
NL80211_STA_INFO_NONPEER_PM,
NL80211_STA_INFO_RX_BYTES64,
NL80211_STA_INFO_TX_BYTES64,
+ NL80211_STA_INFO_CHAIN_SIGNAL,
+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
/* keep last */
__NL80211_STA_INFO_AFTER_LAST,
@@ -2637,6 +2652,10 @@ enum nl80211_meshconf_params {
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
* implement an MPM which handles peer allocation and state.
*
+ * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication
+ * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).
+ * Default is no authentication method required.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -2650,6 +2669,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_USERSPACE_AMPE,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
NL80211_MESH_SETUP_USERSPACE_MPM,
+ NL80211_MESH_SETUP_AUTH_PROTOCOL,
/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index e3e760dc..6b3dafba 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -492,11 +492,7 @@ void p2p_invitation_req_cb(struct p2p_data *p2p, int success)
* channel.
*/
p2p_set_state(p2p, P2P_INVITE);
-#ifdef ANDROID_P2P
- p2p_set_timeout(p2p, 0, 350000);
-#else
- p2p_set_timeout(p2p, 0, 100000);
-#endif
+ p2p_set_timeout(p2p, 0, success ? 350000 : 100000);
}
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 6b7fa91b..3a40c96f 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -596,6 +596,13 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem,
}
wpa_hexdump_key(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
+ if (sm->group_cipher == WPA_CIPHER_TKIP) {
+ /* Swap Tx/Rx keys for Michael MIC */
+ u8 tmp[8];
+ os_memcpy(tmp, gtk + 16, 8);
+ os_memcpy(gtk + 16, gtk + 24, 8);
+ os_memcpy(gtk + 24, tmp, 8);
+ }
if (wpa_sm_set_key(sm, alg, broadcast_ether_addr, keyidx, 0,
gtk_elem + 3, rsc_len, gtk, keylen) < 0) {
wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to the "
diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c
index 1af43c2d..27c554f3 100644
--- a/src/wps/wps_enrollee.c
+++ b/src/wps/wps_enrollee.c
@@ -842,6 +842,24 @@ static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id)
return 0;
}
+#ifdef CONFIG_P2P
+ if ((id == DEV_PW_DEFAULT &&
+ wps->dev_pw_id == DEV_PW_REGISTRAR_SPECIFIED) ||
+ (id == DEV_PW_REGISTRAR_SPECIFIED &&
+ wps->dev_pw_id == DEV_PW_DEFAULT)) {
+ /*
+ * Common P2P use cases indicate whether the PIN is from the
+ * client or GO using Device Password Id in M1/M2 in a way that
+ * does not look fully compliant with WSC specification. Anyway,
+ * this is deployed and needs to be allowed, so ignore changes
+ * between Registrar-Specified and Default PIN.
+ */
+ wpa_printf(MSG_DEBUG, "WPS: Allow PIN Device Password ID "
+ "change");
+ return 0;
+ }
+#endif /* CONFIG_P2P */
+
wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
"ID from %u to %u", wps->dev_pw_id, id);