{
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)
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)
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)
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)
*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)
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;
}
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;
}
}
-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;
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;
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:
#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)))
#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;
}
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;
}
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)
size_t rsnxe_len;
int rsnxe_used;
int res;
+ u8 mic_control;
sm->ft_completed = 0;
sm->ft_reassoc_completed = 0;
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);
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);
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);
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);
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;
}
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;
}
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;
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);
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;
}
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;
}
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;
}
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;