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:
parent
aabbdb818d
commit
3653663933
6 changed files with 51 additions and 2 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue