aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Theil <markus.theil@tu-ilmenau.de>2020-01-03 15:17:42 (GMT)
committerJouni Malinen <j@w1.fi>2020-01-05 18:34:50 (GMT)
commita79ed068719776ff06e4eb271bdeab55fdb14540 (patch)
tree4fbbac878a1ef442f32984eca07cc147dc34bdef
parent144314eaa7e09374b7f9a3708263a298e05cbfd6 (diff)
downloadhostap-a79ed068719776ff06e4eb271bdeab55fdb14540.zip
hostap-a79ed068719776ff06e4eb271bdeab55fdb14540.tar.gz
hostap-a79ed068719776ff06e4eb271bdeab55fdb14540.tar.bz2
Add no_encrypt flag for control port TX
In order to correctly encrypt rekeying frames, wpa_supplicant now checks if a PTK is currently installed and sets the corresponding encrypt option for tx_control_port(). Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
-rw-r--r--src/drivers/driver.h4
-rw-r--r--src/drivers/driver_nl80211.c11
-rw-r--r--src/rsn_supp/wpa.c8
-rw-r--r--src/rsn_supp/wpa.h1
-rw-r--r--wpa_supplicant/driver_i.h5
-rw-r--r--wpa_supplicant/ibss_rsn.c11
-rw-r--r--wpa_supplicant/wpas_glue.c9
7 files changed, 36 insertions, 13 deletions
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 09867f2..f455a2f 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -2878,6 +2878,7 @@ struct wpa_driver_ops {
* @proto: Ethertype in host byte order
* @buf: Frame payload starting from IEEE 802.1X header
* @len: Frame payload length
+ * @no_encrypt: Do not encrypt frame
*
* Returns 0 on success, else an error
*
@@ -2894,7 +2895,8 @@ struct wpa_driver_ops {
* API users will fall back to sending the frame via a normal socket.
*/
int (*tx_control_port)(void *priv, const u8 *dest,
- u16 proto, const u8 *buf, size_t len);
+ u16 proto, const u8 *buf, size_t len,
+ int no_encrypt);
/**
* hapd_send_eapol - Send an EAPOL packet (AP only)
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index f940ac5..e9f86aa 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -5093,7 +5093,8 @@ static void nl80211_teardown_ap(struct i802_bss *bss)
static int nl80211_tx_control_port(void *priv, const u8 *dest,
- u16 proto, const u8 *buf, size_t len)
+ u16 proto, const u8 *buf, size_t len,
+ int no_encrypt)
{
struct i802_bss *bss = priv;
struct nl_msg *msg;
@@ -5101,14 +5102,16 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest,
wpa_printf(MSG_DEBUG,
"nl80211: Send over control port dest=" MACSTR
- " proto=0x%04x len=%u",
- MAC2STR(dest), proto, (unsigned int) len);
+ " proto=0x%04x len=%u no_encrypt=%d",
+ MAC2STR(dest), proto, (unsigned int) len, no_encrypt);
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CONTROL_PORT_FRAME);
if (!msg ||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dest) ||
- nla_put(msg, NL80211_ATTR_FRAME, len, buf)) {
+ nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
+ (no_encrypt &&
+ nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) {
nlmsg_free(msg);
return -ENOBUFS;
}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index e9df04e..85c2840 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -3510,6 +3510,14 @@ int wpa_sm_has_ptk(struct wpa_sm *sm)
}
+int wpa_sm_has_ptk_installed(struct wpa_sm *sm)
+{
+ if (!sm)
+ return 0;
+ return sm->ptk.installed;
+}
+
+
void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
{
os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index f1fbb1b..31a8bd0 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -172,6 +172,7 @@ int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
const void *network_ctx);
void wpa_sm_drop_sa(struct wpa_sm *sm);
int wpa_sm_has_ptk(struct wpa_sm *sm);
+int wpa_sm_has_ptk_installed(struct wpa_sm *sm);
void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr);
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index d091c87..bc1373b 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -344,12 +344,13 @@ static inline int wpa_drv_sta_remove(struct wpa_supplicant *wpa_s,
static inline int wpa_drv_tx_control_port(struct wpa_supplicant *wpa_s,
const u8 *dest, u16 proto,
- const u8 *buf, size_t len)
+ const u8 *buf, size_t len,
+ int no_encrypt)
{
if (!wpa_s->driver->tx_control_port)
return -1;
return wpa_s->driver->tx_control_port(wpa_s->drv_priv, dest, proto,
- buf, len);
+ buf, len, no_encrypt);
}
static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
index 0aba8cb..f1e3ecd 100644
--- a/wpa_supplicant/ibss_rsn.c
+++ b/wpa_supplicant/ibss_rsn.c
@@ -64,13 +64,16 @@ static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf,
{
struct ibss_rsn_peer *peer = ctx;
struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s;
+ int encrypt = peer->authentication_status & IBSS_RSN_REPORTED_PTK;
- wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x "
- "len=%lu)",
- __func__, MAC2STR(dest), proto, (unsigned long) len);
+ wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR
+ " proto=0x%04x len=%lu no_encrypt=%d)",
+ __func__, MAC2STR(dest), proto, (unsigned long) len,
+ !encrypt);
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
- return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len);
+ return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
+ !encrypt);
if (wpa_s->l2)
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index b67a24e..240d610 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -112,8 +112,13 @@ static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
}
#endif /* CONFIG_TESTING_OPTIONS */
- if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
- return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len);
+ if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) {
+ int encrypt = wpa_s->wpa &&
+ wpa_sm_has_ptk_installed(wpa_s->wpa);
+
+ return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len,
+ !encrypt);
+ }
if (wpa_s->l2) {
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);