AP: Support PASN with FT key derivation

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@intel.com>
This commit is contained in:
Ilan Peer 2020-12-16 13:01:04 +02:00 committed by Jouni Malinen
parent 5c65ad6c0b
commit 2eb2fb8bd4
3 changed files with 59 additions and 18 deletions

View file

@ -2811,7 +2811,7 @@ static struct wpabuf * pasn_get_wrapped_data(struct hostapd_data *hapd,
static int static int
pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta, 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 wpa_pasn_params_data *pasn_data,
struct wpabuf *wrapped_data, struct wpabuf *wrapped_data,
struct wpabuf *secret) struct wpabuf *secret)
@ -2824,7 +2824,7 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
os_memset(pmk, 0, sizeof(pmk)); os_memset(pmk, 0, sizeof(pmk));
pmk_len = 0; pmk_len = 0;
if (!pmksa) if (!cached_pmk || !cached_pmk_len)
wpa_printf(MSG_DEBUG, "PASN: No valid PMKSA entry"); wpa_printf(MSG_DEBUG, "PASN: No valid PMKSA entry");
if (sta->pasn->akmp == WPA_KEY_MGMT_PASN) { if (sta->pasn->akmp == WPA_KEY_MGMT_PASN) {
@ -2832,11 +2832,11 @@ pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
pmk_len = WPA_PASN_PMK_LEN; pmk_len = WPA_PASN_PMK_LEN;
os_memcpy(pmk, pasn_default_pmk, sizeof(pasn_default_pmk)); 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"); wpa_printf(MSG_DEBUG, "PASN: Using PMKSA entry");
pmk_len = pmksa->pmk_len; pmk_len = cached_pmk_len;
os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len); os_memcpy(pmk, cached_pmk, cached_pmk_len);
} else { } else {
switch (sta->pasn->akmp) { switch (sta->pasn->akmp) {
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
@ -2983,6 +2983,12 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
struct wpa_ie_data rsn_data; struct wpa_ie_data rsn_data;
struct wpa_pasn_params_data pasn_params; struct wpa_pasn_params_data pasn_params;
struct rsn_pmksa_cache_entry *pmksa = NULL; 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; struct wpabuf *wrapped_data = NULL, *secret = NULL;
const int *groups = hapd->conf->pasn_groups; const int *groups = hapd->conf->pasn_groups;
static const int default_groups[] = { 19, 0 }; static const int default_groups[] = { 19, 0 };
@ -3145,17 +3151,44 @@ static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
} }
if (rsn_data.num_pmkid) { if (rsn_data.num_pmkid) {
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 /* CONFIG_IEEE80211R_AP */
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"); wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry");
pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr, pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
rsn_data.pmkid); rsn_data.pmkid);
if (pmksa) {
cached_pmk = pmksa->pmk;
cached_pmk_len = pmksa->pmk_len;
}
}
} else { } else {
wpa_printf(MSG_DEBUG, "PASN: No PMKID specified"); wpa_printf(MSG_DEBUG, "PASN: No PMKID specified");
pmksa = NULL;
} }
ret = pasn_derive_keys(hapd, sta, pmksa, &pasn_params, ret = pasn_derive_keys(hapd, sta, cached_pmk, cached_pmk_len,
wrapped_data, secret); &pasn_params, wrapped_data, secret);
if (ret) { if (ret) {
wpa_printf(MSG_DEBUG, "PASN: Failed to derive keys"); wpa_printf(MSG_DEBUG, "PASN: Failed to derive keys");
status = WLAN_STATUS_UNSPECIFIED_FAILURE; status = WLAN_STATUS_UNSPECIFIED_FAILURE;

View file

@ -468,6 +468,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_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
void wpa_ft_deinit(struct wpa_authenticator *wpa_auth); void wpa_ft_deinit(struct wpa_authenticator *wpa_auth);
void wpa_ft_sta_deinit(struct wpa_state_machine *sm); 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 */ #endif /* CONFIG_IEEE80211R_AP */
void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);

View file

@ -1473,7 +1473,7 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
} }
static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
const u8 *spa, const u8 *pmk_r1_name, const u8 *spa, const u8 *pmk_r1_name,
u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise, u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
struct vlan_description *vlan, struct vlan_description *vlan,