FILS+FT: AP mode processing of PMKR1Name in initial MD association

Derive PMKR1Name during the FILS authentication step, verify that the
station uses matching PMKR1Name in (Re)Association Request frame, and
add RSNE[PMKR1Name] into (Re)Association Response frame when going
through FT initial mobility domain association using FILS. These steps
were missed from the initial implementation, but are needed to match the
IEEE 802.11ai requirements for explicit confirmation of the FT key
hierarchy (similarly to what is done in FT 4-way handshake when FILS is
not used).

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-03-13 17:24:29 +02:00 committed by Jouni Malinen
parent aabbdb818d
commit 3653663933
6 changed files with 51 additions and 2 deletions

View file

@ -2865,6 +2865,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
"state machine");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
hapd->iface->freq,
wpa_ie, wpa_ie_len,

View file

@ -2210,6 +2210,16 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
pmk_r0_name, WPA_PMK_NAME_LEN);
wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name);
os_memset(fils_ft, 0, sizeof(fils_ft));
res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder,
sm->addr, sm->pmk_r1_name,
use_sha384);
os_memset(pmk_r0, 0, PMK_LEN_MAX);
if (res < 0)
return -1;
wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name,
WPA_PMK_NAME_LEN);
sm->pmk_r1_name_valid = 1;
}
#endif /* CONFIG_IEEE80211R_AP */
@ -4812,6 +4822,13 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
#endif /* CONFIG_FILS */
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg)
{
if (sm)
sm->auth_alg = auth_alg;
}
#ifdef CONFIG_TESTING_OPTIONS
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,

View file

@ -473,6 +473,7 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
u8 *pos, size_t max_len,
const u8 *req_ies, size_t req_ies_len);
void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg);
int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce,
void (*cb)(void *ctx1, void *ctx2),

View file

@ -2386,10 +2386,24 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
end = pos + max_len;
if (auth_alg == WLAN_AUTH_FT) {
if (auth_alg == WLAN_AUTH_FT ||
((auth_alg == WLAN_AUTH_FILS_SK ||
auth_alg == WLAN_AUTH_FILS_SK_PFS ||
auth_alg == WLAN_AUTH_FILS_PK) &&
(sm->wpa_key_mgmt & (WPA_KEY_MGMT_FT_FILS_SHA256 |
WPA_KEY_MGMT_FT_FILS_SHA384)))) {
if (!sm->pmk_r1_name_valid) {
wpa_printf(MSG_ERROR,
"FT: PMKR1Name is not valid for Assoc Resp RSNE");
return NULL;
}
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name for Assoc Resp RSNE",
sm->pmk_r1_name, WPA_PMK_NAME_LEN);
/*
* RSN (only present if this is a Reassociation Response and
* part of a fast BSS transition)
* part of a fast BSS transition; or if this is a
* (Re)Association Response frame during an FT initial mobility
* domain association using FILS)
*/
res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
if (res < 0)

View file

@ -22,6 +22,7 @@ struct wpa_state_machine {
u8 addr[ETH_ALEN];
u8 p2p_dev_addr[ETH_ALEN];
u16 auth_alg;
enum {
WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED,

View file

@ -852,6 +852,21 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
else
sm->wpa = WPA_VERSION_WPA;
#if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS)
if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) &&
(sm->auth_alg == WLAN_AUTH_FILS_SK ||
sm->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
sm->auth_alg == WLAN_AUTH_FILS_PK) &&
(data.num_pmkid != 1 || !data.pmkid || !sm->pmk_r1_name_valid ||
os_memcmp_const(data.pmkid, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0)) {
wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
"No PMKR1Name match for FILS+FT");
return WPA_INVALID_PMKID;
}
#endif /* CONFIG_IEEE80211R_AP && CONFIG_FILS */
sm->pmksa = NULL;
for (i = 0; i < data.num_pmkid; i++) {
wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",