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:
parent
df20cdc457
commit
5732b770f4
6 changed files with 134 additions and 6 deletions
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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, ¶ms.fils_kek,
|
buf = fils_build_assoc_req(wpa_s->wpa, ¶ms.fils_kek,
|
||||||
¶ms.fils_kek_len, &snonce,
|
¶ms.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 */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue