From a79ed068719776ff06e4eb271bdeab55fdb14540 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Fri, 3 Jan 2020 16:17:42 +0100 Subject: [PATCH] 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 --- src/drivers/driver.h | 4 +++- src/drivers/driver_nl80211.c | 11 +++++++---- src/rsn_supp/wpa.c | 8 ++++++++ src/rsn_supp/wpa.h | 1 + wpa_supplicant/driver_i.h | 5 +++-- wpa_supplicant/ibss_rsn.c | 11 +++++++---- wpa_supplicant/wpas_glue.c | 9 +++++++-- 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 09867f2cd..f455a2f90 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 f940ac552..e9f86aabd 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 e9df04e11..85c28401b 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 f1fbb1bb5..31a8bd0c6 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 d091c8761..bc1373bbb 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 0aba8cb04..f1e3ecdb2 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 b67a24e53..240d61099 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);