diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index e5d3b6aff..91e4a2560 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -814,6 +814,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len, { u8 *pos = buf, *ielen; size_t hdrlen; + u16 mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0; if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && key_len == SHA256_MAC_LEN) @@ -842,7 +843,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); + mic_control |= FTE_MIC_LEN_32 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + WPA_PUT_LE16(hdr->mic_control, mic_control); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -854,7 +856,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); + mic_control |= FTE_MIC_LEN_24 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + WPA_PUT_LE16(hdr->mic_control, mic_control); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -864,7 +867,8 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int key_mgmt, size_t key_len, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); + mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + WPA_PUT_LE16(hdr->mic_control, mic_control); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -2788,8 +2792,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, *elem_count = 3; /* Information element count */ ric_start = pos; - if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, sm->wpa_key_mgmt, - key_len, false, false) == 0 && parse.ric) { + if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, + sm->wpa_key_mgmt) == 0 && parse.ric) { pos = wpa_ft_process_ric(sm, pos, end, parse.ric, parse.ric_len); if (auth_alg == WLAN_AUTH_FT) @@ -3165,7 +3169,7 @@ 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, 0, false, false)) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } @@ -3463,8 +3467,7 @@ int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); - if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt, - sm->pmk_r1_len, true, true) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 9f3ebd50a..32e37468d 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -1090,19 +1090,46 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, } -static int wpa_ft_parse_fte(const u8 *ie, size_t len, size_t mic_len, +static int wpa_ft_parse_fte(int key_mgmt, const u8 *ie, size_t len, struct wpa_ft_ies *parse) { + size_t mic_len; + u8 mic_len_info; const u8 *pos = ie; const u8 *end = pos + len; wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control", pos, 2); - parse->fte_rsnxe_used = pos[0] & 0x01; + parse->fte_rsnxe_used = pos[0] & FTE_MIC_CTRL_RSNXE_USED; + mic_len_info = (pos[0] & FTE_MIC_CTRL_MIC_LEN_MASK) >> + FTE_MIC_CTRL_MIC_LEN_SHIFT; parse->fte_elem_count = pos[1]; pos += 2; - if (mic_len > (size_t) (end - pos)) + if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) { + switch (mic_len_info) { + case FTE_MIC_LEN_16: + mic_len = 16; + break; + case FTE_MIC_LEN_24: + mic_len = 24; + break; + case FTE_MIC_LEN_32: + mic_len = 32; + break; + default: + wpa_printf(MSG_DEBUG, + "FT: Unknown MIC Length subfield value %u", + mic_len_info); + return -1; + } + } else { + mic_len = wpa_key_mgmt_sha384(key_mgmt) ? 24 : 16; + } + if (mic_len > (size_t) (end - pos)) { + wpa_printf(MSG_DEBUG, "FT: No room for %zu octet MIC in FTE", + mic_len); return -1; + } wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC", pos, mic_len); parse->fte_mic = pos; parse->fte_mic_len = mic_len; @@ -1124,8 +1151,7 @@ static int wpa_ft_parse_fte(const u8 *ie, size_t len, size_t mic_len, int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, - int key_mgmt, size_t key_len, bool need_r0kh_id, - bool need_r1kh_id) + int key_mgmt) { const u8 *end, *pos; struct wpa_ie_data data; @@ -1195,49 +1221,7 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, prot_ie_count = pos[1]; /* Element Count field in * MIC Control */ - if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && - (key_len == SHA512_MAC_LEN || !key_len)) { - wpa_printf(MSG_DEBUG, - "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA512"); - if (wpa_ft_parse_fte(pos, len, 32, parse) == - 0 && - (!need_r0kh_id || parse->r0kh_id) && - (!need_r1kh_id || parse->r1kh_id)) - break; - } - if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && - (key_len == SHA384_MAC_LEN || !key_len)) { - wpa_printf(MSG_DEBUG, - "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA384"); - if (wpa_ft_parse_fte(pos, len, 24, parse) == - 0 && - (!need_r0kh_id || parse->r0kh_id) && - (!need_r1kh_id || parse->r1kh_id)) - break; - } - if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && - (key_len == SHA256_MAC_LEN || !key_len)) { - wpa_printf(MSG_DEBUG, - "FT: Trying to parse FTE for FT-SAE-EXT-KEY - SHA256"); - if (wpa_ft_parse_fte(pos, len, 16, parse) == - 0 && - (!need_r0kh_id || parse->r0kh_id) && - (!need_r1kh_id || parse->r1kh_id)) - break; - } - if (key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) { - wpa_printf(MSG_DEBUG, - "FT: Failed to parse FTE for FT-SAE-EXT-KEY"); - return -1; - } - - if (wpa_key_mgmt_sha384(key_mgmt)) { - if (wpa_ft_parse_fte(pos, len, 24, parse) < 0) - return -1; - break; - } - - if (wpa_ft_parse_fte(pos, len, 16, parse) < 0) + if (wpa_ft_parse_fte(key_mgmt, pos, len, parse) < 0) return -1; break; case WLAN_EID_TIMEOUT_INTERVAL: diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index acb975ce5..05b1a8a05 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -186,6 +186,18 @@ WPA_CIPHER_BIP_CMAC_256) #define FT_R1KH_ID_LEN 6 #define WPA_PMK_NAME_LEN 16 +/* FTE - MIC Control - RSNXE Used */ +#define FTE_MIC_CTRL_RSNXE_USED BIT(0) +#define FTE_MIC_CTRL_MIC_LEN_MASK (BIT(1) | BIT(2) | BIT(3)) +#define FTE_MIC_CTRL_MIC_LEN_SHIFT 1 + +/* FTE - MIC Length subfield values */ +enum ft_mic_len_subfield { + FTE_MIC_LEN_16 = 0, + FTE_MIC_LEN_24 = 1, + FTE_MIC_LEN_32 = 2, +}; + /* IEEE 802.11, 8.5.2 EAPOL-Key frames */ #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) @@ -612,8 +624,7 @@ struct wpa_pasn_params_data { #define WPA_PASN_PUBKEY_UNCOMPRESSED 0x04 int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse, - int key_mgmt, size_t key_len, bool need_r0kh_id, - bool need_r1kh_id); + int key_mgmt); struct wpa_eapol_ie_parse { const u8 *wpa_ie; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 889bb0fc5..689db834b 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -5196,8 +5196,7 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, } if (wpa_ft_parse_ies(pos, end - pos, &parse, - sm->key_mgmt, sm->xxkey_len, true, - true) < 0) { + sm->key_mgmt) < 0) { wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs"); goto fail; } diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index fdf921d5d..eca09f7f4 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -127,8 +127,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) return 0; } - if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt, - sm->xxkey_len, false, false) < 0) + if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt) < 0) return -1; if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) @@ -217,6 +216,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, size_t rsnxe_len; int rsnxe_used; int res; + u8 mic_control; sm->ft_completed = 0; sm->ft_reassoc_completed = 0; @@ -348,12 +348,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, rsnxe_used); } #endif /* CONFIG_TESTING_OPTIONS */ + mic_control = rsnxe_used ? FTE_MIC_CTRL_RSNXE_USED : 0; if (sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY && sm->pmk_r0_len == SHA512_MAC_LEN) { struct rsn_ftie_sha512 *ftie; ftie = (struct rsn_ftie_sha512 *) pos; - ftie->mic_control[0] = !!rsnxe_used; + mic_control |= FTE_MIC_LEN_32 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + ftie->mic_control[0] = mic_control; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -366,7 +368,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ftie_sha384 *ftie; ftie = (struct rsn_ftie_sha384 *) pos; - ftie->mic_control[0] = !!rsnxe_used; + mic_control |= FTE_MIC_LEN_24 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + ftie->mic_control[0] = mic_control; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -377,7 +380,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ftie *ftie; ftie = (struct rsn_ftie *) pos; - ftie->mic_control[0] = !!rsnxe_used; + mic_control |= FTE_MIC_LEN_16 << FTE_MIC_CTRL_MIC_LEN_SHIFT; + ftie->mic_control[0] = mic_control; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -584,7 +588,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, int ret; const u8 *bssid; const u8 *kck; - size_t kck_len, kdk_len, key_len; + size_t kck_len, kdk_len; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); wpa_hexdump(MSG_DEBUG, "FT: RIC IEs", ric_ies, ric_ies_len); @@ -610,11 +614,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, return -1; } - key_len = sm->xxkey_len; - if (!key_len) - key_len = sm->pmk_r1_len; - if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt, - key_len, true, false) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); return -1; } @@ -1032,8 +1032,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, sm->key_mgmt, - sm->xxkey_len, true, true) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); return -1; } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 2a32510f1..49813ce78 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -250,7 +250,7 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, if (wpa_ft_parse_ies(mgmt->u.auth.variable, len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth), - &parse, 0, 0, false, false)) { + &parse, 0)) { add_note(wt, MSG_INFO, "Could not parse FT Authentication Response frame"); return; @@ -829,7 +829,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, 0, false, false) == 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); @@ -925,8 +925,7 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); - if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt, - 0, false, false) < 0) { + if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt) < 0) { add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); return; } @@ -1419,8 +1418,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); - if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt, - 0, false, false) < 0) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt) < 0) { add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); return; } @@ -1730,7 +1728,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt, ies_len = len - (24 + 2 + 2 * ETH_ALEN); wpa_hexdump(MSG_DEBUG, "FT Request frame body", ies, ies_len); - if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { add_note(wt, MSG_INFO, "Could not parse FT Request frame body"); return; } @@ -1779,7 +1777,7 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, ies_len = len - (24 + 2 + 2 * ETH_ALEN); wpa_hexdump(MSG_DEBUG, "FT Response frame body", ies, ies_len); - if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) { + if (wpa_ft_parse_ies(ies, ies_len, &parse, 0)) { add_note(wt, MSG_INFO, "Could not parse FT Response frame body"); return;