*elem_count = 3; /* Information element count */
ric_start = pos;
- if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, use_sha384) == 0
- && parse.ric) {
+ if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse, sm->wpa_key_mgmt,
+ key_len, false, false) == 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, -1)) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
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, use_sha384) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->wpa_key_mgmt,
+ sm->pmk_r1_len, true, true) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len,
- struct wpa_ft_ies *parse, int use_sha384)
+ struct wpa_ft_ies *parse, const u8 *opt)
{
const u8 *end, *pos;
parse->ftie = ie;
parse->ftie_len = ie_len;
- pos = ie + (use_sha384 ? sizeof(struct rsn_ftie_sha384) :
- sizeof(struct rsn_ftie));
+ pos = opt;
end = ie + ie_len;
wpa_hexdump(MSG_DEBUG, "FT: Parse FTE subelements", pos, end - pos);
len = *pos++;
if (len > end - pos) {
wpa_printf(MSG_DEBUG, "FT: Truncated subelement");
- break;
+ return -1;
}
switch (id) {
}
-int wpa_ft_parse_ies(const u8 *ies, size_t ies_len,
- struct wpa_ft_ies *parse, int use_sha384)
+static int wpa_ft_parse_fte(const u8 *ie, size_t len, size_t mic_len,
+ struct wpa_ft_ies *parse)
+{
+ 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_elem_count = pos[1];
+ pos += 2;
+
+ if (mic_len > (size_t) (end - pos))
+ return -1;
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC", pos, mic_len);
+ parse->fte_mic = pos;
+ parse->fte_mic_len = mic_len;
+ pos += mic_len;
+
+ if (2 * WPA_NONCE_LEN > end - pos)
+ return -1;
+ parse->fte_anonce = pos;
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
+ parse->fte_anonce, WPA_NONCE_LEN);
+ pos += WPA_NONCE_LEN;
+ parse->fte_snonce = pos;
+ wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
+ parse->fte_snonce, WPA_NONCE_LEN);
+ pos += WPA_NONCE_LEN;
+
+ return wpa_ft_parse_ftie(ie, len, parse, pos);
+}
+
+
+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)
{
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)
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;
- }
+ if (!key_mgmt)
+ key_mgmt = parse->key_mgmt;
break;
case WLAN_EID_RSNX:
wpa_hexdump(MSG_DEBUG, "FT: RSNXE", pos, len);
break;
case WLAN_EID_FAST_BSS_TRANSITION:
wpa_hexdump(MSG_DEBUG, "FT: FTE", pos, len);
- if (use_sha384) {
- const struct rsn_ftie_sha384 *ftie_sha384;
+ /* The first two octets (MIC Control field) is in the
+ * same offset for all cases, but the second field (MIC)
+ * has variable length with three different values.
+ * In particular the FT-SAE-EXT-KEY is inconvinient to
+ * parse, so try to handle this in pieces instead of
+ * using the struct rsn_ftie* definitions. */
+
+ if (len < 2)
+ return -1;
+ prot_ie_count = pos[1]; /* Element Count field in
+ * MIC Control */
- if (len < sizeof(*ftie_sha384))
- return -1;
- ftie_sha384 =
- (const struct rsn_ftie_sha384 *) pos;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
- ftie_sha384->mic_control, 2);
- wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
- ftie_sha384->mic,
- sizeof(ftie_sha384->mic));
- parse->fte_anonce = ftie_sha384->anonce;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
- ftie_sha384->anonce,
- WPA_NONCE_LEN);
- parse->fte_snonce = ftie_sha384->snonce;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
- ftie_sha384->snonce,
- WPA_NONCE_LEN);
- prot_ie_count = ftie_sha384->mic_control[1];
- if (wpa_ft_parse_ftie(pos, len, parse, 1) < 0)
+ 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 (len < sizeof(*ftie))
- return -1;
- ftie = (const struct rsn_ftie *) pos;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC Control",
- ftie->mic_control, 2);
- wpa_hexdump(MSG_DEBUG, "FT: FTE-MIC",
- ftie->mic, sizeof(ftie->mic));
- parse->fte_anonce = ftie->anonce;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-ANonce",
- ftie->anonce, WPA_NONCE_LEN);
- parse->fte_snonce = ftie->snonce;
- wpa_hexdump(MSG_DEBUG, "FT: FTE-SNonce",
- ftie->snonce, WPA_NONCE_LEN);
- prot_ie_count = ftie->mic_control[1];
- if (wpa_ft_parse_ftie(pos, len, parse, 0) < 0)
+ if (wpa_ft_parse_fte(pos, len, 16, parse) < 0)
return -1;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
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;
return 0;
}
- use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
- if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0)
+ if (wpa_ft_parse_ies(ies, ies_len, &ft, sm->key_mgmt,
+ sm->xxkey_len, false, false) < 0)
return -1;
if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1)
int ret;
const u8 *bssid;
const u8 *kck;
- size_t kck_len, kdk_len;
+ size_t kck_len, kdk_len, key_len;
int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
const u8 *anonce, *snonce;
return -1;
}
- if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
+ 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) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
}
return 0;
}
- if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, sm->key_mgmt,
+ sm->xxkey_len, true, true) < 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, -1)) {
+ &parse, 0, 0, false, false)) {
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) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false) == 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, use_sha384) < 0) {
+ if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt,
+ 0, false, false) < 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, use_sha384) < 0) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt,
+ 0, false, false) < 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, -1)) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
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, -1)) {
+ if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, 0, false, false)) {
add_note(wt, MSG_INFO,
"Could not parse FT Response frame body");
return;