mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2025-02-06 04:04:01 -05:00
FT: Add RIC Request processing and RIC Response generation
hostapd will now go through the RIC Request and process each RDIE. Only WMM TSPEC requests are currently supported; all other request descriptors will be declined. RIC Response is written by hostapd and verified by wpa_supplicant (MIC validation). wpa_supplicant does not yet have code to notify the driver about the resource request results.
This commit is contained in:
parent
babfbf15cc
commit
f238cf9f42
@ -675,7 +675,7 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
int send_deauth = 0, send_len, left, i;
|
int send_deauth = 0, send_len, left, i;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
u8 buf[sizeof(struct ieee80211_mgmt) + 512];
|
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
|
||||||
struct ieee80211_mgmt *reply;
|
struct ieee80211_mgmt *reply;
|
||||||
|
|
||||||
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
|
||||||
@ -1133,10 +1133,11 @@ static void handle_assoc(struct hostapd_data *hapd,
|
|||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
if (resp == WLAN_STATUS_SUCCESS) {
|
if (resp == WLAN_STATUS_SUCCESS) {
|
||||||
/* IEEE 802.11r: Mobility Domain Information, Fast BSS
|
/* IEEE 802.11r: Mobility Domain Information, Fast BSS
|
||||||
* Transition Information, RSN */
|
* Transition Information, RSN, [RIC Response] */
|
||||||
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
|
p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
|
||||||
buf + sizeof(buf) - p,
|
buf + sizeof(buf) - p,
|
||||||
sta->auth_alg);
|
sta->auth_alg,
|
||||||
|
pos, left);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
|
@ -165,25 +165,12 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wmm_addts_req(struct hostapd_data *hapd,
|
int wmm_process_tspec(struct wmm_tspec_element *tspec)
|
||||||
struct ieee80211_mgmt *mgmt,
|
|
||||||
struct wmm_tspec_element *tspec, size_t len)
|
|
||||||
{
|
{
|
||||||
u8 *end = ((u8 *) mgmt) + len;
|
|
||||||
int medium_time, pps, duration;
|
int medium_time, pps, duration;
|
||||||
int up, psb, dir, tid;
|
int up, psb, dir, tid;
|
||||||
u16 val, surplus;
|
u16 val, surplus;
|
||||||
|
|
||||||
if ((u8 *) (tspec + 1) > end) {
|
|
||||||
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
|
|
||||||
"from " MACSTR,
|
|
||||||
mgmt->u.action.u.wmm_action.dialog_token,
|
|
||||||
MAC2STR(mgmt->sa));
|
|
||||||
|
|
||||||
up = (tspec->ts_info[1] >> 3) & 0x07;
|
up = (tspec->ts_info[1] >> 3) & 0x07;
|
||||||
psb = (tspec->ts_info[1] >> 2) & 0x01;
|
psb = (tspec->ts_info[1] >> 2) & 0x01;
|
||||||
dir = (tspec->ts_info[0] >> 5) & 0x03;
|
dir = (tspec->ts_info[0] >> 5) & 0x03;
|
||||||
@ -204,7 +191,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
|
|||||||
val = le_to_host16(tspec->nominal_msdu_size);
|
val = le_to_host16(tspec->nominal_msdu_size);
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
|
wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)");
|
||||||
goto invalid;
|
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
/* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
|
/* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */
|
||||||
pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
|
pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val;
|
||||||
@ -213,7 +200,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
|
|||||||
|
|
||||||
if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
|
if (le_to_host32(tspec->minimum_phy_rate) < 1000000) {
|
||||||
wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
|
wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate");
|
||||||
goto invalid;
|
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
|
duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 /
|
||||||
@ -226,7 +213,7 @@ static void wmm_addts_req(struct hostapd_data *hapd,
|
|||||||
if (surplus <= 0x2000) {
|
if (surplus <= 0x2000) {
|
||||||
wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
|
wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not "
|
||||||
"greater than unity");
|
"greater than unity");
|
||||||
goto invalid;
|
return WMM_ADDTS_STATUS_INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
medium_time = surplus * pps * duration / 0x2000;
|
medium_time = surplus * pps * duration / 0x2000;
|
||||||
@ -241,26 +228,38 @@ static void wmm_addts_req(struct hostapd_data *hapd,
|
|||||||
if (medium_time > 750000) {
|
if (medium_time > 750000) {
|
||||||
wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
|
wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over "
|
||||||
"75%% of available bandwidth");
|
"75%% of available bandwidth");
|
||||||
wmm_send_action(hapd, mgmt->sa, tspec,
|
return WMM_ADDTS_STATUS_REFUSED;
|
||||||
WMM_ACTION_CODE_ADDTS_RESP,
|
|
||||||
mgmt->u.action.u.wmm_action.dialog_token,
|
|
||||||
WMM_ADDTS_STATUS_REFUSED);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert to 32 microseconds per second unit */
|
/* Convert to 32 microseconds per second unit */
|
||||||
tspec->medium_time = host_to_le16(medium_time / 32);
|
tspec->medium_time = host_to_le16(medium_time / 32);
|
||||||
|
|
||||||
wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
|
return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED;
|
||||||
mgmt->u.action.u.wmm_action.dialog_token,
|
}
|
||||||
WMM_ADDTS_STATUS_ADMISSION_ACCEPTED);
|
|
||||||
return;
|
|
||||||
|
|
||||||
invalid:
|
|
||||||
wmm_send_action(hapd, mgmt->sa, tspec,
|
static void wmm_addts_req(struct hostapd_data *hapd,
|
||||||
WMM_ACTION_CODE_ADDTS_RESP,
|
struct ieee80211_mgmt *mgmt,
|
||||||
|
struct wmm_tspec_element *tspec, size_t len)
|
||||||
|
{
|
||||||
|
u8 *end = ((u8 *) mgmt) + len;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if ((u8 *) (tspec + 1) > end) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC "
|
||||||
|
"from " MACSTR,
|
||||||
mgmt->u.action.u.wmm_action.dialog_token,
|
mgmt->u.action.u.wmm_action.dialog_token,
|
||||||
WMM_ADDTS_STATUS_INVALID_PARAMETERS);
|
MAC2STR(mgmt->sa));
|
||||||
|
|
||||||
|
res = wmm_process_tspec(tspec);
|
||||||
|
wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res);
|
||||||
|
|
||||||
|
wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP,
|
||||||
|
mgmt->u.action.u.wmm_action.dialog_token, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,5 +31,6 @@ static inline int hostapd_wmm_sta_config(struct hostapd_data *hapd,
|
|||||||
#endif /* NEED_MLME */
|
#endif /* NEED_MLME */
|
||||||
void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
|
void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
int wmm_process_tspec(struct wmm_tspec_element *tspec);
|
||||||
|
|
||||||
#endif /* WME_H */
|
#endif /* WME_H */
|
||||||
|
@ -266,7 +266,8 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id);
|
|||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||||
size_t max_len, int auth_alg);
|
size_t max_len, int auth_alg,
|
||||||
|
const u8 *req_ies, size_t req_ies_len);
|
||||||
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
|
||||||
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
u16 auth_transaction, const u8 *ies, size_t ies_len,
|
||||||
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
|
||||||
|
165
hostapd/wpa_ft.c
165
hostapd/wpa_ft.c
@ -19,6 +19,7 @@
|
|||||||
#include "wpa.h"
|
#include "wpa.h"
|
||||||
#include "aes_wrap.h"
|
#include "aes_wrap.h"
|
||||||
#include "ieee802_11.h"
|
#include "ieee802_11.h"
|
||||||
|
#include "wme.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "wpa_auth_i.h"
|
#include "wpa_auth_i.h"
|
||||||
#include "wpa_auth_ie.h"
|
#include "wpa_auth_ie.h"
|
||||||
@ -26,6 +27,28 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_IEEE80211R
|
#ifdef CONFIG_IEEE80211R
|
||||||
|
|
||||||
|
struct wpa_ft_ies {
|
||||||
|
const u8 *mdie;
|
||||||
|
size_t mdie_len;
|
||||||
|
const u8 *ftie;
|
||||||
|
size_t ftie_len;
|
||||||
|
const u8 *r1kh_id;
|
||||||
|
const u8 *gtk;
|
||||||
|
size_t gtk_len;
|
||||||
|
const u8 *r0kh_id;
|
||||||
|
size_t r0kh_id_len;
|
||||||
|
const u8 *rsn;
|
||||||
|
size_t rsn_len;
|
||||||
|
const u8 *rsn_pmkid;
|
||||||
|
const u8 *ric;
|
||||||
|
size_t ric_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||||
|
struct wpa_ft_ies *parse);
|
||||||
|
|
||||||
|
|
||||||
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
|
static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
|
||||||
const u8 *data, size_t data_len)
|
const u8 *data, size_t data_len)
|
||||||
{
|
{
|
||||||
@ -471,14 +494,122 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
|
|||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count,
|
||||||
|
const u8 *ies, size_t ies_len)
|
||||||
|
{
|
||||||
|
struct ieee802_11_elems parse;
|
||||||
|
struct rsn_rdie *rdie;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d",
|
||||||
|
id, descr_count);
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)",
|
||||||
|
ies, ies_len);
|
||||||
|
|
||||||
|
if (end - pos < (int) sizeof(*rdie)) {
|
||||||
|
wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE");
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pos++ = WLAN_EID_RIC_DATA;
|
||||||
|
*pos++ = sizeof(*rdie);
|
||||||
|
rdie = (struct rsn_rdie *) pos;
|
||||||
|
rdie->id = id;
|
||||||
|
rdie->descr_count = 0;
|
||||||
|
rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS);
|
||||||
|
pos += sizeof(*rdie);
|
||||||
|
|
||||||
|
if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) ==
|
||||||
|
ParseFailed) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs");
|
||||||
|
rdie->status_code =
|
||||||
|
host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parse.wmm_tspec) {
|
||||||
|
struct wmm_tspec_element *tspec;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE "
|
||||||
|
"(%d)", (int) parse.wmm_tspec_len);
|
||||||
|
rdie->status_code =
|
||||||
|
host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
if (end - pos < (int) sizeof(*tspec)) {
|
||||||
|
wpa_printf(MSG_ERROR, "FT: Not enough room for "
|
||||||
|
"response TSPEC");
|
||||||
|
rdie->status_code =
|
||||||
|
host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
tspec = (struct wmm_tspec_element *) pos;
|
||||||
|
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
|
||||||
|
res = wmm_process_tspec(tspec);
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res);
|
||||||
|
if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS)
|
||||||
|
rdie->status_code =
|
||||||
|
host_to_le16(WLAN_STATUS_INVALID_PARAMETERS);
|
||||||
|
else if (res == WMM_ADDTS_STATUS_REFUSED)
|
||||||
|
rdie->status_code =
|
||||||
|
host_to_le16(WLAN_STATUS_REQUEST_DECLINED);
|
||||||
|
else {
|
||||||
|
/* TSPEC accepted; include updated TSPEC in response */
|
||||||
|
rdie->descr_count = 1;
|
||||||
|
pos += sizeof(*tspec);
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
|
||||||
|
rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len)
|
||||||
|
{
|
||||||
|
const u8 *rpos, *start;
|
||||||
|
const struct rsn_rdie *rdie;
|
||||||
|
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len);
|
||||||
|
|
||||||
|
rpos = ric;
|
||||||
|
while (rpos + sizeof(*rdie) < ric + ric_len) {
|
||||||
|
if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) ||
|
||||||
|
rpos + 2 + rpos[1] > ric + ric_len)
|
||||||
|
break;
|
||||||
|
rdie = (const struct rsn_rdie *) (rpos + 2);
|
||||||
|
rpos += 2 + rpos[1];
|
||||||
|
start = rpos;
|
||||||
|
|
||||||
|
while (rpos + 2 <= ric + ric_len &&
|
||||||
|
rpos + 2 + rpos[1] <= ric + ric_len) {
|
||||||
|
if (rpos[0] == WLAN_EID_RIC_DATA)
|
||||||
|
break;
|
||||||
|
rpos += 2 + rpos[1];
|
||||||
|
}
|
||||||
|
pos = wpa_ft_process_rdie(pos, end, rdie->id,
|
||||||
|
rdie->descr_count,
|
||||||
|
start, rpos - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
||||||
size_t max_len, int auth_alg)
|
size_t max_len, int auth_alg,
|
||||||
|
const u8 *req_ies, size_t req_ies_len)
|
||||||
{
|
{
|
||||||
u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL;
|
u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL;
|
||||||
size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0;
|
size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0;
|
||||||
int res;
|
int res;
|
||||||
struct wpa_auth_config *conf;
|
struct wpa_auth_config *conf;
|
||||||
struct rsn_ftie *_ftie;
|
struct rsn_ftie *_ftie;
|
||||||
|
struct wpa_ft_ies parse;
|
||||||
|
u8 *ric_start;
|
||||||
|
|
||||||
if (sm == NULL)
|
if (sm == NULL)
|
||||||
return pos;
|
return pos;
|
||||||
@ -549,33 +680,27 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||||||
|
|
||||||
_ftie = (struct rsn_ftie *) (ftie + 2);
|
_ftie = (struct rsn_ftie *) (ftie + 2);
|
||||||
_ftie->mic_control[1] = 3; /* Information element count */
|
_ftie->mic_control[1] = 3; /* Information element count */
|
||||||
|
|
||||||
|
ric_start = pos;
|
||||||
|
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
|
||||||
|
pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len);
|
||||||
|
_ftie->mic_control[1] += ieee802_11_ie_count(ric_start,
|
||||||
|
pos - ric_start);
|
||||||
|
}
|
||||||
|
if (ric_start == pos)
|
||||||
|
ric_start = NULL;
|
||||||
|
|
||||||
if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6,
|
if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6,
|
||||||
mdie, mdie_len, ftie, ftie_len,
|
mdie, mdie_len, ftie, ftie_len,
|
||||||
rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0)
|
rsnie, rsnie_len,
|
||||||
|
ric_start, ric_start ? pos - ric_start : 0,
|
||||||
|
_ftie->mic) < 0)
|
||||||
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
|
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct wpa_ft_ies {
|
|
||||||
const u8 *mdie;
|
|
||||||
size_t mdie_len;
|
|
||||||
const u8 *ftie;
|
|
||||||
size_t ftie_len;
|
|
||||||
const u8 *r1kh_id;
|
|
||||||
const u8 *gtk;
|
|
||||||
size_t gtk_len;
|
|
||||||
const u8 *r0kh_id;
|
|
||||||
size_t r0kh_id_len;
|
|
||||||
const u8 *rsn;
|
|
||||||
size_t rsn_len;
|
|
||||||
const u8 *rsn_pmkid;
|
|
||||||
const u8 *ric;
|
|
||||||
size_t ric_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
||||||
struct wpa_ft_ies *parse)
|
struct wpa_ft_ies *parse)
|
||||||
{
|
{
|
||||||
|
@ -116,9 +116,13 @@
|
|||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
#define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26
|
||||||
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27
|
||||||
|
#define WLAN_STATUS_R0KH_UNREACHABLE 28
|
||||||
/* IEEE 802.11w */
|
/* IEEE 802.11w */
|
||||||
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30
|
||||||
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31
|
||||||
|
#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32
|
||||||
|
#define WLAN_STATUS_REQUEST_DECLINED 37
|
||||||
|
#define WLAN_STATUS_INVALID_PARAMETERS 38
|
||||||
/* IEEE 802.11i */
|
/* IEEE 802.11i */
|
||||||
#define WLAN_STATUS_INVALID_IE 40
|
#define WLAN_STATUS_INVALID_IE 40
|
||||||
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41
|
||||||
|
@ -282,6 +282,12 @@ struct rsn_ftie {
|
|||||||
#define FTIE_SUBELEM_R0KH_ID 3
|
#define FTIE_SUBELEM_R0KH_ID 3
|
||||||
#define FTIE_SUBELEM_IGTK 4
|
#define FTIE_SUBELEM_IGTK 4
|
||||||
|
|
||||||
|
struct rsn_rdie {
|
||||||
|
u8 id;
|
||||||
|
u8 descr_count;
|
||||||
|
le16 status_code;
|
||||||
|
} STRUCT_PACKED;
|
||||||
|
|
||||||
#endif /* CONFIG_IEEE80211R */
|
#endif /* CONFIG_IEEE80211R */
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -300,6 +300,8 @@ struct wpa_ft_ies {
|
|||||||
size_t tie_len;
|
size_t tie_len;
|
||||||
const u8 *igtk;
|
const u8 *igtk;
|
||||||
size_t igtk_len;
|
size_t igtk_len;
|
||||||
|
const u8 *ric;
|
||||||
|
size_t ric_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -358,6 +360,8 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
|||||||
const u8 *end, *pos;
|
const u8 *end, *pos;
|
||||||
struct wpa_ie_data data;
|
struct wpa_ie_data data;
|
||||||
int ret;
|
int ret;
|
||||||
|
const struct rsn_ftie *ftie;
|
||||||
|
int prot_ie_count = 0;
|
||||||
|
|
||||||
os_memset(parse, 0, sizeof(*parse));
|
os_memset(parse, 0, sizeof(*parse));
|
||||||
if (ies == NULL)
|
if (ies == NULL)
|
||||||
@ -386,6 +390,10 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
|||||||
parse->mdie_len = pos[1];
|
parse->mdie_len = pos[1];
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||||
|
if (pos[1] < sizeof(*ftie))
|
||||||
|
return -1;
|
||||||
|
ftie = (const struct rsn_ftie *) (pos + 2);
|
||||||
|
prot_ie_count = ftie->mic_control[1];
|
||||||
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
|
if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
@ -393,11 +401,55 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
|||||||
parse->tie = pos + 2;
|
parse->tie = pos + 2;
|
||||||
parse->tie_len = pos[1];
|
parse->tie_len = pos[1];
|
||||||
break;
|
break;
|
||||||
|
case WLAN_EID_RIC_DATA:
|
||||||
|
if (parse->ric == NULL)
|
||||||
|
parse->ric = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos += 2 + pos[1];
|
pos += 2 + pos[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prot_ie_count == 0)
|
||||||
|
return 0; /* no MIC */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the protected IE count matches with IEs included in the
|
||||||
|
* frame.
|
||||||
|
*/
|
||||||
|
if (parse->rsn)
|
||||||
|
prot_ie_count--;
|
||||||
|
if (parse->mdie)
|
||||||
|
prot_ie_count--;
|
||||||
|
if (parse->ftie)
|
||||||
|
prot_ie_count--;
|
||||||
|
if (parse->tie)
|
||||||
|
prot_ie_count--;
|
||||||
|
if (prot_ie_count < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in "
|
||||||
|
"the protected IE count");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prot_ie_count == 0 && parse->ric) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not "
|
||||||
|
"included in protected IE count");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine the end of the RIC IE(s) */
|
||||||
|
pos = parse->ric;
|
||||||
|
while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end &&
|
||||||
|
prot_ie_count) {
|
||||||
|
prot_ie_count--;
|
||||||
|
pos += 2 + pos[1];
|
||||||
|
}
|
||||||
|
parse->ric_len = pos - parse->ric;
|
||||||
|
if (prot_ie_count) {
|
||||||
|
wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from "
|
||||||
|
"frame", (int) prot_ie_count);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,16 +870,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||||||
if (parse.tie)
|
if (parse.tie)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
if (ftie->mic_control[1] != count) {
|
|
||||||
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)",
|
|
||||||
ftie->mic_control[1]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
|
if (wpa_ft_mic(sm->ptk.kck, sm->own_addr, src_addr, 6,
|
||||||
parse.mdie - 2, parse.mdie_len + 2,
|
parse.mdie - 2, parse.mdie_len + 2,
|
||||||
parse.ftie - 2, parse.ftie_len + 2,
|
parse.ftie - 2, parse.ftie_len + 2,
|
||||||
parse.rsn - 2, parse.rsn_len + 2, NULL, 0,
|
parse.rsn - 2, parse.rsn_len + 2,
|
||||||
|
parse.ric, parse.ric_len,
|
||||||
mic) < 0) {
|
mic) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
|
wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
|
||||||
return -1;
|
return -1;
|
||||||
@ -848,6 +895,12 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||||||
return -1;
|
return -1;
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
|
if (parse.ric) {
|
||||||
|
wpa_hexdump(MSG_MSGDUMP, "FT: RIC Response",
|
||||||
|
parse.ric, parse.ric_len);
|
||||||
|
/* TODO: parse response and inform driver about results */
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user