FT: FTE parsing for SHA384-based AKM
The MIC field is now a variable length field, so make the FTE parser aware of the two different field lengths. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
8c2715b358
commit
9a33737a0b
6 changed files with 190 additions and 60 deletions
|
@ -2317,10 +2317,12 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||
u8 *anonce, *snonce;
|
||||
const u8 *kck;
|
||||
size_t kck_len;
|
||||
int use_sha384;
|
||||
|
||||
if (sm == NULL)
|
||||
return pos;
|
||||
|
||||
use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
|
||||
conf = &sm->wpa_auth->conf;
|
||||
|
||||
if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt))
|
||||
|
@ -2398,7 +2400,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
|
|||
_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) {
|
||||
if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, use_sha384) == 0
|
||||
&& parse.ric) {
|
||||
pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
|
||||
parse.ric_len);
|
||||
if (auth_alg == WLAN_AUTH_FT)
|
||||
|
@ -2683,7 +2686,6 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
u8 **resp_ies, size_t *resp_ies_len)
|
||||
{
|
||||
struct rsn_mdie *mdie;
|
||||
struct rsn_ftie *ftie;
|
||||
u8 pmk_r1[PMK_LEN_MAX], pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
u8 ptk_name[WPA_PMK_NAME_LEN];
|
||||
struct wpa_auth_config *conf;
|
||||
|
@ -2695,8 +2697,8 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
struct vlan_description vlan;
|
||||
const u8 *identity, *radius_cui;
|
||||
size_t identity_len = 0, radius_cui_len = 0;
|
||||
int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
|
||||
size_t pmk_r1_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
|
||||
int use_sha384;
|
||||
size_t pmk_r1_len;
|
||||
|
||||
*resp_ies = NULL;
|
||||
*resp_ies_len = 0;
|
||||
|
@ -2707,10 +2709,12 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
|
||||
ies, ies_len);
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse, -1)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
use_sha384 = wpa_key_mgmt_sha384(parse.key_mgmt);
|
||||
pmk_r1_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
|
||||
|
||||
mdie = (struct rsn_mdie *) parse.mdie;
|
||||
if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
|
||||
|
@ -2721,13 +2725,27 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
return WLAN_STATUS_INVALID_MDIE;
|
||||
}
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
|
||||
if (use_sha384) {
|
||||
struct rsn_ftie_sha384 *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie_sha384 *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
|
||||
} else {
|
||||
struct rsn_ftie *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
|
||||
}
|
||||
|
||||
if (parse.r0kh_id == NULL) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");
|
||||
|
@ -2917,19 +2935,23 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||
{
|
||||
struct wpa_ft_ies parse;
|
||||
struct rsn_mdie *mdie;
|
||||
struct rsn_ftie *ftie;
|
||||
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||
size_t mic_len = 16;
|
||||
unsigned int count;
|
||||
const u8 *kck;
|
||||
size_t kck_len;
|
||||
int use_sha384;
|
||||
const u8 *anonce, *snonce, *fte_mic;
|
||||
u8 fte_elem_count;
|
||||
|
||||
if (sm == NULL)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
|
||||
use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
@ -2960,25 +2982,47 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||
return WLAN_STATUS_INVALID_MDIE;
|
||||
}
|
||||
|
||||
if (use_sha384) {
|
||||
struct rsn_ftie_sha384 *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie_sha384 *) parse.ftie;
|
||||
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
fte_elem_count = ftie->mic_control[1];
|
||||
fte_mic = ftie->mic;
|
||||
} else {
|
||||
struct rsn_ftie *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
fte_elem_count = ftie->mic_control[1];
|
||||
fte_mic = ftie->mic;
|
||||
}
|
||||
|
||||
if (os_memcmp(snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
|
||||
ftie->snonce, WPA_NONCE_LEN);
|
||||
snonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
|
||||
sm->SNonce, WPA_NONCE_LEN);
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
}
|
||||
|
||||
if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
|
||||
if (os_memcmp(anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
|
||||
ftie->anonce, WPA_NONCE_LEN);
|
||||
anonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
|
||||
sm->ANonce, WPA_NONCE_LEN);
|
||||
return WLAN_STATUS_INVALID_FTIE;
|
||||
|
@ -3029,10 +3073,10 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||
count = 3;
|
||||
if (parse.ric)
|
||||
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
|
||||
if (ftie->mic_control[1] != count) {
|
||||
if (fte_elem_count != count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
|
||||
"Control: received %u expected %u",
|
||||
ftie->mic_control[1], count);
|
||||
fte_elem_count, count);
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -3053,12 +3097,12 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
|
|||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
|
||||
if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) {
|
||||
if (os_memcmp_const(mic, fte_mic, mic_len) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
|
||||
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
|
||||
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
|
||||
ftie->mic, mic_len);
|
||||
fte_mic, mic_len);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
|
||||
parse.mdie - 2, parse.mdie_len + 2);
|
||||
|
|
|
@ -828,23 +828,27 @@ int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr,
|
|||
|
||||
|
||||
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
struct wpa_ft_ies *parse, int use_sha384)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
|
||||
parse->ftie = ie;
|
||||
parse->ftie_len = ie_len;
|
||||
|
||||
pos = ie + sizeof(struct rsn_ftie);
|
||||
pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) :
|
||||
sizeof(struct rsn_ftie));
|
||||
end = ie + ie_len;
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
|
||||
|
||||
while (end - pos >= 2) {
|
||||
u8 id, len;
|
||||
|
||||
id = *pos++;
|
||||
len = *pos++;
|
||||
if (len > end - pos)
|
||||
if (len > end - pos) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Truncated subelement");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case FTIE_SUBELEM_R1KH_ID:
|
||||
|
@ -876,6 +880,9 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
parse->igtk_len = len;
|
||||
break;
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id);
|
||||
break;
|
||||
}
|
||||
|
||||
pos += len;
|
||||
|
@ -886,13 +893,19 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
|
|||
|
||||
|
||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
||||
struct wpa_ft_ies *parse)
|
||||
struct wpa_ft_ies *parse, int use_sha384)
|
||||
{
|
||||
const u8 *end, *pos;
|
||||
struct wpa_ie_data data;
|
||||
int ret;
|
||||
const struct rsn_ftie *ftie;
|
||||
int prot_ie_count = 0;
|
||||
int update_use_sha384 = 0;
|
||||
|
||||
if (use_sha384 < 0) {
|
||||
use_sha384 = 0;
|
||||
update_use_sha384 = 1;
|
||||
}
|
||||
|
||||
os_memset(parse, 0, sizeof(*parse));
|
||||
if (ies == NULL)
|
||||
|
@ -924,6 +937,11 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
|||
parse->rsn_pmkid = data.pmkid;
|
||||
parse->key_mgmt = data.key_mgmt;
|
||||
parse->pairwise_cipher = data.pairwise_cipher;
|
||||
if (update_use_sha384) {
|
||||
use_sha384 =
|
||||
wpa_key_mgmt_sha384(parse->key_mgmt);
|
||||
update_use_sha384 = 0;
|
||||
}
|
||||
break;
|
||||
case WLAN_EID_MOBILITY_DOMAIN:
|
||||
if (len < sizeof(struct rsn_mdie))
|
||||
|
@ -932,11 +950,24 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
|
|||
parse->mdie_len = len;
|
||||
break;
|
||||
case WLAN_EID_FAST_BSS_TRANSITION:
|
||||
if (use_sha384) {
|
||||
const struct rsn_ftie_sha384 *ftie_sha384;
|
||||
|
||||
if (len < sizeof(*ftie_sha384))
|
||||
return -1;
|
||||
ftie_sha384 =
|
||||
(const struct rsn_ftie_sha384 *) pos;
|
||||
prot_ie_count = ftie_sha384->mic_control[1];
|
||||
if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (len < sizeof(*ftie))
|
||||
return -1;
|
||||
ftie = (const struct rsn_ftie *) pos;
|
||||
prot_ie_count = ftie->mic_control[1];
|
||||
if (wpa_ft_parse_ftie(pos, len, parse) < 0)
|
||||
if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
|
||||
return -1;
|
||||
break;
|
||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||
|
|
|
@ -314,6 +314,14 @@ struct rsn_ftie {
|
|||
/* followed by optional parameters */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
struct rsn_ftie_sha384 {
|
||||
u8 mic_control[2];
|
||||
u8 mic[24];
|
||||
u8 anonce[WPA_NONCE_LEN];
|
||||
u8 snonce[WPA_NONCE_LEN];
|
||||
/* followed by optional parameters */
|
||||
} STRUCT_PACKED;
|
||||
|
||||
#define FTIE_SUBELEM_R1KH_ID 1
|
||||
#define FTIE_SUBELEM_GTK 2
|
||||
#define FTIE_SUBELEM_R0KH_ID 3
|
||||
|
@ -449,7 +457,8 @@ struct wpa_ft_ies {
|
|||
int pairwise_cipher;
|
||||
};
|
||||
|
||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse);
|
||||
int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
|
||||
int use_sha384);
|
||||
|
||||
int wpa_cipher_key_len(int cipher);
|
||||
int wpa_cipher_rsc_len(int cipher);
|
||||
|
|
|
@ -3547,7 +3547,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (wpa_ft_parse_ies(pos, end - pos, &parse) < 0) {
|
||||
if (wpa_ft_parse_ies(pos, end - pos, &parse,
|
||||
wpa_key_mgmt_sha384(sm->key_mgmt)) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -65,11 +65,13 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr,
|
|||
int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len)
|
||||
{
|
||||
struct wpa_ft_ies ft;
|
||||
int use_sha384;
|
||||
|
||||
if (sm == NULL)
|
||||
return 0;
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &ft) < 0)
|
||||
use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0)
|
||||
return -1;
|
||||
|
||||
if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
|
||||
|
@ -423,12 +425,13 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
size_t ft_ies_len;
|
||||
struct wpa_ft_ies parse;
|
||||
struct rsn_mdie *mdie;
|
||||
struct rsn_ftie *ftie;
|
||||
u8 ptk_name[WPA_PMK_NAME_LEN];
|
||||
int ret;
|
||||
const u8 *bssid;
|
||||
const u8 *kck;
|
||||
size_t kck_len;
|
||||
int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
|
||||
const u8 *anonce, *snonce;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len);
|
||||
|
@ -454,7 +457,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
|
||||
return -1;
|
||||
}
|
||||
|
@ -467,16 +470,34 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
return -1;
|
||||
}
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
|
||||
if (use_sha384) {
|
||||
struct rsn_ftie_sha384 *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie_sha384 *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
} else {
|
||||
struct rsn_ftie *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
}
|
||||
|
||||
if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
|
||||
ftie->snonce, WPA_NONCE_LEN);
|
||||
snonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
|
||||
sm->snonce, WPA_NONCE_LEN);
|
||||
return -1;
|
||||
|
@ -515,8 +536,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID", sm->r1kh_id, FT_R1KH_ID_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: SNonce", sm->snonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: ANonce", ftie->anonce, WPA_NONCE_LEN);
|
||||
os_memcpy(sm->anonce, ftie->anonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: ANonce", anonce, WPA_NONCE_LEN);
|
||||
os_memcpy(sm->anonce, anonce, WPA_NONCE_LEN);
|
||||
if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name,
|
||||
sm->r1kh_id, sm->own_addr, sm->pmk_r1,
|
||||
sm->pmk_r1_name) < 0)
|
||||
|
@ -528,7 +549,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
|
||||
bssid = target_ap;
|
||||
if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce,
|
||||
ftie->anonce, sm->own_addr, bssid,
|
||||
anonce, sm->own_addr, bssid,
|
||||
sm->pmk_r1_name, &sm->ptk, ptk_name, sm->key_mgmt,
|
||||
sm->pairwise_cipher) < 0)
|
||||
return -1;
|
||||
|
@ -540,7 +561,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
|
|||
kck = sm->ptk.kck;
|
||||
kck_len = sm->ptk.kck_len;
|
||||
}
|
||||
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, ftie->anonce,
|
||||
ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, anonce,
|
||||
sm->pmk_r1_name,
|
||||
kck, kck_len, bssid,
|
||||
ric_ies, ric_ies_len,
|
||||
|
@ -731,11 +752,13 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||
{
|
||||
struct wpa_ft_ies parse;
|
||||
struct rsn_mdie *mdie;
|
||||
struct rsn_ftie *ftie;
|
||||
unsigned int count;
|
||||
u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
|
||||
const u8 *kck;
|
||||
size_t kck_len;
|
||||
int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
|
||||
const u8 *anonce, *snonce, *fte_mic;
|
||||
u8 fte_elem_count;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len);
|
||||
|
||||
|
@ -750,7 +773,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
|
||||
return -1;
|
||||
}
|
||||
|
@ -763,25 +786,47 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||
return -1;
|
||||
}
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
|
||||
if (use_sha384) {
|
||||
struct rsn_ftie_sha384 *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie_sha384 *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_memcmp(ftie->snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
fte_elem_count = ftie->mic_control[1];
|
||||
fte_mic = ftie->mic;
|
||||
} else {
|
||||
struct rsn_ftie *ftie;
|
||||
|
||||
ftie = (struct rsn_ftie *) parse.ftie;
|
||||
if (!ftie || parse.ftie_len < sizeof(*ftie)) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
|
||||
return -1;
|
||||
}
|
||||
|
||||
anonce = ftie->anonce;
|
||||
snonce = ftie->snonce;
|
||||
fte_elem_count = ftie->mic_control[1];
|
||||
fte_mic = ftie->mic;
|
||||
}
|
||||
|
||||
if (os_memcmp(snonce, sm->snonce, WPA_NONCE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
|
||||
ftie->snonce, WPA_NONCE_LEN);
|
||||
snonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
|
||||
sm->snonce, WPA_NONCE_LEN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_memcmp(ftie->anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
|
||||
if (os_memcmp(anonce, sm->anonce, WPA_NONCE_LEN) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
|
||||
ftie->anonce, WPA_NONCE_LEN);
|
||||
anonce, WPA_NONCE_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
|
||||
sm->anonce, WPA_NONCE_LEN);
|
||||
return -1;
|
||||
|
@ -826,10 +871,10 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||
count = 3;
|
||||
if (parse.ric)
|
||||
count += ieee802_11_ie_count(parse.ric, parse.ric_len);
|
||||
if (ftie->mic_control[1] != count) {
|
||||
if (fte_elem_count != count) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
|
||||
"Control: received %u expected %u",
|
||||
ftie->mic_control[1], count);
|
||||
fte_elem_count, count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -851,9 +896,9 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
|
||||
if (os_memcmp_const(mic, fte_mic, 16) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", ftie->mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", fte_mic, 16);
|
||||
wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -656,7 +656,7 @@ static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
|
|||
sta->state = STATE3;
|
||||
}
|
||||
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse) == 0) {
|
||||
if (wpa_ft_parse_ies(ies, ies_len, &parse, 0) == 0) {
|
||||
if (parse.r0kh_id) {
|
||||
os_memcpy(bss->r0kh_id, parse.r0kh_id,
|
||||
parse.r0kh_id_len);
|
||||
|
|
Loading…
Reference in a new issue