From: Benjamin Berg <benjamin.berg@xxxxxxxxxxxxx> The PMK-R0 is usually cached, but it may happen that an item was removed from the cache already for a client that is still associated. When this happens, simply recalculate the PMK-R0 for immediate use in the pull request without caching the result. Signed-off-by: Benjamin Berg <benjamin.berg@xxxxxxxxxxxxx> --- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_ft.c | 42 +++++++++++++++++++++++++++++++++++++++--- src/ap/wpa_auth_glue.c | 15 +++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index cd70912..7ea2ae5 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -224,6 +224,7 @@ struct wpa_auth_callbacks { size_t data_len); #ifdef CONFIG_IEEE80211R struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + struct wpa_state_machine * (*get_sta)(void *ctx, const u8 *sta_addr); int (*send_ft_action)(void *ctx, const u8 *dst, const u8 *data, size_t data_len); int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie, diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index a6e277d..c45ff89 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -60,6 +60,15 @@ wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) } +static struct wpa_state_machine * +wpa_ft_get_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr) +{ + if (wpa_auth->cb.get_sta == NULL) + return NULL; + return wpa_auth->cb.get_sta(wpa_auth->cb.ctx, sta_addr); +} + + static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, u8 *tspec_ie, size_t tspec_ielen) @@ -1405,6 +1414,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, const u8 *src_addr, const u8 *data, size_t data_len) { + struct wpa_state_machine *sm; struct ft_r0kh_r1kh_pull_frame f; const u8 *crypt; u8 *plain; @@ -1412,6 +1422,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, u8 r1kh_key[16]; struct ft_r0kh_r1kh_resp_frame resp, r; u8 pmk_r0[PMK_LEN]; + u8 pmk_r0_name[WPA_PMK_NAME_LEN]; int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); @@ -1470,9 +1481,34 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN); if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0, &pairwise) < 0) { - wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " - "PMK-R1 pull"); - return -1; + + wpa_printf(MSG_DEBUG, "FT: PMK-R0 not in cache, " + "re-calculating on the fly."); + + /* No cache entry exists, derive the PMK-R0 again. */ + sm = wpa_ft_get_sta(wpa_auth, f.s1kh_id); + if (sm == NULL) { + wpa_printf(MSG_DEBUG, "FT: Could not find station to " + "calculate PMK-R0 for."); + return -1; + } + + wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, + sm->wpa_auth->conf.ssid, + sm->wpa_auth->conf.ssid_len, + sm->wpa_auth->conf.mobility_domain, + sm->wpa_auth->conf.r0_key_holder, + sm->wpa_auth->conf.r0_key_holder_len, + sm->addr, + pmk_r0, pmk_r0_name); + + if (os_memcmp_const(f.pmk_r0_name, pmk_r0_name, + WPA_PMK_NAME_LEN)) { + wpa_printf(MSG_DEBUG, "FT: Newly generated PMKR0Name " + "does not match the PMK-R1 pull request."); + return -1; + } + pairwise = sm->pairwise; } wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id, diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 90e39a4..4981c49 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -565,6 +565,20 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) } +static struct wpa_state_machine * +hostapd_wpa_auth_get_sta(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_get_sta(hapd, addr); + if (sta != NULL) + return sta->wpa_sm; + else + return NULL; +} + + static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) { @@ -624,6 +638,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifdef CONFIG_IEEE80211R cb.send_ft_action = hostapd_wpa_auth_send_ft_action; cb.add_sta = hostapd_wpa_auth_add_sta; + cb.get_sta = hostapd_wpa_auth_get_sta; cb.add_tspec = hostapd_wpa_auth_add_tspec; #endif /* CONFIG_IEEE80211R */ hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); -- 2.9.3 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap