From db76aa64f1a292561eccc8a1ca93849034d1aa9f Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 28 Dec 2013 11:40:23 +0200 Subject: [PATCH] Fix PeerKey 4-way handshake The earlier changes to buffer EAPOL frames when not associated to avoid race conditions (especially commit 3ab35a660364dc68eaebfc0df6130071bbee6be5 but maybe something even before that) broke PeerKey 4-way handshake. Fix this by using a separate check before the race condition workaround to process PeerKey 4-way handshake EAPOL-Key messages differently. Signed-hostap: Jouni Malinen --- src/rsn_supp/wpa.c | 21 +++++++++++++++++++++ src/rsn_supp/wpa.h | 8 ++++++++ wpa_supplicant/wpa_supplicant.c | 10 ++++++++++ 3 files changed, 39 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index d26a7a8b0..a294730df 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2710,3 +2710,24 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) return 0; } #endif /* CONFIG_WNM */ + + +#ifdef CONFIG_PEERKEY +int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + struct wpa_peerkey *peerkey; + + for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { + if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) + break; + } + + if (!peerkey) + return 0; + + wpa_sm_rx_eapol(sm, src_addr, buf, len); + + return 1; +} +#endif /* CONFIG_PEERKEY */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index db7f0db8c..e189a585f 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -306,11 +306,19 @@ static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, #ifdef CONFIG_PEERKEY int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer); +int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len); #else /* CONFIG_PEERKEY */ static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) { return -1; } + +static inline int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + return 0; +} #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211R diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 095ab97c1..50436cb91 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -2328,6 +2328,16 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); +#ifdef CONFIG_PEERKEY + if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid && + wpa_s->current_ssid->peerkey && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) { + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key"); + return; + } +#endif /* CONFIG_PEERKEY */ + if (wpa_s->wpa_state < WPA_ASSOCIATED || (wpa_s->last_eapol_matches_bssid && #ifdef CONFIG_AP