FILS: Allow FILS HLP requests to be added

The new wpa_supplicant control interface commands FILS_HLP_REQ_FLUSH and
FILS_HLP_REQ_ADD can now be used to request FILS HLP requests to be
added to the (Re)Association Request frame whenever FILS authentication
is used.

FILS_HLP_REQ_ADD parameters use the following format:
<destination MAC address> <hexdump of payload starting from ethertype>

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2017-01-29 14:07:20 +02:00 committed by Jouni Malinen
parent df20cdc457
commit 5732b770f4
6 changed files with 134 additions and 6 deletions

View file

@ -3483,11 +3483,18 @@ 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, struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
size_t *kek_len, const u8 **snonce, size_t *kek_len, const u8 **snonce,
const u8 **anonce) const u8 **anonce,
const struct wpabuf **hlp,
unsigned int num_hlp)
{ {
struct wpabuf *buf; struct wpabuf *buf;
size_t len;
unsigned int i;
buf = wpabuf_alloc(1000); len = 1000;
for (i = 0; hlp && i < num_hlp; i++)
len += 10 + wpabuf_len(hlp[i]);
buf = wpabuf_alloc(len);
if (!buf) if (!buf)
return NULL; return NULL;
@ -3510,7 +3517,34 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM); wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len); wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
/* TODO: FILS HLP Container */ /* FILS HLP Container */
for (i = 0; hlp && i < num_hlp; i++) {
const u8 *pos = wpabuf_head(hlp[i]);
size_t left = wpabuf_len(hlp[i]);
wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
if (left <= 254)
len = 1 + left;
else
len = 255;
wpabuf_put_u8(buf, len); /* Length */
/* Element ID Extension */
wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
/* Destination MAC Address, Source MAC Address, HLP Packet.
* HLP Packet is in MSDU format (i.e., included the LLC/SNAP
* header when LPD is used). */
wpabuf_put_data(buf, pos, len - 1);
pos += len - 1;
left -= len - 1;
while (left) {
wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
len = left > 255 ? 255 : left;
wpabuf_put_u8(buf, len);
wpabuf_put_data(buf, pos, len);
pos += len;
left -= len;
}
}
/* TODO: FILS IP Address Assignment */ /* TODO: FILS IP Address Assignment */

View file

@ -436,7 +436,9 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm);
int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len); 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, struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
size_t *kek_len, const u8 **snonce, size_t *kek_len, const u8 **snonce,
const u8 **anonce); const u8 **anonce,
const struct wpabuf **hlp,
unsigned int num_hlp);
int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len); int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
int wpa_fils_is_completed(struct wpa_sm *sm); int wpa_fils_is_completed(struct wpa_sm *sm);

View file

@ -9153,6 +9153,40 @@ static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
#ifdef CONFIG_FILS
static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
const char *cmd)
{
struct fils_hlp_req *req;
const char *pos;
/* format: <dst> <packet starting from ethertype> */
req = os_zalloc(sizeof(*req));
if (!req)
return -1;
if (hwaddr_aton(cmd, req->dst))
goto fail;
pos = os_strchr(cmd, ' ');
if (!pos)
goto fail;
pos++;
req->pkt = wpabuf_parse_bin(pos);
if (!req->pkt)
goto fail;
dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
return 0;
fail:
wpabuf_free(req->pkt);
os_free(req);
return -1;
}
#endif /* CONFIG_FILS */
static int wpas_ctrl_cmd_debug_level(const char *cmd) static int wpas_ctrl_cmd_debug_level(const char *cmd)
{ {
if (os_strcmp(cmd, "PING") == 0 || if (os_strcmp(cmd, "PING") == 0 ||
@ -9881,6 +9915,13 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) { } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
reply_len = wpas_ctrl_iface_get_pref_freq_list( reply_len = wpas_ctrl_iface_get_pref_freq_list(
wpa_s, buf + 19, reply, reply_size); wpa_s, buf + 19, reply, reply_size);
#ifdef CONFIG_FILS
} else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
reply_len = -1;
} else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
wpas_flush_fils_hlp_req(wpa_s);
#endif /* CONFIG_FILS */
} else { } else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16); os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16; reply_len = 16;

View file

@ -995,10 +995,35 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
if (auth_type == WLAN_AUTH_FILS_SK) { if (auth_type == WLAN_AUTH_FILS_SK) {
struct wpabuf *buf; struct wpabuf *buf;
const u8 *snonce, *anonce; const u8 *snonce, *anonce;
const unsigned int max_hlp = 20;
struct wpabuf *hlp[max_hlp];
unsigned int i, num_hlp = 0;
struct fils_hlp_req *req;
dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
list) {
hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
wpabuf_len(req->pkt));
if (!hlp[num_hlp])
break;
wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
ETH_ALEN);
wpabuf_put_data(hlp[num_hlp],
"\xaa\xaa\x03\x00\x00\x00", 6);
wpabuf_put_buf(hlp[num_hlp], req->pkt);
num_hlp++;
if (num_hlp >= max_hlp)
break;
}
buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek, buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
&params.fils_kek_len, &snonce, &params.fils_kek_len, &snonce,
&anonce); &anonce,
(const struct wpabuf **) hlp,
num_hlp);
for (i = 0; i < num_hlp; i++)
wpabuf_free(hlp[i]);
if (!buf) if (!buf)
return; return;
/* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */ /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */

View file

@ -420,6 +420,19 @@ static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
} }
void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
{
struct fils_hlp_req *req;
while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
list)) != NULL) {
dl_list_del(&req->list);
wpabuf_free(req->pkt);
os_free(req);
}
}
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
{ {
int i; int i;
@ -602,6 +615,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
} }
#endif /* CONFIG_MESH */ #endif /* CONFIG_MESH */
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
wpas_flush_fils_hlp_req(wpa_s);
} }
@ -3719,6 +3734,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
wpa_s->sched_scanning = 0; wpa_s->sched_scanning = 0;
dl_list_init(&wpa_s->bss_tmp_disallowed); dl_list_init(&wpa_s->bss_tmp_disallowed);
dl_list_init(&wpa_s->fils_hlp_req);
return wpa_s; return wpa_s;
} }

View file

@ -466,6 +466,12 @@ struct external_pmksa_cache {
void *pmksa_cache; void *pmksa_cache;
}; };
struct fils_hlp_req {
struct dl_list list;
u8 dst[ETH_ALEN];
struct wpabuf *pkt;
};
/** /**
* struct wpa_supplicant - Internal data for wpa_supplicant interface * struct wpa_supplicant - Internal data for wpa_supplicant interface
* *
@ -747,7 +753,7 @@ struct wpa_supplicant {
u8 ssid[SSID_MAX_LEN]; u8 ssid[SSID_MAX_LEN];
size_t ssid_len; size_t ssid_len;
int freq; int freq;
u8 assoc_req_ie[300]; u8 assoc_req_ie[1500];
size_t assoc_req_ie_len; size_t assoc_req_ie_len;
int mfp; int mfp;
int ft_used; int ft_used;
@ -1103,6 +1109,9 @@ struct wpa_supplicant {
struct os_reltime lci_time; struct os_reltime lci_time;
struct os_reltime beacon_rep_scan; struct os_reltime beacon_rep_scan;
/* FILS HLP requests (struct fils_hlp_req) */
struct dl_list fils_hlp_req;
}; };
@ -1227,6 +1236,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res, struct wpa_scan_results *scan_res,
struct scan_info *info); struct scan_info *info);
void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s); void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
/* MBO functions */ /* MBO functions */