FILS: Fix PTK rekeying

The PMK and PMKID information from FILS ERP and FILS PMKSA caching needs
to be stored within struct wpa_state_machine for PTK to work. Without
this, PTK derivation would fail and attempt to go through rekeying would
result in disconnection. Furthermore, wpa_rekey_ptk() timer needs to be
started at the completion of FILS association since the place where it
was done for non-FILS cases at the end of 4-way handshake is not reached
when FILS authentication is used.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
Jouni Malinen 2019-04-17 22:52:23 +03:00 committed by Jouni Malinen
parent c8931afe24
commit a40bd06e9b
4 changed files with 51 additions and 6 deletions

View file

@ -1821,6 +1821,8 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
} }
sta->fils_erp_pmkid_set = 0; sta->fils_erp_pmkid_set = 0;
wpa_auth_add_fils_pmk_pmkid(sta->wpa_sm, pmk, pmk_len,
sta->fils_erp_pmkid);
if (!hapd->conf->disable_pmksa_caching && if (!hapd->conf->disable_pmksa_caching &&
wpa_auth_pmksa_add2( wpa_auth_pmksa_add2(
hapd->wpa_auth, sta->addr, hapd->wpa_auth, sta->addr,

View file

@ -1236,6 +1236,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
sta->eapol_sm->portValid = TRUE; sta->eapol_sm->portValid = TRUE;
if (sta->eapol_sm->eap) if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap); eap_sm_notify_cached(sta->eapol_sm->eap);
wpa_auth_set_ptk_rekey_timer(sta->wpa_sm);
return; return;
} }
#endif /* CONFIG_FILS */ #endif /* CONFIG_FILS */

View file

@ -320,6 +320,19 @@ static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
} }
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
{
if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
MACSTR " (%d seconds)", MAC2STR(sm->addr),
sm->wpa_auth->conf.wpa_ptk_rekey);
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
wpa_rekey_ptk, sm->wpa_auth, sm);
}
}
static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
{ {
if (sm->pmksa == ctx) if (sm->pmksa == ctx)
@ -2124,6 +2137,21 @@ SM_STATE(WPA_PTK, PTKSTART)
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"RSN: No KCK available to derive PMKID for message 1/4"); "RSN: No KCK available to derive PMKID for message 1/4");
pmkid = NULL; pmkid = NULL;
#ifdef CONFIG_FILS
} else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
if (sm->pmkid_set) {
wpa_hexdump(MSG_DEBUG,
"RSN: Message 1/4 PMKID from FILS/ERP",
sm->pmkid, PMKID_LEN);
os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
sm->pmkid, PMKID_LEN);
} else {
/* No PMKID available */
wpa_printf(MSG_DEBUG,
"RSN: No FILS/ERP PMKID available for message 1/4");
pmkid = NULL;
}
#endif /* CONFIG_FILS */
#ifdef CONFIG_SAE #ifdef CONFIG_SAE
} else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
if (sm->pmkid_set) { if (sm->pmkid_set) {
@ -2790,6 +2818,12 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
pmk_len = sm->pmk_len; pmk_len = sm->pmk_len;
} }
if ((!pmk || !pmk_len) && sm->pmksa) {
wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
pmk = sm->pmksa->pmk;
pmk_len = sm->pmksa->pmk_len;
}
if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0) if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
break; break;
@ -3287,12 +3321,7 @@ SM_STATE(WPA_PTK, PTKINITDONE)
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
sm->pairwise_set = TRUE; sm->pairwise_set = TRUE;
if (sm->wpa_auth->conf.wpa_ptk_rekey) { wpa_auth_set_ptk_rekey_timer(sm);
eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
eloop_register_timeout(sm->wpa_auth->conf.
wpa_ptk_rekey, 0, wpa_rekey_ptk,
sm->wpa_auth, sm);
}
if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
@ -4840,6 +4869,16 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
*fils_kek_len = sm->PTK.kek_len; *fils_kek_len = sm->PTK.kek_len;
} }
void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
size_t pmk_len, const u8 *pmkid)
{
os_memcpy(sm->PMK, pmk, pmk_len);
sm->pmk_len = pmk_len;
os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
sm->pmkid_set = 1;
}
#endif /* CONFIG_FILS */ #endif /* CONFIG_FILS */

View file

@ -470,6 +470,8 @@ int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
u8 *fils_anonce, u8 *fils_snonce, u8 *fils_anonce, u8 *fils_snonce,
u8 *fils_kek, size_t *fils_kek_len); u8 *fils_kek, size_t *fils_kek_len);
void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
size_t pmk_len, const u8 *pmkid);
u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
u8 *pos, size_t max_len, u8 *pos, size_t max_len,
const u8 *req_ies, size_t req_ies_len); const u8 *req_ies, size_t req_ies_len);
@ -486,5 +488,6 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
void (*cb)(void *ctx1, void *ctx2), void (*cb)(void *ctx1, void *ctx2),
void *ctx1, void *ctx2); void *ctx1, void *ctx2);
int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
#endif /* WPA_AUTH_H */ #endif /* WPA_AUTH_H */