diff --git a/src/ft.c b/src/ft.c index 8457163a..b5cf1353 100644 --- a/src/ft.c +++ b/src/ft.c @@ -237,6 +237,7 @@ static int ft_tx_reassociate(struct ft_sm *ft) struct iovec iov[3]; int iov_elems = 0; struct handshake_state *hs = ft->hs; + uint32_t kck_len = handshake_state_get_kck_len(hs); bool is_rsn = hs->supplicant_ie != NULL; uint8_t *rsne = NULL; @@ -302,13 +303,13 @@ static int ft_tx_reassociate(struct ft_sm *ft) memcpy(ft_info.snonce, hs->snonce, 32); fte = alloca(256); - ie_build_fast_bss_transition(&ft_info, fte); + ie_build_fast_bss_transition(&ft_info, kck_len, fte); if (!ft_calculate_fte_mic(hs, 5, rsne, fte, NULL, ft_info.mic)) goto error; /* Rebuild the FT IE now with the MIC included */ - ie_build_fast_bss_transition(&ft_info, fte); + ie_build_fast_bss_transition(&ft_info, kck_len, fte); iov[iov_elems].iov_base = fte; iov[iov_elems].iov_len = fte[1] + 2; @@ -330,6 +331,7 @@ static int ft_process_ies(struct ft_sm *ft, const uint8_t *ies, size_t ies_len) const uint8_t *mde = NULL; const uint8_t *fte = NULL; struct handshake_state *hs = ft->hs; + uint32_t kck_len = handshake_state_get_kck_len(hs); bool is_rsn; /* Check 802.11r IEs */ @@ -434,7 +436,7 @@ static int ft_process_ies(struct ft_sm *ft, const uint8_t *ies, size_t ies_len) goto ft_error; if (ie_parse_fast_bss_transition_from_data(fte, fte[1] + 2, - &ft_info) < 0) + kck_len, &ft_info) < 0) goto ft_error; if (ft_info.mic_element_count != 0 || @@ -524,6 +526,7 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame, { struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); struct handshake_state *hs = ft->hs; + uint32_t kck_len = handshake_state_get_kck_len(hs); const uint8_t *rsne = NULL; const uint8_t *mde = NULL; const uint8_t *fte = NULL; @@ -589,7 +592,7 @@ static int ft_rx_associate(struct auth_proto *ap, const uint8_t *frame, uint8_t mic[16]; if (ie_parse_fast_bss_transition_from_data(fte, fte[1] + 2, - &ft_info) < 0) + kck_len, &ft_info) < 0) return -EBADMSG; /* @@ -665,6 +668,7 @@ static bool ft_start(struct auth_proto *ap) { struct ft_sm *ft = l_container_of(ap, struct ft_sm, ap); struct handshake_state *hs = ft->hs; + uint32_t kck_len = handshake_state_get_kck_len(hs); bool is_rsn = hs->supplicant_ie != NULL; uint8_t mde[5]; struct iovec iov[3]; @@ -732,7 +736,7 @@ static bool ft_start(struct auth_proto *ap) memcpy(ft_info.snonce, hs->snonce, 32); fte = alloca(256); - ie_build_fast_bss_transition(&ft_info, fte); + ie_build_fast_bss_transition(&ft_info, kck_len, fte); iov[iov_elems].iov_base = fte; iov[iov_elems].iov_len = fte[1] + 2; diff --git a/src/ie.c b/src/ie.c index 239cb2c8..c4edeab3 100644 --- a/src/ie.c +++ b/src/ie.c @@ -2010,14 +2010,14 @@ bool ie_build_mobility_domain(uint16_t mdid, bool ft_over_ds, bool resource_req, return true; } -int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, - struct ie_ft_info *info) +int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, uint32_t mic_len, + struct ie_ft_info *info) { const uint8_t *data; uint8_t len, subelem_id, subelem_len; len = ie_tlv_iter_get_length(iter); - if (len < 82) + if (len < 66 + mic_len) return -EINVAL; data = ie_tlv_iter_get_data(iter); @@ -2026,14 +2026,14 @@ int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, info->mic_element_count = data[1]; - memcpy(info->mic, data + 2, 16); + memcpy(info->mic, data + 2, mic_len); - memcpy(info->anonce, data + 18, 32); + memcpy(info->anonce, data + mic_len + 2, 32); - memcpy(info->snonce, data + 50, 32); + memcpy(info->snonce, data + mic_len + 34, 32); - len -= 82; - data += 82; + len -= 66 + mic_len; + data += 66 + mic_len; while (len >= 2) { subelem_id = *data++; @@ -2104,7 +2104,8 @@ int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, } int ie_parse_fast_bss_transition_from_data(const uint8_t *data, uint8_t len, - struct ie_ft_info *info) + uint32_t mic_len, + struct ie_ft_info *info) { struct ie_tlv_iter iter; @@ -2116,28 +2117,29 @@ int ie_parse_fast_bss_transition_from_data(const uint8_t *data, uint8_t len, if (ie_tlv_iter_get_tag(&iter) != IE_TYPE_FAST_BSS_TRANSITION) return -EPROTOTYPE; - return ie_parse_fast_bss_transition(&iter, info); + return ie_parse_fast_bss_transition(&iter, mic_len, info); } -bool ie_build_fast_bss_transition(const struct ie_ft_info *info, uint8_t *to) +bool ie_build_fast_bss_transition(const struct ie_ft_info *info, + uint32_t mic_len, uint8_t *to) { uint8_t *len; *to++ = IE_TYPE_FAST_BSS_TRANSITION; len = to++; - *len = 82; + *len = (mic_len == 16) ? 82 : 90; to[0] = 0x00; to[1] = info->mic_element_count; - memcpy(to + 2, info->mic, 16); + memcpy(to + 2, info->mic, mic_len); - memcpy(to + 18, info->anonce, 32); + memcpy(to + mic_len + 2, info->anonce, 32); - memcpy(to + 50, info->snonce, 32); + memcpy(to + mic_len + 34, info->snonce, 32); - to += 82; + to += (mic_len == 16) ? 82 : 90; if (info->r1khid_present) { to[0] = 1; diff --git a/src/ie.h b/src/ie.h index e621d2e4..a6b2c8f7 100644 --- a/src/ie.h +++ b/src/ie.h @@ -324,7 +324,7 @@ enum ie_bss_capability { struct ie_ft_info { uint8_t mic_element_count; - uint8_t mic[16]; + uint8_t mic[24]; uint8_t anonce[32]; uint8_t snonce[32]; uint8_t r0khid[48]; @@ -449,10 +449,13 @@ bool ie_build_mobility_domain(uint16_t mdid, bool ft_over_ds, bool resource_req, uint8_t *to); int ie_parse_fast_bss_transition(struct ie_tlv_iter *iter, - struct ie_ft_info *info); + uint32_t mic_len, + struct ie_ft_info *info); int ie_parse_fast_bss_transition_from_data(const uint8_t *data, uint8_t len, - struct ie_ft_info *info); -bool ie_build_fast_bss_transition(const struct ie_ft_info *info, uint8_t *to); + uint32_t mic_len, + struct ie_ft_info *info); +bool ie_build_fast_bss_transition(const struct ie_ft_info *info, + uint32_t mic_len, uint8_t *to); int ie_parse_neighbor_report(struct ie_tlv_iter *iter, struct ie_neighbor_report_info *info); diff --git a/src/netdev.c b/src/netdev.c index 1508ef04..34750fb1 100644 --- a/src/netdev.c +++ b/src/netdev.c @@ -1649,6 +1649,8 @@ static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev) } if (fte) { + uint32_t kck_len = + handshake_state_get_kck_len(netdev->handshake); /* * If we are here, then most likely we have a FullMac * hw performing initial mobility association. We need @@ -1657,7 +1659,7 @@ static void netdev_connect_event(struct l_genl_msg *msg, struct netdev *netdev) * sanitize the contents and just assume they're okay. */ if (ie_parse_fast_bss_transition_from_data(fte, - fte[1] + 2, &ft_info) >= 0) { + fte[1] + 2, kck_len, &ft_info) >= 0) { handshake_state_set_fte(netdev->handshake, fte); handshake_state_set_kh_ids(netdev->handshake, ft_info.r0khid,