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>
This commit is contained in:
parent
144314eaa7
commit
a79ed06871
7 changed files with 36 additions and 13 deletions
|
@ -2878,6 +2878,7 @@ struct wpa_driver_ops {
|
||||||
* @proto: Ethertype in host byte order
|
* @proto: Ethertype in host byte order
|
||||||
* @buf: Frame payload starting from IEEE 802.1X header
|
* @buf: Frame payload starting from IEEE 802.1X header
|
||||||
* @len: Frame payload length
|
* @len: Frame payload length
|
||||||
|
* @no_encrypt: Do not encrypt frame
|
||||||
*
|
*
|
||||||
* Returns 0 on success, else an error
|
* 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.
|
* API users will fall back to sending the frame via a normal socket.
|
||||||
*/
|
*/
|
||||||
int (*tx_control_port)(void *priv, const u8 *dest,
|
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)
|
* hapd_send_eapol - Send an EAPOL packet (AP only)
|
||||||
|
|
|
@ -5093,7 +5093,8 @@ static void nl80211_teardown_ap(struct i802_bss *bss)
|
||||||
|
|
||||||
|
|
||||||
static int nl80211_tx_control_port(void *priv, const u8 *dest,
|
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 i802_bss *bss = priv;
|
||||||
struct nl_msg *msg;
|
struct nl_msg *msg;
|
||||||
|
@ -5101,14 +5102,16 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest,
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Send over control port dest=" MACSTR
|
"nl80211: Send over control port dest=" MACSTR
|
||||||
" proto=0x%04x len=%u",
|
" proto=0x%04x len=%u no_encrypt=%d",
|
||||||
MAC2STR(dest), proto, (unsigned int) len);
|
MAC2STR(dest), proto, (unsigned int) len, no_encrypt);
|
||||||
|
|
||||||
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CONTROL_PORT_FRAME);
|
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_CONTROL_PORT_FRAME);
|
||||||
if (!msg ||
|
if (!msg ||
|
||||||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
|
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
|
||||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dest) ||
|
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);
|
nlmsg_free(msg);
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
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);
|
os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
|
||||||
|
|
|
@ -172,6 +172,7 @@ int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
|
||||||
const void *network_ctx);
|
const void *network_ctx);
|
||||||
void wpa_sm_drop_sa(struct wpa_sm *sm);
|
void wpa_sm_drop_sa(struct wpa_sm *sm);
|
||||||
int wpa_sm_has_ptk(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);
|
void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr);
|
||||||
|
|
||||||
|
|
|
@ -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,
|
static inline int wpa_drv_tx_control_port(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *dest, u16 proto,
|
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)
|
if (!wpa_s->driver->tx_control_port)
|
||||||
return -1;
|
return -1;
|
||||||
return wpa_s->driver->tx_control_port(wpa_s->drv_priv, dest, proto,
|
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,
|
static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s,
|
||||||
|
|
|
@ -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 ibss_rsn_peer *peer = ctx;
|
||||||
struct wpa_supplicant *wpa_s = peer->ibss_rsn->wpa_s;
|
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 "
|
wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR
|
||||||
"len=%lu)",
|
" proto=0x%04x len=%lu no_encrypt=%d)",
|
||||||
__func__, MAC2STR(dest), proto, (unsigned long) len);
|
__func__, MAC2STR(dest), proto, (unsigned long) len,
|
||||||
|
!encrypt);
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
|
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)
|
if (wpa_s->l2)
|
||||||
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
||||||
|
|
|
@ -112,8 +112,13 @@ static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_TESTING_OPTIONS */
|
#endif /* CONFIG_TESTING_OPTIONS */
|
||||||
|
|
||||||
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT)
|
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) {
|
||||||
return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len);
|
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) {
|
if (wpa_s->l2) {
|
||||||
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
|
||||||
|
|
Loading…
Reference in a new issue