@@ -3108,6 +3108,10 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
u32 selector;
const u8 *p;
size_t left;
+ struct wpa_mlo_gtk_hdr *gtk_hdr;
+ struct wpa_mlo_igtk_hdr *igtk_hdr;
+ struct wpa_mlo_bigtk_hdr *bigtk_hdr;
+ struct wpa_mlo_link_hdr *link_hdr;
if (len == 0)
return 1;
@@ -3216,6 +3220,52 @@ static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie)
return 0;
}
+ if (left >= sizeof(struct wpa_mlo_gtk_hdr) &&
+ selector == RSN_KEY_DATA_MLO_GTK) {
+ ie->mlo_gtk_found = true;
+ gtk_hdr = (struct wpa_mlo_gtk_hdr *)(p);
+ ie->mlo_gtk[gtk_hdr->link_id] = p;
+ ie->mlo_gtk_len[gtk_hdr->link_id] = left;
+ wpa_printf(MSG_ERROR, "WPA: link id %u", gtk_hdr->link_id);
+ wpa_hexdump_key(MSG_DEBUG, "WPA: MLO_GTK in EAPOL-Key",
+ pos, dlen);
+ return 0;
+ }
+
+ if (left >= sizeof(struct wpa_mlo_igtk_hdr) &&
+ selector == RSN_KEY_DATA_MLO_IGTK) {
+ ie->mlo_igtk_found = true;
+ igtk_hdr = (struct wpa_mlo_igtk_hdr *)(p);
+ ie->mlo_igtk[igtk_hdr->link_id] = p;
+ ie->mlo_igtk_len[igtk_hdr->link_id] = left;
+ wpa_printf(MSG_ERROR, "WPA: link id %u", igtk_hdr->link_id);
+ wpa_hexdump_key(MSG_DEBUG, "WPA: MLO_IGTK in EAPOL-Key",
+ pos, dlen);
+ return 0;
+ }
+
+ if (left >= sizeof(struct wpa_mlo_bigtk_hdr) &&
+ selector == RSN_KEY_DATA_MLO_BIGTK) {
+ bigtk_hdr = (struct wpa_mlo_bigtk_hdr *)(p);
+ ie->mlo_bigtk[bigtk_hdr->link_id] = p;
+ ie->mlo_bigtk_len[bigtk_hdr->link_id] = left;
+ wpa_printf(MSG_ERROR, "WPA: link id %u", bigtk_hdr->link_id);
+ wpa_hexdump_key(MSG_DEBUG, "WPA: MLO_BIGTK in EAPOL-Key",
+ pos, dlen);
+ return 0;
+ }
+
+ if (left >= sizeof(struct wpa_mlo_link_hdr) &&
+ selector == RSN_KEY_DATA_MLO_LINK) {
+ link_hdr = (struct wpa_mlo_link_hdr *)(p);
+ ie->mlo_link[link_hdr->link_id] = p;
+ ie->mlo_link_len[link_hdr->link_id] = left;
+ wpa_printf(MSG_ERROR, "WPA: link id %u", link_hdr->link_id);
+ wpa_hexdump(MSG_DEBUG, "WPA: MLO_LINK in EAPOL-Key",
+ pos, dlen);
+ return 0;
+ }
+
return 2;
}
@@ -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)
@@ -336,6 +340,52 @@ struct wpa_bigtk_kde {
u8 bigtk[WPA_BIGTK_MAX_LEN];
} STRUCT_PACKED;
+struct wpa_mlo_gtk_hdr {
+ u8 keyid:2;
+ u8 tx:1;
+ u8 res:1;
+ u8 link_id:4;
+ u8 pn[6];
+} STRUCT_PACKED;
+
+struct wpa_mlo_gtk_kde {
+ struct wpa_mlo_gtk_hdr hdr;
+ u8 gtk[WPA_GTK_MAX_LEN];
+} STRUCT_PACKED;
+
+struct wpa_mlo_igtk_hdr {
+ u8 keyid[2];
+ u8 pn[6];
+ u8 res:4;
+ u8 link_id:4;
+} STRUCT_PACKED;
+
+struct wpa_mlo_igtk_kde {
+ struct wpa_mlo_igtk_hdr hdr;
+ u8 igtk[WPA_IGTK_MAX_LEN];
+} STRUCT_PACKED;
+
+struct wpa_mlo_bigtk_hdr {
+ u8 keyid[2];
+ u8 pn[6];
+ u8 res:4;
+ u8 link_id:4;
+} STRUCT_PACKED;
+
+struct wpa_mlo_bigtk_kde {
+ struct wpa_mlo_bigtk_hdr hdr;
+ u8 bigtk[WPA_BIGTK_MAX_LEN];
+} STRUCT_PACKED;
+
+struct wpa_mlo_link_hdr {
+ u8 link_id:4;
+ u8 rsne_present:1;
+ u8 rsnxe_present:1;
+ u8 res:2;
+ u8 mac[6];
+ /* variable RSNE and RSNXE */
+} STRUCT_PACKED;
+
struct rsn_mdie {
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 ft_capab;
@@ -614,6 +664,17 @@ struct wpa_eapol_ie_parse {
u16 aid;
const u8 *wmm;
size_t wmm_len;
+#define MAX_NUM_MLO_LINKS 15
+ bool mlo_gtk_found;
+ bool mlo_igtk_found;
+ const u8 *mlo_gtk[MAX_NUM_MLO_LINKS];
+ size_t mlo_gtk_len[MAX_NUM_MLO_LINKS];
+ const u8 *mlo_igtk[MAX_NUM_MLO_LINKS];
+ size_t mlo_igtk_len[MAX_NUM_MLO_LINKS];
+ const u8 *mlo_bigtk[MAX_NUM_MLO_LINKS];
+ size_t mlo_bigtk_len[MAX_NUM_MLO_LINKS];
+ 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);