blob: 5895635bc27d53173b9a1e83ed067df875ce1790 [file] [log] [blame]
developer617abbd2024-04-23 14:50:01 +08001From 5e6164cb6143d55409c08ae9bfd859efa188e383 Mon Sep 17 00:00:00 2001
2From: Rameshkumar Sundaram <quic_ramess@quicinc.com>
3Date: Thu, 28 Mar 2024 23:46:47 +0530
4Subject: [PATCH 017/104] hostapd: MLO: add support for MLO rekey
5
6Currently wpa group rekey is not supported for ML Stations when non-assoc
7link initiates a group rekey, to support the same following changes have
8been made-
9 * Calculate links specific MLO GTK/IGTK and BIGTK KDE lengths based on
10 corresponding cipher and key instead of taking length of one link and
11 multiplying it by no of associated links.
12 * For MLD, Arm group key rekey timer on one of the links and whenever it
13 fires do group key rekey for all links.
14
15Signed-off-by: Rameshkumar Sundaram <quic_ramess@quicinc.com>
16Co-developed-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
17Signed-off-by: Adil Saeed Musthafa <quic_adilm@quicinc.com>
18Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
19---
20 src/ap/drv_callbacks.c | 2 +-
21 src/ap/ieee802_11.c | 13 +-
22 src/ap/wpa_auth.c | 310 +++++++++++++++---
23 src/ap/wpa_auth.h | 9 +-
24 src/ap/wpa_auth_glue.c | 22 ++
25 src/ap/wpa_auth_i.h | 1 +
26 src/ap/wpa_auth_ie.c | 12 +-
27 src/common/wpa_common.h | 1 +
28 tests/fuzzing/eapol-key-auth/eapol-key-auth.c | 2 +-
29 wpa_supplicant/ibss_rsn.c | 2 +-
30 10 files changed, 317 insertions(+), 57 deletions(-)
31
32diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
33index 064c7abae..dc21977ff 100644
34--- a/src/ap/drv_callbacks.c
35+++ b/src/ap/drv_callbacks.c
36@@ -528,7 +528,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
37 elems.rsnxe ? elems.rsnxe - 2 : NULL,
38 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
39 elems.mdie, elems.mdie_len,
40- elems.owe_dh, elems.owe_dh_len);
41+ elems.owe_dh, elems.owe_dh_len, NULL);
42 reason = WLAN_REASON_INVALID_IE;
43 status = WLAN_STATUS_INVALID_IE;
44 switch (res) {
45diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
46index 9d04bdf43..7ee18f4ae 100644
47--- a/src/ap/ieee802_11.c
48+++ b/src/ap/ieee802_11.c
49@@ -1887,7 +1887,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
50 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
51 elems.rsnxe ? elems.rsnxe - 2 : NULL,
52 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
53- elems.mdie, elems.mdie_len, NULL, 0);
54+ elems.mdie, elems.mdie_len, NULL, 0, NULL);
55 resp = wpa_res_to_status_code(res);
56 if (resp != WLAN_STATUS_SUCCESS)
57 goto fail;
58@@ -3778,7 +3778,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd,
59 rsn_ie_len += 2;
60 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
61 hapd->iface->freq, rsn_ie, rsn_ie_len,
62- NULL, 0, NULL, 0, owe_dh, owe_dh_len);
63+ NULL, 0, NULL, 0, owe_dh, owe_dh_len, NULL);
64 status = wpa_res_to_status_code(res);
65 if (status != WLAN_STATUS_SUCCESS)
66 goto end;
67@@ -3867,6 +3867,8 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
68 const u8 *wpa_ie;
69 size_t wpa_ie_len;
70 const u8 *p2p_dev_addr = NULL;
71+ struct hostapd_data *assoc_hapd;
72+ struct sta_info *assoc_sta = NULL;
73
74 resp = check_ssid(hapd, sta, elems->ssid, elems->ssid_len);
75 if (resp != WLAN_STATUS_SUCCESS)
76@@ -4041,6 +4043,10 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
77 wpa_ie_len += 2;
78
79 if (!sta->wpa_sm) {
80+ if (!link)
81+ assoc_sta = hostapd_ml_get_assoc_sta(hapd, sta,
82+ &assoc_hapd);
83+
84 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
85 sta->addr,
86 p2p_dev_addr);
87@@ -4076,7 +4082,8 @@ static int __check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
88 elems->rsnxe ? elems->rsnxe_len + 2 :
89 0,
90 elems->mdie, elems->mdie_len,
91- elems->owe_dh, elems->owe_dh_len);
92+ elems->owe_dh, elems->owe_dh_len,
93+ assoc_sta ? assoc_sta->wpa_sm : NULL);
94 resp = wpa_res_to_status_code(res);
95 if (resp != WLAN_STATUS_SUCCESS)
96 return resp;
97diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
98index 8c1052c25..7a07dcc4c 100644
99--- a/src/ap/wpa_auth.c
100+++ b/src/ap/wpa_auth.c
101@@ -71,6 +71,9 @@ static void wpa_group_put(struct wpa_authenticator *wpa_auth,
102 struct wpa_group *group);
103 static int ieee80211w_kde_len(struct wpa_state_machine *sm);
104 static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
105+static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
106+ struct wpa_group *group);
107+
108
109 static const u32 eapol_key_timeout_first = 100; /* ms */
110 static const u32 eapol_key_timeout_subseq = 1000; /* ms */
111@@ -102,6 +105,22 @@ static const u8 * wpa_auth_get_spa(const struct wpa_state_machine *sm)
112 return sm->addr;
113 }
114
115+static void wpa_update_gkeydone(struct wpa_state_machine *sm, int update)
116+{
117+#ifdef CONFIG_IEEE80211BE
118+ int link_id;
119+#endif /* CONFIG_IEEE80211BE */
120+ if (!sm || !sm->wpa_auth)
121+ return;
122+
123+ sm->wpa_auth->group->GKeyDoneStations += update;
124+
125+#ifdef CONFIG_IEEE80211BE
126+ for_each_sm_auth(sm, link_id)
127+ sm->mld_links[link_id].wpa_auth->group->GKeyDoneStations += update;
128+#endif /* CONFIG_IEEE80211BE */
129+}
130+
131 #ifdef CONFIG_IEEE80211BE
132 void wpa_release_link_auth_ref(struct wpa_state_machine *sm, int release_link_id)
133 {
134@@ -139,10 +158,12 @@ static int wpa_get_primary_wpa_auth_cb(struct wpa_authenticator *wpa_auth, void
135 ctx->wpa_auth = wpa_auth;
136 return 1;
137 }
138+#endif /* CONFIG_IEEE80211BE */
139
140 static struct wpa_authenticator *
141 wpa_get_primary_wpa_auth(struct wpa_authenticator *wpa_auth)
142 {
143+#ifdef CONFIG_IEEE80211BE
144 struct wpa_get_link_auth_ctx ctx;
145
146 if (!wpa_auth || !wpa_auth->is_ml || wpa_auth->primary_auth)
147@@ -153,8 +174,10 @@ wpa_get_primary_wpa_auth(struct wpa_authenticator *wpa_auth)
148 wpa_auth_for_each_auth(wpa_auth, wpa_get_primary_wpa_auth_cb, &ctx);
149
150 return ctx.wpa_auth;
151-}
152+#else
153+ return wpa_auth;
154 #endif /* CONFIG_IEEE80211BE */
155+}
156
157 static inline int wpa_auth_mic_failure_report(
158 struct wpa_authenticator *wpa_auth, const u8 *addr)
159@@ -420,15 +443,16 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
160 }
161 }
162
163-
164-static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
165+static void wpa_rekey_all_groups(struct wpa_authenticator *wpa_auth)
166 {
167- struct wpa_authenticator *wpa_auth = eloop_ctx;
168 struct wpa_group *group, *next;
169
170 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
171 group = wpa_auth->group;
172 while (group) {
173+ wpa_printf(MSG_DEBUG, "GTK rekey start for authenticator("
174+ MACSTR "), group vlan %d",
175+ MAC2STR(wpa_auth->addr), group->vlan_id);
176 wpa_group_get(wpa_auth, group);
177
178 group->GTKReKey = true;
179@@ -441,6 +465,80 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
180 wpa_group_put(wpa_auth, group);
181 group = next;
182 }
183+}
184+
185+#ifdef CONFIG_IEEE80211BE
186+static void wpa_update_all_gtks(struct wpa_authenticator *wpa_auth)
187+{
188+ struct wpa_group *group, *next;
189+
190+ group = wpa_auth->group;
191+ while (group) {
192+ wpa_group_get(wpa_auth, group);
193+
194+ wpa_group_update_gtk(wpa_auth, group);
195+ next = group->next;
196+ wpa_group_put(wpa_auth, group);
197+ group = next;
198+ }
199+}
200+
201+static int wpa_update_all_gtks_cb(struct wpa_authenticator *wpa_auth, void *ctx)
202+{
203+ u8 *mld_addr = ctx;
204+
205+ if (os_memcmp(wpa_auth->mld_addr, mld_addr, ETH_ALEN) != 0)
206+ return 0;
207+
208+ wpa_update_all_gtks(wpa_auth);
209+ return 0;
210+}
211+
212+static int wpa_rekey_all_groups_cb(struct wpa_authenticator *wpa_auth,
213+ void *ctx)
214+{
215+ u8 *mld_addr = ctx;
216+
217+ if (os_memcmp(wpa_auth->mld_addr, mld_addr, ETH_ALEN) != 0)
218+ return 0;
219+
220+ wpa_rekey_all_groups(wpa_auth);
221+ return 0;
222+}
223+#endif /* CONFIG_IEEE80211BE */
224+
225+static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
226+{
227+ struct wpa_authenticator *wpa_auth = eloop_ctx;
228+
229+#ifdef CONFIG_IEEE80211BE
230+ if (wpa_auth->is_ml) {
231+ /* Non Primary ML authenticator eloop timer for group rekey is never
232+ * started and shouldn't fire too check and warn just in case
233+ */
234+ if (!wpa_auth->primary_auth) {
235+ wpa_printf(MSG_DEBUG,
236+ "WPA: Can't start GTK rekey on non-primary ML authenticator");
237+ return;
238+ }
239+ /*
240+ * Generate all the new I/BIG/GTKs
241+ */
242+ wpa_auth_for_each_auth(wpa_auth, wpa_update_all_gtks_cb,
243+ wpa_auth->mld_addr);
244+
245+ /*
246+ * Send all the generated I/BIG/GTKs to the respective
247+ * stations via G1 messages
248+ */
249+ wpa_auth_for_each_auth(wpa_auth, wpa_rekey_all_groups_cb,
250+ wpa_auth->mld_addr);
251+ } else {
252+ wpa_rekey_all_groups(wpa_auth);
253+ }
254+#else
255+ wpa_rekey_all_groups(wpa_auth);
256+#endif /* CONFIG_IEEE80211BE */
257
258 if (wpa_auth->conf.wpa_group_rekey) {
259 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey,
260@@ -590,8 +688,19 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
261 wpa_auth = os_zalloc(sizeof(struct wpa_authenticator));
262 if (!wpa_auth)
263 return NULL;
264+
265 os_memcpy(wpa_auth->addr, addr, ETH_ALEN);
266 os_memcpy(&wpa_auth->conf, conf, sizeof(*conf));
267+
268+#ifdef CONFIG_IEEE80211BE
269+ if (conf->mld_addr) {
270+ wpa_auth->is_ml = true;
271+ wpa_auth->link_id = conf->link_id;
272+ wpa_auth->primary_auth = !conf->first_link_auth;
273+ os_memcpy(wpa_auth->mld_addr, conf->mld_addr, ETH_ALEN);
274+ }
275+#endif /* CONFIG_IEEE80211BE */
276+
277 wpa_auth->cb = cb;
278 wpa_auth->cb_ctx = cb_ctx;
279
280@@ -635,7 +744,15 @@ struct wpa_authenticator * wpa_init(const u8 *addr,
281 wpa_rekey_gmk, wpa_auth, NULL);
282 }
283
284+#ifdef CONFIG_IEEE80211BE
285+ /* For ML AP, run Group rekey timer only on one link(first) and whenever
286+ * it fires do rekey on all associated ML links at one shot.
287+ */
288+ if ((!wpa_auth->is_ml || !conf->first_link_auth) &&
289+ wpa_auth->conf.wpa_group_rekey) {
290+#else
291 if (wpa_auth->conf.wpa_group_rekey) {
292+#endif /* CONFIG_IEEE80211BE */
293 eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0,
294 wpa_rekey_gtk, wpa_auth, NULL);
295 }
296@@ -699,6 +816,10 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
297 struct wpa_group *group, *prev;
298
299 eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL);
300+
301+ /* TODO: assign ML Primary authenticator to next link auth and
302+ * start rekey timer.
303+ */
304 eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
305
306 pmksa_cache_auth_deinit(wpa_auth->pmksa);
307@@ -868,7 +989,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
308 }
309 #endif /* CONFIG_P2P */
310 if (sm->GUpdateStationKeys) {
311- sm->group->GKeyDoneStations--;
312+ wpa_update_gkeydone(sm, -1);
313 sm->GUpdateStationKeys = false;
314 }
315 #ifdef CONFIG_IEEE80211R_AP
316@@ -1669,12 +1790,14 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
317 wpa_auth_logger(wpa_auth, wpa_auth_get_spa(sm),
318 LOGGER_INFO,
319 "received EAPOL-Key Request for GTK rekeying");
320- eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
321+
322+ eloop_cancel_timeout(wpa_rekey_gtk,
323+ wpa_get_primary_wpa_auth(wpa_auth), NULL);
324 if (wpa_auth_gtk_rekey_in_process(wpa_auth))
325 wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG,
326 "skip new GTK rekey - already in process");
327 else
328- wpa_rekey_gtk(wpa_auth, NULL);
329+ wpa_rekey_gtk(wpa_get_primary_wpa_auth(wpa_auth), NULL);
330 }
331 } else {
332 /* Do not allow the same key replay counter to be reused. */
333@@ -2207,7 +2330,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
334 * Reauthentication cancels the pending group key
335 * update for this STA.
336 */
337- sm->group->GKeyDoneStations--;
338+ wpa_update_gkeydone(sm, -1);
339 sm->GUpdateStationKeys = false;
340 sm->PtkGroupInit = true;
341 }
342@@ -2284,7 +2407,7 @@ SM_STATE(WPA_PTK, INITIALIZE)
343
344 sm->keycount = 0;
345 if (sm->GUpdateStationKeys)
346- sm->group->GKeyDoneStations--;
347+ wpa_update_gkeydone(sm, -1);
348 sm->GUpdateStationKeys = false;
349 if (sm->wpa == WPA_VERSION_WPA)
350 sm->PInitAKeys = false;
351@@ -4058,41 +4181,54 @@ static void wpa_auth_get_ml_key_info(struct wpa_authenticator *wpa_auth,
352 wpa_auth->cb->get_ml_key_info(wpa_auth->cb_ctx, info);
353 }
354
355+#define KDE_HDR_LEN (1 + 1 + RSN_SELECTOR_LEN)
356
357 static size_t wpa_auth_ml_group_kdes_len(struct wpa_state_machine *sm)
358 {
359- struct wpa_authenticator *wpa_auth = sm->wpa_auth;
360- struct wpa_group *gsm = sm->group;
361- size_t gtk_len = gsm->GTK_len;
362- size_t igtk_len;
363- size_t kde_len;
364- unsigned int n_links;
365+ struct wpa_authenticator *wpa_auth;
366+ size_t kde_len = 0;
367+ int link_id;
368
369 if (sm->mld_assoc_link_id < 0)
370 return 0;
371
372- n_links = sm->n_mld_affiliated_links + 1;
373+ for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
374+ if (!sm->mld_links[link_id].valid)
375+ continue;
376+
377+ wpa_auth = sm->mld_links[link_id].wpa_auth;
378+ if (!wpa_auth || !wpa_auth->group)
379+ continue;
380
381- /* MLO GTK KDE for each link */
382- kde_len = n_links * (2 + RSN_SELECTOR_LEN + 1 + 6 + gtk_len);
383+ /* MLO GTK KDE
384+ * Header + Key-idx and Link-id + PN
385+ */
386+ kde_len += (KDE_HDR_LEN + 1 + WPA_MLO_GTK_KDE_PN_LEN);
387+ kde_len += wpa_auth->group->GTK_len;
388
389- if (!sm->mgmt_frame_prot)
390- return kde_len;
391+ if (!sm->mgmt_frame_prot)
392+ continue;
393
394- /* MLO IGTK KDE for each link */
395- igtk_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
396- kde_len += n_links * (2 + RSN_SELECTOR_LEN + 2 + 6 + 1 + igtk_len);
397+ if (wpa_auth->conf.tx_bss_auth)
398+ wpa_auth = wpa_auth->conf.tx_bss_auth;
399
400- if (wpa_auth->conf.tx_bss_auth) {
401- wpa_auth = wpa_auth->conf.tx_bss_auth;
402- igtk_len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
403- }
404+ /* MLO IGTK KDE
405+ * Header + Key-idx & IPN + Link-id
406+ */
407+ kde_len += (KDE_HDR_LEN + WPA_IGTK_KDE_PREFIX_LEN + 1);
408+ kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
409
410- if (!wpa_auth->conf.beacon_prot)
411- return kde_len;
412+ if (!wpa_auth->conf.beacon_prot)
413+ continue;
414+
415+ /* MLO BIGTK KDE
416+ * Header + Key-idx & IPN + Link-id
417+ */
418+ kde_len += (KDE_HDR_LEN + WPA_BIGTK_KDE_PREFIX_LEN + 1);
419+ kde_len += wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
420+ }
421
422- /* MLO BIGTK KDE for each link */
423- kde_len += n_links * (2 + RSN_SELECTOR_LEN + 2 + 6 + 1 + igtk_len);
424+ wpa_printf(MSG_DEBUG, "MLO Group kdes len = %zu", kde_len);
425
426 return kde_len;
427 }
428@@ -4102,6 +4238,7 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
429 {
430 struct wpa_auth_ml_key_info ml_key_info;
431 unsigned int i, link_id;
432+ u8 *start = pos;
433
434 /* First fetch the key information from all the authenticators */
435 os_memset(&ml_key_info, 0, sizeof(ml_key_info));
436@@ -4153,8 +4290,10 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
437 i++;
438 }
439
440- if (!sm->mgmt_frame_prot)
441+ if (!sm->mgmt_frame_prot) {
442+ wpa_printf(MSG_DEBUG, "RSN: MLO Group kde len = %ld", pos - start);
443 return pos;
444+ }
445
446 /* Add MLO IGTK KDEs */
447 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
448@@ -4193,8 +4332,10 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
449 i++;
450 }
451
452- if (!sm->wpa_auth->conf.beacon_prot)
453+ if (!sm->wpa_auth->conf.beacon_prot) {
454+ wpa_printf(MSG_DEBUG, "RSN: MLO Group kde len = %ld", pos - start);
455 return pos;
456+ }
457
458 /* Add MLO BIGTK KDEs */
459 for (i = 0, link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
460@@ -4234,6 +4375,7 @@ static u8 * wpa_auth_ml_group_kdes(struct wpa_state_machine *sm, u8 *pos)
461 i++;
462 }
463
464+ wpa_printf(MSG_DEBUG, "RSN: MLO Group kde len = %ld", pos - start);
465 return pos;
466 }
467
468@@ -4274,6 +4416,7 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
469 {
470 #ifdef CONFIG_IEEE80211BE
471 u8 link_id;
472+ u8 *start = pos;
473
474 if (sm->mld_assoc_link_id < 0)
475 return pos;
476@@ -4324,6 +4467,7 @@ static u8 * wpa_auth_ml_kdes(struct wpa_state_machine *sm, u8 *pos)
477 }
478 }
479
480+ wpa_printf(MSG_DEBUG, "RSN: MLO Link kde len = %ld", pos - start);
481 pos = wpa_auth_ml_group_kdes(sm, pos);
482 #endif /* CONFIG_IEEE80211BE */
483
484@@ -5106,7 +5250,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED)
485 #endif /* CONFIG_OCV */
486
487 if (sm->GUpdateStationKeys)
488- sm->group->GKeyDoneStations--;
489+ wpa_update_gkeydone(sm, -1);
490 sm->GUpdateStationKeys = false;
491 sm->GTimeoutCtr = 0;
492 /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */
493@@ -5121,7 +5265,7 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR)
494 {
495 SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group);
496 if (sm->GUpdateStationKeys)
497- sm->group->GKeyDoneStations--;
498+ wpa_update_gkeydone(sm, -1);
499 sm->GUpdateStationKeys = false;
500 sm->Disconnect = true;
501 sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT;
502@@ -5415,18 +5559,11 @@ int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos)
503
504 #endif /* CONFIG_WNM_AP */
505
506-
507-static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
508- struct wpa_group *group)
509+static void wpa_group_update_gtk(struct wpa_authenticator *wpa_auth,
510+ struct wpa_group *group)
511 {
512 int tmp;
513
514- wpa_printf(MSG_DEBUG,
515- "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
516- group->vlan_id);
517- group->changed = true;
518- group->wpa_group_state = WPA_GROUP_SETKEYS;
519- group->GTKReKey = false;
520 tmp = group->GM;
521 group->GM = group->GN;
522 group->GN = tmp;
523@@ -5440,6 +5577,24 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
524 * counting the STAs that are marked with GUpdateStationKeys instead of
525 * including all STAs that could be in not-yet-completed state. */
526 wpa_gtk_update(wpa_auth, group);
527+}
528+
529+static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
530+ struct wpa_group *group)
531+{
532+ wpa_printf(MSG_DEBUG,
533+ "WPA: group state machine entering state SETKEYS (VLAN-ID %d)",
534+ group->vlan_id);
535+ group->changed = true;
536+ group->wpa_group_state = WPA_GROUP_SETKEYS;
537+ group->GTKReKey = false;
538+
539+#ifdef CONFIG_IEEE80211BE
540+ if (wpa_auth->is_ml)
541+ goto skip_update;
542+#endif /* CONFIG_IEEE80211BE */
543+
544+ wpa_group_update_gtk(wpa_auth, group);
545
546 if (group->GKeyDoneStations) {
547 wpa_printf(MSG_DEBUG,
548@@ -5447,6 +5602,10 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth,
549 group->GKeyDoneStations);
550 group->GKeyDoneStations = 0;
551 }
552+
553+#ifdef CONFIG_IEEE80211BE
554+skip_update:
555+#endif /* CONFIG_IEEE80211BE */
556 wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group);
557 wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d",
558 group->GKeyDoneStations);
559@@ -5564,6 +5723,57 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth,
560 }
561 }
562
563+static void wpa_mark_group_change(struct wpa_state_machine *sm, bool change)
564+{
565+#ifdef CONFIG_IEEE80211BE
566+ int link_id;
567+#endif /* CONFIG_IEEE80211BE */
568+
569+ if (!sm || !sm->wpa_auth)
570+ return;
571+ sm->wpa_auth->group->changed = change;
572+
573+#ifdef CONFIG_IEEE80211BE
574+ for_each_sm_auth(sm, link_id)
575+ sm->mld_links[link_id].wpa_auth->group->changed = change;
576+#endif /* CONFIG_IEEE80211BE */
577+}
578+
579+static void wpa_group_sm_step_links(struct wpa_state_machine *sm)
580+{
581+#ifdef CONFIG_IEEE80211BE
582+ int link_id;
583+#endif /* CONFIG_IEEE80211BE */
584+
585+ if (!sm || !sm->wpa_auth)
586+ return;
587+ wpa_group_sm_step(sm->wpa_auth, sm->wpa_auth->group);
588+
589+#ifdef CONFIG_IEEE80211BE
590+ for_each_sm_auth(sm, link_id)
591+ wpa_group_sm_step(sm->mld_links[link_id].wpa_auth,
592+ sm->mld_links[link_id].wpa_auth->group);
593+#endif /* CONFIG_IEEE80211BE */
594+}
595+
596+static bool wpa_group_sm_changed(struct wpa_state_machine *sm)
597+{
598+#ifdef CONFIG_IEEE80211BE
599+ int link_id;
600+#endif /* CONFIG_IEEE80211BE */
601+ bool changed;
602+
603+ if (!sm || !sm->wpa_auth)
604+ return false;
605+ changed = sm->wpa_auth->group->changed;
606+
607+#ifdef CONFIG_IEEE80211BE
608+ for_each_sm_auth(sm, link_id)
609+ changed |= sm->mld_links[link_id].wpa_auth->group->changed;
610+#endif /* CONFIG_IEEE80211BE */
611+
612+ return changed;
613+}
614
615 static int wpa_sm_step(struct wpa_state_machine *sm)
616 {
617@@ -5584,7 +5794,7 @@ static int wpa_sm_step(struct wpa_state_machine *sm)
618 break;
619
620 sm->changed = false;
621- sm->wpa_auth->group->changed = false;
622+ wpa_mark_group_change(sm, false);
623
624 SM_STEP_RUN(WPA_PTK);
625 if (sm->pending_deinit)
626@@ -5592,8 +5802,8 @@ static int wpa_sm_step(struct wpa_state_machine *sm)
627 SM_STEP_RUN(WPA_PTK_GROUP);
628 if (sm->pending_deinit)
629 break;
630- wpa_group_sm_step(sm->wpa_auth, sm->group);
631- } while (sm->changed || sm->wpa_auth->group->changed);
632+ wpa_group_sm_step_links(sm);
633+ } while (sm->changed || wpa_group_sm_changed(sm));
634 sm->in_step_loop = 0;
635
636 if (sm->pending_deinit) {
637@@ -6807,8 +7017,10 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth)
638 {
639 if (!wpa_auth)
640 return -1;
641- eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL);
642- return eloop_register_timeout(0, 0, wpa_rekey_gtk, wpa_auth, NULL);
643+ eloop_cancel_timeout(wpa_rekey_gtk,
644+ wpa_get_primary_wpa_auth(wpa_auth), NULL);
645+ return eloop_register_timeout(0, 0, wpa_rekey_gtk,
646+ wpa_get_primary_wpa_auth(wpa_auth), NULL);
647 }
648
649
650diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
651index 1446872f3..331d217b5 100644
652--- a/src/ap/wpa_auth.h
653+++ b/src/ap/wpa_auth.h
654@@ -285,6 +285,12 @@ struct wpa_auth_config {
655 * Set only in nontransmitted BSSs, i.e., is NULL for transmitted BSS
656 * and in BSSs that are not part of a Multi-BSSID set. */
657 struct wpa_authenticator *tx_bss_auth;
658+
659+#ifdef CONFIG_IEEE80211BE
660+ u8 *mld_addr;
661+ int link_id;
662+ struct wpa_authenticator *first_link_auth;
663+#endif /* CONFIG_IEEE80211BE */
664 };
665
666 typedef enum {
667@@ -429,7 +435,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
668 const u8 *wpa_ie, size_t wpa_ie_len,
669 const u8 *rsnxe, size_t rsnxe_len,
670 const u8 *mdie, size_t mdie_len,
671- const u8 *owe_dh, size_t owe_dh_len);
672+ const u8 *owe_dh, size_t owe_dh_len,
673+ struct wpa_state_machine *assoc_sm);
674 int wpa_validate_osen(struct wpa_authenticator *wpa_auth,
675 struct wpa_state_machine *sm,
676 const u8 *osen_ie, size_t osen_ie_len);
677diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
678index d3cd44695..1726c7201 100644
679--- a/src/ap/wpa_auth_glue.c
680+++ b/src/ap/wpa_auth_glue.c
681@@ -1713,6 +1713,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
682
683 hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
684 _conf.msg_ctx = hapd->msg_ctx;
685+
686 tx_bss = hostapd_mbssid_get_tx_bss(hapd);
687 if (tx_bss != hapd)
688 _conf.tx_bss_auth = tx_bss->wpa_auth;
689@@ -1753,6 +1754,27 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
690 !!(hapd->iface->drv_flags2 &
691 WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
692
693+#ifdef CONFIG_IEEE80211BE
694+ _conf.mld_addr = NULL;
695+ _conf.link_id = -1;
696+ _conf.first_link_auth = NULL;
697+
698+ if (hapd->conf->mld_ap) {
699+ struct hostapd_data *lhapd;
700+
701+ _conf.mld_addr = hapd->mld->mld_addr;
702+ _conf.link_id = hapd->mld_link_id;
703+
704+ for_each_mld_link(lhapd, hapd) {
705+ if (lhapd == hapd)
706+ continue;
707+
708+ if (lhapd->wpa_auth)
709+ _conf.first_link_auth = lhapd->wpa_auth;
710+ }
711+ }
712+#endif /* CONFIG_IEEE80211BE */
713+
714 hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
715 if (hapd->wpa_auth == NULL) {
716 wpa_printf(MSG_ERROR, "WPA initialization failed.");
717diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
718index 9ba90749d..29bb66733 100644
719--- a/src/ap/wpa_auth_i.h
720+++ b/src/ap/wpa_auth_i.h
721@@ -176,6 +176,7 @@ struct wpa_state_machine {
722 u8 peer_mld_addr[ETH_ALEN];
723 s8 mld_assoc_link_id;
724 u8 n_mld_affiliated_links;
725+ u16 valid_links;
726
727 struct mld_link {
728 bool valid;
729diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
730index a5f2861c9..bf2303e4f 100644
731--- a/src/ap/wpa_auth_ie.c
732+++ b/src/ap/wpa_auth_ie.c
733@@ -608,7 +608,8 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
734 const u8 *wpa_ie, size_t wpa_ie_len,
735 const u8 *rsnxe, size_t rsnxe_len,
736 const u8 *mdie, size_t mdie_len,
737- const u8 *owe_dh, size_t owe_dh_len)
738+ const u8 *owe_dh, size_t owe_dh_len,
739+ struct wpa_state_machine *assoc_sm)
740 {
741 struct wpa_auth_config *conf = &wpa_auth->conf;
742 struct wpa_ie_data data;
743@@ -956,6 +957,15 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
744 else
745 sm->wpa = WPA_VERSION_WPA;
746
747+ if (assoc_sm) {
748+ /* For ML Association Link STA cannot choose a different
749+ * akm or pairwise cipher from assoc STA
750+ */
751+ if (sm->wpa_key_mgmt != assoc_sm->wpa_key_mgmt)
752+ return WPA_INVALID_AKMP;
753+ if (sm->pairwise != assoc_sm->pairwise)
754+ return WPA_INVALID_PAIRWISE;
755+ }
756 #if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS)
757 if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 ||
758 sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) &&
759diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h
760index 01efeea3a..24ceed600 100644
761--- a/src/common/wpa_common.h
762+++ b/src/common/wpa_common.h
763@@ -24,6 +24,7 @@
764 #define WPA_PASN_PMK_LEN 32
765 #define WPA_PASN_MAX_MIC_LEN 24
766 #define WPA_MAX_RSNXE_LEN 4
767+#define WPA_MLO_GTK_KDE_PN_LEN 6
768
769 #define OWE_DH_GROUP 19
770
771diff --git a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c
772index bb46422c6..17f69fd76 100644
773--- a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c
774+++ b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c
775@@ -262,7 +262,7 @@ static int auth_init(struct wpa *wpa)
776 }
777
778 if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, supp_ie,
779- supp_ie_len, NULL, 0, NULL, 0, NULL, 0) !=
780+ supp_ie_len, NULL, 0, NULL, 0, NULL, 0, NULL) !=
781 WPA_IE_OK) {
782 wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
783 return -1;
784diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
785index 554268a47..2d06f1a6a 100644
786--- a/wpa_supplicant/ibss_rsn.c
787+++ b/wpa_supplicant/ibss_rsn.c
788@@ -484,7 +484,7 @@ static int ibss_rsn_auth_init(struct ibss_rsn *ibss_rsn,
789 "\x00\x0f\xac\x04"
790 "\x01\x00\x00\x0f\xac\x04"
791 "\x01\x00\x00\x0f\xac\x02"
792- "\x00\x00", 22, NULL, 0, NULL, 0, NULL, 0) !=
793+ "\x00\x00", 22, NULL, 0, NULL, 0, NULL, 0, NULL) !=
794 WPA_IE_OK) {
795 wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed");
796 return -1;
797--
7982.39.2
799