Note that the implementation is not complete as it is missing support for the FT wrapped data (which is optional for the station, but must be supported by the AP in case the station included it). Signed-off-by: Ilan Peer <ilan.peer@xxxxxxxxx> --- src/ap/ieee802_11.c | 56 +++++++++++++++++++++++++++++++++++--------- src/ap/wpa_auth.h | 8 +++++++ src/ap/wpa_auth_ft.c | 14 +++++------ 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 5371d45b13..79c7a4c2fb 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2669,7 +2669,7 @@ static struct wpabuf *pasn_get_wrapped_data(struct hostapd_data *hapd, static int pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta, - struct rsn_pmksa_cache_entry *pmksa, + const u8 *cached_pmk, size_t cached_pmk_len, struct wpa_pasn_params_data *pasn_data, struct wpabuf *wrapped_data, struct wpabuf *secret) @@ -2682,7 +2682,7 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta, os_memset(pmk, 0, sizeof(pmk)); pmk_len = 0; - if (!pmksa) + if (!cached_pmk || !cached_pmk_len) wpa_printf(MSG_DEBUG, "PASN: no valid PMKSA entry"); if (sta->pasn->akmp == WPA_KEY_MGMT_PASN) { @@ -2690,11 +2690,11 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta, pmk_len = WPA_PASN_PMK_LEN; os_memcpy(pmk, pasn_default_pmk, sizeof(pasn_default_pmk)); - } else if (pmksa) { + } else if (cached_pmk && cached_pmk_len) { wpa_printf(MSG_DEBUG, "PASN: using PMKSA entry"); - pmk_len = pmksa->pmk_len; - os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len); + pmk_len = cached_pmk_len; + os_memcpy(pmk, cached_pmk, cached_pmk_len); } else { switch (sta->pasn->akmp) { #ifdef CONFIG_SAE @@ -2885,6 +2885,12 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta, struct wpa_ie_data rsn_data; struct wpa_pasn_params_data pasn_params; struct rsn_pmksa_cache_entry *pmksa = NULL; + const u8 *cached_pmk = NULL; + size_t cached_pmk_len = 0; +#ifdef CONFIG_IEEE80211R_AP + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len; +#endif /* CONFIG_IEEE80211R_AP */ struct wpabuf *wrapped_data = NULL, *secret = NULL; int *groups = hapd->conf->pasn_groups; int default_groups[] = { 19, 0 }; @@ -3071,17 +3077,45 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta, } if (rsn_data.num_pmkid) { - wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry"); + if (wpa_key_mgmt_ft(sta->pasn->akmp)) { +#ifdef CONFIG_IEEE80211R_AP + wpa_printf(MSG_DEBUG, "PASN: FT: Fetch PMK R1"); + + ret = wpa_ft_fetch_pmk_r1(hapd->wpa_auth, sta->addr, + rsn_data.pmkid, + pmk_r1, &pmk_r1_len, + NULL, + NULL, NULL, NULL, + NULL, NULL, NULL); + if (ret) { + wpa_printf(MSG_DEBUG, + "PASN: FT: failed getting PMK R1"); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto send_resp; + } + cached_pmk = pmk_r1; + cached_pmk_len = pmk_r1_len; +#else + wpa_printf(MSG_DEBUG, "PASN: FT: not supported"); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto send_resp; +#endif /* CONFIG_IEEE80211R_AP */ + } else { + wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry"); - pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, - rsn_data.pmkid); + pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, + rsn_data.pmkid); + if (pmksa) { + cached_pmk = pmksa->pmk; + cached_pmk_len = pmksa->pmk_len; + } + } } else { wpa_printf(MSG_DEBUG, "PASN: No PMKID specified"); - pmksa = NULL; } - ret = pasn_derive_keys(hapd, sta, pmksa, &pasn_params, - wrapped_data, secret); + ret = pasn_derive_keys(hapd, sta, cached_pmk, cached_pmk_len, + &pasn_params, wrapped_data, secret); if (ret) { wpa_printf(MSG_DEBUG, "PASN: failed to derive keys"); status = WLAN_STATUS_UNSPECIFIED_FAILURE; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index ed5bd9bd8e..ca6ebdb6cb 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -434,6 +434,14 @@ void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); void wpa_ft_deinit(struct wpa_authenticator *wpa_auth); void wpa_ft_sta_deinit(struct wpa_state_machine *sm); +int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, + const u8 *spa, const u8 *pmk_r1_name, + u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise, + struct vlan_description *vlan, + const u8 **identity, size_t *identity_len, + const u8 **radius_cui, size_t *radius_cui_len, + int *session_timeout); + #endif /* CONFIG_IEEE80211R_AP */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index aea0197674..3ac65ca34a 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -1471,13 +1471,13 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, } -static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, - const u8 *spa, const u8 *pmk_r1_name, - u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise, - struct vlan_description *vlan, - const u8 **identity, size_t *identity_len, - const u8 **radius_cui, size_t *radius_cui_len, - int *session_timeout) +int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, + const u8 *spa, const u8 *pmk_r1_name, + u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise, + struct vlan_description *vlan, + const u8 **identity, size_t *identity_len, + const u8 **radius_cui, size_t *radius_cui_len, + int *session_timeout) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r1_sa *r1; -- 2.17.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap