From 86cd6928e022794c5d352f6ae6fa1caf0726b869 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 8 Sep 2015 20:58:53 +0300 Subject: [PATCH] FILS: Add elements to FILS Association Request frame Signed-off-by: Jouni Malinen --- src/rsn_supp/wpa.c | 49 +++++++++++++++++++++++++++++++ src/rsn_supp/wpa.h | 3 ++ wpa_supplicant/sme.c | 34 +++++++++++++++++++++ wpa_supplicant/wpa_supplicant_i.h | 2 +- 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 9201a1035..136fd091e 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -3422,4 +3422,53 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len) return res; } + +struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, + size_t *kek_len, const u8 **snonce, + const u8 **anonce) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(1000); + if (!buf) + return NULL; + + /* 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); + + /* Everything after FILS Session element gets encrypted in the driver + * with KEK. The buffer returned from here is the plaintext version. */ + + /* TODO: FILS Public Key */ + + /* FILS Key Confirm */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM); + wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len); + + /* TODO: FILS HLP Container */ + + /* TODO: FILS IP Address Assignment */ + + wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf); + + *kek = sm->ptk.kek; + *kek_len = sm->ptk.kek_len; + wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len); + *snonce = sm->fils_nonce; + wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD", + *snonce, FILS_NONCE_LEN); + *anonce = sm->fils_anonce; + wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD", + *anonce, FILS_NONCE_LEN); + + return buf; +} + #endif /* CONFIG_FILS */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 2f99b6ee1..3b2dbcf43 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -428,5 +428,8 @@ void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf); struct wpabuf * fils_build_auth(struct wpa_sm *sm); int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len); +struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, + size_t *kek_len, const u8 **snonce, + const u8 **anonce); #endif /* WPA_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 4e004e979..ab71f6d92 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -986,6 +986,9 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; +#ifdef CONFIG_FILS + u8 nonces[2 * FILS_NONCE_LEN]; +#endif /* CONFIG_FILS */ #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; @@ -996,6 +999,37 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #endif /* CONFIG_VHT_OVERRIDES */ os_memset(¶ms, 0, sizeof(params)); + +#ifdef CONFIG_FILS + if (auth_type == WLAN_AUTH_FILS_SK) { + struct wpabuf *buf; + const u8 *snonce, *anonce; + + buf = fils_build_assoc_req(wpa_s->wpa, ¶ms.fils_kek, + ¶ms.fils_kek_len, &snonce, + &anonce); + if (!buf) + return; + /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */ + if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) > + sizeof(wpa_s->sme.assoc_req_ie)) { + wpa_printf(MSG_ERROR, + "FILS: Not enough buffer room for own AssocReq elements"); + wpabuf_free(buf); + return; + } + os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, + wpabuf_head(buf), wpabuf_len(buf)); + wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf); + wpabuf_free(buf); + + os_memcpy(nonces, snonce, FILS_NONCE_LEN); + os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN); + params.fils_nonces = nonces; + params.fils_nonces_len = sizeof(nonces); + } +#endif /* CONFIG_FILS */ + params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ef9273d09..d6ff6dee2 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -721,7 +721,7 @@ struct wpa_supplicant { u8 ssid[SSID_MAX_LEN]; size_t ssid_len; int freq; - u8 assoc_req_ie[200]; + u8 assoc_req_ie[300]; size_t assoc_req_ie_len; int mfp; int ft_used;