diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 33d9bce39..da707e66d 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -3164,6 +3164,9 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) u32 selector; const u8 *p; size_t left; + u8 link_id; + char title[50]; + int ret; if (len == 0) return 1; @@ -3271,6 +3274,78 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) return 0; } + if (left >= RSN_MLO_GTK_KDE_PREFIX_LENGTH && + selector == RSN_KEY_DATA_MLO_GTK) { + link_id = (p[0] & RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK) >> + RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT; + if (link_id >= MAX_NUM_MLO_LINKS) + return 2; + + ie->valid_mlo_gtks |= BIT(link_id); + ie->mlo_gtk[link_id] = p; + ie->mlo_gtk_len[link_id] = left; + ret = os_snprintf(title, sizeof(title), + "RSN: Link ID %u - MLO GTK KDE in EAPOL-Key", + link_id); + if (!os_snprintf_error(sizeof(title), ret)) + wpa_hexdump_key(MSG_DEBUG, title, pos, dlen); + return 0; + } + + if (left >= RSN_MLO_IGTK_KDE_PREFIX_LENGTH && + selector == RSN_KEY_DATA_MLO_IGTK) { + link_id = (p[8] & RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK) >> + RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT; + if (link_id >= MAX_NUM_MLO_LINKS) + return 2; + + ie->valid_mlo_igtks |= BIT(link_id); + ie->mlo_igtk[link_id] = p; + ie->mlo_igtk_len[link_id] = left; + ret = os_snprintf(title, sizeof(title), + "RSN: Link ID %u - MLO IGTK KDE in EAPOL-Key", + link_id); + if (!os_snprintf_error(sizeof(title), ret)) + wpa_hexdump_key(MSG_DEBUG, title, pos, dlen); + return 0; + } + + if (left >= RSN_MLO_BIGTK_KDE_PREFIX_LENGTH && + selector == RSN_KEY_DATA_MLO_BIGTK) { + link_id = (p[8] & RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK) >> + RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT; + if (link_id >= MAX_NUM_MLO_LINKS) + return 2; + + ie->valid_mlo_bigtks |= BIT(link_id); + ie->mlo_bigtk[link_id] = p; + ie->mlo_bigtk_len[link_id] = left; + ret = os_snprintf(title, sizeof(title), + "RSN: Link ID %u - MLO BIGTK KDE in EAPOL-Key", + link_id); + if (!os_snprintf_error(sizeof(title), ret)) + wpa_hexdump_key(MSG_DEBUG, title, pos, dlen); + return 0; + } + + if (left >= RSN_MLO_LINK_KDE_FIXED_LENGTH && + selector == RSN_KEY_DATA_MLO_LINK) { + link_id = (p[0] & RSN_MLO_LINK_KDE_LI_LINK_ID_MASK) >> + RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT; + if (link_id >= MAX_NUM_MLO_LINKS) + return 2; + + ie->valid_mlo_links |= BIT(link_id); + ie->mlo_link[link_id] = p; + ie->mlo_link_len[link_id] = left; + ret = os_snprintf(title, sizeof(title), + "RSN: Link ID %u - MLO Link KDE in EAPOL-Key", + link_id); + if (!os_snprintf_error(sizeof(title), ret)) + wpa_hexdump(MSG_DEBUG, title, pos, dlen); + return 0; + } + return 2; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index c01ddaa6b..71b423cbf 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -132,6 +132,10 @@ WPA_CIPHER_BIP_CMAC_256) #define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define RSN_KEY_DATA_OCI RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_KEY_DATA_BIGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 14) +#define RSN_KEY_DATA_MLO_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 16) +#define RSN_KEY_DATA_MLO_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 17) +#define RSN_KEY_DATA_MLO_BIGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 18) +#define RSN_KEY_DATA_MLO_LINK RSN_SELECTOR(0x00, 0x0f, 0xac, 19) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) @@ -339,6 +343,40 @@ struct wpa_bigtk_kde { u8 bigtk[WPA_BIGTK_MAX_LEN]; } STRUCT_PACKED; +#define RSN_MLO_GTK_KDE_PREFIX_LENGTH (1 + 6) +#define RSN_MLO_GTK_KDE_PREFIX0_KEY_ID_MASK 0x03 +#define RSN_MLO_GTK_KDE_PREFIX0_TX 0x04 +#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_SHIFT 4 +#define RSN_MLO_GTK_KDE_PREFIX0_LINK_ID_MASK 0xF0 + +#define RSN_MLO_IGTK_KDE_PREFIX_LENGTH (2 + 6 + 1) +#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_SHIFT 4 +#define RSN_MLO_IGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0 +struct rsn_mlo_igtk_kde { + u8 keyid[2]; + u8 pn[6]; + u8 prefix8; + u8 igtk[WPA_IGTK_MAX_LEN]; +} STRUCT_PACKED; + +#define RSN_MLO_BIGTK_KDE_PREFIX_LENGTH (2 + 6 + 1) +#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_SHIFT 4 +#define RSN_MLO_BIGTK_KDE_PREFIX8_LINK_ID_MASK 0xF0 +struct rsn_mlo_bigtk_kde { + u8 keyid[2]; + u8 pn[6]; + u8 prefix8; + u8 bigtk[WPA_BIGTK_MAX_LEN]; +} STRUCT_PACKED; + +#define RSN_MLO_LINK_KDE_FIXED_LENGTH (1 + 6) +#define RSN_MLO_LINK_KDE_LINK_INFO_INDEX 0 +#define RSN_MLO_LINK_KDE_LI_LINK_ID_SHIFT 0 +#define RSN_MLO_LINK_KDE_LI_LINK_ID_MASK 0x0F +#define RSN_MLO_LINK_KDE_LI_RSNE_INFO 0x10 +#define RSN_MLO_LINK_KDE_LI_RSNXE_INFO 0x20 +#define RSN_MLO_LINK_KDE_LINK_MAC_INDEX 1 + struct rsn_mdie { u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 ft_capab; @@ -616,6 +654,19 @@ struct wpa_eapol_ie_parse { u16 aid; const u8 *wmm; size_t wmm_len; +#define MAX_NUM_MLO_LINKS 15 + u16 valid_mlo_gtks; /* bitmap of valid link GTK KDEs */ + const u8 *mlo_gtk[MAX_NUM_MLO_LINKS]; + size_t mlo_gtk_len[MAX_NUM_MLO_LINKS]; + u16 valid_mlo_igtks; /* bitmap of valid link IGTK KDEs */ + const u8 *mlo_igtk[MAX_NUM_MLO_LINKS]; + size_t mlo_igtk_len[MAX_NUM_MLO_LINKS]; + u16 valid_mlo_bigtks; /* bitmap of valid link BIGTK KDEs */ + const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS]; + size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS]; + u16 valid_mlo_links; /* bitmap of valid MLO link KDEs */ + const u8 *mlo_link[MAX_NUM_MLO_LINKS]; + size_t mlo_link_len[MAX_NUM_MLO_LINKS]; }; int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie);