FILS: Try to use FILS authentication if PMKSA or ERP entry is available

If a PMKSA cache entry for the target AP is available, try to use FILS
with PMKSA caching.

If an ERP key for the target AP is available, try to use FILS with
EAP-Initiate/Re-auth added as Wrapper Data element.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2015-09-04 15:32:07 +03:00 committed by Jouni Malinen
parent 2c2c557917
commit f00b9b8864
4 changed files with 120 additions and 4 deletions

View file

@ -3199,3 +3199,91 @@ void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
sm->test_assoc_ie = buf;
}
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_FILS
struct wpabuf * fils_build_auth(struct wpa_sm *sm)
{
struct wpabuf *buf = NULL;
struct wpabuf *erp_msg;
erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
if (!erp_msg && !sm->cur_pmksa) {
wpa_printf(MSG_DEBUG,
"FILS: Neither ERP EAP-Initiate/Re-auth nor PMKSA cache entry is available - skip FILS");
goto fail;
}
wpa_printf(MSG_DEBUG, "FILS: Try to use FILS (erp=%d pmksa_cache=%d)",
erp_msg != NULL, sm->cur_pmksa != NULL);
if (!sm->assoc_wpa_ie) {
wpa_printf(MSG_INFO, "FILS: No own RSN IE set for FILS");
goto fail;
}
if (random_get_bytes(sm->fils_nonce, FILS_NONCE_LEN) < 0 ||
random_get_bytes(sm->fils_session, FILS_SESSION_LEN) < 0)
goto fail;
wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Nonce",
sm->fils_nonce, FILS_NONCE_LEN);
wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
sm->fils_session, FILS_SESSION_LEN);
buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len);
if (!buf)
goto fail;
/* Fields following the Authentication algorithm number field */
/* Authentication Transaction seq# */
wpabuf_put_le16(buf, 1);
/* Status Code */
wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
/* TODO: Finite Cyclic Group when using PK or PFS */
/* TODO: Element when using PK or PFS */
/* RSNE */
wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
wpabuf_put_data(buf, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
/* TODO: MDE when using FILS for FT initial association */
/* TODO: FTE when using FILS for FT initial association */
/* FILS Nonce */
wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN); /* Length */
/* Element ID Extension */
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
wpabuf_put_data(buf, sm->fils_nonce, FILS_NONCE_LEN);
/* FILS Session */
wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
/* Element ID Extension */
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
/* FILS Wrapped Data */
if (erp_msg) {
wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
/* Element ID Extension */
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA);
wpabuf_put_buf(buf, erp_msg);
}
wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
buf);
fail:
wpabuf_free(erp_msg);
return buf;
}
#endif /* CONFIG_FILS */

View file

@ -426,4 +426,6 @@ extern unsigned int tdls_testing;
int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf);
void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
struct wpabuf * fils_build_auth(struct wpa_sm *sm);
#endif /* WPA_H */

View file

@ -138,6 +138,11 @@ struct wpa_sm {
#ifdef CONFIG_TESTING_OPTIONS
struct wpabuf *test_assoc_ie;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_FILS
u8 fils_nonce[FILS_NONCE_LEN];
u8 fils_session[FILS_SESSION_LEN];
#endif /* CONFIG_FILS */
};

View file

@ -549,6 +549,31 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_SAE */
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
#ifdef CONFIG_FILS
/* TODO: FILS operations can in some cases be done between different
* network_ctx (i.e., same credentials can be used with multiple
* networks). */
if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
wpa_key_mgmt_fils(ssid->key_mgmt)) {
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
ssid, 0) == 0)
wpa_printf(MSG_DEBUG,
"SME: Try to use FILS with PMKSA caching");
resp = fils_build_auth(wpa_s->wpa);
if (resp) {
params.auth_alg = WPA_AUTH_ALG_FILS;
params.auth_data = wpabuf_head(resp);
params.auth_data_len = wpabuf_len(resp);
wpa_s->sme.auth_alg = WPA_AUTH_ALG_FILS;
}
}
#endif /* CONFIG_FILS */
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_cancel_scan(wpa_s);
@ -558,10 +583,6 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_clear_keys(wpa_s, bss->bssid);
wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
if (old_ssid != wpa_s->current_ssid)
wpas_notify_network_changed(wpa_s);