[PATCH 4/6] FT: Re-calculate PMK-R0 for pull requests if value is not cached.
Benjamin Berg
benjamin at sipsolutions.net
Mon Sep 19 08:47:42 PDT 2016
From: Benjamin Berg <benjamin.berg at open-mesh.com>
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 at open-mesh.com>
---
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
More information about the Hostap
mailing list