Defragmentation of FTE

Defragment the FTE if it was fragmented. This is needed for MLO when the
FTE in Reassociation Response frame might be longer than 255 octets to
include all the group keys for all the links.

Signed-off-by: Jouni Malinen <quic_jouni@quicinc.com>
This commit is contained in:
Jouni Malinen 2023-08-08 12:37:39 +03:00 committed by Jouni Malinen
parent 053bd8af8e
commit 43b5f11d96

View file

@ -17,6 +17,7 @@
#include "crypto/aes_wrap.h" #include "crypto/aes_wrap.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#include "ieee802_11_defs.h" #include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
#include "defs.h" #include "defs.h"
#include "wpa_common.h" #include "wpa_common.h"
@ -1203,6 +1204,9 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
struct wpa_ie_data data; struct wpa_ie_data data;
int ret; int ret;
int prot_ie_count = 0; int prot_ie_count = 0;
const u8 *fte = NULL;
size_t fte_len = 0;
bool is_fte = false;
os_memset(parse, 0, sizeof(*parse)); os_memset(parse, 0, sizeof(*parse));
if (ies == NULL) if (ies == NULL)
@ -1218,6 +1222,10 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
if (len > end - pos) if (len > end - pos)
break; break;
if (id != WLAN_EID_FAST_BSS_TRANSITION &&
id != WLAN_EID_FRAGMENT)
is_fte = false;
switch (id) { switch (id) {
case WLAN_EID_RSN: case WLAN_EID_RSN:
wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len); wpa_hexdump(MSG_DEBUG, "FT: RSNE", pos, len);
@ -1266,9 +1274,16 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
return -1; return -1;
prot_ie_count = pos[1]; /* Element Count field in prot_ie_count = pos[1]; /* Element Count field in
* MIC Control */ * MIC Control */
is_fte = true;
if (wpa_ft_parse_fte(key_mgmt, pos, len, parse) < 0) fte = pos;
return -1; fte_len = len;
break;
case WLAN_EID_FRAGMENT:
if (is_fte) {
wpa_hexdump(MSG_DEBUG, "FT: FTE fragment",
pos, len);
fte_len += 2 + len;
}
break; break;
case WLAN_EID_TIMEOUT_INTERVAL: case WLAN_EID_TIMEOUT_INTERVAL:
wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval", wpa_hexdump(MSG_DEBUG, "FT: Timeout Interval",
@ -1287,6 +1302,25 @@ int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse,
pos += len; pos += len;
} }
if (fte) {
int res;
if (fte_len < 255) {
res = wpa_ft_parse_fte(key_mgmt, fte, fte_len, parse);
} else {
struct wpabuf *buf;
buf = ieee802_11_defrag_data(fte, fte_len, false);
if (!buf)
return -1;
res = wpa_ft_parse_fte(key_mgmt, wpabuf_head(buf),
wpabuf_len(buf), parse);
wpabuf_free(buf);
}
if (res < 0)
return -1;
}
if (prot_ie_count == 0) if (prot_ie_count == 0)
return 0; /* no MIC */ return 0; /* no MIC */